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.bouncycastle_version = constants.getProperty("bouncycastleVersion")
ext.guava_version = constants.getProperty("guavaVersion")
ext.quickcheck_version = '0.7'
ext.okhttp_version = '3.5.0'
ext.netty_version = '4.1.9.Final'
ext.typesafe_config_version = constants.getProperty("typesafeConfigVersion")

View File

@ -20,12 +20,6 @@ dependencies {
testCompile project(path: ':core', configuration: 'testArtifacts')
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 {

View File

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

View File

@ -41,12 +41,6 @@ dependencies {
// AssertJ: for fluent assertions for testing
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.
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(path: ':core', configuration: 'testArtifacts')
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 {

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'
}
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
integrationTestRuntime.extendsFrom testRuntime
@ -142,7 +135,6 @@ dependencies {
// Unit testing helpers.
testCompile "junit:junit:$junit_version"
testCompile "org.assertj:assertj-core:${assertj_version}"
testCompile "com.pholser:junit-quickcheck-core:$quickcheck_version"
testCompile project(':test-utils')
testCompile project(':client:jfx')
testCompile project(':finance')