#include #include namespace { using namespace testing; using namespace fx::Lexer; struct LexerTest : Test { }; struct LexerSingleTokenTest : Test { template void test() { const std::string content = std::string(Token::repr); Lexer lexer(content); EXPECT_TRUE(std::holds_alternative(lexer.next())); } }; TEST_F(LexerSingleTokenTest, single_token_shared) { test(); } TEST_F(LexerSingleTokenTest, single_token_technique) { test(); } TEST_F(LexerSingleTokenTest, single_token_render_target) { test(); } TEST_F(LexerSingleTokenTest, single_token_vertex) { test(); } TEST_F(LexerSingleTokenTest, single_token_fragment) { test(); } TEST_F(LexerSingleTokenTest, single_token_compute) { test(); } TEST_F(LexerSingleTokenTest, single_token_sampler_1d) { test(); } TEST_F(LexerSingleTokenTest, single_token_sampler_2d) { test(); } TEST_F(LexerSingleTokenTest, single_token_sampler_3d) { test(); } TEST_F(LexerSingleTokenTest, single_token_true) { test(); } TEST_F(LexerSingleTokenTest, single_token_false) { test(); } TEST_F(LexerSingleTokenTest, single_token_vec2) { test(); } TEST_F(LexerSingleTokenTest, single_token_vec3) { test(); } TEST_F(LexerSingleTokenTest, single_token_vec4) { test(); } TEST(LexerTest, peek_whitespace_only_content_should_be_eof) { Lexer lexer(R"( )"); EXPECT_TRUE(std::holds_alternative(lexer.peek())); } TEST(LexerTest, float_with_no_prefixed_digits) { Lexer lexer(R"( 0.123; )"); auto token = lexer.next(); EXPECT_TRUE(std::holds_alternative(token)); EXPECT_FLOAT_EQ(std::get(token).value, 0.123f); } TEST(LexerTest, float_with_alpha_prefix) { Lexer lexer(R"( abc.123; )"); EXPECT_TRUE(std::holds_alternative(lexer.next())); auto token = lexer.next(); EXPECT_TRUE(std::holds_alternative(token)); EXPECT_FLOAT_EQ(std::get(token).value, 0.123f); } TEST(LexerTest, float_with_numeric_prefix) { Lexer lexer(R"( 123.123; )"); auto token = lexer.next(); EXPECT_TRUE(std::holds_alternative(token)); EXPECT_FLOAT_EQ(std::get(token).value, 123.123f); } TEST(LexerTest, int_should_not_be_float) { Lexer lexer(R"( 123 )"); auto token = lexer.next(); EXPECT_TRUE(std::holds_alternative(token)); EXPECT_EQ(std::get(token).value, 123); } TEST(LexerTest, simple_string) { Lexer lexer(R"( "test string" )"); auto token = lexer.next(); EXPECT_TRUE(std::holds_alternative(token)); std::string parsed = std::string(std::get(token).value); EXPECT_EQ("test string", parsed); } TEST(LexerTest, fail_on_unterminated_double_quotes) { Lexer lexer(R"( "unterminated string' )"); EXPECT_THROW(lexer.next(), LexerException); } TEST(LexerTest, multiline_strings_with_single_quotes) { Lexer lexer(R"( "string that is on multiple with 'single quotes' and correctly terminated!" )"); auto token = lexer.next(); EXPECT_TRUE(std::holds_alternative(token)); } TEST(LexerTest, fail_on_unterminated_double_quotes_with_multiline_strings) { Lexer lexer(R"( "string that is on multiple with 'single quotes' and but is unterminated :( )"); EXPECT_THROW(lexer.next(), LexerException); } TEST(LexerTest, jump_with_single_nested_bracket) { const std::string content = R"( #version 120 void main() { return 0; }})"; const std::string expected = content.substr(0, content.size() - 1); Lexer lexer(content); auto block = lexer.jump(); EXPECT_NE(block, std::nullopt); EXPECT_EQ(expected, std::string(block.value())); } TEST(LexerTest, jump_with_single_line_comments_and_mismatching_brackets) { const std::string content = R"( #version 120 void main() { // } return 0; }})"; const std::string expected = content.substr(0, content.size() - 1); Lexer lexer(content); auto block = lexer.jump(); EXPECT_NE(block, std::nullopt); EXPECT_EQ(expected, std::string(block.value())); } TEST(LexerTest, jump_with_multi_line_comments_and_mismatching_brackets) { const std::string content = R"( #version 120 void main() { /* } */ return 0; }})"; const std::string expected = content.substr(0, content.size() - 1); Lexer lexer(content); auto block = lexer.jump(); EXPECT_NE(block, std::nullopt); EXPECT_EQ(expected, std::string(block.value())); } TEST(LexerTest, immediate_closed_blocks) { Lexer lexer(R"(block{})"); EXPECT_TRUE(std::holds_alternative(lexer.next())); EXPECT_TRUE(std::holds_alternative(lexer.next())); auto block = lexer.jump(); EXPECT_TRUE(block.has_value()); EXPECT_TRUE(block.value().empty()); EXPECT_TRUE(std::holds_alternative(lexer.next())); } }