Alexandre Zani | fca71ca | 2015-04-01 07:57:24 -0700 | [diff] [blame] | 1 | // Copyright 2015 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 "base/logging.h" |
| 6 | #include "mojom/lexer.h" |
| 7 | #include "testing/gtest/include/gtest/gtest.h" |
| 8 | |
| 9 | namespace mojo { |
| 10 | namespace mojom { |
| 11 | namespace { |
| 12 | |
| 13 | TEST(LexerTest, AllNonErrorTokens) { |
| 14 | const struct TestData { |
| 15 | const char* name; |
| 16 | const char* source; |
| 17 | mojom::TokenType expected_token; |
| 18 | } test_data[] = { |
| 19 | {"LPAREN", "(", mojom::TokenType::LPAREN}, |
| 20 | {"RPAREN", ")", mojom::TokenType::RPAREN}, |
| 21 | {"LBRACKET", "[", mojom::TokenType::LBRACKET}, |
| 22 | {"RBRACKET", "]", mojom::TokenType::RBRACKET}, |
| 23 | {"LBRACE", "{", mojom::TokenType::LBRACE}, |
| 24 | {"RBRACE", "}", mojom::TokenType::RBRACE}, |
| 25 | {"LANGLE", "<", mojom::TokenType::LANGLE}, |
| 26 | {"RANGLE", ">", mojom::TokenType::RANGLE}, |
| 27 | {"SEMI", ";", mojom::TokenType::SEMI}, |
| 28 | {"COMMA", ",", mojom::TokenType::COMMA}, |
| 29 | {"DOT", ".", mojom::TokenType::DOT}, |
| 30 | {"MINUS", "-", mojom::TokenType::MINUS}, |
| 31 | {"PLUS", "+", mojom::TokenType::PLUS}, |
| 32 | {"AMP", "&", mojom::TokenType::AMP}, |
| 33 | {"QSTN", "?", mojom::TokenType::QSTN}, |
| 34 | {"EQUALS", "=", mojom::TokenType::EQUALS}, |
| 35 | {"RESPONSE", "=>", mojom::TokenType::RESPONSE}, |
| 36 | {"IDENTIFIER", "something", mojom::TokenType::IDENTIFIER}, |
| 37 | {"IMPORT", "import", mojom::TokenType::IMPORT}, |
| 38 | {"MODULE", "module", mojom::TokenType::MODULE}, |
| 39 | {"STRUCT", "struct", mojom::TokenType::STRUCT}, |
| 40 | {"UNION", "union", mojom::TokenType::UNION}, |
| 41 | {"INTERFACE", "interface", mojom::TokenType::INTERFACE}, |
| 42 | {"ENUM", "enum", mojom::TokenType::ENUM}, |
| 43 | {"CONST", "const", mojom::TokenType::CONST}, |
| 44 | {"TRUE", "true", mojom::TokenType::TRUE}, |
| 45 | {"FALSE", "false", mojom::TokenType::FALSE}, |
| 46 | {"DEFAULT", "default", mojom::TokenType::DEFAULT}, |
| 47 | {"INT_CONST_DEC", "10", mojom::TokenType::INT_CONST_DEC}, |
| 48 | {"INT_CONST_DEC_0", "0", mojom::TokenType::INT_CONST_DEC}, |
| 49 | {"FLOAT_CONST", "10.5", mojom::TokenType::FLOAT_CONST}, |
| 50 | {"FLOAT_CONST_E", "10e5", mojom::TokenType::FLOAT_CONST}, |
| 51 | {"FLOAT_CONST_ZERO", "0.5", mojom::TokenType::FLOAT_CONST}, |
| 52 | {"FLOAT_CONST_E_ZERO", "0e5", mojom::TokenType::FLOAT_CONST}, |
| 53 | {"FLOAT_CONST_E_PLUS", "10e+5", mojom::TokenType::FLOAT_CONST}, |
| 54 | {"FLOAT_CONST_E_MINUS", "10e-5", mojom::TokenType::FLOAT_CONST}, |
| 55 | {"INT_CONST_HEX", "0x10A", mojom::TokenType::INT_CONST_HEX}, |
| 56 | {"ORDINAL", "@10", mojom::TokenType::ORDINAL}, |
| 57 | {"STRING_LITERAL", "\"hello world\"", mojom::TokenType::STRING_LITERAL}, |
| 58 | {"STRING_LITERAL_ESCAPE", |
| 59 | "\"hello \\\"world\\\"\"", |
| 60 | mojom::TokenType::STRING_LITERAL}, |
| 61 | {"STRING_LITERAL_HEX_ESCAPE", |
| 62 | "\"hello \\x23 world\"", |
| 63 | mojom::TokenType::STRING_LITERAL}, |
| 64 | }; |
| 65 | for (size_t i = 0; i < arraysize(test_data); i++) { |
| 66 | const char* test_name = test_data[i].name; |
| 67 | const char* source = test_data[i].source; |
| 68 | const mojom::TokenType expected_token = test_data[i].expected_token; |
| 69 | std::vector<mojom::Token> tokens = mojom::Tokenize(source); |
| 70 | DCHECK(tokens.size() >= 1) << "Failure to tokenize at all: " << test_name; |
| 71 | const mojom::Token token = tokens[0]; |
| 72 | EXPECT_EQ(expected_token, token.token_type) |
| 73 | << "Wrong token type: " << test_name; |
| 74 | EXPECT_EQ(source, token.token) << "Wrong token value: " << test_name; |
| 75 | } |
| 76 | } |
| 77 | |
| 78 | TEST(LexerTest, TokenPosition) { |
| 79 | std::string source(" \n ."); |
| 80 | std::vector<mojom::Token> tokens = mojom::Tokenize(source); |
| 81 | const mojom::Token token = tokens[0]; |
| 82 | EXPECT_EQ(mojom::TokenType::DOT, token.token_type); |
| 83 | EXPECT_EQ(".", token.token); |
| 84 | EXPECT_EQ(5U, token.char_pos); |
| 85 | EXPECT_EQ(1U, token.line_no); |
| 86 | EXPECT_EQ(2U, token.line_pos); |
| 87 | } |
| 88 | |
| 89 | TEST(LexerTest, ExhaustedTokens) { |
| 90 | std::string source(""); |
| 91 | std::vector<mojom::Token> tokens = mojom::Tokenize(source); |
| 92 | EXPECT_EQ(0U, tokens.size()); |
| 93 | } |
| 94 | |
| 95 | TEST(LexerTest, SkipSkippable) { |
| 96 | std::string source(" \t \r \n ."); |
| 97 | std::vector<mojom::Token> tokens = mojom::Tokenize(source); |
| 98 | const mojom::Token token = tokens[0]; |
| 99 | EXPECT_EQ(mojom::TokenType::DOT, token.token_type); |
| 100 | EXPECT_EQ(".", token.token); |
| 101 | } |
| 102 | |
| 103 | TEST(LexerTest, SkipToTheEnd) { |
| 104 | std::string source(" \t \r \n "); |
| 105 | std::vector<mojom::Token> tokens = mojom::Tokenize(source); |
| 106 | EXPECT_EQ(0U, tokens.size()); |
| 107 | } |
| 108 | |
| 109 | TEST(LexerTest, TokenizeMoreThanOne) { |
| 110 | std::string source("()"); |
| 111 | std::vector<mojom::Token> tokens = mojom::Tokenize(source); |
| 112 | |
| 113 | EXPECT_EQ(mojom::TokenType::LPAREN, tokens[0].token_type); |
| 114 | EXPECT_EQ(mojom::TokenType::RPAREN, tokens[1].token_type); |
| 115 | EXPECT_EQ(2U, tokens.size()); |
| 116 | } |
| 117 | |
| 118 | TEST(LexerTest, ERROR_ILLEGAL_CHAR) { |
| 119 | std::string source("#"); |
| 120 | std::vector<mojom::Token> tokens = mojom::Tokenize(source); |
| 121 | const mojom::Token token = tokens[0]; |
| 122 | EXPECT_EQ(mojom::TokenType::ERROR_ILLEGAL_CHAR, token.token_type); |
| 123 | EXPECT_EQ("#", token.token); |
| 124 | EXPECT_TRUE(token.error()); |
| 125 | } |
| 126 | |
| 127 | TEST(LexerTest, ERROR_UNTERMINATED_STRING_LITERAL_EOL) { |
| 128 | std::string source("\"Hello \n World\""); |
| 129 | std::vector<mojom::Token> tokens = mojom::Tokenize(source); |
| 130 | const mojom::Token token = tokens[0]; |
| 131 | EXPECT_EQ(mojom::TokenType::ERROR_UNTERMINATED_STRING_LITERAL, |
| 132 | token.token_type); |
| 133 | EXPECT_EQ("\"Hello ", token.token); |
| 134 | EXPECT_EQ(0U, token.char_pos); |
| 135 | EXPECT_TRUE(token.error()); |
| 136 | } |
| 137 | |
| 138 | TEST(LexerTest, ERROR_UNTERMINATED_STRING_LITERAL_EOF) { |
| 139 | std::string source("\"Hello "); |
| 140 | std::vector<mojom::Token> tokens = mojom::Tokenize(source); |
| 141 | const mojom::Token token = tokens[0]; |
| 142 | EXPECT_EQ(mojom::TokenType::ERROR_UNTERMINATED_STRING_LITERAL, |
| 143 | token.token_type); |
| 144 | EXPECT_EQ("\"Hello ", token.token); |
| 145 | EXPECT_EQ(0U, token.char_pos); |
| 146 | EXPECT_TRUE(token.error()); |
| 147 | } |
| 148 | |
| 149 | TEST(LexerTest, ERROR_UNTERMINATED_STRING_LITERAL_ESC_EOF) { |
| 150 | std::string source("\"Hello \\"); |
| 151 | std::vector<mojom::Token> tokens = mojom::Tokenize(source); |
| 152 | const mojom::Token token = tokens[0]; |
| 153 | EXPECT_EQ(mojom::TokenType::ERROR_UNTERMINATED_STRING_LITERAL, |
| 154 | token.token_type); |
| 155 | EXPECT_EQ("\"Hello \\", token.token); |
| 156 | EXPECT_EQ(0U, token.char_pos); |
| 157 | EXPECT_TRUE(token.error()); |
| 158 | } |
| 159 | |
| 160 | } // namespace |
| 161 | } // namespace mojom |
| 162 | } // namespace mojo |