diff options
-rw-r--r-- | .circleci/config.yml | 6 | ||||
-rw-r--r-- | test/boostTest.cpp | 7 | ||||
-rw-r--r-- | test/libjulia/Disambiguator.cpp | 105 | ||||
-rw-r--r-- | test/libjulia/YulOptimizerTest.cpp | 167 | ||||
-rw-r--r-- | test/libjulia/YulOptimizerTest.h | 75 | ||||
-rw-r--r-- | test/libjulia/yulOptimizerTests/disambiguator/for_statement.yul | 28 | ||||
-rw-r--r-- | test/libjulia/yulOptimizerTests/disambiguator/funtion_call.yul | 22 | ||||
-rw-r--r-- | test/libjulia/yulOptimizerTests/disambiguator/if_statement.yul | 22 | ||||
-rw-r--r-- | test/libjulia/yulOptimizerTests/disambiguator/smoke.yul | 5 | ||||
-rw-r--r-- | test/libjulia/yulOptimizerTests/disambiguator/smoke_yul.yul | 6 | ||||
-rw-r--r-- | test/libjulia/yulOptimizerTests/disambiguator/switch_statement.yul | 27 | ||||
-rw-r--r-- | test/libjulia/yulOptimizerTests/disambiguator/variables.yul | 12 | ||||
-rw-r--r-- | test/libjulia/yulOptimizerTests/disambiguator/variables_clash.yul | 13 | ||||
-rw-r--r-- | test/libjulia/yulOptimizerTests/disambiguator/variables_inside_functions.yul | 24 | ||||
-rw-r--r-- | test/libsolidity/TestCase.cpp | 3 | ||||
-rw-r--r-- | test/tools/CMakeLists.txt | 2 | ||||
-rw-r--r-- | test/tools/isoltest.cpp | 14 |
17 files changed, 431 insertions, 107 deletions
diff --git a/.circleci/config.yml b/.circleci/config.yml index f8e380d9..c975740d 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -233,6 +233,9 @@ jobs: command: codecov --flags all --gcov-root build - store_test_results: path: test_results/ + - store_artifacts: + path: test_results/ + destination: test_results/ test_x86_mac: macos: @@ -254,6 +257,9 @@ jobs: - run: *run_tests - store_test_results: path: test_results/ + - store_artifacts: + path: test_results/ + destination: test_results/ docs: docker: diff --git a/test/boostTest.cpp b/test/boostTest.cpp index d9e939eb..cbbf586f 100644 --- a/test/boostTest.cpp +++ b/test/boostTest.cpp @@ -38,6 +38,7 @@ #include <test/Options.h> #include <test/libsolidity/ASTJSONTest.h> #include <test/libsolidity/SyntaxTest.h> +#include <test/libjulia/YulOptimizerTest.h> #include <boost/algorithm/string.hpp> #include <boost/algorithm/string/predicate.hpp> @@ -138,6 +139,12 @@ test_suite* init_unit_test_suite( int /*argc*/, char* /*argv*/[] ) "ASTJSON", ASTJSONTest::create ) > 0, "no JSON AST tests found"); + solAssert(registerTests( + master, + dev::test::Options::get().testPath / "libjulia", + "yulOptimizerTests", + dev::julia::test::YulOptimizerTest::create + ) > 0, "no Yul Optimizer tests found"); if (dev::test::Options::get().disableIPC) { for (auto suite: { diff --git a/test/libjulia/Disambiguator.cpp b/test/libjulia/Disambiguator.cpp deleted file mode 100644 index 48e02c7e..00000000 --- a/test/libjulia/Disambiguator.cpp +++ /dev/null @@ -1,105 +0,0 @@ -/* - This file is part of solidity. - - solidity is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - solidity is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with solidity. If not, see <http://www.gnu.org/licenses/>. -*/ -/** - * @date 2017 - * Unit tests for the Yul name disambiguator. - */ - -#include <test/libjulia/Common.h> - -#include <libsolidity/inlineasm/AsmPrinter.h> - -#include <boost/test/unit_test.hpp> - -using namespace std; -using namespace dev::julia::test; -using namespace dev::solidity; - -#define CHECK(_original, _expectation)\ -do\ -{\ - assembly::AsmPrinter p(true);\ - string result = p(disambiguate(_original));\ - BOOST_CHECK_EQUAL(result, format(_expectation));\ - BOOST_CHECK_EQUAL(result, p(disambiguate(result)));\ -}\ -while(false) - -BOOST_AUTO_TEST_SUITE(YulDisambiguator) - -BOOST_AUTO_TEST_CASE(smoke_test) -{ - CHECK("{ }", "{ }"); -} - -BOOST_AUTO_TEST_CASE(variables) -{ - CHECK( - "{ { let a:u256 } { let a:u256 } }", - "{ { let a:u256 } { let a_1:u256 } }" - ); -} - -BOOST_AUTO_TEST_CASE(variables_clash) -{ - CHECK( - "{ { let a:u256 let a_1:u256 } { let a:u256 } }", - "{ { let a:u256 let a_1:u256 } { let a_2:u256 } }" - ); -} - -BOOST_AUTO_TEST_CASE(variables_inside_functions) -{ - CHECK( - "{ { let c:u256 let b:u256 } function f(a:u256, c:u256) -> b:u256 { let x:u256 } { let a:u256 let x:u256 } }", - "{ { let c:u256 let b:u256 } function f(a:u256, c_1:u256) -> b_1:u256 { let x:u256 } { let a_1:u256 let x_1:u256 } }" - ); -} - -BOOST_AUTO_TEST_CASE(function_call) -{ - CHECK( - "{ { let a:u256, b:u256, c:u256, d:u256, f:u256 } { function f(a:u256) -> c:u256, d:u256 { let b:u256, c_1:u256 := f(a) } } }", - "{ { let a:u256, b:u256, c:u256, d:u256, f:u256 } { function f_1(a_1:u256) -> c_1:u256, d_1:u256 { let b_1:u256, c_1_1:u256 := f_1(a_1) } } }" - ); -} - -BOOST_AUTO_TEST_CASE(for_statement) -{ - CHECK( - "{ { let a:u256, b:u256 } { for { let a:u256 } a { a := a } { let b:u256 := a } } }", - "{ { let a:u256, b:u256 } { for { let a_1:u256 } a_1 { a_1 := a_1 } { let b_1:u256 := a_1 } } }" - ); -} - -BOOST_AUTO_TEST_CASE(switch_statement) -{ - CHECK( - "{ { let a:u256, b:u256, c:u256 } { let a:u256 switch a case 0:u256 { let b:u256 := a } default { let c:u256 := a } } }", - "{ { let a:u256, b:u256, c:u256 } { let a_1:u256 switch a_1 case 0:u256 { let b_1:u256 := a_1 } default { let c_1:u256 := a_1 } } }" - ); -} - -BOOST_AUTO_TEST_CASE(if_statement) -{ - CHECK( - "{ { let a:u256, b:u256, c:u256 } { let a:bool if a { let b:bool := a } } }", - "{ { let a:u256, b:u256, c:u256 } { let a_1:bool if a_1 { let b_1:bool := a_1 } } }" - ); -} - -BOOST_AUTO_TEST_SUITE_END() diff --git a/test/libjulia/YulOptimizerTest.cpp b/test/libjulia/YulOptimizerTest.cpp new file mode 100644 index 00000000..fd15623c --- /dev/null +++ b/test/libjulia/YulOptimizerTest.cpp @@ -0,0 +1,167 @@ +/* + This file is part of solidity. + + solidity is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + solidity is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with solidity. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include <test/libjulia/YulOptimizerTest.h> + +#include <test/libsolidity/FormattedScope.h> + +#include <test/Options.h> + +#include <libjulia/optimiser/Disambiguator.h> +#include <libsolidity/parsing/Scanner.h> +#include <libsolidity/inlineasm/AsmPrinter.h> +#include <libsolidity/inlineasm/AsmParser.h> +#include <libsolidity/inlineasm/AsmAnalysis.h> +#include <libsolidity/interface/SourceReferenceFormatter.h> +#include <libsolidity/interface/ErrorReporter.h> + +#include <boost/test/unit_test.hpp> +#include <boost/algorithm/string.hpp> + +#include <fstream> + +using namespace dev; +using namespace dev::julia; +using namespace dev::julia::test; +using namespace dev::solidity; +using namespace dev::solidity::test; +using namespace std; + +YulOptimizerTest::YulOptimizerTest(string const& _filename) +{ + boost::filesystem::path path(_filename); + + if (path.empty() || std::next(path.begin()) == path.end() || std::next(std::next(path.begin())) == path.end()) + BOOST_THROW_EXCEPTION(runtime_error("Filename path has to contain a directory: \"" + _filename + "\".")); + m_optimizerStep = std::prev(std::prev(path.end()))->string(); + + ifstream file(_filename); + if (!file) + BOOST_THROW_EXCEPTION(runtime_error("Cannot open test case: \"" + _filename + "\".")); + file.exceptions(ios::badbit); + + string line; + while (getline(file, line)) + { + if (boost::algorithm::starts_with(line, "// ----")) + break; + if (m_source.empty() && boost::algorithm::starts_with(line, "// yul")) + m_yul = true; + m_source += line + "\n"; + } + while (getline(file, line)) + if (boost::algorithm::starts_with(line, "// ")) + m_expectation += line.substr(3) + "\n"; + else + m_expectation += line + "\n"; +} + +bool YulOptimizerTest::run(ostream& _stream, string const& _linePrefix, bool const _formatted) +{ + assembly::AsmPrinter printer{m_yul}; + shared_ptr<Block> ast; + shared_ptr<assembly::AsmAnalysisInfo> analysisInfo; + if (!parse(_stream, _linePrefix, _formatted)) + return false; + + if (m_optimizerStep == "disambiguator") + disambiguate(); + else + { + FormattedScope(_stream, _formatted, {formatting::BOLD, formatting::RED}) << _linePrefix << "Invalid optimizer step: " << m_optimizerStep << endl; + return false; + } + + m_obtainedResult = m_optimizerStep + "\n" + printer(*m_ast) + "\n"; + + if (m_expectation != m_obtainedResult) + { + string nextIndentLevel = _linePrefix + " "; + FormattedScope(_stream, _formatted, {formatting::BOLD, formatting::CYAN}) << _linePrefix << "Expected result:" << endl; + // TODO could compute a simple diff with highlighted lines + printIndented(_stream, m_expectation, nextIndentLevel); + FormattedScope(_stream, _formatted, {formatting::BOLD, formatting::CYAN}) << _linePrefix << "Obtained result:" << endl; + printIndented(_stream, m_obtainedResult, nextIndentLevel); + return false; + } + return true; +} + +void YulOptimizerTest::printSource(ostream& _stream, string const& _linePrefix, bool const) const +{ + printIndented(_stream, m_source, _linePrefix); +} + +void YulOptimizerTest::printUpdatedExpectations(ostream& _stream, string const& _linePrefix) const +{ + printIndented(_stream, m_obtainedResult, _linePrefix); +} + +void YulOptimizerTest::printIndented(ostream& _stream, string const& _output, string const& _linePrefix) const +{ + stringstream output(_output); + string line; + while (getline(output, line)) + _stream << _linePrefix << line << endl; +} + +bool YulOptimizerTest::parse(ostream& _stream, string const& _linePrefix, bool const _formatted) +{ + assembly::AsmFlavour flavour = m_yul ? assembly::AsmFlavour::Yul : assembly::AsmFlavour::Strict; + ErrorList errors; + ErrorReporter errorReporter(errors); + shared_ptr<Scanner> scanner = make_shared<Scanner>(CharStream(m_source), ""); + m_ast = assembly::Parser(errorReporter, flavour).parse(scanner, false); + if (!m_ast || !errorReporter.errors().empty()) + { + FormattedScope(_stream, _formatted, {formatting::BOLD, formatting::RED}) << _linePrefix << "Error parsing source." << endl; + printErrors(_stream, errorReporter.errors(), *scanner); + return false; + } + m_analysisInfo = make_shared<assembly::AsmAnalysisInfo>(); + assembly::AsmAnalyzer analyzer( + *m_analysisInfo, + errorReporter, + dev::test::Options::get().evmVersion(), + boost::none, + flavour + ); + if (!analyzer.analyze(*m_ast) || !errorReporter.errors().empty()) + { + FormattedScope(_stream, _formatted, {formatting::BOLD, formatting::RED}) << _linePrefix << "Error analyzing source." << endl; + printErrors(_stream, errorReporter.errors(), *scanner); + return false; + } + return true; +} + +void YulOptimizerTest::disambiguate() +{ + *m_ast = boost::get<Block>(Disambiguator(*m_analysisInfo)(*m_ast)); + m_analysisInfo.reset(); +} + +void YulOptimizerTest::printErrors(ostream& _stream, ErrorList const& _errors, Scanner const& _scanner) +{ + SourceReferenceFormatter formatter(_stream, [&](string const&) -> Scanner const& { return _scanner; }); + + for (auto const& error: _errors) + formatter.printExceptionInformation( + *error, + (error->type() == Error::Type::Warning) ? "Warning" : "Error" + ); +} diff --git a/test/libjulia/YulOptimizerTest.h b/test/libjulia/YulOptimizerTest.h new file mode 100644 index 00000000..8f9a81f7 --- /dev/null +++ b/test/libjulia/YulOptimizerTest.h @@ -0,0 +1,75 @@ +/* + This file is part of solidity. + + solidity is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + solidity is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with solidity. If not, see <http://www.gnu.org/licenses/>. +*/ + +#pragma once + +#include <test/libsolidity/TestCase.h> + + +namespace dev +{ +namespace solidity +{ +class Scanner; +class Error; +using ErrorList = std::vector<std::shared_ptr<Error const>>; +namespace assembly +{ +struct AsmAnalysisInfo; +struct Block; +} +} +namespace julia +{ +namespace test +{ + +class YulOptimizerTest: public solidity::test::TestCase +{ +public: + static std::unique_ptr<TestCase> create(std::string const& _filename) + { + return std::unique_ptr<TestCase>(new YulOptimizerTest(_filename)); + } + + explicit YulOptimizerTest(std::string const& _filename); + + bool run(std::ostream& _stream, std::string const& _linePrefix = "", bool const _formatted = false) override; + + void printSource(std::ostream& _stream, std::string const &_linePrefix = "", bool const _formatted = false) const override; + void printUpdatedExpectations(std::ostream& _stream, std::string const& _linePrefix) const override; + +private: + void printIndented(std::ostream& _stream, std::string const& _output, std::string const& _linePrefix = "") const; + bool parse(std::ostream& _stream, std::string const& _linePrefix, bool const _formatted); + void disambiguate(); + + static void printErrors(std::ostream& _stream, solidity::ErrorList const& _errors, solidity::Scanner const& _scanner); + + std::string m_source; + bool m_yul = false; + std::string m_optimizerStep; + std::string m_expectation; + + std::shared_ptr<solidity::assembly::Block> m_ast; + std::shared_ptr<solidity::assembly::AsmAnalysisInfo> m_analysisInfo; + std::string m_obtainedResult; +}; + +} +} +} diff --git a/test/libjulia/yulOptimizerTests/disambiguator/for_statement.yul b/test/libjulia/yulOptimizerTests/disambiguator/for_statement.yul new file mode 100644 index 00000000..0d2a38c5 --- /dev/null +++ b/test/libjulia/yulOptimizerTests/disambiguator/for_statement.yul @@ -0,0 +1,28 @@ +// yul +{ + { let a:u256, b:u256 } + { + for { let a:u256 } a { a := a } { + let b:u256 := a + } + } +} +// ---- +// disambiguator +// { +// { +// let a:u256, b:u256 +// } +// { +// for { +// let a_1:u256 +// } +// a_1 +// { +// a_1 := a_1 +// } +// { +// let b_1:u256 := a_1 +// } +// } +// } diff --git a/test/libjulia/yulOptimizerTests/disambiguator/funtion_call.yul b/test/libjulia/yulOptimizerTests/disambiguator/funtion_call.yul new file mode 100644 index 00000000..f917bb68 --- /dev/null +++ b/test/libjulia/yulOptimizerTests/disambiguator/funtion_call.yul @@ -0,0 +1,22 @@ +// yul +{ + { let a:u256, b:u256, c:u256, d:u256, f:u256 } + { + function f(a:u256) -> c:u256, d:u256 { + let b:u256, c_1:u256 := f(a) + } + } +} +// ---- +// disambiguator +// { +// { +// let a:u256, b:u256, c:u256, d:u256, f:u256 +// } +// { +// function f_1(a_1:u256) -> c_1:u256, d_1:u256 +// { +// let b_1:u256, c_1_1:u256 := f_1(a_1) +// } +// } +// } diff --git a/test/libjulia/yulOptimizerTests/disambiguator/if_statement.yul b/test/libjulia/yulOptimizerTests/disambiguator/if_statement.yul new file mode 100644 index 00000000..14f53757 --- /dev/null +++ b/test/libjulia/yulOptimizerTests/disambiguator/if_statement.yul @@ -0,0 +1,22 @@ +// yul +{ + { let a:u256, b:u256, c:u256 } + { + let a:bool + if a { let b:bool := a } + } +} +// ---- +// disambiguator +// { +// { +// let a:u256, b:u256, c:u256 +// } +// { +// let a_1:bool +// if a_1 +// { +// let b_1:bool := a_1 +// } +// } +// } diff --git a/test/libjulia/yulOptimizerTests/disambiguator/smoke.yul b/test/libjulia/yulOptimizerTests/disambiguator/smoke.yul new file mode 100644 index 00000000..d6cd8a61 --- /dev/null +++ b/test/libjulia/yulOptimizerTests/disambiguator/smoke.yul @@ -0,0 +1,5 @@ +{ } +// ---- +// disambiguator +// { +// } diff --git a/test/libjulia/yulOptimizerTests/disambiguator/smoke_yul.yul b/test/libjulia/yulOptimizerTests/disambiguator/smoke_yul.yul new file mode 100644 index 00000000..e55f4cd3 --- /dev/null +++ b/test/libjulia/yulOptimizerTests/disambiguator/smoke_yul.yul @@ -0,0 +1,6 @@ +// yul +{ } +// ---- +// disambiguator +// { +// } diff --git a/test/libjulia/yulOptimizerTests/disambiguator/switch_statement.yul b/test/libjulia/yulOptimizerTests/disambiguator/switch_statement.yul new file mode 100644 index 00000000..340ecccf --- /dev/null +++ b/test/libjulia/yulOptimizerTests/disambiguator/switch_statement.yul @@ -0,0 +1,27 @@ +// yul +{ + { let a:u256, b:u256, c:u256 } + { + let a:u256 + switch a + case 0:u256 { let b:u256 := a } + default { let c:u256 := a } + } +} +// ---- +// disambiguator +// { +// { +// let a:u256, b:u256, c:u256 +// } +// { +// let a_1:u256 +// switch a_1 +// case 0:u256 { +// let b_1:u256 := a_1 +// } +// default { +// let c_1:u256 := a_1 +// } +// } +// } diff --git a/test/libjulia/yulOptimizerTests/disambiguator/variables.yul b/test/libjulia/yulOptimizerTests/disambiguator/variables.yul new file mode 100644 index 00000000..65bd4c8f --- /dev/null +++ b/test/libjulia/yulOptimizerTests/disambiguator/variables.yul @@ -0,0 +1,12 @@ +// yul +{ { let a:u256 } { let a:u256 } } +// ---- +// disambiguator +// { +// { +// let a:u256 +// } +// { +// let a_1:u256 +// } +// } diff --git a/test/libjulia/yulOptimizerTests/disambiguator/variables_clash.yul b/test/libjulia/yulOptimizerTests/disambiguator/variables_clash.yul new file mode 100644 index 00000000..e462442a --- /dev/null +++ b/test/libjulia/yulOptimizerTests/disambiguator/variables_clash.yul @@ -0,0 +1,13 @@ +// yul +{ { let a:u256 let a_1:u256 } { let a:u256 } } +// ---- +// disambiguator +// { +// { +// let a:u256 +// let a_1:u256 +// } +// { +// let a_2:u256 +// } +// } diff --git a/test/libjulia/yulOptimizerTests/disambiguator/variables_inside_functions.yul b/test/libjulia/yulOptimizerTests/disambiguator/variables_inside_functions.yul new file mode 100644 index 00000000..e80959f6 --- /dev/null +++ b/test/libjulia/yulOptimizerTests/disambiguator/variables_inside_functions.yul @@ -0,0 +1,24 @@ +// yul +{ + { let c:u256 let b:u256 } + function f(a:u256, c:u256) -> b:u256 { let x:u256 } + { + let a:u256 let x:u256 + } +} +// ---- +// disambiguator +// { +// { +// let c:u256 +// let b:u256 +// } +// function f(a:u256, c_1:u256) -> b_1:u256 +// { +// let x:u256 +// } +// { +// let a_1:u256 +// let x_1:u256 +// } +// } diff --git a/test/libsolidity/TestCase.cpp b/test/libsolidity/TestCase.cpp index 6c4e0aea..17972269 100644 --- a/test/libsolidity/TestCase.cpp +++ b/test/libsolidity/TestCase.cpp @@ -29,7 +29,8 @@ using namespace std; bool TestCase::isTestFilename(boost::filesystem::path const& _filename) { - return _filename.extension().string() == ".sol" && + string extension = _filename.extension().string(); + return (extension == ".sol" || extension == ".yul") && !boost::starts_with(_filename.string(), "~") && !boost::starts_with(_filename.string(), "."); } diff --git a/test/tools/CMakeLists.txt b/test/tools/CMakeLists.txt index 2f107d39..bb7adc13 100644 --- a/test/tools/CMakeLists.txt +++ b/test/tools/CMakeLists.txt @@ -3,5 +3,5 @@ target_link_libraries(solfuzzer PRIVATE libsolc evmasm ${Boost_PROGRAM_OPTIONS_L add_executable(isoltest isoltest.cpp ../Options.cpp ../Common.cpp ../libsolidity/TestCase.cpp ../libsolidity/SyntaxTest.cpp ../libsolidity/AnalysisFramework.cpp ../libsolidity/SolidityExecutionFramework.cpp ../ExecutionFramework.cpp - ../RPCSession.cpp ../libsolidity/ASTJSONTest.cpp) + ../RPCSession.cpp ../libsolidity/ASTJSONTest.cpp ../libjulia/YulOptimizerTest.cpp) target_link_libraries(isoltest PRIVATE libsolc solidity evmasm ${Boost_PROGRAM_OPTIONS_LIBRARIES} ${Boost_UNIT_TEST_FRAMEWORK_LIBRARIES}) diff --git a/test/tools/isoltest.cpp b/test/tools/isoltest.cpp index dac87d1c..5134fe4f 100644 --- a/test/tools/isoltest.cpp +++ b/test/tools/isoltest.cpp @@ -21,6 +21,7 @@ #include <test/libsolidity/AnalysisFramework.h> #include <test/libsolidity/SyntaxTest.h> #include <test/libsolidity/ASTJSONTest.h> +#include <test/libjulia/YulOptimizerTest.h> #include <boost/algorithm/string.hpp> #include <boost/algorithm/string/replace.hpp> @@ -371,6 +372,8 @@ Allowed options)", TestStats global_stats{0, 0}; + // Actually run the tests. + // If you add new tests here, you also have to add them in boostTest.cpp if (auto stats = runTestSuite("Syntax", testPath / "libsolidity", "syntaxTests", SyntaxTest::create, formatted)) global_stats += *stats; else @@ -381,6 +384,17 @@ Allowed options)", else return 1; + if (auto stats = runTestSuite( + "Yul Optimizer", + testPath / "libjulia", + "yulOptimizerTests", + julia::test::YulOptimizerTest::create, + formatted + )) + global_stats += *stats; + else + return 1; + cout << endl << "Summary: "; FormattedScope(cout, formatted, {BOLD, global_stats ? GREEN : RED}) << global_stats.successCount << "/" << global_stats.testCount; |