Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
B
baas-ide
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
JIRA
JIRA
Merge Requests
1
Merge Requests
1
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
guxukai
baas-ide
Commits
28773548
Commit
28773548
authored
Feb 11, 2021
by
aniket-engg
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
linting for remix-tests fixed
parent
84d0bac2
Hide whitespace changes
Inline
Side-by-side
Showing
13 changed files
with
909 additions
and
918 deletions
+909
-918
.eslintrc
libs/remix-tests/.eslintrc
+2
-5
assertionEvents.ts
libs/remix-tests/src/assertionEvents.ts
+37
-38
compiler.ts
libs/remix-tests/src/compiler.ts
+160
-163
deployer.ts
libs/remix-tests/src/deployer.ts
+92
-92
fileSystem.ts
libs/remix-tests/src/fileSystem.ts
+12
-12
logger.ts
libs/remix-tests/src/logger.ts
+32
-31
run.ts
libs/remix-tests/src/run.ts
+91
-92
runTestFiles.ts
libs/remix-tests/src/runTestFiles.ts
+134
-135
runTestSources.ts
libs/remix-tests/src/runTestSources.ts
+106
-107
testRunner.ts
libs/remix-tests/src/testRunner.ts
+230
-230
types.ts
libs/remix-tests/src/types.ts
+11
-11
package.json
package.json
+1
-1
workspace.json
workspace.json
+1
-1
No files found.
libs/remix-tests/.eslintrc
View file @
28773548
{
{
"extends": "../../.eslintrc",
"extends": "../../.eslintrc",
"rules": {
"rules": {
"@typescript-eslint/no-explicit-any": "off",
"dot-notation": "off",
"@typescript-eslint/no-var-requires": "off",
"no-unused-vars": "off"
"@typescript-eslint/no-unused-vars": "off",
"@typescript-eslint/explicit-module-boundary-types": "off",
"@typescript-eslint/ban-ts-comment": "off"
},
},
"env": {
"env": {
"browser": true,
"browser": true,
...
...
libs/remix-tests/src/assertionEvents.ts
View file @
28773548
const
assertionEvents
=
[
const
assertionEvents
=
[
{
{
name
:
'AssertionEvent'
,
name
:
'AssertionEvent'
,
params
:
[
'bool'
,
'string'
,
'string'
]
params
:
[
'bool'
,
'string'
,
'string'
]
},
},
{
{
name
:
'AssertionEventUint'
,
name
:
'AssertionEventUint'
,
params
:
[
'bool'
,
'string'
,
'string'
,
'uint256'
,
'uint256'
]
params
:
[
'bool'
,
'string'
,
'string'
,
'uint256'
,
'uint256'
]
},
},
{
{
name
:
'AssertionEventInt'
,
name
:
'AssertionEventInt'
,
params
:
[
'bool'
,
'string'
,
'string'
,
'int256'
,
'int256'
]
params
:
[
'bool'
,
'string'
,
'string'
,
'int256'
,
'int256'
]
},
},
{
{
name
:
'AssertionEventBool'
,
name
:
'AssertionEventBool'
,
params
:
[
'bool'
,
'string'
,
'string'
,
'bool'
,
'bool'
]
params
:
[
'bool'
,
'string'
,
'string'
,
'bool'
,
'bool'
]
},
},
{
{
name
:
'AssertionEventAddress'
,
name
:
'AssertionEventAddress'
,
params
:
[
'bool'
,
'string'
,
'string'
,
'address'
,
'address'
]
params
:
[
'bool'
,
'string'
,
'string'
,
'address'
,
'address'
]
},
},
{
{
name
:
'AssertionEventBytes32'
,
name
:
'AssertionEventBytes32'
,
params
:
[
'bool'
,
'string'
,
'string'
,
'bytes32'
,
'bytes32'
]
params
:
[
'bool'
,
'string'
,
'string'
,
'bytes32'
,
'bytes32'
]
},
},
{
{
name
:
'AssertionEventString'
,
name
:
'AssertionEventString'
,
params
:
[
'bool'
,
'string'
,
'string'
,
'string'
,
'string'
]
params
:
[
'bool'
,
'string'
,
'string'
,
'string'
,
'string'
]
},
},
{
{
name
:
'AssertionEventUintInt'
,
name
:
'AssertionEventUintInt'
,
params
:
[
'bool'
,
'string'
,
'string'
,
'uint256'
,
'int256'
]
params
:
[
'bool'
,
'string'
,
'string'
,
'uint256'
,
'int256'
]
},
},
{
{
name
:
'AssertionEventIntUint'
,
name
:
'AssertionEventIntUint'
,
params
:
[
'bool'
,
'string'
,
'string'
,
'int256'
,
'uint256'
]
params
:
[
'bool'
,
'string'
,
'string'
,
'int256'
,
'uint256'
]
}
}
]
]
export
default
assertionEvents
export
default
assertionEvents
\ No newline at end of file
libs/remix-tests/src/compiler.ts
View file @
28773548
...
@@ -2,26 +2,26 @@ import fs from './fileSystem'
...
@@ -2,26 +2,26 @@ import fs from './fileSystem'
import
async
from
'async'
import
async
from
'async'
import
path
from
'path'
import
path
from
'path'
import
Log
from
'./logger'
import
Log
from
'./logger'
const
logger
=
new
Log
()
const
log
=
logger
.
logger
import
{
Compiler
as
RemixCompiler
}
from
'@remix-project/remix-solidity'
import
{
Compiler
as
RemixCompiler
}
from
'@remix-project/remix-solidity'
import
{
SrcIfc
,
CompilerConfiguration
,
CompilationErrors
}
from
'./types'
import
{
SrcIfc
,
CompilerConfiguration
,
CompilationErrors
}
from
'./types'
const
logger
=
new
Log
()
const
log
=
logger
.
logger
function
regexIndexOf
(
inputString
:
string
,
regex
:
RegExp
,
startpos
=
0
)
{
function
regexIndexOf
(
inputString
:
string
,
regex
:
RegExp
,
startpos
=
0
)
{
const
indexOf
=
inputString
.
substring
(
startpos
).
search
(
regex
)
const
indexOf
=
inputString
.
substring
(
startpos
).
search
(
regex
)
return
(
indexOf
>=
0
)
?
(
indexOf
+
(
startpos
))
:
indexOf
return
(
indexOf
>=
0
)
?
(
indexOf
+
(
startpos
))
:
indexOf
}
}
function
writeTestAccountsContract
(
accounts
:
string
[])
{
function
writeTestAccountsContract
(
accounts
:
string
[])
{
const
testAccountContract
=
require
(
'../sol/tests_accounts.sol'
)
const
testAccountContract
=
require
(
'../sol/tests_accounts.sol'
)
let
body
=
`address[
${
accounts
.
length
}
] memory accounts;`
let
body
=
`address[
${
accounts
.
length
}
] memory accounts;`
if
(
!
accounts
.
length
)
body
+=
';'
if
(
!
accounts
.
length
)
body
+=
';'
else
{
else
{
accounts
.
map
((
address
,
index
)
=>
{
accounts
.
map
((
address
,
index
)
=>
{
body
+=
`\naccounts[
${
index
}
] =
${
address
}
;\n`
body
+=
`\naccounts[
${
index
}
] =
${
address
}
;\n`
})
})
}
}
return
testAccountContract
.
replace
(
'>accounts<'
,
body
)
return
testAccountContract
.
replace
(
'>accounts<'
,
body
)
}
}
/**
/**
...
@@ -29,47 +29,46 @@ function writeTestAccountsContract (accounts: string[]) {
...
@@ -29,47 +29,46 @@ function writeTestAccountsContract (accounts: string[]) {
* @param path file path to check
* @param path file path to check
*/
*/
function
isRemixTestFile
(
path
:
string
)
{
function
isRemixTestFile
(
path
:
string
)
{
return
[
'tests.sol'
,
'remix_tests.sol'
,
'remix_accounts.sol'
].
some
(
name
=>
path
.
includes
(
name
))
return
[
'tests.sol'
,
'remix_tests.sol'
,
'remix_accounts.sol'
].
some
(
name
=>
path
.
includes
(
name
))
}
}
/**
/**
* @dev Process file to prepare sources object to be passed in solc compiler input
* @dev Process file to prepare sources object to be passed in solc compiler input
*
*
* See: https://solidity.readthedocs.io/en/latest/using-the-compiler.html#input-description
* See: https://solidity.readthedocs.io/en/latest/using-the-compiler.html#input-description
*
*
* @param filePath path of file to process
* @param filePath path of file to process
* @param sources existing 'sources' object in which keys are the "global" names of the source files and
* @param sources existing 'sources' object in which keys are the "global" names of the source files and
* value is object containing content of corresponding file with under key 'content'
* value is object containing content of corresponding file with under key 'content'
* @param isRoot True, If file is a root test contract file which is getting processed, not an imported file
* @param isRoot True, If file is a root test contract file which is getting processed, not an imported file
*/
*/
function
processFile
(
filePath
:
string
,
sources
:
SrcIfc
,
isRoot
=
false
)
{
function
processFile
(
filePath
:
string
,
sources
:
SrcIfc
,
isRoot
=
false
)
{
const
importRegEx
=
/import
[
'"
](
.+
?)[
'"
]
;/g
const
importRegEx
=
/import
[
'"
](
.+
?)[
'"
]
;/g
let
group
:
RegExpExecArray
|
null
=
null
let
group
:
RegExpExecArray
|
null
=
null
const
isFileAlreadyInSources
:
boolean
=
Object
.
keys
(
sources
).
includes
(
filePath
)
const
isFileAlreadyInSources
:
boolean
=
Object
.
keys
(
sources
).
includes
(
filePath
)
// Return if file is a remix test file or already processed
// Return if file is a remix test file or already processed
if
(
isRemixTestFile
(
filePath
)
||
isFileAlreadyInSources
)
if
(
isRemixTestFile
(
filePath
)
||
isFileAlreadyInSources
)
{
return
}
return
let
content
:
string
=
fs
.
readFileSync
(
filePath
,
{
encoding
:
'utf-8'
})
let
content
:
string
=
fs
.
readFileSync
(
filePath
,
{
encoding
:
'utf-8'
})
const
testFileImportRegEx
=
/^
(
import
)\s[
'"
](
remix_tests.sol|tests.sol
)[
'"
]
;/gm
const
testFileImportRegEx
=
/^
(
import
)\s[
'"
](
remix_tests.sol|tests.sol
)[
'"
]
;/gm
// import 'remix_tests.sol', if file is a root test contract file and doesn't already have it
// import 'remix_tests.sol', if file is a root test contract file and doesn't already have it
if
(
isRoot
&&
filePath
.
endsWith
(
'_test.sol'
)
&&
regexIndexOf
(
content
,
testFileImportRegEx
)
<
0
)
{
if
(
isRoot
&&
filePath
.
endsWith
(
'_test.sol'
)
&&
regexIndexOf
(
content
,
testFileImportRegEx
)
<
0
)
{
const
includeTestLibs
=
'
\
nimport
\'
remix_tests.sol
\'
;
\
n'
const
includeTestLibs
=
'
\
nimport
\'
remix_tests.sol
\'
;
\
n'
content
=
includeTestLibs
.
concat
(
content
)
content
=
includeTestLibs
.
concat
(
content
)
}
}
sources
[
filePath
]
=
{
content
}
sources
[
filePath
]
=
{
content
}
importRegEx
.
exec
(
''
)
// Resetting state of RegEx
importRegEx
.
exec
(
''
)
// Resetting state of RegEx
// Process each 'import' in file content
// Process each 'import' in file content
while
((
group
=
importRegEx
.
exec
(
content
)))
{
while
((
group
=
importRegEx
.
exec
(
content
)))
{
const
importedFile
:
string
=
group
[
1
]
const
importedFile
:
string
=
group
[
1
]
const
importedFilePath
:
string
=
path
.
join
(
path
.
dirname
(
filePath
),
importedFile
)
const
importedFilePath
:
string
=
path
.
join
(
path
.
dirname
(
filePath
),
importedFile
)
processFile
(
importedFilePath
,
sources
)
processFile
(
importedFilePath
,
sources
)
}
}
}
}
const
userAgent
=
(
typeof
(
navigator
)
!==
'undefined'
)
&&
navigator
.
userAgent
?
navigator
.
userAgent
.
toLowerCase
()
:
'-'
const
userAgent
=
(
typeof
(
navigator
)
!==
'undefined'
)
&&
navigator
.
userAgent
?
navigator
.
userAgent
.
toLowerCase
()
:
'-'
...
@@ -81,88 +80,86 @@ const isBrowser = !(typeof (window) === 'undefined' || userAgent.indexOf(' elect
...
@@ -81,88 +80,86 @@ const isBrowser = !(typeof (window) === 'undefined' || userAgent.indexOf(' elect
* @param isDirectory True, if path is a directory
* @param isDirectory True, if path is a directory
* @param opts Options
* @param opts Options
* @param cb Callback
* @param cb Callback
*
*
* TODO: replace this with remix's own compiler code
* TODO: replace this with remix's own compiler code
*/
*/
export
function
compileFileOrFiles
(
filename
:
string
,
isDirectory
:
boolean
,
opts
:
any
,
compilerConfig
:
CompilerConfiguration
,
cb
):
void
{
export
function
compileFileOrFiles
(
filename
:
string
,
isDirectory
:
boolean
,
opts
:
any
,
compilerConfig
:
CompilerConfiguration
,
cb
):
void
{
let
compiler
:
any
let
compiler
:
any
const
accounts
:
string
[]
=
opts
.
accounts
||
[]
const
accounts
:
string
[]
=
opts
.
accounts
||
[]
const
sources
:
SrcIfc
=
{
const
sources
:
SrcIfc
=
{
'tests.sol'
:
{
content
:
require
(
'../sol/tests.sol'
)
},
'tests.sol'
:
{
content
:
require
(
'../sol/tests.sol'
)
},
'remix_tests.sol'
:
{
content
:
require
(
'../sol/tests.sol'
)
},
'remix_tests.sol'
:
{
content
:
require
(
'../sol/tests.sol'
)
},
'remix_accounts.sol'
:
{
content
:
writeTestAccountsContract
(
accounts
)
}
'remix_accounts.sol'
:
{
content
:
writeTestAccountsContract
(
accounts
)
}
}
const
filepath
:
string
=
(
isDirectory
?
filename
:
path
.
dirname
(
filename
))
try
{
if
(
!
isDirectory
&&
fs
.
existsSync
(
filename
))
{
if
(
filename
.
split
(
'.'
).
pop
()
===
'sol'
)
{
processFile
(
filename
,
sources
,
true
)
}
else
{
throw
new
Error
(
'Not a solidity file'
)
}
}
else
{
// walkSync only if it is a directory
let
testFileCount
=
0
fs
.
walkSync
(
filepath
,
(
foundpath
:
string
)
=>
{
// only process .sol files
if
(
foundpath
.
split
(
'.'
).
pop
()
===
'sol'
&&
foundpath
.
endsWith
(
'_test.sol'
))
{
testFileCount
++
processFile
(
foundpath
,
sources
,
true
)
}
})
if
(
testFileCount
>
0
)
{
log
.
info
(
`
${
testFileCount
}
Solidity test file
${
testFileCount
===
1
?
''
:
's'
}
found`
)
}
else
{
log
.
error
(
'No Solidity test file found. Make sure your test file ends with
\'
_test.sol
\'
'
)
process
.
exit
()
}
}
}
const
filepath
:
string
=
(
isDirectory
?
filename
:
path
.
dirname
(
filename
))
}
catch
(
e
)
{
// eslint-disable-line no-useless-catch
try
{
throw
e
if
(
!
isDirectory
&&
fs
.
existsSync
(
filename
))
{
}
finally
{
if
(
filename
.
split
(
'.'
).
pop
()
===
'sol'
)
{
async
.
waterfall
([
processFile
(
filename
,
sources
,
true
)
function
loadCompiler
(
next
)
{
}
else
{
compiler
=
new
RemixCompiler
()
throw
new
Error
(
'Not a solidity file'
)
if
(
compilerConfig
)
{
}
const
{
currentCompilerUrl
,
evmVersion
,
optimize
,
runs
}
=
compilerConfig
}
else
{
if
(
evmVersion
)
compiler
.
set
(
'evmVersion'
,
evmVersion
)
// walkSync only if it is a directory
if
(
optimize
)
compiler
.
set
(
'optimize'
,
optimize
)
let
testFileCount
=
0
if
(
runs
)
compiler
.
set
(
'runs'
,
runs
)
fs
.
walkSync
(
filepath
,
(
foundpath
:
string
)
=>
{
if
(
currentCompilerUrl
)
{
// only process .sol files
compiler
.
loadRemoteVersion
(
currentCompilerUrl
)
if
(
foundpath
.
split
(
'.'
).
pop
()
===
'sol'
&&
foundpath
.
endsWith
(
'_test.sol'
))
{
compiler
.
event
.
register
(
'compilerLoaded'
,
this
,
function
(
version
)
{
testFileCount
++
next
()
processFile
(
foundpath
,
sources
,
true
)
}
})
})
if
(
testFileCount
>
0
)
{
}
else
{
log
.
info
(
`
${
testFileCount
}
Solidity test file
${
testFileCount
===
1
?
''
:
's'
}
found`
)
compiler
.
onInternalCompilerLoaded
(
)
}
next
()
else
{
}
log
.
error
(
`No Solidity test file found. Make sure your test file ends with '_test.sol'`
)
}
else
{
process
.
exit
()
compiler
.
onInternalCompilerLoaded
()
}
next
()
}
}
},
}
catch
(
e
)
{
// eslint-disable-line no-useless-catch
function
doCompilation
(
next
)
{
throw
e
// @ts-ignore
}
finally
{
compiler
.
event
.
register
(
'compilationFinished'
,
this
,
(
success
,
data
,
source
)
=>
{
async
.
waterfall
([
next
(
null
,
data
)
function
loadCompiler
(
next
)
{
compiler
=
new
RemixCompiler
()
if
(
compilerConfig
)
{
const
{
currentCompilerUrl
,
evmVersion
,
optimize
,
runs
}
=
compilerConfig
evmVersion
?
compiler
.
set
(
'evmVersion'
,
evmVersion
)
:
null
optimize
?
compiler
.
set
(
'optimize'
,
optimize
)
:
null
runs
?
compiler
.
set
(
'runs'
,
runs
)
:
null
if
(
currentCompilerUrl
)
{
compiler
.
loadRemoteVersion
(
currentCompilerUrl
)
compiler
.
event
.
register
(
'compilerLoaded'
,
this
,
function
(
version
)
{
next
()
})
}
else
{
compiler
.
onInternalCompilerLoaded
()
next
()
}
}
else
{
compiler
.
onInternalCompilerLoaded
()
next
()
}
},
function
doCompilation
(
next
)
{
// @ts-ignore
compiler
.
event
.
register
(
'compilationFinished'
,
this
,
(
success
,
data
,
source
)
=>
{
next
(
null
,
data
)
})
compiler
.
compile
(
sources
,
filepath
)
}
],
function
(
err
:
Error
|
null
|
undefined
,
result
:
any
)
{
const
error
:
Error
[]
=
[]
if
(
result
.
error
)
error
.
push
(
result
.
error
)
const
errors
=
(
result
.
errors
||
error
).
filter
((
e
)
=>
e
.
type
===
'Error'
||
e
.
severity
===
'error'
)
if
(
errors
.
length
>
0
)
{
if
(
!
isBrowser
)
require
(
'signale'
).
fatal
(
errors
)
return
cb
(
new
CompilationErrors
(
errors
))
}
cb
(
err
,
result
.
contracts
,
result
.
sources
)
//return callback with contract details & ASTs
})
})
}
compiler
.
compile
(
sources
,
filepath
)
}
],
function
(
err
:
Error
|
null
|
undefined
,
result
:
any
)
{
const
error
:
Error
[]
=
[]
if
(
result
.
error
)
error
.
push
(
result
.
error
)
const
errors
=
(
result
.
errors
||
error
).
filter
((
e
)
=>
e
.
type
===
'Error'
||
e
.
severity
===
'error'
)
if
(
errors
.
length
>
0
)
{
if
(
!
isBrowser
)
require
(
'signale'
).
fatal
(
errors
)
return
cb
(
new
CompilationErrors
(
errors
))
}
cb
(
err
,
result
.
contracts
,
result
.
sources
)
// return callback with contract details & ASTs
})
}
}
}
/**
/**
...
@@ -173,53 +170,53 @@ export function compileFileOrFiles(filename: string, isDirectory: boolean, opts:
...
@@ -173,53 +170,53 @@ export function compileFileOrFiles(filename: string, isDirectory: boolean, opts:
* @param opts Options
* @param opts Options
* @param cb Callback
* @param cb Callback
*/
*/
export
function
compileContractSources
(
sources
:
SrcIfc
,
compilerConfig
:
CompilerConfiguration
,
importFileCb
:
any
,
opts
:
any
,
cb
):
void
{
export
function
compileContractSources
(
sources
:
SrcIfc
,
compilerConfig
:
CompilerConfiguration
,
importFileCb
:
any
,
opts
:
any
,
cb
):
void
{
let
compiler
,
filepath
:
string
let
compiler
,
filepath
:
string
const
accounts
:
string
[]
=
opts
.
accounts
||
[]
const
accounts
:
string
[]
=
opts
.
accounts
||
[]
// Iterate over sources keys. Inject test libraries. Inject test library import statements.
// Iterate over sources keys. Inject test libraries. Inject test library import statements.
if
(
!
(
'remix_tests.sol'
in
sources
)
&&
!
(
'tests.sol'
in
sources
))
{
if
(
!
(
'remix_tests.sol'
in
sources
)
&&
!
(
'tests.sol'
in
sources
))
{
sources
[
'tests.sol'
]
=
{
content
:
require
(
'../sol/tests.sol.js'
)
}
sources
[
'tests.sol'
]
=
{
content
:
require
(
'../sol/tests.sol.js'
)
}
sources
[
'remix_tests.sol'
]
=
{
content
:
require
(
'../sol/tests.sol.js'
)
}
sources
[
'remix_tests.sol'
]
=
{
content
:
require
(
'../sol/tests.sol.js'
)
}
sources
[
'remix_accounts.sol'
]
=
{
content
:
writeTestAccountsContract
(
accounts
)
}
sources
[
'remix_accounts.sol'
]
=
{
content
:
writeTestAccountsContract
(
accounts
)
}
}
const
testFileImportRegEx
=
/^
(
import
)\s[
'"
](
remix_tests.sol|tests.sol
)[
'"
]
;/gm
const
includeTestLibs
=
'
\
nimport
\'
remix_tests.sol
\'
;
\
n'
for
(
const
file
in
sources
)
{
const
c
:
string
=
sources
[
file
].
content
if
(
file
.
endsWith
(
'_test.sol'
)
&&
c
&&
regexIndexOf
(
c
,
testFileImportRegEx
)
<
0
)
{
sources
[
file
].
content
=
includeTestLibs
.
concat
(
c
)
}
}
const
testFileImportRegEx
=
/^
(
import
)\s[
'"
](
remix_tests.sol|tests.sol
)[
'"
]
;/gm
}
const
includeTestLibs
=
'
\
nimport
\'
remix_tests.sol
\'
;
\
n'
async
.
waterfall
([
for
(
const
file
in
sources
)
{
function
loadCompiler
(
next
)
{
const
c
:
string
=
sources
[
file
].
content
const
{
currentCompilerUrl
,
evmVersion
,
optimize
,
runs
,
usingWorker
}
=
compilerConfig
if
(
file
.
endsWith
(
'_test.sol'
)
&&
c
&&
regexIndexOf
(
c
,
testFileImportRegEx
)
<
0
)
{
compiler
=
new
RemixCompiler
(
importFileCb
)
sources
[
file
].
content
=
includeTestLibs
.
concat
(
c
)
compiler
.
set
(
'evmVersion'
,
evmVersion
)
}
compiler
.
set
(
'optimize'
,
optimize
)
compiler
.
set
(
'runs'
,
runs
)
compiler
.
loadVersion
(
usingWorker
,
currentCompilerUrl
)
// @ts-ignore
compiler
.
event
.
register
(
'compilerLoaded'
,
this
,
(
version
)
=>
{
next
()
})
},
function
doCompilation
(
next
)
{
// @ts-ignore
compiler
.
event
.
register
(
'compilationFinished'
,
this
,
(
success
,
data
,
source
)
=>
{
next
(
null
,
data
)
})
compiler
.
compile
(
sources
,
filepath
)
}
}
],
function
(
err
:
Error
|
null
|
undefined
,
result
:
any
)
{
async
.
waterfall
([
const
error
:
Error
[]
=
[]
function
loadCompiler
(
next
)
{
if
(
result
.
error
)
error
.
push
(
result
.
error
)
const
{
currentCompilerUrl
,
evmVersion
,
optimize
,
runs
,
usingWorker
}
=
compilerConfig
const
errors
=
(
result
.
errors
||
error
).
filter
((
e
)
=>
e
.
type
===
'Error'
||
e
.
severity
===
'error'
)
compiler
=
new
RemixCompiler
(
importFileCb
)
if
(
errors
.
length
>
0
)
{
compiler
.
set
(
'evmVersion'
,
evmVersion
)
if
(
!
isBrowser
)
require
(
'signale'
).
fatal
(
errors
)
compiler
.
set
(
'optimize'
,
optimize
)
return
cb
(
new
CompilationErrors
(
errors
))
compiler
.
set
(
'runs'
,
runs
)
}
compiler
.
loadVersion
(
usingWorker
,
currentCompilerUrl
)
cb
(
err
,
result
.
contracts
,
result
.
sources
)
// return callback with contract details & ASTs
// @ts-ignore
})
compiler
.
event
.
register
(
'compilerLoaded'
,
this
,
(
version
)
=>
{
next
()
})
},
function
doCompilation
(
next
)
{
// @ts-ignore
compiler
.
event
.
register
(
'compilationFinished'
,
this
,
(
success
,
data
,
source
)
=>
{
next
(
null
,
data
)
})
compiler
.
compile
(
sources
,
filepath
)
}
],
function
(
err
:
Error
|
null
|
undefined
,
result
:
any
)
{
const
error
:
Error
[]
=
[]
if
(
result
.
error
)
error
.
push
(
result
.
error
)
const
errors
=
(
result
.
errors
||
error
).
filter
((
e
)
=>
e
.
type
===
'Error'
||
e
.
severity
===
'error'
)
if
(
errors
.
length
>
0
)
{
if
(
!
isBrowser
)
require
(
'signale'
).
fatal
(
errors
)
return
cb
(
new
CompilationErrors
(
errors
))
}
cb
(
err
,
result
.
contracts
,
result
.
sources
)
// return callback with contract details & ASTs
})
}
}
libs/remix-tests/src/deployer.ts
View file @
28773548
...
@@ -11,108 +11,108 @@ import { compilationInterface } from './types'
...
@@ -11,108 +11,108 @@ import { compilationInterface } from './types'
* @param callback Callback
* @param callback Callback
*/
*/
export
function
deployAll
(
compileResult
:
compilationInterface
,
web3
:
Web3
,
withDoubleGas
:
boolean
,
callback
)
{
export
function
deployAll
(
compileResult
:
compilationInterface
,
web3
:
Web3
,
withDoubleGas
:
boolean
,
callback
)
{
const
compiledObject
=
{}
const
compiledObject
=
{}
const
contracts
=
{}
const
contracts
=
{}
let
accounts
:
string
[]
=
[]
let
accounts
:
string
[]
=
[]
async
.
waterfall
([
async
.
waterfall
([
function
getAccountList
(
next
)
{
function
getAccountList
(
next
)
{
web3
.
eth
.
getAccounts
((
_err
,
_accounts
)
=>
{
web3
.
eth
.
getAccounts
((
_err
,
_accounts
)
=>
{
accounts
=
_accounts
accounts
=
_accounts
next
()
next
()
})
})
},
},
function
getContractData
(
next
)
{
function
getContractData
(
next
)
{
for
(
const
contractFile
in
compileResult
)
{
for
(
const
contractFile
in
compileResult
)
{
for
(
const
contractName
in
compileResult
[
contractFile
])
{
for
(
const
contractName
in
compileResult
[
contractFile
])
{
const
contract
=
compileResult
[
contractFile
][
contractName
]
const
contract
=
compileResult
[
contractFile
][
contractName
]
const
className
=
contractName
const
className
=
contractName
const
filename
=
contractFile
const
filename
=
contractFile
const
abi
=
contract
.
abi
const
abi
=
contract
.
abi
const
code
=
contract
.
evm
.
bytecode
.
object
const
code
=
contract
.
evm
.
bytecode
.
object
compiledObject
[
className
]
=
{}
compiledObject
[
className
]
=
{}
compiledObject
[
className
].
abi
=
abi
compiledObject
[
className
].
abi
=
abi
compiledObject
[
className
].
code
=
code
compiledObject
[
className
].
code
=
code
compiledObject
[
className
].
filename
=
filename
compiledObject
[
className
].
filename
=
filename
compiledObject
[
className
].
className
=
className
compiledObject
[
className
].
className
=
className
compiledObject
[
className
].
raw
=
contract
compiledObject
[
className
].
raw
=
contract
if
(
contractFile
.
endsWith
(
'_test.sol'
))
{
if
(
contractFile
.
endsWith
(
'_test.sol'
))
{
compiledObject
[
className
].
isTest
=
true
compiledObject
[
className
].
isTest
=
true
}
}
}
}
}
}
next
()
next
()
},
},
function
determineContractsToDeploy
(
next
)
{
function
determineContractsToDeploy
(
next
)
{
const
contractsToDeploy
:
string
[]
=
[
'Assert'
]
const
contractsToDeploy
:
string
[]
=
[
'Assert'
]
const
allContracts
=
Object
.
keys
(
compiledObject
)
const
allContracts
=
Object
.
keys
(
compiledObject
)
for
(
const
contractName
of
allContracts
)
{
if
(
contractName
===
'Assert'
)
{
continue
}
if
(
compiledObject
[
contractName
].
isTest
)
{
contractsToDeploy
.
push
(
contractName
)
}
}
next
(
null
,
contractsToDeploy
)
},
function
deployContracts
(
contractsToDeploy
:
string
[],
next
)
{
const
deployRunner
=
(
deployObject
,
contractObject
,
contractName
,
filename
,
callback
)
=>
{
deployObject
.
estimateGas
().
then
((
gasValue
)
=>
{
const
gasBase
=
Math
.
ceil
(
gasValue
*
1.2
)
const
gas
=
withDoubleGas
?
gasBase
*
2
:
gasBase
deployObject
.
send
({
from
:
accounts
[
0
],
gas
:
gas
}).
on
(
'receipt'
,
function
(
receipt
)
{
contractObject
.
options
.
address
=
receipt
.
contractAddress
contractObject
.
options
.
from
=
accounts
[
0
]
contractObject
.
options
.
gas
=
5000
*
1000
compiledObject
[
contractName
].
deployedAddress
=
receipt
.
contractAddress
contracts
[
contractName
]
=
contractObject
for
(
const
contractName
of
allContracts
)
{
contracts
[
contractName
].
filename
=
filename
if
(
contractName
===
'Assert'
)
{
continue
}
if
(
compiledObject
[
contractName
].
isTest
)
{
contractsToDeploy
.
push
(
contractName
)
}
}
next
(
null
,
contractsToDeploy
)
},
function
deployContracts
(
contractsToDeploy
:
string
[],
next
)
{
const
deployRunner
=
(
deployObject
,
contractObject
,
contractName
,
filename
,
callback
)
=>
{
deployObject
.
estimateGas
().
then
((
gasValue
)
=>
{
const
gasBase
=
Math
.
ceil
(
gasValue
*
1.2
)
const
gas
=
withDoubleGas
?
gasBase
*
2
:
gasBase
deployObject
.
send
({
from
:
accounts
[
0
],
gas
:
gas
}).
on
(
'receipt'
,
function
(
receipt
)
{
contractObject
.
options
.
address
=
receipt
.
contractAddress
contractObject
.
options
.
from
=
accounts
[
0
]
contractObject
.
options
.
gas
=
5000
*
1000
compiledObject
[
contractName
].
deployedAddress
=
receipt
.
contractAddress
callback
(
null
,
{
result
:
{
createdAddress
:
receipt
.
contractAddress
}
})
// TODO this will only work with JavaScriptV VM
contracts
[
contractName
]
=
contractObject
}).
on
(
'error'
,
function
(
err
)
{
contracts
[
contractName
].
filename
=
filename
console
.
error
(
err
)
callback
(
err
)
})
})
}
async
.
eachOfLimit
(
contractsToDeploy
,
1
,
function
(
contractName
,
index
,
nextEach
)
{
callback
(
null
,
{
result
:
{
createdAddress
:
receipt
.
contractAddress
}
})
// TODO this will only work with JavaScriptV VM
const
contract
=
compiledObject
[
contractName
]
}).
on
(
'error'
,
function
(
err
)
{
const
encodeDataFinalCallback
=
(
error
,
contractDeployData
)
=>
{
console
.
error
(
err
)
if
(
error
)
return
nextEach
(
error
)
callback
(
err
)
const
contractObject
=
new
web3
.
eth
.
Contract
(
contract
.
abi
)
})
const
deployObject
=
contractObject
.
deploy
({
arguments
:
[],
data
:
'0x'
+
contractDeployData
.
dataHex
})
})
deployRunner
(
deployObject
,
contractObject
,
contractName
,
contract
.
filename
,
(
error
)
=>
{
nextEach
(
error
)
})
}
}
const
encodeDataStepCallback
=
(
msg
)
=>
{
console
.
dir
(
msg
)
}
async
.
eachOfLimit
(
contractsToDeploy
,
1
,
function
(
contractName
,
index
,
nextEach
)
{
const
contract
=
compiledObject
[
contractName
]
const
encodeDataFinalCallback
=
(
error
,
contractDeployData
)
=>
{
if
(
error
)
return
nextEach
(
error
)
const
contractObject
=
new
web3
.
eth
.
Contract
(
contract
.
abi
)
const
deployObject
=
contractObject
.
deploy
({
arguments
:
[],
data
:
'0x'
+
contractDeployData
.
dataHex
})
deployRunner
(
deployObject
,
contractObject
,
contractName
,
contract
.
filename
,
(
error
)
=>
{
nextEach
(
error
)
})
}
const
encodeDataDeployLibraryCallback
=
(
libData
,
callback
)
=>
{
const
encodeDataStepCallback
=
(
msg
)
=>
{
console
.
dir
(
msg
)
}
const
abi
=
compiledObject
[
libData
.
data
.
contractName
].
abi
const
code
=
compiledObject
[
libData
.
data
.
contractName
].
code
const
libraryObject
=
new
web3
.
eth
.
Contract
(
abi
)
const
deployObject
=
libraryObject
.
deploy
({
arguments
:
[],
data
:
'0x'
+
code
})
deployRunner
(
deployObject
,
libraryObject
,
libData
.
data
.
contractName
,
contract
.
filename
,
callback
)
}
const
funAbi
=
null
// no need to set the abi for encoding the constructor
const
encodeDataDeployLibraryCallback
=
(
libData
,
callback
)
=>
{
const
params
=
''
// we suppose that the test contract does not have any param in the constructor
const
abi
=
compiledObject
[
libData
.
data
.
contractName
].
abi
execution
.
txFormat
.
encodeConstructorCallAndDeployLibraries
(
contractName
,
contract
.
raw
,
compileResult
,
params
,
funAbi
,
encodeDataFinalCallback
,
encodeDataStepCallback
,
encodeDataDeployLibraryCallback
)
const
code
=
compiledObject
[
libData
.
data
.
contractName
].
code
},
function
(
err
)
{
const
libraryObject
=
new
web3
.
eth
.
Contract
(
abi
)
if
(
err
)
next
(
err
)
const
deployObject
=
libraryObject
.
deploy
({
arguments
:
[],
data
:
'0x'
+
code
})
next
(
null
,
contracts
)
deployRunner
(
deployObject
,
libraryObject
,
libData
.
data
.
contractName
,
contract
.
filename
,
callback
)
})
}
}
],
callback
)
const
funAbi
=
null
// no need to set the abi for encoding the constructor
const
params
=
''
// we suppose that the test contract does not have any param in the constructor
execution
.
txFormat
.
encodeConstructorCallAndDeployLibraries
(
contractName
,
contract
.
raw
,
compileResult
,
params
,
funAbi
,
encodeDataFinalCallback
,
encodeDataStepCallback
,
encodeDataDeployLibraryCallback
)
},
function
(
err
)
{
if
(
err
)
next
(
err
)
next
(
null
,
contracts
)
})
}
],
callback
)
}
}
libs/remix-tests/src/fileSystem.ts
View file @
28773548
// Extend fs
// Extend fs
const
fs
:
any
=
require
(
'fs'
)
import
path
from
'path'
import
path
from
'path'
const
fs
:
any
=
require
(
'fs'
)
// https://github.com/mikeal/node-utils/blob/master/file/lib/main.js
// https://github.com/mikeal/node-utils/blob/master/file/lib/main.js
fs
.
walkSync
=
function
(
start
:
string
,
callback
)
{
fs
.
walkSync
=
function
(
start
:
string
,
callback
)
{
fs
.
readdirSync
(
start
).
forEach
((
name
:
string
)
=>
{
fs
.
readdirSync
(
start
).
forEach
((
name
:
string
)
=>
{
if
(
name
===
'node_modules'
)
{
if
(
name
===
'node_modules'
)
{
return
// hack
return
// hack
}
}
const
abspath
=
path
.
join
(
start
,
name
)
const
abspath
=
path
.
join
(
start
,
name
)
if
(
fs
.
statSync
(
abspath
).
isDirectory
())
{
if
(
fs
.
statSync
(
abspath
).
isDirectory
())
{
fs
.
walkSync
(
abspath
,
callback
)
fs
.
walkSync
(
abspath
,
callback
)
}
else
{
}
else
{
callback
(
abspath
)
callback
(
abspath
)
}
}
})
})
}
}
export
=
fs
export
=
fs
libs/remix-tests/src/logger.ts
View file @
28773548
import
colors
from
'colors'
import
colors
from
'colors'
import
winston
,
{
Logger
,
LoggerOptions
}
from
'winston'
import
winston
,
{
Logger
,
LoggerOptions
}
from
'winston'
import
timestamp
from
'time-stamp'
;
import
timestamp
from
'time-stamp'
import
supportsColor
from
'color-support'
import
supportsColor
from
'color-support'
function
hasFlag
(
flag
:
string
)
{
function
hasFlag
(
flag
:
string
)
{
return
((
typeof
(
process
)
!==
'undefined'
)
&&
(
process
.
argv
.
indexOf
(
'--'
+
flag
)
!==
-
1
))
return
((
typeof
(
process
)
!==
'undefined'
)
&&
(
process
.
argv
.
indexOf
(
'--'
+
flag
)
!==
-
1
))
}
}
function
addColor
(
str
:
string
)
{
function
addColor
(
str
:
string
)
{
if
(
hasFlag
(
'no-color'
))
{
if
(
hasFlag
(
'no-color'
))
{
return
str
return
str
}
}
if
(
hasFlag
(
'color'
))
{
if
(
hasFlag
(
'color'
))
{
return
colors
.
gray
(
str
)
return
colors
.
gray
(
str
)
}
}
if
(
supportsColor
())
{
if
(
supportsColor
())
{
return
colors
.
gray
(
str
)
return
colors
.
gray
(
str
)
}
}
return
str
return
str
}
}
function
getTimestamp
()
{
function
getTimestamp
()
{
return
'['
+
addColor
(
timestamp
(
'HH:mm:ss'
))
+
']'
return
'['
+
addColor
(
timestamp
(
'HH:mm:ss'
))
+
']'
}
}
// create winston logger format
// create winston logger format
const
logFmt
=
winston
.
format
.
printf
((
info
)
=>
{
const
logFmt
=
winston
.
format
.
printf
((
info
)
=>
{
return
`
${
getTimestamp
()}
${
info
.
level
}
:
${
info
.
message
}
`
return
`
${
getTimestamp
()}
${
info
.
level
}
:
${
info
.
message
}
`
})
})
class
Log
{
class
Log
{
logger
:
Logger
;
logger
:
Logger
;
constructor
()
{
constructor
()
{
this
.
logger
=
winston
.
createLogger
({
this
.
logger
=
winston
.
createLogger
({
level
:
'info'
,
level
:
'info'
,
transports
:
[
new
winston
.
transports
.
Console
()],
transports
:
[
new
winston
.
transports
.
Console
()],
format
:
winston
.
format
.
combine
(
format
:
winston
.
format
.
combine
(
winston
.
format
.
colorize
({
all
:
true
}),
winston
.
format
.
colorize
({
all
:
true
}),
logFmt
logFmt
)
)
})
})
}
}
setVerbosity
(
v
:
LoggerOptions
[
"level"
]):
void
{
this
.
logger
.
configure
({
setVerbosity
(
v
:
LoggerOptions
[
'level'
]):
void
{
level
:
v
,
this
.
logger
.
configure
({
transports
:
[
new
winston
.
transports
.
Console
()],
level
:
v
,
format
:
winston
.
format
.
combine
(
transports
:
[
new
winston
.
transports
.
Console
()],
winston
.
format
.
colorize
({
all
:
true
}),
format
:
winston
.
format
.
combine
(
logFmt
winston
.
format
.
colorize
({
all
:
true
}),
)
logFmt
})
)
})
}
}
}
}
...
...
libs/remix-tests/src/run.ts
View file @
28773548
...
@@ -7,29 +7,29 @@ import fs from './fileSystem'
...
@@ -7,29 +7,29 @@ import fs from './fileSystem'
import
{
Provider
}
from
'@remix-project/remix-simulator'
import
{
Provider
}
from
'@remix-project/remix-simulator'
import
{
CompilerConfiguration
}
from
'./types'
import
{
CompilerConfiguration
}
from
'./types'
import
Log
from
'./logger'
import
Log
from
'./logger'
import
colors
from
'colors'
const
logger
=
new
Log
()
const
logger
=
new
Log
()
const
log
=
logger
.
logger
const
log
=
logger
.
logger
import
colors
from
'colors'
// parse verbosity
// parse verbosity
function
mapVerbosity
(
v
:
number
)
{
function
mapVerbosity
(
v
:
number
)
{
const
levels
=
{
const
levels
=
{
0
:
'error'
,
0
:
'error'
,
1
:
'warn'
,
1
:
'warn'
,
2
:
'info'
,
2
:
'info'
,
3
:
'verbose'
,
3
:
'verbose'
,
4
:
'debug'
,
4
:
'debug'
,
5
:
'silly'
5
:
'silly'
}
}
return
levels
[
v
]
return
levels
[
v
]
}
}
function
mapOptimize
(
v
:
string
)
{
function
mapOptimize
(
v
:
string
)
{
const
optimize
=
{
const
optimize
=
{
'true'
:
true
,
true
:
true
,
'false'
:
false
false
:
false
}
}
return
optimize
[
v
];
return
optimize
[
v
]
}
}
const
version
=
require
(
'../package.json'
).
version
const
version
=
require
(
'../package.json'
).
version
...
@@ -37,92 +37,91 @@ const version = require('../package.json').version
...
@@ -37,92 +37,91 @@ const version = require('../package.json').version
commander
.
version
(
version
)
commander
.
version
(
version
)
commander
.
command
(
'version'
).
description
(
'output the version number'
).
action
(
function
()
{
commander
.
command
(
'version'
).
description
(
'output the version number'
).
action
(
function
()
{
console
.
log
(
version
)
console
.
log
(
version
)
})
})
commander
.
command
(
'help'
).
description
(
'output usage information'
).
action
(
function
()
{
commander
.
command
(
'help'
).
description
(
'output usage information'
).
action
(
function
()
{
commander
.
help
()
commander
.
help
()
})
})
// get current version
// get current version
commander
commander
.
option
(
'-c, --compiler <string>'
,
'set compiler version (e.g: 0.6.1, 0.7.1 etc)'
)
.
option
(
'-c, --compiler <string>'
,
'set compiler version (e.g: 0.6.1, 0.7.1 etc)'
)
.
option
(
'-e, --evm <string>'
,
'set EVM version (e.g: petersburg, istanbul etc)'
)
.
option
(
'-e, --evm <string>'
,
'set EVM version (e.g: petersburg, istanbul etc)'
)
.
option
(
'-o, --optimize <bool>'
,
'enable/disable optimization'
,
mapOptimize
)
.
option
(
'-o, --optimize <bool>'
,
'enable/disable optimization'
,
mapOptimize
)
.
option
(
'-r, --runs <number>'
,
'set runs (e.g: 150, 250 etc)'
)
.
option
(
'-r, --runs <number>'
,
'set runs (e.g: 150, 250 etc)'
)
.
option
(
'-v, --verbose <level>'
,
'set verbosity level (0 to 5)'
,
mapVerbosity
)
.
option
(
'-v, --verbose <level>'
,
'set verbosity level (0 to 5)'
,
mapVerbosity
)
.
action
(
async
(
testsPath
)
=>
{
.
action
(
async
(
testsPath
)
=>
{
// Check if path exists
// Check if path exists
if
(
!
fs
.
existsSync
(
testsPath
))
{
if
(
!
fs
.
existsSync
(
testsPath
))
{
log
.
error
(
testsPath
+
' not found'
)
log
.
error
(
testsPath
+
' not found'
)
process
.
exit
(
1
)
process
.
exit
(
1
)
}
}
// Check if path is for a directory
// Check if path is for a directory
const
isDirectory
=
fs
.
lstatSync
(
testsPath
).
isDirectory
()
const
isDirectory
=
fs
.
lstatSync
(
testsPath
).
isDirectory
()
// If path is for a file, file name must have `_test.sol` suffix
// If path is for a file, file name must have `_test.sol` suffix
if
(
!
isDirectory
&&
!
testsPath
.
endsWith
(
'_test.sol'
))
{
if
(
!
isDirectory
&&
!
testsPath
.
endsWith
(
'_test.sol'
))
{
log
.
error
(
'Test filename should end with "_test.sol"'
)
log
.
error
(
'Test filename should end with "_test.sol"'
)
process
.
exit
()
process
.
exit
()
}
}
// Console message
// Console message
console
.
log
(
colors
.
white
(
'
\
n
\
t👁
\
t:: Running remix-tests - Unit testing for solidity ::
\
t👁
\
n'
))
console
.
log
(
colors
.
white
(
'
\
n
\
t👁
\
t:: Running remix-tests - Unit testing for solidity ::
\
t👁
\
n'
))
// Set logger verbosity
// Set logger verbosity
if
(
commander
.
verbose
)
{
if
(
commander
.
verbose
)
{
logger
.
setVerbosity
(
commander
.
verbose
)
logger
.
setVerbosity
(
commander
.
verbose
)
log
.
info
(
'verbosity level set to '
+
commander
.
verbose
.
blue
)
log
.
info
(
'verbosity level set to '
+
commander
.
verbose
.
blue
)
}
}
const
compilerConfig
=
{}
as
CompilerConfiguration
let
compilerConfig
=
{}
as
CompilerConfiguration
if
(
commander
.
compiler
)
{
if
(
commander
.
compiler
)
{
const
compVersion
=
commander
.
compiler
const
compVersion
=
commander
.
compiler
const
baseURL
=
'https://binaries.soliditylang.org/wasm/'
const
baseURL
=
'https://binaries.soliditylang.org/wasm/'
const
response
:
AxiosResponse
=
await
axios
.
get
(
baseURL
+
'list.json'
)
const
response
:
AxiosResponse
=
await
axios
.
get
(
baseURL
+
'list.json'
)
const
{
releases
,
latestRelease
}
=
response
.
data
const
{
releases
,
latestRelease
}
=
response
.
data
const
compString
=
releases
[
compVersion
]
const
compString
=
releases
[
compVersion
]
if
(
!
compString
)
{
if
(
!
compString
)
{
log
.
error
(
`No compiler found in releases with version
${
compVersion
}
`
)
log
.
error
(
`No compiler found in releases with version
${
compVersion
}
`
)
process
.
exit
()
process
.
exit
()
}
else
{
}
else
{
compilerConfig
.
currentCompilerUrl
=
compString
.
replace
(
'soljson-'
,
''
).
replace
(
'.js'
,
''
)
compilerConfig
.
currentCompilerUrl
=
compString
.
replace
(
'soljson-'
,
''
).
replace
(
'.js'
,
''
)
log
.
info
(
`Compiler version set to
${
compVersion
}
. Latest version is
${
latestRelease
}
`
)
log
.
info
(
`Compiler version set to
${
compVersion
}
. Latest version is
${
latestRelease
}
`
)
}
}
}
}
if
(
commander
.
evm
)
{
if
(
commander
.
evm
)
{
compilerConfig
.
evmVersion
=
commander
.
evm
compilerConfig
.
evmVersion
=
commander
.
evm
log
.
info
(
`EVM set to
${
compilerConfig
.
evmVersion
}
`
)
log
.
info
(
`EVM set to
${
compilerConfig
.
evmVersion
}
`
)
}
}
if
(
commander
.
optimize
)
{
if
(
commander
.
optimize
)
{
compilerConfig
.
optimize
=
commander
.
optimize
compilerConfig
.
optimize
=
commander
.
optimize
log
.
info
(
`Optimization is
${
compilerConfig
.
optimize
?
'enabled'
:
'disabled'
}
`
)
log
.
info
(
`Optimization is
${
compilerConfig
.
optimize
?
'enabled'
:
'disabled'
}
`
)
}
}
if
(
commander
.
runs
)
{
if
(
commander
.
runs
)
{
if
(
!
commander
.
optimize
)
{
if
(
!
commander
.
optimize
)
{
log
.
error
(
'Optimization should be enabled for runs'
)
log
.
error
(
`Optimization should be enabled for runs`
)
process
.
exit
()
process
.
exit
()
}
}
compilerConfig
.
runs
=
commander
.
runs
compilerConfig
.
runs
=
commander
.
runs
log
.
info
(
`Runs set to
${
compilerConfig
.
runs
}
`
)
log
.
info
(
`Runs set to
${
compilerConfig
.
runs
}
`
)
}
}
const
web3
=
new
Web3
()
const
web3
=
new
Web3
()
const
provider
:
any
=
new
Provider
()
const
provider
:
any
=
new
Provider
()
await
provider
.
init
()
await
provider
.
init
()
web3
.
setProvider
(
provider
)
web3
.
setProvider
(
provider
)
runTestFiles
(
path
.
resolve
(
testsPath
),
isDirectory
,
web3
,
compilerConfig
)
runTestFiles
(
path
.
resolve
(
testsPath
),
isDirectory
,
web3
,
compilerConfig
)
})
})
if
(
!
process
.
argv
.
slice
(
2
).
length
)
{
if
(
!
process
.
argv
.
slice
(
2
).
length
)
{
log
.
error
(
'Please specify a file or directory path'
)
log
.
error
(
'Please specify a file or directory path'
)
process
.
exit
()
process
.
exit
()
}
}
commander
.
parse
(
process
.
argv
)
commander
.
parse
(
process
.
argv
)
libs/remix-tests/src/runTestFiles.ts
View file @
28773548
...
@@ -3,7 +3,7 @@ import fs from './fileSystem'
...
@@ -3,7 +3,7 @@ import fs from './fileSystem'
import
{
runTest
}
from
'./testRunner'
import
{
runTest
}
from
'./testRunner'
import
{
TestResultInterface
,
ResultsInterface
,
CompilerConfiguration
,
compilationInterface
,
ASTInterface
,
Options
,
AstNode
}
from
'./types'
import
{
TestResultInterface
,
ResultsInterface
,
CompilerConfiguration
,
compilationInterface
,
ASTInterface
,
Options
,
AstNode
}
from
'./types'
import
colors
from
'colors'
import
colors
from
'colors'
import
Web3
from
'web3'
;
import
Web3
from
'web3'
import
{
compileFileOrFiles
}
from
'./compiler'
import
{
compileFileOrFiles
}
from
'./compiler'
import
{
deployAll
}
from
'./deployer'
import
{
deployAll
}
from
'./deployer'
...
@@ -18,144 +18,143 @@ import { deployAll } from './deployer'
...
@@ -18,144 +18,143 @@ import { deployAll } from './deployer'
*/
*/
// eslint-disable-next-line @typescript-eslint/no-empty-function
// eslint-disable-next-line @typescript-eslint/no-empty-function
export
function
runTestFiles
(
filepath
:
string
,
isDirectory
:
boolean
,
web3
:
Web3
,
compilerConfig
:
CompilerConfiguration
,
finalCallback
:
any
=
()
=>
{},
opts
?:
Options
)
{
export
function
runTestFiles
(
filepath
:
string
,
isDirectory
:
boolean
,
web3
:
Web3
,
compilerConfig
:
CompilerConfiguration
,
finalCallback
:
any
=
()
=>
{},
opts
?:
Options
)
{
opts
=
opts
||
{}
opts
=
opts
||
{}
compilerConfig
=
compilerConfig
||
{}
as
CompilerConfiguration
compilerConfig
=
compilerConfig
||
{}
as
CompilerConfiguration
const
sourceASTs
:
any
=
{}
const
sourceASTs
:
any
=
{}
const
{
Signale
}
=
require
(
'signale'
)
const
{
Signale
}
=
require
(
'signale'
)
// signale configuration
// signale configuration
const
options
=
{
const
options
=
{
types
:
{
types
:
{
result
:
{
result
:
{
badge
:
'
\
t✓'
,
badge
:
'
\
t✓'
,
label
:
''
,
label
:
''
,
color
:
'greenBright'
color
:
'greenBright'
},
},
name
:
{
name
:
{
badge
:
'
\
n
\
t◼'
,
badge
:
'
\
n
\
t◼'
,
label
:
''
,
label
:
''
,
color
:
'white'
color
:
'white'
},
},
error
:
{
error
:
{
badge
:
'
\
t✘'
,
badge
:
'
\
t✘'
,
label
:
''
,
label
:
''
,
color
:
'redBright'
color
:
'redBright'
}
}
}
}
}
const
signale
=
new
Signale
(
options
)
}
let
accounts
=
opts
[
'accounts'
]
||
null
const
signale
=
new
Signale
(
options
)
async
.
waterfall
([
let
accounts
=
opts
[
'accounts'
]
||
null
function
getAccountList
(
next
)
{
async
.
waterfall
([
if
(
accounts
)
return
next
(
null
)
function
getAccountList
(
next
)
{
web3
.
eth
.
getAccounts
((
_err
:
Error
|
null
|
undefined
,
_accounts
)
=>
{
if
(
accounts
)
return
next
(
null
)
accounts
=
_accounts
web3
.
eth
.
getAccounts
((
_err
:
Error
|
null
|
undefined
,
_accounts
)
=>
{
next
(
null
)
accounts
=
_accounts
}
)
next
(
null
)
},
})
function
compile
(
next
)
{
},
compileFileOrFiles
(
filepath
,
isDirectory
,
{
accounts
},
compilerConfig
,
next
)
function
compile
(
next
)
{
},
compileFileOrFiles
(
filepath
,
isDirectory
,
{
accounts
},
compilerConfig
,
next
)
function
deployAllContracts
(
compilationResult
:
compilationInterface
,
asts
:
ASTInterface
,
next
)
{
},
// Extract AST of test contract file source
function
deployAllContracts
(
compilationResult
:
compilationInterface
,
asts
:
ASTInterface
,
next
)
{
for
(
const
filename
in
asts
)
{
// Extract AST of test contract file source
if
(
filename
.
endsWith
(
'_test.sol'
))
for
(
const
filename
in
asts
)
{
sourceASTs
[
filename
]
=
asts
[
filename
].
ast
if
(
filename
.
endsWith
(
'_test.sol'
))
{
sourceASTs
[
filename
]
=
asts
[
filename
].
ast
}
}
}
deployAll
(
compilationResult
,
web3
,
false
,
(
err
,
contracts
)
=>
{
deployAll
(
compilationResult
,
web3
,
false
,
(
err
,
contracts
)
=>
{
if
(
err
)
{
if
(
err
)
{
next
(
err
)
next
(
err
)
}
}
next
(
null
,
compilationResult
,
contracts
)
next
(
null
,
compilationResult
,
contracts
)
})
})
},
},
function
determineTestContractsToRun
(
compilationResult
:
compilationInterface
,
contracts
:
any
,
next
)
{
function
determineTestContractsToRun
(
compilationResult
:
compilationInterface
,
contracts
:
any
,
next
)
{
const
contractsToTest
:
string
[]
=
[]
const
contractsToTest
:
string
[]
=
[]
const
contractsToTestDetails
:
any
[]
=
[]
const
contractsToTestDetails
:
any
[]
=
[]
const
gatherContractsFrom
=
function
(
filename
:
string
)
{
const
gatherContractsFrom
=
function
(
filename
:
string
)
{
if
(
!
filename
.
endsWith
(
'_test.sol'
))
{
if
(
!
filename
.
endsWith
(
'_test.sol'
))
{
return
return
}
}
try
{
try
{
Object
.
keys
(
compilationResult
[
filename
]).
forEach
(
contractName
=>
{
Object
.
keys
(
compilationResult
[
filename
]).
forEach
(
contractName
=>
{
contractsToTest
.
push
(
contractName
)
contractsToTest
.
push
(
contractName
)
contractsToTestDetails
.
push
(
compilationResult
[
filename
][
contractName
])
contractsToTestDetails
.
push
(
compilationResult
[
filename
][
contractName
])
})
})
}
catch
(
e
)
{
}
catch
(
e
)
{
console
.
error
(
e
)
console
.
error
(
e
)
}
}
}
}
if
(
isDirectory
)
{
if
(
isDirectory
)
{
fs
.
walkSync
(
filepath
,
(
foundpath
:
string
)
=>
{
fs
.
walkSync
(
filepath
,
(
foundpath
:
string
)
=>
{
gatherContractsFrom
(
foundpath
)
gatherContractsFrom
(
foundpath
)
})
})
}
else
{
}
else
{
gatherContractsFrom
(
filepath
)
gatherContractsFrom
(
filepath
)
}
}
next
(
null
,
contractsToTest
,
contractsToTestDetails
,
contracts
)
next
(
null
,
contractsToTest
,
contractsToTestDetails
,
contracts
)
},
},
function
runTests
(
contractsToTest
:
string
[],
contractsToTestDetails
:
any
[],
contracts
:
any
,
next
)
{
function
runTests
(
contractsToTest
:
string
[],
contractsToTestDetails
:
any
[],
contracts
:
any
,
next
)
{
let
totalPassing
=
0
let
totalPassing
=
0
let
totalFailing
=
0
let
totalFailing
=
0
let
totalTime
=
0
let
totalTime
=
0
const
errors
:
any
[]
=
[]
const
errors
:
any
[]
=
[]
const
_testCallback
=
function
(
err
:
Error
|
null
|
undefined
,
result
:
TestResultInterface
)
{
const
_testCallback
=
function
(
err
:
Error
|
null
|
undefined
,
result
:
TestResultInterface
)
{
if
(
err
)
throw
err
;
if
(
err
)
throw
err
if
(
result
.
type
===
'contract'
)
{
if
(
result
.
type
===
'contract'
)
{
signale
.
name
(
result
.
value
.
white
)
signale
.
name
(
result
.
value
.
white
)
}
else
if
(
result
.
type
===
'testPass'
)
{
}
else
if
(
result
.
type
===
'testPass'
)
{
signale
.
result
(
result
.
value
)
signale
.
result
(
result
.
value
)
}
else
if
(
result
.
type
===
'testFailure'
)
{
}
else
if
(
result
.
type
===
'testFailure'
)
{
signale
.
error
(
result
.
value
.
red
)
signale
.
error
(
result
.
value
.
red
)
errors
.
push
(
result
)
errors
.
push
(
result
)
}
}
}
}
const
_resultsCallback
=
(
_err
:
Error
|
null
|
undefined
,
result
:
ResultsInterface
,
cb
)
=>
{
const
_resultsCallback
=
(
_err
:
Error
|
null
|
undefined
,
result
:
ResultsInterface
,
cb
)
=>
{
totalPassing
+=
result
.
passingNum
totalPassing
+=
result
.
passingNum
totalFailing
+=
result
.
failureNum
totalFailing
+=
result
.
failureNum
totalTime
+=
result
.
timePassed
totalTime
+=
result
.
timePassed
cb
()
cb
()
}
}
async
.
eachOfLimit
(
contractsToTest
,
1
,
(
contractName
:
string
,
index
,
cb
)
=>
{
async
.
eachOfLimit
(
contractsToTest
,
1
,
(
contractName
:
string
,
index
,
cb
)
=>
{
try
{
try
{
const
fileAST
:
AstNode
=
sourceASTs
[
contracts
[
contractName
][
'filename'
]]
const
fileAST
:
AstNode
=
sourceASTs
[
contracts
[
contractName
][
'filename'
]]
runTest
(
contractName
,
contracts
[
contractName
],
contractsToTestDetails
[
index
],
fileAST
,
{
accounts
},
_testCallback
,
(
err
,
result
)
=>
{
runTest
(
contractName
,
contracts
[
contractName
],
contractsToTestDetails
[
index
],
fileAST
,
{
accounts
},
_testCallback
,
(
err
,
result
)
=>
{
if
(
err
)
{
if
(
err
)
{
console
.
log
(
err
)
console
.
log
(
err
)
return
cb
(
err
)
return
cb
(
err
)
}
}
_resultsCallback
(
null
,
result
,
cb
)
_resultsCallback
(
null
,
result
,
cb
)
})
})
}
catch
(
e
)
{
}
catch
(
e
)
{
console
.
error
(
e
)
console
.
error
(
e
)
}
}
},
function
(
err
)
{
},
function
(
err
)
{
if
(
err
)
{
if
(
err
)
{
return
next
(
err
)
return
next
(
err
)
}
}
console
.
log
(
'
\
n'
)
console
.
log
(
'
\
n'
)
if
(
totalPassing
>
0
)
{
if
(
totalPassing
>
0
)
{
console
.
log
(
colors
.
green
(
totalPassing
+
' passing '
)
+
colors
.
grey
(
'('
+
totalTime
+
's)'
))
console
.
log
(
colors
.
green
(
totalPassing
+
' passing '
)
+
colors
.
grey
(
'('
+
totalTime
+
's)'
))
}
}
if
(
totalFailing
>
0
)
{
if
(
totalFailing
>
0
)
{
console
.
log
(
colors
.
red
(
totalFailing
+
' failing'
))
console
.
log
(
colors
.
red
(
totalFailing
+
' failing'
))
}
}
console
.
log
(
''
)
console
.
log
(
''
)
errors
.
forEach
((
error
,
index
)
=>
{
errors
.
forEach
((
error
,
index
)
=>
{
console
.
log
(
' '
+
(
index
+
1
)
+
') '
+
colors
.
bold
(
error
.
context
+
': '
)
+
error
.
value
)
console
.
log
(
' '
+
(
index
+
1
)
+
') '
+
colors
.
bold
(
error
.
context
+
': '
)
+
error
.
value
)
console
.
log
(
''
)
console
.
log
(
''
)
console
.
log
(
colors
.
red
(
'
\
t error: '
+
error
.
errMsg
))
console
.
log
(
colors
.
red
(
'
\
t error: '
+
error
.
errMsg
))
console
.
log
(
colors
.
green
(
'
\
t expected value to be '
+
error
.
assertMethod
+
' to: '
+
error
.
expected
))
console
.
log
(
colors
.
green
(
'
\
t expected value to be '
+
error
.
assertMethod
+
' to: '
+
error
.
expected
))
console
.
log
(
colors
.
red
(
'
\
t returned: '
+
error
.
returned
))
console
.
log
(
colors
.
red
(
'
\
t returned: '
+
error
.
returned
))
})
})
console
.
log
(
''
)
console
.
log
(
''
)
next
()
next
()
})
})
}
}
],
finalCallback
)
],
finalCallback
)
}
}
libs/remix-tests/src/runTestSources.ts
View file @
28773548
import
async
,
{
ErrorCallback
}
from
'async'
import
async
,
{
ErrorCallback
}
from
'async'
require
(
'colors'
)
import
{
compileContractSources
}
from
'./compiler'
import
{
compileContractSources
}
from
'./compiler'
import
{
deployAll
}
from
'./deployer'
import
{
deployAll
}
from
'./deployer'
import
{
runTest
}
from
'./testRunner'
import
{
runTest
}
from
'./testRunner'
import
Web3
from
'web3'
;
import
Web3
from
'web3'
import
{
Provider
}
from
'@remix-project/remix-simulator'
import
{
Provider
}
from
'@remix-project/remix-simulator'
import
{
FinalResult
,
SrcIfc
,
compilationInterface
,
ASTInterface
,
Options
,
import
{
TestResultInterface
,
AstNode
,
CompilerConfiguration
}
from
'./types'
FinalResult
,
SrcIfc
,
compilationInterface
,
ASTInterface
,
Options
,
TestResultInterface
,
AstNode
,
CompilerConfiguration
}
from
'./types'
require
(
'colors'
)
const
createWeb3Provider
=
async
function
()
{
const
createWeb3Provider
=
async
function
()
{
const
web3
=
new
Web3
()
const
web3
=
new
Web3
()
const
provider
:
any
=
new
Provider
()
const
provider
:
any
=
new
Provider
()
await
provider
.
init
()
await
provider
.
init
()
web3
.
setProvider
(
provider
)
web3
.
setProvider
(
provider
)
return
web3
return
web3
}
}
/**
/**
...
@@ -28,110 +30,107 @@ const createWeb3Provider = async function () {
...
@@ -28,110 +30,107 @@ const createWeb3Provider = async function () {
* @param importFileCb Import file callback
* @param importFileCb Import file callback
* @param opts Options
* @param opts Options
*/
*/
export
async
function
runTestSources
(
contractSources
:
SrcIfc
,
compilerConfig
:
CompilerConfiguration
,
testCallback
,
resultCallback
,
finalCallback
:
any
,
importFileCb
,
opts
:
Options
)
{
export
async
function
runTestSources
(
contractSources
:
SrcIfc
,
compilerConfig
:
CompilerConfiguration
,
testCallback
,
resultCallback
,
finalCallback
:
any
,
importFileCb
,
opts
:
Options
)
{
opts
=
opts
||
{}
opts
=
opts
||
{}
const
sourceASTs
:
any
=
{}
const
sourceASTs
:
any
=
{}
const
web3
=
opts
.
web3
||
await
createWeb3Provider
()
const
web3
=
opts
.
web3
||
await
createWeb3Provider
()
let
accounts
:
string
[]
|
null
=
opts
.
accounts
||
null
let
accounts
:
string
[]
|
null
=
opts
.
accounts
||
null
async
.
waterfall
([
async
.
waterfall
([
function
getAccountList
(
next
)
{
function
getAccountList
(
next
)
{
if
(
accounts
)
return
next
()
if
(
accounts
)
return
next
()
web3
.
eth
.
getAccounts
((
_err
,
_accounts
)
=>
{
web3
.
eth
.
getAccounts
((
_err
,
_accounts
)
=>
{
accounts
=
_accounts
accounts
=
_accounts
next
()
next
()
})
})
},
},
function
compile
(
next
)
{
function
compile
(
next
)
{
compileContractSources
(
contractSources
,
compilerConfig
,
importFileCb
,
{
accounts
},
next
)
compileContractSources
(
contractSources
,
compilerConfig
,
importFileCb
,
{
accounts
},
next
)
},
},
function
deployAllContracts
(
compilationResult
:
compilationInterface
,
asts
:
ASTInterface
,
next
)
{
function
deployAllContracts
(
compilationResult
:
compilationInterface
,
asts
:
ASTInterface
,
next
)
{
for
(
const
filename
in
asts
)
{
for
(
const
filename
in
asts
)
{
if
(
filename
.
endsWith
(
'_test.sol'
))
if
(
filename
.
endsWith
(
'_test.sol'
))
{
sourceASTs
[
filename
]
=
asts
[
filename
].
ast
}
sourceASTs
[
filename
]
=
asts
[
filename
].
ast
}
}
deployAll
(
compilationResult
,
web3
,
false
,
(
err
,
contracts
)
=>
{
deployAll
(
compilationResult
,
web3
,
false
,
(
err
,
contracts
)
=>
{
if
(
err
)
{
if
(
err
)
{
// If contract deployment fails because of 'Out of Gas' error, try again with double gas
// If contract deployment fails because of 'Out of Gas' error, try again with double gas
// This is temporary, should be removed when remix-tests will have a dedicated UI to
// This is temporary, should be removed when remix-tests will have a dedicated UI to
// accept deployment params from UI
// accept deployment params from UI
if
(
err
.
message
.
includes
(
'The contract code couldn
\'
t be stored, please check your gas limit'
))
{
if
(
err
.
message
.
includes
(
'The contract code couldn
\'
t be stored, please check your gas limit'
))
{
deployAll
(
compilationResult
,
web3
,
true
,
(
error
,
contracts
)
=>
{
deployAll
(
compilationResult
,
web3
,
true
,
(
error
,
contracts
)
=>
{
if
(
error
)
next
([{
message
:
'contract deployment failed after trying twice: '
+
error
.
message
,
severity
:
'error'
}])
// IDE expects errors in array
if
(
error
)
next
([{
message
:
'contract deployment failed after trying twice: '
+
error
.
message
,
severity
:
'error'
}])
// IDE expects errors in array
else
next
(
null
,
compilationResult
,
contracts
)
else
next
(
null
,
compilationResult
,
contracts
)
})
}
else
next
([{
message
:
'contract deployment failed: '
+
err
.
message
,
severity
:
'error'
}])
// IDE expects errors in array
}
else
next
(
null
,
compilationResult
,
contracts
)
})
})
},
}
else
{
next
([{
message
:
'contract deployment failed: '
+
err
.
message
,
severity
:
'error'
}])
}
// IDE expects errors in array
function
determineTestContractsToRun
(
compilationResult
:
compilationInterface
,
contracts
:
any
,
next
)
{
}
else
{
next
(
null
,
compilationResult
,
contracts
)
}
const
contractsToTest
:
string
[]
=
[]
})
const
contractsToTestDetails
:
any
[]
=
[]
},
function
determineTestContractsToRun
(
compilationResult
:
compilationInterface
,
contracts
:
any
,
next
)
{
const
contractsToTest
:
string
[]
=
[]
const
contractsToTestDetails
:
any
[]
=
[]
for
(
const
filename
in
compilationResult
)
{
for
(
const
filename
in
compilationResult
)
{
if
(
!
filename
.
endsWith
(
'_test.sol'
))
{
if
(
!
filename
.
endsWith
(
'_test.sol'
))
{
continue
continue
}
}
Object
.
keys
(
compilationResult
[
filename
]).
forEach
(
contractName
=>
{
Object
.
keys
(
compilationResult
[
filename
]).
forEach
(
contractName
=>
{
contractsToTestDetails
.
push
(
compilationResult
[
filename
][
contractName
])
contractsToTestDetails
.
push
(
compilationResult
[
filename
][
contractName
])
contractsToTest
.
push
(
contractName
)
contractsToTest
.
push
(
contractName
)
})
})
}
}
next
(
null
,
contractsToTest
,
contractsToTestDetails
,
contracts
)
next
(
null
,
contractsToTest
,
contractsToTestDetails
,
contracts
)
},
},
function
runTests
(
contractsToTest
:
string
[],
contractsToTestDetails
:
any
[],
contracts
:
any
,
next
)
{
function
runTests
(
contractsToTest
:
string
[],
contractsToTestDetails
:
any
[],
contracts
:
any
,
next
)
{
let
totalPassing
=
0
let
totalPassing
=
0
let
totalFailing
=
0
let
totalFailing
=
0
let
totalTime
=
0
let
totalTime
=
0
const
errors
:
any
[]
=
[]
const
errors
:
any
[]
=
[]
// eslint-disable-next-line handle-callback-err
const
_testCallback
=
function
(
err
:
Error
|
null
|
undefined
,
result
:
TestResultInterface
)
{
const
_testCallback
=
function
(
err
:
Error
|
null
|
undefined
,
result
:
TestResultInterface
)
{
if
(
result
.
type
===
'testFailure'
)
{
if
(
result
.
type
===
'testFailure'
)
{
errors
.
push
(
result
)
errors
.
push
(
result
)
}
}
testCallback
(
result
)
testCallback
(
result
)
}
}
const
_resultsCallback
=
function
(
_err
,
result
,
cb
)
{
const
_resultsCallback
=
function
(
_err
,
result
,
cb
)
{
resultCallback
(
_err
,
result
,
()
=>
{})
//
eslint-disable-line @typescript-eslint/no-empty-function
resultCallback
(
_err
,
result
,
()
=>
{})
//
eslint-disable-line @typescript-eslint/no-empty-function
totalPassing
+=
result
.
passingNum
totalPassing
+=
result
.
passingNum
totalFailing
+=
result
.
failureNum
totalFailing
+=
result
.
failureNum
totalTime
+=
result
.
timePassed
totalTime
+=
result
.
timePassed
cb
()
cb
()
}
}
async
.
eachOfLimit
(
contractsToTest
,
1
,
(
contractName
:
string
,
index
:
string
|
number
,
cb
:
ErrorCallback
)
=>
{
async
.
eachOfLimit
(
contractsToTest
,
1
,
(
contractName
:
string
,
index
:
string
|
number
,
cb
:
ErrorCallback
)
=>
{
const
fileAST
:
AstNode
=
sourceASTs
[
contracts
[
contractName
][
'filename'
]]
const
fileAST
:
AstNode
=
sourceASTs
[
contracts
[
contractName
][
'filename'
]]
runTest
(
contractName
,
contracts
[
contractName
],
contractsToTestDetails
[
index
],
fileAST
,
{
accounts
},
_testCallback
,
(
err
,
result
)
=>
{
runTest
(
contractName
,
contracts
[
contractName
],
contractsToTestDetails
[
index
],
fileAST
,
{
accounts
},
_testCallback
,
(
err
,
result
)
=>
{
if
(
err
)
{
if
(
err
)
{
return
cb
(
err
)
return
cb
(
err
)
}
}
_resultsCallback
(
null
,
result
,
cb
)
_resultsCallback
(
null
,
result
,
cb
)
})
})
},
function
(
err
)
{
},
function
(
err
)
{
if
(
err
)
{
if
(
err
)
{
return
next
(
err
)
return
next
(
err
)
}
}
const
finalResults
:
FinalResult
=
{
const
finalResults
:
FinalResult
=
{
totalPassing
:
0
,
totalPassing
:
0
,
totalFailing
:
0
,
totalFailing
:
0
,
totalTime
:
0
,
totalTime
:
0
,
errors
:
[],
errors
:
[]
}
}
finalResults
.
totalPassing
=
totalPassing
||
0
finalResults
.
totalPassing
=
totalPassing
||
0
finalResults
.
totalFailing
=
totalFailing
||
0
finalResults
.
totalFailing
=
totalFailing
||
0
finalResults
.
totalTime
=
totalTime
||
0
finalResults
.
totalTime
=
totalTime
||
0
finalResults
.
errors
=
[]
finalResults
.
errors
=
[]
errors
.
forEach
((
error
,
_index
)
=>
{
errors
.
forEach
((
error
,
_index
)
=>
{
finalResults
.
errors
.
push
({
context
:
error
.
context
,
value
:
error
.
value
,
message
:
error
.
errMsg
})
finalResults
.
errors
.
push
({
context
:
error
.
context
,
value
:
error
.
value
,
message
:
error
.
errMsg
})
})
})
next
(
null
,
finalResults
)
next
(
null
,
finalResults
)
})
})
}
}
],
finalCallback
)
],
finalCallback
)
}
}
libs/remix-tests/src/testRunner.ts
View file @
28773548
import
async
from
'async'
import
async
from
'async'
import
*
as
changeCase
from
'change-case'
import
*
as
changeCase
from
'change-case'
import
Web3
from
'web3'
;
import
Web3
from
'web3'
import
assertionEvents
from
'./assertionEvents'
import
assertionEvents
from
'./assertionEvents'
import
{
RunListInterface
,
TestCbInterface
,
TestResultInterface
,
ResultCbInterface
,
import
{
CompiledContract
,
AstNode
,
Options
,
FunctionDescription
,
UserDocumentation
}
from
'./types'
RunListInterface
,
TestCbInterface
,
TestResultInterface
,
ResultCbInterface
,
CompiledContract
,
AstNode
,
Options
,
FunctionDescription
,
UserDocumentation
}
from
'./types'
/**
/**
* @dev Get function name using method signature
* @dev Get function name using method signature
...
@@ -12,12 +14,12 @@ import { RunListInterface, TestCbInterface, TestResultInterface, ResultCbInterfa
...
@@ -12,12 +14,12 @@ import { RunListInterface, TestCbInterface, TestResultInterface, ResultCbInterfa
*/
*/
function
getFunctionFullName
(
signature
:
string
,
methodIdentifiers
:
Record
<
string
,
string
>
):
string
|
null
{
function
getFunctionFullName
(
signature
:
string
,
methodIdentifiers
:
Record
<
string
,
string
>
):
string
|
null
{
for
(
const
method
in
methodIdentifiers
)
{
for
(
const
method
in
methodIdentifiers
)
{
if
(
signature
.
replace
(
'0x'
,
''
)
===
methodIdentifiers
[
method
].
replace
(
'0x'
,
''
))
{
if
(
signature
.
replace
(
'0x'
,
''
)
===
methodIdentifiers
[
method
].
replace
(
'0x'
,
''
))
{
return
method
return
method
}
}
}
return
null
}
return
null
}
}
/**
/**
...
@@ -25,8 +27,8 @@ function getFunctionFullName (signature: string, methodIdentifiers: Record <stri
...
@@ -25,8 +27,8 @@ function getFunctionFullName (signature: string, methodIdentifiers: Record <stri
* @param funcABI function ABI
* @param funcABI function ABI
*/
*/
function
isConstant
(
funcABI
:
FunctionDescription
):
boolean
{
function
isConstant
(
funcABI
:
FunctionDescription
):
boolean
{
return
(
funcABI
.
constant
||
funcABI
.
stateMutability
===
'view'
||
funcABI
.
stateMutability
===
'pure'
)
return
(
funcABI
.
constant
||
funcABI
.
stateMutability
===
'view'
||
funcABI
.
stateMutability
===
'pure'
)
}
}
/**
/**
...
@@ -34,8 +36,8 @@ function isConstant(funcABI: FunctionDescription): boolean {
...
@@ -34,8 +36,8 @@ function isConstant(funcABI: FunctionDescription): boolean {
* @param funcABI function ABI
* @param funcABI function ABI
*/
*/
function
isPayable
(
funcABI
:
FunctionDescription
):
boolean
{
function
isPayable
(
funcABI
:
FunctionDescription
):
boolean
{
return
(
funcABI
.
payable
||
funcABI
.
stateMutability
===
'payable'
)
return
(
funcABI
.
payable
||
funcABI
.
stateMutability
===
'payable'
)
}
}
/**
/**
...
@@ -44,8 +46,8 @@ function isPayable(funcABI: FunctionDescription): boolean {
...
@@ -44,8 +46,8 @@ function isPayable(funcABI: FunctionDescription): boolean {
* @param name name
* @param name name
*/
*/
function
isNodeName
(
node
:
AstNode
,
name
:
string
):
boolean
{
function
isNodeName
(
node
:
AstNode
,
name
:
string
):
boolean
{
return
node
.
name
===
name
return
node
.
name
===
name
}
}
/**
/**
...
@@ -54,8 +56,8 @@ function isNodeName(node: AstNode, name: string): boolean {
...
@@ -54,8 +56,8 @@ function isNodeName(node: AstNode, name: string): boolean {
* @param type type
* @param type type
*/
*/
function
isNodeType
(
node
:
AstNode
,
type
:
string
):
boolean
{
function
isNodeType
(
node
:
AstNode
,
type
:
string
):
boolean
{
return
node
.
nodeType
===
type
return
node
.
nodeType
===
type
}
}
/**
/**
...
@@ -64,8 +66,8 @@ function isNodeType(node: AstNode, type: string): boolean {
...
@@ -64,8 +66,8 @@ function isNodeType(node: AstNode, type: string): boolean {
* @param typesList list of types
* @param typesList list of types
*/
*/
function
isNodeTypeIn
(
node
:
AstNode
,
typesList
:
string
[]):
boolean
{
function
isNodeTypeIn
(
node
:
AstNode
,
typesList
:
string
[]):
boolean
{
return
typesList
.
includes
(
node
.
nodeType
)
return
typesList
.
includes
(
node
.
nodeType
)
}
}
/**
/**
...
@@ -76,10 +78,10 @@ function isNodeTypeIn(node: AstNode, typesList: string[]): boolean {
...
@@ -76,10 +78,10 @@ function isNodeTypeIn(node: AstNode, typesList: string[]): boolean {
*/
*/
function
getOverridedSender
(
userdoc
:
UserDocumentation
,
signature
:
string
,
methodIdentifiers
:
Record
<
string
,
string
>
):
string
|
null
{
function
getOverridedSender
(
userdoc
:
UserDocumentation
,
signature
:
string
,
methodIdentifiers
:
Record
<
string
,
string
>
):
string
|
null
{
const
fullName
:
string
|
null
=
getFunctionFullName
(
signature
,
methodIdentifiers
)
const
fullName
:
string
|
null
=
getFunctionFullName
(
signature
,
methodIdentifiers
)
const
senderRegex
=
/#sender: account-+
(\d)
/g
const
senderRegex
=
/#sender: account-+
(\d)
/g
const
accountIndex
:
RegExpExecArray
|
null
=
fullName
&&
userdoc
.
methods
[
fullName
]
?
senderRegex
.
exec
(
userdoc
.
methods
[
fullName
].
notice
)
:
null
const
accountIndex
:
RegExpExecArray
|
null
=
fullName
&&
userdoc
.
methods
[
fullName
]
?
senderRegex
.
exec
(
userdoc
.
methods
[
fullName
].
notice
)
:
null
return
fullName
&&
accountIndex
?
accountIndex
[
1
]
:
null
return
fullName
&&
accountIndex
?
accountIndex
[
1
]
:
null
}
}
/**
/**
...
@@ -90,10 +92,10 @@ function getOverridedSender (userdoc: UserDocumentation, signature: string, meth
...
@@ -90,10 +92,10 @@ function getOverridedSender (userdoc: UserDocumentation, signature: string, meth
*/
*/
function
getProvidedValue
(
userdoc
:
UserDocumentation
,
signature
:
string
,
methodIdentifiers
:
Record
<
string
,
string
>
):
string
|
null
{
function
getProvidedValue
(
userdoc
:
UserDocumentation
,
signature
:
string
,
methodIdentifiers
:
Record
<
string
,
string
>
):
string
|
null
{
const
fullName
:
string
|
null
=
getFunctionFullName
(
signature
,
methodIdentifiers
)
const
fullName
:
string
|
null
=
getFunctionFullName
(
signature
,
methodIdentifiers
)
const
valueRegex
=
/#value:
(\d
+
)
/g
const
valueRegex
=
/#value:
(\d
+
)
/g
const
value
:
RegExpExecArray
|
null
=
fullName
&&
userdoc
.
methods
[
fullName
]
?
valueRegex
.
exec
(
userdoc
.
methods
[
fullName
].
notice
)
:
null
const
value
:
RegExpExecArray
|
null
=
fullName
&&
userdoc
.
methods
[
fullName
]
?
valueRegex
.
exec
(
userdoc
.
methods
[
fullName
].
notice
)
:
null
return
fullName
&&
value
?
value
[
1
]
:
null
return
fullName
&&
value
?
value
[
1
]
:
null
}
}
/**
/**
...
@@ -103,36 +105,36 @@ function getProvidedValue (userdoc: UserDocumentation, signature: string, method
...
@@ -103,36 +105,36 @@ function getProvidedValue (userdoc: UserDocumentation, signature: string, method
*/
*/
function
getAvailableFunctions
(
fileAST
:
AstNode
,
testContractName
:
string
):
string
[]
{
function
getAvailableFunctions
(
fileAST
:
AstNode
,
testContractName
:
string
):
string
[]
{
let
funcList
:
string
[]
=
[]
let
funcList
:
string
[]
=
[]
if
(
fileAST
.
nodes
&&
fileAST
.
nodes
.
length
>
0
)
{
if
(
fileAST
.
nodes
&&
fileAST
.
nodes
.
length
>
0
)
{
const
contractAST
:
AstNode
[]
=
fileAST
.
nodes
.
filter
(
node
=>
isNodeName
(
node
,
testContractName
)
&&
isNodeType
(
node
,
'ContractDefinition'
))
const
contractAST
:
AstNode
[]
=
fileAST
.
nodes
.
filter
(
node
=>
isNodeName
(
node
,
testContractName
)
&&
isNodeType
(
node
,
'ContractDefinition'
))
if
(
contractAST
.
length
>
0
&&
contractAST
[
0
].
nodes
)
{
if
(
contractAST
.
length
>
0
&&
contractAST
[
0
].
nodes
)
{
const
funcNodes
:
AstNode
[]
=
contractAST
[
0
].
nodes
.
filter
(
node
=>
((
node
.
kind
===
"function"
&&
isNodeType
(
node
,
'FunctionDefinition'
))
||
isNodeType
(
node
,
'FunctionDefinition'
)))
const
funcNodes
:
AstNode
[]
=
contractAST
[
0
].
nodes
.
filter
(
node
=>
((
node
.
kind
===
'function'
&&
isNodeType
(
node
,
'FunctionDefinition'
))
||
isNodeType
(
node
,
'FunctionDefinition'
)))
funcList
=
funcNodes
.
map
(
node
=>
node
.
name
)
funcList
=
funcNodes
.
map
(
node
=>
node
.
name
)
}
}
}
return
funcList
;
}
return
funcList
}
}
function
getAssertMethodLocation
(
fileAST
:
AstNode
,
testContractName
:
string
,
functionName
:
string
,
assertMethod
:
string
):
string
{
function
getAssertMethodLocation
(
fileAST
:
AstNode
,
testContractName
:
string
,
functionName
:
string
,
assertMethod
:
string
):
string
{
if
(
fileAST
.
nodes
?.
length
)
{
if
(
fileAST
.
nodes
?.
length
)
{
const
contractAST
:
AstNode
=
fileAST
.
nodes
.
find
(
node
=>
isNodeName
(
node
,
testContractName
)
&&
isNodeType
(
node
,
'ContractDefinition'
))
const
contractAST
:
AstNode
=
fileAST
.
nodes
.
find
(
node
=>
isNodeName
(
node
,
testContractName
)
&&
isNodeType
(
node
,
'ContractDefinition'
))
if
(
contractAST
?.
nodes
?.
length
)
{
if
(
contractAST
?.
nodes
?.
length
)
{
const
funcNode
:
AstNode
=
contractAST
.
nodes
.
find
(
node
=>
isNodeName
(
node
,
functionName
)
&&
isNodeType
(
node
,
'FunctionDefinition'
))
const
funcNode
:
AstNode
=
contractAST
.
nodes
.
find
(
node
=>
isNodeName
(
node
,
functionName
)
&&
isNodeType
(
node
,
'FunctionDefinition'
))
// Check if statement nodeType is 'ExpressionStatement' or 'Return', for examples:
// Check if statement nodeType is 'ExpressionStatement' or 'Return', for examples:
// Assert.equal(foo.get(), 100, "initial value is not correct");
// Assert.equal(foo.get(), 100, "initial value is not correct");
// return Assert.equal(foo.get(), 100, "initial value is not correct");
// return Assert.equal(foo.get(), 100, "initial value is not correct");
const
expressions
=
funcNode
.
body
.
statements
.
filter
(
s
=>
const
expressions
=
funcNode
.
body
.
statements
.
filter
(
s
=>
isNodeTypeIn
(
s
,
[
'ExpressionStatement'
,
'Return'
])
isNodeTypeIn
(
s
,
[
'ExpressionStatement'
,
'Return'
])
&&
&&
isNodeType
(
s
.
expression
,
'FunctionCall'
))
isNodeType
(
s
.
expression
,
'FunctionCall'
))
const
assetExpression
=
expressions
.
find
(
e
=>
e
.
expression
.
expression
const
assetExpression
=
expressions
.
find
(
e
=>
e
.
expression
.
expression
&&
&&
isNodeType
(
e
.
expression
.
expression
,
'MemberAccess'
)
isNodeType
(
e
.
expression
.
expression
,
'MemberAccess'
)
&&
&&
e
.
expression
.
expression
.
memberName
===
assertMethod
e
.
expression
.
expression
.
memberName
===
assertMethod
&&
&&
isNodeName
(
e
.
expression
.
expression
.
expression
,
'Assert'
)
isNodeName
(
e
.
expression
.
expression
.
expression
,
'Assert'
)
)
)
return
assetExpression
?.
expression
?.
src
return
assetExpression
?.
expression
?.
src
}
}
}
}
}
}
/**
/**
...
@@ -142,15 +144,15 @@ function getAssertMethodLocation (fileAST: AstNode, testContractName: string, fu
...
@@ -142,15 +144,15 @@ function getAssertMethodLocation (fileAST: AstNode, testContractName: string, fu
*/
*/
function
getTestFunctionsInterface
(
jsonInterface
:
FunctionDescription
[],
funcList
:
string
[]):
FunctionDescription
[]
{
function
getTestFunctionsInterface
(
jsonInterface
:
FunctionDescription
[],
funcList
:
string
[]):
FunctionDescription
[]
{
const
functionsInterface
:
FunctionDescription
[]
=
[]
const
functionsInterface
:
FunctionDescription
[]
=
[]
const
specialFunctions
:
string
[]
=
[
'beforeAll'
,
'beforeEach'
,
'afterAll'
,
'afterEach'
]
const
specialFunctions
:
string
[]
=
[
'beforeAll'
,
'beforeEach'
,
'afterAll'
,
'afterEach'
]
for
(
const
func
of
funcList
){
for
(
const
func
of
funcList
)
{
if
(
!
specialFunctions
.
includes
(
func
))
{
if
(
!
specialFunctions
.
includes
(
func
))
{
const
funcInterface
:
FunctionDescription
|
undefined
=
jsonInterface
.
find
(
node
=>
node
.
type
===
'function'
&&
node
.
name
===
func
)
const
funcInterface
:
FunctionDescription
|
undefined
=
jsonInterface
.
find
(
node
=>
node
.
type
===
'function'
&&
node
.
name
===
func
)
if
(
funcInterface
)
functionsInterface
.
push
(
funcInterface
)
if
(
funcInterface
)
functionsInterface
.
push
(
funcInterface
)
}
}
}
return
functionsInterface
}
return
functionsInterface
}
}
/**
/**
...
@@ -159,15 +161,15 @@ function getTestFunctionsInterface (jsonInterface: FunctionDescription[], funcLi
...
@@ -159,15 +161,15 @@ function getTestFunctionsInterface (jsonInterface: FunctionDescription[], funcLi
*/
*/
function
getSpecialFunctionsInterface
(
jsonInterface
:
FunctionDescription
[]):
Record
<
string
,
FunctionDescription
>
{
function
getSpecialFunctionsInterface
(
jsonInterface
:
FunctionDescription
[]):
Record
<
string
,
FunctionDescription
>
{
const
specialFunctionsInterface
:
Record
<
string
,
FunctionDescription
>
=
{}
const
specialFunctionsInterface
:
Record
<
string
,
FunctionDescription
>
=
{}
const
funcList
:
string
[]
=
[
'beforeAll'
,
'beforeEach'
,
'afterAll'
,
'afterEach'
]
const
funcList
:
string
[]
=
[
'beforeAll'
,
'beforeEach'
,
'afterAll'
,
'afterEach'
]
for
(
const
func
of
funcList
){
for
(
const
func
of
funcList
)
{
const
funcInterface
:
FunctionDescription
|
undefined
=
jsonInterface
.
find
(
node
=>
node
.
type
===
'function'
&&
node
.
name
===
func
)
const
funcInterface
:
FunctionDescription
|
undefined
=
jsonInterface
.
find
(
node
=>
node
.
type
===
'function'
&&
node
.
name
===
func
)
if
(
funcInterface
)
{
if
(
funcInterface
)
{
specialFunctionsInterface
[
func
]
=
funcInterface
specialFunctionsInterface
[
func
]
=
funcInterface
}
}
}
return
specialFunctionsInterface
}
return
specialFunctionsInterface
}
}
/**
/**
...
@@ -178,184 +180,182 @@ function getSpecialFunctionsInterface (jsonInterface: FunctionDescription[]): Re
...
@@ -178,184 +180,182 @@ function getSpecialFunctionsInterface (jsonInterface: FunctionDescription[]): Re
*/
*/
function
createRunList
(
jsonInterface
:
FunctionDescription
[],
fileAST
:
AstNode
,
testContractName
:
string
):
RunListInterface
[]
{
function
createRunList
(
jsonInterface
:
FunctionDescription
[],
fileAST
:
AstNode
,
testContractName
:
string
):
RunListInterface
[]
{
const
availableFunctions
:
string
[]
=
getAvailableFunctions
(
fileAST
,
testContractName
)
const
availableFunctions
:
string
[]
=
getAvailableFunctions
(
fileAST
,
testContractName
)
const
testFunctionsInterface
:
FunctionDescription
[]
=
getTestFunctionsInterface
(
jsonInterface
,
availableFunctions
)
const
testFunctionsInterface
:
FunctionDescription
[]
=
getTestFunctionsInterface
(
jsonInterface
,
availableFunctions
)
const
specialFunctionsInterface
:
Record
<
string
,
FunctionDescription
>
=
getSpecialFunctionsInterface
(
jsonInterface
)
const
specialFunctionsInterface
:
Record
<
string
,
FunctionDescription
>
=
getSpecialFunctionsInterface
(
jsonInterface
)
const
runList
:
RunListInterface
[]
=
[]
const
runList
:
RunListInterface
[]
=
[]
if
(
availableFunctions
.
includes
(
'beforeAll'
))
{
if
(
availableFunctions
.
includes
(
'beforeAll'
))
{
const
func
=
specialFunctionsInterface
[
'beforeAll'
]
const
func
=
specialFunctionsInterface
[
'beforeAll'
]
runList
.
push
({
name
:
'beforeAll'
,
inputs
:
func
.
inputs
,
signature
:
func
.
signature
,
type
:
'internal'
,
constant
:
isConstant
(
func
),
payable
:
isPayable
(
func
)
})
runList
.
push
({
name
:
'beforeAll'
,
inputs
:
func
.
inputs
,
signature
:
func
.
signature
,
type
:
'internal'
,
constant
:
isConstant
(
func
),
payable
:
isPayable
(
func
)
})
}
for
(
const
func
of
testFunctionsInterface
)
{
if
(
availableFunctions
.
includes
(
'beforeEach'
))
{
const
func
=
specialFunctionsInterface
[
'beforeEach'
]
runList
.
push
({
name
:
'beforeEach'
,
inputs
:
func
.
inputs
,
signature
:
func
.
signature
,
type
:
'internal'
,
constant
:
isConstant
(
func
),
payable
:
isPayable
(
func
)
})
}
}
if
(
func
.
name
&&
func
.
inputs
)
runList
.
push
({
name
:
func
.
name
,
inputs
:
func
.
inputs
,
signature
:
func
.
signature
,
type
:
'test'
,
constant
:
isConstant
(
func
),
payable
:
isPayable
(
func
)
})
for
(
const
func
of
testFunctionsInterface
)
{
if
(
availableFunctions
.
indexOf
(
'afterEach'
)
>=
0
)
{
if
(
availableFunctions
.
includes
(
'beforeEach'
))
{
const
func
=
specialFunctionsInterface
[
'afterEach'
]
const
func
=
specialFunctionsInterface
[
'beforeEach'
]
runList
.
push
({
name
:
'afterEach'
,
inputs
:
func
.
inputs
,
signature
:
func
.
signature
,
type
:
'internal'
,
constant
:
isConstant
(
func
),
payable
:
isPayable
(
func
)
})
runList
.
push
({
name
:
'beforeEach'
,
inputs
:
func
.
inputs
,
signature
:
func
.
signature
,
type
:
'internal'
,
constant
:
isConstant
(
func
),
payable
:
isPayable
(
func
)
})
}
if
(
func
.
name
&&
func
.
inputs
)
runList
.
push
({
name
:
func
.
name
,
inputs
:
func
.
inputs
,
signature
:
func
.
signature
,
type
:
'test'
,
constant
:
isConstant
(
func
),
payable
:
isPayable
(
func
)
})
if
(
availableFunctions
.
indexOf
(
'afterEach'
)
>=
0
)
{
const
func
=
specialFunctionsInterface
[
'afterEach'
]
runList
.
push
({
name
:
'afterEach'
,
inputs
:
func
.
inputs
,
signature
:
func
.
signature
,
type
:
'internal'
,
constant
:
isConstant
(
func
),
payable
:
isPayable
(
func
)
})
}
}
}
}
if
(
availableFunctions
.
indexOf
(
'afterAll'
)
>=
0
)
{
if
(
availableFunctions
.
indexOf
(
'afterAll'
)
>=
0
)
{
const
func
=
specialFunctionsInterface
[
'afterAll'
]
const
func
=
specialFunctionsInterface
[
'afterAll'
]
runList
.
push
({
name
:
'afterAll'
,
inputs
:
func
.
inputs
,
signature
:
func
.
signature
,
type
:
'internal'
,
constant
:
isConstant
(
func
),
payable
:
isPayable
(
func
)
})
runList
.
push
({
name
:
'afterAll'
,
inputs
:
func
.
inputs
,
signature
:
func
.
signature
,
type
:
'internal'
,
constant
:
isConstant
(
func
),
payable
:
isPayable
(
func
)
})
}
}
return
runList
return
runList
}
}
export
function
runTest
(
testName
:
string
,
testObject
:
any
,
contractDetails
:
CompiledContract
,
fileAST
:
AstNode
,
opts
:
Options
,
testCallback
:
TestCbInterface
,
resultsCallback
:
ResultCbInterface
):
void
{
export
function
runTest
(
testName
:
string
,
testObject
:
any
,
contractDetails
:
CompiledContract
,
fileAST
:
AstNode
,
opts
:
Options
,
testCallback
:
TestCbInterface
,
resultsCallback
:
ResultCbInterface
):
void
{
let
passingNum
=
0
let
passingNum
=
0
let
failureNum
=
0
let
failureNum
=
0
let
timePassed
=
0
let
timePassed
=
0
const
isJSONInterfaceAvailable
=
testObject
&&
testObject
.
options
&&
testObject
.
options
.
jsonInterface
const
isJSONInterfaceAvailable
=
testObject
&&
testObject
.
options
&&
testObject
.
options
.
jsonInterface
if
(
!
isJSONInterfaceAvailable
)
if
(
!
isJSONInterfaceAvailable
)
{
return
resultsCallback
(
new
Error
(
'Contract interface not available'
),
{
passingNum
,
failureNum
,
timePassed
})
}
return
resultsCallback
(
new
Error
(
'Contract interface not available'
),
{
passingNum
,
failureNum
,
timePassed
})
const
runList
:
RunListInterface
[]
=
createRunList
(
testObject
.
options
.
jsonInterface
,
fileAST
,
testName
)
const
runList
:
RunListInterface
[]
=
createRunList
(
testObject
.
options
.
jsonInterface
,
fileAST
,
testName
)
const
web3
=
new
Web3
()
const
web3
=
new
Web3
()
const
accts
:
TestResultInterface
=
{
const
accts
:
TestResultInterface
=
{
type
:
'accountList'
,
type
:
'accountList'
,
value
:
opts
.
accounts
value
:
opts
.
accounts
}
}
testCallback
(
undefined
,
accts
)
testCallback
(
undefined
,
accts
)
const
resp
:
TestResultInterface
=
{
const
resp
:
TestResultInterface
=
{
type
:
'contract'
,
type
:
'contract'
,
value
:
testName
,
value
:
testName
,
filename
:
testObject
.
filename
filename
:
testObject
.
filename
}
testCallback
(
undefined
,
resp
)
async
.
eachOfLimit
(
runList
,
1
,
function
(
func
,
index
,
next
)
{
let
sender
:
string
|
null
=
null
if
(
func
.
signature
)
{
sender
=
getOverridedSender
(
contractDetails
.
userdoc
,
func
.
signature
,
contractDetails
.
evm
.
methodIdentifiers
)
if
(
opts
.
accounts
&&
sender
)
{
sender
=
opts
.
accounts
[
sender
]
}
}
}
testCallback
(
undefined
,
resp
)
let
sendParams
:
Record
<
string
,
string
>
|
null
=
null
async
.
eachOfLimit
(
runList
,
1
,
function
(
func
,
index
,
next
)
{
if
(
sender
)
sendParams
=
{
from
:
sender
}
let
sender
:
string
|
null
=
null
if
(
func
.
inputs
&&
func
.
inputs
.
length
>
0
)
{
return
resultsCallback
(
new
Error
(
`Method '
${
func
.
name
}
' can not have parameters inside a test contract`
),
{
passingNum
,
failureNum
,
timePassed
})
}
if
(
func
.
signature
)
{
const
method
=
testObject
.
methods
[
func
.
name
].
apply
(
testObject
.
methods
[
func
.
name
],
[])
sender
=
getOverridedSender
(
contractDetails
.
userdoc
,
func
.
signature
,
contractDetails
.
evm
.
methodIdentifiers
)
const
startTime
=
Date
.
now
()
if
(
opts
.
accounts
&&
sender
)
{
if
(
func
.
constant
)
{
sender
=
opts
.
accounts
[
sender
]
method
.
call
(
sendParams
).
then
((
result
)
=>
{
}
const
time
=
(
Date
.
now
()
-
startTime
)
/
1000.0
}
if
(
result
)
{
let
sendParams
:
Record
<
string
,
string
>
|
null
=
null
const
resp
:
TestResultInterface
=
{
if
(
sender
)
sendParams
=
{
from
:
sender
}
type
:
'testPass'
,
if
(
func
.
inputs
&&
func
.
inputs
.
length
>
0
)
value
:
changeCase
.
sentenceCase
(
func
.
name
),
return
resultsCallback
(
new
Error
(
`Method '
${
func
.
name
}
' can not have parameters inside a test contract`
),
{
passingNum
,
failureNum
,
timePassed
})
filename
:
testObject
.
filename
,
const
method
=
testObject
.
methods
[
func
.
name
].
apply
(
testObject
.
methods
[
func
.
name
],
[])
time
:
time
,
const
startTime
=
Date
.
now
()
context
:
testName
if
(
func
.
constant
)
{
}
method
.
call
(
sendParams
).
then
((
result
)
=>
{
testCallback
(
undefined
,
resp
)
const
time
=
(
Date
.
now
()
-
startTime
)
/
1000.0
passingNum
+=
1
if
(
result
)
{
timePassed
+=
time
const
resp
:
TestResultInterface
=
{
type
:
'testPass'
,
value
:
changeCase
.
sentenceCase
(
func
.
name
),
filename
:
testObject
.
filename
,
time
:
time
,
context
:
testName
}
testCallback
(
undefined
,
resp
)
passingNum
+=
1
timePassed
+=
time
}
else
{
const
resp
:
TestResultInterface
=
{
type
:
'testFailure'
,
value
:
changeCase
.
sentenceCase
(
func
.
name
),
filename
:
testObject
.
filename
,
time
:
time
,
errMsg
:
'function returned false'
,
context
:
testName
}
testCallback
(
undefined
,
resp
)
failureNum
+=
1
timePassed
+=
time
}
next
()
})
}
else
{
}
else
{
if
(
func
.
payable
)
{
const
resp
:
TestResultInterface
=
{
const
value
=
getProvidedValue
(
contractDetails
.
userdoc
,
func
.
signature
,
contractDetails
.
evm
.
methodIdentifiers
)
type
:
'testFailure'
,
if
(
value
)
{
value
:
changeCase
.
sentenceCase
(
func
.
name
),
if
(
sendParams
)
sendParams
.
value
=
value
filename
:
testObject
.
filename
,
else
sendParams
=
{
value
}
time
:
time
,
}
errMsg
:
'function returned false'
,
}
context
:
testName
method
.
send
(
sendParams
).
on
(
'receipt'
,
(
receipt
)
=>
{
}
try
{
testCallback
(
undefined
,
resp
)
const
time
:
number
=
(
Date
.
now
()
-
startTime
)
/
1000.0
failureNum
+=
1
const
assertionEventHashes
=
assertionEvents
.
map
(
e
=>
Web3
.
utils
.
sha3
(
e
.
name
+
'('
+
e
.
params
.
join
()
+
')'
)
)
timePassed
+=
time
let
testPassed
=
false
}
for
(
const
i
in
receipt
.
events
)
{
next
()
let
events
=
receipt
.
events
[
i
]
})
if
(
!
Array
.
isArray
(
events
))
events
=
[
events
]
}
else
{
for
(
const
event
of
events
)
{
if
(
func
.
payable
)
{
const
eIndex
=
assertionEventHashes
.
indexOf
(
event
.
raw
.
topics
[
0
])
// event name topic will always be at index 0
const
value
=
getProvidedValue
(
contractDetails
.
userdoc
,
func
.
signature
,
contractDetails
.
evm
.
methodIdentifiers
)
if
(
eIndex
>=
0
)
{
if
(
value
)
{
const
testEvent
=
web3
.
eth
.
abi
.
decodeParameters
(
assertionEvents
[
eIndex
].
params
,
event
.
raw
.
data
)
if
(
sendParams
)
sendParams
.
value
=
value
if
(
!
testEvent
[
0
])
{
else
sendParams
=
{
value
}
const
assertMethod
=
testEvent
[
2
]
}
if
(
assertMethod
===
'ok'
)
{
// for 'Assert.ok' method
}
testEvent
[
3
]
=
'false'
method
.
send
(
sendParams
).
on
(
'receipt'
,
(
receipt
)
=>
{
testEvent
[
4
]
=
'true'
try
{
}
const
time
:
number
=
(
Date
.
now
()
-
startTime
)
/
1000.0
const
location
=
getAssertMethodLocation
(
fileAST
,
testName
,
func
.
name
,
assertMethod
)
const
assertionEventHashes
=
assertionEvents
.
map
(
e
=>
Web3
.
utils
.
sha3
(
e
.
name
+
'('
+
e
.
params
.
join
()
+
')'
))
const
resp
:
TestResultInterface
=
{
let
testPassed
=
false
type
:
'testFailure'
,
for
(
const
i
in
receipt
.
events
)
{
value
:
changeCase
.
sentenceCase
(
func
.
name
),
let
events
=
receipt
.
events
[
i
]
filename
:
testObject
.
filename
,
if
(
!
Array
.
isArray
(
events
))
events
=
[
events
]
time
:
time
,
for
(
const
event
of
events
)
{
errMsg
:
testEvent
[
1
],
const
eIndex
=
assertionEventHashes
.
indexOf
(
event
.
raw
.
topics
[
0
])
// event name topic will always be at index 0
context
:
testName
,
if
(
eIndex
>=
0
)
{
assertMethod
,
const
testEvent
=
web3
.
eth
.
abi
.
decodeParameters
(
assertionEvents
[
eIndex
].
params
,
event
.
raw
.
data
)
returned
:
testEvent
[
3
],
if
(
!
testEvent
[
0
])
{
expected
:
testEvent
[
4
],
const
assertMethod
=
testEvent
[
2
]
location
if
(
assertMethod
===
'ok'
)
{
// for 'Assert.ok' method
};
testEvent
[
3
]
=
'false'
testCallback
(
undefined
,
resp
)
testEvent
[
4
]
=
'true'
failureNum
+=
1
}
timePassed
+=
time
const
location
=
getAssertMethodLocation
(
fileAST
,
testName
,
func
.
name
,
assertMethod
)
return
next
()
const
resp
:
TestResultInterface
=
{
}
testPassed
=
true
}
}
}
if
(
testPassed
)
{
const
resp
:
TestResultInterface
=
{
type
:
'testPass'
,
value
:
changeCase
.
sentenceCase
(
func
.
name
),
filename
:
testObject
.
filename
,
time
:
time
,
context
:
testName
}
testCallback
(
undefined
,
resp
)
passingNum
+=
1
timePassed
+=
time
}
return
next
()
}
catch
(
err
)
{
console
.
error
(
err
)
return
next
(
err
)
}
}).
on
(
'error'
,
function
(
err
:
Error
)
{
const
time
:
number
=
(
Date
.
now
()
-
startTime
)
/
1000.0
const
resp
:
TestResultInterface
=
{
type
:
'testFailure'
,
type
:
'testFailure'
,
value
:
changeCase
.
sentenceCase
(
func
.
name
),
value
:
changeCase
.
sentenceCase
(
func
.
name
),
filename
:
testObject
.
filename
,
filename
:
testObject
.
filename
,
time
:
time
,
time
:
time
,
errMsg
:
err
.
message
,
errMsg
:
testEvent
[
1
],
context
:
testName
context
:
testName
,
};
assertMethod
,
returned
:
testEvent
[
3
],
expected
:
testEvent
[
4
],
location
}
testCallback
(
undefined
,
resp
)
testCallback
(
undefined
,
resp
)
failureNum
+=
1
failureNum
+=
1
timePassed
+=
time
timePassed
+=
time
return
next
()
return
next
()
})
}
testPassed
=
true
}
}
}
if
(
testPassed
)
{
const
resp
:
TestResultInterface
=
{
type
:
'testPass'
,
value
:
changeCase
.
sentenceCase
(
func
.
name
),
filename
:
testObject
.
filename
,
time
:
time
,
context
:
testName
}
testCallback
(
undefined
,
resp
)
passingNum
+=
1
timePassed
+=
time
}
return
next
()
}
catch
(
err
)
{
console
.
error
(
err
)
return
next
(
err
)
}
}
},
function
(
error
)
{
}).
on
(
'error'
,
function
(
err
:
Error
)
{
resultsCallback
(
error
,
{
passingNum
,
failureNum
,
timePassed
})
const
time
:
number
=
(
Date
.
now
()
-
startTime
)
/
1000.0
})
const
resp
:
TestResultInterface
=
{
type
:
'testFailure'
,
value
:
changeCase
.
sentenceCase
(
func
.
name
),
filename
:
testObject
.
filename
,
time
:
time
,
errMsg
:
err
.
message
,
context
:
testName
}
testCallback
(
undefined
,
resp
)
failureNum
+=
1
timePassed
+=
time
return
next
()
})
}
},
function
(
error
)
{
resultsCallback
(
error
,
{
passingNum
,
failureNum
,
timePassed
})
})
}
}
libs/remix-tests/src/types.ts
View file @
28773548
...
@@ -51,8 +51,8 @@ export interface Options {
...
@@ -51,8 +51,8 @@ export interface Options {
export
interface
CompilerConfiguration
{
export
interface
CompilerConfiguration
{
currentCompilerUrl
:
string
,
currentCompilerUrl
:
string
,
evmVersion
:
string
,
evmVersion
:
string
,
optimize
:
boolean
,
optimize
:
boolean
,
usingWorker
?:
boolean
,
usingWorker
?:
boolean
,
runs
:
number
runs
:
number
}
}
...
@@ -64,7 +64,7 @@ export interface CompilationErrors {
...
@@ -64,7 +64,7 @@ export interface CompilationErrors {
}
}
export
class
CompilationErrors
extends
Error
{
export
class
CompilationErrors
extends
Error
{
constructor
(
errors
:
Array
<
any
>
)
{
constructor
(
errors
:
Array
<
any
>
)
{
const
mapError
=
errors
.
map
((
e
)
=>
{
return
e
.
formattedMessage
||
e
.
message
})
const
mapError
=
errors
.
map
((
e
)
=>
{
return
e
.
formattedMessage
||
e
.
message
})
super
(
mapError
.
join
(
'
\
n'
))
super
(
mapError
.
join
(
'
\
n'
))
this
.
errors
=
errors
this
.
errors
=
errors
...
@@ -74,9 +74,9 @@ export class CompilationErrors extends Error {
...
@@ -74,9 +74,9 @@ export class CompilationErrors extends Error {
/** sources object with name of the file and content **/
/** sources object with name of the file and content **/
////////////
///
/////////
// SOURCE //
// SOURCE //
////////////
///
/////////
export
interface
CompilationSource
{
export
interface
CompilationSource
{
/** Identifier of the source (used in source maps) */
/** Identifier of the source (used in source maps) */
id
:
number
id
:
number
...
@@ -162,9 +162,9 @@ export interface CompiledContract {
...
@@ -162,9 +162,9 @@ export interface CompiledContract {
}
}
}
}
/////////
///
//////
// ABI //
// ABI //
/////////
///
//////
export
type
ABIDescription
=
FunctionDescription
|
EventDescription
export
type
ABIDescription
=
FunctionDescription
|
EventDescription
export
interface
FunctionDescription
{
export
interface
FunctionDescription
{
...
@@ -227,9 +227,9 @@ export type ABITypeParameter =
...
@@ -227,9 +227,9 @@ export type ABITypeParameter =
|
'tuple[]'
|
'tuple[]'
|
string
// Fallback
|
string
// Fallback
///////////////////////////
///
////////////////////////
// NATURAL SPECIFICATION //
// NATURAL SPECIFICATION //
///////////////////////////
///
////////////////////////
// Userdoc
// Userdoc
export
interface
UserDocumentation
{
export
interface
UserDocumentation
{
...
@@ -267,9 +267,9 @@ export interface DevMethodDoc {
...
@@ -267,9 +267,9 @@ export interface DevMethodDoc {
}
}
}
}
//////////////
///
///////////
// BYTECODE //
// BYTECODE //
//////////////
///
///////////
export
interface
BytecodeObject
{
export
interface
BytecodeObject
{
/** The bytecode as a hex string. */
/** The bytecode as a hex string. */
object
:
string
object
:
string
...
...
package.json
View file @
28773548
...
@@ -41,7 +41,7 @@
...
@@ -41,7 +41,7 @@
"workspace-schematic"
:
"nx workspace-schematic"
,
"workspace-schematic"
:
"nx workspace-schematic"
,
"dep-graph"
:
"nx dep-graph"
,
"dep-graph"
:
"nx dep-graph"
,
"help"
:
"nx help"
,
"help"
:
"nx help"
,
"lint:libs"
:
"nx run-many --target=lint --projects=remix-analyzer,remix-astwalker,remix-debug,remix-lib,remix-simulator,remix-solidity,remixd,remix-ui-tree-view,remix-ui-modal-dialog,remix-ui-toaster,remix-ui-file-explorer,remix-ui-debugger-ui"
,
"lint:libs"
:
"nx run-many --target=lint --projects=remix-analyzer,remix-astwalker,remix-debug,remix-lib,remix-simulator,remix-solidity,remix
-tests,remix
d,remix-ui-tree-view,remix-ui-modal-dialog,remix-ui-toaster,remix-ui-file-explorer,remix-ui-debugger-ui"
,
"build:libs"
:
"nx run-many --target=build --parallel=false --with-deps=true --projects=remix-analyzer,remix-astwalker,remix-debug,remix-lib,remix-simulator,remix-solidity,remix-tests,remix-url-resolver,remixd"
,
"build:libs"
:
"nx run-many --target=build --parallel=false --with-deps=true --projects=remix-analyzer,remix-astwalker,remix-debug,remix-lib,remix-simulator,remix-solidity,remix-tests,remix-url-resolver,remixd"
,
"test:libs"
:
"nx run-many --target=test --projects=remix-analyzer,remix-astwalker,remix-debug,remix-lib,remix-simulator,remix-solidity,remix-tests,remix-url-resolver,remixd"
,
"test:libs"
:
"nx run-many --target=test --projects=remix-analyzer,remix-astwalker,remix-debug,remix-lib,remix-simulator,remix-solidity,remix-tests,remix-url-resolver,remixd"
,
"publish:libs"
:
"npm run build:libs & lerna publish --skip-git & npm run bumpVersion:libs"
,
"publish:libs"
:
"npm run build:libs & lerna publish --skip-git & npm run bumpVersion:libs"
,
...
...
workspace.json
View file @
28773548
...
@@ -347,7 +347,7 @@
...
@@ -347,7 +347,7 @@
"linter"
:
"eslint"
,
"linter"
:
"eslint"
,
"config"
:
"libs/remix-tests/.eslintrc"
,
"config"
:
"libs/remix-tests/.eslintrc"
,
"tsConfig"
:
[
"libs/remix-tests/tsconfig.lib.json"
],
"tsConfig"
:
[
"libs/remix-tests/tsconfig.lib.json"
],
"exclude"
:
[
"**/node_modules/**"
,
"libs/remix-tests/tests/**/*"
]
"exclude"
:
[
"**/node_modules/**"
,
"libs/remix-tests/tests/**/*"
,
"**/dist/**"
]
}
}
},
},
"test"
:
{
"test"
:
{
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment