diff options
author | engedy@chromium.org <engedy@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-10-25 15:13:49 +0000 |
---|---|---|
committer | engedy@chromium.org <engedy@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-10-25 15:13:49 +0000 |
commit | 8682d2accd2025287abe1336a158fc2b604cd7ed (patch) | |
tree | 30efb2b0a014012c4d3a7d4b07f2853569060d3d /chrome/tools | |
parent | 5c023ebb6038cb573e25b3aebd6c2f4bd59b07b5 (diff) | |
download | chromium_src-8682d2accd2025287abe1336a158fc2b604cd7ed.zip chromium_src-8682d2accd2025287abe1336a158fc2b604cd7ed.tar.gz chromium_src-8682d2accd2025287abe1336a158fc2b604cd7ed.tar.bz2 |
Improved syntax, and added new instructions to the JTL interpreter.
Added 5 new commands to the JTL interpreter. Also fixed a few nits, typos, tests, and clarified some comments in existing code, as well as changed the syntax so JTL programs became a lot more readable.
BUG=298036
Review URL: https://codereview.chromium.org/35353002
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@231019 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/tools')
-rw-r--r-- | chrome/tools/profile_reset/jtl_compiler.cc | 52 | ||||
-rw-r--r-- | chrome/tools/profile_reset/jtl_compiler.h | 6 | ||||
-rw-r--r-- | chrome/tools/profile_reset/jtl_compiler_unittest.cc | 81 | ||||
-rw-r--r-- | chrome/tools/profile_reset/jtl_parser.cc | 2 | ||||
-rw-r--r-- | chrome/tools/profile_reset/jtl_parser_unittest.cc | 59 |
5 files changed, 127 insertions, 73 deletions
diff --git a/chrome/tools/profile_reset/jtl_compiler.cc b/chrome/tools/profile_reset/jtl_compiler.cc index 21104e9..f98d3d5 100644 --- a/chrome/tools/profile_reset/jtl_compiler.cc +++ b/chrome/tools/profile_reset/jtl_compiler.cc @@ -23,7 +23,7 @@ class ByteCodeWriter { void WriteUint8(uint8 value) { output_->push_back(static_cast<char>(value)); } void WriteOpCode(uint8 op_code) { WriteUint8(op_code); } void WriteHash(const std::string& hash) { - CHECK_EQ(hash.size(), jtl::kHashSizeInBytes); + CHECK(jtl::Hasher::IsHash(hash)); *output_ += hash; } void WriteBool(bool value) { WriteUint8(value ? 1u : 0u); } @@ -40,19 +40,40 @@ class InstructionSet { public: InstructionSet() { // Define each instruction in this list. - Add(Instruction("node", jtl::NAVIGATE, Arguments(Hash))); + // Note: + // - Instructions ending in "hash" will write their 'HashString' arguments + // directly into the byte-code. + // - Instructions ending in "hashed" will first hash their 'String' + // arguments, and will write this hash to the byte-code. + Add(Instruction("go", jtl::NAVIGATE, Arguments(String))); Add(Instruction("any", jtl::NAVIGATE_ANY, Arguments())); Add(Instruction("back", jtl::NAVIGATE_BACK, Arguments())); - Add(Instruction("store_bool", jtl::STORE_BOOL, Arguments(Hash, Bool))); + Add(Instruction("store_bool", jtl::STORE_BOOL, Arguments(String, Bool))); + Add(Instruction("store_hash", + jtl::STORE_HASH, Arguments(String, HashString))); + Add(Instruction("store_hashed", + jtl::STORE_HASH, Arguments(String, String))); + Add(Instruction("store_node_bool", + jtl::STORE_NODE_BOOL, Arguments(String))); + Add(Instruction("store_node_hash", + jtl::STORE_NODE_HASH, Arguments(String))); + Add(Instruction("compare_bool", jtl::COMPARE_NODE_BOOL, Arguments(Bool))); + Add(Instruction("compare_hashed", + jtl::COMPARE_NODE_HASH, Arguments(String))); + Add(Instruction("compare_hashed_not", + jtl::COMPARE_NODE_HASH_NOT, Arguments(String))); Add(Instruction("compare_stored_bool", jtl::COMPARE_STORED_BOOL, - Arguments(Hash, Bool, Bool))); - Add(Instruction("store_hash", jtl::STORE_HASH, Arguments(Hash, Hash))); - Add(Instruction("compare_stored_hash", + Arguments(String, Bool, Bool))); + Add(Instruction("compare_stored_hashed", jtl::COMPARE_STORED_HASH, - Arguments(Hash, Hash, Hash))); - Add(Instruction("compare_bool", jtl::COMPARE_NODE_BOOL, Arguments(Bool))); - Add(Instruction("compare_hash", jtl::COMPARE_NODE_HASH, Arguments(Hash))); + Arguments(String, String, String))); + Add(Instruction("compare_to_stored_bool", + jtl::COMPARE_NODE_TO_STORED_BOOL, + Arguments(String))); + Add(Instruction("compare_to_stored_hash", + jtl::COMPARE_NODE_TO_STORED_HASH, + Arguments(String))); Add(Instruction("break", jtl::STOP_EXECUTING_SENTENCE, Arguments())); } @@ -77,13 +98,21 @@ class InstructionSet { target->WriteBool(value); break; } - case Hash: { + case String: { std::string value; if (!arguments.GetString(i, &value)) return JtlCompiler::CompileError::INVALID_ARGUMENT_TYPE; target->WriteHash(hasher.GetHash(value)); break; } + case HashString: { + std::string hash_value; + if (!arguments.GetString(i, &hash_value) || + !jtl::Hasher::IsHash(hash_value)) + return JtlCompiler::CompileError::INVALID_ARGUMENT_TYPE; + target->WriteHash(hash_value); + break; + } default: NOTREACHED(); return JtlCompiler::CompileError::INVALID_ARGUMENT_TYPE; @@ -99,7 +128,8 @@ class InstructionSet { enum ArgumentType { None, Bool, - Hash + String, + HashString }; // Encapsulates meta-data about one instruction. diff --git a/chrome/tools/profile_reset/jtl_compiler.h b/chrome/tools/profile_reset/jtl_compiler.h index fe3a68d..e5630360 100644 --- a/chrome/tools/profile_reset/jtl_compiler.h +++ b/chrome/tools/profile_reset/jtl_compiler.h @@ -16,7 +16,7 @@ // // The text-based JTL syntax itself much resembles C/C++. A program consists of // zero or more sentences. Each sentence is terminated by a semi-colon (;), and -// is composed of *one* or more operations, separated by forward slashes (/). +// is composed of *one* or more operations, separated by periods (.). // // Each operation resembles a C/C++ function call and consists of an instruction // name, and an optional argument list, which takes Boolean values and/or string @@ -28,10 +28,10 @@ // Example source code: // // // Store "x"=true if path "foo.bar" is found. -// node("foo")/node("bar")/store_bool("x", true); +// go("foo").go("bar").store_bool("x", true); // // // Store "y"="1" if the above value is set. -// compare_stored_bool("x", true, false)/store_hash("y", "1"); +// compare_stored_bool("x", true, false).store_hash("y", "1"); // class JtlCompiler { public: diff --git a/chrome/tools/profile_reset/jtl_compiler_unittest.cc b/chrome/tools/profile_reset/jtl_compiler_unittest.cc index 2eb1d61..6b83774 100644 --- a/chrome/tools/profile_reset/jtl_compiler_unittest.cc +++ b/chrome/tools/profile_reset/jtl_compiler_unittest.cc @@ -33,25 +33,36 @@ TEST(JtlCompiler, CompileSingleInstructions) { std::string source_code; std::string expected_bytecode; } cases[] = { - {"node(\"foo\")/", OP_NAVIGATE(GetHash("foo"))}, - {"node(\"has whitespace\t\")/", + {"go(\"foo\").", OP_NAVIGATE(GetHash("foo"))}, + {"go(\"has whitespace\t\").", OP_NAVIGATE(GetHash("has whitespace\t"))}, - {"any/", OP_NAVIGATE_ANY}, - {"back/", OP_NAVIGATE_BACK}, - {"store_bool(\"name\", true)/", + {"any.", OP_NAVIGATE_ANY}, + {"back.", OP_NAVIGATE_BACK}, + {"store_bool(\"name\", true).", OP_STORE_BOOL(GetHash("name"), VALUE_TRUE)}, - {"compare_stored_bool(\"name\", true, false)/", + {"compare_stored_bool(\"name\", true, false).", OP_COMPARE_STORED_BOOL(GetHash("name"), VALUE_TRUE, VALUE_FALSE)}, - {"store_hash(\"name\", \"value\")/", + {"store_hash(\"name\", \"" + GetHash("value") + "\").", OP_STORE_HASH(GetHash("name"), GetHash("value"))}, - {"compare_stored_hash(\"name\", \"value\", \"default\")/", + {"store_hashed(\"name\", \"value\").", + OP_STORE_HASH(GetHash("name"), GetHash("value"))}, + {"store_node_bool(\"name\").", + OP_STORE_NODE_BOOL(GetHash("name"))}, + {"store_node_hash(\"name\").", + OP_STORE_NODE_HASH(GetHash("name"))}, + {"compare_stored_hashed(\"name\", \"value\", \"default\").", OP_COMPARE_STORED_HASH( GetHash("name"), GetHash("value"), GetHash("default"))}, - {"compare_bool(false)/", OP_COMPARE_NODE_BOOL(VALUE_FALSE)}, - {"compare_bool(true)/", OP_COMPARE_NODE_BOOL(VALUE_TRUE)}, - {"compare_hash(\"foo\")/", OP_COMPARE_NODE_HASH(GetHash("foo"))}, - {"compare_hash(\"bar\")/", OP_COMPARE_NODE_HASH(GetHash("bar"))}, - {"break/", OP_STOP_EXECUTING_SENTENCE}, + {"compare_bool(false).", OP_COMPARE_NODE_BOOL(VALUE_FALSE)}, + {"compare_bool(true).", OP_COMPARE_NODE_BOOL(VALUE_TRUE)}, + {"compare_hashed(\"foo\").", OP_COMPARE_NODE_HASH(GetHash("foo"))}, + {"compare_hashed_not(\"foo\").", + OP_COMPARE_NODE_HASH_NOT(GetHash("foo"))}, + {"compare_to_stored_bool(\"name\").", + OP_COMPARE_NODE_TO_STORED_BOOL(GetHash("name"))}, + {"compare_to_stored_hash(\"name\").", + OP_COMPARE_NODE_TO_STORED_HASH(GetHash("name"))}, + {"break.", OP_STOP_EXECUTING_SENTENCE}, {"break;", OP_STOP_EXECUTING_SENTENCE + OP_END_OF_SENTENCE}}; for (size_t i = 0; i < ARRAYSIZE_UNSAFE(cases); ++i) { @@ -66,10 +77,10 @@ TEST(JtlCompiler, CompileSingleInstructions) { TEST(JtlCompiler, CompileEntireProgram) { const char kSourceCode[] = "// Store \"x\"=true if path is found.\n" - "node(\"foo\")/node(\"bar\")/store_bool(\"x\", true);\n" + "go(\"foo\").go(\"bar\").store_bool(\"x\", true);\n" "// ...\n" "// Store \"y\"=\"1\" if above value is set.\n" - "compare_stored_bool(\"x\", true, false)/store_hash(\"y\", \"1\");\n"; + "compare_stored_bool(\"x\", true, false).store_hashed(\"y\", \"1\");\n"; std::string expected_bytecode = OP_NAVIGATE(GetHash("foo")) + @@ -85,7 +96,7 @@ TEST(JtlCompiler, CompileEntireProgram) { } TEST(JtlCompiler, InvalidOperationName) { - const char kSourceCode[] = "any()\n/\nnon_existent_instruction\n(\n)\n;\n"; + const char kSourceCode[] = "any()\n.\nnon_existent_instruction\n(\n)\n;\n"; std::string bytecode; JtlCompiler::CompileError error; @@ -99,8 +110,8 @@ TEST(JtlCompiler, InvalidOperationName) { TEST(JtlCompiler, InvalidArgumentsCount) { const char* kSourceCodes[] = { - "any()/\nstore_bool(\"name\", true, \"superfluous argument\");\n", - "any()/\nstore_bool(\"name\");"}; // missing argument + "any().\nstore_bool(\"name\", true, \"superfluous argument\");\n", + "any().\nstore_bool(\"name\");"}; // missing argument for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kSourceCodes); ++i) { SCOPED_TRACE(kSourceCodes[i]); @@ -116,19 +127,29 @@ TEST(JtlCompiler, InvalidArgumentsCount) { } TEST(JtlCompiler, InvalidArgumentType) { - const char* kSourceCodes[] = { - "any()\n/\ncompare_stored_bool(true, false, false);", // Arg#1 should be - // a hash. - "any()\n/\ncompare_stored_bool(\"name\", \"should be a bool\", false);", - "any()\n/\ncompare_stored_bool(\"name\", false, \"should be a bool\");"}; + struct TestCase { + std::string expected_context_prefix; + std::string source_code; + } cases[] = { + {"compare_bool", "any()\n.\ncompare_bool(\"foo\");"}, + {"compare_bool", + "any()\n.\ncompare_bool(\"01234567890123456789012345678901\");"}, + {"compare_hashed", "any()\n.\ncompare_hashed(false);"}, + {"store_hash", "any()\n.\nstore_hash(\"name\", false);"}, + {"store_hash", "any()\n.\nstore_hash(\"name\", \"foo\");"}, + {"compare_stored_bool", + "any()\n.\ncompare_stored_bool(\"name\", \"need a bool\", false);"}, + {"compare_stored_bool", + "any()\n.\ncompare_stored_bool(\"name\", false, \"need a bool\");"}}; - for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kSourceCodes); ++i) { - SCOPED_TRACE(kSourceCodes[i]); + for (size_t i = 0; i < ARRAYSIZE_UNSAFE(cases); ++i) { + SCOPED_TRACE(cases[i].source_code); std::string bytecode; JtlCompiler::CompileError error; EXPECT_FALSE(JtlCompiler::Compile( - kSourceCodes[i], kTestHashSeed, &bytecode, &error)); - EXPECT_THAT(error.context, testing::StartsWith("compare_stored_bool")); + cases[i].source_code, kTestHashSeed, &bytecode, &error)); + EXPECT_THAT(error.context, + testing::StartsWith(cases[i].expected_context_prefix)); EXPECT_EQ(2u, error.line_number); EXPECT_EQ(JtlCompiler::CompileError::INVALID_ARGUMENT_TYPE, error.error_code); @@ -136,7 +157,7 @@ TEST(JtlCompiler, InvalidArgumentType) { } TEST(JtlCompiler, MistmatchedDoubleQuotes) { - const char kSourceCode[] = "any()/\nnode(\"ok\", \"stray quote)/break();"; + const char kSourceCode[] = "any().\ngo(\"ok\", \"stray quote).break();"; std::string bytecode; JtlCompiler::CompileError error; @@ -148,13 +169,13 @@ TEST(JtlCompiler, MistmatchedDoubleQuotes) { } TEST(JtlCompiler, ParsingError) { - const char kSourceCode[] = "any()/\nnode()missing_separator();"; + const char kSourceCode[] = "any().\ngo()missing_separator();"; std::string bytecode; JtlCompiler::CompileError error; EXPECT_FALSE( JtlCompiler::Compile(kSourceCode, kTestHashSeed, &bytecode, &error)); - EXPECT_THAT(error.context, testing::StartsWith("node")); + EXPECT_THAT(error.context, testing::StartsWith("go")); EXPECT_EQ(1u, error.line_number); EXPECT_EQ(JtlCompiler::CompileError::PARSING_ERROR, error.error_code); } diff --git a/chrome/tools/profile_reset/jtl_parser.cc b/chrome/tools/profile_reset/jtl_parser.cc index 9a4e1d2..9c9bdbb 100644 --- a/chrome/tools/profile_reset/jtl_parser.cc +++ b/chrome/tools/profile_reset/jtl_parser.cc @@ -50,7 +50,7 @@ const char kMaybeArgumentListRE[] = "(?:\\(" // Opening parenthesis. "((?:\"[^\"]*\"|[^\")])*)" // Capture: anything inside, quote-aware. "\\))?"; // Closing parenthesis + everything optional. -const char kOperationSeparatorRE[] = "(;|/)"; +const char kOperationSeparatorRE[] = "(;|\\.)"; } // namespace diff --git a/chrome/tools/profile_reset/jtl_parser_unittest.cc b/chrome/tools/profile_reset/jtl_parser_unittest.cc index 58ee3d6..1868df8 100644 --- a/chrome/tools/profile_reset/jtl_parser_unittest.cc +++ b/chrome/tools/profile_reset/jtl_parser_unittest.cc @@ -215,12 +215,12 @@ TEST(JtlParser, ParsingOneWellFormedOperation) { const bool expected_ends_sentence; } cases[] = { {"foo1;", "foo1", "[]", true}, - {"foo2()/", "foo2", "[]", false}, + {"foo2().", "foo2", "[]", false}, {"foo3(true);", "foo3", "[true]", true}, - {"foo4(false)/", "foo4", "[false]", false}, - {"foo5(\"bar\")/", "foo5", "[\"bar\"]", false}, - {"foo6(\" b a r \")/", "foo6", "[\" b a r \"]", false}, - {"foo7(true, \"bar\")/", "foo7", "[true,\"bar\"]", false}, + {"foo4(false).", "foo4", "[false]", false}, + {"foo5(\"bar\").", "foo5", "[\"bar\"]", false}, + {"foo6(\" b a r \").", "foo6", "[\" b a r \"]", false}, + {"foo7(true, \"bar\").", "foo7", "[true,\"bar\"]", false}, {"foo8(\"bar\", false, true);", "foo8", "[\"bar\",false,true]", true}, {"foo9(\"bar\", \" b a r \");", "foo9", "[\"bar\",\" b a r \"]", true} }; @@ -239,7 +239,7 @@ TEST(JtlParser, ParsingOneWellFormedOperation) { TEST(JtlParser, ParsingMultipleWellFormedOperations) { const char kSourceCode[] = - "foo1(true)/foo2/foo3(\"bar\");" + "foo1(true).foo2.foo3(\"bar\");" "foo4(\"bar\", false);"; scoped_ptr<JtlParser> parser(CreateParserFromVerboseText(kSourceCode)); @@ -257,13 +257,14 @@ TEST(JtlParser, ParsingTrickyStringLiterals) { const char* expected_args; const bool expected_ends_sentence; } cases[] = { - {"prev()/foo1(\"\");next(true);", "foo1", "[\"\"]", true}, - {"prev()/foo2(\" \");next(true);", "foo2", "[\" \"]", true}, - {"prev()/foo3(\",\",true);next(true);", "foo3", "[\",\",true]", true}, - {"prev()/foo4(\")\",true);next(true);", "foo4", "[\")\",true]", true}, - {"prev()/foo5(\";\",true);next(true);", "foo5", "[\";\",true]", true}, - {"prev()/foo6(\"/\",true)/next(true);", "foo6", "[\"/\",true]", false}, - {"prev()/foo7(\"//\",true)/next(true);", "foo7", "[\"//\",true]", false}, + {"prev().foo1(\"\");next(true);", "foo1", "[\"\"]", true}, + {"prev().foo2(\" \");next(true);", "foo2", "[\" \"]", true}, + {"prev().foo3(\",\",true);next(true);", "foo3", "[\",\",true]", true}, + {"prev().foo4(\")\",true);next(true);", "foo4", "[\")\",true]", true}, + {"prev().foo5(\";\",true);next(true);", "foo5", "[\";\",true]", true}, + {"prev().foo6(\"/\",true).next(true);", "foo6", "[\"/\",true]", false}, + {"prev().foo7(\"//\",true).next(true);", "foo7", "[\"//\",true]", false}, + {"prev().foo8(\".\",true).next(true);", "foo8", "[\".\",true]", false}, }; for (size_t i = 0; i < ARRAYSIZE_UNSAFE(cases); ++i) { @@ -294,14 +295,14 @@ TEST(JtlParser, FirstOperationIsIllFormed) { {"bad_args6([\"bar\"]);", "bad_args6"}, {"bad_args7(False);", "bad_args7"}, {"bad_args8(True);", "bad_args8"}, - {"bad_quotes1(missing both, true)/good();", "bad_quotes1"}, - {"bad_quotes2(true, \"missing one)/good(); //\"", "bad_quotes2"}, - {"bad_quotes3(\"too\" \"much\", true)/good();", "bad_quotes3"}, + {"bad_quotes1(missing both, true).good();", "bad_quotes1"}, + {"bad_quotes2(true, \"missing one).good(); //\"", "bad_quotes2"}, + {"bad_quotes3(\"too\" \"much\", true).good();", "bad_quotes3"}, {"bad_missing_separator1", "bad_missing_separator1"}, {"bad_missing_separator2()good();", "bad_missing_separator2"}, - {"bad_parenthesis1(true/good();", "bad_parenthesis1"}, - {"bad_parenthesis2(true/good());", "bad_parenthesis2"}, - {"bad_parenthesis3)/good();", "bad_parenthesis3"} + {"bad_parenthesis1(true.good();", "bad_parenthesis1"}, + {"bad_parenthesis2(true.good());", "bad_parenthesis2"}, + {"bad_parenthesis3).good();", "bad_parenthesis3"} }; for (size_t i = 0; i < ARRAYSIZE_UNSAFE(cases); ++i) { @@ -317,18 +318,20 @@ TEST(JtlParser, SecondOperationIsIllFormed) { const char* source_code; const char* bad_operation_name; } cases[] = { - {"\ngood(true,false)\n/bad_args(,);", "bad_args"}, - {"\ngood(true,false)\n/bad_quotes1(missing both, true)/good();", + {"\ngood(true,false)\n.bad_args(,);", "bad_args"}, + {"\ngood(true,false)\n.bad_quotes1(missing both, true).good();", "bad_quotes1"}, - {"\ngood(true,false)\n/bad_quotes2(\"missing one, true)/good(); //\"", + {"\ngood(true,false)\n.bad_quotes2(\"missing one, true).good(); //\"", "bad_quotes2"}, - {"\ngood(true,false)\n/bad_quotes3(\"too\" \"many\", true)/good();", + {"\ngood(true,false)\n.bad_quotes3(\"too\" \"many\", true).good();", "bad_quotes3"}, - {"\ngood(true,false)\n/missing_separator1", "missing_separator1"}, - {"\ngood(true,false)\n/missing_separator2()good()", "missing_separator2"}, - {"\ngood(true,false)\n/bad_parens1(true/good();", "bad_parens1"}, - {"\ngood(true,false)\n/bad_parens2(true/good());", "bad_parens2"}, - {"\ngood(true,false)\n/bad_parens3)/good();", "bad_parens3"} + {"\ngood(true,false)\n.bad_separator1()/good();", "bad_separator1"}, + {"\ngood(true,false)\n.missing_separator1", "missing_separator1"}, + {"\ngood(true,false)\n.missing_separator2()good();", + "missing_separator2"}, + {"\ngood(true,false)\n.bad_parens1(true.good();", "bad_parens1"}, + {"\ngood(true,false)\n.bad_parens2(true.good());", "bad_parens2"}, + {"\ngood(true,false)\n.bad_parens3).good();", "bad_parens3"} }; for (size_t i = 0; i < ARRAYSIZE_UNSAFE(cases); ++i) { |