OLD | NEW |
---|---|
(Empty) | |
1 // Copyright 2013 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/tools/profile_reset/jtl_compiler.h" | |
6 | |
7 #include <string> | |
8 | |
9 #include "base/json/json_writer.h" | |
10 #include "base/memory/scoped_ptr.h" | |
11 #include "base/values.h" | |
12 #include "chrome/browser/profile_resetter/jtl_foundation.h" | |
13 #include "chrome/browser/profile_resetter/jtl_instructions.h" | |
14 #include "testing/gmock/include/gmock/gmock-matchers.h" | |
15 #include "testing/gtest/include/gtest/gtest.h" | |
16 | |
17 namespace { | |
18 | |
19 const char kHashSeed[] = "test-hash-seed"; | |
20 | |
21 // Helpers ------------------------------------------------------------------- | |
22 | |
23 std::string GetHash(const std::string& input) { | |
24 return jtl_foundation::Hasher(kHashSeed).GetHash(input); | |
25 } | |
26 | |
27 // Tests --------------------------------------------------------------------- | |
28 | |
29 // Note: Parsing and parsing-related errors are unit-tested separately in more | |
30 // detail in "jtl_parser_unittest.cc". Here we assume that creating the parse | |
31 // tree works. | |
32 | |
33 TEST(JtlCompiler, CompileSingleInstructions) { | |
34 struct TestCase { | |
35 std::string source_code; | |
36 std::string expected_bytecode; | |
37 } cases[] = { | |
38 {"node(\"foo\")/", OP_NAVIGATE(GetHash("foo"))}, | |
39 {"node(\"has whitespace\")/", OP_NAVIGATE(GetHash("has whitespace"))}, | |
40 {"any/", OP_NAVIGATE_ANY}, {"back/", OP_NAVIGATE_BACK}, | |
battre
2013/10/01 12:18:26
nit: {"back/" in new line?
engedy
2013/10/01 15:09:33
Sorry, clang-format again... Done.
| |
41 {"store_bool(\"name\", true)/", | |
42 OP_STORE_BOOL(GetHash("name"), VALUE_TRUE)}, | |
43 {"compare_stored_bool(\"name\", true, false)/", | |
44 OP_COMPARE_STORED_BOOL(GetHash("name"), VALUE_TRUE, VALUE_FALSE)}, | |
45 {"store_hash(\"name\", \"value\")/", | |
46 OP_STORE_HASH(GetHash("name"), GetHash("value"))}, | |
47 {"compare_stored_hash(\"name\", \"value\", \"default\")/", | |
48 OP_COMPARE_STORED_HASH( | |
49 GetHash("name"), GetHash("value"), GetHash("default"))}, | |
50 {"compare_bool(false)/", OP_COMPARE_NODE_BOOL(VALUE_FALSE)}, | |
51 {"compare_bool(true)/", OP_COMPARE_NODE_BOOL(VALUE_TRUE)}, | |
52 {"compare_hash(\"foo\")/", OP_COMPARE_NODE_HASH(GetHash("foo"))}, | |
53 {"compare_hash(\"bar\")/", OP_COMPARE_NODE_HASH(GetHash("bar"))}, | |
54 {"break/", OP_STOP_EXECUTING_SENTENCE}, | |
55 {"break;", OP_STOP_EXECUTING_SENTENCE + OP_END_OF_SENTENCE}}; | |
56 | |
57 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(cases); ++i) { | |
58 SCOPED_TRACE(cases[i].source_code); | |
59 std::string bytecode; | |
60 EXPECT_TRUE( | |
61 JtlCompiler::Compile(cases[i].source_code, kHashSeed, &bytecode, NULL)); | |
62 EXPECT_EQ(cases[i].expected_bytecode, bytecode); | |
63 } | |
64 } | |
65 | |
66 TEST(JtlCompiler, CompileEntireProgram) { | |
67 const char kSourceCode[] = | |
68 "// Store \"x\"=true if path is found.\n" | |
69 "node(\"foo\")/node(\"bar\")/store_bool(\"x\", true);\n" | |
70 "// ...\n" | |
71 "// Store \"y\"=\"1\" if above value is set.\n" | |
72 "compare_stored_bool(\"x\", true, false)/store_hash(\"y\", \"1\");\n"; | |
73 | |
74 std::string expected_bytecode = | |
75 OP_NAVIGATE(GetHash("foo")) + OP_NAVIGATE(GetHash("bar")) + | |
76 OP_STORE_BOOL(GetHash("x"), VALUE_TRUE) + OP_END_OF_SENTENCE + | |
77 OP_COMPARE_STORED_BOOL(GetHash("x"), VALUE_TRUE, VALUE_FALSE) + | |
78 OP_STORE_HASH(GetHash("y"), GetHash("1")) + OP_END_OF_SENTENCE; | |
79 | |
80 std::string bytecode; | |
81 EXPECT_TRUE(JtlCompiler::Compile(kSourceCode, kHashSeed, &bytecode, NULL)); | |
82 EXPECT_EQ(expected_bytecode, bytecode); | |
83 } | |
84 | |
85 TEST(JtlCompiler, InvalidOperationName) { | |
86 const char kSourceCode[] = "any()\n/\nnon_existent_instruction\n(\n)\n;\n"; | |
87 | |
88 std::string bytecode; | |
89 JtlCompiler::CompileError error; | |
90 EXPECT_FALSE(JtlCompiler::Compile(kSourceCode, kHashSeed, &bytecode, &error)); | |
91 EXPECT_THAT(error.context, testing::StartsWith("non_existent_instruction")); | |
92 EXPECT_EQ(2u, error.line_number); | |
93 EXPECT_EQ(JtlCompiler::CompileError::INVALID_OPERATION_NAME, | |
94 error.error_code); | |
95 } | |
96 | |
97 TEST(JtlCompiler, InvalidArgumentsCount) { | |
98 const char* kSourceCodes[] = { | |
99 "any()/\nstore_bool(\"name\", true, \"superfluous argument\");\n", | |
100 "any()/\nstore_bool(\"name\");"}; // missing argument | |
101 | |
102 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kSourceCodes); ++i) { | |
103 SCOPED_TRACE(kSourceCodes[i]); | |
104 std::string bytecode; | |
105 JtlCompiler::CompileError error; | |
106 EXPECT_FALSE( | |
107 JtlCompiler::Compile(kSourceCodes[i], kHashSeed, &bytecode, &error)); | |
108 EXPECT_THAT(error.context, testing::StartsWith("store_bool")); | |
109 EXPECT_EQ(1u, error.line_number); | |
110 EXPECT_EQ(JtlCompiler::CompileError::INVALID_ARGUMENT_COUNT, | |
111 error.error_code); | |
112 } | |
113 } | |
114 | |
115 TEST(JtlCompiler, InvalidArgumentType) { | |
116 const char* kSourceCodes[] = { | |
117 "any()\n/\ncompare_stored_bool(true, false, false);", // Arg#1 should be | |
118 // a hash. | |
119 "any()\n/\ncompare_stored_bool(\"name\", \"should be a bool\", false);", | |
120 "any()\n/\ncompare_stored_bool(\"name\", false, \"should be a bool\");"}; | |
121 | |
122 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kSourceCodes); ++i) { | |
123 SCOPED_TRACE(kSourceCodes[i]); | |
124 std::string bytecode; | |
125 JtlCompiler::CompileError error; | |
126 EXPECT_FALSE( | |
127 JtlCompiler::Compile(kSourceCodes[i], kHashSeed, &bytecode, &error)); | |
128 EXPECT_THAT(error.context, testing::StartsWith("compare_stored_bool")); | |
129 EXPECT_EQ(2u, error.line_number); | |
130 EXPECT_EQ(JtlCompiler::CompileError::INVALID_ARGUMENT_TYPE, | |
131 error.error_code); | |
132 } | |
133 } | |
134 | |
135 TEST(JtlCompiler, MistmatchedDoubleQuotes) { | |
136 const char kSourceCode[] = "any()/\nnode(\"stray quote)/break();"; | |
137 | |
138 std::string bytecode; | |
139 JtlCompiler::CompileError error; | |
140 EXPECT_FALSE(JtlCompiler::Compile(kSourceCode, kHashSeed, &bytecode, &error)); | |
141 EXPECT_EQ(1u, error.line_number); | |
142 EXPECT_EQ(JtlCompiler::CompileError::MISMATCHED_DOUBLE_QUOTES, | |
143 error.error_code); | |
144 } | |
145 | |
146 TEST(JtlCompiler, ParsingError) { | |
147 const char kSourceCode[] = "any()/\nnode()missing_separator();"; | |
148 | |
149 std::string bytecode; | |
150 JtlCompiler::CompileError error; | |
151 EXPECT_FALSE(JtlCompiler::Compile(kSourceCode, kHashSeed, &bytecode, &error)); | |
152 EXPECT_THAT(error.context, testing::StartsWith("node")); | |
153 EXPECT_EQ(1u, error.line_number); | |
154 EXPECT_EQ(JtlCompiler::CompileError::PARSING_ERROR, error.error_code); | |
155 } | |
156 | |
157 } // namespace | |
OLD | NEW |