From 943cbbf6ce6649f0299d21256ce34a537ce042da Mon Sep 17 00:00:00 2001 From: Veloman Yunkan Date: Sun, 16 Jan 2022 17:25:47 +0400 Subject: [PATCH 1/3] New unit test ServerTest.suggestions --- test/server.cpp | 93 ++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 92 insertions(+), 1 deletion(-) diff --git a/test/server.cpp b/test/server.cpp index 334f6079b..f90cdcae1 100644 --- a/test/server.cpp +++ b/test/server.cpp @@ -45,6 +45,18 @@ Headers invariantHeaders(Headers headers) return headers; } +// Output generated via mustache templates sometimes contains end-of-line +// whitespace. This complicates representing the expected output of a unit-test +// as C++ raw strings in editors that are configured to delete EOL whitespace. +// A workaround is to put special markers (//EOLWHITESPACEMARKER) at the end +// of such lines in the expected output string and remove them at runtime. +// This is exactly what this function is for. +std::string removeEOLWhitespaceMarkers(const std::string& s) +{ + const std::regex pattern("//EOLWHITESPACEMARKER"); + return std::regex_replace(s, pattern, ""); +} + class ZimFileServer { @@ -444,7 +456,7 @@ TEST_F(ServerTest, ETagOfUncompressibleContentIsNotAffectedByAcceptEncoding) // NOTE: The "Date" header (which should belong to that list as required // NOTE: by RFC 7232) is not included (since the result of this function // NOTE: will be used to check the equality of headers from the 200 and 304 -// NOTe: responses). +// NOTE: responses). Headers special304Headers(const httplib::Response& r) { Headers result; @@ -625,6 +637,85 @@ TEST_F(ServerTest, RangeHeaderIsCaseInsensitive) } } +TEST_F(ServerTest, suggestions) +{ + typedef std::pair UrlAndExpectedResponse; + const std::vector testData{ + { /* url: */ "/ROOT/suggest?content=zimfile&term=thing", +R"EXPECTEDRESPONSE([ + { + "value" : "Doing His Thing", + "label" : "Doing His <b>Thing</b>", + "kind" : "path" + , "path" : "A/Doing_His_Thing" + }, + { + "value" : "We Didn't See a Thing", + "label" : "We Didn't See a <b>Thing</b>", + "kind" : "path" + , "path" : "A/We_Didn't_See_a_Thing" + }, + { + "value" : "thing ", + "label" : "containing 'thing'...", + "kind" : "pattern" + //EOLWHITESPACEMARKER + } +] +)EXPECTEDRESPONSE" + }, + { /* url: */ "/ROOT/suggest?content=zimfile&term=movie", +R"EXPECTEDRESPONSE([ + { + "value" : "Ray (movie)", + "label" : "Ray (<b>movie</b>)", + "kind" : "path" + , "path" : "A/Ray_(movie)" + }, + { + "value" : "movie ", + "label" : "containing 'movie'...", + "kind" : "pattern" + //EOLWHITESPACEMARKER + } +] +)EXPECTEDRESPONSE" + }, + { /* url: */ "/ROOT/suggest?content=zimfile&term=abracadabra", +R"EXPECTEDRESPONSE([ + { + "value" : "abracadabra ", + "label" : "containing 'abracadabra'...", + "kind" : "pattern" + //EOLWHITESPACEMARKER + } +] +)EXPECTEDRESPONSE" + }, + { // Test handling of & (%26 when url-encoded) in the search string + /* url: */ "/ROOT/suggest?content=zimfile&term=A%26B", +R"EXPECTEDRESPONSE([ + { + "value" : "A&B ", + "label" : "containing 'A&B'...", + "kind" : "pattern" + //EOLWHITESPACEMARKER + } +] +)EXPECTEDRESPONSE" + }, + }; + + for ( const auto& urlAndExpectedResponse : testData ) { + const std::string url = urlAndExpectedResponse.first; + const std::string expectedResponse = urlAndExpectedResponse.second; + const TestContext ctx{ {"url", url} }; + const auto r = zfs1_->GET(url.c_str()); + EXPECT_EQ(r->status, 200) << ctx; + EXPECT_EQ(r->body, removeEOLWhitespaceMarkers(expectedResponse)) << ctx; + } +} + //////////////////////////////////////////////////////////////////////////////// // Testing of the library-related functionality of the server //////////////////////////////////////////////////////////////////////////////// From 9a6aef4dba8e96005ddd1b96e30557f2af2c02ee Mon Sep 17 00:00:00 2001 From: Veloman Yunkan Date: Sun, 16 Jan 2022 17:26:57 +0400 Subject: [PATCH 2/3] Moved/renamed LibraryServerTest.suggestions_in_range --- test/server.cpp | 128 ++++++++++++++++++++++++------------------------ 1 file changed, 64 insertions(+), 64 deletions(-) diff --git a/test/server.cpp b/test/server.cpp index f90cdcae1..798d85f83 100644 --- a/test/server.cpp +++ b/test/server.cpp @@ -716,6 +716,70 @@ R"EXPECTEDRESPONSE([ } } +TEST_F(ServerTest, suggestions_in_range) +{ + /** + * Attempt to get 50 suggestions in steps of 5 + * The suggestions are returned in the json format + * [{sugg1}, {sugg2}, ... , {suggN}, {suggest ft search}] + * Assuming the number of suggestions = (occurance of "{" - 1) + */ + { + int suggCount = 0; + for (int i = 0; i < 10; i++) { + std::string url = "/ROOT/suggest?content=zimfile&term=ray&start=" + std::to_string(i*5) + "&count=5"; + const auto r = zfs1_->GET(url.c_str()); + std::string body = r->body; + int currCount = std::count(body.begin(), body.end(), '{') - 1; + ASSERT_EQ(currCount, 5); + suggCount += currCount; + } + ASSERT_EQ(suggCount, 50); + } + + // Attempt to get 10 suggestions in steps of 5 even though there are only 8 + { + std::string url = "/ROOT/suggest?content=zimfile&term=song+for+you&start=0&count=5"; + const auto r1 = zfs1_->GET(url.c_str()); + std::string body = r1->body; + int currCount = std::count(body.begin(), body.end(), '{') - 1; + ASSERT_EQ(currCount, 5); + + url = "/ROOT/suggest?content=zimfile&term=song+for+you&start=5&count=5"; + const auto r2 = zfs1_->GET(url.c_str()); + body = r2->body; + currCount = std::count(body.begin(), body.end(), '{') - 1; + ASSERT_EQ(currCount, 3); + } + + // Attempt to get 10 suggestions even though there is only 1 + { + std::string url = "/ROOT/suggest?content=zimfile&term=strong&start=0&count=5"; + const auto r = zfs1_->GET(url.c_str()); + std::string body = r->body; + int currCount = std::count(body.begin(), body.end(), '{') - 1; + ASSERT_EQ(currCount, 1); + } + + // No Suggestion + { + std::string url = "/ROOT/suggest?content=zimfile&term=oops&start=0&count=5"; + const auto r = zfs1_->GET(url.c_str()); + std::string body = r->body; + int currCount = std::count(body.begin(), body.end(), '{') - 1; + ASSERT_EQ(currCount, 0); + } + + // Out of bound value + { + std::string url = "/ROOT/suggest?content=zimfile&term=ray&start=-2&count=-1"; + const auto r = zfs1_->GET(url.c_str()); + std::string body = r->body; + int currCount = std::count(body.begin(), body.end(), '{') - 1; + ASSERT_EQ(currCount, 0); + } +} + //////////////////////////////////////////////////////////////////////////////// // Testing of the library-related functionality of the server //////////////////////////////////////////////////////////////////////////////// @@ -1367,70 +1431,6 @@ TEST_F(LibraryServerTest, catalog_v2_entries_filtered_by_search_terms) ); } -TEST_F(LibraryServerTest, suggestions_in_range) -{ - /** - * Attempt to get 50 suggestions in steps of 5 - * The suggestions are returned in the json format - * [{sugg1}, {sugg2}, ... , {suggN}, {suggest ft search}] - * Assuming the number of suggestions = (occurance of "{" - 1) - */ - { - int suggCount = 0; - for (int i = 0; i < 10; i++) { - std::string url = "/ROOT/suggest?content=zimfile&term=ray&start=" + std::to_string(i*5) + "&count=5"; - const auto r = zfs1_->GET(url.c_str()); - std::string body = r->body; - int currCount = std::count(body.begin(), body.end(), '{') - 1; - ASSERT_EQ(currCount, 5); - suggCount += currCount; - } - ASSERT_EQ(suggCount, 50); - } - - // Attempt to get 10 suggestions in steps of 5 even though there are only 8 - { - std::string url = "/ROOT/suggest?content=zimfile&term=song+for+you&start=0&count=5"; - const auto r1 = zfs1_->GET(url.c_str()); - std::string body = r1->body; - int currCount = std::count(body.begin(), body.end(), '{') - 1; - ASSERT_EQ(currCount, 5); - - url = "/ROOT/suggest?content=zimfile&term=song+for+you&start=5&count=5"; - const auto r2 = zfs1_->GET(url.c_str()); - body = r2->body; - currCount = std::count(body.begin(), body.end(), '{') - 1; - ASSERT_EQ(currCount, 3); - } - - // Attempt to get 10 suggestions even though there is only 1 - { - std::string url = "/ROOT/suggest?content=zimfile&term=strong&start=0&count=5"; - const auto r = zfs1_->GET(url.c_str()); - std::string body = r->body; - int currCount = std::count(body.begin(), body.end(), '{') - 1; - ASSERT_EQ(currCount, 1); - } - - // No Suggestion - { - std::string url = "/ROOT/suggest?content=zimfile&term=oops&start=0&count=5"; - const auto r = zfs1_->GET(url.c_str()); - std::string body = r->body; - int currCount = std::count(body.begin(), body.end(), '{') - 1; - ASSERT_EQ(currCount, 0); - } - - // Out of bound value - { - std::string url = "/ROOT/suggest?content=zimfile&term=ray&start=-2&count=-1"; - const auto r = zfs1_->GET(url.c_str()); - std::string body = r->body; - int currCount = std::count(body.begin(), body.end(), '{') - 1; - ASSERT_EQ(currCount, 0); - } -} - TEST_F(LibraryServerTest, catalog_v2_individual_entry_access) { const auto r = zfs1_->GET("/ROOT/catalog/v2/entry/raycharles"); From c782cc718ade1f72cfdf4acfc62c973a801df759 Mon Sep 17 00:00:00 2001 From: Veloman Yunkan Date: Mon, 14 Feb 2022 18:17:48 +0400 Subject: [PATCH 3/3] Workaround for Packages/build-deb CI failures Packages/build-deb CI flows failed on ubuntu-bionic and ubuntu-focal with the following mismatch in the ServerTest.suggestions unit-test: ``` [ RUN ] ServerTest.suggestions ../test/server.cpp:715: Failure Expected equality of these values: r->body Which is: ... removeEOLWhitespaceMarkers(expectedResponse) Which is: ... With diff: @@ -2,5 +2,5 @@ { \"value\" : \"Ray (movie)\", - \"label\" : \"Ray (<b>movie</b>...\", + \"label\" : \"Ray (<b>movie</b>)\", \"kind\" : \"path\" , \"path\" : \"A/Ray_(movie)\" Test context: url: /ROOT/suggest?content=zimfile&term=movie ``` For some reason (probably, a bug), the implementation of `Xapian::MSet::snippet()` on those platforms decided that a single closing parenthesis is more than is appropriate for inclusion in the snippet and replaced it with a (longer) ellipsis. Taking advantage of the necessity to work around that bug, the ServerTest.suggestions's functional coverage was enhanced - the problematic test point was replaced with a new one using a phrase instead of a single term. --- test/server.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/test/server.cpp b/test/server.cpp index 798d85f83..fe584ad83 100644 --- a/test/server.cpp +++ b/test/server.cpp @@ -664,17 +664,17 @@ R"EXPECTEDRESPONSE([ ] )EXPECTEDRESPONSE" }, - { /* url: */ "/ROOT/suggest?content=zimfile&term=movie", + { /* url: */ "/ROOT/suggest?content=zimfile&term=old%20sun", R"EXPECTEDRESPONSE([ { - "value" : "Ray (movie)", - "label" : "Ray (<b>movie</b>)", + "value" : "That Lucky Old Sun", + "label" : "That Lucky <b>Old</b> <b>Sun</b>", "kind" : "path" - , "path" : "A/Ray_(movie)" + , "path" : "A/That_Lucky_Old_Sun" }, { - "value" : "movie ", - "label" : "containing 'movie'...", + "value" : "old sun ", + "label" : "containing 'old sun'...", "kind" : "pattern" //EOLWHITESPACEMARKER }