| // Copyright 2017-2020 The Verible Authors. | |
| // | |
| // Licensed under the Apache License, Version 2.0 (the "License"); | |
| // you may not use this file except in compliance with the License. | |
| // You may obtain a copy of the License at | |
| // | |
| // http://www.apache.org/licenses/LICENSE-2.0 | |
| // | |
| // Unless required by applicable law or agreed to in writing, software | |
| // distributed under the License is distributed on an "AS IS" BASIS, | |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
| // See the License for the specific language governing permissions and | |
| // limitations under the License. | |
| #include "common/text/token_info_test_util.h" | |
| #include <vector> | |
| #include "absl/strings/string_view.h" | |
| #include "common/text/token_info.h" | |
| #include "common/util/logging.h" | |
| #include "gtest/gtest.h" | |
| namespace verible { | |
| namespace { | |
| TEST(TokenInfoTestDataTest, EmptyInitializer) { | |
| const TokenInfoTestData test_data{}; | |
| EXPECT_TRUE(test_data.code.empty()); | |
| EXPECT_TRUE(test_data.expected_tokens.empty()); | |
| } | |
| TEST(TokenInfoTestDataTest, ConstructorStringLiteral) { | |
| const TokenInfoTestData test_data = { | |
| {"foo"}, | |
| {"bar"}, | |
| }; | |
| EXPECT_EQ(test_data.code, "foobar"); | |
| const auto& first(test_data.expected_tokens.front()); | |
| EXPECT_EQ(first.text(), "foo"); | |
| EXPECT_EQ(first.token_enum(), ExpectedTokenInfo::kDontCare); | |
| EXPECT_EQ(first.left(test_data.code), 0); | |
| EXPECT_EQ(first.right(test_data.code), 3); | |
| const auto& second(test_data.expected_tokens.back()); | |
| EXPECT_EQ(second.text(), "bar"); | |
| EXPECT_EQ(second.token_enum(), ExpectedTokenInfo::kDontCare); | |
| EXPECT_EQ(second.left(test_data.code), 3); | |
| EXPECT_EQ(second.right(test_data.code), 6); | |
| } | |
| TEST(ExpectedTokenInfoTest, ConstructorCharEnum) { | |
| ExpectedTokenInfo token(';'); | |
| EXPECT_EQ(token.token_enum(), ';'); | |
| EXPECT_EQ(token.text(), ";"); | |
| EXPECT_EQ(token.left(token.text()), 0); | |
| EXPECT_EQ(token.right(token.text()), 1); | |
| } | |
| TEST(TokenInfoTestDataTest, ConstructorCharEnum) { | |
| const TokenInfoTestData test_data = { | |
| {'('}, | |
| {')'}, | |
| }; | |
| EXPECT_EQ(test_data.code, "()"); | |
| const auto& first(test_data.expected_tokens.front()); | |
| EXPECT_EQ(first.text(), "("); | |
| EXPECT_EQ(first.token_enum(), '('); | |
| EXPECT_EQ(first.left(test_data.code), 0); | |
| EXPECT_EQ(first.right(test_data.code), 1); | |
| const auto& second(test_data.expected_tokens.back()); | |
| EXPECT_EQ(second.text(), ")"); | |
| EXPECT_EQ(second.token_enum(), ')'); | |
| EXPECT_EQ(second.left(test_data.code), 1); | |
| EXPECT_EQ(second.right(test_data.code), 2); | |
| } | |
| TEST(ExpectedTokenInfoTest, ConstructorEnumAndStringLiteral) { | |
| ExpectedTokenInfo token(11, "f00"); | |
| EXPECT_EQ(token.token_enum(), 11); | |
| EXPECT_EQ(token.text(), "f00"); | |
| } | |
| TEST(TokenInfoTestDataTest, ConstructorEnumAndStringLiteral) { | |
| const TokenInfoTestData test_data = { | |
| {8, "foo"}, | |
| {7, "bar"}, | |
| }; | |
| EXPECT_EQ(test_data.code, "foobar"); | |
| const auto& first(test_data.expected_tokens.front()); | |
| EXPECT_EQ(first.text(), "foo"); | |
| EXPECT_EQ(first.token_enum(), 8); | |
| EXPECT_EQ(first.left(test_data.code), 0); | |
| EXPECT_EQ(first.right(test_data.code), 3); | |
| const auto& second(test_data.expected_tokens.back()); | |
| EXPECT_EQ(second.text(), "bar"); | |
| EXPECT_EQ(second.token_enum(), 7); | |
| EXPECT_EQ(second.left(test_data.code), 3); | |
| EXPECT_EQ(second.right(test_data.code), 6); | |
| } | |
| TEST(TokenInfoTestDataTest, ConstructorHeterogeneousInitializer) { | |
| // This example best represents a typical lexer test case that verifies a | |
| // sequence of tokens. The token enumeration values would realistically be | |
| // written as enumeration values generated by yacc/bison. | |
| const TokenInfoTestData test_data = {{8, "foo"}, " ", '(', {7, "bar"}, ')'}; | |
| EXPECT_EQ(test_data.code, "foo (bar)"); | |
| const auto& expected_tokens = test_data.expected_tokens; | |
| ASSERT_EQ(expected_tokens.size(), 5); | |
| EXPECT_EQ(expected_tokens[0].text(), "foo"); | |
| EXPECT_EQ(expected_tokens[0].token_enum(), 8); | |
| EXPECT_EQ(expected_tokens[0].left(test_data.code), 0); | |
| EXPECT_EQ(expected_tokens[0].right(test_data.code), 3); | |
| EXPECT_EQ(expected_tokens[1].text(), " "); | |
| EXPECT_EQ(expected_tokens[1].token_enum(), ExpectedTokenInfo::kDontCare); | |
| EXPECT_EQ(expected_tokens[1].left(test_data.code), 3); | |
| EXPECT_EQ(expected_tokens[1].right(test_data.code), 4); | |
| EXPECT_EQ(expected_tokens[2].text(), "("); | |
| EXPECT_EQ(expected_tokens[2].token_enum(), '('); | |
| EXPECT_EQ(expected_tokens[2].left(test_data.code), 4); | |
| EXPECT_EQ(expected_tokens[2].right(test_data.code), 5); | |
| EXPECT_EQ(expected_tokens[3].text(), "bar"); | |
| EXPECT_EQ(expected_tokens[3].token_enum(), 7); | |
| EXPECT_EQ(expected_tokens[3].left(test_data.code), 5); | |
| EXPECT_EQ(expected_tokens[3].right(test_data.code), 8); | |
| EXPECT_EQ(expected_tokens[4].text(), ")"); | |
| EXPECT_EQ(expected_tokens[4].token_enum(), ')'); | |
| EXPECT_EQ(expected_tokens[4].left(test_data.code), 8); | |
| EXPECT_EQ(expected_tokens[4].right(test_data.code), 9); | |
| } | |
| TEST(TokenInfoTestDataTest, FindImportantTokensTest) { | |
| // This example best represents a typical lexer test case that verifies a | |
| // sequence of tokens. The token enumeration values would realistically be | |
| // written as enumeration values generated by yacc/bison. | |
| const TokenInfoTestData test_data = { | |
| {8, "foo"}, " ", '(', {7, "bar"}, " ", "/* comment */", ')', | |
| }; | |
| EXPECT_EQ(test_data.code, "foo (bar /* comment */)"); | |
| const auto& expected_tokens = test_data.expected_tokens; | |
| EXPECT_EQ(expected_tokens.size(), 7); | |
| const auto key_tokens = test_data.FindImportantTokens(); | |
| EXPECT_EQ(key_tokens.size(), 4); | |
| EXPECT_EQ(key_tokens[0].text(), "foo"); | |
| EXPECT_EQ(key_tokens[0].token_enum(), 8); | |
| EXPECT_EQ(key_tokens[0].left(test_data.code), 0); | |
| EXPECT_EQ(key_tokens[0].right(test_data.code), 3); | |
| EXPECT_EQ(key_tokens[1].text(), "("); | |
| EXPECT_EQ(key_tokens[1].token_enum(), '('); | |
| EXPECT_EQ(key_tokens[1].left(test_data.code), 4); | |
| EXPECT_EQ(key_tokens[1].right(test_data.code), 5); | |
| EXPECT_EQ(key_tokens[2].text(), "bar"); | |
| EXPECT_EQ(key_tokens[2].token_enum(), 7); | |
| EXPECT_EQ(key_tokens[2].left(test_data.code), 5); | |
| EXPECT_EQ(key_tokens[2].right(test_data.code), 8); | |
| EXPECT_EQ(key_tokens[3].text(), ")"); | |
| EXPECT_EQ(key_tokens[3].token_enum(), ')'); | |
| EXPECT_EQ(key_tokens[3].left(test_data.code), 22); | |
| EXPECT_EQ(key_tokens[3].right(test_data.code), 23); | |
| } | |
| TEST(TokenInfoTestDataTest, RebaseToCodeCopyEmpty) { | |
| std::vector<TokenInfo> tokens; | |
| const TokenInfoTestData test_data{}; | |
| constexpr absl::string_view other_text(""); | |
| EXPECT_EQ(test_data.code, other_text); | |
| test_data.RebaseToCodeCopy(&tokens, other_text); | |
| EXPECT_TRUE(tokens.empty()); | |
| } | |
| TEST(TokenInfoTestDataTest, RebaseToCodeCopyMoved) { | |
| const TokenInfoTestData test_data{ | |
| {3, "text"}, | |
| {4, "book"}, | |
| }; | |
| constexpr absl::string_view other_text("textbook"); // separate copy | |
| std::vector<TokenInfo> tokens = test_data.expected_tokens; // copy | |
| EXPECT_EQ(test_data.code, other_text); | |
| EXPECT_EQ(tokens.size(), 2); | |
| EXPECT_EQ(tokens[0].left(test_data.code), 0); | |
| EXPECT_EQ(tokens[0].right(test_data.code), 4); | |
| EXPECT_EQ(tokens[1].left(test_data.code), 4); | |
| EXPECT_EQ(tokens[1].right(test_data.code), 8); | |
| test_data.RebaseToCodeCopy(&tokens, other_text); | |
| // Note: expected locations are now based off of other_text. | |
| EXPECT_EQ(tokens[0].text(), "text"); | |
| EXPECT_EQ(tokens[0].token_enum(), 3); | |
| EXPECT_EQ(tokens[0].left(other_text), 0); | |
| EXPECT_EQ(tokens[0].right(other_text), 4); | |
| EXPECT_EQ(tokens[1].text(), "book"); | |
| EXPECT_EQ(tokens[1].token_enum(), 4); | |
| EXPECT_EQ(tokens[1].left(other_text), 4); | |
| EXPECT_EQ(tokens[1].right(other_text), 8); | |
| } | |
| TEST(TokenInfoTestDataTest, FindImportantTokensRebased) { | |
| const TokenInfoTestData test_data{ | |
| {3, "text"}, | |
| {4, "book"}, | |
| }; | |
| constexpr absl::string_view other_text("textbook"); // separate copy | |
| std::vector<TokenInfo> tokens = test_data.FindImportantTokens(other_text); | |
| EXPECT_EQ(test_data.code, other_text); | |
| EXPECT_EQ(tokens.size(), 2); | |
| // Note: expected locations are now based off of other_text. | |
| EXPECT_EQ(tokens[0].text(), "text"); | |
| EXPECT_EQ(tokens[0].token_enum(), 3); | |
| EXPECT_EQ(tokens[0].left(other_text), 0); | |
| EXPECT_EQ(tokens[0].right(other_text), 4); | |
| EXPECT_EQ(tokens[1].text(), "book"); | |
| EXPECT_EQ(tokens[1].token_enum(), 4); | |
| EXPECT_EQ(tokens[1].left(other_text), 4); | |
| EXPECT_EQ(tokens[1].right(other_text), 8); | |
| } | |
| } // namespace | |
| } // namespace verible |