OLD | NEW |
---|---|
(Empty) | |
1 // Copyright (c) 2012 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 "base/basictypes.h" | |
6 #include "sync/internal_api/public/base/ordinal.h" | |
7 #include "testing/gtest/include/gtest/gtest.h" | |
8 | |
9 #include <algorithm> | |
10 #include <string> | |
11 #include <vector> | |
12 | |
13 namespace syncer { | |
14 | |
15 namespace { | |
16 | |
17 struct TestOrdinalTraits { | |
18 static const uint8 kZeroDigit = '0'; | |
19 static const uint8 kMaxDigit = '3'; | |
20 static const size_t kMinLength = 1; | |
21 }; | |
22 | |
23 struct LongOrdinalTraits { | |
24 static const uint8 kZeroDigit = '0'; | |
25 static const uint8 kMaxDigit = '9'; | |
26 static const size_t kMinLength = 5; | |
27 }; | |
28 | |
29 struct LargeOrdinalTraits { | |
30 static const uint8 kZeroDigit = 0; | |
31 static const uint8 kMaxDigit = kuint8max; | |
32 static const size_t kMinLength = 1; | |
33 }; | |
34 | |
35 typedef Ordinal<TestOrdinalTraits> TestOrdinal; | |
36 typedef Ordinal<LongOrdinalTraits> LongOrdinal; | |
37 typedef Ordinal<LargeOrdinalTraits> LargeOrdinal; | |
38 | |
39 COMPILE_ASSERT(TestOrdinal::kZeroDigit == '0', | |
40 TestOrdinalHasCorrectZeroDigit); | |
41 COMPILE_ASSERT(TestOrdinal::kOneDigit == '1', | |
42 TestOrdinalHasCorrectOneDigit); | |
43 COMPILE_ASSERT(TestOrdinal::kMidDigit == '2', | |
44 TestOrdinalHasCorrectMidDigit); | |
45 COMPILE_ASSERT(TestOrdinal::kMaxDigit == '3', | |
46 TestOrdinalHasCorrectMaxDigit); | |
47 COMPILE_ASSERT(TestOrdinal::kMidDigitValue == 2, | |
48 TestOrdinalHasCorrectMidDigitValue); | |
49 COMPILE_ASSERT(TestOrdinal::kMaxDigitValue == 3, | |
50 TestOrdinalHasCorrectMaxDigitValue); | |
51 COMPILE_ASSERT(TestOrdinal::kRadix == 4, | |
52 TestOrdinalHasCorrectRadix); | |
53 | |
54 COMPILE_ASSERT(LongOrdinal::kZeroDigit == '0', | |
55 LongOrdinalkZeroDigit_incorrect); | |
56 COMPILE_ASSERT(LongOrdinal::kOneDigit == '1', | |
57 LongOrdinalkOneDigit_incorrect); | |
58 COMPILE_ASSERT(LongOrdinal::kMidDigit == '5', | |
59 LongOrdinalkMidDigit_incorrect); | |
60 COMPILE_ASSERT(LongOrdinal::kMaxDigit == '9', | |
61 LongOrdinalkMaxDigit_incorrect); | |
62 COMPILE_ASSERT(LongOrdinal::kMidDigitValue == 5, | |
63 LongOrdinalkMidDigitValue_incorrect); | |
64 COMPILE_ASSERT(LongOrdinal::kMaxDigitValue == 9, | |
65 LongOrdinalkMaxDigitValue_incorrect); | |
66 COMPILE_ASSERT(LongOrdinal::kRadix == 10, | |
67 LongOrdinalkRadix_incorrect); | |
68 | |
69 COMPILE_ASSERT(static_cast<char>(LargeOrdinal::kZeroDigit) == '\x00', | |
70 LargeOrdinalkZeroDigit_incorrect); | |
71 COMPILE_ASSERT(static_cast<char>(LargeOrdinal::kOneDigit) == '\x01', | |
72 LargeOrdinalkOneDigit_incorrect); | |
73 COMPILE_ASSERT(static_cast<char>(LargeOrdinal::kMidDigit) == '\x80', | |
74 LargeOrdinalkMidDigit_incorrect); | |
75 COMPILE_ASSERT(static_cast<char>(LargeOrdinal::kMaxDigit) == '\xff', | |
76 LargeOrdinalkMaxDigit_incorrect); | |
77 COMPILE_ASSERT(LargeOrdinal::kMidDigitValue == 128, | |
78 LargeOrdinalkMidDigitValue_incorrect); | |
79 COMPILE_ASSERT(LargeOrdinal::kMaxDigitValue == 255, | |
80 LargeOrdinalkMaxDigitValue_incorrect); | |
81 COMPILE_ASSERT(LargeOrdinal::kRadix == 256, | |
82 LargeOrdinalkRadix_incorrect); | |
83 | |
84 // Create Ordinals that satisfy all but one criterion for validity. | |
85 // IsValid() should return false for all of them. | |
86 TEST(Ordinal, Invalid) { | |
87 // Length criterion. | |
88 EXPECT_FALSE(TestOrdinal("").IsValid()); | |
89 EXPECT_FALSE(LongOrdinal("0001").IsValid()); | |
90 | |
91 const char kBeforeZero[] = { '0' - 1, '\0' }; | |
92 const char kAfterNine[] = { '9' + 1, '\0' }; | |
93 | |
94 // Character criterion. | |
95 EXPECT_FALSE(TestOrdinal(kBeforeZero).IsValid()); | |
96 EXPECT_FALSE(TestOrdinal("4").IsValid()); | |
97 EXPECT_FALSE(LongOrdinal(std::string("0000") + kBeforeZero).IsValid()); | |
98 EXPECT_FALSE(LongOrdinal(std::string("0000") + kAfterNine).IsValid()); | |
99 | |
100 // Zero criterion. | |
101 EXPECT_FALSE(TestOrdinal("0").IsValid()); | |
102 EXPECT_FALSE(TestOrdinal("00000").IsValid()); | |
103 | |
104 // Trailing zero criterion. | |
105 EXPECT_FALSE(TestOrdinal("10").IsValid()); | |
106 EXPECT_FALSE(TestOrdinal("111110").IsValid()); | |
107 } | |
108 | |
109 // Create Ordinals that satisfy all criteria for validity. | |
110 // IsValid() should return true for all of them. | |
111 TEST(Ordinal, Valid) { | |
112 // Length criterion. | |
113 EXPECT_TRUE(TestOrdinal("1").IsValid()); | |
114 EXPECT_TRUE(LongOrdinal("10000").IsValid()); | |
115 } | |
116 | |
117 // Create Ordinals from CreateInitialOrdinal. They should be valid | |
118 // and close to the middle of the range. | |
119 TEST(Ordinal, CreateInitialOrdinal) { | |
120 const TestOrdinal& ordinal1 = TestOrdinal::CreateInitialOrdinal(); | |
121 const LongOrdinal& ordinal2 = LongOrdinal::CreateInitialOrdinal(); | |
122 ASSERT_TRUE(ordinal1.IsValid()); | |
123 ASSERT_TRUE(ordinal2.IsValid()); | |
124 EXPECT_TRUE(ordinal1.Equals(TestOrdinal("2"))); | |
125 EXPECT_TRUE(ordinal2.Equals(LongOrdinal("50000"))); | |
126 } | |
127 | |
128 // Create an invalid and a valid Ordinal. EqualsOrBothInvalid should | |
129 // return true if called reflexively and false otherwise. | |
130 TEST(Ordinal, EqualsOrBothInvalid) { | |
131 const TestOrdinal& valid_ordinal = TestOrdinal::CreateInitialOrdinal(); | |
132 const TestOrdinal invalid_ordinal; | |
133 | |
134 EXPECT_TRUE(valid_ordinal.EqualsOrBothInvalid(valid_ordinal)); | |
135 EXPECT_TRUE(invalid_ordinal.EqualsOrBothInvalid(invalid_ordinal)); | |
136 EXPECT_FALSE(invalid_ordinal.EqualsOrBothInvalid(valid_ordinal)); | |
137 EXPECT_FALSE(valid_ordinal.EqualsOrBothInvalid(invalid_ordinal)); | |
138 } | |
139 | |
140 // Create three Ordinals in order. LessThan should return values | |
141 // consistent with that order. | |
142 TEST(Ordinal, LessThan) { | |
143 const TestOrdinal small_ordinal("1"); | |
144 const TestOrdinal middle_ordinal("2"); | |
145 const TestOrdinal big_ordinal("3"); | |
146 | |
147 EXPECT_FALSE(small_ordinal.LessThan(small_ordinal)); | |
148 EXPECT_TRUE(small_ordinal.LessThan(middle_ordinal)); | |
149 EXPECT_TRUE(small_ordinal.LessThan(big_ordinal)); | |
150 | |
151 EXPECT_FALSE(middle_ordinal.LessThan(small_ordinal)); | |
152 EXPECT_FALSE(middle_ordinal.LessThan(middle_ordinal)); | |
153 EXPECT_TRUE(middle_ordinal.LessThan(big_ordinal)); | |
154 | |
155 EXPECT_FALSE(big_ordinal.LessThan(small_ordinal)); | |
156 EXPECT_FALSE(big_ordinal.LessThan(middle_ordinal)); | |
157 EXPECT_FALSE(big_ordinal.LessThan(big_ordinal)); | |
158 } | |
159 | |
160 // Create two single-digit ordinals with byte values 0 and 255. The | |
161 // former should compare as less than the latter, even though the | |
162 // native char type may be signed. | |
163 TEST(Ordinal, LessThanLarge) { | |
164 const LargeOrdinal small_ordinal("\x01"); | |
165 const LargeOrdinal big_ordinal("\xff"); | |
166 | |
167 EXPECT_TRUE(small_ordinal.LessThan(big_ordinal)); | |
168 } | |
169 | |
170 // Create three Ordinals in order. GreaterThan should return values | |
171 // consistent with that order. | |
172 TEST(Ordinal, GreaterThan) { | |
173 const LongOrdinal small_ordinal("10000"); | |
174 const LongOrdinal middle_ordinal("55555"); | |
175 const LongOrdinal big_ordinal("99999"); | |
176 | |
177 EXPECT_FALSE(small_ordinal.GreaterThan(small_ordinal)); | |
178 EXPECT_FALSE(small_ordinal.GreaterThan(middle_ordinal)); | |
179 EXPECT_FALSE(small_ordinal.GreaterThan(big_ordinal)); | |
180 | |
181 EXPECT_TRUE(middle_ordinal.GreaterThan(small_ordinal)); | |
182 EXPECT_FALSE(middle_ordinal.GreaterThan(middle_ordinal)); | |
183 EXPECT_FALSE(middle_ordinal.GreaterThan(big_ordinal)); | |
184 | |
185 EXPECT_TRUE(big_ordinal.GreaterThan(small_ordinal)); | |
186 EXPECT_TRUE(big_ordinal.GreaterThan(middle_ordinal)); | |
187 EXPECT_FALSE(big_ordinal.GreaterThan(big_ordinal)); | |
188 } | |
189 | |
190 // Create two valid Ordinals. Equals should return true only when | |
191 // called reflexively. | |
192 TEST(Ordinal, Equals) { | |
193 const TestOrdinal ordinal1("1"); | |
194 const TestOrdinal ordinal2("2"); | |
195 | |
196 EXPECT_TRUE(ordinal1.Equals(ordinal1)); | |
197 EXPECT_FALSE(ordinal1.Equals(ordinal2)); | |
198 | |
199 EXPECT_FALSE(ordinal2.Equals(ordinal1)); | |
200 EXPECT_TRUE(ordinal2.Equals(ordinal2)); | |
201 } | |
202 | |
203 // Create some valid ordinals from some byte strings. | |
204 // ToInternalValue() should return the original byte string. | |
205 TEST(OrdinalTest, ToInternalValue) { | |
206 EXPECT_EQ("2", TestOrdinal("2").ToInternalValue()); | |
207 EXPECT_EQ("12345", LongOrdinal("12345").ToInternalValue()); | |
208 EXPECT_EQ("\1\2\3\4\5", LargeOrdinal("\1\2\3\4\5").ToInternalValue()); | |
209 } | |
210 | |
211 // Create some invalid/valid ordinals. ToDebugString() should always | |
212 // return a printable string. | |
213 TEST(OrdinalTest, ToDebugString) { | |
214 EXPECT_EQ("INVALID[]", TestOrdinal().ToDebugString()); | |
rlarocque
2012/09/06 23:19:21
IMO, this is a bit too strict. There are other wa
akalin
2012/09/06 23:44:32
Done.
| |
215 EXPECT_EQ("INVALID[invalid string]", | |
216 TestOrdinal("invalid string").ToDebugString()); | |
217 EXPECT_EQ("2", TestOrdinal("2").ToDebugString()); | |
218 EXPECT_EQ("12345", LongOrdinal("12345").ToDebugString()); | |
219 EXPECT_EQ("\\u0001\\u0002\\u0003\\u0004\\u0005", | |
220 LargeOrdinal("\1\2\3\4\5").ToDebugString()); | |
221 } | |
222 | |
223 // Create three Ordinals in order. LessThanFn should return values | |
224 // consistent with that order. | |
225 TEST(Ordinal, LessThanFn) { | |
226 const TestOrdinal small_ordinal("1"); | |
227 const TestOrdinal middle_ordinal("2"); | |
228 const TestOrdinal big_ordinal("3"); | |
229 | |
230 const TestOrdinal::LessThanFn less_than; | |
231 | |
232 EXPECT_FALSE(less_than(small_ordinal, small_ordinal)); | |
233 EXPECT_TRUE(less_than(small_ordinal, middle_ordinal)); | |
234 EXPECT_TRUE(less_than(small_ordinal, big_ordinal)); | |
235 | |
236 EXPECT_FALSE(less_than(middle_ordinal, small_ordinal)); | |
237 EXPECT_FALSE(less_than(middle_ordinal, middle_ordinal)); | |
238 EXPECT_TRUE(less_than(middle_ordinal, big_ordinal)); | |
239 | |
240 EXPECT_FALSE(less_than(big_ordinal, small_ordinal)); | |
241 EXPECT_FALSE(less_than(big_ordinal, middle_ordinal)); | |
242 EXPECT_FALSE(less_than(big_ordinal, big_ordinal)); | |
243 } | |
244 | |
245 template <typename Traits> | |
246 std::string GetBetween(const std::string& ordinal_string1, | |
247 const std::string& ordinal_string2) { | |
248 const Ordinal<Traits> ordinal1(ordinal_string1); | |
249 const Ordinal<Traits> ordinal2(ordinal_string2); | |
250 const Ordinal<Traits> between1 = ordinal1.CreateBetween(ordinal2); | |
251 const Ordinal<Traits> between2 = ordinal2.CreateBetween(ordinal1); | |
252 EXPECT_TRUE(between1.Equals(between2)); | |
253 return between1.ToInternalValue(); | |
254 } | |
255 | |
256 // Create some Ordinals from single-digit strings. Given two strings | |
257 // from this set, CreateBetween should return an Ordinal roughly between | |
258 // them that are also single-digit when possible. | |
259 TEST(Ordinal, CreateBetweenSingleDigit) { | |
260 EXPECT_EQ("2", GetBetween<TestOrdinal>("1", "3")); | |
261 EXPECT_EQ("12", GetBetween<TestOrdinal>("1", "2")); | |
262 EXPECT_EQ("22", GetBetween<TestOrdinal>("2", "3")); | |
263 } | |
264 | |
265 // Create some Ordinals from strings of various lengths. Given two | |
266 // strings from this set, CreateBetween should return an Ordinal roughly | |
267 // between them that have as few digits as possible. | |
268 TEST(Ordinal, CreateBetweenDifferentLengths) { | |
269 EXPECT_EQ("102", GetBetween<TestOrdinal>("1", "11")); | |
270 EXPECT_EQ("2", GetBetween<TestOrdinal>("1", "31")); | |
271 EXPECT_EQ("132", GetBetween<TestOrdinal>("13", "2")); | |
272 EXPECT_EQ("2", GetBetween<TestOrdinal>("10001", "3")); | |
273 EXPECT_EQ("20000", GetBetween<LongOrdinal>("10001", "30000")); | |
274 EXPECT_EQ("2", GetBetween<TestOrdinal>("10002", "3")); | |
275 EXPECT_EQ("20001", GetBetween<LongOrdinal>("10002", "30000")); | |
276 EXPECT_EQ("2", GetBetween<TestOrdinal>("1", "30002")); | |
277 EXPECT_EQ("20001", GetBetween<LongOrdinal>("10000", "30002")); | |
278 } | |
279 | |
280 // Create some Ordinals specifically designed to trigger overflow | |
281 // cases. Given two strings from this set, CreateBetween should | |
282 // return an Ordinal roughly between them that have as few digits as | |
283 // possible. | |
284 TEST(Ordinal, CreateBetweenOverflow) { | |
285 EXPECT_EQ("03", GetBetween<TestOrdinal>("01", "11")); | |
286 EXPECT_EQ("13", GetBetween<TestOrdinal>("11", "21")); | |
287 EXPECT_EQ("113", GetBetween<TestOrdinal>("111", "121")); | |
288 EXPECT_EQ("2", GetBetween<TestOrdinal>("001", "333")); | |
289 EXPECT_EQ("31", GetBetween<TestOrdinal>("222", "333")); | |
290 EXPECT_EQ("3", GetBetween<TestOrdinal>("201", "333")); | |
291 EXPECT_EQ("2", GetBetween<TestOrdinal>("003", "333")); | |
292 EXPECT_EQ("2", GetBetween<TestOrdinal>("2223", "1113")); | |
293 } | |
294 | |
295 // Create some Ordinals specifically designed to trigger digit | |
296 // overflow cases. Given two strings from this set, CreateBetween | |
297 // should return an Ordinal roughly between them that have as few digits | |
298 // as possible. | |
299 TEST(Ordinal, CreateBetweenOverflowLarge) { | |
300 EXPECT_EQ("\x80", GetBetween<LargeOrdinal>("\x01\xff", "\xff\xff")); | |
301 EXPECT_EQ("\xff\xfe\x80", GetBetween<LargeOrdinal>("\xff\xfe", "\xff\xff")); | |
302 } | |
303 | |
304 // Create some Ordinals. CreateBefore should return an Ordinal | |
305 // roughly halfway towards 0. | |
306 TEST(Ordinal, CreateBefore) { | |
307 EXPECT_EQ("02", TestOrdinal("1").CreateBefore().ToInternalValue()); | |
308 EXPECT_EQ("03", TestOrdinal("11").CreateBefore().ToInternalValue()); | |
309 EXPECT_EQ("03", TestOrdinal("12").CreateBefore().ToInternalValue()); | |
310 EXPECT_EQ("1", TestOrdinal("13").CreateBefore().ToInternalValue()); | |
311 } | |
312 | |
313 // Create some Ordinals. CreateAfter should return an Ordinal | |
314 // roughly halfway towards 0. | |
315 TEST(Ordinal, CreateAfter) { | |
316 EXPECT_EQ("31", TestOrdinal("3").CreateAfter().ToInternalValue()); | |
317 EXPECT_EQ("322", TestOrdinal("32").CreateAfter().ToInternalValue()); | |
318 EXPECT_EQ("33322", TestOrdinal("3332").CreateAfter().ToInternalValue()); | |
319 EXPECT_EQ("3", TestOrdinal("22").CreateAfter().ToInternalValue()); | |
320 EXPECT_EQ("3", TestOrdinal("23").CreateAfter().ToInternalValue()); | |
321 } | |
322 | |
323 // Create two valid Ordinals. EqualsFn should return true only when | |
324 // called reflexively. | |
325 TEST(Ordinal, EqualsFn) { | |
326 const TestOrdinal ordinal1("1"); | |
327 const TestOrdinal ordinal2("2"); | |
328 | |
329 const TestOrdinal::EqualsFn equals; | |
330 | |
331 EXPECT_TRUE(equals(ordinal1, ordinal1)); | |
332 EXPECT_FALSE(equals(ordinal1, ordinal2)); | |
333 | |
334 EXPECT_FALSE(equals(ordinal2, ordinal1)); | |
335 EXPECT_TRUE(equals(ordinal2,ordinal2)); | |
336 } | |
337 | |
338 // Create some Ordinals and shuffle them. Sorting them using | |
339 // LessThanFn should produce the correct order. | |
340 TEST(Ordinal, Sort) { | |
341 const LongOrdinal ordinal1("12345"); | |
342 const LongOrdinal ordinal2("54321"); | |
343 const LongOrdinal ordinal3("87654"); | |
344 const LongOrdinal ordinal4("98765"); | |
345 | |
346 std::vector<LongOrdinal> sorted_ordinals; | |
347 sorted_ordinals.push_back(ordinal1); | |
348 sorted_ordinals.push_back(ordinal2); | |
349 sorted_ordinals.push_back(ordinal3); | |
350 sorted_ordinals.push_back(ordinal4); | |
351 | |
352 std::vector<LongOrdinal> ordinals = sorted_ordinals; | |
353 std::random_shuffle(ordinals.begin(), ordinals.end()); | |
354 std::sort(ordinals.begin(), ordinals.end(), LongOrdinal::LessThanFn()); | |
355 EXPECT_TRUE(std::equal(ordinals.begin(), ordinals.end(), | |
356 sorted_ordinals.begin(), LongOrdinal::EqualsFn())); | |
357 } | |
358 | |
359 } // namespace | |
360 | |
361 } // namespace syncer | |
OLD | NEW |