diff --git a/op-finder-tests/CMakeLists.txt b/op-finder-tests/CMakeLists.txt index ccf5f02..e78b378 100644 --- a/op-finder-tests/CMakeLists.txt +++ b/op-finder-tests/CMakeLists.txt @@ -15,7 +15,10 @@ if (NOT LLVM_ENABLE_RTTI) endif () add_executable(op-finder-tests - main.cpp basic_operations.cpp fixtures/RunOnCodeFixture.cpp fixtures/RunOnCodeFixture.hpp) + main.cpp + fixtures/RunOnCodeFixture.cpp + basic_operations.cpp + branches.cpp) target_link_libraries(op-finder-tests PUBLIC diff --git a/op-finder-tests/basic_operations.cpp b/op-finder-tests/basic_operations.cpp index 75e71c6..a399901 100644 --- a/op-finder-tests/basic_operations.cpp +++ b/op-finder-tests/basic_operations.cpp @@ -51,3 +51,45 @@ TEST_CASE("Find unary operations", "[basic_operation]") REQUIRE(op->type_rhs.empty()); REQUIRE(op->type_result == "int"); } + +TEST_CASE("Find subscript operation", "[basic_operation]") +{ + RunOnCodeFixture fixture; + + const std::string code = "int main() { int a[4]; (void)a[4]; }"; + const auto& operations = fixture(code); + + REQUIRE(operations.size() == 1); + + const OperationLog& log = operations.front(); + + REQUIRE(log.entry_type == OperationLog::BasicOperation::TYPE_NAME); + + const OperationLog::BasicOperation* op = (OperationLog::BasicOperation*)(log.entry.get()); + + REQUIRE(op->operation_name == "subscript"); + REQUIRE(op->type_lhs == "int *"); + REQUIRE(op->type_rhs == "int"); + REQUIRE(op->type_result == "int"); +} + +TEST_CASE("Find subscript operation reversed", "[basic_operation]") +{ + RunOnCodeFixture fixture; + + const std::string code = "int main() { int a[4]; (void)4[a]; }"; + const auto& operations = fixture(code); + + REQUIRE(operations.size() == 1); + + const OperationLog& log = operations.front(); + + REQUIRE(log.entry_type == OperationLog::BasicOperation::TYPE_NAME); + + const OperationLog::BasicOperation* op = (OperationLog::BasicOperation*)(log.entry.get()); + + REQUIRE(op->operation_name == "subscript"); + REQUIRE(op->type_lhs == "int *"); + REQUIRE(op->type_rhs == "int"); + REQUIRE(op->type_result == "int"); +} diff --git a/op-finder-tests/branches.cpp b/op-finder-tests/branches.cpp new file mode 100644 index 0000000..b10096e --- /dev/null +++ b/op-finder-tests/branches.cpp @@ -0,0 +1,125 @@ +// +// Created by erki on 07.03.21. +// + +#include + +#include "fixtures/RunOnCodeFixture.hpp" + +TEST_CASE("For loop without header", "[branches][for_loops]") +{ + RunOnCodeFixture fixture; + + const std::string code = "int main() { int a; for (;;) {} }"; + REQUIRE(fixture.runCode(code)); + + REQUIRE(fixture.storage.getOperations().empty()); +} + +TEST_CASE("For loop with init only.", "[branches][for_loops]") +{ + RunOnCodeFixture fixture; + + const std::string code = "int main() { int a; for (a = 4;;) {} }"; + const auto& operations = fixture(code); + + REQUIRE(operations.size() == 1); + + const OperationLog& log = operations.front(); + + REQUIRE(log.branch_number == 1); +} + + +TEST_CASE("For loop with init & cond.", "[branches][for_loops]") +{ + RunOnCodeFixture fixture; + + const std::string code = "int main() { int a; for (a = 4; a < 4;) {} }"; + const auto& operations = fixture(code); + + REQUIRE(operations.size() == 2); + + const OperationLog& log_init = operations.at(0); + REQUIRE(log_init.branch_number == 1); + + const OperationLog& log_cond = operations.at(1); + REQUIRE(log_cond.branch_number == 2); +} + +TEST_CASE("For loop with init & inc.", "[branches][for_loops]") +{ + RunOnCodeFixture fixture; + + const std::string code = "int main() { int a; for (a = 4;;a++) {} }"; + const auto& operations = fixture(code); + + REQUIRE(operations.size() == 2); + + const OperationLog& log_init = operations.at(0); + REQUIRE(log_init.branch_number == 1); + + const OperationLog& log_inc = operations.at(1); + REQUIRE(log_inc.branch_number == 2); +} + +TEST_CASE("For loop with full header.", "[branches][for_loops]") +{ + RunOnCodeFixture fixture; + + const std::string code = "int main() { int a; for (a = 4; a < 4 ;a++) {} }"; + const auto& operations = fixture(code); + + REQUIRE(operations.size() == 3); + + const OperationLog& log_init = operations.at(0); + REQUIRE(log_init.branch_number == 1); + + const OperationLog& log_cond = operations.at(1); + REQUIRE(log_cond.branch_number == 2); + + const OperationLog& log_inc = operations.at(2); + REQUIRE(log_inc.branch_number == 2); +} + +TEST_CASE("For loop without init.", "[branches][for_loops]") +{ + RunOnCodeFixture fixture; + + const std::string code = "int main() { int a; for (;a < 4 ;a++) {} }"; + const auto& operations = fixture(code); + + REQUIRE(operations.size() == 2); + + const OperationLog& log_cond = operations.at(0); + REQUIRE(log_cond.branch_number == 0); + + const OperationLog& log_inc = operations.at(1); + REQUIRE(log_inc.branch_number == 0); +} + +TEST_CASE("For loop closes branches inside the loop.", "[branches][for_loops]") +{ + RunOnCodeFixture fixture; + + const std::string code = "int main() { int a; for (a = 4; a < 4 ; a++) { a = 5; } }"; + const auto& operations = fixture(code); + + REQUIRE(operations.size() == 4); + + const OperationLog& log_inner = operations.back(); + REQUIRE(log_inner.branch_number == 0); +} + +TEST_CASE("For loop closes branches outside the loop.", "[branches][for_loops]") +{ + RunOnCodeFixture fixture; + + const std::string code = "int main() { int a; for (a = 4; a < 4 ; a++) {} a = 5; }"; + const auto& operations = fixture(code); + + REQUIRE(operations.size() == 4); + + const OperationLog& log_outer = operations.back(); + REQUIRE(log_outer.branch_number == 0); +} diff --git a/op-finder-tests/fixtures/RunOnCodeFixture.cpp b/op-finder-tests/fixtures/RunOnCodeFixture.cpp index 2af9256..56cb147 100644 --- a/op-finder-tests/fixtures/RunOnCodeFixture.cpp +++ b/op-finder-tests/fixtures/RunOnCodeFixture.cpp @@ -14,13 +14,18 @@ RunOnCodeFixture::RunOnCodeFixture() , action(&finder) { } -const std::vector& RunOnCodeFixture::operator()(const std::string& code) +bool RunOnCodeFixture::runCode(const std::string& code) { - const bool success = clang::tooling::runToolOnCode( + return clang::tooling::runToolOnCode( clang::tooling::newFrontendActionFactory(&action)->create(), code, RunOnCodeFixture::INPUT_FILE ); +} + +const std::vector& RunOnCodeFixture::operator()(const std::string& code) +{ + const bool success = runCode(code); REQUIRE(success); diff --git a/op-finder-tests/fixtures/RunOnCodeFixture.hpp b/op-finder-tests/fixtures/RunOnCodeFixture.hpp index 7abd514..98a8833 100644 --- a/op-finder-tests/fixtures/RunOnCodeFixture.hpp +++ b/op-finder-tests/fixtures/RunOnCodeFixture.hpp @@ -19,6 +19,8 @@ struct RunOnCodeFixture RunOnCodeFixture(); + bool runCode(const std::string& code); + const std::vector& operator()(const std::string& code); };