aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn Ankarström <john@ankarstrom.se>2022-08-20 20:16:07 +0200
committerJohn Ankarström <john@ankarstrom.se>2022-08-20 20:16:07 +0200
commit3fa33fc6b16e066838f4db3e182776a04c5c7d26 (patch)
tree109510c47b006c65f9d603c6f030826310981d46
parent3add6b2f9e87258e06ecdf0120529a096e9ea8d3 (diff)
downloadEpisodeBrowser-3fa33fc6b16e066838f4db3e182776a04c5c7d26.tar.gz
Fix XML test.
-rw-r--r--c/test.cpp152
1 files changed, 89 insertions, 63 deletions
diff --git a/c/test.cpp b/c/test.cpp
index 78f7017..b125a20 100644
--- a/c/test.cpp
+++ b/c/test.cpp
@@ -25,6 +25,56 @@ struct Test
#define TEST(id) }; struct id : public Test { id() : Test(#id)
#define FAIL(...) do { Sprintf(error, __VA_ARGS__); return; } while (0)
+template <typename F>
+struct Defer
+{
+ Defer(F dtor) : dtor(dtor) {}
+ ~Defer() { dtor(); }
+ F dtor;
+};
+
+#define DEFER(x) Defer APPLY(CAT, defer_, __COUNTER__) {[=](){x;}}
+
+struct InternetFile
+{
+ InternetFile(const wchar_t* url);
+ ~InternetFile();
+ DWORD Read(void* buf, DWORD cb);
+ HINTERNET hi;
+ HINTERNET hiUrl;
+};
+
+InternetFile::InternetFile(const wchar_t* url)
+{
+ hi = InternetOpen(L"Episode Browser",
+ INTERNET_OPEN_TYPE_DIRECT, nullptr, nullptr,
+ /*INTERNET_FLAG_ASYNC*/0);
+ if (!hi)
+ throw Win32Error{};
+
+ hiUrl = InternetOpenUrl(hi, url,
+ nullptr, 0, INTERNET_FLAG_NO_UI, 0);
+ if (!hiUrl) {
+ InternetCloseHandle(hi);
+ throw Win32Error{};
+ }
+}
+
+InternetFile::~InternetFile()
+{
+ InternetCloseHandle(hiUrl);
+ InternetCloseHandle(hi);
+}
+
+DWORD InternetFile::Read(void* buf, DWORD cb)
+{
+ DWORD cbRead;
+ if (InternetReadFile(hiUrl, buf, cb, &cbRead))
+ return cbRead;
+ else
+ throw Win32Error{};
+}
+
TESTS
{
TEST(StrcpyWithSmallerDestination)
@@ -226,55 +276,42 @@ TESTS
g_cfg.cEp = i;
}
- TEST(Internet)
+ TEST(XML)
{
- HINTERNET hi, hiUrl;
- static unsigned char buf[8'388'608] = {0};
- DWORD cbRead;
-
- /* Download HTML. */
- hi = InternetOpen(L"Episode Browser",
- INTERNET_OPEN_TYPE_DIRECT, nullptr, nullptr,
- /*INTERNET_FLAG_ASYNC*/0);
- if (!hi)
- goto a;
-
- hiUrl = InternetOpenUrl(hi, L"https://www.detectiveconanworld.com/wiki/Anime",
- nullptr, 0, INTERNET_FLAG_NO_UI, 0);
- if (!hiUrl)
- goto b;
-
- cbRead = 1;
- while (cbRead)
- if (!InternetReadFile(hiUrl, &buf, sizeof(buf), &cbRead))
- goto c;
-
- //printf("%s\n", buf);
-
- InternetCloseHandle(hiUrl);
- InternetCloseHandle(hi);
-
- /* Parse HTML. */
LIBXML_TEST_VERSION;
- htmlDocPtr doc;
- doc = htmlReadMemory(reinterpret_cast<const char*>(buf), sizeof(buf),
- "https://www.detectiveconanworld.com/wiki/Anime", nullptr,
- HTML_PARSE_RECOVER|HTML_PARSE_NOERROR|HTML_PARSE_NOWARNING);
- if (!doc)
- goto z;
- xmlXPathContextPtr xpathCtx;
- xmlXPathObjectPtr xpathObj;
+ InternetFile inf{L"https://www.detectiveconanworld.com/wiki/Anime"};
+ char buf[1024];
+
+ htmlParserCtxtPtr ctxt = htmlCreatePushParserCtxt(nullptr, nullptr,
+ buf, sizeof(buf), "https://www.detectiveconanworld.com/wiki/Anime",
+ XML_CHAR_ENCODING_UTF8);
+ DEFER(xmlFreeParserCtxt(ctxt));
- xpathCtx = xmlXPathNewContext(doc);
+ htmlCtxtUseOptions(ctxt, HTML_PARSE_RECOVER|HTML_PARSE_NOERROR|HTML_PARSE_NOWARNING);
+
+ while (DWORD cbRead = inf.Read(&buf, sizeof(buf))) {
+ if (!htmlParseChunk(ctxt, buf, cbRead, 0))
+ FAIL(xmlGetLastError()->message);
+ }
+ htmlParseChunk(ctxt, buf, 0, 1); /* Terminate. */
+
+ htmlDocPtr doc = ctxt->myDoc;
+ if (!doc)
+ FAIL(xmlGetLastError()->message);
+ DEFER(xmlFreeDoc(doc)); /* Needed? */
+
+ xmlXPathContextPtr xpathCtx = xmlXPathNewContext(doc);
if (!xpathCtx)
- goto y;
+ FAIL(xmlGetLastError()->message);
+ DEFER(xmlXPathFreeContext(xpathCtx));
- xpathObj = xmlXPathEvalExpression(
- reinterpret_cast<const xmlChar*>("//tr"),
+ xmlXPathObjectPtr xpathObj = xmlXPathEvalExpression(
+ reinterpret_cast<const xmlChar*>("//tr/td[@style='background:#f2fde9;']"),
xpathCtx);
if (!xpathObj)
- goto x;
+ FAIL(xmlGetLastError()->message);
+ DEFER(xmlXPathFreeObject(xpathObj));
xmlNodeSetPtr nodes;
int cNodes;
@@ -282,39 +319,28 @@ TESTS
cNodes = nodes? nodes->nodeNr: 0;
printf("%d nodes\n", cNodes);
- for (int i = 0; i < cNodes; i++) {
- xmlNodePtr node = nodes->nodeTab[i];
- printf("node \"%s\": type %d\n", node->name, node->type);
- }
-
- xmlXPathFreeObject(xpathObj);
- xmlXPathFreeContext(xpathCtx);
- xmlFreeDoc(doc);
- return;
-
- x: xmlXPathFreeContext(xpathCtx);
- y: xmlFreeDoc(doc);
- z: FAIL(xmlGetLastError()->message);
-
- c: InternetCloseHandle(hiUrl);
- b: InternetCloseHandle(hi);
- a: FAIL(Win32Error{}.what());
+ // for (int i = 0; i < cNodes; i++) {
+ // xmlNodePtr node = nodes->nodeTab[i];
+ // printf("node \"%s\": type %d\n", node->name, node->type);
+ // }
}
};
int RunTests()
{
const Test tests[] = {
- StrcpyWithSmallerDestination{},
+ //StrcpyWithSmallerDestination{},
//EpisodeDataFromWeb{},
- EpisodeDataFromProlog{},
- IO{},
+ //EpisodeDataFromProlog{},
+ //IO{},
//MigrateElvDataFromPrologToDisk{},
- SampleConfigurationToDisk{},
+ //SampleConfigurationToDisk{},
//MigrateCfg{}
//MigrateDlvDataFromPrologToDisk{},
//DownloadData{},
- Internet{},
+ XML{},
+ //ImportElvData{},
+ //ImportDlvData{},
};
printf("Results (%llu tests):\n", sizeof(tests)/sizeof(*tests));