From 00cf5a489443f81de7b00fc4aaa13370849e1b2c Mon Sep 17 00:00:00 2001 From: Dan Sinclair Date: Thu, 5 Mar 2020 20:35:57 +0000 Subject: [PATCH] Add test for call expression This CL adds unit tests for the call expression. The IsValid method is extended to verify none of the provided parameters are a nullptr. Change-Id: I5dfd3ec1f086ef02ab965218a1d8610a1c212628 Bug: tint:11 Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/16360 Reviewed-by: Sarah Mashayekhi Commit-Queue: Sarah Mashayekhi --- src/CMakeLists.txt | 1 + src/ast/call_expression.cc | 20 ++++- src/ast/call_expression.h | 2 + src/ast/call_expression_test.cc | 131 ++++++++++++++++++++++++++++++++ 4 files changed, 152 insertions(+), 2 deletions(-) create mode 100644 src/ast/call_expression_test.cc diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 2a6a9be429..0434df8229 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -200,6 +200,7 @@ set(TINT_TEST_SRCS ast/bool_literal_test.cc ast/break_statement_test.cc ast/builtin_decoration_test.cc + ast/call_expression_test.cc ast/entry_point_test.cc ast/import_test.cc ast/int_literal_test.cc diff --git a/src/ast/call_expression.cc b/src/ast/call_expression.cc index 4b0d97d476..6dad233da4 100644 --- a/src/ast/call_expression.cc +++ b/src/ast/call_expression.cc @@ -17,6 +17,8 @@ namespace tint { namespace ast { +CallExpression::CallExpression() : Expression() {} + CallExpression::CallExpression(std::unique_ptr func, std::vector> params) : Expression(), func_(std::move(func)), params_(std::move(params)) {} @@ -29,11 +31,22 @@ CallExpression::CallExpression(const Source& source, CallExpression::~CallExpression() = default; bool CallExpression::IsValid() const { - return func_ != nullptr; + if (func_ == nullptr || !func_->IsValid()) + return false; + + // All params must be valid + for (const auto& param : params_) { + if (param == nullptr || !param->IsValid()) + return false; + } + return true; } void CallExpression::to_str(std::ostream& out, size_t indent) const { - func_->to_str(out, indent); + make_indent(out, indent); + out << "Call{" << std::endl; + func_->to_str(out, indent + 2); + make_indent(out, indent + 2); out << "(" << std::endl; for (const auto& param : params_) @@ -41,6 +54,9 @@ void CallExpression::to_str(std::ostream& out, size_t indent) const { make_indent(out, indent + 2); out << ")" << std::endl; + + make_indent(out, indent); + out << "}" << std::endl; } } // namespace ast diff --git a/src/ast/call_expression.h b/src/ast/call_expression.h index ac5178f2ae..0644d691af 100644 --- a/src/ast/call_expression.h +++ b/src/ast/call_expression.h @@ -28,6 +28,8 @@ namespace ast { /// A call expression class CallExpression : public Expression { public: + /// Constructor + CallExpression(); /// Constructor /// @param func the function /// @param params the parameters diff --git a/src/ast/call_expression_test.cc b/src/ast/call_expression_test.cc new file mode 100644 index 0000000000..b4dad2fd95 --- /dev/null +++ b/src/ast/call_expression_test.cc @@ -0,0 +1,131 @@ +// Copyright 2020 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/ast/call_expression.h" + +#include "gtest/gtest.h" +#include "src/ast/identifier_expression.h" + +namespace tint { +namespace ast { + +using CallExpressionTest = testing::Test; + +TEST_F(CallExpressionTest, Creation) { + auto func = std::make_unique("func"); + std::vector> params; + params.push_back(std::make_unique("param1")); + params.push_back(std::make_unique("param2")); + + auto func_ptr = func.get(); + auto param1_ptr = params[0].get(); + auto param2_ptr = params[1].get(); + + CallExpression stmt(std::move(func), std::move(params)); + EXPECT_EQ(stmt.func(), func_ptr); + + const auto& vec = stmt.params(); + ASSERT_EQ(vec.size(), 2); + EXPECT_EQ(vec[0].get(), param1_ptr); + EXPECT_EQ(vec[1].get(), param2_ptr); +} + +TEST_F(CallExpressionTest, Creation_WithSource) { + auto func = std::make_unique("func"); + CallExpression stmt(Source{20, 2}, std::move(func), {}); + auto src = stmt.source(); + EXPECT_EQ(src.line, 20); + EXPECT_EQ(src.column, 2); +} + +TEST_F(CallExpressionTest, IsCall) { + auto func = std::make_unique("func"); + CallExpression stmt(std::move(func), {}); + EXPECT_TRUE(stmt.IsCall()); +} + +TEST_F(CallExpressionTest, IsValid) { + auto func = std::make_unique("func"); + CallExpression stmt(std::move(func), {}); + EXPECT_TRUE(stmt.IsValid()); +} + +TEST_F(CallExpressionTest, IsValid_MissingFunction) { + CallExpression stmt; + EXPECT_FALSE(stmt.IsValid()); +} + +TEST_F(CallExpressionTest, IsValid_NullParam) { + auto func = std::make_unique("func"); + std::vector> params; + params.push_back(std::make_unique("param1")); + params.push_back(nullptr); + params.push_back(std::make_unique("param2")); + + CallExpression stmt(std::move(func), std::move(params)); + EXPECT_FALSE(stmt.IsValid()); +} + +TEST_F(CallExpressionTest, IsValid_InvalidFunction) { + auto func = std::make_unique(""); + std::vector> params; + params.push_back(std::make_unique("param1")); + + CallExpression stmt(std::move(func), std::move(params)); + EXPECT_FALSE(stmt.IsValid()); +} + +TEST_F(CallExpressionTest, IsValid_InvalidParam) { + auto func = std::make_unique("func"); + std::vector> params; + params.push_back(std::make_unique("")); + + CallExpression stmt(std::move(func), std::move(params)); + EXPECT_FALSE(stmt.IsValid()); +} + +TEST_F(CallExpressionTest, ToStr_NoParams) { + auto func = std::make_unique("func"); + CallExpression stmt(std::move(func), {}); + std::ostringstream out; + stmt.to_str(out, 2); + EXPECT_EQ(out.str(), R"( Call{ + Identifier{func} + ( + ) + } +)"); +} + +TEST_F(CallExpressionTest, ToStr_WithParams) { + auto func = std::make_unique("func"); + std::vector> params; + params.push_back(std::make_unique("param1")); + params.push_back(std::make_unique("param2")); + + CallExpression stmt(std::move(func), std::move(params)); + std::ostringstream out; + stmt.to_str(out, 2); + EXPECT_EQ(out.str(), R"( Call{ + Identifier{func} + ( + Identifier{param1} + Identifier{param2} + ) + } +)"); +} + +} // namespace ast +} // namespace tint