|
|
|
/*
|
|
|
|
* Copyright ConsenSys AG.
|
|
|
|
*
|
|
|
|
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
|
|
|
|
* the License. You may obtain a copy of the License at
|
|
|
|
*
|
|
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
*
|
|
|
|
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
|
|
|
|
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
|
|
|
* specific language governing permissions and limitations under the License.
|
|
|
|
*
|
|
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
|
|
*/
|
|
|
|
|
|
|
|
configurations {
|
|
|
|
// we need this because referenceTestImplementation defaults to 'canBeResolved=false'.
|
|
|
|
tarConfig.extendsFrom referenceTestImplementation
|
|
|
|
tarConfig {
|
|
|
|
canBeResolved = true
|
|
|
|
canBeConsumed = false
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
def blockchainReferenceTests = tasks.register("blockchainReferenceTests") {
|
|
|
|
final referenceTestsPath = 'src/reference-test/external-resources/BlockchainTests'
|
|
|
|
final generatedTestsPath = "$buildDir/generated/sources/reference-test/$name/java"
|
|
|
|
inputs.files fileTree(referenceTestsPath),
|
|
|
|
fileTree(generatedTestsPath)
|
|
|
|
outputs.files generatedTestsPath
|
|
|
|
generateTestFiles(
|
|
|
|
fileTree(referenceTestsPath),
|
|
|
|
file("src/reference-test/templates/BlockchainReferenceTest.java.template"),
|
|
|
|
"BlockchainTests",
|
|
|
|
"$generatedTestsPath/org/hyperledger/besu/ethereum/vm/blockchain",
|
|
|
|
"BlockchainReferenceTest",
|
|
|
|
"org.hyperledger.besu.ethereum.vm.blockchain",
|
|
|
|
("BlockchainTests/InvalidBlocks/bcExpectSection") // exclude test for test filling tool
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
|
|
|
def eipBlockchainReferenceTests = tasks.register("eipBlockchainReferenceTests") {
|
|
|
|
final referenceTestsPath = 'src/reference-test/external-resources/EIPTests/BlockchainTests'
|
|
|
|
final generatedTestsPath = "$buildDir/generated/sources/reference-test/$name/java"
|
|
|
|
inputs.files fileTree(referenceTestsPath),
|
|
|
|
fileTree(generatedTestsPath)
|
|
|
|
outputs.files generatedTestsPath
|
|
|
|
generateTestFiles(
|
|
|
|
fileTree(referenceTestsPath),
|
|
|
|
file("src/reference-test/templates/BlockchainReferenceTest.java.template"),
|
|
|
|
"EIPTests${File.separatorChar}BlockchainTests",
|
|
|
|
"$generatedTestsPath/org/hyperledger/besu/ethereum/vm/eip",
|
|
|
|
"EIPBlockchainReferenceTest",
|
|
|
|
"org.hyperledger.besu.ethereum.vm.eip",
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
|
|
|
def eipStateReferenceTests = tasks.register("eipStateReferenceTests") {
|
|
|
|
final referenceTestsPath = 'src/reference-test/external-resources/EIPTests/StateTests'
|
|
|
|
final generatedTestsPath = "$buildDir/generated/sources/reference-test/$name/java"
|
|
|
|
inputs.files fileTree(referenceTestsPath),
|
|
|
|
fileTree(generatedTestsPath)
|
|
|
|
outputs.files generatedTestsPath
|
|
|
|
generateTestFiles(
|
|
|
|
fileTree(referenceTestsPath),
|
|
|
|
file("src/reference-test/templates/GeneralStateReferenceTest.java.template"),
|
|
|
|
"EIPTests${File.separatorChar}StateTests",
|
|
|
|
"$generatedTestsPath/org/hyperledger/besu/ethereum/vm/eip",
|
|
|
|
"EIPStateReferenceTest",
|
|
|
|
"org.hyperledger.besu.ethereum.vm.eip",
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
|
|
|
def executionSpecTests = tasks.register("executionSpecTests") {
|
|
|
|
final referenceTestsPath = "$buildDir/execution-spec-tests/"
|
|
|
|
final generatedTestsPath = "$buildDir/generated/sources/reference-test/$name/java"
|
|
|
|
def tarPath = configurations.tarConfig.files.find{ it.name.startsWith('execution-spec-tests')}
|
|
|
|
|
|
|
|
copy {
|
|
|
|
from tarTree(tarPath)
|
|
|
|
into "$referenceTestsPath"
|
|
|
|
}
|
|
|
|
|
|
|
|
inputs.files fileTree(referenceTestsPath), fileTree(generatedTestsPath)
|
|
|
|
outputs.files generatedTestsPath
|
|
|
|
// generate blockchain_tests:
|
|
|
|
generateTestFiles(
|
|
|
|
fileTree(referenceTestsPath + "/fixtures/blockchain_tests"),
|
|
|
|
file("src/reference-test/templates/BlockchainReferenceTest.java.template"),
|
|
|
|
"fixtures",
|
|
|
|
"$generatedTestsPath/org/hyperledger/besu/ethereum/vm/executionspec",
|
|
|
|
"ExecutionSpecBlockchainTest",
|
|
|
|
"org.hyperledger.besu.ethereum.vm.executionspec",
|
|
|
|
)
|
|
|
|
|
|
|
|
// generate state_tests:
|
|
|
|
generateTestFiles(
|
|
|
|
fileTree(referenceTestsPath + "/fixtures/state_tests"),
|
|
|
|
file("src/reference-test/templates/GeneralStateReferenceTest.java.template"),
|
|
|
|
"fixtures",
|
|
|
|
"$generatedTestsPath/org/hyperledger/besu/ethereum/vm/executionspec",
|
|
|
|
"ExecutionSpecStateTest",
|
|
|
|
"org.hyperledger.besu.ethereum.vm.executionspec",
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
|
|
|
def generalstateReferenceTests = tasks.register("generalstateReferenceTests") {
|
|
|
|
final referenceTestsPath = "src/reference-test/external-resources/GeneralStateTests"
|
|
|
|
final generatedTestsPath = "$buildDir/generated/sources/reference-test/$name/java"
|
|
|
|
inputs.files fileTree(referenceTestsPath),
|
|
|
|
fileTree(generatedTestsPath)
|
|
|
|
outputs.files generatedTestsPath
|
|
|
|
generateTestFiles(
|
|
|
|
fileTree(referenceTestsPath),
|
|
|
|
file("src/reference-test/templates/GeneralStateReferenceTest.java.template"),
|
|
|
|
"GeneralStateTests",
|
|
|
|
"$generatedTestsPath/org/hyperledger/besu/ethereum/vm/generalstate",
|
|
|
|
"GeneralStateReferenceTest",
|
|
|
|
"org.hyperledger.besu.ethereum.vm.generalstate",
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
|
|
|
def generalstateRegressionReferenceTests = tasks.register("generalstateRegressionReferenceTests") {
|
|
|
|
final referenceTestsPath = "src/reference-test/resources/regressions/generalstate"
|
|
|
|
final generatedTestsPath = "$buildDir/generated/sources/reference-test/$name/java"
|
|
|
|
inputs.files fileTree(referenceTestsPath),
|
|
|
|
fileTree(generatedTestsPath)
|
|
|
|
outputs.files generatedTestsPath
|
|
|
|
generateTestFiles(
|
|
|
|
fileTree(referenceTestsPath),
|
|
|
|
file("src/reference-test/templates/GeneralStateReferenceTest.java.template"),
|
|
|
|
"regressions",
|
|
|
|
"$generatedTestsPath/org/hyperledger/besu/ethereum/vm/generalstate",
|
|
|
|
"GeneralStateRegressionReferenceTest",
|
|
|
|
"org.hyperledger.besu.ethereum.vm.generalstate"
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
|
|
|
def eofReferenceTests = tasks.register("eofReferenceTests") {
|
|
|
|
final referenceTestsPath = "src/reference-test/external-resources/EOFTests"
|
|
|
|
final generatedTestsPath = "$buildDir/generated/sources/reference-test/$name/java"
|
|
|
|
inputs.files fileTree(referenceTestsPath),
|
|
|
|
fileTree(generatedTestsPath)
|
|
|
|
outputs.files generatedTestsPath
|
|
|
|
generateTestFiles(
|
|
|
|
fileTree(referenceTestsPath),
|
|
|
|
file("src/reference-test/templates/EOFReferenceTest.java.template"),
|
|
|
|
"EOFTests",
|
|
|
|
"$generatedTestsPath/org/hyperledger/besu/ethereum/vm/eof",
|
|
|
|
"EOFReferenceTest",
|
|
|
|
"org.hyperledger.besu.ethereum.vm.eof"
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
|
|
|
sourceSets {
|
|
|
|
referenceTest {
|
|
|
|
java {
|
|
|
|
compileClasspath += main.output
|
|
|
|
runtimeClasspath += main.output
|
|
|
|
srcDirs "src/reference-test/java",
|
|
|
|
blockchainReferenceTests,
|
|
|
|
eipBlockchainReferenceTests,
|
|
|
|
eipStateReferenceTests,
|
|
|
|
executionSpecTests,
|
|
|
|
generalstateReferenceTests,
|
|
|
|
generalstateRegressionReferenceTests,
|
|
|
|
eofReferenceTests
|
|
|
|
}
|
|
|
|
resources {
|
|
|
|
srcDirs 'src/reference-test/resources',
|
|
|
|
'src/reference-test/external-resources',
|
|
|
|
'src/reference-test/templates',
|
|
|
|
'build/execution-spec-tests/'
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
dependencies {
|
|
|
|
implementation project(':config')
|
|
|
|
implementation project(':crypto:algorithms')
|
|
|
|
implementation project(':datatypes')
|
|
|
|
implementation project(':ethereum:core')
|
|
|
|
implementation project(':metrics:core')
|
|
|
|
implementation project(':util')
|
|
|
|
implementation project(path: ':ethereum:core', configuration: 'testSupportArtifacts')
|
|
|
|
implementation project(':ethereum:rlp')
|
|
|
|
implementation project(':evm')
|
|
|
|
implementation project(':services:kvstore')
|
|
|
|
|
|
|
|
implementation 'io.tmio:tuweni-rlp'
|
|
|
|
implementation 'com.fasterxml.jackson.core:jackson-databind'
|
|
|
|
implementation 'com.google.guava:guava'
|
|
|
|
|
|
|
|
referenceTestImplementation project(path: ':config')
|
|
|
|
referenceTestImplementation project(path: ':datatypes')
|
|
|
|
referenceTestImplementation project(path: ':ethereum:core')
|
|
|
|
referenceTestImplementation project(path: ':ethereum:core', configuration: 'testSupportArtifacts')
|
|
|
|
referenceTestImplementation project(path: ':ethereum:rlp')
|
|
|
|
referenceTestImplementation project(path: ':ethereum:rlp', configuration: 'testSupportArtifacts')
|
|
|
|
referenceTestImplementation project(path: ':ethereum:trie')
|
|
|
|
referenceTestImplementation project(path: ':evm')
|
|
|
|
referenceTestImplementation project(path: ':plugin-api')
|
|
|
|
referenceTestImplementation project(path: ':testutil')
|
|
|
|
referenceTestImplementation project(path: ':util')
|
|
|
|
// the following will be resolved via custom ivy repository declared in root build.gradle
|
|
|
|
referenceTestImplementation 'ethereum:execution-spec-tests:2.1.1:fixtures@tar.gz'
|
|
|
|
referenceTestImplementation 'com.fasterxml.jackson.core:jackson-databind'
|
|
|
|
referenceTestImplementation 'com.google.guava:guava'
|
|
|
|
referenceTestImplementation 'io.tmio:tuweni-bytes'
|
|
|
|
referenceTestImplementation 'io.tmio:tuweni-units'
|
|
|
|
referenceTestImplementation 'org.assertj:assertj-core'
|
|
|
|
referenceTestImplementation 'org.junit.jupiter:junit-jupiter-api'
|
|
|
|
referenceTestImplementation 'org.junit.jupiter:junit-jupiter-params'
|
|
|
|
|
|
|
|
referenceTestRuntimeOnly 'org.junit.jupiter:junit-jupiter'
|
|
|
|
}
|
|
|
|
|
|
|
|
tasks.register('referenceTests', Test) {
|
|
|
|
useJUnitPlatform()
|
|
|
|
doFirst {
|
|
|
|
if (!file("src/reference-test/external-resources/README.md").exists()) {
|
|
|
|
throw new GradleException("ethereum/referencetest/src/reference-test/external-resources/README.md missing: please clone submodules (git submodule update --init --recursive)")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
description = 'Runs ETH reference tests.'
|
|
|
|
testClassesDirs = sourceSets.referenceTest.output.classesDirs
|
|
|
|
classpath = sourceSets.referenceTest.runtimeClasspath
|
|
|
|
}
|
|
|
|
|
|
|
|
tasks.register('validateReferenceTestSubmodule') {
|
|
|
|
description = "Checks that the reference tests submodule is not accidentally changed"
|
|
|
|
doLast {
|
|
|
|
def result = new ByteArrayOutputStream()
|
|
|
|
def expectedHash = 'faf33b471465d3c6cdc3d04fbd690895f78d33f2'
|
|
|
|
def submodulePath = java.nio.file.Path.of("${rootProject.projectDir}", "ethereum/referencetests/src/reference-test/external-resources").toAbsolutePath()
|
|
|
|
try {
|
|
|
|
exec {
|
|
|
|
commandLine 'git', 'submodule', 'status', submodulePath
|
|
|
|
standardOutput = result
|
|
|
|
errorOutput = result
|
|
|
|
}
|
|
|
|
} catch (Exception ignore) {
|
|
|
|
// Ignore it. We want to fail in a friendly fashion if they don't have git installed.
|
|
|
|
// The CI servers have git and that is the only critical place for this failure
|
|
|
|
expectedHash = ''
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!result.toString().contains(expectedHash)) {
|
|
|
|
throw new GradleException("""For the Ethereum Reference Tests the git commit did not match what was expected.
|
|
|
|
|
|
|
|
If this is a deliberate change where you are updating the reference tests
|
|
|
|
then update "expectedHash" in `ethereum/referencetests/build.gradle` as the
|
|
|
|
commit hash for this task.
|
|
|
|
Expected hash : ${expectedHash}
|
|
|
|
Full git output : ${result}
|
|
|
|
|
|
|
|
If this is accidental you can correct the reference test versions with the
|
|
|
|
following commands:
|
|
|
|
pushd ${submodulePath}
|
|
|
|
git fetch
|
|
|
|
git checkout ${expectedHash}
|
|
|
|
cd ..
|
|
|
|
git add ${submodulePath}
|
|
|
|
popd""")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
processResources.dependsOn('validateReferenceTestSubmodule')
|
|
|
|
|
|
|
|
def generateTestFiles(
|
|
|
|
FileTree jsonPath,
|
|
|
|
File templateFile,
|
|
|
|
String pathstrip,
|
|
|
|
String destination,
|
|
|
|
String namePrefix,
|
|
|
|
String packageString,
|
|
|
|
String ... excludedPath) {
|
|
|
|
mkdir(destination)
|
|
|
|
def referenceTestTemplate = templateFile.text
|
|
|
|
|
|
|
|
def paths = []
|
|
|
|
jsonPath.getFiles().forEach { testJsonFile ->
|
|
|
|
def parentFile = testJsonFile.getParentFile()
|
|
|
|
def parentPathFile = parentFile.getPath().substring(parentFile.getPath().indexOf(pathstrip))
|
|
|
|
if (!testJsonFile.getName().toString().startsWith(".") && !excludedPath.contains(parentPathFile)) {
|
|
|
|
def pathFile = testJsonFile.getPath()
|
|
|
|
paths << pathFile.substring(pathFile.indexOf(pathstrip))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
paths.collate(5).eachWithIndex { tests, idx ->
|
|
|
|
def testFile = file(destination + "/" + namePrefix + "_" + idx + ".java")
|
|
|
|
|
|
|
|
def allPaths = '"' + tests.join('",\n "') + '"'
|
|
|
|
|
|
|
|
def testFileContents = referenceTestTemplate
|
|
|
|
.replaceAll("%%TESTS_FILE%%", allPaths)
|
|
|
|
.replaceAll("%%TESTS_NAME%%", namePrefix + "_" + idx)
|
|
|
|
.replaceAll("%%PACKAGE_NAME%%", packageString)
|
|
|
|
testFile.newWriter().withWriter { w -> w << testFileContents }
|
|
|
|
}
|
|
|
|
}
|