Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(307)

Side by Side Diff: components/subresource_filter/core/common/knuth_morris_pratt_unittest.cc

Issue 2793993002: [subresource_filter] Replace KMP by std::search. (Closed)
Patch Set: Fix DCHECK. Created 3 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
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
3 // found in the LICENSE file.
4
5 #include "components/subresource_filter/core/common/knuth_morris_pratt.h"
6
7 #include <cctype>
8 #include <functional>
9 #include <string>
10 #include <vector>
11
12 #include "testing/gtest/include/gtest/gtest.h"
13
14 namespace subresource_filter {
15
16 namespace {
17
18 bool NumerophobicEquivalentTo(char first, char second) {
19 return first == second || (std::isdigit(first) && std::isdigit(second));
20 }
21
22 template <typename EquivalentTo = std::equal_to<char>>
23 std::vector<size_t> FindAllOccurrences(
24 base::StringPiece string,
25 base::StringPiece pattern,
26 const std::vector<size_t>& failure_function,
27 EquivalentTo equivalent_to = EquivalentTo()) {
28 std::vector<size_t> positions;
29
30 size_t position = 0;
31 size_t relative_position = FindFirstOccurrence(
32 string, pattern, failure_function.data(), equivalent_to);
33
34 while (relative_position != base::StringPiece::npos) {
35 position += relative_position;
36 positions.push_back(position);
37 relative_position =
38 FindNextOccurrence(string.substr(position), pattern,
39 failure_function.data(), equivalent_to);
40 }
41
42 return positions;
43 }
44
45 } // namespace
46
47 TEST(KnuthMorrisPrattTest, BuildFailureFunctionRegular) {
48 const struct {
49 std::string string;
50 std::vector<size_t> expected_failure_function;
51 } kTestCases[] = {
52 {"", std::vector<size_t>()},
53 {"a", {0}},
54 {"aa", {0, 1}},
55 {"aaa", {0, 1, 2}},
56 {"abc", {0, 0, 0}},
57 {"abca", {0, 0, 0, 1}},
58 {"abacaba", {0, 0, 1, 0, 1, 2, 3}},
59 {"str-sstrr", {0, 0, 0, 0, 1, 1, 2, 3, 0}},
60 {"sts-ststs", {0, 0, 1, 0, 1, 2, 3, 2, 3}},
61 };
62
63 for (const auto& test_case : kTestCases) {
64 SCOPED_TRACE(testing::Message() << "String: " << test_case.string);
65
66 std::vector<size_t> failure;
67 BuildFailureFunction(test_case.string, &failure);
68 EXPECT_EQ(test_case.expected_failure_function, failure);
69 }
70 }
71
72 TEST(KnuthMorrisPrattTest, BuildFailureFunctionWithEquivalentChars) {
73 const struct {
74 std::string string;
75 std::vector<size_t> expected_failure_function;
76 } kTestCases[] = {
77 {"123", {0, 1, 2}},
78 {"0str1str", {0, 0, 0, 0, 1, 2, 3, 4}},
79 {"7str8srr", {0, 0, 0, 0, 1, 2, 0, 0}},
80 {"567str9sr", {0, 1, 2, 0, 0, 0, 1, 0, 0}},
81 {"567str999sr", {0, 1, 2, 0, 0, 0, 1, 2, 3, 4, 0}},
82 {"str9sr6", {0, 0, 0, 0, 1, 0, 0}},
83 {"5a6a7a8a9a", {0, 0, 1, 2, 3, 4, 5, 6, 7, 8}},
84 };
85
86 for (const auto& test_case : kTestCases) {
87 SCOPED_TRACE(testing::Message() << "String: " << test_case.string);
88
89 std::vector<size_t> failure;
90 BuildFailureFunction(test_case.string, &failure, NumerophobicEquivalentTo);
91 EXPECT_EQ(test_case.expected_failure_function, failure);
92 }
93 }
94
95 TEST(KnuthMorrisPrattTest, FindSubstringsRegular) {
96 const struct {
97 std::string string;
98 std::string pattern;
99 std::vector<size_t> expected_positions;
100 } kTestCases[] = {
101 {"", "abc", std::vector<size_t>()},
102 {"abc", "", {0, 1, 2, 3}},
103 {"abc", "abc", {3}},
104 {"aaaabc", "abc", {6}},
105 {"abcccc", "abc", {3}},
106 {"aabcc", "abc", {4}},
107 {"aabcabcabcc", "abc", {4, 7, 10}},
108 {"abcabcabc", "abc", {3, 6, 9}},
109 {"abab", "abc", std::vector<size_t>()},
110 {"ababac", "abc", std::vector<size_t>()},
111 {"aaaaaa", "a", {1, 2, 3, 4, 5, 6}},
112 {"aaaaaa", "aaa", {3, 4, 5, 6}},
113 {"abababa", "aba", {3, 5, 7}},
114 {"acdacdacdac", "cdacd", {6, 9}},
115 };
116
117 for (const auto& test_case : kTestCases) {
118 SCOPED_TRACE(testing::Message() << "String: " << test_case.string
119 << "; Pattern: " << test_case.pattern);
120
121 std::vector<size_t> failure;
122 BuildFailureFunction(test_case.pattern, &failure);
123
124 std::vector<size_t> positions =
125 FindAllOccurrences(test_case.string, test_case.pattern, failure);
126 EXPECT_EQ(test_case.expected_positions, positions);
127
128 auto occurrences = CreateAllOccurrences(test_case.string, test_case.pattern,
129 failure.data());
130 positions.assign(occurrences.begin(), occurrences.end());
131 EXPECT_EQ(test_case.expected_positions, positions);
132 }
133 }
134
135 TEST(KnuthMorrisPrattTest, FindSubstringsWithEquivalentChars) {
136 const struct {
137 std::string string;
138 std::string pattern;
139 std::vector<size_t> expected_positions;
140 } kTestCases[] = {
141 {"", "abc", std::vector<size_t>()},
142 {"012", "1", {1, 2, 3}},
143 {"012", "012", {3}},
144 {"123456", "000", {3, 4, 5, 6}},
145 {"0a1a2a3a", "1a2", {3, 5, 7}},
146 {"0aa1a2aa3a", "1aa2", {4, 9}},
147 };
148
149 for (const auto& test_case : kTestCases) {
150 SCOPED_TRACE(testing::Message() << "String: " << test_case.string
151 << "; Pattern: " << test_case.pattern);
152
153 std::vector<size_t> failure;
154 BuildFailureFunction(test_case.pattern, &failure, NumerophobicEquivalentTo);
155
156 std::vector<size_t> positions = FindAllOccurrences(
157 test_case.string, test_case.pattern, failure, NumerophobicEquivalentTo);
158 EXPECT_EQ(test_case.expected_positions, positions);
159
160 auto occurrences =
161 CreateAllOccurrences(test_case.string, test_case.pattern,
162 failure.data(), NumerophobicEquivalentTo);
163 positions.assign(occurrences.begin(), occurrences.end());
164 EXPECT_EQ(test_case.expected_positions, positions);
165 }
166 }
167
168 TEST(KnuthMorrisPrattTest, AllOccurrencesIterator) {
169 const struct {
170 std::string string;
171 std::string pattern;
172 std::vector<size_t> expected_positions;
173 } kTestCases[] = {
174 {"", "abc", std::vector<size_t>()},
175 {"abc", "", {0, 1, 2, 3}},
176 {"abc", "abc", {3}},
177 {"aaa", "a", {1, 2, 3}},
178 {"aaaabc", "abc", {6}},
179 };
180
181 for (const auto& test_case : kTestCases) {
182 SCOPED_TRACE(testing::Message() << "String: " << test_case.string
183 << "; Pattern: " << test_case.pattern);
184
185 std::vector<size_t> failure;
186 BuildFailureFunction(test_case.pattern, &failure);
187
188 auto occurrences = CreateAllOccurrences(test_case.string, test_case.pattern,
189 failure.data());
190
191 auto iterator = occurrences.begin();
192 const size_t size = test_case.expected_positions.size();
193 for (size_t i = 0; i != size; ++i, ++iterator) {
194 const size_t expected_position = test_case.expected_positions[i];
195 EXPECT_EQ(expected_position, *iterator);
196
197 auto iterator_copy = iterator;
198 EXPECT_EQ(iterator, iterator_copy);
199 EXPECT_EQ(expected_position, *iterator_copy);
200
201 EXPECT_EQ(iterator_copy, iterator++);
202 EXPECT_NE(iterator_copy, iterator);
203 if (i + 1 != size) {
204 EXPECT_NE(occurrences.end(), iterator);
205 EXPECT_EQ(test_case.expected_positions[i + 1], *iterator);
206 } else {
207 EXPECT_EQ(occurrences.end(), iterator);
208 }
209
210 iterator = iterator_copy;
211 EXPECT_EQ(expected_position, *iterator);
212 }
213
214 EXPECT_EQ(occurrences.end(), iterator);
215 }
216 }
217
218 } // namespace subresource_filter
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698