1 /*
2 This file is part of solidity.
3
4 solidity is free software: you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation, either version 3 of the License, or
7 (at your option) any later version.
8
9 solidity is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with solidity. If not, see <http://www.gnu.org/licenses/>.
16 */
17 /**
18 * @date 2017
19 * Unit tests for the metadata output.
20 */
21
22 #include <test/Metadata.h>
23 #include <test/Common.h>
24 #include <libsolidity/interface/CompilerStack.h>
25 #include <libsolidity/interface/Version.h>
26 #include <libsolutil/SwarmHash.h>
27 #include <libsolutil/IpfsHash.h>
28 #include <libsolutil/JSON.h>
29
30 #include <boost/test/unit_test.hpp>
31
32 using namespace std;
33
34 namespace solidity::frontend::test
35 {
36
37 namespace
38 {
39
requireParsedCBORMetadata(bytes const & _bytecode,CompilerStack::MetadataFormat _metadataFormat)40 map<string, string> requireParsedCBORMetadata(bytes const& _bytecode, CompilerStack::MetadataFormat _metadataFormat)
41 {
42 bytes cborMetadata = solidity::test::onlyMetadata(_bytecode);
43 if (_metadataFormat != CompilerStack::MetadataFormat::NoMetadata)
44 {
45 BOOST_REQUIRE(!cborMetadata.empty());
46 std::optional<map<string, string>> tmp = solidity::test::parseCBORMetadata(cborMetadata);
47 BOOST_REQUIRE(tmp);
48 return *tmp;
49 }
50 BOOST_REQUIRE(cborMetadata.empty());
51 return {};
52 }
53
compileAndCheckLicenseMetadata(string const & _contractName,char const * _sourceCode)54 optional<string> compileAndCheckLicenseMetadata(string const& _contractName, char const* _sourceCode)
55 {
56 CompilerStack compilerStack;
57 compilerStack.setSources({{"A.sol", std::string(_sourceCode)}});
58 BOOST_REQUIRE_MESSAGE(compilerStack.compile(), "Compiling contract failed");
59
60 std::string const& serialisedMetadata = compilerStack.metadata(_contractName);
61 Json::Value metadata;
62 BOOST_REQUIRE(util::jsonParseStrict(serialisedMetadata, metadata));
63 BOOST_CHECK(solidity::test::isValidMetadata(metadata));
64
65 BOOST_CHECK_EQUAL(metadata["sources"].size(), 1);
66 BOOST_REQUIRE(metadata["sources"].isMember("A.sol"));
67
68 if (metadata["sources"]["A.sol"].isMember("license"))
69 {
70 BOOST_REQUIRE(metadata["sources"]["A.sol"]["license"].isString());
71 return metadata["sources"]["A.sol"]["license"].asString();
72 }
73 else
74 return nullopt;
75 }
76
77 }
78
79 BOOST_AUTO_TEST_SUITE(Metadata)
80
BOOST_AUTO_TEST_CASE(metadata_stamp)81 BOOST_AUTO_TEST_CASE(metadata_stamp)
82 {
83 // Check that the metadata stamp is at the end of the runtime bytecode.
84 char const* sourceCode = R"(
85 pragma solidity >=0.0;
86 pragma experimental __testOnlyAnalysis;
87 contract test {
88 function g(function(uint) external returns (uint) x) public {}
89 }
90 )";
91 for (auto metadataFormat: std::set<CompilerStack::MetadataFormat>{
92 CompilerStack::MetadataFormat::NoMetadata,
93 CompilerStack::MetadataFormat::WithReleaseVersionTag,
94 CompilerStack::MetadataFormat::WithPrereleaseVersionTag
95 })
96 for (auto metadataHash: set<CompilerStack::MetadataHash>{
97 CompilerStack::MetadataHash::IPFS,
98 CompilerStack::MetadataHash::Bzzr1,
99 CompilerStack::MetadataHash::None
100 })
101 {
102 CompilerStack compilerStack;
103 compilerStack.setMetadataFormat(metadataFormat);
104 compilerStack.setSources({{"", std::string(sourceCode)}});
105 compilerStack.setEVMVersion(solidity::test::CommonOptions::get().evmVersion());
106 compilerStack.setOptimiserSettings(solidity::test::CommonOptions::get().optimize);
107 compilerStack.setMetadataHash(metadataHash);
108 BOOST_REQUIRE_MESSAGE(compilerStack.compile(), "Compiling contract failed");
109 bytes const& bytecode = compilerStack.runtimeObject("test").bytecode;
110 std::string const& metadata = compilerStack.metadata("test");
111 BOOST_CHECK(solidity::test::isValidMetadata(metadata));
112
113 auto const cborMetadata = requireParsedCBORMetadata(bytecode, metadataFormat);
114 if (metadataHash == CompilerStack::MetadataHash::None)
115 BOOST_CHECK(cborMetadata.size() == (metadataFormat == CompilerStack::MetadataFormat::NoMetadata ? 0 : 1));
116 else
117 {
118 bytes hash;
119 string hashMethod;
120 if (metadataHash == CompilerStack::MetadataHash::IPFS)
121 {
122 hash = util::ipfsHash(metadata);
123 BOOST_REQUIRE(hash.size() == 34);
124 hashMethod = "ipfs";
125 }
126 else
127 {
128 hash = util::bzzr1Hash(metadata).asBytes();
129 BOOST_REQUIRE(hash.size() == 32);
130 hashMethod = "bzzr1";
131 }
132
133 if (metadataFormat != CompilerStack::MetadataFormat::NoMetadata)
134 {
135 BOOST_CHECK(cborMetadata.size() == 2);
136 BOOST_CHECK(cborMetadata.count(hashMethod) == 1);
137 BOOST_CHECK(cborMetadata.at(hashMethod) == util::toHex(hash));
138 }
139 }
140
141 if (metadataFormat == CompilerStack::MetadataFormat::NoMetadata)
142 BOOST_CHECK(cborMetadata.count("solc") == 0);
143 else
144 {
145 BOOST_CHECK(cborMetadata.count("solc") == 1);
146 if (metadataFormat == CompilerStack::MetadataFormat::WithReleaseVersionTag)
147 BOOST_CHECK(cborMetadata.at("solc") == util::toHex(VersionCompactBytes));
148 else
149 BOOST_CHECK(cborMetadata.at("solc") == VersionStringStrict);
150 }
151 }
152 }
153
BOOST_AUTO_TEST_CASE(metadata_stamp_experimental)154 BOOST_AUTO_TEST_CASE(metadata_stamp_experimental)
155 {
156 // Check that the metadata stamp is at the end of the runtime bytecode.
157 char const* sourceCode = R"(
158 pragma solidity >=0.0;
159 pragma experimental __test;
160 contract test {
161 function g(function(uint) external returns (uint) x) public {}
162 }
163 )";
164 for (auto metadataFormat: std::set<CompilerStack::MetadataFormat>{
165 CompilerStack::MetadataFormat::NoMetadata,
166 CompilerStack::MetadataFormat::WithReleaseVersionTag,
167 CompilerStack::MetadataFormat::WithPrereleaseVersionTag
168 })
169 for (auto metadataHash: set<CompilerStack::MetadataHash>{
170 CompilerStack::MetadataHash::IPFS,
171 CompilerStack::MetadataHash::Bzzr1,
172 CompilerStack::MetadataHash::None
173 })
174 {
175 CompilerStack compilerStack;
176 compilerStack.setMetadataFormat(metadataFormat);
177 compilerStack.setSources({{"", std::string(sourceCode)}});
178 compilerStack.setEVMVersion(solidity::test::CommonOptions::get().evmVersion());
179 compilerStack.setOptimiserSettings(solidity::test::CommonOptions::get().optimize);
180 compilerStack.setMetadataHash(metadataHash);
181 BOOST_REQUIRE_MESSAGE(compilerStack.compile(), "Compiling contract failed");
182 bytes const& bytecode = compilerStack.runtimeObject("test").bytecode;
183 std::string const& metadata = compilerStack.metadata("test");
184 BOOST_CHECK(solidity::test::isValidMetadata(metadata));
185
186 auto const cborMetadata = requireParsedCBORMetadata(bytecode, metadataFormat);
187 if (metadataHash == CompilerStack::MetadataHash::None)
188 BOOST_CHECK(cborMetadata.size() == (metadataFormat == CompilerStack::MetadataFormat::NoMetadata ? 0 : 2));
189 else
190 {
191 bytes hash;
192 string hashMethod;
193 if (metadataHash == CompilerStack::MetadataHash::IPFS)
194 {
195 hash = util::ipfsHash(metadata);
196 BOOST_REQUIRE(hash.size() == 34);
197 hashMethod = "ipfs";
198 }
199 else
200 {
201 hash = util::bzzr1Hash(metadata).asBytes();
202 BOOST_REQUIRE(hash.size() == 32);
203 hashMethod = "bzzr1";
204 }
205
206 if (metadataFormat != CompilerStack::MetadataFormat::NoMetadata)
207 {
208 BOOST_CHECK(cborMetadata.size() == 3);
209 BOOST_CHECK(cborMetadata.count(hashMethod) == 1);
210 BOOST_CHECK(cborMetadata.at(hashMethod) == util::toHex(hash));
211 }
212 }
213
214 if (metadataFormat == CompilerStack::MetadataFormat::NoMetadata)
215 BOOST_CHECK(cborMetadata.count("solc") == 0);
216 else
217 {
218 BOOST_CHECK(cborMetadata.count("solc") == 1);
219 if (metadataFormat == CompilerStack::MetadataFormat::WithReleaseVersionTag)
220 BOOST_CHECK(cborMetadata.at("solc") == util::toHex(VersionCompactBytes));
221 else
222 BOOST_CHECK(cborMetadata.at("solc") == VersionStringStrict);
223 BOOST_CHECK(cborMetadata.count("experimental") == 1);
224 BOOST_CHECK(cborMetadata.at("experimental") == "true");
225 }
226 }
227 }
228
BOOST_AUTO_TEST_CASE(metadata_relevant_sources)229 BOOST_AUTO_TEST_CASE(metadata_relevant_sources)
230 {
231 CompilerStack compilerStack;
232 char const* sourceCodeA = R"(
233 pragma solidity >=0.0;
234 contract A {
235 function g(function(uint) external returns (uint) x) public {}
236 }
237 )";
238 char const* sourceCodeB = R"(
239 pragma solidity >=0.0;
240 contract B {
241 function g(function(uint) external returns (uint) x) public {}
242 }
243 )";
244 compilerStack.setSources({
245 {"A", std::string(sourceCodeA)},
246 {"B", std::string(sourceCodeB)},
247 });
248 compilerStack.setEVMVersion(solidity::test::CommonOptions::get().evmVersion());
249 compilerStack.setOptimiserSettings(solidity::test::CommonOptions::get().optimize);
250 BOOST_REQUIRE_MESSAGE(compilerStack.compile(), "Compiling contract failed");
251
252 std::string const& serialisedMetadata = compilerStack.metadata("A");
253 Json::Value metadata;
254 BOOST_REQUIRE(util::jsonParseStrict(serialisedMetadata, metadata));
255 BOOST_CHECK(solidity::test::isValidMetadata(metadata));
256
257 BOOST_CHECK_EQUAL(metadata["sources"].size(), 1);
258 BOOST_CHECK(metadata["sources"].isMember("A"));
259 }
260
BOOST_AUTO_TEST_CASE(metadata_relevant_sources_imports)261 BOOST_AUTO_TEST_CASE(metadata_relevant_sources_imports)
262 {
263 CompilerStack compilerStack;
264 char const* sourceCodeA = R"(
265 pragma solidity >=0.0;
266 contract A {
267 function g(function(uint) external returns (uint) x) public virtual {}
268 }
269 )";
270 char const* sourceCodeB = R"(
271 pragma solidity >=0.0;
272 import "./A";
273 contract B is A {
274 function g(function(uint) external returns (uint) x) public virtual override {}
275 }
276 )";
277 char const* sourceCodeC = R"(
278 pragma solidity >=0.0;
279 import "./B";
280 contract C is B {
281 function g(function(uint) external returns (uint) x) public override {}
282 }
283 )";
284 compilerStack.setSources({
285 {"A", std::string(sourceCodeA)},
286 {"B", std::string(sourceCodeB)},
287 {"C", std::string(sourceCodeC)}
288 });
289 compilerStack.setEVMVersion(solidity::test::CommonOptions::get().evmVersion());
290 compilerStack.setOptimiserSettings(solidity::test::CommonOptions::get().optimize);
291 BOOST_REQUIRE_MESSAGE(compilerStack.compile(), "Compiling contract failed");
292
293 std::string const& serialisedMetadata = compilerStack.metadata("C");
294 Json::Value metadata;
295 BOOST_REQUIRE(util::jsonParseStrict(serialisedMetadata, metadata));
296 BOOST_CHECK(solidity::test::isValidMetadata(metadata));
297
298 BOOST_CHECK_EQUAL(metadata["sources"].size(), 3);
299 BOOST_CHECK(metadata["sources"].isMember("A"));
300 BOOST_CHECK(metadata["sources"].isMember("B"));
301 BOOST_CHECK(metadata["sources"].isMember("C"));
302 }
303
BOOST_AUTO_TEST_CASE(metadata_useLiteralContent)304 BOOST_AUTO_TEST_CASE(metadata_useLiteralContent)
305 {
306 // Check that the metadata contains "useLiteralContent"
307 char const* sourceCode = R"(
308 pragma solidity >=0.0;
309 contract test {
310 }
311 )";
312
313 auto check = [](char const* _src, bool _literal)
314 {
315 CompilerStack compilerStack;
316 compilerStack.setSources({{"", std::string(_src)}});
317 compilerStack.setEVMVersion(solidity::test::CommonOptions::get().evmVersion());
318 compilerStack.setOptimiserSettings(solidity::test::CommonOptions::get().optimize);
319 compilerStack.useMetadataLiteralSources(_literal);
320 BOOST_REQUIRE_MESSAGE(compilerStack.compile(), "Compiling contract failed");
321 string metadata_str = compilerStack.metadata("test");
322 Json::Value metadata;
323 BOOST_REQUIRE(util::jsonParseStrict(metadata_str, metadata));
324 BOOST_CHECK(solidity::test::isValidMetadata(metadata));
325 BOOST_CHECK(metadata.isMember("settings"));
326 BOOST_CHECK(metadata["settings"].isMember("metadata"));
327 BOOST_CHECK(metadata["settings"]["metadata"].isMember("bytecodeHash"));
328 if (_literal)
329 {
330 BOOST_CHECK(metadata["settings"]["metadata"].isMember("useLiteralContent"));
331 BOOST_CHECK(metadata["settings"]["metadata"]["useLiteralContent"].asBool());
332 }
333 };
334
335 check(sourceCode, true);
336 check(sourceCode, false);
337 }
338
BOOST_AUTO_TEST_CASE(metadata_viair)339 BOOST_AUTO_TEST_CASE(metadata_viair)
340 {
341 char const* sourceCode = R"(
342 pragma solidity >=0.0;
343 contract test {
344 }
345 )";
346
347 auto check = [](char const* _src, bool _viaIR)
348 {
349 CompilerStack compilerStack;
350 compilerStack.setSources({{"", std::string(_src)}});
351 compilerStack.setEVMVersion(solidity::test::CommonOptions::get().evmVersion());
352 compilerStack.setOptimiserSettings(solidity::test::CommonOptions::get().optimize);
353 compilerStack.setViaIR(_viaIR);
354 BOOST_REQUIRE_MESSAGE(compilerStack.compile(), "Compiling contract failed");
355
356 Json::Value metadata;
357 BOOST_REQUIRE(util::jsonParseStrict(compilerStack.metadata("test"), metadata));
358 BOOST_CHECK(solidity::test::isValidMetadata(metadata));
359 BOOST_CHECK(metadata.isMember("settings"));
360 if (_viaIR)
361 {
362 BOOST_CHECK(metadata["settings"].isMember("viaIR"));
363 BOOST_CHECK(metadata["settings"]["viaIR"].asBool());
364 }
365 else
366 BOOST_CHECK(!metadata["settings"].isMember("viaIR"));
367
368 BOOST_CHECK(compilerStack.cborMetadata("test") == compilerStack.cborMetadata("test", _viaIR));
369 BOOST_CHECK(compilerStack.cborMetadata("test") != compilerStack.cborMetadata("test", !_viaIR));
370
371 map<string, string> const parsedCBORMetadata = requireParsedCBORMetadata(
372 compilerStack.runtimeObject("test").bytecode,
373 CompilerStack::MetadataFormat::WithReleaseVersionTag
374 );
375
376 if (_viaIR)
377 {
378 BOOST_CHECK(parsedCBORMetadata.count("experimental") == 1);
379 BOOST_CHECK(parsedCBORMetadata.at("experimental") == "true");
380 }
381 else
382 BOOST_CHECK(parsedCBORMetadata.count("experimental") == 0);
383 };
384
385 check(sourceCode, true);
386 check(sourceCode, false);
387 }
388
BOOST_AUTO_TEST_CASE(metadata_revert_strings)389 BOOST_AUTO_TEST_CASE(metadata_revert_strings)
390 {
391 CompilerStack compilerStack;
392 char const* sourceCodeA = R"(
393 pragma solidity >=0.0;
394 contract A {
395 }
396 )";
397 compilerStack.setSources({{"A", std::string(sourceCodeA)}});
398 compilerStack.setRevertStringBehaviour(RevertStrings::Strip);
399 BOOST_REQUIRE_MESSAGE(compilerStack.compile(), "Compiling contract failed");
400
401 std::string const& serialisedMetadata = compilerStack.metadata("A");
402 Json::Value metadata;
403 BOOST_REQUIRE(util::jsonParseStrict(serialisedMetadata, metadata));
404 BOOST_CHECK(solidity::test::isValidMetadata(metadata));
405
406 BOOST_CHECK_EQUAL(metadata["settings"]["debug"]["revertStrings"], "strip");
407 }
408
BOOST_AUTO_TEST_CASE(metadata_license_missing)409 BOOST_AUTO_TEST_CASE(metadata_license_missing)
410 {
411 char const* sourceCode = R"(
412 pragma solidity >=0.0;
413 contract C {
414 }
415 )";
416 BOOST_CHECK(compileAndCheckLicenseMetadata("C", sourceCode) == nullopt);
417 }
418
BOOST_AUTO_TEST_CASE(metadata_license_gpl3)419 BOOST_AUTO_TEST_CASE(metadata_license_gpl3)
420 {
421 // Can't use a raw string here due to the stylechecker.
422 char const* sourceCode =
423 "// NOTE: we also add trailing whitespace after the license, to see it is trimmed.\n"
424 "// SPDX-License-Identifier: GPL-3.0 \n"
425 "pragma solidity >=0.0;\n"
426 "contract C {\n"
427 "}\n";
428 BOOST_CHECK(compileAndCheckLicenseMetadata("C", sourceCode) == "GPL-3.0");
429 }
430
BOOST_AUTO_TEST_CASE(metadata_license_whitespace_before_spdx)431 BOOST_AUTO_TEST_CASE(metadata_license_whitespace_before_spdx)
432 {
433 char const* sourceCode = R"(
434 // SPDX-License-Identifier: GPL-3.0
435 contract C {}
436 )";
437 BOOST_CHECK(compileAndCheckLicenseMetadata("C", sourceCode) == "GPL-3.0");
438 }
439
BOOST_AUTO_TEST_CASE(metadata_license_whitespace_after_colon)440 BOOST_AUTO_TEST_CASE(metadata_license_whitespace_after_colon)
441 {
442 char const* sourceCode = R"(
443 // SPDX-License-Identifier: GPL-3.0
444 contract C {}
445 )";
446 BOOST_CHECK(compileAndCheckLicenseMetadata("C", sourceCode) == "GPL-3.0");
447 }
448
BOOST_AUTO_TEST_CASE(metadata_license_gpl3_or_apache2)449 BOOST_AUTO_TEST_CASE(metadata_license_gpl3_or_apache2)
450 {
451 char const* sourceCode = R"(
452 // SPDX-License-Identifier: GPL-3.0 OR Apache-2.0
453 pragma solidity >=0.0;
454 contract C {
455 }
456 )";
457 BOOST_CHECK(compileAndCheckLicenseMetadata("C", sourceCode) == "GPL-3.0 OR Apache-2.0");
458 }
459
BOOST_AUTO_TEST_CASE(metadata_license_bidi_marks)460 BOOST_AUTO_TEST_CASE(metadata_license_bidi_marks)
461 {
462 char const* sourceCode =
463 "// \xE2\x80\xAE""0.3-LPG :reifitnedI-esneciL-XDPS\xE2\x80\xAC\n"
464 "// NOTE: The text above is reversed using Unicode directional marks. In raw form it would look like this:\n"
465 "// <LRO>0.3-LPG :reifitnedI-esneciL-XDPS<PDF>\n"
466 "contract C {}\n";
467 BOOST_CHECK(compileAndCheckLicenseMetadata("C", sourceCode) == nullopt);
468 }
469
BOOST_AUTO_TEST_CASE(metadata_license_bottom)470 BOOST_AUTO_TEST_CASE(metadata_license_bottom)
471 {
472 char const* sourceCode = R"(
473 contract C {}
474 // SPDX-License-Identifier: GPL-3.0
475 )";
476 BOOST_CHECK(compileAndCheckLicenseMetadata("C", sourceCode) == "GPL-3.0");
477 }
478
BOOST_AUTO_TEST_CASE(metadata_cr_endings)479 BOOST_AUTO_TEST_CASE(metadata_cr_endings)
480 {
481 char const* sourceCode =
482 "// SPDX-License-Identifier: GPL-3.0\r"
483 "contract C {}\r";
484 BOOST_CHECK(compileAndCheckLicenseMetadata("C", sourceCode) == "GPL-3.0");
485 }
486
BOOST_AUTO_TEST_CASE(metadata_crlf_endings)487 BOOST_AUTO_TEST_CASE(metadata_crlf_endings)
488 {
489 char const* sourceCode =
490 "// SPDX-License-Identifier: GPL-3.0\r\n"
491 "contract C {}\r\n";
492 BOOST_CHECK(compileAndCheckLicenseMetadata("C", sourceCode) == "GPL-3.0");
493 }
494
BOOST_AUTO_TEST_CASE(metadata_license_in_string)495 BOOST_AUTO_TEST_CASE(metadata_license_in_string)
496 {
497 char const* sourceCode = R"(
498 contract C {
499 bytes license = "// SPDX-License-Identifier: GPL-3.0";
500 }
501 )";
502 BOOST_CHECK(compileAndCheckLicenseMetadata("C", sourceCode) == nullopt);
503 }
504
BOOST_AUTO_TEST_CASE(metadata_license_in_contract)505 BOOST_AUTO_TEST_CASE(metadata_license_in_contract)
506 {
507 char const* sourceCode = R"(
508 contract C {
509 // SPDX-License-Identifier: GPL-3.0
510 }
511 )";
512 BOOST_CHECK(compileAndCheckLicenseMetadata("C", sourceCode) == nullopt);
513 }
514
BOOST_AUTO_TEST_CASE(metadata_license_missing_colon)515 BOOST_AUTO_TEST_CASE(metadata_license_missing_colon)
516 {
517 char const* sourceCode = R"(
518 // SPDX-License-Identifier GPL-3.0
519 contract C {}
520 )";
521 BOOST_CHECK(compileAndCheckLicenseMetadata("C", sourceCode) == nullopt);
522 }
523
BOOST_AUTO_TEST_CASE(metadata_license_multiline)524 BOOST_AUTO_TEST_CASE(metadata_license_multiline)
525 {
526 char const* sourceCode = R"(
527 /* SPDX-License-Identifier: GPL-3.0 */
528 contract C {}
529 )";
530 BOOST_CHECK(compileAndCheckLicenseMetadata("C", sourceCode) == "GPL-3.0");
531 }
532
BOOST_AUTO_TEST_CASE(metadata_license_natspec)533 BOOST_AUTO_TEST_CASE(metadata_license_natspec)
534 {
535 char const* sourceCode = R"(
536 /// SPDX-License-Identifier: GPL-3.0
537 contract C {}
538 )";
539 BOOST_CHECK(compileAndCheckLicenseMetadata("C", sourceCode) == "GPL-3.0");
540 }
541
BOOST_AUTO_TEST_CASE(metadata_license_natspec_multiline)542 BOOST_AUTO_TEST_CASE(metadata_license_natspec_multiline)
543 {
544 char const* sourceCode = R"(
545 /** SPDX-License-Identifier: GPL-3.0 */
546 contract C {}
547 )";
548 BOOST_CHECK(compileAndCheckLicenseMetadata("C", sourceCode) == "GPL-3.0");
549 }
550
BOOST_AUTO_TEST_CASE(metadata_license_no_whitespace_multiline)551 BOOST_AUTO_TEST_CASE(metadata_license_no_whitespace_multiline)
552 {
553 char const* sourceCode = R"(
554 /*SPDX-License-Identifier:GPL-3.0*/
555 contract C {}
556 )";
557 BOOST_CHECK(compileAndCheckLicenseMetadata("C", sourceCode) == "GPL-3.0");
558 }
559
BOOST_AUTO_TEST_CASE(metadata_license_nonempty_line)560 BOOST_AUTO_TEST_CASE(metadata_license_nonempty_line)
561 {
562 char const* sourceCode = R"(
563 pragma solidity >= 0.0; // SPDX-License-Identifier: GPL-3.0
564 contract C {}
565 )";
566 BOOST_CHECK(compileAndCheckLicenseMetadata("C", sourceCode) == "GPL-3.0");
567 }
568
BOOST_AUTO_TEST_CASE(metadata_license_no_whitespace)569 BOOST_AUTO_TEST_CASE(metadata_license_no_whitespace)
570 {
571 char const* sourceCode = R"(
572 //SPDX-License-Identifier:GPL-3.0
573 contract C {}
574 )";
575 BOOST_CHECK(compileAndCheckLicenseMetadata("C", sourceCode) == "GPL-3.0");
576 }
577
578 BOOST_AUTO_TEST_SUITE_END()
579
580 }
581