Add LoopStatement AST tests This CL adds tests for the loop statement AST node. Bug: tint: 11 Change-Id: I32a3e1d4d40d21e00f4022bd1a2d03ba2ef4f404 Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/16563 Reviewed-by: Sarah Mashayekhi <sarahmashay@google.com>
diff --git a/src/ast/loop_statement.cc b/src/ast/loop_statement.cc index b0e645b..e99c87c 100644 --- a/src/ast/loop_statement.cc +++ b/src/ast/loop_statement.cc
@@ -17,6 +17,8 @@ namespace tint { namespace ast { +LoopStatement::LoopStatement() : Statement() {} + LoopStatement::LoopStatement(std::vector<std::unique_ptr<Statement>> body, std::vector<std::unique_ptr<Statement>> continuing) : Statement(), body_(std::move(body)), continuing_(std::move(continuing)) {} @@ -31,6 +33,14 @@ LoopStatement::~LoopStatement() = default; bool LoopStatement::IsValid() const { + for (const auto& stmt : body_) { + if (stmt == nullptr || !stmt->IsValid()) + return false; + } + for (const auto& stmt : continuing_) { + if (stmt == nullptr || !stmt->IsValid()) + return false; + } return true; } @@ -41,14 +51,16 @@ for (const auto& stmt : body_) stmt->to_str(out, indent + 2); - make_indent(out, indent + 2); - out << "continuing {" << std::endl; - - for (const auto& stmt : continuing_) - stmt->to_str(out, indent + 4); - - make_indent(out, indent + 2); - out << "}" << std::endl; + if (continuing_.size() > 0) { + make_indent(out, indent + 2); + out << "continuing {" << std::endl; + + for (const auto& stmt : continuing_) + stmt->to_str(out, indent + 4); + + make_indent(out, indent + 2); + out << "}" << std::endl; + } make_indent(out, indent); out << "}" << std::endl;
diff --git a/src/ast/loop_statement.h b/src/ast/loop_statement.h index 99acd96..917eaa6 100644 --- a/src/ast/loop_statement.h +++ b/src/ast/loop_statement.h
@@ -28,6 +28,8 @@ class LoopStatement : public Statement { public: /// Constructor + LoopStatement(); + /// Constructor /// @param body the body statements /// @param continuing the continuing statements LoopStatement(std::vector<std::unique_ptr<Statement>> body,
diff --git a/src/ast/loop_statement_test.cc b/src/ast/loop_statement_test.cc new file mode 100644 index 0000000..cb7f8cb --- /dev/null +++ b/src/ast/loop_statement_test.cc
@@ -0,0 +1,168 @@ +// 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/loop_statement.h" + +#include <sstream> + +#include "gtest/gtest.h" +#include "src/ast/kill_statement.h" +#include "src/ast/if_statement.h" +#include "src/ast/nop_statement.h" + +namespace tint { +namespace ast { + +using LoopStatementTest = testing::Test; + +TEST_F(LoopStatementTest, Creation) { + std::vector<std::unique_ptr<Statement>> body; + body.push_back(std::make_unique<KillStatement>()); + auto b_ptr = body[0].get(); + + std::vector<std::unique_ptr<Statement>> continuing; + continuing.push_back(std::make_unique<NopStatement>()); + auto c_ptr = continuing[0].get(); + + LoopStatement l(std::move(body), std::move(continuing)); + ASSERT_EQ(l.body().size(), 1); + EXPECT_EQ(l.body()[0].get(), b_ptr); + ASSERT_EQ(l.continuing().size(), 1); + EXPECT_EQ(l.continuing()[0].get(), c_ptr); +} + +TEST_F(LoopStatementTest, Creation_WithSource) { + std::vector<std::unique_ptr<Statement>> body; + body.push_back(std::make_unique<KillStatement>()); + + std::vector<std::unique_ptr<Statement>> continuing; + continuing.push_back(std::make_unique<NopStatement>()); + + LoopStatement l(Source{20, 2}, std::move(body), std::move(continuing)); + auto src = l.source(); + EXPECT_EQ(src.line, 20); + EXPECT_EQ(src.column, 2); +} + +TEST_F(LoopStatementTest, IsLoop) { + LoopStatement l; + EXPECT_TRUE(l.IsLoop()); +} + +TEST_F(LoopStatementTest, IsValid) { + std::vector<std::unique_ptr<Statement>> body; + body.push_back(std::make_unique<KillStatement>()); + + std::vector<std::unique_ptr<Statement>> continuing; + continuing.push_back(std::make_unique<NopStatement>()); + + LoopStatement l(std::move(body), std::move(continuing)); + EXPECT_TRUE(l.IsValid()); +} + +TEST_F(LoopStatementTest, IsValid_WithoutContinuing) { + std::vector<std::unique_ptr<Statement>> body; + body.push_back(std::make_unique<KillStatement>()); + + LoopStatement l(std::move(body), {}); + EXPECT_TRUE(l.IsValid()); +} + +TEST_F(LoopStatementTest, IsValid_WithoutBody) { + LoopStatement l({}, {}); + EXPECT_TRUE(l.IsValid()); +} + +TEST_F(LoopStatementTest, IsValid_NullBodyStatement) { + std::vector<std::unique_ptr<Statement>> body; + body.push_back(std::make_unique<KillStatement>()); + body.push_back(nullptr); + + std::vector<std::unique_ptr<Statement>> continuing; + continuing.push_back(std::make_unique<NopStatement>()); + + LoopStatement l(std::move(body), std::move(continuing)); + EXPECT_FALSE(l.IsValid()); +} + +TEST_F(LoopStatementTest, IsValid_InvalidBodyStatement) { + std::vector<std::unique_ptr<Statement>> body; + body.push_back(std::make_unique<KillStatement>()); + body.push_back(std::make_unique<IfStatement>()); + + std::vector<std::unique_ptr<Statement>> continuing; + continuing.push_back(std::make_unique<NopStatement>()); + + LoopStatement l(std::move(body), std::move(continuing)); + EXPECT_FALSE(l.IsValid()); +} + +TEST_F(LoopStatementTest, IsValid_NullContinuingStatement) { + std::vector<std::unique_ptr<Statement>> body; + body.push_back(std::make_unique<KillStatement>()); + + std::vector<std::unique_ptr<Statement>> continuing; + continuing.push_back(std::make_unique<NopStatement>()); + continuing.push_back(nullptr); + + LoopStatement l(std::move(body), std::move(continuing)); + EXPECT_FALSE(l.IsValid()); +} + +TEST_F(LoopStatementTest, IsValid_InvalidContinuingStatement) { + std::vector<std::unique_ptr<Statement>> body; + body.push_back(std::make_unique<KillStatement>()); + + std::vector<std::unique_ptr<Statement>> continuing; + continuing.push_back(std::make_unique<NopStatement>()); + continuing.push_back(std::make_unique<IfStatement>()); + + LoopStatement l(std::move(body), std::move(continuing)); + EXPECT_FALSE(l.IsValid()); +} + +TEST_F(LoopStatementTest, ToStr) { + std::vector<std::unique_ptr<Statement>> body; + body.push_back(std::make_unique<KillStatement>()); + + LoopStatement l(std::move(body), {}); + std::ostringstream out; + l.to_str(out, 2); + EXPECT_EQ(out.str(), R"( Loop{ + Kill{} + } +)"); +} + +TEST_F(LoopStatementTest, ToStr_WithContinuing) { + std::vector<std::unique_ptr<Statement>> body; + body.push_back(std::make_unique<KillStatement>()); + + std::vector<std::unique_ptr<Statement>> continuing; + continuing.push_back(std::make_unique<NopStatement>()); + + LoopStatement l(std::move(body), std::move(continuing)); + std::ostringstream out; + l.to_str(out, 2); + EXPECT_EQ(out.str(), R"( Loop{ + Kill{} + continuing { + Nop{} + } + } +)"); +} + +} // namespace ast +} // namespace tint