Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "components/subresource_filter/core/common/fuzzy_pattern_matching.h" | 5 #include "components/subresource_filter/core/common/fuzzy_pattern_matching.h" |
| 6 | 6 |
| 7 #include <vector> | 7 #include <vector> |
| 8 | 8 |
| 9 #include "testing/gtest/include/gtest/gtest.h" | 9 #include "testing/gtest/include/gtest/gtest.h" |
| 10 | 10 |
| 11 namespace subresource_filter { | 11 namespace subresource_filter { |
| 12 | 12 |
| 13 TEST(FuzzyPatternMatchingTest, StartsWithFuzzy) { | 13 TEST(SubresourceFilterFuzzyPatternMatchingTest, StartsWithFuzzy) { |
| 14 const struct { | 14 const struct { |
| 15 const char* text; | 15 const char* text; |
| 16 const char* subpattern; | 16 const char* subpattern; |
| 17 bool expected_starts_with; | 17 bool expected_starts_with; |
| 18 } kTestCases[] = { | 18 } kTestCases[] = { |
| 19 {"abc", "", true}, {"abc", "a", true}, {"abc", "ab", true}, | 19 {"abc", "", true}, {"abc", "a", true}, {"abc", "ab", true}, |
| 20 {"abc", "abc", true}, {"abc", "abcd", false}, {"abc", "abc^^", false}, | 20 {"abc", "abc", true}, {"abc", "abcd", false}, {"abc", "abc^^", false}, |
| 21 {"abc", "abcd^", false}, {"abc", "ab^", false}, {"abc", "bc", false}, | 21 {"abc", "abcd^", false}, {"abc", "ab^", false}, {"abc", "bc", false}, |
| 22 {"abc", "bc^", false}, {"abc", "^abc", false}, | 22 {"abc", "bc^", false}, {"abc", "^abc", false}, |
| 23 }; | 23 }; |
| 24 // TODO(pkalinnikov): Make end-of-string match '^' again. | 24 // TODO(pkalinnikov): Make end-of-string match '^' again. |
| 25 | 25 |
| 26 for (const auto& test_case : kTestCases) { | 26 for (const auto& test_case : kTestCases) { |
| 27 SCOPED_TRACE(testing::Message() | 27 SCOPED_TRACE(testing::Message() |
| 28 << "Test: " << test_case.text | 28 << "Test: " << test_case.text |
| 29 << "; Subpattern: " << test_case.subpattern); | 29 << "; Subpattern: " << test_case.subpattern); |
| 30 | 30 |
| 31 const bool starts_with = | 31 const bool starts_with = |
| 32 StartsWithFuzzy(test_case.text, test_case.subpattern); | 32 StartsWithFuzzy(test_case.text, test_case.subpattern); |
| 33 EXPECT_EQ(test_case.expected_starts_with, starts_with); | 33 EXPECT_EQ(test_case.expected_starts_with, starts_with); |
| 34 } | 34 } |
| 35 } | 35 } |
| 36 | 36 |
| 37 TEST(FuzzyPatternMatchingTest, EndsWithFuzzy) { | 37 TEST(SubresourceFilterFuzzyPatternMatchingTest, EndsWithFuzzy) { |
| 38 const struct { | 38 const struct { |
| 39 const char* text; | 39 const char* text; |
| 40 const char* subpattern; | 40 const char* subpattern; |
| 41 bool expected_ends_with; | 41 bool expected_ends_with; |
| 42 } kTestCases[] = { | 42 } kTestCases[] = { |
| 43 {"abc", "", true}, {"abc", "c", true}, {"abc", "bc", true}, | 43 {"abc", "", true}, {"abc", "c", true}, {"abc", "bc", true}, |
| 44 {"abc", "abc", true}, {"abc", "0abc", false}, {"abc", "abc^^", false}, | 44 {"abc", "abc", true}, {"abc", "0abc", false}, {"abc", "abc^^", false}, |
| 45 {"abc", "abcd^", false}, {"abc", "ab^", false}, {"abc", "ab", false}, | 45 {"abc", "abcd^", false}, {"abc", "ab^", false}, {"abc", "ab", false}, |
| 46 {"abc", "^abc", false}, | 46 {"abc", "^abc", false}, |
| 47 }; | 47 }; |
| 48 // TODO(pkalinnikov): Make end-of-string match '^' again. | 48 // TODO(pkalinnikov): Make end-of-string match '^' again. |
| 49 | 49 |
| 50 for (const auto& test_case : kTestCases) { | 50 for (const auto& test_case : kTestCases) { |
| 51 SCOPED_TRACE(testing::Message() | 51 SCOPED_TRACE(testing::Message() |
| 52 << "Test: " << test_case.text | 52 << "Test: " << test_case.text |
| 53 << "; Subpattern: " << test_case.subpattern); | 53 << "; Subpattern: " << test_case.subpattern); |
| 54 | 54 |
| 55 const bool ends_with = EndsWithFuzzy(test_case.text, test_case.subpattern); | 55 const bool ends_with = EndsWithFuzzy(test_case.text, test_case.subpattern); |
| 56 EXPECT_EQ(test_case.expected_ends_with, ends_with); | 56 EXPECT_EQ(test_case.expected_ends_with, ends_with); |
| 57 } | 57 } |
| 58 } | 58 } |
| 59 | |
| 59 TEST(FuzzyPatternMatchingTest, AllOccurrences) { | 60 TEST(FuzzyPatternMatchingTest, AllOccurrences) { |
|
pkalinnikov
2017/04/05 13:30:57
nit: Add "SubresourceFilter" prefix.
pkalinnikov
2017/04/05 13:48:46
Done.
| |
| 60 const struct { | 61 const struct { |
| 61 const char* text; | 62 base::StringPiece text; |
| 62 const char* subpattern; | 63 base::StringPiece subpattern; |
| 63 std::vector<size_t> expected_matches; | 64 std::vector<size_t> expected_matches; |
| 64 } kTestCases[] = { | 65 } kTestCases[] = { |
| 65 {"abcd", "", {0, 1, 2, 3, 4}}, | 66 {"abcd", "", {0, 1, 2, 3, 4}}, |
| 66 {"abcd", "de", std::vector<size_t>()}, | 67 {"abcd", "de", std::vector<size_t>()}, |
| 67 {"abcd", "ab", {2}}, | 68 {"abcd", "ab", {0}}, |
| 68 {"abcd", "bc", {3}}, | 69 {"abcd", "bc", {1}}, |
| 69 {"abcd", "cd", {4}}, | 70 {"abcd", "cd", {2}}, |
| 70 | 71 |
| 71 {"a/bc/a/b", "", {0, 1, 2, 3, 4, 5, 6, 7, 8}}, | 72 {"a/bc/a/b", "", {0, 1, 2, 3, 4, 5, 6, 7, 8}}, |
| 72 {"a/bc/a/b", "de", std::vector<size_t>()}, | 73 {"a/bc/a/b", "de", std::vector<size_t>()}, |
| 73 {"a/bc/a/b", "a/", {2, 7}}, | 74 {"a/bc/a/b", "a/", {0, 5}}, |
| 74 {"a/bc/a/c", "a/c", {8}}, | 75 {"a/bc/a/c", "a/c", {5}}, |
| 75 {"a/bc/a/c", "a^c", {8}}, | 76 {"a/bc/a/c", "a^c", {5}}, |
| 76 {"a/bc/a/c", "a?c", std::vector<size_t>()}, | 77 {"a/bc/a/c", "a?c", std::vector<size_t>()}, |
| 77 | 78 |
| 78 {"ab^cd", "ab/cd", std::vector<size_t>()}, | 79 {"ab^cd", "ab/cd", std::vector<size_t>()}, |
| 79 {"ab^cd", "b/c", std::vector<size_t>()}, | 80 {"ab^cd", "b/c", std::vector<size_t>()}, |
| 80 {"ab^cd", "ab^cd", {5}}, | 81 {"ab^cd", "ab^cd", {0}}, |
| 81 {"ab^cd", "b^c", {4}}, | 82 {"ab^cd", "b^c", {1}}, |
| 82 {"ab^b/b", "b/b", {6}}, | 83 {"ab^b/b", "b/b", {3}}, |
| 83 | 84 |
| 84 {"a/a/a/a", "a/a", {3, 5, 7}}, | 85 {"a/a/a/a", "a/a", {0, 2, 4}}, |
| 85 {"a/a/a/a", "^a^a^a", {7}}, | 86 {"a/a/a/a", "^a^a^a", {1}}, |
| 86 {"a/a/a/a", "^a^a?a", std::vector<size_t>()}, | 87 {"a/a/a/a", "^a^a?a", std::vector<size_t>()}, |
| 87 {"a/a/a/a", "?a?a?a", std::vector<size_t>()}, | 88 {"a/a/a/a", "?a?a?a", std::vector<size_t>()}, |
| 88 }; | 89 }; |
| 89 | 90 |
| 90 for (const auto& test_case : kTestCases) { | 91 for (const auto& test_case : kTestCases) { |
| 91 SCOPED_TRACE(testing::Message() | 92 SCOPED_TRACE(testing::Message() |
| 92 << "Test: " << test_case.text | 93 << "Test: " << test_case.text |
| 93 << "; Subpattern: " << test_case.subpattern); | 94 << "; Subpattern: " << test_case.subpattern); |
| 94 | 95 |
| 95 std::vector<size_t> failure; | 96 std::vector<size_t> matches; |
| 96 BuildFailureFunctionFuzzy(test_case.subpattern, &failure); | |
| 97 | 97 |
|
pkalinnikov
2017/04/05 13:30:57
nit: Remove the blank line.
pkalinnikov
2017/04/05 13:48:47
Done.
| |
| 98 const auto& occurrences = AllOccurrencesFuzzy<size_t>( | 98 for (size_t position = 0; position <= test_case.text.size(); ++position) { |
| 99 test_case.text, test_case.subpattern, failure.data()); | 99 position = FindFuzzy(test_case.text, test_case.subpattern, position); |
| 100 std::vector<size_t> matches(occurrences.begin(), occurrences.end()); | 100 if (position == base::StringPiece::npos) |
| 101 break; | |
| 102 matches.push_back(position); | |
| 103 } | |
| 104 | |
| 101 EXPECT_EQ(test_case.expected_matches, matches); | 105 EXPECT_EQ(test_case.expected_matches, matches); |
| 102 } | 106 } |
| 103 } | 107 } |
| 104 | 108 |
| 105 } // namespace subresource_filter | 109 } // namespace subresource_filter |
| OLD | NEW |