// Part of the Carbon Language project, under the Apache License v2.0 with LLVM // Exceptions. See /LICENSE for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception #include "explorer/ast/ast_test_matchers.h" #include #include #include "explorer/ast/declaration.h" #include "explorer/ast/expression.h" #include "explorer/ast/pattern.h" #include "explorer/ast/statement.h" #include "explorer/base/arena.h" namespace Carbon { namespace { using ::testing::_; using ::testing::ElementsAre; using ::testing::IsEmpty; using ::testing::Not; static constexpr SourceLocation DummyLoc("dummy", 0, FileKind::Main); TEST(ASTTestMatchers, BlockContentsAreTest) { Block empty_block(DummyLoc, {}); EXPECT_THAT(empty_block, BlockContentsAre(IsEmpty())); EXPECT_THAT(&empty_block, BlockContentsAre(IsEmpty())); Break break_node(DummyLoc); EXPECT_THAT(break_node, Not(BlockContentsAre(_))); Block break_block(DummyLoc, {&break_node}); EXPECT_THAT(break_block, Not(BlockContentsAre(IsEmpty()))); } TEST(ASTTestMatchers, MatchesLiteralTest) { IntLiteral literal(DummyLoc, 42); EXPECT_THAT(literal, MatchesLiteral(42)); EXPECT_THAT(&literal, MatchesLiteral(42)); EXPECT_THAT(literal, Not(MatchesLiteral(43))); EXPECT_THAT(StringLiteral(DummyLoc, "foo"), Not(MatchesLiteral(42))); } TEST(ASTTestMatchers, MatchesMulTest) { IntLiteral two(DummyLoc, 2); IntLiteral three(DummyLoc, 3); OperatorExpression mul(DummyLoc, Operator::Mul, {&two, &three}); EXPECT_THAT(mul, MatchesMul(MatchesLiteral(2), MatchesLiteral(3))); EXPECT_THAT(&mul, MatchesMul(MatchesLiteral(2), MatchesLiteral(3))); EXPECT_THAT(mul, MatchesMul(_, _)); EXPECT_THAT(mul, Not(MatchesMul(MatchesLiteral(2), MatchesLiteral(2)))); EXPECT_THAT(StringLiteral(DummyLoc, "foo"), Not(MatchesMul(_, _))); EXPECT_THAT(OperatorExpression(DummyLoc, Operator::Deref, {&two}), Not(MatchesMul(_, _))); OperatorExpression nested(DummyLoc, Operator::Mul, {&two, &mul}); EXPECT_THAT(nested, MatchesMul(MatchesLiteral(2), MatchesMul(MatchesLiteral(2), MatchesLiteral(3)))); } TEST(ASTTestMatchers, MatchesBinaryOpTest) { IntLiteral two(DummyLoc, 2); IntLiteral three(DummyLoc, 3); // Testing of MatchesMul provides most of the coverage for these matchers, // since they are thin wrappers around a common implementation. We only test // the others enough to detect copy-paste errors in the wrappers. EXPECT_THAT(OperatorExpression(DummyLoc, Operator::Add, {&two, &three}), MatchesAdd(MatchesLiteral(2), MatchesLiteral(3))); EXPECT_THAT(OperatorExpression(DummyLoc, Operator::And, {&two, &three}), MatchesAnd(MatchesLiteral(2), MatchesLiteral(3))); EXPECT_THAT(OperatorExpression(DummyLoc, Operator::Eq, {&two, &three}), MatchesEq(MatchesLiteral(2), MatchesLiteral(3))); EXPECT_THAT(OperatorExpression(DummyLoc, Operator::Or, {&two, &three}), MatchesOr(MatchesLiteral(2), MatchesLiteral(3))); EXPECT_THAT(OperatorExpression(DummyLoc, Operator::Sub, {&two, &three}), MatchesSub(MatchesLiteral(2), MatchesLiteral(3))); } TEST(ASTTestMatchers, MatchesReturnTest) { TupleLiteral unit(DummyLoc); ReturnExpression empty_return(DummyLoc, &unit, /*is_omitted_expression=*/true); EXPECT_THAT(empty_return, MatchesEmptyReturn()); EXPECT_THAT(&empty_return, MatchesEmptyReturn()); EXPECT_THAT(empty_return, Not(MatchesReturn(_))); IntLiteral int_val(DummyLoc, 42); ReturnExpression explicit_return(DummyLoc, &int_val, /*is_omitted_expression=*/false); EXPECT_THAT(explicit_return, MatchesReturn(MatchesLiteral(42))); EXPECT_THAT(explicit_return, Not(MatchesEmptyReturn())); EXPECT_THAT(int_val, Not(MatchesEmptyReturn())); EXPECT_THAT(int_val, Not(MatchesReturn(_))); } TEST(ASTTestMatchers, MatchesFunctionDeclarationTest) { TuplePattern params(DummyLoc, {}); Block body(DummyLoc, {}); FunctionDeclaration decl(DummyLoc, DeclaredName(DummyLoc, "Foo"), {}, std::nullopt, ¶ms, ReturnTerm::Omitted(DummyLoc), &body, VirtualOverride::None); EXPECT_THAT(decl, MatchesFunctionDeclaration()); EXPECT_THAT(&decl, MatchesFunctionDeclaration()); EXPECT_THAT(decl, MatchesFunctionDeclaration().WithName("Foo")); EXPECT_THAT(decl, MatchesFunctionDeclaration().WithBody(_)); EXPECT_THAT(decl, MatchesFunctionDeclaration().WithName("Foo").WithBody(_)); EXPECT_THAT(decl, MatchesFunctionDeclaration().WithBody(_).WithName("Foo")); EXPECT_THAT(decl, Not(MatchesFunctionDeclaration().WithName("Bar"))); EXPECT_THAT(decl, Not(MatchesFunctionDeclaration().WithBody(MatchesLiteral(0)))); FunctionDeclaration forward_decl( DummyLoc, DeclaredName(DummyLoc, "Foo"), {}, std::nullopt, ¶ms, ReturnTerm::Omitted(DummyLoc), std::nullopt, VirtualOverride::None); EXPECT_THAT(forward_decl, MatchesFunctionDeclaration().WithName("Foo")); EXPECT_THAT(forward_decl, Not(MatchesFunctionDeclaration().WithBody(_))); EXPECT_THAT(body, Not(MatchesFunctionDeclaration())); } TEST(ASTTestMatchers, MatchesUnimplementedExpressionTest) { IntLiteral two(DummyLoc, 2); IntLiteral three(DummyLoc, 3); UnimplementedExpression unimplemented(DummyLoc, "DummyLabel", &two, &three); EXPECT_THAT(unimplemented, MatchesUnimplementedExpression( "DummyLabel", ElementsAre(MatchesLiteral(2), MatchesLiteral(3)))); EXPECT_THAT( &unimplemented, MatchesUnimplementedExpression( "DummyLabel", ElementsAre(MatchesLiteral(2), MatchesLiteral(3)))); EXPECT_THAT( unimplemented, Not(MatchesUnimplementedExpression( "WrongLabel", ElementsAre(MatchesLiteral(2), MatchesLiteral(3))))); EXPECT_THAT(unimplemented, Not(MatchesUnimplementedExpression("DummyLabel", IsEmpty()))); EXPECT_THAT(two, Not(MatchesUnimplementedExpression("DummyLabel", IsEmpty()))); } TEST(ASTTestMatchers, ASTDeclarationsTest) { TuplePattern params(DummyLoc, {}); Block body(DummyLoc, {}); FunctionDeclaration decl(DummyLoc, DeclaredName(DummyLoc, "Foo"), {}, std::nullopt, ¶ms, ReturnTerm::Omitted(DummyLoc), &body, VirtualOverride::None); AST ast = {.declarations = {&decl}}; EXPECT_THAT(ast, ASTDeclarations(ElementsAre(MatchesFunctionDeclaration()))); EXPECT_THAT(ast, Not(ASTDeclarations(IsEmpty()))); } } // namespace } // namespace Carbon