- add sources.
[platform/framework/web/crosswalk.git] / src / chrome / browser / profile_resetter / jtl_interpreter_unittest.cc
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.
4
5 #include "chrome/browser/profile_resetter/jtl_interpreter.h"
6
7 #include "base/strings/string_util.h"
8 #include "base/test/values_test_util.h"
9 #include "chrome/browser/profile_resetter/jtl_foundation.h"
10 #include "chrome/browser/profile_resetter/jtl_instructions.h"
11 #include "crypto/hmac.h"
12 #include "testing/gtest/include/gtest/gtest.h"
13
14 namespace {
15
16 const char seed[] = "foobar";
17
18 #define KEY_HASH_1 GetHash("KEY_HASH_1")
19 #define KEY_HASH_2 GetHash("KEY_HASH_2")
20 #define KEY_HASH_3 GetHash("KEY_HASH_3")
21 #define KEY_HASH_4 GetHash("KEY_HASH_4")
22
23 #define VALUE_HASH_1 GetHash("VALUE_HASH_1")
24 #define VALUE_HASH_2 GetHash("VALUE_HASH_2")
25
26 #define VAR_HASH_1 "01234567890123456789012345678901"
27 #define VAR_HASH_2 "12345678901234567890123456789012"
28
29 std::string GetHash(const std::string& input) {
30   return jtl_foundation::Hasher(seed).GetHash(input);
31 }
32
33 // escaped_json_param may contain ' characters that are replaced with ". This
34 // makes the code more readable because we need less escaping.
35 #define INIT_INTERPRETER(program_param, escaped_json_param) \
36     const char* escaped_json = escaped_json_param; \
37     std::string json; \
38     ReplaceChars(escaped_json, "'", "\"", &json); \
39     scoped_ptr<Value> json_value(ParseJson(json)); \
40     JtlInterpreter interpreter( \
41         seed, \
42         program_param, \
43         static_cast<const DictionaryValue*>(json_value.get())); \
44     interpreter.Execute()
45
46 using base::test::ParseJson;
47
48 TEST(JtlInterpreter, Store) {
49   INIT_INTERPRETER(
50       OP_STORE_BOOL(VAR_HASH_1, VALUE_TRUE),
51       "{ 'KEY_HASH_1': 'VALUE_HASH_1' }");
52   EXPECT_EQ(JtlInterpreter::OK, interpreter.result());
53   base::ExpectDictBooleanValue(true, *interpreter.working_memory(), VAR_HASH_1);
54 }
55
56 TEST(JtlInterpreter, NavigateAndStore) {
57   INIT_INTERPRETER(
58       OP_NAVIGATE(KEY_HASH_1) +
59       OP_STORE_BOOL(VAR_HASH_1, VALUE_TRUE),
60       "{ 'KEY_HASH_1': 'VALUE_HASH_1' }");
61   EXPECT_EQ(JtlInterpreter::OK, interpreter.result());
62   base::ExpectDictBooleanValue(true, *interpreter.working_memory(), VAR_HASH_1);
63 }
64
65 TEST(JtlInterpreter, FailNavigate) {
66   INIT_INTERPRETER(
67       OP_NAVIGATE(KEY_HASH_2) +
68       OP_STORE_BOOL(VAR_HASH_1, VALUE_TRUE),
69       "{ 'KEY_HASH_1': 'VALUE_HASH_1' }");
70   EXPECT_EQ(JtlInterpreter::OK, interpreter.result());
71   EXPECT_FALSE(interpreter.working_memory()->HasKey(VAR_HASH_1));
72 }
73
74 TEST(JtlInterpreter, ConsecutiveNavigate) {
75   INIT_INTERPRETER(
76       OP_NAVIGATE(KEY_HASH_1) +
77       OP_NAVIGATE(KEY_HASH_2) +
78       OP_STORE_BOOL(VAR_HASH_1, VALUE_TRUE),
79       "{ 'KEY_HASH_1': { 'KEY_HASH_2': 'VALUE_HASH_1' } }");
80   EXPECT_EQ(JtlInterpreter::OK, interpreter.result());
81   base::ExpectDictBooleanValue(true, *interpreter.working_memory(), VAR_HASH_1);
82 }
83
84 TEST(JtlInterpreter, FailConsecutiveNavigate) {
85   INIT_INTERPRETER(
86       OP_NAVIGATE(KEY_HASH_1) +
87       OP_NAVIGATE(KEY_HASH_2) +
88       OP_STORE_BOOL(VAR_HASH_1, VALUE_TRUE),
89       "{ 'KEY_HASH_1': 'foo' }");
90   EXPECT_EQ(JtlInterpreter::OK, interpreter.result());
91   EXPECT_FALSE(interpreter.working_memory()->HasKey(VAR_HASH_1));
92 }
93
94 TEST(JtlInterpreter, NavigateAnyInDictionary) {
95   INIT_INTERPRETER(
96       OP_NAVIGATE(KEY_HASH_1) +
97       OP_NAVIGATE_ANY +
98       OP_NAVIGATE(KEY_HASH_4) +
99       OP_STORE_BOOL(VAR_HASH_1, VALUE_TRUE),
100           "{ 'KEY_HASH_1':"
101           "  { 'KEY_HASH_2': {'KEY_HASH_3': 'VALUE_HASH_1' },"
102           "    'KEY_HASH_3': {'KEY_HASH_4': 'VALUE_HASH_1' }"
103           "  } }");
104   EXPECT_EQ(JtlInterpreter::OK, interpreter.result());
105   base::ExpectDictBooleanValue(true, *interpreter.working_memory(), VAR_HASH_1);
106 }
107
108 TEST(JtlInterpreter, NavigateAnyInList) {
109   INIT_INTERPRETER(
110       OP_NAVIGATE(KEY_HASH_1) +
111       OP_NAVIGATE_ANY +
112       OP_NAVIGATE(KEY_HASH_4) +
113       OP_STORE_BOOL(VAR_HASH_1, VALUE_TRUE),
114           "{ 'KEY_HASH_1':"
115           "  [ {'KEY_HASH_3': 'VALUE_HASH_1' },"
116           "    {'KEY_HASH_4': 'VALUE_HASH_1' }"
117           "  ] }");
118   EXPECT_EQ(JtlInterpreter::OK, interpreter.result());
119   base::ExpectDictBooleanValue(true, *interpreter.working_memory(), VAR_HASH_1);
120 }
121
122 TEST(JtlInterpreter, NavigateBack) {
123   INIT_INTERPRETER(
124       OP_NAVIGATE(KEY_HASH_1) +
125       OP_NAVIGATE(KEY_HASH_2) +
126       OP_NAVIGATE_BACK +
127       OP_NAVIGATE(KEY_HASH_3) +
128       OP_NAVIGATE(KEY_HASH_4) +
129       OP_STORE_BOOL(VAR_HASH_1, VALUE_TRUE),
130           "{ 'KEY_HASH_1':"
131           "  { 'KEY_HASH_2': {'KEY_HASH_3': 'VALUE_HASH_1' },"
132           "    'KEY_HASH_3': {'KEY_HASH_4': 'VALUE_HASH_1' }"
133           "  } }");
134   EXPECT_EQ(JtlInterpreter::OK, interpreter.result());
135   base::ExpectDictBooleanValue(true, *interpreter.working_memory(), VAR_HASH_1);
136 }
137
138 TEST(JtlInterpreter, StoreTwoValues) {
139   INIT_INTERPRETER(
140       OP_NAVIGATE(KEY_HASH_1) +
141       OP_NAVIGATE(KEY_HASH_2) +
142       OP_STORE_BOOL(VAR_HASH_1, VALUE_TRUE) +
143       OP_STORE_HASH(VAR_HASH_2, VALUE_HASH_1),
144       "{ 'KEY_HASH_1': { 'KEY_HASH_2': 'VALUE_HASH_1' } }");
145   EXPECT_EQ(JtlInterpreter::OK, interpreter.result());
146   base::ExpectDictBooleanValue(true, *interpreter.working_memory(), VAR_HASH_1);
147   base::ExpectDictStringValue(VALUE_HASH_1, *interpreter.working_memory(),
148                               VAR_HASH_2);
149 }
150
151 TEST(JtlInterpreter, CompareStoredMatch) {
152   INIT_INTERPRETER(
153       OP_NAVIGATE(KEY_HASH_1) +
154       OP_STORE_BOOL(VAR_HASH_1, VALUE_TRUE) +
155       OP_NAVIGATE(KEY_HASH_2) +
156       OP_COMPARE_STORED_BOOL(VAR_HASH_1, VALUE_TRUE, VALUE_FALSE) +
157       OP_STORE_BOOL(VAR_HASH_2, VALUE_TRUE),
158       "{ 'KEY_HASH_1': { 'KEY_HASH_2': 'VALUE_HASH_1' } }");
159   EXPECT_EQ(JtlInterpreter::OK, interpreter.result());
160   base::ExpectDictBooleanValue(true, *interpreter.working_memory(), VAR_HASH_1);
161   base::ExpectDictBooleanValue(true, *interpreter.working_memory(), VAR_HASH_2);
162 }
163
164 TEST(JtlInterpreter, CompareStoredMismatch) {
165   INIT_INTERPRETER(
166       OP_NAVIGATE(KEY_HASH_1) +
167       OP_STORE_BOOL(VAR_HASH_1, VALUE_TRUE) +
168       OP_NAVIGATE(KEY_HASH_2) +
169       OP_COMPARE_STORED_BOOL(VAR_HASH_1, VALUE_FALSE, VALUE_TRUE) +
170       OP_STORE_BOOL(VAR_HASH_2, VALUE_TRUE),
171       "{ 'KEY_HASH_1': { 'KEY_HASH_2': 'VALUE_HASH_1' } }");
172   EXPECT_EQ(JtlInterpreter::OK, interpreter.result());
173   base::ExpectDictBooleanValue(true, *interpreter.working_memory(), VAR_HASH_1);
174   EXPECT_FALSE(interpreter.working_memory()->HasKey(VAR_HASH_2));
175 }
176
177 TEST(JtlInterpreter, CompareStoredNoValueMatchingDefault) {
178   INIT_INTERPRETER(
179       OP_NAVIGATE(KEY_HASH_1) +
180       OP_NAVIGATE(KEY_HASH_2) +
181       OP_COMPARE_STORED_BOOL(VAR_HASH_1, VALUE_TRUE, VALUE_TRUE) +
182       OP_STORE_BOOL(VAR_HASH_2, VALUE_TRUE),
183       "{ 'KEY_HASH_1': { 'KEY_HASH_2': 'VALUE_HASH_1' } }");
184   EXPECT_EQ(JtlInterpreter::OK, interpreter.result());
185   base::ExpectDictBooleanValue(true, *interpreter.working_memory(), VAR_HASH_2);
186 }
187
188 TEST(JtlInterpreter, CompareStoredNoValueMismatchingDefault) {
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_FALSE) +
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   EXPECT_FALSE(interpreter.working_memory()->HasKey(VAR_HASH_2));
197 }
198
199 TEST(JtlInterpreter, CompareBool) {
200   struct TestCase {
201     std::string expected_value;
202     const char* json;
203     bool expected_success;
204   } cases[] = {
205     { VALUE_TRUE, "{ 'KEY_HASH_1': true }", true },
206     { VALUE_FALSE, "{ 'KEY_HASH_1': false }", true },
207     { VALUE_TRUE, "{ 'KEY_HASH_1': false }", false },
208     { VALUE_TRUE, "{ 'KEY_HASH_1': 'abc' }", false },
209     { VALUE_TRUE, "{ 'KEY_HASH_1': 1 }", false },
210     { VALUE_TRUE, "{ 'KEY_HASH_1': 1.2 }", false },
211     { VALUE_TRUE, "{ 'KEY_HASH_1': [1] }", false },
212     { VALUE_TRUE, "{ 'KEY_HASH_1': {'a': 'b'} }", false },
213   };
214
215   for (size_t i = 0; i < ARRAYSIZE_UNSAFE(cases); ++i) {
216     SCOPED_TRACE(testing::Message() << "Iteration " << i);
217     INIT_INTERPRETER(
218         OP_NAVIGATE(KEY_HASH_1) +
219         OP_COMPARE_NODE_BOOL(cases[i].expected_value) +
220         OP_STORE_BOOL(VAR_HASH_1, VALUE_TRUE),
221         cases[i].json);
222     EXPECT_EQ(JtlInterpreter::OK, interpreter.result());
223     if (cases[i].expected_success) {
224       base::ExpectDictBooleanValue(
225           true, *interpreter.working_memory(), VAR_HASH_1);
226     } else {
227       EXPECT_FALSE(interpreter.working_memory()->HasKey(VAR_HASH_1));
228     }
229   }
230 }
231
232 TEST(JtlInterpreter, CompareHashString) {
233   struct TestCase {
234     std::string expected_value;
235     const char* json;
236     bool expected_success;
237   } cases[] = {
238     { VALUE_HASH_1, "{ 'KEY_HASH_1': 'VALUE_HASH_1' }", true },
239     { VALUE_HASH_1, "{ 'KEY_HASH_1': 'VALUE_HASH_2' }", false },
240     { VALUE_HASH_1, "{ 'KEY_HASH_1': true }", false },
241     { VALUE_HASH_1, "{ 'KEY_HASH_1': 1 }", false },
242     { VALUE_HASH_1, "{ 'KEY_HASH_1': 1.1 }", false },
243     { VALUE_HASH_1, "{ 'KEY_HASH_1': [1] }", false },
244     { VALUE_HASH_1, "{ 'KEY_HASH_1': {'a': 'b'} }", false },
245
246     { GetHash("1.2"), "{ 'KEY_HASH_1': 1.2 }", true },
247     { GetHash("1.2"), "{ 'KEY_HASH_1': 'VALUE_HASH_1' }", false },
248     { GetHash("1.2"), "{ 'KEY_HASH_1': true }", false },
249     { GetHash("1.2"), "{ 'KEY_HASH_1': 1 }", false },
250     { GetHash("1.2"), "{ 'KEY_HASH_1': 1.3 }", false },
251     { GetHash("1.2"), "{ 'KEY_HASH_1': [1] }", false },
252     { GetHash("1.2"), "{ 'KEY_HASH_1': {'a': 'b'} }", false },
253
254     { GetHash("1"), "{ 'KEY_HASH_1': 1 }", true },
255     { GetHash("1"), "{ 'KEY_HASH_1': 'VALUE_HASH_1' }", false },
256     { GetHash("1"), "{ 'KEY_HASH_1': true }", false },
257     { GetHash("1"), "{ 'KEY_HASH_1': 2 }", false },
258     { GetHash("1"), "{ 'KEY_HASH_1': 1.1 }", false },
259     { GetHash("1"), "{ 'KEY_HASH_1': [1] }", false },
260     { GetHash("1"), "{ 'KEY_HASH_1': {'a': 'b'} }", false },
261   };
262
263   for (size_t i = 0; i < ARRAYSIZE_UNSAFE(cases); ++i) {
264     SCOPED_TRACE(testing::Message() << "Iteration " << i);
265     INIT_INTERPRETER(
266         OP_NAVIGATE(KEY_HASH_1) +
267         OP_COMPARE_NODE_HASH(cases[i].expected_value) +
268         OP_STORE_BOOL(VAR_HASH_1, VALUE_TRUE),
269         cases[i].json);
270     EXPECT_EQ(JtlInterpreter::OK, interpreter.result());
271     if (cases[i].expected_success) {
272       base::ExpectDictBooleanValue(
273           true, *interpreter.working_memory(), VAR_HASH_1);
274     } else {
275       EXPECT_FALSE(interpreter.working_memory()->HasKey(VAR_HASH_1));
276     }
277   }
278
279   for (size_t i = 0; i < ARRAYSIZE_UNSAFE(cases); ++i) {
280     SCOPED_TRACE(testing::Message() << "Negated, Iteration " << i);
281     INIT_INTERPRETER(
282         OP_NAVIGATE(KEY_HASH_1) +
283         OP_COMPARE_NODE_HASH_NOT(cases[i].expected_value) +
284         OP_STORE_BOOL(VAR_HASH_1, VALUE_TRUE),
285         cases[i].json);
286     EXPECT_EQ(JtlInterpreter::OK, interpreter.result());
287     if (!cases[i].expected_success) {
288       base::ExpectDictBooleanValue(
289           true, *interpreter.working_memory(), VAR_HASH_1);
290     } else {
291       EXPECT_FALSE(interpreter.working_memory()->HasKey(VAR_HASH_1));
292     }
293   }
294 }
295
296 TEST(JtlInterpreter, StoreNodeBool) {
297   struct TestCase {
298     bool expected_value;
299     const char* json;
300     bool expected_success;
301   } cases[] = {
302     { true, "{ 'KEY_HASH_1': true }", true },
303     { false, "{ 'KEY_HASH_1': false }", true },
304     { false, "{ 'KEY_HASH_1': 'abc' }", false },
305     { false, "{ 'KEY_HASH_1': 1 }", false },
306     { false, "{ 'KEY_HASH_1': 1.2 }", false },
307     { false, "{ 'KEY_HASH_1': [1] }", false },
308     { false, "{ 'KEY_HASH_1': {'a': 'b'} }", false },
309   };
310
311   for (size_t i = 0; i < ARRAYSIZE_UNSAFE(cases); ++i) {
312     SCOPED_TRACE(testing::Message() << "Iteration " << i);
313     INIT_INTERPRETER(
314         OP_NAVIGATE(KEY_HASH_1) +
315         OP_STORE_NODE_BOOL(VAR_HASH_1) +
316         OP_STORE_BOOL(VAR_HASH_2, VALUE_TRUE),
317         cases[i].json);
318     EXPECT_EQ(JtlInterpreter::OK, interpreter.result());
319     if (cases[i].expected_success) {
320       base::ExpectDictBooleanValue(
321           cases[i].expected_value, *interpreter.working_memory(), VAR_HASH_1);
322       base::ExpectDictBooleanValue(
323           true, *interpreter.working_memory(), VAR_HASH_2);
324     } else {
325       EXPECT_FALSE(interpreter.working_memory()->HasKey(VAR_HASH_1));
326       EXPECT_FALSE(interpreter.working_memory()->HasKey(VAR_HASH_2));
327     }
328   }
329 }
330
331 TEST(JtlInterpreter, CompareNodeToStoredBool) {
332   struct TestCase {
333     std::string stored_value;
334     const char* json;
335     bool expected_success;
336   } cases[] = {
337     { VALUE_TRUE, "{ 'KEY_HASH_1': true }", true },
338     { VALUE_FALSE, "{ 'KEY_HASH_1': false }", true },
339     { VALUE_FALSE, "{ 'KEY_HASH_1': true }", false },
340     { std::string(), "{ 'KEY_HASH_1': true }", false },
341
342     { VALUE_HASH_1, "{ 'KEY_HASH_1': 'VALUE_HASH_1' }", false },
343     { GetHash("1"), "{ 'KEY_HASH_1': 1 }", false },
344     { GetHash("1.2"), "{ 'KEY_HASH_1': 1.2 }", false },
345
346     { VALUE_HASH_1, "{ 'KEY_HASH_1': true }", false },
347     { GetHash("1"), "{ 'KEY_HASH_1': true }", false },
348     { GetHash("1.2"), "{ 'KEY_HASH_1': true }", false },
349
350     { VALUE_TRUE, "{ 'KEY_HASH_1': 'VALUE_HASH_1' }", false },
351     { VALUE_TRUE, "{ 'KEY_HASH_1': 1 }", false },
352     { VALUE_TRUE, "{ 'KEY_HASH_1': 1.2 }", false },
353     { VALUE_TRUE, "{ 'KEY_HASH_1': [1] }", false },
354     { VALUE_TRUE, "{ 'KEY_HASH_1': {'a': 'b'} }", false },
355   };
356
357   for (size_t i = 0; i < ARRAYSIZE_UNSAFE(cases); ++i) {
358     SCOPED_TRACE(testing::Message() << "Iteration " << i);
359     std::string store_op;
360     if (cases[i].stored_value == VALUE_TRUE ||
361         cases[i].stored_value == VALUE_FALSE)
362       store_op = OP_STORE_BOOL(VAR_HASH_1, cases[i].stored_value);
363     else if (!cases[i].stored_value.empty())
364       store_op = OP_STORE_HASH(VAR_HASH_1, cases[i].stored_value);
365     INIT_INTERPRETER(
366         store_op +
367         OP_NAVIGATE(KEY_HASH_1) +
368         OP_COMPARE_NODE_TO_STORED_BOOL(VAR_HASH_1) +
369         OP_STORE_BOOL(VAR_HASH_2, VALUE_TRUE),
370         cases[i].json);
371     EXPECT_EQ(JtlInterpreter::OK, interpreter.result());
372     if (cases[i].expected_success) {
373       base::ExpectDictBooleanValue(
374           true, *interpreter.working_memory(), VAR_HASH_2);
375     } else {
376       EXPECT_FALSE(interpreter.working_memory()->HasKey(VAR_HASH_2));
377     }
378   }
379 }
380
381 TEST(JtlInterpreter, StoreNodeHash) {
382   struct TestCase {
383     std::string expected_value;
384     const char* json;
385     bool expected_success;
386   } cases[] = {
387     { VALUE_HASH_1, "{ 'KEY_HASH_1': 'VALUE_HASH_1' }", true },
388     { VALUE_HASH_2, "{ 'KEY_HASH_1': 'VALUE_HASH_2' }", true },
389     { GetHash("1"), "{ 'KEY_HASH_1': 1 }", true },
390     { GetHash("1.2"), "{ 'KEY_HASH_1': 1.2 }", true },
391     { std::string(), "{ 'KEY_HASH_1': true }", false },
392     { std::string(), "{ 'KEY_HASH_1': [1] }", false },
393     { std::string(), "{ 'KEY_HASH_1': {'a': 'b'} }", false },
394   };
395
396   for (size_t i = 0; i < ARRAYSIZE_UNSAFE(cases); ++i) {
397     SCOPED_TRACE(testing::Message() << "Iteration " << i);
398     INIT_INTERPRETER(
399         OP_NAVIGATE(KEY_HASH_1) +
400         OP_STORE_NODE_HASH(VAR_HASH_1) +
401         OP_STORE_BOOL(VAR_HASH_2, VALUE_TRUE),
402         cases[i].json);
403     EXPECT_EQ(JtlInterpreter::OK, interpreter.result());
404     if (cases[i].expected_success) {
405       base::ExpectDictStringValue(
406           cases[i].expected_value, *interpreter.working_memory(), VAR_HASH_1);
407       base::ExpectDictBooleanValue(
408           true, *interpreter.working_memory(), VAR_HASH_2);
409     } else {
410       EXPECT_FALSE(interpreter.working_memory()->HasKey(VAR_HASH_1));
411       EXPECT_FALSE(interpreter.working_memory()->HasKey(VAR_HASH_2));
412     }
413   }
414 }
415
416 TEST(JtlInterpreter, CompareNodeToStoredHash) {
417   struct TestCase {
418     std::string stored_value;
419     const char* json;
420     bool expected_success;
421   } cases[] = {
422     { VALUE_HASH_1, "{ 'KEY_HASH_1': 'VALUE_HASH_1' }", true },
423     { VALUE_HASH_2, "{ 'KEY_HASH_1': 'VALUE_HASH_2' }", true },
424     { std::string(), "{ 'KEY_HASH_1': 'VALUE_HASH_2' }", false },
425     { VALUE_HASH_1, "{ 'KEY_HASH_1': 'VALUE_HASH_2' }", false },
426     { VALUE_HASH_1, "{ 'KEY_HASH_1': true }", false },
427     { VALUE_HASH_1, "{ 'KEY_HASH_1': 1 }", false },
428     { VALUE_HASH_1, "{ 'KEY_HASH_1': 1.1 }", false },
429     { VALUE_HASH_1, "{ 'KEY_HASH_1': [1] }", false },
430     { VALUE_HASH_1, "{ 'KEY_HASH_1': {'a': 'b'} }", false },
431
432     { GetHash("1.2"), "{ 'KEY_HASH_1': 1.2 }", true },
433     { GetHash("1.3"), "{ 'KEY_HASH_1': 1.3 }", true },
434     { std::string(), "{ 'KEY_HASH_1': 1.2 }", false },
435     { GetHash("1.2"), "{ 'KEY_HASH_1': 'VALUE_HASH_1' }", false },
436     { GetHash("1.2"), "{ 'KEY_HASH_1': true }", false },
437     { GetHash("1.2"), "{ 'KEY_HASH_1': 1 }", false },
438     { GetHash("1.2"), "{ 'KEY_HASH_1': 1.3 }", false },
439     { GetHash("1.2"), "{ 'KEY_HASH_1': [1] }", false },
440     { GetHash("1.2"), "{ 'KEY_HASH_1': {'a': 'b'} }", false },
441
442     { GetHash("1"), "{ 'KEY_HASH_1': 1 }", true },
443     { GetHash("2"), "{ 'KEY_HASH_1': 2 }", true },
444     { std::string(), "{ 'KEY_HASH_1': 2 }", false },
445     { GetHash("1"), "{ 'KEY_HASH_1': 'VALUE_HASH_1' }", false },
446     { GetHash("1"), "{ 'KEY_HASH_1': true }", false },
447     { GetHash("1"), "{ 'KEY_HASH_1': 2 }", false },
448     { GetHash("1"), "{ 'KEY_HASH_1': 1.1 }", false },
449     { GetHash("1"), "{ 'KEY_HASH_1': [1] }", false },
450     { GetHash("1"), "{ 'KEY_HASH_1': {'a': 'b'} }", false },
451
452     { VALUE_TRUE, "{ 'KEY_HASH_1': 'VALUE_HASH_1' }", false },
453     { VALUE_TRUE, "{ 'KEY_HASH_1': 1 }", false },
454     { VALUE_TRUE, "{ 'KEY_HASH_1': 1.3 }", false },
455     { VALUE_TRUE, "{ 'KEY_HASH_1': [1] }", false },
456     { VALUE_TRUE, "{ 'KEY_HASH_1': {'a': 'b'} }", false },
457
458     { VALUE_TRUE, "{ 'KEY_HASH_1': true }", false },
459     { VALUE_FALSE, "{ 'KEY_HASH_1': false }", false },
460   };
461
462   for (size_t i = 0; i < ARRAYSIZE_UNSAFE(cases); ++i) {
463     SCOPED_TRACE(testing::Message() << "Iteration " << i);
464     std::string store_op;
465     if (cases[i].stored_value == VALUE_TRUE ||
466         cases[i].stored_value == VALUE_FALSE)
467       store_op = OP_STORE_BOOL(VAR_HASH_1, cases[i].stored_value);
468     else if (!cases[i].stored_value.empty())
469       store_op = OP_STORE_HASH(VAR_HASH_1, cases[i].stored_value);
470     INIT_INTERPRETER(
471         store_op +
472         OP_NAVIGATE(KEY_HASH_1) +
473         OP_COMPARE_NODE_TO_STORED_HASH(VAR_HASH_1) +
474         OP_STORE_BOOL(VAR_HASH_2, VALUE_TRUE),
475         cases[i].json);
476     EXPECT_EQ(JtlInterpreter::OK, interpreter.result());
477     if (cases[i].expected_success) {
478       base::ExpectDictBooleanValue(
479           true, *interpreter.working_memory(), VAR_HASH_2);
480     } else {
481       EXPECT_FALSE(interpreter.working_memory()->HasKey(VAR_HASH_2));
482     }
483   }
484 }
485
486 TEST(JtlInterpreter, Stop) {
487   INIT_INTERPRETER(
488       OP_NAVIGATE(KEY_HASH_1) +
489       OP_NAVIGATE(KEY_HASH_2) +
490       OP_STORE_BOOL(VAR_HASH_1, VALUE_TRUE) +
491       OP_STOP_EXECUTING_SENTENCE +
492       OP_STORE_BOOL(VAR_HASH_2, VALUE_TRUE),
493       "{ 'KEY_HASH_1': { 'KEY_HASH_2': 'VALUE_HASH_1' } }");
494   EXPECT_EQ(JtlInterpreter::OK, interpreter.result());
495   base::ExpectDictBooleanValue(true, *interpreter.working_memory(), VAR_HASH_1);
496   EXPECT_FALSE(interpreter.working_memory()->HasKey(VAR_HASH_2));
497 }
498
499 TEST(JtlInterpreter, EndOfSentence) {
500   INIT_INTERPRETER(
501       OP_NAVIGATE(KEY_HASH_1) +
502       OP_NAVIGATE(KEY_HASH_2) +
503       OP_STORE_BOOL(VAR_HASH_1, VALUE_TRUE) +
504       OP_END_OF_SENTENCE +
505       OP_STORE_BOOL(VAR_HASH_2, VALUE_TRUE),
506       "{ 'KEY_HASH_1': { 'KEY_HASH_2': 'VALUE_HASH_1' } }");
507   EXPECT_EQ(JtlInterpreter::OK, interpreter.result());
508   base::ExpectDictBooleanValue(true, *interpreter.working_memory(), VAR_HASH_1);
509   base::ExpectDictBooleanValue(true, *interpreter.working_memory(), VAR_HASH_2);
510 }
511
512 TEST(JtlInterpreter, InvalidBack) {
513   INIT_INTERPRETER(
514       OP_NAVIGATE(KEY_HASH_1) +
515       OP_NAVIGATE_BACK +
516       OP_NAVIGATE_BACK,
517       "{ 'KEY_HASH_1': { 'KEY_HASH_2': 'VALUE_HASH_1' } }");
518   EXPECT_EQ(JtlInterpreter::RUNTIME_ERROR, interpreter.result());
519 }
520
521 TEST(JtlInterpreter, IncorrectPrograms) {
522   std::string missing_hash;
523   std::string missing_bool;
524   std::string invalid_hash("123");
525   std::string invalid_bool("\x02", 1);
526   std::string invalid_operation("\x99", 1);
527   std::string programs[] = {
528     OP_NAVIGATE(missing_hash),
529     OP_NAVIGATE(invalid_hash),
530     OP_STORE_BOOL(VAR_HASH_1, invalid_bool),
531     OP_STORE_BOOL(missing_hash, VALUE_TRUE),
532     OP_STORE_BOOL(invalid_hash, VALUE_TRUE),
533     OP_COMPARE_STORED_BOOL(invalid_hash, VALUE_TRUE, VALUE_TRUE),
534     OP_COMPARE_STORED_BOOL(VAR_HASH_1, invalid_bool, VALUE_TRUE),
535     OP_COMPARE_STORED_BOOL(VAR_HASH_1, VALUE_TRUE, invalid_bool),
536     OP_COMPARE_STORED_BOOL(VAR_HASH_1, VALUE_TRUE, missing_bool),
537     OP_STORE_NODE_BOOL(missing_hash),
538     OP_STORE_NODE_BOOL(invalid_hash),
539     OP_STORE_NODE_HASH(missing_hash),
540     OP_STORE_NODE_HASH(invalid_hash),
541     OP_COMPARE_NODE_BOOL(missing_bool),
542     OP_COMPARE_NODE_BOOL(invalid_bool),
543     OP_COMPARE_NODE_HASH(missing_hash),
544     OP_COMPARE_NODE_HASH(invalid_hash),
545     OP_COMPARE_NODE_TO_STORED_BOOL(missing_hash),
546     OP_COMPARE_NODE_TO_STORED_BOOL(invalid_hash),
547     OP_COMPARE_NODE_TO_STORED_HASH(missing_hash),
548     OP_COMPARE_NODE_TO_STORED_HASH(invalid_hash),
549     invalid_operation,
550   };
551   for (size_t i = 0; i < arraysize(programs); ++i) {
552     SCOPED_TRACE(testing::Message() << "Iteration " << i);
553     INIT_INTERPRETER(programs[i],
554                      "{ 'KEY_HASH_1': { 'KEY_HASH_2': 'VALUE_HASH_1' } }");
555     EXPECT_EQ(JtlInterpreter::PARSE_ERROR, interpreter.result());
556   }
557 }
558
559 TEST(JtlInterpreter, GetOutput) {
560   INIT_INTERPRETER(
561       OP_STORE_BOOL(GetHash("output1"), VALUE_TRUE) +
562       OP_STORE_HASH(GetHash("output2"), VALUE_HASH_1),
563       "{}");
564   bool output1 = false;
565   std::string output2;
566   EXPECT_TRUE(interpreter.GetOutputBoolean("output1", &output1));
567   EXPECT_EQ(true, output1);
568   EXPECT_TRUE(interpreter.GetOutputString("output2", &output2));
569   EXPECT_EQ(VALUE_HASH_1, output2);
570   EXPECT_FALSE(interpreter.GetOutputBoolean("outputxx", &output1));
571   EXPECT_FALSE(interpreter.GetOutputString("outputxx", &output2));
572 }
573
574 }  // namespace