|
12 | 12 | along with solidity. If not, see <http://www.gnu.org/licenses/>.
|
13 | 13 | */
|
14 | 14 |
|
15 |
| -#include <test/libsolidity/SemanticTest.h> |
16 |
| -#include <test/libsolidity/util/BytesUtils.h> |
17 |
| -#include <libsolutil/Whiskers.h> |
18 |
| -#include <libyul/Exceptions.h> |
19 |
| -#include <test/Common.h> |
20 | 15 | #include <boost/algorithm/string.hpp>
|
21 | 16 | #include <boost/algorithm/string/predicate.hpp>
|
22 | 17 | #include <boost/algorithm/string/trim.hpp>
|
23 | 18 | #include <boost/throw_exception.hpp>
|
| 19 | +#include <libsolutil/Whiskers.h> |
| 20 | +#include <libyul/Exceptions.h> |
| 21 | +#include <test/Common.h> |
| 22 | +#include <test/libsolidity/SemanticTest.h> |
| 23 | +#include <test/libsolidity/util/BytesUtils.h> |
| 24 | + |
| 25 | +#include <test/libsolidity/Behaviour.h> |
| 26 | +#include <test/libsolidity/Builtin.h> |
| 27 | +#include <test/libsolidity/behaviour/LogsBehaviour.h> |
| 28 | +#include <test/libsolidity/behaviour/SmokeBehaviour.h> |
24 | 29 |
|
25 | 30 | #include <algorithm>
|
26 | 31 | #include <cctype>
|
@@ -50,13 +55,24 @@ SemanticTest::SemanticTest(string const& _filename, langutil::EVMVersion _evmVer
|
50 | 55 | m_enforceViaYul(enforceViaYul)
|
51 | 56 | {
|
52 | 57 | using namespace std::placeholders;
|
53 |
| - m_builtins |
54 |
| - = {{"smoke", |
55 |
| - { |
56 |
| - {"test0", {std::bind(&SemanticTest::builtinSmokeTest, this, _1)}}, |
57 |
| - {"test1", {std::bind(&SemanticTest::builtinSmokeTest, this, _1)}}, |
58 |
| - {"test2", {std::bind(&SemanticTest::builtinSmokeTest, this, _1)}}, |
59 |
| - }}}; |
| 58 | + // clang-format off |
| 59 | + auto simpleSmokeBuiltin = std::make_shared<Builtin>( |
| 60 | + std::bind(&SemanticTest::builtinSmokeTest, this, _1) |
| 61 | + ); |
| 62 | + m_builtins = |
| 63 | + { |
| 64 | + {"smoke", |
| 65 | + {{"test0", simpleSmokeBuiltin}, |
| 66 | + {"test1", simpleSmokeBuiltin}, |
| 67 | + {"test2", simpleSmokeBuiltin}} |
| 68 | + } |
| 69 | + }; |
| 70 | + m_behaviours = |
| 71 | + { |
| 72 | + std::make_shared<SmokeBehaviour>(), |
| 73 | + std::make_shared<LogsBehaviour>(this) |
| 74 | + }; |
| 75 | + // clang-format on |
60 | 76 |
|
61 | 77 | string choice = m_reader.stringSetting("compileViaYul", "default");
|
62 | 78 | if (choice == "also")
|
@@ -130,7 +146,13 @@ TestCase::TestResult SemanticTest::run(ostream& _stream, string const& _linePref
|
130 | 146 | return result;
|
131 | 147 | }
|
132 | 148 |
|
133 |
| -TestCase::TestResult SemanticTest::runTest(ostream& _stream, string const& _linePrefix, bool _formatted, bool _compileViaYul, bool _compileToEwasm) |
| 149 | +void SemanticTest::addBuiltin(std::string _module, std::string _function, std::shared_ptr<Builtin> _builtin) |
| 150 | +{ |
| 151 | + m_builtins[_module][_function] = _builtin; |
| 152 | +} |
| 153 | + |
| 154 | +TestCase::TestResult SemanticTest::runTest( |
| 155 | + ostream& _stream, string const& _linePrefix, bool _formatted, bool _compileViaYul, bool _compileToEwasm) |
134 | 156 | {
|
135 | 157 | bool success = true;
|
136 | 158 |
|
@@ -160,11 +182,28 @@ TestCase::TestResult SemanticTest::runTest(ostream& _stream, string const& _line
|
160 | 182 |
|
161 | 183 | bool constructed = false;
|
162 | 184 |
|
| 185 | + // Iterate through the test calls and set the previous call. |
| 186 | + TestFunctionCall* previousCall{nullptr}; |
| 187 | + for (auto& test: m_tests) |
| 188 | + { |
| 189 | + test.setPreviousCall(previousCall); |
| 190 | + test.setBehaviours(&m_behaviours); |
| 191 | + previousCall = &test; |
| 192 | + } |
| 193 | + |
| 194 | + for (auto& behaviour: m_behaviours) |
| 195 | + behaviour->begin(); |
| 196 | + |
163 | 197 | for (auto& test: m_tests)
|
164 | 198 | {
|
| 199 | + for (auto& behaviour: m_behaviours) |
| 200 | + behaviour->before(test); |
| 201 | + |
165 | 202 | if (constructed)
|
166 | 203 | {
|
167 |
| - soltestAssert(test.call().kind != FunctionCall::Kind::Library, "Libraries have to be deployed before any other call."); |
| 204 | + soltestAssert( |
| 205 | + test.call().kind != FunctionCall::Kind::Library, |
| 206 | + "Libraries have to be deployed before any other call."); |
168 | 207 | soltestAssert(
|
169 | 208 | test.call().kind != FunctionCall::Kind::Constructor,
|
170 | 209 | "Constructor has to be the first function call expect for library deployments.");
|
@@ -214,7 +253,7 @@ TestCase::TestResult SemanticTest::runTest(ostream& _stream, string const& _line
|
214 | 253 | boost::split(builtinPath, test.call().signature, boost::is_any_of("."));
|
215 | 254 | soltestAssert(builtinPath.size() == 2, "");
|
216 | 255 | auto builtin = m_builtins[builtinPath.front()][builtinPath.back()];
|
217 |
| - std::optional<bytes> builtinOutput{builtin.function(test.call())}; |
| 256 | + std::optional<bytes> builtinOutput{builtin->builtin(test.call())}; |
218 | 257 | if (builtinOutput.has_value())
|
219 | 258 | {
|
220 | 259 | test.setFailure(false);
|
@@ -245,7 +284,7 @@ TestCase::TestResult SemanticTest::runTest(ostream& _stream, string const& _line
|
245 | 284 | boost::split(builtinPath, test.call().expectations.builtin->signature, boost::is_any_of("."));
|
246 | 285 | assert(builtinPath.size() == 2);
|
247 | 286 | auto builtin = m_builtins[builtinPath.front()][builtinPath.back()];
|
248 |
| - std::optional<bytes> builtinResult = builtin.function(*test.call().expectations.builtin); |
| 287 | + std::optional<bytes> builtinResult = builtin->builtin(*test.call().expectations.builtin); |
249 | 288 | if (builtinResult.has_value())
|
250 | 289 | expectationOutput = builtinResult.value();
|
251 | 290 | else
|
@@ -273,8 +312,29 @@ TestCase::TestResult SemanticTest::runTest(ostream& _stream, string const& _line
|
273 | 312 | test.setRawBytes(std::move(output));
|
274 | 313 | test.setContractABI(m_compiler.contractABI(m_compiler.lastContractName()));
|
275 | 314 | }
|
| 315 | + |
| 316 | + for (auto& behaviour: m_behaviours) |
| 317 | + behaviour->after(test); |
| 318 | + } |
| 319 | + |
| 320 | + // The artificialFunctionCall is an artificially created function call, |
| 321 | + // where it's previous call is pointing to the last call of the test. |
| 322 | + TestFunctionCall artificialFunctionCall(FunctionCall{}); |
| 323 | + artificialFunctionCall.setBehaviours(&m_behaviours); |
| 324 | + artificialFunctionCall.setPreviousCall(previousCall); |
| 325 | + for (auto& behaviour: m_behaviours) |
| 326 | + { |
| 327 | + behaviour->before(artificialFunctionCall); |
| 328 | + behaviour->after(artificialFunctionCall); |
276 | 329 | }
|
277 | 330 |
|
| 331 | + for (auto& behaviour: m_behaviours) |
| 332 | + behaviour->end(); |
| 333 | + |
| 334 | + for (auto& test: m_tests) |
| 335 | + for (auto& behaviour: m_behaviours) |
| 336 | + success &= behaviour->isValid(test); |
| 337 | + |
278 | 338 | if (!m_runWithYul && _compileViaYul)
|
279 | 339 | {
|
280 | 340 | m_compileViaYulCanBeSet = success;
|
|
0 commit comments