Don't show supervised user as "already on this device" while they're being imported.
[chromium-blink-merge.git] / chrome / browser / profile_resetter / jtl_interpreter_unittest.cc
blob8457264f33af2c33c00bab0e505e8902bbc42e66
1 // Copyright 2011 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.
5 #include "chrome/browser/profile_resetter/jtl_interpreter.h"
7 #include <numeric>
9 #include "base/strings/string_util.h"
10 #include "base/test/values_test_util.h"
11 #include "chrome/browser/profile_resetter/jtl_foundation.h"
12 #include "chrome/browser/profile_resetter/jtl_instructions.h"
13 #include "crypto/hmac.h"
14 #include "testing/gtest/include/gtest/gtest.h"
16 namespace {
18 const char seed[] = "foobar";
20 #define KEY_HASH_1 GetHash("KEY_HASH_1")
21 #define KEY_HASH_2 GetHash("KEY_HASH_2")
22 #define KEY_HASH_3 GetHash("KEY_HASH_3")
23 #define KEY_HASH_4 GetHash("KEY_HASH_4")
25 #define VALUE_HASH_1 GetHash("VALUE_HASH_1")
26 #define VALUE_HASH_2 GetHash("VALUE_HASH_2")
28 #define VAR_HASH_1 "01234567890123456789012345678901"
29 #define VAR_HASH_2 "12345678901234567890123456789012"
31 std::string GetHash(const std::string& input) {
32 return jtl_foundation::Hasher(seed).GetHash(input);
35 std::string EncodeUint32(uint32 value) {
36 std::string bytecode;
37 for (int i = 0; i < 4; ++i) {
38 bytecode.push_back(static_cast<char>(value & 0xFFu));
39 value >>= 8;
41 return bytecode;
44 // escaped_json_param may contain ' characters that are replaced with ". This
45 // makes the code more readable because we need less escaping.
46 #define INIT_INTERPRETER(program_param, escaped_json_param) \
47 const char* escaped_json = escaped_json_param; \
48 std::string json; \
49 base::ReplaceChars(escaped_json, "'", "\"", &json); \
50 scoped_ptr<base::Value> json_value(ParseJson(json)); \
51 JtlInterpreter interpreter( \
52 seed, \
53 program_param, \
54 static_cast<const base::DictionaryValue*>(json_value.get())); \
55 interpreter.Execute()
57 using base::test::ParseJson;
59 TEST(JtlInterpreter, Store) {
60 INIT_INTERPRETER(
61 OP_STORE_BOOL(VAR_HASH_1, VALUE_TRUE),
62 "{ 'KEY_HASH_1': 'VALUE_HASH_1' }");
63 EXPECT_EQ(JtlInterpreter::OK, interpreter.result());
64 base::ExpectDictBooleanValue(true, *interpreter.working_memory(), VAR_HASH_1);
67 TEST(JtlInterpreter, NavigateAndStore) {
68 INIT_INTERPRETER(
69 OP_NAVIGATE(KEY_HASH_1) +
70 OP_STORE_BOOL(VAR_HASH_1, VALUE_TRUE),
71 "{ 'KEY_HASH_1': 'VALUE_HASH_1' }");
72 EXPECT_EQ(JtlInterpreter::OK, interpreter.result());
73 base::ExpectDictBooleanValue(true, *interpreter.working_memory(), VAR_HASH_1);
76 TEST(JtlInterpreter, FailNavigate) {
77 INIT_INTERPRETER(
78 OP_NAVIGATE(KEY_HASH_2) +
79 OP_STORE_BOOL(VAR_HASH_1, VALUE_TRUE),
80 "{ 'KEY_HASH_1': 'VALUE_HASH_1' }");
81 EXPECT_EQ(JtlInterpreter::OK, interpreter.result());
82 EXPECT_FALSE(interpreter.working_memory()->HasKey(VAR_HASH_1));
85 TEST(JtlInterpreter, ConsecutiveNavigate) {
86 INIT_INTERPRETER(
87 OP_NAVIGATE(KEY_HASH_1) +
88 OP_NAVIGATE(KEY_HASH_2) +
89 OP_STORE_BOOL(VAR_HASH_1, VALUE_TRUE),
90 "{ 'KEY_HASH_1': { 'KEY_HASH_2': 'VALUE_HASH_1' } }");
91 EXPECT_EQ(JtlInterpreter::OK, interpreter.result());
92 base::ExpectDictBooleanValue(true, *interpreter.working_memory(), VAR_HASH_1);
95 TEST(JtlInterpreter, FailConsecutiveNavigate) {
96 INIT_INTERPRETER(
97 OP_NAVIGATE(KEY_HASH_1) +
98 OP_NAVIGATE(KEY_HASH_2) +
99 OP_STORE_BOOL(VAR_HASH_1, VALUE_TRUE),
100 "{ 'KEY_HASH_1': 'foo' }");
101 EXPECT_EQ(JtlInterpreter::OK, interpreter.result());
102 EXPECT_FALSE(interpreter.working_memory()->HasKey(VAR_HASH_1));
105 TEST(JtlInterpreter, NavigateAnyInDictionary) {
106 INIT_INTERPRETER(
107 OP_NAVIGATE(KEY_HASH_1) +
108 OP_NAVIGATE_ANY +
109 OP_NAVIGATE(KEY_HASH_4) +
110 OP_STORE_BOOL(VAR_HASH_1, VALUE_TRUE),
111 "{ 'KEY_HASH_1':"
112 " { 'KEY_HASH_2': {'KEY_HASH_3': 'VALUE_HASH_1' },"
113 " 'KEY_HASH_3': {'KEY_HASH_4': 'VALUE_HASH_1' }"
114 " } }");
115 EXPECT_EQ(JtlInterpreter::OK, interpreter.result());
116 base::ExpectDictBooleanValue(true, *interpreter.working_memory(), VAR_HASH_1);
119 TEST(JtlInterpreter, NavigateAnyInList) {
120 INIT_INTERPRETER(
121 OP_NAVIGATE(KEY_HASH_1) +
122 OP_NAVIGATE_ANY +
123 OP_NAVIGATE(KEY_HASH_4) +
124 OP_STORE_BOOL(VAR_HASH_1, VALUE_TRUE),
125 "{ 'KEY_HASH_1':"
126 " [ {'KEY_HASH_3': 'VALUE_HASH_1' },"
127 " {'KEY_HASH_4': 'VALUE_HASH_1' }"
128 " ] }");
129 EXPECT_EQ(JtlInterpreter::OK, interpreter.result());
130 base::ExpectDictBooleanValue(true, *interpreter.working_memory(), VAR_HASH_1);
133 TEST(JtlInterpreter, NavigateBack) {
134 INIT_INTERPRETER(
135 OP_NAVIGATE(KEY_HASH_1) +
136 OP_NAVIGATE(KEY_HASH_2) +
137 OP_NAVIGATE_BACK +
138 OP_NAVIGATE(KEY_HASH_3) +
139 OP_NAVIGATE(KEY_HASH_4) +
140 OP_STORE_BOOL(VAR_HASH_1, VALUE_TRUE),
141 "{ 'KEY_HASH_1':"
142 " { 'KEY_HASH_2': {'KEY_HASH_3': 'VALUE_HASH_1' },"
143 " 'KEY_HASH_3': {'KEY_HASH_4': 'VALUE_HASH_1' }"
144 " } }");
145 EXPECT_EQ(JtlInterpreter::OK, interpreter.result());
146 base::ExpectDictBooleanValue(true, *interpreter.working_memory(), VAR_HASH_1);
149 TEST(JtlInterpreter, StoreTwoValues) {
150 INIT_INTERPRETER(
151 OP_NAVIGATE(KEY_HASH_1) +
152 OP_NAVIGATE(KEY_HASH_2) +
153 OP_STORE_BOOL(VAR_HASH_1, VALUE_TRUE) +
154 OP_STORE_HASH(VAR_HASH_2, VALUE_HASH_1),
155 "{ 'KEY_HASH_1': { 'KEY_HASH_2': 'VALUE_HASH_1' } }");
156 EXPECT_EQ(JtlInterpreter::OK, interpreter.result());
157 base::ExpectDictBooleanValue(true, *interpreter.working_memory(), VAR_HASH_1);
158 base::ExpectDictStringValue(VALUE_HASH_1, *interpreter.working_memory(),
159 VAR_HASH_2);
162 TEST(JtlInterpreter, CompareStoredMatch) {
163 INIT_INTERPRETER(
164 OP_NAVIGATE(KEY_HASH_1) +
165 OP_STORE_BOOL(VAR_HASH_1, VALUE_TRUE) +
166 OP_NAVIGATE(KEY_HASH_2) +
167 OP_COMPARE_STORED_BOOL(VAR_HASH_1, VALUE_TRUE, VALUE_FALSE) +
168 OP_STORE_BOOL(VAR_HASH_2, VALUE_TRUE),
169 "{ 'KEY_HASH_1': { 'KEY_HASH_2': 'VALUE_HASH_1' } }");
170 EXPECT_EQ(JtlInterpreter::OK, interpreter.result());
171 base::ExpectDictBooleanValue(true, *interpreter.working_memory(), VAR_HASH_1);
172 base::ExpectDictBooleanValue(true, *interpreter.working_memory(), VAR_HASH_2);
175 TEST(JtlInterpreter, CompareStoredMismatch) {
176 INIT_INTERPRETER(
177 OP_NAVIGATE(KEY_HASH_1) +
178 OP_STORE_BOOL(VAR_HASH_1, VALUE_TRUE) +
179 OP_NAVIGATE(KEY_HASH_2) +
180 OP_COMPARE_STORED_BOOL(VAR_HASH_1, VALUE_FALSE, VALUE_TRUE) +
181 OP_STORE_BOOL(VAR_HASH_2, VALUE_TRUE),
182 "{ 'KEY_HASH_1': { 'KEY_HASH_2': 'VALUE_HASH_1' } }");
183 EXPECT_EQ(JtlInterpreter::OK, interpreter.result());
184 base::ExpectDictBooleanValue(true, *interpreter.working_memory(), VAR_HASH_1);
185 EXPECT_FALSE(interpreter.working_memory()->HasKey(VAR_HASH_2));
188 TEST(JtlInterpreter, CompareStoredNoValueMatchingDefault) {
189 INIT_INTERPRETER(
190 OP_NAVIGATE(KEY_HASH_1) +
191 OP_NAVIGATE(KEY_HASH_2) +
192 OP_COMPARE_STORED_BOOL(VAR_HASH_1, VALUE_TRUE, VALUE_TRUE) +
193 OP_STORE_BOOL(VAR_HASH_2, VALUE_TRUE),
194 "{ 'KEY_HASH_1': { 'KEY_HASH_2': 'VALUE_HASH_1' } }");
195 EXPECT_EQ(JtlInterpreter::OK, interpreter.result());
196 base::ExpectDictBooleanValue(true, *interpreter.working_memory(), VAR_HASH_2);
199 TEST(JtlInterpreter, CompareStoredNoValueMismatchingDefault) {
200 INIT_INTERPRETER(
201 OP_NAVIGATE(KEY_HASH_1) +
202 OP_NAVIGATE(KEY_HASH_2) +
203 OP_COMPARE_STORED_BOOL(VAR_HASH_1, VALUE_TRUE, VALUE_FALSE) +
204 OP_STORE_BOOL(VAR_HASH_2, VALUE_TRUE),
205 "{ 'KEY_HASH_1': { 'KEY_HASH_2': 'VALUE_HASH_1' } }");
206 EXPECT_EQ(JtlInterpreter::OK, interpreter.result());
207 EXPECT_FALSE(interpreter.working_memory()->HasKey(VAR_HASH_2));
210 TEST(JtlInterpreter, CompareBool) {
211 struct TestCase {
212 std::string expected_value;
213 const char* json;
214 bool expected_success;
215 } cases[] = {
216 { VALUE_TRUE, "{ 'KEY_HASH_1': true }", true },
217 { VALUE_FALSE, "{ 'KEY_HASH_1': false }", true },
218 { VALUE_TRUE, "{ 'KEY_HASH_1': false }", false },
219 { VALUE_TRUE, "{ 'KEY_HASH_1': 'abc' }", false },
220 { VALUE_TRUE, "{ 'KEY_HASH_1': 1 }", false },
221 { VALUE_TRUE, "{ 'KEY_HASH_1': 1.2 }", false },
222 { VALUE_TRUE, "{ 'KEY_HASH_1': [1] }", false },
223 { VALUE_TRUE, "{ 'KEY_HASH_1': {'a': 'b'} }", false },
226 for (size_t i = 0; i < arraysize(cases); ++i) {
227 SCOPED_TRACE(testing::Message() << "Iteration " << i);
228 INIT_INTERPRETER(
229 OP_NAVIGATE(KEY_HASH_1) +
230 OP_COMPARE_NODE_BOOL(cases[i].expected_value) +
231 OP_STORE_BOOL(VAR_HASH_1, VALUE_TRUE),
232 cases[i].json);
233 EXPECT_EQ(JtlInterpreter::OK, interpreter.result());
234 if (cases[i].expected_success) {
235 base::ExpectDictBooleanValue(
236 true, *interpreter.working_memory(), VAR_HASH_1);
237 } else {
238 EXPECT_FALSE(interpreter.working_memory()->HasKey(VAR_HASH_1));
243 TEST(JtlInterpreter, CompareHashString) {
244 struct TestCase {
245 std::string expected_value;
246 const char* json;
247 bool expected_success;
248 } cases[] = {
249 { VALUE_HASH_1, "{ 'KEY_HASH_1': 'VALUE_HASH_1' }", true },
250 { VALUE_HASH_1, "{ 'KEY_HASH_1': 'VALUE_HASH_2' }", false },
251 { VALUE_HASH_1, "{ 'KEY_HASH_1': true }", false },
252 { VALUE_HASH_1, "{ 'KEY_HASH_1': 1 }", false },
253 { VALUE_HASH_1, "{ 'KEY_HASH_1': 1.1 }", false },
254 { VALUE_HASH_1, "{ 'KEY_HASH_1': [1] }", false },
255 { VALUE_HASH_1, "{ 'KEY_HASH_1': {'a': 'b'} }", false },
257 { GetHash("1.2"), "{ 'KEY_HASH_1': 1.2 }", true },
258 { GetHash("1.2"), "{ 'KEY_HASH_1': 'VALUE_HASH_1' }", false },
259 { GetHash("1.2"), "{ 'KEY_HASH_1': true }", false },
260 { GetHash("1.2"), "{ 'KEY_HASH_1': 1 }", false },
261 { GetHash("1.2"), "{ 'KEY_HASH_1': 1.3 }", false },
262 { GetHash("1.2"), "{ 'KEY_HASH_1': [1] }", false },
263 { GetHash("1.2"), "{ 'KEY_HASH_1': {'a': 'b'} }", false },
265 { GetHash("1"), "{ 'KEY_HASH_1': 1 }", true },
266 { GetHash("1"), "{ 'KEY_HASH_1': 'VALUE_HASH_1' }", false },
267 { GetHash("1"), "{ 'KEY_HASH_1': true }", false },
268 { GetHash("1"), "{ 'KEY_HASH_1': 2 }", false },
269 { GetHash("1"), "{ 'KEY_HASH_1': 1.1 }", false },
270 { GetHash("1"), "{ 'KEY_HASH_1': [1] }", false },
271 { GetHash("1"), "{ 'KEY_HASH_1': {'a': 'b'} }", false },
274 for (size_t i = 0; i < arraysize(cases); ++i) {
275 SCOPED_TRACE(testing::Message() << "Iteration " << i);
276 INIT_INTERPRETER(
277 OP_NAVIGATE(KEY_HASH_1) +
278 OP_COMPARE_NODE_HASH(cases[i].expected_value) +
279 OP_STORE_BOOL(VAR_HASH_1, VALUE_TRUE),
280 cases[i].json);
281 EXPECT_EQ(JtlInterpreter::OK, interpreter.result());
282 if (cases[i].expected_success) {
283 base::ExpectDictBooleanValue(
284 true, *interpreter.working_memory(), VAR_HASH_1);
285 } else {
286 EXPECT_FALSE(interpreter.working_memory()->HasKey(VAR_HASH_1));
290 for (size_t i = 0; i < arraysize(cases); ++i) {
291 SCOPED_TRACE(testing::Message() << "Negated, Iteration " << i);
292 INIT_INTERPRETER(
293 OP_NAVIGATE(KEY_HASH_1) +
294 OP_COMPARE_NODE_HASH_NOT(cases[i].expected_value) +
295 OP_STORE_BOOL(VAR_HASH_1, VALUE_TRUE),
296 cases[i].json);
297 EXPECT_EQ(JtlInterpreter::OK, interpreter.result());
298 if (!cases[i].expected_success) {
299 base::ExpectDictBooleanValue(
300 true, *interpreter.working_memory(), VAR_HASH_1);
301 } else {
302 EXPECT_FALSE(interpreter.working_memory()->HasKey(VAR_HASH_1));
307 TEST(JtlInterpreter, StoreNodeBool) {
308 struct TestCase {
309 bool expected_value;
310 const char* json;
311 bool expected_success;
312 } cases[] = {
313 { true, "{ 'KEY_HASH_1': true }", true },
314 { false, "{ 'KEY_HASH_1': false }", true },
315 { false, "{ 'KEY_HASH_1': 'abc' }", false },
316 { false, "{ 'KEY_HASH_1': 1 }", false },
317 { false, "{ 'KEY_HASH_1': 1.2 }", false },
318 { false, "{ 'KEY_HASH_1': [1] }", false },
319 { false, "{ 'KEY_HASH_1': {'a': 'b'} }", false },
322 for (size_t i = 0; i < arraysize(cases); ++i) {
323 SCOPED_TRACE(testing::Message() << "Iteration " << i);
324 INIT_INTERPRETER(
325 OP_NAVIGATE(KEY_HASH_1) +
326 OP_STORE_NODE_BOOL(VAR_HASH_1) +
327 OP_STORE_BOOL(VAR_HASH_2, VALUE_TRUE),
328 cases[i].json);
329 EXPECT_EQ(JtlInterpreter::OK, interpreter.result());
330 if (cases[i].expected_success) {
331 base::ExpectDictBooleanValue(
332 cases[i].expected_value, *interpreter.working_memory(), VAR_HASH_1);
333 base::ExpectDictBooleanValue(
334 true, *interpreter.working_memory(), VAR_HASH_2);
335 } else {
336 EXPECT_FALSE(interpreter.working_memory()->HasKey(VAR_HASH_1));
337 EXPECT_FALSE(interpreter.working_memory()->HasKey(VAR_HASH_2));
342 TEST(JtlInterpreter, CompareNodeToStoredBool) {
343 struct TestCase {
344 std::string stored_value;
345 const char* json;
346 bool expected_success;
347 } cases[] = {
348 { VALUE_TRUE, "{ 'KEY_HASH_1': true }", true },
349 { VALUE_FALSE, "{ 'KEY_HASH_1': false }", true },
350 { VALUE_FALSE, "{ 'KEY_HASH_1': true }", false },
351 { std::string(), "{ 'KEY_HASH_1': true }", false },
353 { VALUE_HASH_1, "{ 'KEY_HASH_1': 'VALUE_HASH_1' }", false },
354 { GetHash("1"), "{ 'KEY_HASH_1': 1 }", false },
355 { GetHash("1.2"), "{ 'KEY_HASH_1': 1.2 }", false },
357 { VALUE_HASH_1, "{ 'KEY_HASH_1': true }", false },
358 { GetHash("1"), "{ 'KEY_HASH_1': true }", false },
359 { GetHash("1.2"), "{ 'KEY_HASH_1': true }", false },
361 { VALUE_TRUE, "{ 'KEY_HASH_1': 'VALUE_HASH_1' }", false },
362 { VALUE_TRUE, "{ 'KEY_HASH_1': 1 }", false },
363 { VALUE_TRUE, "{ 'KEY_HASH_1': 1.2 }", false },
364 { VALUE_TRUE, "{ 'KEY_HASH_1': [1] }", false },
365 { VALUE_TRUE, "{ 'KEY_HASH_1': {'a': 'b'} }", false },
368 for (size_t i = 0; i < arraysize(cases); ++i) {
369 SCOPED_TRACE(testing::Message() << "Iteration " << i);
370 std::string store_op;
371 if (cases[i].stored_value == VALUE_TRUE ||
372 cases[i].stored_value == VALUE_FALSE)
373 store_op = OP_STORE_BOOL(VAR_HASH_1, cases[i].stored_value);
374 else if (!cases[i].stored_value.empty())
375 store_op = OP_STORE_HASH(VAR_HASH_1, cases[i].stored_value);
376 INIT_INTERPRETER(
377 store_op +
378 OP_NAVIGATE(KEY_HASH_1) +
379 OP_COMPARE_NODE_TO_STORED_BOOL(VAR_HASH_1) +
380 OP_STORE_BOOL(VAR_HASH_2, VALUE_TRUE),
381 cases[i].json);
382 EXPECT_EQ(JtlInterpreter::OK, interpreter.result());
383 if (cases[i].expected_success) {
384 base::ExpectDictBooleanValue(
385 true, *interpreter.working_memory(), VAR_HASH_2);
386 } else {
387 EXPECT_FALSE(interpreter.working_memory()->HasKey(VAR_HASH_2));
392 TEST(JtlInterpreter, StoreNodeHash) {
393 struct TestCase {
394 std::string expected_value;
395 const char* json;
396 bool expected_success;
397 } cases[] = {
398 { VALUE_HASH_1, "{ 'KEY_HASH_1': 'VALUE_HASH_1' }", true },
399 { VALUE_HASH_2, "{ 'KEY_HASH_1': 'VALUE_HASH_2' }", true },
400 { GetHash("1"), "{ 'KEY_HASH_1': 1 }", true },
401 { GetHash("1.2"), "{ 'KEY_HASH_1': 1.2 }", true },
402 { std::string(), "{ 'KEY_HASH_1': true }", false },
403 { std::string(), "{ 'KEY_HASH_1': [1] }", false },
404 { std::string(), "{ 'KEY_HASH_1': {'a': 'b'} }", false },
407 for (size_t i = 0; i < arraysize(cases); ++i) {
408 SCOPED_TRACE(testing::Message() << "Iteration " << i);
409 INIT_INTERPRETER(
410 OP_NAVIGATE(KEY_HASH_1) +
411 OP_STORE_NODE_HASH(VAR_HASH_1) +
412 OP_STORE_BOOL(VAR_HASH_2, VALUE_TRUE),
413 cases[i].json);
414 EXPECT_EQ(JtlInterpreter::OK, interpreter.result());
415 if (cases[i].expected_success) {
416 base::ExpectDictStringValue(
417 cases[i].expected_value, *interpreter.working_memory(), VAR_HASH_1);
418 base::ExpectDictBooleanValue(
419 true, *interpreter.working_memory(), VAR_HASH_2);
420 } else {
421 EXPECT_FALSE(interpreter.working_memory()->HasKey(VAR_HASH_1));
422 EXPECT_FALSE(interpreter.working_memory()->HasKey(VAR_HASH_2));
427 TEST(JtlInterpreter, CompareNodeToStoredHash) {
428 struct TestCase {
429 std::string stored_value;
430 const char* json;
431 bool expected_success;
432 } cases[] = {
433 { VALUE_HASH_1, "{ 'KEY_HASH_1': 'VALUE_HASH_1' }", true },
434 { VALUE_HASH_2, "{ 'KEY_HASH_1': 'VALUE_HASH_2' }", true },
435 { std::string(), "{ 'KEY_HASH_1': 'VALUE_HASH_2' }", false },
436 { VALUE_HASH_1, "{ 'KEY_HASH_1': 'VALUE_HASH_2' }", false },
437 { VALUE_HASH_1, "{ 'KEY_HASH_1': true }", false },
438 { VALUE_HASH_1, "{ 'KEY_HASH_1': 1 }", false },
439 { VALUE_HASH_1, "{ 'KEY_HASH_1': 1.1 }", false },
440 { VALUE_HASH_1, "{ 'KEY_HASH_1': [1] }", false },
441 { VALUE_HASH_1, "{ 'KEY_HASH_1': {'a': 'b'} }", false },
443 { GetHash("1.2"), "{ 'KEY_HASH_1': 1.2 }", true },
444 { GetHash("1.3"), "{ 'KEY_HASH_1': 1.3 }", true },
445 { std::string(), "{ 'KEY_HASH_1': 1.2 }", false },
446 { GetHash("1.2"), "{ 'KEY_HASH_1': 'VALUE_HASH_1' }", false },
447 { GetHash("1.2"), "{ 'KEY_HASH_1': true }", false },
448 { GetHash("1.2"), "{ 'KEY_HASH_1': 1 }", false },
449 { GetHash("1.2"), "{ 'KEY_HASH_1': 1.3 }", false },
450 { GetHash("1.2"), "{ 'KEY_HASH_1': [1] }", false },
451 { GetHash("1.2"), "{ 'KEY_HASH_1': {'a': 'b'} }", false },
453 { GetHash("1"), "{ 'KEY_HASH_1': 1 }", true },
454 { GetHash("2"), "{ 'KEY_HASH_1': 2 }", true },
455 { std::string(), "{ 'KEY_HASH_1': 2 }", false },
456 { GetHash("1"), "{ 'KEY_HASH_1': 'VALUE_HASH_1' }", false },
457 { GetHash("1"), "{ 'KEY_HASH_1': true }", false },
458 { GetHash("1"), "{ 'KEY_HASH_1': 2 }", false },
459 { GetHash("1"), "{ 'KEY_HASH_1': 1.1 }", false },
460 { GetHash("1"), "{ 'KEY_HASH_1': [1] }", false },
461 { GetHash("1"), "{ 'KEY_HASH_1': {'a': 'b'} }", false },
463 { VALUE_TRUE, "{ 'KEY_HASH_1': 'VALUE_HASH_1' }", false },
464 { VALUE_TRUE, "{ 'KEY_HASH_1': 1 }", false },
465 { VALUE_TRUE, "{ 'KEY_HASH_1': 1.3 }", false },
466 { VALUE_TRUE, "{ 'KEY_HASH_1': [1] }", false },
467 { VALUE_TRUE, "{ 'KEY_HASH_1': {'a': 'b'} }", false },
469 { VALUE_TRUE, "{ 'KEY_HASH_1': true }", false },
470 { VALUE_FALSE, "{ 'KEY_HASH_1': false }", false },
473 for (size_t i = 0; i < arraysize(cases); ++i) {
474 SCOPED_TRACE(testing::Message() << "Iteration " << i);
475 std::string store_op;
476 if (cases[i].stored_value == VALUE_TRUE ||
477 cases[i].stored_value == VALUE_FALSE)
478 store_op = OP_STORE_BOOL(VAR_HASH_1, cases[i].stored_value);
479 else if (!cases[i].stored_value.empty())
480 store_op = OP_STORE_HASH(VAR_HASH_1, cases[i].stored_value);
481 INIT_INTERPRETER(
482 store_op +
483 OP_NAVIGATE(KEY_HASH_1) +
484 OP_COMPARE_NODE_TO_STORED_HASH(VAR_HASH_1) +
485 OP_STORE_BOOL(VAR_HASH_2, VALUE_TRUE),
486 cases[i].json);
487 EXPECT_EQ(JtlInterpreter::OK, interpreter.result());
488 if (cases[i].expected_success) {
489 base::ExpectDictBooleanValue(
490 true, *interpreter.working_memory(), VAR_HASH_2);
491 } else {
492 EXPECT_FALSE(interpreter.working_memory()->HasKey(VAR_HASH_2));
497 TEST(JtlInterpreter, CompareSubstring) {
498 struct TestCase {
499 std::string pattern;
500 const char* json;
501 bool expected_success;
502 } cases[] = {
503 { "abc", "{ 'KEY_HASH_1': 'abcdefghijklmnopqrstuvwxyz' }", true },
504 { "xyz", "{ 'KEY_HASH_1': 'abcdefghijklmnopqrstuvwxyz' }", true },
505 { "m", "{ 'KEY_HASH_1': 'abcdefghijklmnopqrstuvwxyz' }", true },
506 { "abc", "{ 'KEY_HASH_1': 'abc' }", true },
507 { "cba", "{ 'KEY_HASH_1': 'abcdefghijklmnopqrstuvwxyz' }", false },
508 { "acd", "{ 'KEY_HASH_1': 'abcdefghijklmnopqrstuvwxyz' }", false },
509 { "waaaaaaay_too_long", "{ 'KEY_HASH_1': 'abc' }", false },
511 { VALUE_HASH_1, "{ 'KEY_HASH_1': true }", false },
512 { VALUE_HASH_1, "{ 'KEY_HASH_1': 1 }", false },
513 { VALUE_HASH_1, "{ 'KEY_HASH_1': 1.1 }", false },
514 { VALUE_HASH_1, "{ 'KEY_HASH_1': [1] }", false },
515 { VALUE_HASH_1, "{ 'KEY_HASH_1': {'a': 'b'} }", false },
518 for (size_t i = 0; i < arraysize(cases); ++i) {
519 SCOPED_TRACE(testing::Message() << "Iteration " << i);
520 std::string pattern = cases[i].pattern;
521 uint32 pattern_sum = std::accumulate(
522 pattern.begin(), pattern.end(), static_cast<uint32>(0u));
523 INIT_INTERPRETER(
524 OP_NAVIGATE(KEY_HASH_1) +
525 OP_COMPARE_NODE_SUBSTRING(GetHash(pattern),
526 EncodeUint32(pattern.size()),
527 EncodeUint32(pattern_sum)) +
528 OP_STORE_BOOL(VAR_HASH_1, VALUE_TRUE),
529 cases[i].json);
530 EXPECT_EQ(JtlInterpreter::OK, interpreter.result());
531 if (cases[i].expected_success) {
532 base::ExpectDictBooleanValue(
533 true, *interpreter.working_memory(), VAR_HASH_1);
534 } else {
535 EXPECT_FALSE(interpreter.working_memory()->HasKey(VAR_HASH_1));
540 TEST(JtlInterpreter, StoreNodeRegisterableDomainHash) {
541 struct TestCase {
542 std::string expected_value;
543 const char* json;
544 bool expected_success;
545 } cases[] = {
546 { GetHash("google"), "{ 'KEY_HASH_1': 'http://google.com/path' }", true },
547 { GetHash("google"), "{ 'KEY_HASH_1': 'http://mail.google.com/' }", true },
548 { GetHash("google"), "{ 'KEY_HASH_1': 'http://google.co.uk/' }", true },
549 { GetHash("google"), "{ 'KEY_HASH_1': 'http://google.com./' }", true },
550 { GetHash("google"), "{ 'KEY_HASH_1': 'http://..google.com/' }", true },
552 { GetHash("foo"), "{ 'KEY_HASH_1': 'http://foo.bar/path' }", true },
553 { GetHash("foo"), "{ 'KEY_HASH_1': 'http://sub.foo.bar' }", true },
554 { GetHash("foo"), "{ 'KEY_HASH_1': 'http://foo.appspot.com/' }", true },
555 { GetHash("foo"), "{ 'KEY_HASH_1': 'http://sub.foo.appspot.com' }", true },
557 { std::string(), "{ 'KEY_HASH_1': 'http://google.com../' }", false },
559 { std::string(), "{ 'KEY_HASH_1': 'http://bar/path' }", false },
560 { std::string(), "{ 'KEY_HASH_1': 'http://co.uk/path' }", false },
561 { std::string(), "{ 'KEY_HASH_1': 'http://appspot.com/path' }", false },
562 { std::string(), "{ 'KEY_HASH_1': 'http://127.0.0.1/path' }", false },
563 { std::string(), "{ 'KEY_HASH_1': 'file:///C:/bar.html' }", false },
565 { std::string(), "{ 'KEY_HASH_1': 1 }", false },
566 { std::string(), "{ 'KEY_HASH_1': 1.2 }", false },
567 { std::string(), "{ 'KEY_HASH_1': true }", false },
568 { std::string(), "{ 'KEY_HASH_1': [1] }", false },
569 { std::string(), "{ 'KEY_HASH_1': {'a': 'b'} }", false },
572 for (size_t i = 0; i < arraysize(cases); ++i) {
573 SCOPED_TRACE(testing::Message() << "Iteration " << i);
574 INIT_INTERPRETER(
575 OP_NAVIGATE(KEY_HASH_1) +
576 OP_STORE_NODE_REGISTERABLE_DOMAIN_HASH(VAR_HASH_1) +
577 OP_STORE_BOOL(VAR_HASH_2, VALUE_TRUE),
578 cases[i].json);
579 EXPECT_EQ(JtlInterpreter::OK, interpreter.result());
580 if (cases[i].expected_success) {
581 base::ExpectDictStringValue(
582 cases[i].expected_value, *interpreter.working_memory(), VAR_HASH_1);
583 base::ExpectDictBooleanValue(
584 true, *interpreter.working_memory(), VAR_HASH_2);
585 } else {
586 EXPECT_FALSE(interpreter.working_memory()->HasKey(VAR_HASH_1));
587 EXPECT_FALSE(interpreter.working_memory()->HasKey(VAR_HASH_2));
592 TEST(JtlInterpreter, Stop) {
593 INIT_INTERPRETER(
594 OP_NAVIGATE(KEY_HASH_1) +
595 OP_NAVIGATE(KEY_HASH_2) +
596 OP_STORE_BOOL(VAR_HASH_1, VALUE_TRUE) +
597 OP_STOP_EXECUTING_SENTENCE +
598 OP_STORE_BOOL(VAR_HASH_2, VALUE_TRUE),
599 "{ 'KEY_HASH_1': { 'KEY_HASH_2': 'VALUE_HASH_1' } }");
600 EXPECT_EQ(JtlInterpreter::OK, interpreter.result());
601 base::ExpectDictBooleanValue(true, *interpreter.working_memory(), VAR_HASH_1);
602 EXPECT_FALSE(interpreter.working_memory()->HasKey(VAR_HASH_2));
605 TEST(JtlInterpreter, EndOfSentence) {
606 INIT_INTERPRETER(
607 OP_NAVIGATE(KEY_HASH_1) +
608 OP_NAVIGATE(KEY_HASH_2) +
609 OP_STORE_BOOL(VAR_HASH_1, VALUE_TRUE) +
610 OP_END_OF_SENTENCE +
611 OP_STORE_BOOL(VAR_HASH_2, VALUE_TRUE),
612 "{ 'KEY_HASH_1': { 'KEY_HASH_2': 'VALUE_HASH_1' } }");
613 EXPECT_EQ(JtlInterpreter::OK, interpreter.result());
614 base::ExpectDictBooleanValue(true, *interpreter.working_memory(), VAR_HASH_1);
615 base::ExpectDictBooleanValue(true, *interpreter.working_memory(), VAR_HASH_2);
618 TEST(JtlInterpreter, InvalidBack) {
619 INIT_INTERPRETER(
620 OP_NAVIGATE(KEY_HASH_1) +
621 OP_NAVIGATE_BACK +
622 OP_NAVIGATE_BACK,
623 "{ 'KEY_HASH_1': { 'KEY_HASH_2': 'VALUE_HASH_1' } }");
624 EXPECT_EQ(JtlInterpreter::RUNTIME_ERROR, interpreter.result());
627 TEST(JtlInterpreter, IncorrectPrograms) {
628 std::string missing_hash;
629 std::string missing_bool;
630 std::string invalid_hash("123");
631 std::string invalid_bool("\x02", 1);
632 std::string invalid_operation("\x99", 1);
633 std::string programs[] = {
634 OP_NAVIGATE(missing_hash),
635 OP_NAVIGATE(invalid_hash),
636 OP_STORE_BOOL(VAR_HASH_1, invalid_bool),
637 OP_STORE_BOOL(missing_hash, VALUE_TRUE),
638 OP_STORE_BOOL(invalid_hash, VALUE_TRUE),
639 OP_COMPARE_STORED_BOOL(invalid_hash, VALUE_TRUE, VALUE_TRUE),
640 OP_COMPARE_STORED_BOOL(VAR_HASH_1, invalid_bool, VALUE_TRUE),
641 OP_COMPARE_STORED_BOOL(VAR_HASH_1, VALUE_TRUE, invalid_bool),
642 OP_COMPARE_STORED_BOOL(VAR_HASH_1, VALUE_TRUE, missing_bool),
643 OP_STORE_NODE_BOOL(missing_hash),
644 OP_STORE_NODE_BOOL(invalid_hash),
645 OP_STORE_NODE_HASH(missing_hash),
646 OP_STORE_NODE_HASH(invalid_hash),
647 OP_COMPARE_NODE_BOOL(missing_bool),
648 OP_COMPARE_NODE_BOOL(invalid_bool),
649 OP_COMPARE_NODE_HASH(missing_hash),
650 OP_COMPARE_NODE_HASH(invalid_hash),
651 OP_COMPARE_NODE_TO_STORED_BOOL(missing_hash),
652 OP_COMPARE_NODE_TO_STORED_BOOL(invalid_hash),
653 OP_COMPARE_NODE_TO_STORED_HASH(missing_hash),
654 OP_COMPARE_NODE_TO_STORED_HASH(invalid_hash),
655 invalid_operation,
657 for (size_t i = 0; i < arraysize(programs); ++i) {
658 SCOPED_TRACE(testing::Message() << "Iteration " << i);
659 INIT_INTERPRETER(programs[i],
660 "{ 'KEY_HASH_1': { 'KEY_HASH_2': 'VALUE_HASH_1' } }");
661 EXPECT_EQ(JtlInterpreter::PARSE_ERROR, interpreter.result());
665 TEST(JtlInterpreter, GetOutput) {
666 INIT_INTERPRETER(
667 OP_STORE_BOOL(GetHash("output1"), VALUE_TRUE) +
668 OP_STORE_HASH(GetHash("output2"), VALUE_HASH_1),
669 "{}");
670 bool output1 = false;
671 std::string output2;
672 EXPECT_TRUE(interpreter.GetOutputBoolean("output1", &output1));
673 EXPECT_EQ(true, output1);
674 EXPECT_TRUE(interpreter.GetOutputString("output2", &output2));
675 EXPECT_EQ(VALUE_HASH_1, output2);
676 EXPECT_FALSE(interpreter.GetOutputBoolean("outputxx", &output1));
677 EXPECT_FALSE(interpreter.GetOutputString("outputxx", &output2));
680 TEST(JtlInterpreter, CalculateProgramChecksum) {
681 const char kTestSeed[] = "Irrelevant seed value.";
682 const char kTestProgram[] = "The quick brown fox jumps over the lazy dog.";
683 // This program is invalid, but we are not actually executing it.
684 base::DictionaryValue input;
685 JtlInterpreter interpreter(kTestSeed, kTestProgram, &input);
686 EXPECT_EQ(0xef537f, interpreter.CalculateProgramChecksum());
689 } // namespace