Remove junit-quickcheck and redundant generators

This commit is contained in:
Andrius Dagys 2017-08-11 17:22:46 +01:00
parent f69273027c
commit 43adbfd66c
9 changed files with 4 additions and 327 deletions

View File

@ -31,7 +31,6 @@ buildscript {
ext.log4j_version = '2.7' ext.log4j_version = '2.7'
ext.bouncycastle_version = constants.getProperty("bouncycastleVersion") ext.bouncycastle_version = constants.getProperty("bouncycastleVersion")
ext.guava_version = constants.getProperty("guavaVersion") ext.guava_version = constants.getProperty("guavaVersion")
ext.quickcheck_version = '0.7'
ext.okhttp_version = '3.5.0' ext.okhttp_version = '3.5.0'
ext.netty_version = '4.1.9.Final' ext.netty_version = '4.1.9.Final'
ext.typesafe_config_version = constants.getProperty("typesafeConfigVersion") ext.typesafe_config_version = constants.getProperty("typesafeConfigVersion")

View File

@ -20,12 +20,6 @@ dependencies {
testCompile project(path: ':core', configuration: 'testArtifacts') testCompile project(path: ':core', configuration: 'testArtifacts')
testCompile "junit:junit:$junit_version" testCompile "junit:junit:$junit_version"
// TODO: Upgrade to junit-quickcheck 0.8, once it is released,
// because it depends on org.javassist:javassist instead
// of javassist:javassist.
testCompile "com.pholser:junit-quickcheck-core:$quickcheck_version"
testCompile "com.pholser:junit-quickcheck-generators:$quickcheck_version"
} }
jar { jar {

View File

@ -1,15 +1,12 @@
package net.corda.jackson package net.corda.jackson
import com.fasterxml.jackson.databind.SerializationFeature import com.fasterxml.jackson.databind.SerializationFeature
import com.pholser.junit.quickcheck.From
import com.pholser.junit.quickcheck.Property
import com.pholser.junit.quickcheck.runner.JUnitQuickcheck
import net.corda.core.contracts.Amount import net.corda.core.contracts.Amount
import net.corda.core.contracts.USD import net.corda.core.contracts.USD
import net.corda.core.crypto.Crypto import net.corda.core.crypto.Crypto
import net.corda.core.crypto.SignatureMetadata import net.corda.core.crypto.SignatureMetadata
import net.corda.core.crypto.TransactionSignature import net.corda.core.crypto.TransactionSignature
import net.corda.core.testing.PublicKeyGenerator import net.corda.core.crypto.generateKeyPair
import net.corda.core.transactions.SignedTransaction import net.corda.core.transactions.SignedTransaction
import net.corda.testing.ALICE_PUBKEY import net.corda.testing.ALICE_PUBKEY
import net.corda.testing.DUMMY_NOTARY import net.corda.testing.DUMMY_NOTARY
@ -18,19 +15,17 @@ import net.corda.testing.TestDependencyInjectionBase
import net.corda.testing.contracts.DummyContract import net.corda.testing.contracts.DummyContract
import net.i2p.crypto.eddsa.EdDSAPublicKey import net.i2p.crypto.eddsa.EdDSAPublicKey
import org.junit.Test import org.junit.Test
import org.junit.runner.RunWith
import java.security.PublicKey
import java.util.* import java.util.*
import kotlin.test.assertEquals import kotlin.test.assertEquals
@RunWith(JUnitQuickcheck::class)
class JacksonSupportTest : TestDependencyInjectionBase() { class JacksonSupportTest : TestDependencyInjectionBase() {
companion object { companion object {
val mapper = JacksonSupport.createNonRpcMapper() val mapper = JacksonSupport.createNonRpcMapper()
} }
@Property @Test
fun publicKeySerializingWorks(@From(PublicKeyGenerator::class) publicKey: PublicKey) { fun publicKeySerializingWorks() {
val publicKey = generateKeyPair().public
val serialized = mapper.writeValueAsString(publicKey) val serialized = mapper.writeValueAsString(publicKey)
val parsedKey = mapper.readValue(serialized, EdDSAPublicKey::class.java) val parsedKey = mapper.readValue(serialized, EdDSAPublicKey::class.java)
assertEquals(publicKey, parsedKey) assertEquals(publicKey, parsedKey)

View File

@ -41,12 +41,6 @@ dependencies {
// AssertJ: for fluent assertions for testing // AssertJ: for fluent assertions for testing
testCompile "org.assertj:assertj-core:${assertj_version}" testCompile "org.assertj:assertj-core:${assertj_version}"
// TODO: Upgrade to junit-quickcheck 0.8, once it is released,
// because it depends on org.javassist:javassist instead
// of javassist:javassist.
testCompile "com.pholser:junit-quickcheck-core:$quickcheck_version"
testCompile "com.pholser:junit-quickcheck-generators:$quickcheck_version"
// Guava: Google utilities library. // Guava: Google utilities library.
compile "com.google.guava:guava:$guava_version" compile "com.google.guava:guava:$guava_version"

View File

@ -1,156 +0,0 @@
package net.corda.core.testing
import com.pholser.junit.quickcheck.generator.GenerationStatus
import com.pholser.junit.quickcheck.generator.Generator
import com.pholser.junit.quickcheck.generator.java.util.ArrayListGenerator
import com.pholser.junit.quickcheck.random.SourceOfRandomness
import net.corda.core.contracts.*
import net.corda.core.crypto.SecureHash
import net.corda.core.crypto.entropyToKeyPair
import net.corda.core.identity.AnonymousParty
import net.corda.core.identity.Party
import net.corda.core.utilities.OpaqueBytes
import net.corda.testing.getTestX509Name
import org.bouncycastle.asn1.x500.X500Name
import java.nio.ByteBuffer
import java.nio.charset.Charset
import java.security.PrivateKey
import java.security.PublicKey
import java.time.Duration
import java.time.Instant
import java.util.*
/**
* Generators for quickcheck
*
* TODO Split this into several files
*/
fun <A> Generator<A>.generateList(random: SourceOfRandomness, status: GenerationStatus): List<A> {
val arrayGenerator = ArrayListGenerator()
arrayGenerator.addComponentGenerators(listOf(this))
@Suppress("UNCHECKED_CAST")
return arrayGenerator.generate(random, status) as List<A>
}
class PrivateKeyGenerator : Generator<PrivateKey>(PrivateKey::class.java) {
override fun generate(random: SourceOfRandomness, status: GenerationStatus): PrivateKey {
return entropyToKeyPair(random.nextBigInteger(32)).private
}
}
// TODO add CompositeKeyGenerator that actually does something useful.
class PublicKeyGenerator : Generator<PublicKey>(PublicKey::class.java) {
override fun generate(random: SourceOfRandomness, status: GenerationStatus): PublicKey {
return entropyToKeyPair(random.nextBigInteger(32)).public
}
}
class AnonymousPartyGenerator : Generator<AnonymousParty>(AnonymousParty::class.java) {
override fun generate(random: SourceOfRandomness, status: GenerationStatus): AnonymousParty {
return AnonymousParty(PublicKeyGenerator().generate(random, status))
}
}
class PartyGenerator : Generator<Party>(Party::class.java) {
override fun generate(random: SourceOfRandomness, status: GenerationStatus): Party {
return Party(X500NameGenerator().generate(random, status), PublicKeyGenerator().generate(random, status))
}
}
class PartyAndReferenceGenerator : Generator<PartyAndReference>(PartyAndReference::class.java) {
override fun generate(random: SourceOfRandomness, status: GenerationStatus): PartyAndReference {
return PartyAndReference(AnonymousPartyGenerator().generate(random, status), OpaqueBytes(random.nextBytes(16)))
}
}
class SecureHashGenerator : Generator<SecureHash>(SecureHash::class.java) {
override fun generate(random: SourceOfRandomness, status: GenerationStatus): SecureHash {
return SecureHash.sha256(random.nextBytes(16))
}
}
class StateRefGenerator : Generator<StateRef>(StateRef::class.java) {
override fun generate(random: SourceOfRandomness, status: GenerationStatus): StateRef {
return StateRef(SecureHash.sha256(random.nextBytes(16)), random.nextInt(0, 10))
}
}
@Suppress("CAST_NEVER_SUCCEEDS", "UNCHECKED_CAST")
class TransactionStateGenerator<T : ContractState>(val stateGenerator: Generator<T>) : Generator<TransactionState<T>>(TransactionState::class.java as Class<TransactionState<T>>) {
override fun generate(random: SourceOfRandomness, status: GenerationStatus): TransactionState<T> {
return TransactionState(stateGenerator.generate(random, status), PartyGenerator().generate(random, status))
}
}
@Suppress("CAST_NEVER_SUCCEEDS", "UNCHECKED_CAST")
class IssuedGenerator<T : Any>(val productGenerator: Generator<T>) : Generator<Issued<T>>(Issued::class.java as Class<Issued<T>>) {
override fun generate(random: SourceOfRandomness, status: GenerationStatus): Issued<T> {
return Issued(PartyAndReferenceGenerator().generate(random, status), productGenerator.generate(random, status))
}
}
@Suppress("CAST_NEVER_SUCCEEDS", "UNCHECKED_CAST")
class AmountGenerator<T : Any>(val tokenGenerator: Generator<T>) : Generator<Amount<T>>(Amount::class.java as Class<Amount<T>>) {
override fun generate(random: SourceOfRandomness, status: GenerationStatus): Amount<T> {
return Amount(random.nextLong(0, 1000000), tokenGenerator.generate(random, status))
}
}
class CurrencyGenerator : Generator<Currency>(Currency::class.java) {
companion object {
val currencies = Currency.getAvailableCurrencies().toList()
}
override fun generate(random: SourceOfRandomness, status: GenerationStatus): Currency {
return currencies[random.nextInt(0, currencies.size - 1)]
}
}
class InstantGenerator : Generator<Instant>(Instant::class.java) {
override fun generate(random: SourceOfRandomness, status: GenerationStatus): Instant {
return Instant.ofEpochMilli(random.nextLong(0, 1000000))
}
}
class DurationGenerator : Generator<Duration>(Duration::class.java) {
override fun generate(random: SourceOfRandomness, status: GenerationStatus): Duration {
return Duration.ofMillis(random.nextLong(0, 1000000))
}
}
class TimeWindowGenerator : Generator<TimeWindow>(TimeWindow::class.java) {
override fun generate(random: SourceOfRandomness, status: GenerationStatus): TimeWindow {
return TimeWindow.withTolerance(InstantGenerator().generate(random, status), DurationGenerator().generate(random, status))
}
}
class X500NameGenerator : Generator<X500Name>(X500Name::class.java) {
companion object {
private val charset = Charset.forName("US-ASCII")
private val asciiA = charset.encode("A")[0]
private val asciia = charset.encode("a")[0]
}
/**
* Append something that looks a bit like a proper noun to the string builder.
*/
private fun appendProperNoun(builder: StringBuilder, random: SourceOfRandomness) : StringBuilder {
val length = random.nextByte(1, 8)
val encoded = ByteBuffer.allocate(length.toInt())
encoded.put((random.nextByte(0, 25) + asciiA).toByte())
for (charIdx in 1..length - 1) {
encoded.put((random.nextByte(0, 25) + asciia).toByte())
}
return builder.append(charset.decode(encoded))
}
override fun generate(random: SourceOfRandomness, status: GenerationStatus): X500Name {
val wordCount = random.nextByte(1, 3)
val cn = StringBuilder()
for (word in 0..wordCount) {
appendProperNoun(cn, random).append(" ")
}
return getTestX509Name(cn.trim().toString())
}
}

View File

@ -16,19 +16,6 @@ dependencies {
testCompile project(':test-utils') testCompile project(':test-utils')
testCompile project(path: ':core', configuration: 'testArtifacts') testCompile project(path: ':core', configuration: 'testArtifacts')
testCompile "junit:junit:$junit_version" testCompile "junit:junit:$junit_version"
// TODO: Upgrade to junit-quickcheck 0.8, once it is released,
// because it depends on org.javassist:javassist instead
// of javassist:javassist.
testCompile "com.pholser:junit-quickcheck-core:$quickcheck_version"
testCompile "com.pholser:junit-quickcheck-generators:$quickcheck_version"
}
configurations.testCompile {
// Excluding javassist:javassist because it clashes with Hibernate's
// transitive org.javassist:javassist dependency.
// TODO: Remove this exclusion once junit-quickcheck 0.8 is released.
exclude group: 'javassist', module: 'javassist'
} }
configurations { configurations {

View File

@ -1,88 +0,0 @@
package net.corda.contracts.testing
import com.pholser.junit.quickcheck.generator.GenerationStatus
import com.pholser.junit.quickcheck.generator.Generator
import com.pholser.junit.quickcheck.generator.java.util.ArrayListGenerator
import com.pholser.junit.quickcheck.random.SourceOfRandomness
import net.corda.contracts.asset.Cash
import net.corda.core.contracts.Command
import net.corda.core.contracts.CommandData
import net.corda.core.contracts.ContractState
import net.corda.core.crypto.testing.NULL_SIGNATURE
import net.corda.core.identity.AnonymousParty
import net.corda.core.testing.*
import net.corda.core.transactions.SignedTransaction
import net.corda.core.transactions.WireTransaction
/**
* This file contains generators for quickcheck style testing. The idea is that we can write random instance generators
* for each type we have in the code and test against those instead of predefined mock data. This style of testing can
* catch corner case bugs and test algebraic properties of the code, for example deserialize(serialize(generatedThing)) == generatedThing
*
* TODO add combinators for easier Generator writing
*/
class ContractStateGenerator : Generator<ContractState>(ContractState::class.java) {
override fun generate(random: SourceOfRandomness, status: GenerationStatus): ContractState {
return Cash.State(
amount = AmountGenerator(IssuedGenerator(CurrencyGenerator())).generate(random, status),
owner = AnonymousParty(PublicKeyGenerator().generate(random, status))
)
}
}
class MoveGenerator : Generator<Cash.Commands.Move>(Cash.Commands.Move::class.java) {
override fun generate(random: SourceOfRandomness, status: GenerationStatus): Cash.Commands.Move {
return Cash.Commands.Move(SecureHashGenerator().generate(random, status))
}
}
class IssueGenerator : Generator<Cash.Commands.Issue>(Cash.Commands.Issue::class.java) {
override fun generate(random: SourceOfRandomness, status: GenerationStatus): Cash.Commands.Issue {
return Cash.Commands.Issue(random.nextLong())
}
}
class ExitGenerator : Generator<Cash.Commands.Exit>(Cash.Commands.Exit::class.java) {
override fun generate(random: SourceOfRandomness, status: GenerationStatus): Cash.Commands.Exit {
return Cash.Commands.Exit(AmountGenerator(IssuedGenerator(CurrencyGenerator())).generate(random, status))
}
}
class CommandDataGenerator : Generator<CommandData>(CommandData::class.java) {
override fun generate(random: SourceOfRandomness, status: GenerationStatus): CommandData {
val generators = listOf(MoveGenerator(), IssueGenerator(), ExitGenerator())
return generators[random.nextInt(0, generators.size - 1)].generate(random, status)
}
}
class CommandGenerator : Generator<Command<*>>(Command::class.java) {
override fun generate(random: SourceOfRandomness, status: GenerationStatus): Command<*> {
val signersGenerator = ArrayListGenerator()
signersGenerator.addComponentGenerators(listOf(PublicKeyGenerator()))
return Command(CommandDataGenerator().generate(random, status), PublicKeyGenerator().generate(random, status))
}
}
class WiredTransactionGenerator : Generator<WireTransaction>(WireTransaction::class.java) {
override fun generate(random: SourceOfRandomness, status: GenerationStatus): WireTransaction {
val commands = CommandGenerator().generateList(random, status) + listOf(CommandGenerator().generate(random, status))
return WireTransaction(
inputs = StateRefGenerator().generateList(random, status) + listOf(StateRefGenerator().generate(random, status)),
attachments = SecureHashGenerator().generateList(random, status),
outputs = TransactionStateGenerator(ContractStateGenerator()).generateList(random, status),
commands = commands,
notary = PartyGenerator().generate(random, status),
timeWindow = TimeWindowGenerator().generate(random, status)
)
}
}
class SignedTransactionGenerator : Generator<SignedTransaction>(SignedTransaction::class.java) {
override fun generate(random: SourceOfRandomness, status: GenerationStatus): SignedTransaction {
val wireTransaction = WiredTransactionGenerator().generate(random, status)
return SignedTransaction(
ctx = wireTransaction,
sigs = listOf(NULL_SIGNATURE)
)
}
}

View File

@ -1,40 +0,0 @@
package net.corda.flows
import com.pholser.junit.quickcheck.From
import com.pholser.junit.quickcheck.Property
import com.pholser.junit.quickcheck.generator.GenerationStatus
import com.pholser.junit.quickcheck.generator.Generator
import com.pholser.junit.quickcheck.random.SourceOfRandomness
import com.pholser.junit.quickcheck.runner.JUnitQuickcheck
import net.corda.contracts.testing.SignedTransactionGenerator
import net.corda.core.serialization.deserialize
import net.corda.core.serialization.serialize
import net.corda.core.transactions.SignedTransaction
import net.corda.testing.initialiseTestSerialization
import net.corda.testing.resetTestSerialization
import org.junit.After
import org.junit.runner.RunWith
import kotlin.test.assertEquals
@RunWith(JUnitQuickcheck::class)
class BroadcastTransactionFlowTest {
class NotifyTxRequestMessageGenerator : Generator<SignedTransaction>(SignedTransaction::class.java) {
override fun generate(random: SourceOfRandomness, status: GenerationStatus): SignedTransaction {
initialiseTestSerialization()
return SignedTransactionGenerator().generate(random, status)
}
}
@After
fun teardown() {
resetTestSerialization()
}
@Property
fun serialiseDeserialiseOfNotifyMessageWorks(@From(NotifyTxRequestMessageGenerator::class) message: SignedTransaction) {
val serialized = message.serialize().bytes
val deserialized = serialized.deserialize<SignedTransaction>()
assertEquals(deserialized, message)
}
}

View File

@ -20,13 +20,6 @@ configurations {
exclude group: 'io.netty', module: 'netty-handler' exclude group: 'io.netty', module: 'netty-handler'
} }
testCompile {
// Excluding javassist:javassist because it clashes with Hibernate's
// transitive org.javassist:javassist dependency.
// TODO: Remove this exclusion once junit-quickcheck 0.8 is released.
exclude group: 'javassist', module: 'javassist'
}
integrationTestCompile.extendsFrom testCompile integrationTestCompile.extendsFrom testCompile
integrationTestRuntime.extendsFrom testRuntime integrationTestRuntime.extendsFrom testRuntime
@ -142,7 +135,6 @@ dependencies {
// Unit testing helpers. // Unit testing helpers.
testCompile "junit:junit:$junit_version" testCompile "junit:junit:$junit_version"
testCompile "org.assertj:assertj-core:${assertj_version}" testCompile "org.assertj:assertj-core:${assertj_version}"
testCompile "com.pholser:junit-quickcheck-core:$quickcheck_version"
testCompile project(':test-utils') testCompile project(':test-utils')
testCompile project(':client:jfx') testCompile project(':client:jfx')
testCompile project(':finance') testCompile project(':finance')