From 3fa33fc6b16e066838f4db3e182776a04c5c7d26 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20Ankarstr=C3=B6m?= Date: Sat, 20 Aug 2022 20:16:07 +0200 Subject: Fix XML test. --- c/test.cpp | 152 ++++++++++++++++++++++++++++++++++++------------------------- 1 file changed, 89 insertions(+), 63 deletions(-) (limited to 'c') 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 +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(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("//tr"), + xmlXPathObjectPtr xpathObj = xmlXPathEvalExpression( + reinterpret_cast("//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)); -- cgit v1.2.3