diff --git a/3party/bsdiff-courgette/bsdiff/bsdiff_search_unittest.cc b/3party/bsdiff-courgette/bsdiff/bsdiff_search_unittest.cc deleted file mode 100644 index e3f5e1210b..0000000000 --- a/3party/bsdiff-courgette/bsdiff/bsdiff_search_unittest.cc +++ /dev/null @@ -1,127 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "courgette/third_party/bsdiff/bsdiff_search.h" - -#include -#include - -#include "base/macros.h" -#include "courgette/third_party/divsufsort/divsufsort.h" -#include "testing/gtest/include/gtest/gtest.h" - -TEST(BSDiffSearchTest, Search) { - // Initialize main string and the suffix array. - // Positions: 000000000011111111111222222222333333333344444 - // 012345678901234567890123456789012345678901234 - const char* str = "the quick brown fox jumps over the lazy dog."; - int size = static_cast(::strlen(str)); - const unsigned char* buf = reinterpret_cast(str); - std::vector I(size + 1); - divsuf::divsufsort_include_empty(buf, I.data(), size); - - // Specific queries. - const struct { - int exp_match_pos; // -1 means "don't care". - int exp_match_size; - const char* query_str; - } test_cases[] = { - // Entire string: exact and unique. - {0, 44, "the quick brown fox jumps over the lazy dog."}, - // Empty string: exact and non-unique. - {-1, 0, ""}, - // Exact and unique suffix matches. - {43, 1, "."}, - {31, 13, "the lazy dog."}, - // Exact and unique non-suffix matches. - {4, 5, "quick"}, - {0, 9, "the quick"}, // Unique prefix. - // Partial and unique matches. - {16, 10, "fox jumps with the hosps"}, // Unique prefix. - {18, 1, "xyz"}, - // Exact and non-unique match: take lexicographical first. - {-1, 3, "the"}, // Non-unique prefix. - {-1, 1, " "}, - // Partial and non-unique match: no guarantees on |match.pos|! - {-1, 4, "the apple"}, // query < "the l"... < "the q"... - {-1, 4, "the opera"}, // "the l"... < query < "the q"... - {-1, 4, "the zebra"}, // "the l"... < "the q"... < query - // Prefix match dominates suffix match (unique). - {26, 5, "over quick brown fox"}, - // Empty matchs. - {-1, 0, ","}, - {-1, 0, "1234"}, - {-1, 0, "THE QUICK BROWN FOX"}, - {-1, 0, "(the"}, - }; - - for (size_t idx = 0; idx < arraysize(test_cases); ++idx) { - const auto& test_case = test_cases[idx]; - int query_size = static_cast(::strlen(test_case.query_str)); - const unsigned char* query_buf = - reinterpret_cast(test_case.query_str); - - // Perform the search. - bsdiff::SearchResult match = - bsdiff::search( - I, buf, size, query_buf, query_size); - - // Check basic properties and match with expected values. - EXPECT_GE(match.size, 0); - EXPECT_LE(match.size, query_size); - if (match.size > 0) { - EXPECT_GE(match.pos, 0); - EXPECT_LE(match.pos, size - match.size); - EXPECT_EQ(0, ::memcmp(buf + match.pos, query_buf, match.size)); - } - if (test_case.exp_match_pos >= 0) { - EXPECT_EQ(test_case.exp_match_pos, match.pos); - } - EXPECT_EQ(test_case.exp_match_size, match.size); - } -} - -TEST(BSDiffSearchTest, SearchExact) { - const char* test_cases[] = { - "a", - "aa", - "az", - "za", - "aaaaa", - "CACAO", - "banana", - "tobeornottobe", - "the quick brown fox jumps over the lazy dog.", - "elephantelephantelephantelephantelephant", - "011010011001011010010110011010010", - }; - for (size_t idx = 0; idx < arraysize(test_cases); ++idx) { - int size = static_cast(::strlen(test_cases[idx])); - const unsigned char* buf = - reinterpret_cast(test_cases[idx]); - - std::vector I(size + 1); - divsuf::divsufsort_include_empty(buf, I.data(), size); - - // Test exact matches for every non-empty substring. - for (int lo = 0; lo < size; ++lo) { - for (int hi = lo + 1; hi <= size; ++hi) { - std::string query(buf + lo, buf + hi); - int query_size = static_cast(query.length()); - ASSERT_EQ(query_size, hi - lo); - const unsigned char* query_buf = - reinterpret_cast(query.c_str()); - bsdiff::SearchResult match = - bsdiff::search( - I, buf, size, query_buf, query_size); - - EXPECT_EQ(query_size, match.size); - EXPECT_GE(match.pos, 0); - EXPECT_LE(match.pos, size - match.size); - std::string suffix(buf + match.pos, buf + size); - EXPECT_EQ(suffix.substr(0, query_size), query); - } - } - } -} diff --git a/generator/mwm_diff/mwm_diff_tests/CMakeLists.txt b/generator/mwm_diff/mwm_diff_tests/CMakeLists.txt index 92dd2a0cee..f6807262ee 100644 --- a/generator/mwm_diff/mwm_diff_tests/CMakeLists.txt +++ b/generator/mwm_diff/mwm_diff_tests/CMakeLists.txt @@ -2,7 +2,8 @@ project(mwm_diff_tests) set( SRC - diff_test.cpp + bsdiff_search_tests.cpp + diff_tests.cpp ) omim_add_test(${PROJECT_NAME} ${SRC}) diff --git a/generator/mwm_diff/mwm_diff_tests/bsdiff_search_tests.cpp b/generator/mwm_diff/mwm_diff_tests/bsdiff_search_tests.cpp new file mode 100644 index 0000000000..39c707019c --- /dev/null +++ b/generator/mwm_diff/mwm_diff_tests/bsdiff_search_tests.cpp @@ -0,0 +1,135 @@ +#include "testing/testing.hpp" + +#include "base/macros.hpp" + +#include +#include +#include + +#include "3party/bsdiff-courgette/bsdiff/bsdiff_search.h" +#include "3party/bsdiff-courgette/divsufsort/divsufsort.h" + +using namespace std; + +// Adapted from 3party/bsdiff-courgette. +UNIT_TEST(BSDiffSearchTest_Search) +{ + // Initialize main string and the suffix array. + // Positions: 000000000011111111111222222222333333333344444 + // 012345678901234567890123456789012345678901234 + string const str = "the quick brown fox jumps over the lazy dog."; + int const size = static_cast(str.size()); + unsigned char const * const buf = reinterpret_cast(str.data()); + vector I(size + 1); + divsuf::divsufsort_include_empty(buf, I.data(), size); + + // Specific queries. + struct + { + int m_expMatchPos; // -1 means "don't care". + int m_expMatchSize; + string m_query_str; + } const testCases[] = { + // Entire string: exact and unique. + {0, 44, "the quick brown fox jumps over the lazy dog."}, + // Empty string: exact and non-unique. + {-1, 0, ""}, + // Exact and unique suffix matches. + {43, 1, "."}, + {31, 13, "the lazy dog."}, + // Exact and unique non-suffix matches. + {4, 5, "quick"}, + {0, 9, "the quick"}, // Unique prefix. + // Partial and unique matches. + {16, 10, "fox jumps with the hosps"}, // Unique prefix. + {18, 1, "xyz"}, + // Exact and non-unique match: take lexicographical first. + {-1, 3, "the"}, // Non-unique prefix. + {-1, 1, " "}, + // Partial and non-unique match: no guarantees on |match.pos|! + {-1, 4, "the apple"}, // query < "the l"... < "the q"... + {-1, 4, "the opera"}, // "the l"... < query < "the q"... + {-1, 4, "the zebra"}, // "the l"... < "the q"... < query + // Prefix match dominates suffix match (unique). + {26, 5, "over quick brown fox"}, + // Empty matchs. + {-1, 0, ","}, + {-1, 0, "1234"}, + {-1, 0, "THE QUICK BROWN FOX"}, + {-1, 0, "(the"}, + }; + + for (size_t idx = 0; idx < ARRAY_SIZE(testCases); ++idx) + { + auto const & testCase = testCases[idx]; + int const querySize = static_cast(testCase.m_query_str.size()); + unsigned char const * const query_buf = + reinterpret_cast(testCase.m_query_str.data()); + + // Perform the search. + bsdiff::SearchResult const match = bsdiff::search(I, buf, size, query_buf, querySize); + + // Check basic properties and match with expected values. + TEST_GREATER_OR_EQUAL(match.size, 0, ()); + TEST_LESS_OR_EQUAL(match.size, querySize, ()); + if (match.size > 0) + { + TEST_GREATER_OR_EQUAL(match.pos, 0, ()); + TEST_LESS_OR_EQUAL(match.pos, size - match.size, ()); + TEST_EQUAL(0, memcmp(buf + match.pos, query_buf, match.size), ()); + } + if (testCase.m_expMatchPos >= 0) + { + TEST_EQUAL(testCase.m_expMatchPos, match.pos, ()); + } + TEST_EQUAL(testCase.m_expMatchSize, match.size, ()); + } +} + +// Adapted from 3party/bsdiff-courgette. +UNIT_TEST(BSDiffSearchTest_SearchExact) +{ + string const testCases[] = { + "a", + "aa", + "az", + "za", + "aaaaa", + "CACAO", + "banana", + "tobeornottobe", + "the quick brown fox jumps over the lazy dog.", + "elephantelephantelephantelephantelephant", + "011010011001011010010110011010010", + }; + for (size_t idx = 0; idx < ARRAY_SIZE(testCases); ++idx) + { + int const size = static_cast(testCases[idx].size()); + unsigned char const * const buf = + reinterpret_cast(testCases[idx].data()); + + vector I(size + 1); + divsuf::divsufsort_include_empty(buf, I.data(), size); + + // Test exact matches for every non-empty substring. + for (int lo = 0; lo < size; ++lo) + { + for (int hi = lo + 1; hi <= size; ++hi) + { + string query(buf + lo, buf + hi); + int querySize = static_cast(query.size()); + CHECK_EQUAL(querySize, hi - lo, ()); + unsigned char const * const query_buf = + reinterpret_cast(query.c_str()); + bsdiff::SearchResult const match = + bsdiff::search(I, buf, size, query_buf, querySize); + + TEST_EQUAL(querySize, match.size, ()); + TEST_GREATER_OR_EQUAL(match.pos, 0, ()); + TEST_LESS_OR_EQUAL(match.pos, size - match.size, ()); + string const suffix(buf + match.pos, buf + size); + TEST_EQUAL(suffix.substr(0, querySize), query, ()); + } + } + } +} diff --git a/generator/mwm_diff/mwm_diff_tests/diff_test.cpp b/generator/mwm_diff/mwm_diff_tests/diff_tests.cpp similarity index 95% rename from generator/mwm_diff/mwm_diff_tests/diff_test.cpp rename to generator/mwm_diff/mwm_diff_tests/diff_tests.cpp index 48b65acc5a..88f0d4dac4 100644 --- a/generator/mwm_diff/mwm_diff_tests/diff_test.cpp +++ b/generator/mwm_diff/mwm_diff_tests/diff_tests.cpp @@ -31,7 +31,8 @@ UNIT_TEST(IncrementalUpdates_Smoke) base::JoinFoldersToPath(GetPlatform().WritableDir(), "minsk-pass-new1.mwm"); string const newMwmPath2 = base::JoinFoldersToPath(GetPlatform().WritableDir(), "minsk-pass-new2.mwm"); - string const diffPath = base::JoinFoldersToPath(GetPlatform().WritableDir(), "minsk-pass.mwmdiff"); + string const diffPath = + base::JoinFoldersToPath(GetPlatform().WritableDir(), "minsk-pass.mwmdiff"); SCOPE_GUARD(cleanup, [&] { FileWriter::DeleteFileX(newMwmPath1);