aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn Ankarström <john@ankarstrom.se>2022-08-16 15:24:24 +0200
committerJohn Ankarström <john@ankarstrom.se>2022-08-16 15:24:24 +0200
commitab621173afc918797a4ea68b5d6ceee7cc043f72 (patch)
treee347f9ff7b8139851e69a84b58717a93e957ab92
parent1cb00589065fd05b8d7cf0030eed84c488e9634d (diff)
downloadEpisodeBrowser-ab621173afc918797a4ea68b5d6ceee7cc043f72.tar.gz
Add data migration test.
-rw-r--r--c/data.cpp6
-rw-r--r--c/data.h42
-rw-r--r--c/episodelistview.cpp4
-rw-r--r--c/episodelistview.h2
-rw-r--r--c/test.cpp81
5 files changed, 92 insertions, 43 deletions
diff --git a/c/data.cpp b/c/data.cpp
index fe348e7..60decc9 100644
--- a/c/data.cpp
+++ b/c/data.cpp
@@ -52,14 +52,14 @@ FileView::~FileView()
CloseHandle(hf);
}
-void Write(unsigned char* buf, const ElvData& e)
+void Write(unsigned char* buf, const ElvDataA& e)
{
memcpy(buf, reinterpret_cast<const unsigned char*>(&e), sizeof(e));
}
-ElvData* Read(unsigned char* const buf)
+ElvDataA* Read(unsigned char* const buf)
{
if (buf[0] != 'a')
return nullptr;
- return reinterpret_cast<ElvData*>(buf);
+ return reinterpret_cast<ElvDataA*>(buf);
}
diff --git a/c/data.h b/c/data.h
index 4e25251..e584442 100644
--- a/c/data.h
+++ b/c/data.h
@@ -5,27 +5,29 @@
#include "util.h"
#include "wcharptr.h"
-/* ElvData and DlvData are written as-is to disk; note the careful
- * alignment. */
+/* ElvDataA and DlvDataA are written as-is to disk; note the careful
+ * alignment. As such, they should be regarded as immutable. If the
+ * format needs to be changed in the future, then new structs called
+ * ElvDataB and DlvDataB should be added. */
-struct ElvData
+struct ElvDataA
{
- unsigned char version = 'a'; /* 0-1 */
- unsigned char rating = 0; /* 1-2 */
- unsigned char bWatched = 0; /* 2-3 */
- unsigned char bTVOriginal = 0; /* 3-4 */
- wchar_t sRating[4] = {0}; /* 4-12 */
- wchar_t siEp[6] = {0}; /* 12-24 */
- wchar_t title[128] = {0}; /* 24-280 */
+ unsigned char version = 'a';
+ unsigned char rating = 0;
+ unsigned char bWatched = 0;
+ unsigned char bTVOriginal = 0;
+ wchar_t sRating[4] = {0};
+ wchar_t siEp[6] = {0};
+ wchar_t title[128] = {0};
};
-struct DlvData
+struct DlvDataA
{
- wchar_t date[64] = {0};
- wchar_t source[64] = {0};
- wchar_t screenwriter[64] = {0};
+ wchar_t date[32] = {0};
+ wchar_t source[48] = {0};
+ wchar_t screenwriter[48] = {0};
wchar_t hint[128] = {0};
- wchar_t wiki[128] = {0};
+ wchar_t wiki[192] = {0};
};
struct FileView
@@ -39,10 +41,10 @@ struct FileView
/* TODO: Handle exceptions on read and write... */
};
-void Write(unsigned char* buf, const ElvData& e);
-ElvData* Read(unsigned char* buf);
+void Write(unsigned char* buf, const ElvDataA& e);
+ElvDataA* Read(unsigned char* buf);
-inline int FromWeb(const int iEp, ElvData& e, DlvData& d) noexcept
+inline int FromWeb(const int iEp, ElvDataA& e, DlvDataA& d) noexcept
{
WcharPtr title, wiki, date, source, hint;
const int r = Pl("episode_data","fetch_episode_data",iEp,&title,&wiki,&date,&source,&hint);
@@ -54,7 +56,7 @@ inline int FromWeb(const int iEp, ElvData& e, DlvData& d) noexcept
return r;
}
-inline bool FromProlog(const int iEp, ElvData& e) noexcept
+inline bool FromProlog(const int iEp, ElvDataA& e) noexcept
{
if (WcharPtr title; Pl("episode_data","episode_title",iEp,&title))
Wcscpy(e.title, title);
@@ -75,7 +77,7 @@ inline bool FromProlog(const int iEp, ElvData& e) noexcept
return true;
}
-inline void FromProlog(const int iEp, DlvData& d) noexcept
+inline void FromProlog(const int iEp, DlvDataA& d) noexcept
{
if (WcharPtr wiki; Pl("episode_data","episode_wiki",iEp,&wiki))
Wcscpy(d.wiki, wiki);
diff --git a/c/episodelistview.cpp b/c/episodelistview.cpp
index e591952..3f2104f 100644
--- a/c/episodelistview.cpp
+++ b/c/episodelistview.cpp
@@ -53,7 +53,7 @@ LRESULT EpisodeListView::HandleNotify(const LPARAM lParam)
case LVN_GETDISPINFO: /* Display item. */
{
NMLVDISPINFO* const nm = reinterpret_cast<NMLVDISPINFO*>(lParam);
- ElvData& e = m_vData.at(nm->item.lParam-1);
+ ElvDataA& e = m_vData.at(nm->item.lParam-1);
wchar_t* vs[] = {e.siEp, e.title, e.sRating}; /* ELVSIEPISODE, ELVSITITLE, ELVSIRATING */
nm->item.pszText = vs[nm->item.iSubItem];
return 0;
@@ -336,7 +336,7 @@ void EpisodeListView::Update()
m_vData.clear();
ListView_DeleteAllItems(hWnd);
for (int iEp = 1; iEp <= cEp; iEp++) {
- ElvData e;
+ ElvDataA e;
if (!FromProlog(iEp, e))
goto push;
diff --git a/c/episodelistview.h b/c/episodelistview.h
index 7e0c539..0fcf444 100644
--- a/c/episodelistview.h
+++ b/c/episodelistview.h
@@ -32,7 +32,7 @@ struct EpisodeListView : public ListView
private:
int m_iSortCol;
static int CALLBACK SortProc(LPARAM lParam1, LPARAM lParam2, LPARAM extra);
- std::vector<ElvData> m_vData;
+ std::vector<ElvDataA> m_vData;
};
#endif
diff --git a/c/test.cpp b/c/test.cpp
index abb03b3..9402eed 100644
--- a/c/test.cpp
+++ b/c/test.cpp
@@ -1,5 +1,6 @@
#include "data.h"
#include "test.h"
+#include "pl.h"
#include "util.h"
#include "win.h"
@@ -26,8 +27,8 @@ TESTS
TEST(EpisodeDataFromWeb)
{
- ElvData e;
- DlvData d;
+ ElvDataA e;
+ DlvDataA d;
FromWeb(10, e, d);
if (wcscmp(e.title, L"Pro Soccer Player Blackmail Case") != 0)
FAIL("title is not correct");
@@ -37,8 +38,8 @@ TESTS
TEST(EpisodeDataFromProlog)
{
- ElvData e;
- DlvData d;
+ ElvDataA e;
+ DlvDataA d;
FromProlog(10, e);
FromProlog(10, d);
if (wcscmp(e.title, L"Pro Soccer Player Blackmail Case") != 0)
@@ -49,28 +50,73 @@ TESTS
TEST(IO)
{
- ElvData e1;
- FromProlog(6, e1);
+ ElvDataA e1_0, e2_0;
+ FromProlog(6, e1_0);
+ FromProlog(10, e2_0);
{
- FileView fv{L"tmp.dat", sizeof(e1)};
- Write(fv, e1);
+ FileView fv{L"tmp.dat", sizeof(ElvDataA)*2};
+ Write(fv, e1_0);
+ Write(fv+sizeof(ElvDataA), e2_0);
}
{
- FileView fv{L"tmp.dat", sizeof(e1)};
- ElvData* e2 = Read(fv);
- if (e1.rating != e2->rating)
- FAIL("rating is different (%d/%d)", e1.rating, e2->rating);
- if (e1.bWatched != e2->bWatched)
+ FileView fv{L"tmp.dat", sizeof(ElvDataA)};
+ ElvDataA* e1 = Read(fv);
+ if (e1_0.rating != e1->rating)
+ FAIL("rating is different (%d/%d)", e1_0.rating, e1->rating);
+ if (e1_0.bWatched != e1->bWatched)
FAIL("bWatched is different");
- if (e1.bTVOriginal != e2->bTVOriginal)
+ if (e1_0.bTVOriginal != e1->bTVOriginal)
FAIL("bTVOriginal is different");
- if (wcscmp(e1.sRating, e2->sRating) != 0)
+ if (wcscmp(e1_0.sRating, e1->sRating) != 0)
FAIL("sRating is different");
- if (wcscmp(e1.siEp, e2->siEp) != 0)
+ if (wcscmp(e1_0.siEp, e1->siEp) != 0)
FAIL("siEp is different");
- if (wcscmp(e1.title, e2->title) != 0)
+ if (wcscmp(e1_0.title, e1->title) != 0)
FAIL("title is different");
}
+ {
+ FileView fv{L"tmp.dat", sizeof(ElvDataA)*2};
+ ElvDataA* e2 = Read(fv+sizeof(ElvDataA));
+ if (e2_0.rating != e2->rating)
+ FAIL("rating is different (%d/%d)", e2_0.rating, e2->rating);
+ if (e2_0.bWatched != e2->bWatched)
+ FAIL("bWatched is different");
+ if (e2_0.bTVOriginal != e2->bTVOriginal)
+ FAIL("bTVOriginal is different");
+ if (wcscmp(e2_0.sRating, e2->sRating) != 0)
+ FAIL("sRating is different");
+ if (wcscmp(e2_0.siEp, e2->siEp) != 0)
+ FAIL("siEp is different");
+ if (wcscmp(e2_0.title, e2->title) != 0)
+ FAIL("title is different");
+ }
+ //DeleteFile(L"tmp.dat");
+ }
+
+ TEST(MigrateElvDataFromPrologToDisk)
+ {
+ int cEp;
+ if (!Pl("episode_data","episode_count",&cEp))
+ return;
+
+ {
+ FileView fv{L"tmp.dat", sizeof(ElvDataA)*cEp};
+ unsigned char* p = fv;
+
+ for (int iEp = 1; iEp <= cEp; iEp++) {
+ ElvDataA e;
+ FromProlog(iEp, e);
+ Write(p, e);
+ p += sizeof(e);
+ }
+ }
+ {
+ FileView fv{L"tmp.dat", sizeof(ElvDataA)*cEp};
+ ElvDataA* ve = reinterpret_cast<ElvDataA*>(fv.view);
+ ElvDataA e = ve[9];
+ if (wcscmp(e.title, L"Pro Soccer Player Blackmail Case") != 0)
+ FAIL("title is not correct");
+ }
//DeleteFile(L"tmp.dat");
}
};
@@ -82,6 +128,7 @@ int RunTests()
//EpisodeDataFromWeb{},
EpisodeDataFromProlog{},
IO{},
+ MigrateElvDataFromPrologToDisk{},
};
printf("Results (%llu tests):\n", sizeof(tests)/sizeof(*tests));