mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Merge pull request #10676 from ethereum/cli-bytecode-comparison
Bytecode comparison via CLI interface
This commit is contained in:
commit
46bb81d7ae
@ -925,13 +925,19 @@ jobs:
|
||||
- checkout
|
||||
- attach_workspace:
|
||||
at: build
|
||||
- run: scripts/bytecodecompare/storebytecode.sh && cp -v report.txt bytecode-report-ubuntu.txt
|
||||
- run: mkdir test-cases/
|
||||
- run: cd test-cases && ../scripts/isolate_tests.py ../test/
|
||||
- run: cd test-cases && ../scripts/bytecodecompare/prepare_report.py ../build/solc/solc --interface standard-json && mv -v report.txt ../bytecode-report-ubuntu-json.txt
|
||||
- run: cd test-cases && ../scripts/bytecodecompare/prepare_report.py ../build/solc/solc --interface cli && mv -v report.txt ../bytecode-report-ubuntu-cli.txt
|
||||
- store_artifacts:
|
||||
path: report.txt
|
||||
path: bytecode-report-ubuntu-json.txt
|
||||
- store_artifacts:
|
||||
path: bytecode-report-ubuntu-cli.txt
|
||||
- persist_to_workspace:
|
||||
root: .
|
||||
paths:
|
||||
- bytecode-report-ubuntu.txt
|
||||
- bytecode-report-ubuntu-json.txt
|
||||
- bytecode-report-ubuntu-cli.txt
|
||||
|
||||
b_bytecode_osx:
|
||||
macos:
|
||||
@ -942,13 +948,19 @@ jobs:
|
||||
- checkout
|
||||
- attach_workspace:
|
||||
at: .
|
||||
- run: scripts/bytecodecompare/storebytecode.sh && cp -v report.txt bytecode-report-osx.txt
|
||||
- run: mkdir test-cases/
|
||||
- run: cd test-cases && ../scripts/isolate_tests.py ../test/
|
||||
- run: cd test-cases && ../scripts/bytecodecompare/prepare_report.py ../build/solc/solc --interface standard-json && mv -v report.txt ../bytecode-report-osx-json.txt
|
||||
- run: cd test-cases && ../scripts/bytecodecompare/prepare_report.py ../build/solc/solc --interface cli && mv -v report.txt ../bytecode-report-osx-cli.txt
|
||||
- store_artifacts:
|
||||
path: report.txt
|
||||
path: bytecode-report-osx-json.txt
|
||||
- store_artifacts:
|
||||
path: bytecode-report-osx-cli.txt
|
||||
- persist_to_workspace:
|
||||
root: .
|
||||
paths:
|
||||
- bytecode-report-osx.txt
|
||||
- bytecode-report-osx-json.txt
|
||||
- bytecode-report-osx-cli.txt
|
||||
|
||||
b_bytecode_win:
|
||||
executor:
|
||||
@ -961,15 +973,19 @@ jobs:
|
||||
- checkout
|
||||
- attach_workspace:
|
||||
at: build
|
||||
- run: python scripts\isolate_tests.py test\
|
||||
- run: python scripts\bytecodecompare\prepare_report.py build\solc\Release\solc.exe
|
||||
- run: cp report.txt bytecode-report-windows.txt
|
||||
- run: mkdir test-cases\
|
||||
- run: cd test-cases\ && python ..\scripts\isolate_tests.py ..\test\
|
||||
- run: cd test-cases\ && python ..\scripts\bytecodecompare\prepare_report.py ..\build\solc\Release\solc.exe --interface standard-json && move report.txt ..\bytecode-report-windows-json.txt
|
||||
- run: cd test-cases\ && python ..\scripts\bytecodecompare\prepare_report.py ..\build\solc\Release\solc.exe --interface cli && move report.txt ..\bytecode-report-windows-cli.txt
|
||||
- store_artifacts:
|
||||
path: report.txt
|
||||
path: bytecode-report-windows-json.txt
|
||||
- store_artifacts:
|
||||
path: bytecode-report-windows-cli.txt
|
||||
- persist_to_workspace:
|
||||
root: .
|
||||
paths:
|
||||
- bytecode-report-windows.txt
|
||||
- bytecode-report-windows-json.txt
|
||||
- bytecode-report-windows-cli.txt
|
||||
|
||||
b_bytecode_ems:
|
||||
docker:
|
||||
@ -980,9 +996,9 @@ jobs:
|
||||
- checkout
|
||||
- attach_workspace:
|
||||
at: emscripten_build/libsolc
|
||||
- run: scripts/bytecodecompare/storebytecode.sh && cp -v report.txt bytecode-report-emscripten.txt
|
||||
- run: scripts/bytecodecompare/storebytecode.sh && mv -v report.txt bytecode-report-emscripten.txt
|
||||
- store_artifacts:
|
||||
path: report.txt
|
||||
path: bytecode-report-emscripten.txt
|
||||
- persist_to_workspace:
|
||||
root: .
|
||||
paths:
|
||||
@ -994,7 +1010,15 @@ jobs:
|
||||
steps:
|
||||
- attach_workspace:
|
||||
at: .
|
||||
- run: diff --report-identical-files --from-file bytecode-report-emscripten.txt bytecode-report-ubuntu.txt bytecode-report-osx.txt bytecode-report-windows.txt
|
||||
- run: |
|
||||
diff --report-identical-files --from-file \
|
||||
bytecode-report-emscripten.txt \
|
||||
bytecode-report-ubuntu-json.txt \
|
||||
bytecode-report-ubuntu-cli.txt \
|
||||
bytecode-report-osx-json.txt \
|
||||
bytecode-report-osx-cli.txt \
|
||||
bytecode-report-windows-json.txt \
|
||||
bytecode-report-windows-cli.txt
|
||||
|
||||
workflows:
|
||||
version: 2
|
||||
|
@ -24,10 +24,25 @@ for (const optimize of [false, true])
|
||||
|
||||
const result = JSON.parse(compiler.compile(JSON.stringify(input)))
|
||||
|
||||
let internalCompilerError = false
|
||||
if ('errors' in result)
|
||||
{
|
||||
for (const error of result['errors'])
|
||||
// JSON interface still returns contract metadata in case of an internal compiler error while
|
||||
// CLI interface does not. To make reports comparable we must force this case to be detected as
|
||||
// an error in both cases.
|
||||
if (['UnimplementedFeatureError', 'CompilerError', 'CodeGenerationError'].includes(error['type']))
|
||||
{
|
||||
internalCompilerError = true
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if (
|
||||
!('contracts' in result) ||
|
||||
Object.keys(result['contracts']).length === 0 ||
|
||||
Object.keys(result['contracts']).every(file => Object.keys(result['contracts'][file]).length === 0)
|
||||
Object.keys(result['contracts']).every(file => Object.keys(result['contracts'][file]).length === 0) ||
|
||||
internalCompilerError
|
||||
)
|
||||
// NOTE: do not exit here because this may be run on source which cannot be compiled
|
||||
console.log(filename + ': <ERROR>')
|
||||
|
@ -3,13 +3,26 @@
|
||||
import sys
|
||||
import subprocess
|
||||
import json
|
||||
import re
|
||||
from argparse import ArgumentParser
|
||||
from dataclasses import dataclass
|
||||
from enum import Enum
|
||||
from glob import glob
|
||||
from pathlib import Path
|
||||
from tempfile import TemporaryDirectory
|
||||
from typing import List, Optional, Tuple, Union
|
||||
|
||||
|
||||
CONTRACT_SEPARATOR_PATTERN = re.compile(r'^======= (?P<file_name>.+):(?P<contract_name>[^:]+) =======$', re.MULTILINE)
|
||||
BYTECODE_REGEX = re.compile(r'^Binary:\n(?P<bytecode>.*)$', re.MULTILINE)
|
||||
METADATA_REGEX = re.compile(r'^Metadata:\n(?P<metadata>\{.*\})$', re.MULTILINE)
|
||||
|
||||
|
||||
class CompilerInterface(Enum):
|
||||
CLI = 'cli'
|
||||
STANDARD_JSON = 'standard-json'
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class ContractReport:
|
||||
contract_name: str
|
||||
@ -53,10 +66,19 @@ def load_source(path: Union[Path, str]) -> str:
|
||||
def parse_standard_json_output(source_file_name: Path, standard_json_output: str) -> FileReport:
|
||||
decoded_json_output = json.loads(standard_json_output.strip())
|
||||
|
||||
# JSON interface still returns contract metadata in case of an internal compiler error while
|
||||
# CLI interface does not. To make reports comparable we must force this case to be detected as
|
||||
# an error in both cases.
|
||||
internal_compiler_error = any(
|
||||
error['type'] in ['UnimplementedFeatureError', 'CompilerError', 'CodeGenerationError']
|
||||
for error in decoded_json_output.get('errors', {})
|
||||
)
|
||||
|
||||
if (
|
||||
'contracts' not in decoded_json_output or
|
||||
len(decoded_json_output['contracts']) == 0 or
|
||||
all(len(file_results) == 0 for file_name, file_results in decoded_json_output['contracts'].items())
|
||||
all(len(file_results) == 0 for file_name, file_results in decoded_json_output['contracts'].items()) or
|
||||
internal_compiler_error
|
||||
):
|
||||
return FileReport(file_name=source_file_name, contract_reports=None)
|
||||
|
||||
@ -74,7 +96,40 @@ def parse_standard_json_output(source_file_name: Path, standard_json_output: str
|
||||
return file_report
|
||||
|
||||
|
||||
def prepare_compiler_input(compiler_path: Path, source_file_name: Path, optimize: bool) -> Tuple[List[str], str]:
|
||||
def parse_cli_output(source_file_name: Path, cli_output: str) -> FileReport:
|
||||
# re.split() returns a list containing the text between pattern occurrences but also inserts the
|
||||
# content of matched groups in between. It also never omits the empty elements so the number of
|
||||
# list items is predictable (3 per match + the text before the first match)
|
||||
output_segments = re.split(CONTRACT_SEPARATOR_PATTERN, cli_output)
|
||||
assert len(output_segments) % 3 == 1
|
||||
|
||||
if len(output_segments) == 1:
|
||||
return FileReport(file_name=source_file_name, contract_reports=None)
|
||||
|
||||
file_report = FileReport(file_name=source_file_name, contract_reports=[])
|
||||
for file_name, contract_name, contract_output in zip(output_segments[1::3], output_segments[2::3], output_segments[3::3]):
|
||||
bytecode_match = re.search(BYTECODE_REGEX, contract_output)
|
||||
metadata_match = re.search(METADATA_REGEX, contract_output)
|
||||
|
||||
assert file_report.contract_reports is not None
|
||||
file_report.contract_reports.append(ContractReport(
|
||||
contract_name=contract_name,
|
||||
file_name=Path(file_name),
|
||||
bytecode=bytecode_match['bytecode'] if bytecode_match is not None else None,
|
||||
metadata=metadata_match['metadata'] if metadata_match is not None else None,
|
||||
))
|
||||
|
||||
return file_report
|
||||
|
||||
|
||||
def prepare_compiler_input(
|
||||
compiler_path: Path,
|
||||
source_file_name: Path,
|
||||
optimize: bool,
|
||||
interface: CompilerInterface
|
||||
) -> Tuple[List[str], str]:
|
||||
|
||||
if interface == CompilerInterface.STANDARD_JSON:
|
||||
json_input: dict = {
|
||||
'language': 'Solidity',
|
||||
'sources': {
|
||||
@ -89,12 +144,34 @@ def prepare_compiler_input(compiler_path: Path, source_file_name: Path, optimize
|
||||
|
||||
command_line = [str(compiler_path), '--standard-json']
|
||||
compiler_input = json.dumps(json_input)
|
||||
else:
|
||||
assert interface == CompilerInterface.CLI
|
||||
|
||||
compiler_options = [str(source_file_name), '--bin', '--metadata', '--model-checker-engine', 'none']
|
||||
if optimize:
|
||||
compiler_options.append('--optimize')
|
||||
|
||||
command_line = [str(compiler_path)] + compiler_options
|
||||
compiler_input = load_source(source_file_name)
|
||||
|
||||
return (command_line, compiler_input)
|
||||
|
||||
|
||||
def run_compiler(compiler_path: Path, source_file_name: Path, optimize: bool) -> FileReport:
|
||||
(command_line, compiler_input) = prepare_compiler_input(compiler_path, Path(Path(source_file_name).name), optimize)
|
||||
def run_compiler(
|
||||
compiler_path: Path,
|
||||
source_file_name: Path,
|
||||
optimize: bool,
|
||||
interface: CompilerInterface,
|
||||
tmp_dir: Path,
|
||||
) -> FileReport:
|
||||
|
||||
if interface == CompilerInterface.STANDARD_JSON:
|
||||
(command_line, compiler_input) = prepare_compiler_input(
|
||||
compiler_path,
|
||||
Path(source_file_name.name),
|
||||
optimize,
|
||||
interface
|
||||
)
|
||||
|
||||
process = subprocess.run(
|
||||
command_line,
|
||||
@ -105,14 +182,42 @@ def run_compiler(compiler_path: Path, source_file_name: Path, optimize: bool) ->
|
||||
)
|
||||
|
||||
return parse_standard_json_output(Path(source_file_name), process.stdout)
|
||||
else:
|
||||
assert interface == CompilerInterface.CLI
|
||||
assert tmp_dir is not None
|
||||
|
||||
(command_line, compiler_input) = prepare_compiler_input(
|
||||
compiler_path.absolute(),
|
||||
Path(source_file_name.name),
|
||||
optimize,
|
||||
interface
|
||||
)
|
||||
|
||||
# Create a copy that we can use directly with the CLI interface
|
||||
modified_source_path = tmp_dir / source_file_name.name
|
||||
# NOTE: newline='' disables newline conversion.
|
||||
# We want the file exactly as is because changing even a single byte in the source affects metadata.
|
||||
with open(modified_source_path, 'w', encoding='utf8', newline='') as modified_source_file:
|
||||
modified_source_file.write(compiler_input)
|
||||
|
||||
process = subprocess.run(
|
||||
command_line,
|
||||
cwd=tmp_dir,
|
||||
encoding='utf8',
|
||||
capture_output=True,
|
||||
check=False,
|
||||
)
|
||||
|
||||
return parse_cli_output(Path(source_file_name), process.stdout)
|
||||
|
||||
|
||||
def generate_report(source_file_names: List[str], compiler_path: Path):
|
||||
def generate_report(source_file_names: List[str], compiler_path: Path, interface: CompilerInterface):
|
||||
with open('report.txt', mode='w', encoding='utf8', newline='\n') as report_file:
|
||||
for optimize in [False, True]:
|
||||
with TemporaryDirectory(prefix='prepare_report-') as tmp_dir:
|
||||
for source_file_name in sorted(source_file_names):
|
||||
try:
|
||||
report = run_compiler(Path(compiler_path), Path(source_file_name), optimize)
|
||||
report = run_compiler(compiler_path, Path(source_file_name), optimize, interface, Path(tmp_dir))
|
||||
report_file.write(report.format_report())
|
||||
except subprocess.CalledProcessError as exception:
|
||||
print(
|
||||
@ -140,6 +245,13 @@ def commandline_parser() -> ArgumentParser:
|
||||
|
||||
parser = ArgumentParser(description=script_description)
|
||||
parser.add_argument(dest='compiler_path', help="Solidity compiler executable")
|
||||
parser.add_argument(
|
||||
'--interface',
|
||||
dest='interface',
|
||||
default=CompilerInterface.STANDARD_JSON.value,
|
||||
choices=[c.value for c in CompilerInterface],
|
||||
help="Compiler interface to use."
|
||||
)
|
||||
return parser;
|
||||
|
||||
|
||||
@ -148,4 +260,5 @@ if __name__ == "__main__":
|
||||
generate_report(
|
||||
glob("*.sol"),
|
||||
Path(options.compiler_path),
|
||||
CompilerInterface(options.interface),
|
||||
)
|
||||
|
@ -0,0 +1,8 @@
|
||||
Warning: SPDX license identifier not provided in source file. Before publishing, consider adding a comment containing "SPDX-License-Identifier: <SPDX-License>" to each source file. Use "SPDX-License-Identifier: UNLICENSED" for non-open-source code. Please see https://spdx.org for more information.
|
||||
--> test_1c3426238b8296745d8d8bd0ff995ab65a51992b568dc7c5ce73c3f59b107825_no_assignments_sol.sol
|
||||
|
||||
Warning: Source file does not specify required compiler version! Consider adding "pragma solidity ^0.8.0;"
|
||||
--> test_1c3426238b8296745d8d8bd0ff995ab65a51992b568dc7c5ce73c3f59b107825_no_assignments_sol.sol
|
||||
|
||||
Error: Some immutables were read from but never assigned, possibly because of optimization.
|
||||
|
50
test/scripts/fixtures/code_generation_error_json_output.json
Normal file
50
test/scripts/fixtures/code_generation_error_json_output.json
Normal file
@ -0,0 +1,50 @@
|
||||
{
|
||||
"contracts": {
|
||||
"syntaxTests/immutable/no_assignments.sol": {
|
||||
"C": {
|
||||
"metadata": "{\"compiler\":{\"version\":\"0.8.0+commit.c7dfd78e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"f\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"syntaxTests/immutable/no_assignments.sol\":\"C\"},\"evmVersion\":\"istanbul\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"syntaxTests/immutable/no_assignments.sol\":{\"keccak256\":\"0xbafaec265150d52cd293787144247b1a0a782adf3cb89296fb4f0eb05dc25739\",\"urls\":[\"bzz-raw://7c01dbb8146347c8cf62469d57a0e290f7ef1b871426d86d995315160db665c0\",\"dweb:/ipfs/QmPrYtxVbFCFeXwnhcHoBgbg546EqMzQCT5kK7wLc3rat8\"]}},\"version\":1}"
|
||||
}
|
||||
}
|
||||
},
|
||||
"errors": [
|
||||
{
|
||||
"component": "general",
|
||||
"errorCode": "1878",
|
||||
"formattedMessage": "Warning: SPDX license identifier not provided in source file. Before publishing, consider adding a comment containing \"SPDX-License-Identifier: <SPDX-License>\" to each source file. Use \"SPDX-License-Identifier: UNLICENSED\" for non-open-source code. Please see https://spdx.org for more information.\n--> syntaxTests/immutable/no_assignments.sol\n\n",
|
||||
"message": "SPDX license identifier not provided in source file. Before publishing, consider adding a comment containing \"SPDX-License-Identifier: <SPDX-License>\" to each source file. Use \"SPDX-License-Identifier: UNLICENSED\" for non-open-source code. Please see https://spdx.org for more information.",
|
||||
"severity": "warning",
|
||||
"sourceLocation": {
|
||||
"end": -1,
|
||||
"file": "syntaxTests/immutable/no_assignments.sol",
|
||||
"start": -1
|
||||
},
|
||||
"type": "Warning"
|
||||
},
|
||||
{
|
||||
"component": "general",
|
||||
"errorCode": "3420",
|
||||
"formattedMessage": "Warning: Source file does not specify required compiler version! Consider adding \"pragma solidity ^0.8.0;\"\n--> syntaxTests/immutable/no_assignments.sol\n\n",
|
||||
"message": "Source file does not specify required compiler version! Consider adding \"pragma solidity ^0.8.0;\"",
|
||||
"severity": "warning",
|
||||
"sourceLocation": {
|
||||
"end": -1,
|
||||
"file": "syntaxTests/immutable/no_assignments.sol",
|
||||
"start": -1
|
||||
},
|
||||
"type": "Warning"
|
||||
},
|
||||
{
|
||||
"component": "general",
|
||||
"errorCode": "1284",
|
||||
"formattedMessage": "CodeGenerationError: Some immutables were read from but never assigned, possibly because of optimization.\n\n",
|
||||
"message": "Some immutables were read from but never assigned, possibly because of optimization.",
|
||||
"severity": "error",
|
||||
"type": "CodeGenerationError"
|
||||
}
|
||||
],
|
||||
"sources": {
|
||||
"syntaxTests/immutable/no_assignments.sol": {
|
||||
"id": 0
|
||||
}
|
||||
}
|
||||
}
|
24
test/scripts/fixtures/library_inherited2_sol_cli_output.txt
Normal file
24
test/scripts/fixtures/library_inherited2_sol_cli_output.txt
Normal file
@ -0,0 +1,24 @@
|
||||
Warning: SPDX license identifier not provided in source file. Before publishing, consider adding a comment containing "SPDX-License-Identifier: <SPDX-License>" to each source file. Use "SPDX-License-Identifier: UNLICENSED" for non-open-source code. Please see https://spdx.org for more information.
|
||||
--> syntaxTests/scoping/library_inherited2.sol
|
||||
|
||||
Warning: Source file does not specify required compiler version! Consider adding "pragma solidity ^0.8.0;"
|
||||
--> syntaxTests/scoping/library_inherited2.sol
|
||||
|
||||
|
||||
======= syntaxTests/scoping/library_inherited2.sol:A =======
|
||||
Binary:
|
||||
6080604052348015600f57600080fd5b50603f80601d6000396000f3fe6080604052600080fdfea264697066735822122086e727f29d40b264a19bbfcad38d64493dca4bab5dbba8c82ffdaae389d2bba064736f6c63430008000033
|
||||
Metadata:
|
||||
{"compiler":{"version":"0.8.0+commit.c7dfd78e"},"language":"Solidity","output":{"abi":[],"devdoc":{"kind":"dev","methods":{},"version":1},"userdoc":{"kind":"user","methods":{},"version":1}},"settings":{"compilationTarget":{"syntaxTests/scoping/library_inherited2.sol":"A"},"evmVersion":"istanbul","libraries":{},"metadata":{"bytecodeHash":"ipfs"},"optimizer":{"enabled":false,"runs":200},"remappings":[]},"sources":{"syntaxTests/scoping/library_inherited2.sol":{"keccak256":"0xd0619f00638fdfea187368965615dbd599fead93dd14b6558725e85ec7011d96","urls":["bzz-raw://ec7af066be66a223f0d25ba3bf9ba6dc103e1a57531a66a38a5ca2b6ce172f55","dweb:/ipfs/QmW1NrqQNhnY1Tkgr3Z9oM8buCGLUJCJVCDTVejJTT5Vet"]}},"version":1}
|
||||
|
||||
======= syntaxTests/scoping/library_inherited2.sol:B =======
|
||||
Binary:
|
||||
608060405234801561001057600080fd5b506101cc806100206000396000f3fe608060405234801561001057600080fd5b506004361061002b5760003560e01c80630423a13214610030575b600080fd5b61004a6004803603810190610045919061009d565b610060565b60405161005791906100d5565b60405180910390f35b600061006b82610072565b9050919050565b6000602a8261008191906100f0565b9050919050565b6000813590506100978161017f565b92915050565b6000602082840312156100af57600080fd5b60006100bd84828501610088565b91505092915050565b6100cf81610146565b82525050565b60006020820190506100ea60008301846100c6565b92915050565b60006100fb82610146565b915061010683610146565b9250827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0382111561013b5761013a610150565b5b828201905092915050565b6000819050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b61018881610146565b811461019357600080fd5b5056fea2646970667358221220104c345633313efe410492448844d96d78452c3044ce126b5e041b7fbeaa790064736f6c63430008000033
|
||||
Metadata:
|
||||
{"compiler":{"version":"0.8.0+commit.c7dfd78e"},"language":"Solidity","output":{"abi":[{"inputs":[{"internalType":"uint256","name":"value","type":"uint256"}],"name":"bar","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"}],"devdoc":{"kind":"dev","methods":{},"version":1},"userdoc":{"kind":"user","methods":{},"version":1}},"settings":{"compilationTarget":{"syntaxTests/scoping/library_inherited2.sol":"B"},"evmVersion":"istanbul","libraries":{},"metadata":{"bytecodeHash":"ipfs"},"optimizer":{"enabled":false,"runs":200},"remappings":[]},"sources":{"syntaxTests/scoping/library_inherited2.sol":{"keccak256":"0xd0619f00638fdfea187368965615dbd599fead93dd14b6558725e85ec7011d96","urls":["bzz-raw://ec7af066be66a223f0d25ba3bf9ba6dc103e1a57531a66a38a5ca2b6ce172f55","dweb:/ipfs/QmW1NrqQNhnY1Tkgr3Z9oM8buCGLUJCJVCDTVejJTT5Vet"]}},"version":1}
|
||||
|
||||
======= syntaxTests/scoping/library_inherited2.sol:Lib =======
|
||||
Binary:
|
||||
60566050600b82828239805160001a6073146043577f4e487b7100000000000000000000000000000000000000000000000000000000600052600060045260246000fd5b30600052607381538281f3fe73000000000000000000000000000000000000000030146080604052600080fdfea26469706673582212207f9515e2263fa71a7984707e2aefd82241fac15c497386ca798b526f14f8ba6664736f6c63430008000033
|
||||
Metadata:
|
||||
{"compiler":{"version":"0.8.0+commit.c7dfd78e"},"language":"Solidity","output":{"abi":[],"devdoc":{"kind":"dev","methods":{},"version":1},"userdoc":{"kind":"user","methods":{},"version":1}},"settings":{"compilationTarget":{"syntaxTests/scoping/library_inherited2.sol":"Lib"},"evmVersion":"istanbul","libraries":{},"metadata":{"bytecodeHash":"ipfs"},"optimizer":{"enabled":false,"runs":200},"remappings":[]},"sources":{"syntaxTests/scoping/library_inherited2.sol":{"keccak256":"0xd0619f00638fdfea187368965615dbd599fead93dd14b6558725e85ec7011d96","urls":["bzz-raw://ec7af066be66a223f0d25ba3bf9ba6dc103e1a57531a66a38a5ca2b6ce172f55","dweb:/ipfs/QmW1NrqQNhnY1Tkgr3Z9oM8buCGLUJCJVCDTVejJTT5Vet"]}},"version":1}
|
2
test/scripts/fixtures/stack_too_deep_cli_output.txt
Normal file
2
test/scripts/fixtures/stack_too_deep_cli_output.txt
Normal file
@ -0,0 +1,2 @@
|
||||
Compiler error: Stack too deep when compiling inline assembly: Variable value0 is 1 slot(s) too deep inside the stack.
|
||||
|
23
test/scripts/fixtures/stack_too_deep_json_output.json
Normal file
23
test/scripts/fixtures/stack_too_deep_json_output.json
Normal file
@ -0,0 +1,23 @@
|
||||
{
|
||||
"contracts": {
|
||||
"syntaxTests/tupleAssignments/large_component_count.sol": {
|
||||
"C": {
|
||||
"metadata": "{\"compiler\":{\"version\":\"0.8.0+commit.c7dfd78e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"name\":\"f\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"g\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"syntaxTests/tupleAssignments/large_component_count.sol\":\"C\"},\"evmVersion\":\"istanbul\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":false,\"runs\":200},\"remappings\":[]},\"sources\":{\"syntaxTests/tupleAssignments/large_component_count.sol\":{\"keccak256\":\"0xb5478857c30ab2e7cf6b0fdcad0fdc70f4715129a7dd3f3f1dda5b3892a83846\",\"urls\":[\"bzz-raw://abc14e4a2a61618b712c4ac3ba0cab07d9214d0637af78aa7648e3d2f89eb725\",\"dweb:/ipfs/QmTqrQzwWbZgdAck6ma9xY3sL1mGiw61Nsg36P21mZdxLG\"]}},\"version\":1}"
|
||||
}
|
||||
}
|
||||
},
|
||||
"errors": [
|
||||
{
|
||||
"component": "general",
|
||||
"formattedMessage": "CompilerError: Stack too deep when compiling inline assembly: Variable value0 is 1 slot(s) too deep inside the stack.\n\n",
|
||||
"message": "Compiler error (/solidity/libyul/backends/evm/AsmCodeGen.cpp:248):Stack too deep when compiling inline assembly: Variable value0 is 1 slot(s) too deep inside the stack.",
|
||||
"severity": "error",
|
||||
"type": "CompilerError"
|
||||
}
|
||||
],
|
||||
"sources": {
|
||||
"syntaxTests/tupleAssignments/large_component_count.sol": {
|
||||
"id": 0
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,5 @@
|
||||
Unimplemented feature:
|
||||
/solidity/libsolidity/codegen/CompilerUtils.cpp(771): Throw in function void solidity::frontend::CompilerUtils::convertType(const solidity::frontend::Type&, const solidity::frontend::Type&, bool, bool, bool)
|
||||
Dynamic exception type: boost::wrapexcept<solidity::langutil::UnimplementedFeatureError>
|
||||
std::exception::what: Not yet implemented - FixedPointType.
|
||||
[solidity::util::tag_comment*] = Not yet implemented - FixedPointType.
|
23
test/scripts/fixtures/unimplemented_feature_json_output.json
Normal file
23
test/scripts/fixtures/unimplemented_feature_json_output.json
Normal file
@ -0,0 +1,23 @@
|
||||
{
|
||||
"contracts": {
|
||||
"syntaxTests/nameAndTypeResolution/317_fixed_type_valid_explicit_conversions.sol": {
|
||||
"test": {
|
||||
"metadata": "{\"compiler\":{\"version\":\"0.8.0+commit.c7dfd78e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"name\":\"f\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"syntaxTests/nameAndTypeResolution/317_fixed_type_valid_explicit_conversions.sol\":\"test\"},\"evmVersion\":\"istanbul\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":false,\"runs\":200},\"remappings\":[]},\"sources\":{\"syntaxTests/nameAndTypeResolution/317_fixed_type_valid_explicit_conversions.sol\":{\"keccak256\":\"0x44b85b2db00441b574d40d11a6be684517d4312de0f6ef0550e02aea33e2a05f\",\"urls\":[\"bzz-raw://c7a9416a8634c5bd1451742f09d633acab37a6e0db1441d0bb7ea4e8f4af214b\",\"dweb:/ipfs/QmZNMQcZu9wnD6sFH2c7PymZReYeroBXDyKkJ5YEhWtCjc\"]}},\"version\":1}"
|
||||
}
|
||||
}
|
||||
},
|
||||
"errors": [
|
||||
{
|
||||
"component": "general",
|
||||
"formattedMessage": "UnimplementedFeatureError: Not yet implemented - FixedPointType.\n\n",
|
||||
"message": "Unimplemented feature (/solidity/libsolidity/codegen/CompilerUtils.cpp:771):Not yet implemented - FixedPointType.",
|
||||
"severity": "error",
|
||||
"type": "UnimplementedFeatureError"
|
||||
}
|
||||
],
|
||||
"sources": {
|
||||
"syntaxTests/nameAndTypeResolution/317_fixed_type_valid_explicit_conversions.sol": {
|
||||
"id": 0
|
||||
}
|
||||
}
|
||||
}
|
11
test/scripts/fixtures/unknown_pragma_sol_cli_output.txt
Normal file
11
test/scripts/fixtures/unknown_pragma_sol_cli_output.txt
Normal file
@ -0,0 +1,11 @@
|
||||
Warning: SPDX license identifier not provided in source file. Before publishing, consider adding a comment containing "SPDX-License-Identifier: <SPDX-License>" to each source file. Use "SPDX-License-Identifier: UNLICENSED" for non-open-source code. Please see https://spdx.org for more information.
|
||||
--> syntaxTests/pragma/unknown_pragma.sol
|
||||
|
||||
Error: Unknown pragma "thisdoesntexist"
|
||||
--> syntaxTests/pragma/unknown_pragma.sol:1:1:
|
||||
|
|
||||
1 | pragma thisdoesntexist;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Warning: Source file does not specify required compiler version! Consider adding "pragma solidity ^0.8.0;"
|
||||
--> syntaxTests/pragma/unknown_pragma.sol
|
@ -3,13 +3,14 @@
|
||||
import json
|
||||
import unittest
|
||||
from pathlib import Path
|
||||
from textwrap import dedent
|
||||
|
||||
from unittest_helpers import FIXTURE_DIR, LIBSOLIDITY_TEST_DIR, load_fixture, load_libsolidity_test_case
|
||||
|
||||
# NOTE: This test file file only works with scripts/ added to PYTHONPATH so pylint can't find the imports
|
||||
# pragma pylint: disable=import-error
|
||||
from bytecodecompare.prepare_report import FileReport, ContractReport
|
||||
from bytecodecompare.prepare_report import load_source, parse_standard_json_output, prepare_compiler_input
|
||||
from bytecodecompare.prepare_report import CompilerInterface, FileReport, ContractReport
|
||||
from bytecodecompare.prepare_report import load_source, parse_cli_output, parse_standard_json_output, prepare_compiler_input
|
||||
# pragma pylint: enable=import-error
|
||||
|
||||
|
||||
@ -20,16 +21,33 @@ SMT_CONTRACT_WITH_LF_NEWLINES_SOL_PATH = FIXTURE_DIR / 'smt_contract_with_lf_new
|
||||
SMT_CONTRACT_WITH_CRLF_NEWLINES_SOL_PATH = FIXTURE_DIR / 'smt_contract_with_crlf_newlines.sol'
|
||||
SMT_CONTRACT_WITH_CR_NEWLINES_SOL_PATH = FIXTURE_DIR / 'smt_contract_with_cr_newlines.sol'
|
||||
SMT_CONTRACT_WITH_MIXED_NEWLINES_SOL_PATH = FIXTURE_DIR / 'smt_contract_with_mixed_newlines.sol'
|
||||
SMT_CONTRACT_WITH_MIXED_NEWLINES_SOL_CODE = load_fixture(SMT_CONTRACT_WITH_MIXED_NEWLINES_SOL_PATH)
|
||||
|
||||
SYNTAX_SMOKE_TEST_SOL_PATH = LIBSOLIDITY_TEST_DIR / 'syntaxTests/smoke_test.sol'
|
||||
SYNTAX_SMOKE_TEST_SOL_CODE = load_libsolidity_test_case(SYNTAX_SMOKE_TEST_SOL_PATH)
|
||||
|
||||
LIBRARY_INHERITED2_SOL_JSON_OUTPUT = load_fixture('library_inherited2_sol_json_output.json')
|
||||
LIBRARY_INHERITED2_SOL_CLI_OUTPUT = load_fixture('library_inherited2_sol_cli_output.txt')
|
||||
|
||||
UNKNOWN_PRAGMA_SOL_JSON_OUTPUT = load_fixture('unknown_pragma_sol_json_output.json')
|
||||
UNKNOWN_PRAGMA_SOL_CLI_OUTPUT = load_fixture('unknown_pragma_sol_cli_output.txt')
|
||||
|
||||
UNIMPLEMENTED_FEATURE_JSON_OUTPUT = load_fixture('unimplemented_feature_json_output.json')
|
||||
UNIMPLEMENTED_FEATURE_CLI_OUTPUT = load_fixture('unimplemented_feature_cli_output.txt')
|
||||
|
||||
STACK_TOO_DEEP_JSON_OUTPUT = load_fixture('stack_too_deep_json_output.json')
|
||||
STACK_TOO_DEEP_CLI_OUTPUT = load_fixture('stack_too_deep_cli_output.txt')
|
||||
|
||||
CODE_GENERATION_ERROR_JSON_OUTPUT = load_fixture('code_generation_error_json_output.json')
|
||||
CODE_GENERATION_ERROR_CLI_OUTPUT = load_fixture('code_generation_error_cli_output.txt')
|
||||
|
||||
|
||||
class TestPrepareReport_FileReport(unittest.TestCase):
|
||||
class PrepareReportTestBase(unittest.TestCase):
|
||||
def setUp(self):
|
||||
self.maxDiff = 10000
|
||||
|
||||
|
||||
class TestFileReport(PrepareReportTestBase):
|
||||
def test_format_report(self):
|
||||
report = FileReport(
|
||||
file_name=Path('syntaxTests/scoping/library_inherited2.sol'),
|
||||
@ -79,10 +97,7 @@ class TestPrepareReport_FileReport(unittest.TestCase):
|
||||
self.assertEqual(report.format_report(), '')
|
||||
|
||||
|
||||
class TestPrepareReport(unittest.TestCase):
|
||||
def setUp(self):
|
||||
self.maxDiff = 10000
|
||||
|
||||
class TestLoadSource(PrepareReportTestBase):
|
||||
def test_load_source(self):
|
||||
self.assertEqual(load_source(SMT_SMOKE_TEST_SOL_PATH), SMT_SMOKE_TEST_SOL_CODE)
|
||||
|
||||
@ -126,7 +141,9 @@ class TestPrepareReport(unittest.TestCase):
|
||||
|
||||
self.assertEqual(load_source(SMT_CONTRACT_WITH_MIXED_NEWLINES_SOL_PATH), expected_output)
|
||||
|
||||
def test_prepare_compiler_input(self):
|
||||
|
||||
class TestPrepareCompilerInput(PrepareReportTestBase):
|
||||
def test_prepare_compiler_input_should_work_with_standard_json_interface(self):
|
||||
expected_compiler_input = {
|
||||
'language': 'Solidity',
|
||||
'sources': {
|
||||
@ -143,12 +160,27 @@ class TestPrepareReport(unittest.TestCase):
|
||||
Path('solc'),
|
||||
SMT_SMOKE_TEST_SOL_PATH,
|
||||
optimize=True,
|
||||
interface=CompilerInterface.STANDARD_JSON,
|
||||
)
|
||||
|
||||
self.assertEqual(command_line, ['solc', '--standard-json'])
|
||||
self.assertEqual(json.loads(compiler_input), expected_compiler_input)
|
||||
|
||||
def test_prepare_compiler_input_preserves_newlines(self):
|
||||
def test_prepare_compiler_input_should_work_with_cli_interface(self):
|
||||
(command_line, compiler_input) = prepare_compiler_input(
|
||||
Path('solc'),
|
||||
SMT_SMOKE_TEST_SOL_PATH,
|
||||
optimize=True,
|
||||
interface=CompilerInterface.CLI,
|
||||
)
|
||||
|
||||
self.assertEqual(
|
||||
command_line,
|
||||
['solc', str(SMT_SMOKE_TEST_SOL_PATH), '--bin', '--metadata', '--model-checker-engine', 'none', '--optimize']
|
||||
)
|
||||
self.assertEqual(compiler_input, SMT_SMOKE_TEST_SOL_CODE)
|
||||
|
||||
def test_prepare_compiler_input_for_json_preserves_newlines(self):
|
||||
expected_compiler_input = {
|
||||
'language': 'Solidity',
|
||||
'sources': {
|
||||
@ -171,11 +203,24 @@ class TestPrepareReport(unittest.TestCase):
|
||||
Path('solc'),
|
||||
SMT_CONTRACT_WITH_MIXED_NEWLINES_SOL_PATH,
|
||||
optimize=True,
|
||||
interface=CompilerInterface.STANDARD_JSON,
|
||||
)
|
||||
|
||||
self.assertEqual(command_line, ['solc', '--standard-json'])
|
||||
self.assertEqual(json.loads(compiler_input), expected_compiler_input)
|
||||
|
||||
def test_prepare_compiler_input_for_cli_preserves_newlines(self):
|
||||
(_command_line, compiler_input) = prepare_compiler_input(
|
||||
Path('solc'),
|
||||
SMT_CONTRACT_WITH_MIXED_NEWLINES_SOL_PATH,
|
||||
optimize=True,
|
||||
interface=CompilerInterface.CLI,
|
||||
)
|
||||
|
||||
self.assertEqual(compiler_input, SMT_CONTRACT_WITH_MIXED_NEWLINES_SOL_CODE)
|
||||
|
||||
|
||||
class TestParseStandardJSONOutput(PrepareReportTestBase):
|
||||
def test_parse_standard_json_output(self):
|
||||
expected_report = FileReport(
|
||||
file_name=Path('syntaxTests/scoping/library_inherited2.sol'),
|
||||
@ -257,3 +302,118 @@ class TestPrepareReport(unittest.TestCase):
|
||||
)
|
||||
|
||||
self.assertEqual(parse_standard_json_output(Path('contract.sol'), compiler_output), expected_report)
|
||||
|
||||
def test_parse_standard_json_output_should_report_error_on_unimplemented_feature_error(self):
|
||||
expected_report = FileReport(file_name=Path('file.sol'), contract_reports=None)
|
||||
|
||||
self.assertEqual(parse_standard_json_output(Path('file.sol'), UNIMPLEMENTED_FEATURE_JSON_OUTPUT), expected_report)
|
||||
|
||||
def test_parse_standard_json_output_should_report_error_on_stack_too_deep_error(self):
|
||||
expected_report = FileReport(file_name=Path('file.sol'), contract_reports=None)
|
||||
|
||||
self.assertEqual(parse_standard_json_output(Path('file.sol'), STACK_TOO_DEEP_JSON_OUTPUT), expected_report)
|
||||
|
||||
def test_parse_standard_json_output_should_report_error_on_code_generation_error(self):
|
||||
expected_report = FileReport(file_name=Path('file.sol'), contract_reports=None)
|
||||
|
||||
self.assertEqual(parse_standard_json_output(Path('file.sol'), CODE_GENERATION_ERROR_JSON_OUTPUT), expected_report)
|
||||
|
||||
|
||||
class TestParseCLIOutput(PrepareReportTestBase):
|
||||
def test_parse_cli_output(self):
|
||||
expected_report = FileReport(
|
||||
file_name=Path('syntaxTests/scoping/library_inherited2.sol'),
|
||||
contract_reports=[
|
||||
# pragma pylint: disable=line-too-long
|
||||
ContractReport(
|
||||
contract_name='A',
|
||||
file_name=Path('syntaxTests/scoping/library_inherited2.sol'),
|
||||
bytecode='6080604052348015600f57600080fd5b50603f80601d6000396000f3fe6080604052600080fdfea264697066735822122086e727f29d40b264a19bbfcad38d64493dca4bab5dbba8c82ffdaae389d2bba064736f6c63430008000033',
|
||||
metadata='{"compiler":{"version":"0.8.0+commit.c7dfd78e"},"language":"Solidity","output":{"abi":[],"devdoc":{"kind":"dev","methods":{},"version":1},"userdoc":{"kind":"user","methods":{},"version":1}},"settings":{"compilationTarget":{"syntaxTests/scoping/library_inherited2.sol":"A"},"evmVersion":"istanbul","libraries":{},"metadata":{"bytecodeHash":"ipfs"},"optimizer":{"enabled":false,"runs":200},"remappings":[]},"sources":{"syntaxTests/scoping/library_inherited2.sol":{"keccak256":"0xd0619f00638fdfea187368965615dbd599fead93dd14b6558725e85ec7011d96","urls":["bzz-raw://ec7af066be66a223f0d25ba3bf9ba6dc103e1a57531a66a38a5ca2b6ce172f55","dweb:/ipfs/QmW1NrqQNhnY1Tkgr3Z9oM8buCGLUJCJVCDTVejJTT5Vet"]}},"version":1}',
|
||||
),
|
||||
ContractReport(
|
||||
contract_name='B',
|
||||
file_name=Path('syntaxTests/scoping/library_inherited2.sol'),
|
||||
bytecode='608060405234801561001057600080fd5b506101cc806100206000396000f3fe608060405234801561001057600080fd5b506004361061002b5760003560e01c80630423a13214610030575b600080fd5b61004a6004803603810190610045919061009d565b610060565b60405161005791906100d5565b60405180910390f35b600061006b82610072565b9050919050565b6000602a8261008191906100f0565b9050919050565b6000813590506100978161017f565b92915050565b6000602082840312156100af57600080fd5b60006100bd84828501610088565b91505092915050565b6100cf81610146565b82525050565b60006020820190506100ea60008301846100c6565b92915050565b60006100fb82610146565b915061010683610146565b9250827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0382111561013b5761013a610150565b5b828201905092915050565b6000819050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b61018881610146565b811461019357600080fd5b5056fea2646970667358221220104c345633313efe410492448844d96d78452c3044ce126b5e041b7fbeaa790064736f6c63430008000033',
|
||||
metadata='{"compiler":{"version":"0.8.0+commit.c7dfd78e"},"language":"Solidity","output":{"abi":[{"inputs":[{"internalType":"uint256","name":"value","type":"uint256"}],"name":"bar","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"}],"devdoc":{"kind":"dev","methods":{},"version":1},"userdoc":{"kind":"user","methods":{},"version":1}},"settings":{"compilationTarget":{"syntaxTests/scoping/library_inherited2.sol":"B"},"evmVersion":"istanbul","libraries":{},"metadata":{"bytecodeHash":"ipfs"},"optimizer":{"enabled":false,"runs":200},"remappings":[]},"sources":{"syntaxTests/scoping/library_inherited2.sol":{"keccak256":"0xd0619f00638fdfea187368965615dbd599fead93dd14b6558725e85ec7011d96","urls":["bzz-raw://ec7af066be66a223f0d25ba3bf9ba6dc103e1a57531a66a38a5ca2b6ce172f55","dweb:/ipfs/QmW1NrqQNhnY1Tkgr3Z9oM8buCGLUJCJVCDTVejJTT5Vet"]}},"version":1}',
|
||||
),
|
||||
ContractReport(
|
||||
contract_name='Lib',
|
||||
file_name=Path('syntaxTests/scoping/library_inherited2.sol'),
|
||||
bytecode='60566050600b82828239805160001a6073146043577f4e487b7100000000000000000000000000000000000000000000000000000000600052600060045260246000fd5b30600052607381538281f3fe73000000000000000000000000000000000000000030146080604052600080fdfea26469706673582212207f9515e2263fa71a7984707e2aefd82241fac15c497386ca798b526f14f8ba6664736f6c63430008000033',
|
||||
metadata='{"compiler":{"version":"0.8.0+commit.c7dfd78e"},"language":"Solidity","output":{"abi":[],"devdoc":{"kind":"dev","methods":{},"version":1},"userdoc":{"kind":"user","methods":{},"version":1}},"settings":{"compilationTarget":{"syntaxTests/scoping/library_inherited2.sol":"Lib"},"evmVersion":"istanbul","libraries":{},"metadata":{"bytecodeHash":"ipfs"},"optimizer":{"enabled":false,"runs":200},"remappings":[]},"sources":{"syntaxTests/scoping/library_inherited2.sol":{"keccak256":"0xd0619f00638fdfea187368965615dbd599fead93dd14b6558725e85ec7011d96","urls":["bzz-raw://ec7af066be66a223f0d25ba3bf9ba6dc103e1a57531a66a38a5ca2b6ce172f55","dweb:/ipfs/QmW1NrqQNhnY1Tkgr3Z9oM8buCGLUJCJVCDTVejJTT5Vet"]}},"version":1}',
|
||||
),
|
||||
# pragma pylint: enable=line-too-long
|
||||
]
|
||||
)
|
||||
|
||||
report = parse_cli_output(Path('syntaxTests/scoping/library_inherited2.sol'), LIBRARY_INHERITED2_SOL_CLI_OUTPUT)
|
||||
self.assertEqual(report, expected_report)
|
||||
|
||||
def test_parse_cli_output_should_report_error_on_compiler_errors(self):
|
||||
expected_report = FileReport(file_name=Path('syntaxTests/pragma/unknown_pragma.sol'), contract_reports=None)
|
||||
|
||||
report = parse_cli_output(Path('syntaxTests/pragma/unknown_pragma.sol'), UNKNOWN_PRAGMA_SOL_CLI_OUTPUT)
|
||||
self.assertEqual(report, expected_report)
|
||||
|
||||
def test_parse_cli_output_should_report_error_on_empty_output(self):
|
||||
expected_report = FileReport(file_name=Path('file.sol'), contract_reports=None)
|
||||
|
||||
self.assertEqual(parse_cli_output(Path('file.sol'), ''), expected_report)
|
||||
|
||||
def test_parse_cli_output_should_report_missing_bytecode_and_metadata(self):
|
||||
compiler_output = dedent("""\
|
||||
======= syntaxTests/scoping/library_inherited2.sol:A =======
|
||||
======= syntaxTests/scoping/library_inherited2.sol:B =======
|
||||
608060405234801561001057600080fd5b506101cc806100206000396000f3fe608060405234801561001057600080fd5b506004361061002b5760003560e01c80630423a13214610030575b600080fd5b61004a6004803603810190610045919061009d565b610060565b60405161005791906100d5565b60405180910390f35b600061006b82610072565b9050919050565b6000602a8261008191906100f0565b9050919050565b6000813590506100978161017f565b92915050565b6000602082840312156100af57600080fd5b60006100bd84828501610088565b91505092915050565b6100cf81610146565b82525050565b60006020820190506100ea60008301846100c6565b92915050565b60006100fb82610146565b915061010683610146565b9250827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0382111561013b5761013a610150565b5b828201905092915050565b6000819050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b61018881610146565b811461019357600080fd5b5056fea2646970667358221220104c345633313efe410492448844d96d78452c3044ce126b5e041b7fbeaa790064736f6c63430008000033
|
||||
Metadata:
|
||||
{"compiler":{"version":"0.8.0+commit.c7dfd78e"},"language":"Solidity","output":{"abi":[{"inputs":[{"internalType":"uint256","name":"value","type":"uint256"}],"name":"bar","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"}],"devdoc":{"kind":"dev","methods":{},"version":1},"userdoc":{"kind":"user","methods":{},"version":1}},"settings":{"compilationTarget":{"syntaxTests/scoping/library_inherited2.sol":"B"},"evmVersion":"istanbul","libraries":{},"metadata":{"bytecodeHash":"ipfs"},"optimizer":{"enabled":false,"runs":200},"remappings":[]},"sources":{"syntaxTests/scoping/library_inherited2.sol":{"keccak256":"0xd0619f00638fdfea187368965615dbd599fead93dd14b6558725e85ec7011d96","urls":["bzz-raw://ec7af066be66a223f0d25ba3bf9ba6dc103e1a57531a66a38a5ca2b6ce172f55","dweb:/ipfs/QmW1NrqQNhnY1Tkgr3Z9oM8buCGLUJCJVCDTVejJTT5Vet"]}},"version":1}
|
||||
|
||||
======= syntaxTests/scoping/library_inherited2.sol:Lib =======
|
||||
Binary:
|
||||
60566050600b82828239805160001a6073146043577f4e487b7100000000000000000000000000000000000000000000000000000000600052600060045260246000fd5b30600052607381538281f3fe73000000000000000000000000000000000000000030146080604052600080fdfea26469706673582212207f9515e2263fa71a7984707e2aefd82241fac15c497386ca798b526f14f8ba6664736f6c63430008000033
|
||||
Metadata:
|
||||
""")
|
||||
|
||||
expected_report = FileReport(
|
||||
file_name=Path('syntaxTests/scoping/library_inherited2.sol'),
|
||||
contract_reports=[
|
||||
ContractReport(
|
||||
contract_name='A',
|
||||
file_name=Path('syntaxTests/scoping/library_inherited2.sol'),
|
||||
bytecode=None,
|
||||
metadata=None,
|
||||
),
|
||||
# pragma pylint: disable=line-too-long
|
||||
ContractReport(
|
||||
contract_name='B',
|
||||
file_name=Path('syntaxTests/scoping/library_inherited2.sol'),
|
||||
bytecode=None,
|
||||
metadata='{"compiler":{"version":"0.8.0+commit.c7dfd78e"},"language":"Solidity","output":{"abi":[{"inputs":[{"internalType":"uint256","name":"value","type":"uint256"}],"name":"bar","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"}],"devdoc":{"kind":"dev","methods":{},"version":1},"userdoc":{"kind":"user","methods":{},"version":1}},"settings":{"compilationTarget":{"syntaxTests/scoping/library_inherited2.sol":"B"},"evmVersion":"istanbul","libraries":{},"metadata":{"bytecodeHash":"ipfs"},"optimizer":{"enabled":false,"runs":200},"remappings":[]},"sources":{"syntaxTests/scoping/library_inherited2.sol":{"keccak256":"0xd0619f00638fdfea187368965615dbd599fead93dd14b6558725e85ec7011d96","urls":["bzz-raw://ec7af066be66a223f0d25ba3bf9ba6dc103e1a57531a66a38a5ca2b6ce172f55","dweb:/ipfs/QmW1NrqQNhnY1Tkgr3Z9oM8buCGLUJCJVCDTVejJTT5Vet"]}},"version":1}',
|
||||
),
|
||||
ContractReport(
|
||||
contract_name='Lib',
|
||||
file_name=Path('syntaxTests/scoping/library_inherited2.sol'),
|
||||
bytecode='60566050600b82828239805160001a6073146043577f4e487b7100000000000000000000000000000000000000000000000000000000600052600060045260246000fd5b30600052607381538281f3fe73000000000000000000000000000000000000000030146080604052600080fdfea26469706673582212207f9515e2263fa71a7984707e2aefd82241fac15c497386ca798b526f14f8ba6664736f6c63430008000033',
|
||||
metadata=None,
|
||||
),
|
||||
# pragma pylint: enable=line-too-long
|
||||
]
|
||||
)
|
||||
|
||||
self.assertEqual(parse_cli_output(Path('syntaxTests/scoping/library_inherited2.sol'), compiler_output), expected_report)
|
||||
|
||||
def test_parse_cli_output_should_report_error_on_unimplemented_feature_error(self):
|
||||
expected_report = FileReport(file_name=Path('file.sol'), contract_reports=None)
|
||||
|
||||
self.assertEqual(parse_cli_output(Path('file.sol'), UNIMPLEMENTED_FEATURE_CLI_OUTPUT), expected_report)
|
||||
|
||||
def test_parse_cli_output_should_report_error_on_stack_too_deep_error(self):
|
||||
expected_report = FileReport(file_name=Path('file.sol'), contract_reports=None)
|
||||
|
||||
self.assertEqual(parse_cli_output(Path('file.sol'), STACK_TOO_DEEP_CLI_OUTPUT), expected_report)
|
||||
|
||||
def test_parse_cli_output_should_report_error_on_code_generation_error(self):
|
||||
expected_report = FileReport(file_name=Path('file.sol'), contract_reports=None)
|
||||
|
||||
self.assertEqual(parse_cli_output(Path('file.sol'), CODE_GENERATION_ERROR_CLI_OUTPUT), expected_report)
|
||||
|
Loading…
Reference in New Issue
Block a user