tint: Add ast::CheckIdentifier() test helper
A bunch of template magic to recursively test that an identifier (and template arguments) matches the given values. Will be heavily used for AST and parser tests. Bug: tint:1810 Change-Id: I8d83090352c345f0ce1ac7840e163eea96eac8a2 Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/119124 Commit-Queue: Ben Clayton <bclayton@chromium.org> Reviewed-by: Dan Sinclair <dsinclair@chromium.org> Kokoro: Kokoro <noreply+kokoro@google.com>
This commit is contained in:
parent
b75252b7aa
commit
f973d514a1
|
@ -1370,6 +1370,7 @@ if (tint_build_unittests) {
|
|||
"ast/switch_statement_test.cc",
|
||||
"ast/templated_identifier_test.cc",
|
||||
"ast/test_helper.h",
|
||||
"ast/test_helper_test.cc",
|
||||
"ast/texture_test.cc",
|
||||
"ast/traverse_expressions_test.cc",
|
||||
"ast/type_name_test.cc",
|
||||
|
|
|
@ -886,8 +886,9 @@ if(TINT_BUILD_TESTS)
|
|||
ast/struct_member_test.cc
|
||||
ast/struct_test.cc
|
||||
ast/switch_statement_test.cc
|
||||
ast/test_helper.h
|
||||
ast/templated_identifier_test.cc
|
||||
ast/test_helper.h
|
||||
ast/test_helper_test.cc
|
||||
ast/texture_test.cc
|
||||
ast/traverse_expressions_test.cc
|
||||
ast/type_name_test.cc
|
||||
|
|
|
@ -15,6 +15,9 @@
|
|||
#ifndef SRC_TINT_AST_TEST_HELPER_H_
|
||||
#define SRC_TINT_AST_TEST_HELPER_H_
|
||||
|
||||
#include <tuple>
|
||||
#include <utility>
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
#include "src/tint/program_builder.h"
|
||||
|
||||
|
@ -31,6 +34,122 @@ using TestHelper = TestHelperBase<testing::Test>;
|
|||
template <typename T>
|
||||
using TestParamHelper = TestHelperBase<testing::TestWithParam<T>>;
|
||||
|
||||
/// A structure to hold a TemplatedIdentifier matcher, used by the CheckIdentifier() test helper
|
||||
template <typename... ARGS>
|
||||
struct TemplatedIdentifierMatcher {
|
||||
/// The expected name of the TemplatedIdentifier
|
||||
std::string_view name;
|
||||
/// The expected arguments of the TemplatedIdentifier
|
||||
std::tuple<ARGS...> args;
|
||||
};
|
||||
|
||||
/// Deduction guide for TemplatedIdentifierMatcher
|
||||
template <typename... ARGS>
|
||||
TemplatedIdentifierMatcher(std::string_view, std::tuple<ARGS...>&&)
|
||||
-> TemplatedIdentifierMatcher<ARGS...>;
|
||||
|
||||
/// A helper function for building a TemplatedIdentifierMatcher
|
||||
/// @param name the name of the TemplatedIdentifier
|
||||
/// @param args the template arguments
|
||||
/// @return a TemplatedIdentifierMatcher
|
||||
template <typename... ARGS>
|
||||
auto Template(std::string_view name, ARGS&&... args) {
|
||||
return TemplatedIdentifierMatcher{name, std::make_tuple(std::forward<ARGS>(args)...)};
|
||||
}
|
||||
|
||||
/// A traits helper for determining whether the type T is a TemplatedIdentifierMatcher.
|
||||
template <typename T>
|
||||
struct IsTemplatedIdentifierMatcher {
|
||||
/// True iff T is a TemplatedIdentifierMatcher
|
||||
static constexpr bool value = false;
|
||||
};
|
||||
|
||||
/// IsTemplatedIdentifierMatcher specialization for TemplatedIdentifierMatcher.
|
||||
template <typename... ARGS>
|
||||
struct IsTemplatedIdentifierMatcher<TemplatedIdentifierMatcher<ARGS...>> {
|
||||
/// True iff T is a TemplatedIdentifierMatcher
|
||||
static constexpr bool value = true;
|
||||
};
|
||||
|
||||
/// A testing utility for checking that an Identifier and any optional templated arguments match the
|
||||
/// expected values.
|
||||
/// @param symbols the symbol table
|
||||
/// @param got the identifier
|
||||
/// @param expected the expected identifier name
|
||||
template <typename... ARGS>
|
||||
void CheckIdentifier(const SymbolTable& symbols, const Identifier* got, std::string_view expected) {
|
||||
EXPECT_FALSE(got->Is<ast::TemplatedIdentifier>());
|
||||
EXPECT_EQ(symbols.NameFor(got->symbol), expected);
|
||||
}
|
||||
|
||||
/// A testing utility for checking that an Identifier matches the expected name and template
|
||||
/// arguments.
|
||||
/// @param symbols the symbol table
|
||||
/// @param ident the identifier
|
||||
/// @param expected the expected identifier name and arguments
|
||||
template <typename... ARGS>
|
||||
void CheckIdentifier(const SymbolTable& symbols,
|
||||
const Identifier* ident,
|
||||
const TemplatedIdentifierMatcher<ARGS...>& expected) {
|
||||
EXPECT_EQ(symbols.NameFor(ident->symbol), expected.name);
|
||||
ASSERT_TRUE(ident->Is<ast::TemplatedIdentifier>());
|
||||
auto* got = ident->As<ast::TemplatedIdentifier>();
|
||||
ASSERT_EQ(got->arguments.Length(), std::tuple_size_v<decltype(expected.args)>);
|
||||
|
||||
size_t arg_idx = 0;
|
||||
auto check_arg = [&](auto&& expected_arg) {
|
||||
const auto* got_arg = got->arguments[arg_idx++];
|
||||
|
||||
using T = std::decay_t<decltype(expected_arg)>;
|
||||
if constexpr (traits::IsStringLike<T>) {
|
||||
ASSERT_TRUE(got_arg->Is<IdentifierExpression>());
|
||||
ast::CheckIdentifier(symbols, got_arg->As<IdentifierExpression>()->identifier,
|
||||
expected_arg);
|
||||
} else if constexpr (IsTemplatedIdentifierMatcher<T>::value) {
|
||||
ASSERT_TRUE(got_arg->Is<IdentifierExpression>());
|
||||
auto* got_ident = got_arg->As<IdentifierExpression>()->identifier;
|
||||
ASSERT_TRUE(got_ident->Is<TemplatedIdentifier>());
|
||||
CheckIdentifier(symbols, got_ident->As<TemplatedIdentifier>(), expected_arg);
|
||||
} else if constexpr (std::is_same_v<T, bool>) {
|
||||
ASSERT_TRUE(got_arg->Is<BoolLiteralExpression>());
|
||||
EXPECT_EQ(got_arg->As<BoolLiteralExpression>()->value, expected_arg);
|
||||
} else if constexpr (std::is_same_v<T, AInt>) {
|
||||
ASSERT_TRUE(got_arg->Is<IntLiteralExpression>());
|
||||
EXPECT_EQ(got_arg->As<IntLiteralExpression>()->suffix,
|
||||
IntLiteralExpression::Suffix::kNone);
|
||||
EXPECT_EQ(AInt(got_arg->As<IntLiteralExpression>()->value), expected_arg);
|
||||
} else if constexpr (std::is_same_v<T, i32>) {
|
||||
ASSERT_TRUE(got_arg->Is<IntLiteralExpression>());
|
||||
EXPECT_EQ(got_arg->As<IntLiteralExpression>()->suffix,
|
||||
IntLiteralExpression::Suffix::kI);
|
||||
EXPECT_EQ(i32(got_arg->As<IntLiteralExpression>()->value), expected_arg);
|
||||
} else if constexpr (std::is_same_v<T, u32>) {
|
||||
ASSERT_TRUE(got_arg->Is<IntLiteralExpression>());
|
||||
EXPECT_EQ(got_arg->As<IntLiteralExpression>()->suffix,
|
||||
IntLiteralExpression::Suffix::kU);
|
||||
EXPECT_EQ(u32(got_arg->As<IntLiteralExpression>()->value), expected_arg);
|
||||
} else if constexpr (std::is_same_v<T, AFloat>) {
|
||||
ASSERT_TRUE(got_arg->Is<FloatLiteralExpression>());
|
||||
EXPECT_EQ(got_arg->As<FloatLiteralExpression>()->suffix,
|
||||
FloatLiteralExpression::Suffix::kNone);
|
||||
EXPECT_EQ(AFloat(got_arg->As<FloatLiteralExpression>()->value), expected_arg);
|
||||
} else if constexpr (std::is_same_v<T, f32>) {
|
||||
ASSERT_TRUE(got_arg->Is<FloatLiteralExpression>());
|
||||
EXPECT_EQ(got_arg->As<FloatLiteralExpression>()->suffix,
|
||||
FloatLiteralExpression::Suffix::kF);
|
||||
EXPECT_EQ(f32(got_arg->As<FloatLiteralExpression>()->value), expected_arg);
|
||||
} else if constexpr (std::is_same_v<T, f16>) {
|
||||
ASSERT_TRUE(got_arg->Is<FloatLiteralExpression>());
|
||||
EXPECT_EQ(got_arg->As<FloatLiteralExpression>()->suffix,
|
||||
FloatLiteralExpression::Suffix::kH);
|
||||
EXPECT_EQ(f16(got_arg->As<FloatLiteralExpression>()->value), expected_arg);
|
||||
} else {
|
||||
FAIL() << "unhandled expected_args type";
|
||||
}
|
||||
};
|
||||
std::apply([&](auto&&... args) { ((check_arg(args)), ...); }, expected.args);
|
||||
}
|
||||
|
||||
} // namespace tint::ast
|
||||
|
||||
#endif // SRC_TINT_AST_TEST_HELPER_H_
|
||||
|
|
|
@ -0,0 +1,42 @@
|
|||
// Copyright 2023 The Tint 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 "src/tint/ast/test_helper.h"
|
||||
|
||||
namespace tint::ast {
|
||||
|
||||
using namespace tint::number_suffixes; // NOLINT
|
||||
|
||||
using AstCheckIdentifierTest = TestHelper;
|
||||
|
||||
TEST_F(AstCheckIdentifierTest, NonTemplated) {
|
||||
CheckIdentifier(Symbols(), Ident("abc"), "abc");
|
||||
}
|
||||
|
||||
TEST_F(AstCheckIdentifierTest, TemplatedScalars) {
|
||||
CheckIdentifier(Symbols(), Ident("abc", 1_i, 2_u, 3_f, 4_h, 5_a, 6._a, true), //
|
||||
Template("abc", 1_i, 2_u, 3_f, 4_h, 5_a, 6._a, true));
|
||||
}
|
||||
|
||||
TEST_F(AstCheckIdentifierTest, TemplatedIdentifiers) {
|
||||
CheckIdentifier(Symbols(), Ident("abc", "one", "two", "three"), //
|
||||
Template("abc", "one", "two", "three"));
|
||||
}
|
||||
|
||||
TEST_F(AstCheckIdentifierTest, NestedTemplate) {
|
||||
CheckIdentifier(Symbols(), Ident("abc", "pre", Ident("nested", 42_a), "post"), //
|
||||
Template("abc", "pre", Template("nested", 42_a), "post"));
|
||||
}
|
||||
|
||||
} // namespace tint::ast
|
Loading…
Reference in New Issue