mirror of
https://github.com/pezkuwichain/revive.git
synced 2026-04-22 02:07:55 +00:00
Implement Rust CLI tests (#372)
# Description Closes #365 Ports all `resolc` CLI tests to Rust and removes the CLI TypeScript tests.
This commit is contained in:
@@ -56,6 +56,3 @@ jobs:
|
|||||||
|
|
||||||
- name: Test cargo workspace
|
- name: Test cargo workspace
|
||||||
run: make test-workspace
|
run: make test-workspace
|
||||||
|
|
||||||
- name: Test CLI
|
|
||||||
run: make test-cli
|
|
||||||
|
|||||||
@@ -14,7 +14,6 @@
|
|||||||
test-integration \
|
test-integration \
|
||||||
test-resolc \
|
test-resolc \
|
||||||
test-workspace \
|
test-workspace \
|
||||||
test-cli \
|
|
||||||
test-wasm \
|
test-wasm \
|
||||||
test-llvm-builder
|
test-llvm-builder
|
||||||
bench \
|
bench \
|
||||||
@@ -57,7 +56,7 @@ machete:
|
|||||||
cargo install cargo-machete
|
cargo install cargo-machete
|
||||||
cargo machete
|
cargo machete
|
||||||
|
|
||||||
test: format clippy machete test-cli test-workspace install-revive-runner install-revive-explorer
|
test: format clippy machete test-workspace install-revive-runner install-revive-explorer
|
||||||
|
|
||||||
test-integration: install-bin
|
test-integration: install-bin
|
||||||
cargo test --package revive-integration
|
cargo test --package revive-integration
|
||||||
@@ -68,9 +67,6 @@ test-resolc: install
|
|||||||
test-workspace: install
|
test-workspace: install
|
||||||
cargo test --workspace --exclude revive-llvm-builder
|
cargo test --workspace --exclude revive-llvm-builder
|
||||||
|
|
||||||
test-cli: install
|
|
||||||
npm run test:cli
|
|
||||||
|
|
||||||
test-wasm: install-wasm
|
test-wasm: install-wasm
|
||||||
npm run test:wasm
|
npm run test:wasm
|
||||||
|
|
||||||
@@ -94,6 +90,6 @@ clean:
|
|||||||
cargo clean ; \
|
cargo clean ; \
|
||||||
revive-llvm clean ; \
|
revive-llvm clean ; \
|
||||||
rm -rf node_modules ; \
|
rm -rf node_modules ; \
|
||||||
rm -rf crates/resolc/src/tests/cli-tests/artifacts ; \
|
rm -rf crates/resolc/src/tests/cli/artifacts ; \
|
||||||
cargo uninstall resolc ; \
|
cargo uninstall resolc ; \
|
||||||
cargo uninstall revive-llvm-builder ;
|
cargo uninstall revive-llvm-builder ;
|
||||||
|
|||||||
@@ -1,4 +0,0 @@
|
|||||||
module.exports = {
|
|
||||||
preset: "ts-jest",
|
|
||||||
testEnvironment: "node",
|
|
||||||
};
|
|
||||||
@@ -1,66 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<testsuites name="jest tests" tests="27" failures="0" errors="0" time="2.146">
|
|
||||||
<testsuite name="Run with --yul by default" errors="0" failures="0" skipped="1" timestamp="2024-10-24T17:08:50" time="1.508" tests="6">
|
|
||||||
<testcase classname="Run with --yul by default Valid command exit code = 0" name="Run with --yul by default Valid command exit code = 0" time="0.003">
|
|
||||||
</testcase>
|
|
||||||
<testcase classname="Run with --yul by default --yul output is presented" name="Run with --yul by default --yul output is presented" time="0">
|
|
||||||
</testcase>
|
|
||||||
<testcase classname="Run with --yul by default solc exit code == resolc exit code" name="Run with --yul by default solc exit code == resolc exit code" time="0">
|
|
||||||
<skipped/>
|
|
||||||
</testcase>
|
|
||||||
<testcase classname="Run with --yul by default run invalid: resolc --yul" name="Run with --yul by default run invalid: resolc --yul" time="0.001">
|
|
||||||
</testcase>
|
|
||||||
<testcase classname="Run with --yul by default Invalid command exit code = 1" name="Run with --yul by default Invalid command exit code = 1" time="0">
|
|
||||||
</testcase>
|
|
||||||
<testcase classname="Run with --yul by default Invalid solc exit code == Invalid resolc exit code" name="Run with --yul by default Invalid solc exit code == Invalid resolc exit code" time="0.041">
|
|
||||||
</testcase>
|
|
||||||
</testsuite>
|
|
||||||
<testsuite name="Run with --asm by default" errors="0" failures="0" skipped="0" timestamp="2024-10-24T17:08:50" time="1.512" tests="6">
|
|
||||||
<testcase classname="Run with --asm by default Valid command exit code = 0" name="Run with --asm by default Valid command exit code = 0" time="0.002">
|
|
||||||
</testcase>
|
|
||||||
<testcase classname="Run with --asm by default --asm output is presented" name="Run with --asm by default --asm output is presented" time="0.001">
|
|
||||||
</testcase>
|
|
||||||
<testcase classname="Run with --asm by default solc exit code == resolc exit code" name="Run with --asm by default solc exit code == resolc exit code" time="0.044">
|
|
||||||
</testcase>
|
|
||||||
<testcase classname="Run with --asm by default run invalid: resolc --asm" name="Run with --asm by default run invalid: resolc --asm" time="0">
|
|
||||||
</testcase>
|
|
||||||
<testcase classname="Run with --asm by default Invalid command exit code = 1" name="Run with --asm by default Invalid command exit code = 1" time="0.001">
|
|
||||||
</testcase>
|
|
||||||
<testcase classname="Run with --asm by default Invalid solc exit code == Invalid resolc exit code" name="Run with --asm by default Invalid solc exit code == Invalid resolc exit code" time="0.04">
|
|
||||||
</testcase>
|
|
||||||
</testsuite>
|
|
||||||
<testsuite name="Run resolc without any options" errors="0" failures="0" skipped="2" timestamp="2024-10-24T17:08:50" time="2.016" tests="15">
|
|
||||||
<testcase classname="Run resolc without any options Info with help is presented" name="Run resolc without any options Info with help is presented" time="0.002">
|
|
||||||
</testcase>
|
|
||||||
<testcase classname="Run resolc without any options Exit code = 1" name="Run resolc without any options Exit code = 1" time="0">
|
|
||||||
</testcase>
|
|
||||||
<testcase classname="Run resolc without any options solc exit code == resolc exit code" name="Run resolc without any options solc exit code == resolc exit code" time="0.044">
|
|
||||||
</testcase>
|
|
||||||
<testcase classname="Default run a command from the help Compiler run successful" name="Default run a command from the help Compiler run successful" time="0">
|
|
||||||
</testcase>
|
|
||||||
<testcase classname="Default run a command from the help Exit code = 0" name="Default run a command from the help Exit code = 0" time="0.001">
|
|
||||||
</testcase>
|
|
||||||
<testcase classname="Default run a command from the help Output dir is created" name="Default run a command from the help Output dir is created" time="0">
|
|
||||||
</testcase>
|
|
||||||
<testcase classname="Default run a command from the help Output file is created" name="Default run a command from the help Output file is created" time="0">
|
|
||||||
<skipped/>
|
|
||||||
</testcase>
|
|
||||||
<testcase classname="Default run a command from the help the output file is not empty" name="Default run a command from the help the output file is not empty" time="0">
|
|
||||||
</testcase>
|
|
||||||
<testcase classname="Default run a command from the help No 'Error'/'Warning'/'Fail' in the output" name="Default run a command from the help No 'Error'/'Warning'/'Fail' in the output" time="0">
|
|
||||||
</testcase>
|
|
||||||
<testcase classname="Default run a command from the help Compiler run successful" name="Default run a command from the help Compiler run successful" time="0.001">
|
|
||||||
</testcase>
|
|
||||||
<testcase classname="Default run a command from the help Exit code = 0" name="Default run a command from the help Exit code = 0" time="0">
|
|
||||||
</testcase>
|
|
||||||
<testcase classname="Default run a command from the help Output dir is created" name="Default run a command from the help Output dir is created" time="0">
|
|
||||||
</testcase>
|
|
||||||
<testcase classname="Default run a command from the help Output files are created" name="Default run a command from the help Output files are created" time="0">
|
|
||||||
<skipped/>
|
|
||||||
</testcase>
|
|
||||||
<testcase classname="Default run a command from the help the output files are not empty" name="Default run a command from the help the output files are not empty" time="0.003">
|
|
||||||
</testcase>
|
|
||||||
<testcase classname="Default run a command from the help No 'Error'/'Warning'/'Fail' in the output" name="Default run a command from the help No 'Error'/'Warning'/'Fail' in the output" time="0">
|
|
||||||
</testcase>
|
|
||||||
</testsuite>
|
|
||||||
</testsuites>
|
|
||||||
-3812
File diff suppressed because it is too large
Load Diff
@@ -1,26 +0,0 @@
|
|||||||
{
|
|
||||||
"name": "cli-tests",
|
|
||||||
"version": "1.0.0",
|
|
||||||
"title": "resolc CLI Tests",
|
|
||||||
"description": "Auto tests for verifying resolc CLI",
|
|
||||||
"repository": "https://github.com/paritytech/revive",
|
|
||||||
"main": "index.js",
|
|
||||||
"private": true,
|
|
||||||
"scripts": {
|
|
||||||
"test": "npx jest --verbose --testPathPattern="
|
|
||||||
},
|
|
||||||
"keywords": [],
|
|
||||||
"author": "Matter Labs",
|
|
||||||
"contributors": [
|
|
||||||
"cyrill@parity.io"
|
|
||||||
],
|
|
||||||
"license": "MIT",
|
|
||||||
"devDependencies": {
|
|
||||||
"@types/jest": "^29.5.14",
|
|
||||||
"@types/shelljs": "^0.8.15",
|
|
||||||
"jest": "^29.7.0",
|
|
||||||
"shelljs": "^0.8.5",
|
|
||||||
"ts-jest": "^29.2.5",
|
|
||||||
"typescript": "^5.7.3"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,22 +0,0 @@
|
|||||||
object "Test" {
|
|
||||||
code {
|
|
||||||
function allocate(size) -> ptr {
|
|
||||||
ptr := mload(0x40)
|
|
||||||
if iszero(ptr) { ptr := 0x60 }
|
|
||||||
mstore(0x40, add(ptr, size))
|
|
||||||
}
|
|
||||||
let size := datasize("Test_deployed")
|
|
||||||
let offset := allocate(size)
|
|
||||||
datacopy(offset, dataoffset("Test_deployed"), size)
|
|
||||||
return(offset, size)
|
|
||||||
}
|
|
||||||
object "Test_deployed" {
|
|
||||||
code {
|
|
||||||
{
|
|
||||||
let test:=0x5
|
|
||||||
mstore(2,signextend(0x8,0x0))
|
|
||||||
mstore(8,lt(0xc,test))
|
|
||||||
}
|
|
||||||
|
|
||||||
return(0, 65536)
|
|
||||||
}}}
|
|
||||||
@@ -1,53 +0,0 @@
|
|||||||
import * as path from 'path'
|
|
||||||
|
|
||||||
const outputDir = 'artifacts'
|
|
||||||
const binExtension = ':C.pvm'
|
|
||||||
const asmExtension = ':C.pvmasm'
|
|
||||||
const llvmExtension = '.ll'
|
|
||||||
const contractSolFilename = 'contract.sol'
|
|
||||||
const contractYulFilename = 'contract.yul'
|
|
||||||
const contractOptimizedLLVMFilename = contractSolFilename + '.C.optimized'
|
|
||||||
const contractUnoptimizedLLVMFilename = contractSolFilename + '.C.unoptimized'
|
|
||||||
const pathToOutputDir = path.join(__dirname, '..', outputDir)
|
|
||||||
const pathToContracts = path.join(__dirname, '..', 'src', 'contracts')
|
|
||||||
const pathToBasicYulContract = path.join(
|
|
||||||
pathToContracts,
|
|
||||||
'yul',
|
|
||||||
contractYulFilename
|
|
||||||
)
|
|
||||||
const pathToMemsetYulContract = path.join(
|
|
||||||
pathToContracts,
|
|
||||||
'yul',
|
|
||||||
'memset.yul'
|
|
||||||
)
|
|
||||||
const pathToBasicSolContract = path.join(
|
|
||||||
pathToContracts,
|
|
||||||
'solidity',
|
|
||||||
contractSolFilename
|
|
||||||
)
|
|
||||||
const pathToSolBinOutputFile = path.join(
|
|
||||||
pathToOutputDir,
|
|
||||||
contractSolFilename + binExtension
|
|
||||||
)
|
|
||||||
const pathToSolAsmOutputFile = path.join(
|
|
||||||
pathToOutputDir,
|
|
||||||
contractSolFilename + asmExtension
|
|
||||||
)
|
|
||||||
|
|
||||||
export const paths = {
|
|
||||||
outputDir: outputDir,
|
|
||||||
binExtension: binExtension,
|
|
||||||
asmExtension: asmExtension,
|
|
||||||
llvmExtension: llvmExtension,
|
|
||||||
contractSolFilename: contractSolFilename,
|
|
||||||
contractYulFilename: contractYulFilename,
|
|
||||||
contractOptimizedLLVMFilename: contractOptimizedLLVMFilename,
|
|
||||||
contractUnoptimizedLLVMFilename: contractUnoptimizedLLVMFilename,
|
|
||||||
pathToOutputDir: pathToOutputDir,
|
|
||||||
pathToContracts: pathToContracts,
|
|
||||||
pathToBasicSolContract: pathToBasicSolContract,
|
|
||||||
pathToBasicYulContract: pathToBasicYulContract,
|
|
||||||
pathToMemsetYulContract: pathToMemsetYulContract,
|
|
||||||
pathToSolBinOutputFile: pathToSolBinOutputFile,
|
|
||||||
pathToSolAsmOutputFile: pathToSolAsmOutputFile,
|
|
||||||
}
|
|
||||||
@@ -1,51 +0,0 @@
|
|||||||
import * as shell from 'shelljs'
|
|
||||||
import * as fs from 'fs'
|
|
||||||
import { spawnSync } from 'child_process'
|
|
||||||
|
|
||||||
interface CommandResult {
|
|
||||||
output: string
|
|
||||||
exitCode: number
|
|
||||||
}
|
|
||||||
|
|
||||||
export const executeCommand = (
|
|
||||||
command: string,
|
|
||||||
stdin?: string
|
|
||||||
): CommandResult => {
|
|
||||||
if (stdin) {
|
|
||||||
const process = spawnSync(command, [], {
|
|
||||||
input: stdin,
|
|
||||||
shell: true,
|
|
||||||
encoding: 'utf8',
|
|
||||||
maxBuffer: 30 * 1024 * 1024,
|
|
||||||
})
|
|
||||||
|
|
||||||
return {
|
|
||||||
exitCode: process.status || 0,
|
|
||||||
output: (process.stdout || process.stderr || '').toString(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const result = shell.exec(command, { silent: true, async: false })
|
|
||||||
return {
|
|
||||||
exitCode: result.code,
|
|
||||||
output: result.stdout || result.stderr || '',
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export const isFolderExist = (folder: string): boolean => {
|
|
||||||
return shell.test('-d', folder)
|
|
||||||
}
|
|
||||||
|
|
||||||
export const isFileExist = (
|
|
||||||
pathToFileDir: string,
|
|
||||||
fileName: string,
|
|
||||||
fileExtension: string
|
|
||||||
): boolean => {
|
|
||||||
return shell.ls(pathToFileDir).stdout.includes(fileName + fileExtension)
|
|
||||||
}
|
|
||||||
|
|
||||||
export const isFileEmpty = (file: string): boolean => {
|
|
||||||
if (fs.existsSync(file)) {
|
|
||||||
return fs.readFileSync(file).length === 0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,44 +0,0 @@
|
|||||||
import { executeCommand } from '../src/helper'
|
|
||||||
import { paths } from '../src/entities'
|
|
||||||
|
|
||||||
//id1746
|
|
||||||
describe('Run with --asm by default', () => {
|
|
||||||
const command = `resolc ${paths.pathToBasicSolContract} --asm`
|
|
||||||
const result = executeCommand(command)
|
|
||||||
const commandInvalid = 'resolc --asm'
|
|
||||||
const resultInvalid = executeCommand(commandInvalid)
|
|
||||||
|
|
||||||
it('Valid command exit code = 0', () => {
|
|
||||||
expect(result.exitCode).toBe(0)
|
|
||||||
})
|
|
||||||
|
|
||||||
it('--asm output is presented', () => {
|
|
||||||
const expectedPatterns = [/(deploy)/i, /(call)/i, /(seal_return)/i]
|
|
||||||
|
|
||||||
for (const pattern of expectedPatterns) {
|
|
||||||
expect(result.output).toMatch(pattern)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
it('solc exit code == resolc exit code', () => {
|
|
||||||
const command = `solc ${paths.pathToBasicSolContract} --asm`
|
|
||||||
const solcResult = executeCommand(command)
|
|
||||||
expect(solcResult.exitCode).toBe(result.exitCode)
|
|
||||||
})
|
|
||||||
|
|
||||||
it('run invalid: resolc --asm', () => {
|
|
||||||
expect(resultInvalid.output).toMatch(
|
|
||||||
/(No input sources specified|Compilation aborted)/i
|
|
||||||
)
|
|
||||||
})
|
|
||||||
|
|
||||||
it('Invalid command exit code = 1', () => {
|
|
||||||
expect(resultInvalid.exitCode).toBe(1)
|
|
||||||
})
|
|
||||||
|
|
||||||
it('Invalid solc exit code == Invalid resolc exit code', () => {
|
|
||||||
const command = 'solc --asm'
|
|
||||||
const solcResult = executeCommand(command)
|
|
||||||
expect(solcResult.exitCode).toBe(resultInvalid.exitCode)
|
|
||||||
})
|
|
||||||
})
|
|
||||||
@@ -1,241 +0,0 @@
|
|||||||
import {
|
|
||||||
executeCommand,
|
|
||||||
isFolderExist,
|
|
||||||
isFileExist,
|
|
||||||
isFileEmpty,
|
|
||||||
} from '../src/helper'
|
|
||||||
import { paths } from '../src/entities'
|
|
||||||
import * as shell from 'shelljs'
|
|
||||||
import * as path from 'path'
|
|
||||||
|
|
||||||
//id1762
|
|
||||||
describe('Run resolc without any options', () => {
|
|
||||||
const command = 'resolc'
|
|
||||||
const result = executeCommand(command)
|
|
||||||
|
|
||||||
it('Info with help is presented', () => {
|
|
||||||
expect(result.output).toMatch(/(Usage: resolc)/i)
|
|
||||||
})
|
|
||||||
|
|
||||||
it('Exit code = 1', () => {
|
|
||||||
expect(result.exitCode).toBe(1)
|
|
||||||
})
|
|
||||||
|
|
||||||
it('solc exit code == resolc exit code', () => {
|
|
||||||
const command = 'solc'
|
|
||||||
const solcResult = executeCommand(command)
|
|
||||||
expect(solcResult.exitCode).toBe(result.exitCode)
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
//#1713
|
|
||||||
describe('Default run a command from the help', () => {
|
|
||||||
const command = `resolc ${paths.pathToBasicSolContract} --overwrite -O3 --bin --output-dir "${paths.pathToOutputDir}"` // potential issue on resolc with full path on Windows cmd
|
|
||||||
const result = executeCommand(command)
|
|
||||||
|
|
||||||
it('Compiler run successful', () => {
|
|
||||||
expect(result.output).toMatch(/(Compiler run successful.)/i)
|
|
||||||
})
|
|
||||||
it('Exit code = 0', () => {
|
|
||||||
expect(result.exitCode).toBe(0)
|
|
||||||
})
|
|
||||||
it('Output dir is created', () => {
|
|
||||||
expect(isFolderExist(paths.pathToOutputDir)).toBe(true)
|
|
||||||
})
|
|
||||||
xit('Output file is created', () => {
|
|
||||||
// a bug on windows
|
|
||||||
expect(
|
|
||||||
isFileExist(
|
|
||||||
paths.pathToOutputDir,
|
|
||||||
paths.contractSolFilename,
|
|
||||||
paths.binExtension
|
|
||||||
)
|
|
||||||
).toBe(true)
|
|
||||||
})
|
|
||||||
it('the output file is not empty', () => {
|
|
||||||
expect(isFileEmpty(paths.pathToSolBinOutputFile)).toBe(false)
|
|
||||||
})
|
|
||||||
it("No 'Error'/'Warning'/'Fail' in the output", () => {
|
|
||||||
expect(result.output).not.toMatch(/([Ee]rror|[Ww]arning|[Ff]ail)/i)
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
//#1818
|
|
||||||
describe('Default run a command from the help', () => {
|
|
||||||
const command = `resolc ${paths.pathToBasicSolContract} --overwrite -O3 --bin --asm --output-dir "${paths.pathToOutputDir}"` // potential issue on resolc with full path on Windows cmd
|
|
||||||
const result = executeCommand(command)
|
|
||||||
|
|
||||||
it('Compiler run successful', () => {
|
|
||||||
expect(result.output).toMatch(/(Compiler run successful.)/i)
|
|
||||||
})
|
|
||||||
it('Exit code = 0', () => {
|
|
||||||
expect(result.exitCode).toBe(0)
|
|
||||||
})
|
|
||||||
it('Output dir is created', () => {
|
|
||||||
expect(isFolderExist(paths.pathToOutputDir)).toBe(true)
|
|
||||||
})
|
|
||||||
xit('Output files are created', () => {
|
|
||||||
// a bug on windows
|
|
||||||
expect(
|
|
||||||
isFileExist(
|
|
||||||
paths.pathToOutputDir,
|
|
||||||
paths.contractSolFilename,
|
|
||||||
paths.binExtension
|
|
||||||
)
|
|
||||||
).toBe(true)
|
|
||||||
expect(
|
|
||||||
isFileExist(
|
|
||||||
paths.pathToOutputDir,
|
|
||||||
paths.contractSolFilename,
|
|
||||||
paths.asmExtension
|
|
||||||
)
|
|
||||||
).toBe(true)
|
|
||||||
})
|
|
||||||
it('the output files are not empty', () => {
|
|
||||||
expect(isFileEmpty(paths.pathToSolBinOutputFile)).toBe(false)
|
|
||||||
expect(isFileEmpty(paths.pathToSolAsmOutputFile)).toBe(false)
|
|
||||||
})
|
|
||||||
it("No 'Error'/'Warning'/'Fail' in the output", () => {
|
|
||||||
expect(result.output).not.toMatch(/([Ee]rror|[Ww]arning|[Ff]ail)/i)
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
describe('Run resolc with source debug information', () => {
|
|
||||||
const commands = [
|
|
||||||
`resolc -g ${paths.pathToBasicSolContract} --overwrite --bin --asm --output-dir "${paths.pathToOutputDir}"`,
|
|
||||||
`resolc --disable-solc-optimizer -g ${paths.pathToBasicSolContract} --overwrite --bin --asm --output-dir "${paths.pathToOutputDir}"`,
|
|
||||||
] // potential issue on resolc with full path on Windows cmd`;
|
|
||||||
|
|
||||||
for (var idx in commands) {
|
|
||||||
const command = commands[idx]
|
|
||||||
const result = executeCommand(command)
|
|
||||||
|
|
||||||
it('Compiler run successful', () => {
|
|
||||||
expect(result.output).toMatch(/(Compiler run successful.)/i)
|
|
||||||
})
|
|
||||||
it('Exit code = 0', () => {
|
|
||||||
expect(result.exitCode).toBe(0)
|
|
||||||
})
|
|
||||||
it('Output dir is created', () => {
|
|
||||||
expect(isFolderExist(paths.pathToOutputDir)).toBe(true)
|
|
||||||
})
|
|
||||||
it('Output files are created', () => {
|
|
||||||
// a bug on windows
|
|
||||||
expect(
|
|
||||||
isFileExist(
|
|
||||||
paths.pathToOutputDir,
|
|
||||||
paths.contractSolFilename,
|
|
||||||
paths.binExtension
|
|
||||||
)
|
|
||||||
).toBe(true)
|
|
||||||
expect(
|
|
||||||
isFileExist(
|
|
||||||
paths.pathToOutputDir,
|
|
||||||
paths.contractSolFilename,
|
|
||||||
paths.asmExtension
|
|
||||||
)
|
|
||||||
).toBe(true)
|
|
||||||
})
|
|
||||||
it('the output files are not empty', () => {
|
|
||||||
expect(isFileEmpty(paths.pathToSolBinOutputFile)).toBe(false)
|
|
||||||
expect(isFileEmpty(paths.pathToSolAsmOutputFile)).toBe(false)
|
|
||||||
})
|
|
||||||
it("No 'Error'/'Fail' in the output", () => {
|
|
||||||
expect(result.output).not.toMatch(/([Ee]rror|[Ff]ail)/i)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
describe('Run resolc with source debug information, check LLVM debug-info', () => {
|
|
||||||
const commands = [
|
|
||||||
`resolc -g ${paths.pathToBasicSolContract} --overwrite --debug-output-dir="${paths.pathToOutputDir}"`,
|
|
||||||
`resolc -g --disable-solc-optimizer ${paths.pathToBasicSolContract} --overwrite --debug-output-dir="${paths.pathToOutputDir}"`,
|
|
||||||
] // potential issue on resolc with full path on Windows cmd`;
|
|
||||||
|
|
||||||
for (var idx in commands) {
|
|
||||||
const command = commands[idx]
|
|
||||||
const result = executeCommand(command)
|
|
||||||
|
|
||||||
it('Compiler run successful', () => {
|
|
||||||
expect(result.output).toMatch(/(Compiler run successful.)/i)
|
|
||||||
})
|
|
||||||
it('Exit code = 0', () => {
|
|
||||||
expect(result.exitCode).toBe(0)
|
|
||||||
})
|
|
||||||
it('Output dir is created', () => {
|
|
||||||
expect(isFolderExist(paths.pathToOutputDir)).toBe(true)
|
|
||||||
})
|
|
||||||
it('Output files are created', () => {
|
|
||||||
// a bug on windows
|
|
||||||
expect(
|
|
||||||
isFileExist(
|
|
||||||
paths.pathToOutputDir,
|
|
||||||
paths.contractOptimizedLLVMFilename,
|
|
||||||
paths.llvmExtension
|
|
||||||
)
|
|
||||||
).toBe(true)
|
|
||||||
expect(
|
|
||||||
isFileExist(
|
|
||||||
paths.pathToOutputDir,
|
|
||||||
paths.contractUnoptimizedLLVMFilename,
|
|
||||||
paths.llvmExtension
|
|
||||||
)
|
|
||||||
).toBe(true)
|
|
||||||
})
|
|
||||||
it('the output files are not empty', () => {
|
|
||||||
expect(isFileEmpty(paths.pathToSolBinOutputFile)).toBe(false)
|
|
||||||
expect(isFileEmpty(paths.pathToSolAsmOutputFile)).toBe(false)
|
|
||||||
})
|
|
||||||
it("No 'Error'/'Fail' in the output", () => {
|
|
||||||
expect(result.output).not.toMatch(/([Ee]rror|[Ff]ail)/i)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
describe('Standard JSON compilation with path options', () => {
|
|
||||||
const contractsDir = path.join(shell.tempdir(), 'contracts-test')
|
|
||||||
const inputFile = path.join(__dirname, '..', 'src/contracts/compiled/1.json')
|
|
||||||
|
|
||||||
beforeAll(() => {
|
|
||||||
shell.mkdir('-p', contractsDir)
|
|
||||||
|
|
||||||
const input = JSON.parse(shell.cat(inputFile).toString())
|
|
||||||
|
|
||||||
Object.entries(input.sources).forEach(
|
|
||||||
([sourcePath, source]: [string, any]) => {
|
|
||||||
const filePath = path.join(contractsDir, sourcePath)
|
|
||||||
shell.mkdir('-p', path.dirname(filePath))
|
|
||||||
shell.ShellString(source.content).to(filePath)
|
|
||||||
}
|
|
||||||
)
|
|
||||||
})
|
|
||||||
|
|
||||||
afterAll(() => {
|
|
||||||
shell.rm('-rf', contractsDir)
|
|
||||||
})
|
|
||||||
|
|
||||||
describe('Output with all path options', () => {
|
|
||||||
let result: { exitCode: number; output: string }
|
|
||||||
|
|
||||||
beforeAll(() => {
|
|
||||||
const tempInputFile = path.join(contractsDir, 'temp-input.json')
|
|
||||||
shell.cp(inputFile, tempInputFile)
|
|
||||||
const inputContent = shell.cat(inputFile).toString()
|
|
||||||
|
|
||||||
const command = `resolc --standard-json --base-path "${contractsDir}" --include-path "${contractsDir}" --allow-paths "${contractsDir}"`
|
|
||||||
|
|
||||||
result = executeCommand(command, inputContent)
|
|
||||||
|
|
||||||
shell.rm(tempInputFile)
|
|
||||||
})
|
|
||||||
|
|
||||||
it('Compiler run successful without emiting warnings', () => {
|
|
||||||
const parsedResults = JSON.parse(result.output)
|
|
||||||
expect(
|
|
||||||
parsedResults.errors.filter(
|
|
||||||
(error: { type: string }) => error.type != 'Warning'
|
|
||||||
)
|
|
||||||
).toEqual([])
|
|
||||||
})
|
|
||||||
})
|
|
||||||
})
|
|
||||||
@@ -1,18 +0,0 @@
|
|||||||
import { executeCommand } from '../src/helper'
|
|
||||||
import { paths } from '../src/entities'
|
|
||||||
|
|
||||||
describe('tests for the memset builtin to be present', () => {
|
|
||||||
// -O3 is required to reproduce.
|
|
||||||
const command = `resolc ${paths.pathToMemsetYulContract} --yul -O3`
|
|
||||||
const result = executeCommand(command)
|
|
||||||
|
|
||||||
it('Valid command exit code = 0', () => {
|
|
||||||
expect(result.exitCode).toBe(0)
|
|
||||||
})
|
|
||||||
|
|
||||||
it('--yul output is presented', () => {
|
|
||||||
expect(result.output).toMatch(/(Compiler run successful)/i)
|
|
||||||
expect(result.output).toMatch(/(No output requested)/i)
|
|
||||||
})
|
|
||||||
|
|
||||||
})
|
|
||||||
@@ -1,39 +0,0 @@
|
|||||||
import { executeCommand } from '../src/helper'
|
|
||||||
import { paths } from '../src/entities'
|
|
||||||
|
|
||||||
//id1743
|
|
||||||
describe('Run with --yul by default', () => {
|
|
||||||
const command = `resolc ${paths.pathToBasicYulContract} --yul`
|
|
||||||
const result = executeCommand(command)
|
|
||||||
const commandInvalid = 'resolc --yul'
|
|
||||||
const resultInvalid = executeCommand(commandInvalid)
|
|
||||||
|
|
||||||
it('Valid command exit code = 0', () => {
|
|
||||||
expect(result.exitCode).toBe(0)
|
|
||||||
})
|
|
||||||
|
|
||||||
it('--yul output is presented', () => {
|
|
||||||
expect(result.output).toMatch(/(Compiler run successful)/i)
|
|
||||||
expect(result.output).toMatch(/(No output requested)/i)
|
|
||||||
})
|
|
||||||
|
|
||||||
xit('solc exit code == resolc exit code', () => {
|
|
||||||
// unknown solc issue for datatype of the contract
|
|
||||||
const command = `solc ${paths.pathToBasicSolContract} --yul`
|
|
||||||
const solcResult = executeCommand(command)
|
|
||||||
expect(solcResult.exitCode).toBe(result.exitCode)
|
|
||||||
})
|
|
||||||
|
|
||||||
it('run invalid: resolc --yul', () => {
|
|
||||||
expect(resultInvalid.output).toMatch(/(The input file is missing)/i)
|
|
||||||
})
|
|
||||||
it('Invalid command exit code = 1', () => {
|
|
||||||
expect(resultInvalid.exitCode).toBe(1)
|
|
||||||
})
|
|
||||||
|
|
||||||
it('Invalid solc exit code == Invalid resolc exit code', () => {
|
|
||||||
const command = 'solc --yul'
|
|
||||||
const solcResult = executeCommand(command)
|
|
||||||
expect(solcResult.exitCode).toBe(resultInvalid.exitCode)
|
|
||||||
})
|
|
||||||
})
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
{
|
|
||||||
"compilerOptions": {
|
|
||||||
"target": "ES6",
|
|
||||||
"module": "CommonJS",
|
|
||||||
"outDir": "./dist",
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,40 @@
|
|||||||
|
//! The tests for running resolc with asm option.
|
||||||
|
|
||||||
|
#![cfg(test)]
|
||||||
|
|
||||||
|
use crate::tests::cli::utils;
|
||||||
|
|
||||||
|
const ASM_OPTION: &str = "--asm";
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn runs_with_valid_input_file() {
|
||||||
|
let arguments = &[utils::SOLIDITY_CONTRACT_PATH, ASM_OPTION];
|
||||||
|
let resolc_result = utils::execute_resolc(arguments);
|
||||||
|
utils::assert_command_success(&resolc_result, "Providing a valid input file");
|
||||||
|
|
||||||
|
for pattern in &["deploy", "call", "seal_return"] {
|
||||||
|
assert!(
|
||||||
|
resolc_result.stdout.contains(pattern),
|
||||||
|
"Expected the output to contain `{pattern}`."
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
let solc_result = utils::execute_solc(arguments);
|
||||||
|
utils::assert_equal_exit_codes(&solc_result, &resolc_result);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn fails_without_input_file() {
|
||||||
|
let arguments = &[ASM_OPTION];
|
||||||
|
let resolc_result = utils::execute_resolc(arguments);
|
||||||
|
utils::assert_command_failure(&resolc_result, "Omitting an input file");
|
||||||
|
|
||||||
|
let output = resolc_result.stderr.to_lowercase();
|
||||||
|
assert!(
|
||||||
|
output.contains("no input sources specified") || output.contains("compilation aborted"),
|
||||||
|
"Expected the output to contain a specific error message."
|
||||||
|
);
|
||||||
|
|
||||||
|
let solc_result = utils::execute_solc(arguments);
|
||||||
|
utils::assert_equal_exit_codes(&solc_result, &resolc_result);
|
||||||
|
}
|
||||||
@@ -0,0 +1,137 @@
|
|||||||
|
//! The tests for running resolc with combined JSON option.
|
||||||
|
|
||||||
|
#![cfg(test)]
|
||||||
|
|
||||||
|
use revive_common;
|
||||||
|
|
||||||
|
use crate::tests::cli::utils;
|
||||||
|
|
||||||
|
const JSON_OPTION: &str = "--combined-json";
|
||||||
|
const JSON_ARGUMENTS: &[&str] = &[
|
||||||
|
"abi",
|
||||||
|
"hashes",
|
||||||
|
"metadata",
|
||||||
|
"devdoc",
|
||||||
|
"userdoc",
|
||||||
|
"storage-layout",
|
||||||
|
"ast",
|
||||||
|
"asm",
|
||||||
|
"bin",
|
||||||
|
"bin-runtime",
|
||||||
|
];
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn runs_with_valid_json_argument() {
|
||||||
|
for json_argument in JSON_ARGUMENTS {
|
||||||
|
let arguments = &[utils::SOLIDITY_CONTRACT_PATH, JSON_OPTION, json_argument];
|
||||||
|
let resolc_result = utils::execute_resolc(arguments);
|
||||||
|
assert!(
|
||||||
|
resolc_result.success,
|
||||||
|
"Providing the `{json_argument}` argument should succeed with exit code {}, got {}.\nDetails: {}",
|
||||||
|
revive_common::EXIT_CODE_SUCCESS,
|
||||||
|
resolc_result.code,
|
||||||
|
resolc_result.stderr
|
||||||
|
);
|
||||||
|
|
||||||
|
assert!(
|
||||||
|
resolc_result.stdout.contains("contracts"),
|
||||||
|
"Expected the output to contain a `contracts` field when using the `{json_argument}` argument."
|
||||||
|
);
|
||||||
|
|
||||||
|
let solc_result = utils::execute_solc(arguments);
|
||||||
|
utils::assert_equal_exit_codes(&solc_result, &resolc_result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn fails_with_invalid_json_argument() {
|
||||||
|
let arguments = &[
|
||||||
|
utils::SOLIDITY_CONTRACT_PATH,
|
||||||
|
JSON_OPTION,
|
||||||
|
"invalid-argument",
|
||||||
|
];
|
||||||
|
let resolc_result = utils::execute_resolc(arguments);
|
||||||
|
utils::assert_command_failure(&resolc_result, "Providing an invalid json argument");
|
||||||
|
|
||||||
|
assert!(
|
||||||
|
resolc_result.stdout.contains("Invalid option"),
|
||||||
|
"Expected the output to contain a specific error message."
|
||||||
|
);
|
||||||
|
|
||||||
|
let solc_result = utils::execute_solc(arguments);
|
||||||
|
utils::assert_equal_exit_codes(&solc_result, &resolc_result);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn fails_with_multiple_json_arguments() {
|
||||||
|
let arguments = &[
|
||||||
|
utils::SOLIDITY_CONTRACT_PATH,
|
||||||
|
JSON_OPTION,
|
||||||
|
JSON_ARGUMENTS[0],
|
||||||
|
JSON_ARGUMENTS[1],
|
||||||
|
];
|
||||||
|
let resolc_result = utils::execute_resolc(arguments);
|
||||||
|
utils::assert_command_failure(&resolc_result, "Providing multiple json arguments");
|
||||||
|
|
||||||
|
assert!(
|
||||||
|
resolc_result
|
||||||
|
.stderr
|
||||||
|
.contains("reading error: No such file or directory"),
|
||||||
|
"Expected the output to contain a specific error message."
|
||||||
|
);
|
||||||
|
|
||||||
|
// FIX: Resolc exit code == 101
|
||||||
|
// let solc_result = utils::execute_solc(arguments);
|
||||||
|
// utils::assert_equal_exit_codes(&solc_result, &resolc_result);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn fails_without_json_argument() {
|
||||||
|
let arguments = &[utils::SOLIDITY_CONTRACT_PATH, JSON_OPTION];
|
||||||
|
let resolc_result = utils::execute_resolc(arguments);
|
||||||
|
utils::assert_command_failure(&resolc_result, "Omitting a JSON argument");
|
||||||
|
|
||||||
|
assert!(
|
||||||
|
resolc_result.stderr.contains(
|
||||||
|
"a value is required for '--combined-json <COMBINED_JSON>' but none was supplied"
|
||||||
|
),
|
||||||
|
"Expected the output to contain a specific error message."
|
||||||
|
);
|
||||||
|
|
||||||
|
let solc_result = utils::execute_solc(arguments);
|
||||||
|
utils::assert_equal_exit_codes(&solc_result, &resolc_result);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn fails_without_solidity_input_file() {
|
||||||
|
let arguments = &[JSON_OPTION, JSON_ARGUMENTS[0]];
|
||||||
|
let resolc_result = utils::execute_resolc(arguments);
|
||||||
|
utils::assert_command_failure(&resolc_result, "Omitting a Solidity input file");
|
||||||
|
|
||||||
|
assert!(
|
||||||
|
resolc_result.stderr.contains("No input sources specified"),
|
||||||
|
"Expected the output to contain a specific error message."
|
||||||
|
);
|
||||||
|
|
||||||
|
let solc_result = utils::execute_solc(arguments);
|
||||||
|
utils::assert_equal_exit_codes(&solc_result, &resolc_result);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn fails_with_yul_input_file() {
|
||||||
|
for json_argument in JSON_ARGUMENTS {
|
||||||
|
let arguments = &[utils::YUL_CONTRACT_PATH, JSON_OPTION, json_argument];
|
||||||
|
let resolc_result = utils::execute_resolc(arguments);
|
||||||
|
utils::assert_command_failure(&resolc_result, "Providing a Yul input file");
|
||||||
|
|
||||||
|
assert!(
|
||||||
|
resolc_result
|
||||||
|
.stderr
|
||||||
|
.contains("ParserError: Expected identifier"),
|
||||||
|
"Expected the output to contain a specific error message."
|
||||||
|
);
|
||||||
|
|
||||||
|
let solc_result = utils::execute_solc(arguments);
|
||||||
|
utils::assert_equal_exit_codes(&solc_result, &resolc_result);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
object "Test" {
|
||||||
|
code {
|
||||||
|
function allocate(size) -> ptr {
|
||||||
|
ptr := mload(0x40)
|
||||||
|
if iszero(ptr) { ptr := 0x60 }
|
||||||
|
mstore(0x40, add(ptr, size))
|
||||||
|
}
|
||||||
|
let size := datasize("Test_deployed")
|
||||||
|
let offset := allocate(size)
|
||||||
|
datacopy(offset, dataoffset("Test_deployed"), size)
|
||||||
|
return(offset, size)
|
||||||
|
}
|
||||||
|
object "Test_deployed" {
|
||||||
|
code {
|
||||||
|
{
|
||||||
|
let test:=0x5
|
||||||
|
mstore(2,signextend(0x8,0x0))
|
||||||
|
mstore(8,lt(0xc,test))
|
||||||
|
}
|
||||||
|
|
||||||
|
return(0, 65536)
|
||||||
|
}}}
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
//! The CLI tests.
|
||||||
|
|
||||||
|
#![cfg(test)]
|
||||||
|
|
||||||
|
mod asm;
|
||||||
|
mod combined_json;
|
||||||
|
mod optimization;
|
||||||
|
mod output_dir;
|
||||||
|
mod standard_json;
|
||||||
|
mod usage;
|
||||||
|
mod utils;
|
||||||
|
mod yul;
|
||||||
@@ -0,0 +1,53 @@
|
|||||||
|
//! The tests for running resolc with explicit optimization.
|
||||||
|
|
||||||
|
#![cfg(test)]
|
||||||
|
|
||||||
|
use revive_common;
|
||||||
|
|
||||||
|
use crate::tests::cli::{utils, yul};
|
||||||
|
|
||||||
|
const LEVELS: &[char] = &['0', '1', '2', '3', 's', 'z'];
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn runs_with_valid_level() {
|
||||||
|
for level in LEVELS {
|
||||||
|
let optimization_argument = format!("-O{level}");
|
||||||
|
let arguments = &[
|
||||||
|
utils::YUL_MEMSET_CONTRACT_PATH,
|
||||||
|
yul::YUL_OPTION,
|
||||||
|
&optimization_argument,
|
||||||
|
];
|
||||||
|
let resolc_result = utils::execute_resolc(arguments);
|
||||||
|
assert!(
|
||||||
|
resolc_result.success,
|
||||||
|
"Providing the level `{optimization_argument}` should succeed with exit code {}, got {}.\nDetails: {}",
|
||||||
|
revive_common::EXIT_CODE_SUCCESS,
|
||||||
|
resolc_result.code,
|
||||||
|
resolc_result.stderr
|
||||||
|
);
|
||||||
|
|
||||||
|
assert!(
|
||||||
|
resolc_result
|
||||||
|
.stderr
|
||||||
|
.contains("Compiler run successful. No output requested"),
|
||||||
|
"Expected the output to contain a success message when providing the level `{optimization_argument}`."
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn fails_with_invalid_level() {
|
||||||
|
let arguments = &[utils::YUL_MEMSET_CONTRACT_PATH, yul::YUL_OPTION, "-O9"];
|
||||||
|
let resolc_result = utils::execute_resolc(arguments);
|
||||||
|
utils::assert_command_failure(&resolc_result, "Providing an invalid optimization level");
|
||||||
|
|
||||||
|
assert!(
|
||||||
|
resolc_result
|
||||||
|
.stderr
|
||||||
|
.contains("Unexpected optimization option"),
|
||||||
|
"Expected the output to contain a specific error message."
|
||||||
|
);
|
||||||
|
|
||||||
|
let solc_result = utils::execute_solc(arguments);
|
||||||
|
utils::assert_equal_exit_codes(&solc_result, &resolc_result);
|
||||||
|
}
|
||||||
@@ -0,0 +1,122 @@
|
|||||||
|
//! The tests for running resolc with output directory option.
|
||||||
|
|
||||||
|
#![cfg(test)]
|
||||||
|
|
||||||
|
use std::path::Path;
|
||||||
|
|
||||||
|
use crate::tests::cli::utils;
|
||||||
|
|
||||||
|
const OUTPUT_DIRECTORY: &str = "src/tests/cli/artifacts";
|
||||||
|
const OUTPUT_BIN_FILE_PATH: &str = "src/tests/cli/artifacts/contract.sol:C.pvm";
|
||||||
|
const OUTPUT_ASM_FILE_PATH: &str = "src/tests/cli/artifacts/contract.sol:C.pvmasm";
|
||||||
|
const OUTPUT_LLVM_OPTIMIZED_FILE_PATH: &str =
|
||||||
|
"src/tests/cli/artifacts/src_tests_cli_contracts_solidity_contract.sol.C.optimized.ll";
|
||||||
|
const OUTPUT_LLVM_UNOPTIMIZED_FILE_PATH: &str =
|
||||||
|
"src/tests/cli/artifacts/src_tests_cli_contracts_solidity_contract.sol.C.unoptimized.ll";
|
||||||
|
|
||||||
|
fn file_exists(path: &str) -> bool {
|
||||||
|
Path::new(path).try_exists().unwrap()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn file_is_empty(path: &str) -> bool {
|
||||||
|
Path::new(path).metadata().unwrap().len() == 0
|
||||||
|
}
|
||||||
|
|
||||||
|
fn assert_valid_output_file(
|
||||||
|
result: &utils::CommandResult,
|
||||||
|
output_file_type: &str,
|
||||||
|
output_file_path: &str,
|
||||||
|
) {
|
||||||
|
utils::assert_command_success(result, "Providing an output directory");
|
||||||
|
|
||||||
|
assert!(
|
||||||
|
result.stderr.contains("Compiler run successful"),
|
||||||
|
"Expected the compiler output to contain a success message.",
|
||||||
|
);
|
||||||
|
|
||||||
|
assert!(
|
||||||
|
file_exists(output_file_path),
|
||||||
|
"Expected the {output_file_type} output file `{output_file_path}` to exist."
|
||||||
|
);
|
||||||
|
|
||||||
|
assert!(
|
||||||
|
!file_is_empty(output_file_path),
|
||||||
|
"Expected the {output_file_type} output file `{output_file_path}` to not be empty."
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn writes_to_file() {
|
||||||
|
let arguments = &[
|
||||||
|
utils::SOLIDITY_CONTRACT_PATH,
|
||||||
|
"--overwrite",
|
||||||
|
"-O3",
|
||||||
|
"--bin",
|
||||||
|
"--asm",
|
||||||
|
"--output-dir",
|
||||||
|
OUTPUT_DIRECTORY,
|
||||||
|
];
|
||||||
|
let result = utils::execute_resolc(arguments);
|
||||||
|
assert_valid_output_file(&result, "--bin", OUTPUT_BIN_FILE_PATH);
|
||||||
|
assert_valid_output_file(&result, "--asm", OUTPUT_ASM_FILE_PATH);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn writes_debug_info_to_file_unoptimized() {
|
||||||
|
let arguments = &[
|
||||||
|
utils::SOLIDITY_CONTRACT_PATH,
|
||||||
|
"-g",
|
||||||
|
"--disable-solc-optimizer",
|
||||||
|
"--overwrite",
|
||||||
|
"--bin",
|
||||||
|
"--asm",
|
||||||
|
"--output-dir",
|
||||||
|
OUTPUT_DIRECTORY,
|
||||||
|
];
|
||||||
|
let result = utils::execute_resolc(arguments);
|
||||||
|
assert_valid_output_file(&result, "--bin", OUTPUT_BIN_FILE_PATH);
|
||||||
|
assert_valid_output_file(&result, "--asm", OUTPUT_ASM_FILE_PATH);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn writes_debug_info_to_file_optimized() {
|
||||||
|
let arguments = &[
|
||||||
|
utils::SOLIDITY_CONTRACT_PATH,
|
||||||
|
"-g",
|
||||||
|
"--overwrite",
|
||||||
|
"--bin",
|
||||||
|
"--asm",
|
||||||
|
"--output-dir",
|
||||||
|
OUTPUT_DIRECTORY,
|
||||||
|
];
|
||||||
|
let result = utils::execute_resolc(arguments);
|
||||||
|
assert_valid_output_file(&result, "--bin", OUTPUT_BIN_FILE_PATH);
|
||||||
|
assert_valid_output_file(&result, "--asm", OUTPUT_ASM_FILE_PATH);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn writes_llvm_debug_info_to_file_unoptimized() {
|
||||||
|
let arguments = &[
|
||||||
|
utils::SOLIDITY_CONTRACT_PATH,
|
||||||
|
"-g",
|
||||||
|
"--disable-solc-optimizer",
|
||||||
|
"--overwrite",
|
||||||
|
"--debug-output-dir",
|
||||||
|
OUTPUT_DIRECTORY,
|
||||||
|
];
|
||||||
|
let result = utils::execute_resolc(arguments);
|
||||||
|
assert_valid_output_file(&result, "llvm", OUTPUT_LLVM_UNOPTIMIZED_FILE_PATH);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn writes_llvm_debug_info_to_file_optimized() {
|
||||||
|
let arguments = &[
|
||||||
|
utils::SOLIDITY_CONTRACT_PATH,
|
||||||
|
"-g",
|
||||||
|
"--overwrite",
|
||||||
|
"--debug-output-dir",
|
||||||
|
OUTPUT_DIRECTORY,
|
||||||
|
];
|
||||||
|
let result = utils::execute_resolc(arguments);
|
||||||
|
assert_valid_output_file(&result, "llvm", OUTPUT_LLVM_OPTIMIZED_FILE_PATH);
|
||||||
|
}
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
//! The tests for running resolc with standard JSON option.
|
||||||
|
|
||||||
|
#![cfg(test)]
|
||||||
|
|
||||||
|
use crate::tests::cli::utils;
|
||||||
|
|
||||||
|
const JSON_OPTION: &str = "--standard-json";
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn runs_with_valid_input_file() {
|
||||||
|
let arguments = &[JSON_OPTION];
|
||||||
|
let resolc_result =
|
||||||
|
utils::execute_resolc_with_stdin_input(arguments, utils::STANDARD_JSON_CONTRACTS_PATH);
|
||||||
|
utils::assert_command_success(&resolc_result, "Providing a valid input file to stdin");
|
||||||
|
|
||||||
|
assert!(
|
||||||
|
resolc_result.stdout.contains("contracts"),
|
||||||
|
"Expected the output to contain a `contracts` field."
|
||||||
|
);
|
||||||
|
|
||||||
|
let solc_result =
|
||||||
|
utils::execute_solc_with_stdin_input(arguments, utils::STANDARD_JSON_CONTRACTS_PATH);
|
||||||
|
utils::assert_equal_exit_codes(&solc_result, &resolc_result);
|
||||||
|
}
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
//! The tests for running resolc when expecting usage output.
|
||||||
|
|
||||||
|
#![cfg(test)]
|
||||||
|
|
||||||
|
use crate::tests::cli::utils;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[ignore = "Fix: 'resolc --help' should exit with success exit code"]
|
||||||
|
fn shows_usage_with_help() {
|
||||||
|
let arguments = &["--help"];
|
||||||
|
let resolc_result = utils::execute_resolc(arguments);
|
||||||
|
utils::assert_command_success(&resolc_result, "Providing the `--help` option");
|
||||||
|
|
||||||
|
assert!(
|
||||||
|
resolc_result.stdout.contains("Usage: resolc"),
|
||||||
|
"Expected the output to contain usage information."
|
||||||
|
);
|
||||||
|
|
||||||
|
let solc_result = utils::execute_solc(arguments);
|
||||||
|
utils::assert_equal_exit_codes(&solc_result, &resolc_result);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn fails_without_options() {
|
||||||
|
let resolc_result = utils::execute_resolc(&[]);
|
||||||
|
utils::assert_command_failure(&resolc_result, "Omitting options");
|
||||||
|
|
||||||
|
assert!(
|
||||||
|
resolc_result.stderr.contains("Usage: resolc"),
|
||||||
|
"Expected the output to contain usage information."
|
||||||
|
);
|
||||||
|
|
||||||
|
let solc_result = utils::execute_solc(&[]);
|
||||||
|
utils::assert_equal_exit_codes(&solc_result, &resolc_result);
|
||||||
|
}
|
||||||
@@ -0,0 +1,99 @@
|
|||||||
|
//! Common utilities used for CLI tests.
|
||||||
|
|
||||||
|
use std::{
|
||||||
|
fs::File,
|
||||||
|
process::{Command, Stdio},
|
||||||
|
};
|
||||||
|
|
||||||
|
use revive_common;
|
||||||
|
|
||||||
|
use crate::SolcCompiler;
|
||||||
|
|
||||||
|
pub const SOLIDITY_CONTRACT_PATH: &str = "src/tests/cli/contracts/solidity/contract.sol";
|
||||||
|
pub const YUL_CONTRACT_PATH: &str = "src/tests/cli/contracts/yul/contract.yul";
|
||||||
|
pub const YUL_MEMSET_CONTRACT_PATH: &str = "src/tests/cli/contracts/yul/memset.yul";
|
||||||
|
pub const STANDARD_JSON_CONTRACTS_PATH: &str =
|
||||||
|
"src/tests/cli/contracts/standard_json/solidity_contracts.json";
|
||||||
|
|
||||||
|
/// The result of executing a command.
|
||||||
|
pub struct CommandResult {
|
||||||
|
/// The data written to `stdout`.
|
||||||
|
pub stdout: String,
|
||||||
|
/// The data written to `stderr`.
|
||||||
|
pub stderr: String,
|
||||||
|
/// Whether termination was successful.
|
||||||
|
pub success: bool,
|
||||||
|
/// The exit code of the process.
|
||||||
|
pub code: i32,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn execute_resolc(arguments: &[&str]) -> CommandResult {
|
||||||
|
execute_command("resolc", arguments, None)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn execute_resolc_with_stdin_input(arguments: &[&str], stdin_file_path: &str) -> CommandResult {
|
||||||
|
execute_command("resolc", arguments, Some(stdin_file_path))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn execute_solc(arguments: &[&str]) -> CommandResult {
|
||||||
|
execute_command(SolcCompiler::DEFAULT_EXECUTABLE_NAME, arguments, None)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn execute_solc_with_stdin_input(arguments: &[&str], stdin_file_path: &str) -> CommandResult {
|
||||||
|
execute_command(
|
||||||
|
SolcCompiler::DEFAULT_EXECUTABLE_NAME,
|
||||||
|
arguments,
|
||||||
|
Some(stdin_file_path),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn execute_command(
|
||||||
|
command: &str,
|
||||||
|
arguments: &[&str],
|
||||||
|
stdin_file_path: Option<&str>,
|
||||||
|
) -> CommandResult {
|
||||||
|
let stdin_config = match stdin_file_path {
|
||||||
|
Some(path) => Stdio::from(File::open(path).unwrap()),
|
||||||
|
None => Stdio::null(),
|
||||||
|
};
|
||||||
|
let result = Command::new(command)
|
||||||
|
.args(arguments)
|
||||||
|
.stdin(stdin_config)
|
||||||
|
.stdout(Stdio::piped())
|
||||||
|
.stderr(Stdio::piped())
|
||||||
|
.output()
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
CommandResult {
|
||||||
|
stdout: String::from_utf8_lossy(&result.stdout).to_string(),
|
||||||
|
stderr: String::from_utf8_lossy(&result.stderr).to_string(),
|
||||||
|
success: result.status.success(),
|
||||||
|
code: result.status.code().unwrap(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn assert_equal_exit_codes(solc_result: &CommandResult, resolc_result: &CommandResult) {
|
||||||
|
assert_eq!(
|
||||||
|
solc_result.code, resolc_result.code,
|
||||||
|
"Expected solc and resolc to have the same exit code."
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn assert_command_success(result: &CommandResult, error_message_prefix: &str) {
|
||||||
|
assert!(
|
||||||
|
result.success,
|
||||||
|
"{error_message_prefix} should succeed with exit code {}, got {}.\nDetails: {}",
|
||||||
|
revive_common::EXIT_CODE_SUCCESS,
|
||||||
|
result.code,
|
||||||
|
result.stderr
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn assert_command_failure(result: &CommandResult, error_message_prefix: &str) {
|
||||||
|
assert!(
|
||||||
|
!result.success,
|
||||||
|
"{error_message_prefix} should fail with exit code {}, got {}.",
|
||||||
|
revive_common::EXIT_CODE_FAILURE,
|
||||||
|
result.code
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -0,0 +1,44 @@
|
|||||||
|
//! The tests for running resolc with yul option.
|
||||||
|
|
||||||
|
#![cfg(test)]
|
||||||
|
|
||||||
|
use crate::tests::cli::utils;
|
||||||
|
|
||||||
|
pub const YUL_OPTION: &str = "--yul";
|
||||||
|
/// The `--yul` option was deprecated in Solidity 0.8.27 in favor of `--strict-assembly`.
|
||||||
|
/// See section `--strict-assembly vs. --yul` in https://soliditylang.org/blog/2024/09/04/solidity-0.8.27-release-announcement/
|
||||||
|
const SOLC_YUL_OPTION: &str = "--strict-assembly";
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn runs_with_valid_input_file() {
|
||||||
|
let arguments = &[utils::YUL_CONTRACT_PATH, YUL_OPTION];
|
||||||
|
let resolc_result = utils::execute_resolc(arguments);
|
||||||
|
utils::assert_command_success(&resolc_result, "Providing a valid input file");
|
||||||
|
|
||||||
|
assert!(
|
||||||
|
resolc_result
|
||||||
|
.stderr
|
||||||
|
.contains("Compiler run successful. No output requested"),
|
||||||
|
"Expected the output to contain a success message."
|
||||||
|
);
|
||||||
|
|
||||||
|
let solc_arguments = &[utils::YUL_CONTRACT_PATH, SOLC_YUL_OPTION];
|
||||||
|
let solc_result = utils::execute_solc(solc_arguments);
|
||||||
|
utils::assert_equal_exit_codes(&solc_result, &resolc_result);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn fails_without_input_file() {
|
||||||
|
let arguments = &[YUL_OPTION];
|
||||||
|
let resolc_result = utils::execute_resolc(arguments);
|
||||||
|
utils::assert_command_failure(&resolc_result, "Omitting an input file");
|
||||||
|
|
||||||
|
assert!(
|
||||||
|
resolc_result.stderr.contains("The input file is missing"),
|
||||||
|
"Expected the output to contain a specific error message."
|
||||||
|
);
|
||||||
|
|
||||||
|
let solc_arguments = &[SOLC_YUL_OPTION];
|
||||||
|
let solc_result = utils::execute_solc(solc_arguments);
|
||||||
|
utils::assert_equal_exit_codes(&solc_result, &resolc_result);
|
||||||
|
}
|
||||||
@@ -1,188 +0,0 @@
|
|||||||
import { executeCommand } from '../src/helper'
|
|
||||||
import { paths } from '../src/entities'
|
|
||||||
|
|
||||||
describe('Set of --combined-json tests', () => {
|
|
||||||
const zksolcCommand = 'zksolc'
|
|
||||||
const solcCommand = 'solc'
|
|
||||||
const json_args: string[] = [
|
|
||||||
`abi`,
|
|
||||||
`hashes`,
|
|
||||||
`metadata`,
|
|
||||||
`devdoc`,
|
|
||||||
`userdoc`,
|
|
||||||
`storage-layout`,
|
|
||||||
`ast`,
|
|
||||||
`asm`,
|
|
||||||
`bin`,
|
|
||||||
`bin-runtime`,
|
|
||||||
]
|
|
||||||
|
|
||||||
//id1742:I
|
|
||||||
describe(`Run ${zksolcCommand} with just --combined-json`, () => {
|
|
||||||
const args = [`--combined-json`]
|
|
||||||
const result = executeCommand(zksolcCommand, args)
|
|
||||||
|
|
||||||
it('Valid command exit code = 1', () => {
|
|
||||||
expect(result.exitCode).toBe(1)
|
|
||||||
})
|
|
||||||
|
|
||||||
it('--combined-json error is presented', () => {
|
|
||||||
expect(result.output).toMatch(/(requires a value but none was supplied)/i)
|
|
||||||
})
|
|
||||||
|
|
||||||
it('solc exit code == zksolc exit code', () => {
|
|
||||||
const solcResult = executeCommand(solcCommand, args)
|
|
||||||
expect(solcResult.exitCode).toBe(result.exitCode)
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
//id1742:II
|
|
||||||
describe(`Run ${zksolcCommand} with Sol contract and --combined-json`, () => {
|
|
||||||
const args = [`${paths.pathToBasicSolContract}`, `--combined-json`]
|
|
||||||
const result = executeCommand(zksolcCommand, args)
|
|
||||||
|
|
||||||
it('Valid command exit code = 1', () => {
|
|
||||||
expect(result.exitCode).toBe(1)
|
|
||||||
})
|
|
||||||
|
|
||||||
it('--combined-json error is presented', () => {
|
|
||||||
expect(result.output).toMatch(/(requires a value but none was supplied)/i)
|
|
||||||
})
|
|
||||||
|
|
||||||
it('solc exit code == zksolc exit code', () => {
|
|
||||||
const solcResult = executeCommand(solcCommand, args)
|
|
||||||
expect(solcResult.exitCode).toBe(result.exitCode)
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
//id1742:III
|
|
||||||
for (let i = 0; i < json_args.length; i++) {
|
|
||||||
describe(`Run ${zksolcCommand} with Sol, --combined-json and ARG: ${json_args[i]}`, () => {
|
|
||||||
const args = [
|
|
||||||
`${paths.pathToBasicSolContract}`,
|
|
||||||
`--combined-json`,
|
|
||||||
`${json_args[i]}`,
|
|
||||||
]
|
|
||||||
const result = executeCommand(zksolcCommand, args)
|
|
||||||
|
|
||||||
it('Valid command exit code = 0', () => {
|
|
||||||
expect(result.exitCode).toBe(0)
|
|
||||||
})
|
|
||||||
|
|
||||||
it('--combined-json error is presented', () => {
|
|
||||||
expect(result.output).toMatch(/(contracts)/i)
|
|
||||||
})
|
|
||||||
|
|
||||||
it('solc exit code == zksolc exit code', () => {
|
|
||||||
const solcResult = executeCommand(solcCommand, args)
|
|
||||||
expect(solcResult.exitCode).toBe(result.exitCode)
|
|
||||||
})
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
//id1829:I
|
|
||||||
for (let i = 0; i < json_args.length; i++) {
|
|
||||||
describe(`Run ${zksolcCommand} with Sol, --combined-json and wrong ARG: --${json_args[i]}`, () => {
|
|
||||||
const args = [
|
|
||||||
`${paths.pathToBasicSolContract}`,
|
|
||||||
`--combined-json`,
|
|
||||||
`--${json_args[i]}`,
|
|
||||||
]
|
|
||||||
const result = executeCommand(zksolcCommand, args)
|
|
||||||
|
|
||||||
it('Valid command exit code = 1', () => {
|
|
||||||
expect(result.exitCode).toBe(1)
|
|
||||||
})
|
|
||||||
|
|
||||||
it('--combined-json error is presented', () => {
|
|
||||||
expect(result.output).toMatch(/(Invalid option|error)/i)
|
|
||||||
})
|
|
||||||
|
|
||||||
it('solc exit code == zksolc exit code', () => {
|
|
||||||
const solcResult = executeCommand(solcCommand, args)
|
|
||||||
expect(solcResult.exitCode).toBe(result.exitCode)
|
|
||||||
})
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
//id1829:II
|
|
||||||
for (let i = 0; i < json_args.length; i++) {
|
|
||||||
describe(`Run ${zksolcCommand} with Sol, --combined-json and multiple ARG: ${json_args[i]} ${json_args[i]}`, () => {
|
|
||||||
const args = [
|
|
||||||
`${paths.pathToBasicSolContract}`,
|
|
||||||
`--combined-json`,
|
|
||||||
`${json_args[i]}`,
|
|
||||||
`${json_args[i]}`,
|
|
||||||
]
|
|
||||||
const result = executeCommand(zksolcCommand, args)
|
|
||||||
|
|
||||||
xit('Valid command exit code = 1', () => {
|
|
||||||
expect(result.exitCode).toBe(1)
|
|
||||||
})
|
|
||||||
|
|
||||||
it('--combined-json error is presented', () => {
|
|
||||||
expect(result.output).toMatch(
|
|
||||||
/(No such file or directory|cannot find the file specified)/i
|
|
||||||
) // Hopefully we should have more precise message here!
|
|
||||||
})
|
|
||||||
|
|
||||||
xit('solc exit code == zksolc exit code', () => {
|
|
||||||
const solcResult = executeCommand(solcCommand, args)
|
|
||||||
expect(solcResult.exitCode).toBe(result.exitCode)
|
|
||||||
})
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
//id1829:III
|
|
||||||
for (let i = 0; i < json_args.length; i++) {
|
|
||||||
describe(`Run ${zksolcCommand} with Sol, and multiple (--combined-json ${json_args[i]})`, () => {
|
|
||||||
const args = [
|
|
||||||
`${paths.pathToBasicSolContract}`,
|
|
||||||
`--combined-json`,
|
|
||||||
`${json_args[i]}`,
|
|
||||||
`--combined-json`,
|
|
||||||
`${json_args[i]}`,
|
|
||||||
]
|
|
||||||
const result = executeCommand(zksolcCommand, args)
|
|
||||||
|
|
||||||
it('Valid command exit code = 1', () => {
|
|
||||||
expect(result.exitCode).toBe(1)
|
|
||||||
})
|
|
||||||
|
|
||||||
it('--combined-json error is presented', () => {
|
|
||||||
expect(result.output).toMatch(/(cannot be used multiple times)/i)
|
|
||||||
})
|
|
||||||
|
|
||||||
it('solc exit code == zksolc exit code', () => {
|
|
||||||
const solcResult = executeCommand(solcCommand, args)
|
|
||||||
expect(solcResult.exitCode).toBe(result.exitCode)
|
|
||||||
})
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
//id1830
|
|
||||||
for (let i = 0; i < json_args.length; i++) {
|
|
||||||
describe(`Run ${zksolcCommand} with Yul, and --combined-json ${json_args[i]}`, () => {
|
|
||||||
const args = [
|
|
||||||
`${paths.pathToBasicYulContract}`,
|
|
||||||
`--combined-json`,
|
|
||||||
`${json_args[i]}`,
|
|
||||||
]
|
|
||||||
const result = executeCommand(zksolcCommand, args)
|
|
||||||
|
|
||||||
it('Valid command exit code = 1', () => {
|
|
||||||
expect(result.exitCode).toBe(1)
|
|
||||||
})
|
|
||||||
|
|
||||||
it('--combined-json error is presented', () => {
|
|
||||||
expect(result.output).toMatch(/(ParserError: Expected identifier)/i)
|
|
||||||
})
|
|
||||||
asd
|
|
||||||
|
|
||||||
it('solc exit code == zksolc exit code', () => {
|
|
||||||
const solcResult = executeCommand(solcCommand, args)
|
|
||||||
expect(solcResult.exitCode).toBe(result.exitCode)
|
|
||||||
})
|
|
||||||
})
|
|
||||||
}
|
|
||||||
})
|
|
||||||
@@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
#![cfg(test)]
|
#![cfg(test)]
|
||||||
|
|
||||||
|
mod cli;
|
||||||
mod factory_dependency;
|
mod factory_dependency;
|
||||||
mod ir_artifacts;
|
mod ir_artifacts;
|
||||||
mod libraries;
|
mod libraries;
|
||||||
|
|||||||
Generated
-3288
File diff suppressed because it is too large
Load Diff
@@ -2,14 +2,12 @@
|
|||||||
"name": "root",
|
"name": "root",
|
||||||
"private": true,
|
"private": true,
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"test:cli": "npm run test -w crates/resolc/src/tests/cli-tests",
|
|
||||||
"test:wasm": "npm run test:node -w js/emscripten",
|
"test:wasm": "npm run test:node -w js/emscripten",
|
||||||
"build:package": "npm run build:package -w js/emscripten",
|
"build:package": "npm run build:package -w js/emscripten",
|
||||||
"lint": "npx eslint 'js/**/*.{cjs,mjs,ts}' && npx prettier --check '**/*.{mjs,cjs,ts}'",
|
"lint": "npx eslint 'js/**/*.{cjs,mjs,ts}' && npx prettier --check '**/*.{mjs,cjs,ts}'",
|
||||||
"lint:fix": "npx prettier --write '**/*.{mjs,cjs,ts}'"
|
"lint:fix": "npx prettier --write '**/*.{mjs,cjs,ts}'"
|
||||||
},
|
},
|
||||||
"workspaces": [
|
"workspaces": [
|
||||||
"crates/resolc/src/tests/cli-tests",
|
|
||||||
"js/emscripten",
|
"js/emscripten",
|
||||||
"js/resolc"
|
"js/resolc"
|
||||||
],
|
],
|
||||||
|
|||||||
Reference in New Issue
Block a user