Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Move tests from jvmTest to commonTest #108

Merged
merged 4 commits into from
Oct 10, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 4 additions & 5 deletions bip39-lib/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@ kotlin {
val commonTest by getting {
dependencies {
implementation(kotlin("test"))
implementation(libs.kotest.framework.engine)
implementation(libs.kotest.assertion)
implementation(libs.kotest.property)
}
}
val jvmMain by getting {
Expand All @@ -33,11 +36,7 @@ kotlin {
val jvmTest by getting {
dependencies {
implementation(kotlin("test"))
implementation(libs.kotest.runner)
implementation(libs.kotest.assertion)
implementation(libs.kotest.property)
implementation(libs.moshi.core)
implementation(libs.moshi.kotlin)
implementation(libs.kotest.runner.junit5)
}
}
}
Expand Down
23 changes: 10 additions & 13 deletions bip39-lib/gradle.lockfile
Original file line number Diff line number Diff line change
Expand Up @@ -12,32 +12,30 @@ com.fasterxml.woodstox:woodstox-core:6.2.4=dokkaGfmPartialRuntime,dokkaGfmRuntim
com.github.ajalt:colormath:1.2.0=jvmTestCompileClasspath,jvmTestRuntimeClasspath
com.github.ajalt:mordant:1.2.1=jvmTestCompileClasspath,jvmTestRuntimeClasspath
com.github.mifmif:generex:1.0.2=jvmTestRuntimeClasspath
com.squareup.moshi:moshi-kotlin:1.9.2=jvmTestCompileClasspath,jvmTestImplementationDependenciesMetadata,jvmTestRuntimeClasspath
com.squareup.moshi:moshi:1.9.2=jvmTestCompileClasspath,jvmTestImplementationDependenciesMetadata,jvmTestRuntimeClasspath
com.squareup.okio:okio:1.16.0=jvmTestCompileClasspath,jvmTestImplementationDependenciesMetadata,jvmTestRuntimeClasspath
commons-io:commons-io:2.6=jvmTestRuntimeClasspath
dk.brics.automaton:automaton:1.11-8=jvmTestRuntimeClasspath
io.github.classgraph:classgraph:4.8.105=jvmTestCompileClasspath,jvmTestRuntimeClasspath
io.github.java-diff-utils:java-diff-utils:4.9=jvmTestRuntimeClasspath
io.kotest:kotest-assertions-api-jvm:4.6.1=jvmTestCompileClasspath,jvmTestRuntimeClasspath
io.kotest:kotest-assertions-api:4.6.1=jvmTestCompileClasspath,jvmTestImplementationDependenciesMetadata,jvmTestRuntimeClasspath
io.kotest:kotest-assertions-core-jvm:4.6.1=jvmTestCompileClasspath,jvmTestImplementationDependenciesMetadata,jvmTestRuntimeClasspath
io.kotest:kotest-assertions-core:4.6.1=jvmTestCompileClasspath,jvmTestImplementationDependenciesMetadata,jvmTestRuntimeClasspath
io.kotest:kotest-assertions-api:4.6.1=commonTestImplementationDependenciesMetadata,jvmTestCompileClasspath,jvmTestImplementationDependenciesMetadata,jvmTestRuntimeClasspath
io.kotest:kotest-assertions-core-jvm:4.6.1=jvmTestCompileClasspath,jvmTestRuntimeClasspath
io.kotest:kotest-assertions-core:4.6.1=commonTestImplementationDependenciesMetadata,jvmTestCompileClasspath,jvmTestImplementationDependenciesMetadata,jvmTestRuntimeClasspath
io.kotest:kotest-assertions-shared-jvm:4.6.1=jvmTestCompileClasspath,jvmTestRuntimeClasspath
io.kotest:kotest-assertions-shared:4.6.1=jvmTestCompileClasspath,jvmTestImplementationDependenciesMetadata,jvmTestRuntimeClasspath
io.kotest:kotest-assertions-shared:4.6.1=commonTestImplementationDependenciesMetadata,jvmTestCompileClasspath,jvmTestImplementationDependenciesMetadata,jvmTestRuntimeClasspath
io.kotest:kotest-common-jvm:4.6.1=jvmTestCompileClasspath,jvmTestRuntimeClasspath
io.kotest:kotest-common:4.6.1=jvmTestCompileClasspath,jvmTestImplementationDependenciesMetadata,jvmTestRuntimeClasspath
io.kotest:kotest-common:4.6.1=commonTestImplementationDependenciesMetadata,jvmTestCompileClasspath,jvmTestImplementationDependenciesMetadata,jvmTestRuntimeClasspath
io.kotest:kotest-extensions-jvm:4.6.1=jvmTestCompileClasspath,jvmTestRuntimeClasspath
io.kotest:kotest-extensions:4.6.1=jvmTestCompileClasspath,jvmTestImplementationDependenciesMetadata,jvmTestRuntimeClasspath
io.kotest:kotest-framework-api-jvm:4.6.1=jvmTestCompileClasspath,jvmTestRuntimeClasspath
io.kotest:kotest-framework-api:4.6.1=jvmTestCompileClasspath,jvmTestImplementationDependenciesMetadata,jvmTestRuntimeClasspath
io.kotest:kotest-framework-api:4.6.1=commonTestImplementationDependenciesMetadata,jvmTestCompileClasspath,jvmTestImplementationDependenciesMetadata,jvmTestRuntimeClasspath
io.kotest:kotest-framework-concurrency-jvm:4.6.1=jvmTestCompileClasspath,jvmTestRuntimeClasspath
io.kotest:kotest-framework-concurrency:4.6.1=jvmTestCompileClasspath,jvmTestImplementationDependenciesMetadata,jvmTestRuntimeClasspath
io.kotest:kotest-framework-discovery-jvm:4.6.1=jvmTestCompileClasspath,jvmTestRuntimeClasspath
io.kotest:kotest-framework-discovery:4.6.1=jvmTestCompileClasspath,jvmTestImplementationDependenciesMetadata,jvmTestRuntimeClasspath
io.kotest:kotest-framework-engine-jvm:4.6.1=jvmTestCompileClasspath,jvmTestRuntimeClasspath
io.kotest:kotest-framework-engine:4.6.1=jvmTestCompileClasspath,jvmTestImplementationDependenciesMetadata,jvmTestRuntimeClasspath
io.kotest:kotest-property-jvm:4.6.1=jvmTestCompileClasspath,jvmTestImplementationDependenciesMetadata,jvmTestRuntimeClasspath
io.kotest:kotest-framework-engine:4.6.1=commonTestImplementationDependenciesMetadata,jvmTestCompileClasspath,jvmTestImplementationDependenciesMetadata,jvmTestRuntimeClasspath
io.kotest:kotest-property-jvm:4.6.1=jvmTestCompileClasspath,jvmTestRuntimeClasspath
io.kotest:kotest-property:4.6.1=commonTestImplementationDependenciesMetadata,jvmTestCompileClasspath,jvmTestImplementationDependenciesMetadata,jvmTestRuntimeClasspath
io.kotest:kotest-runner-junit5-jvm:4.6.1=jvmTestCompileClasspath,jvmTestImplementationDependenciesMetadata,jvmTestRuntimeClasspath
io.mockk:mockk-agent-api:1.9.3=jvmTestRuntimeClasspath
io.mockk:mockk-agent-common:1.9.3=jvmTestRuntimeClasspath
Expand Down Expand Up @@ -65,8 +63,7 @@ org.jetbrains.kotlin:kotlin-compiler-embeddable:1.7.10=kotlinCompilerClasspath,k
org.jetbrains.kotlin:kotlin-daemon-client:1.5.0=jvmTestRuntimeClasspath
org.jetbrains.kotlin:kotlin-daemon-embeddable:1.7.10=kotlinCompilerClasspath,kotlinKlibCommonizerClasspath
org.jetbrains.kotlin:kotlin-klib-commonizer-embeddable:1.7.10=kotlinKlibCommonizerClasspath
org.jetbrains.kotlin:kotlin-reflect:1.3.50=jvmTestCompileClasspath
org.jetbrains.kotlin:kotlin-reflect:1.5.0=jvmTestImplementationDependenciesMetadata,jvmTestRuntimeClasspath
org.jetbrains.kotlin:kotlin-reflect:1.5.0=jvmTestRuntimeClasspath
org.jetbrains.kotlin:kotlin-reflect:1.7.10=dokkaGfmPartialPlugin,dokkaGfmPartialRuntime,dokkaGfmPlugin,dokkaGfmRuntime,dokkaHtmlPartialPlugin,dokkaHtmlPartialRuntime,dokkaHtmlPlugin,dokkaHtmlRuntime,dokkaJavadocPartialPlugin,dokkaJavadocPartialRuntime,dokkaJavadocPlugin,dokkaJavadocRuntime,dokkaJekyllPartialPlugin,dokkaJekyllPartialRuntime,dokkaJekyllPlugin,dokkaJekyllRuntime,kotlinCompilerClasspath,kotlinKlibCommonizerClasspath
org.jetbrains.kotlin:kotlin-script-runtime:1.5.0=jvmTestCompileClasspath,jvmTestRuntimeClasspath
org.jetbrains.kotlin:kotlin-script-runtime:1.7.10=kotlinCompilerClasspath,kotlinCompilerPluginClasspathJvmMain,kotlinCompilerPluginClasspathJvmTest,kotlinCompilerPluginClasspathMetadataCommonMain,kotlinCompilerPluginClasspathMetadataMain,kotlinKlibCommonizerClasspath
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
package cash.z.ecc.android.bip39

import cash.z.ecc.android.bip39.Mnemonics.MnemonicCode
import com.squareup.moshi.Json
import com.squareup.moshi.JsonClass
import com.squareup.moshi.Moshi
import com.squareup.moshi.kotlin.reflect.KotlinJsonAdapterFactory
import cash.z.ecc.android.bip39.utils.englishTestData
import cash.z.ecc.android.bip39.utils.fromHex
import cash.z.ecc.android.bip39.utils.swap
import cash.z.ecc.android.bip39.utils.toHex
import io.kotest.assertions.asClue
import io.kotest.assertions.throwables.shouldNotThrowAny
import io.kotest.assertions.throwables.shouldThrow
Expand All @@ -14,13 +14,12 @@ import io.kotest.data.row
import io.kotest.matchers.collections.shouldContainAll
import io.kotest.matchers.shouldBe
import io.kotest.matchers.shouldNotBe
import okio.Okio
import java.io.File
import java.util.*

private const val DEFAULT_LANGUAGE_CODE = "en"

class MnemonicsTest : BehaviorSpec({
val validPhrase = "void come effort suffer camp survey warrior heavy shoot primary clutch crush open amazing screen patrol group space point ten exist slush involve unfold"
val lang = Locale.ENGLISH.language
val validPhrase =
"void come effort suffer camp survey warrior heavy shoot primary clutch crush open amazing screen patrol group space point ten exist slush involve unfold"

Given("a valid, known mnemonic phrase") {
When("it is converted into a seed") {
Expand Down Expand Up @@ -97,10 +96,26 @@ class MnemonicsTest : BehaviorSpec({
When("it is converted to a mnemonic phrase") {
Then("it should match the expected phrase") {
forAll(
row(24, "b893a6b0da8fc9b73d709bda939e818a677aa376c266949378300b65a34b8e52", "review outdoor promote relax wish swear volume beach surround ostrich parrot below jeans faculty swallow error nest orange army bitter focus place deer fat"),
row(18, "d5bcbf62dea1a07ab1abb0144b299300137168a7939f3071f112b557", "stick tourist suffer run borrow diary shop invite begin flock gospel ability damage reform oxygen initial corn moon dwarf height image"),
row(15, "e06ce21369dc09eb2bda66510a76f65ab3f947cce90fcb10", "there grow luggage squirrel scene void quarter error extra father rural rely display physical crisp capable slam lumber"),
row(12, "0b01c3c0b0590faf45fc171da17cfb22", "arch asthma usual gaze movie stumble blood load buffalo armor disagree earth")
row(
24,
"b893a6b0da8fc9b73d709bda939e818a677aa376c266949378300b65a34b8e52",
"review outdoor promote relax wish swear volume beach surround ostrich parrot below jeans faculty swallow error nest orange army bitter focus place deer fat"
),
row(
18,
"d5bcbf62dea1a07ab1abb0144b299300137168a7939f3071f112b557",
"stick tourist suffer run borrow diary shop invite begin flock gospel ability damage reform oxygen initial corn moon dwarf height image"
),
row(
15,
"e06ce21369dc09eb2bda66510a76f65ab3f947cce90fcb10",
"there grow luggage squirrel scene void quarter error extra father rural rely display physical crisp capable slam lumber"
),
row(
12,
"0b01c3c0b0590faf45fc171da17cfb22",
"arch asthma usual gaze movie stumble blood load buffalo armor disagree earth"
)
) { _, entropy, mnemonic ->
val code = MnemonicCode(entropy.fromHex())
String(code.chars) shouldBe mnemonic
Expand All @@ -111,11 +126,9 @@ class MnemonicsTest : BehaviorSpec({

// uses test values from the original BIP : https://github.com/trezor/python-mnemonic/blob/master/vectors.json
Given("The original BIP-0039 test data set") {
val testData: TestDataSet? = loadTestData()
testData shouldNotBe null
When("each provided entropy is converted to a mnemonic phrase [entropy -> mnemonic]") {
Then("each result matches the corresponding test mnemonic phrase") {
testData!!.values.forEach {
englishTestData.forEach {
val entropy = it[0].fromHex()
val mnemonic = it[1]
String(MnemonicCode(entropy).chars) shouldBe mnemonic
Expand All @@ -124,7 +137,7 @@ class MnemonicsTest : BehaviorSpec({
}
When("each provided mnemonic phrase is reverted to entropy [mnemonic -> entropy]") {
Then("each result matches the corresponding test entropy") {
testData!!.values.forEach {
englishTestData.forEach {
val entropy = it[0]
val mnemonic = it[1]
MnemonicCode(mnemonic).toEntropy().toHex() shouldBe entropy
Expand All @@ -133,11 +146,11 @@ class MnemonicsTest : BehaviorSpec({
}
When("each provided mnemonic phrase is converted into a seed [mnemonic -> seed]") {
Then("each result matches the corresponding test seed") {
testData!!.values.forEach {
englishTestData.forEach {
val mnemonic = it[1].toCharArray()
val seed = it[2]
val passphrase = "TREZOR".toCharArray()
MnemonicCode(mnemonic, lang).toSeed(passphrase).toHex() shouldBe seed
MnemonicCode(mnemonic, DEFAULT_LANGUAGE_CODE).toSeed(passphrase).toHex() shouldBe seed
}
}
}
Expand Down Expand Up @@ -215,53 +228,3 @@ class MnemonicsTest : BehaviorSpec({
}
}
})

//
// Test Utilities
//

@JsonClass(generateAdapter = true)
data class TestDataSet(
@Json(name = "english") val values: List<List<String>>
)

fun ByteArray.toHex(): String {
val sb = StringBuilder(size * 2)
for (b in this)
sb.append(String.format("%02x", b))
return sb.toString()
}

fun String.fromHex(): ByteArray {
val len = length
val data = ByteArray(len / 2)
var i = 0
while (i < len) {
data[i / 2] =
((Character.digit(this[i], 16) shl 4) + Character.digit(this[i + 1], 16)).toByte()
i += 2
}
return data
}

fun String.swap(srcWord: Int, destWord: Int = srcWord + 1): String {
if (srcWord >= destWord) throw IllegalArgumentException("srcWord must be less than destWord")
if (destWord > count { it == ' ' }) throw IllegalArgumentException("there aren't that many words")
return split(' ').let { words ->
words.reduceIndexed { i, result, word ->
val next = when (i) {
srcWord -> words[destWord]
destWord -> words[srcWord]
else -> word
}
if (srcWord == 0 && i == 1) "${words[destWord]} $next" else "$result $next"
}
}
}

fun loadTestData(): TestDataSet? =
Okio.buffer(Okio.source(File("src/jvmTest/resources/data/BIP-0039-test-values.json")))
.use { dataFile ->
Moshi.Builder().add(KotlinJsonAdapterFactory()).build()
.adapter(TestDataSet::class.java).fromJson(dataFile)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package cash.z.ecc.android.bip39

import cash.z.ecc.android.bip39.utils.fromHex
import cash.z.ecc.android.bip39.utils.toHex
import io.kotest.core.spec.style.ShouldSpec
import io.kotest.matchers.shouldBe

class UtilsTest : ShouldSpec({
should("convert ByteArray to hex String") {
val byteArray = byteArrayOf(-128, -16, 0, 16, 127)
byteArray.toHex() shouldBe "80f000107f"
}

should("convert hex String to ByteArray") {
val hexString = "80f000107f"
val expectedByteArray = byteArrayOf(-128, -16, 0, 16, 127)
hexString.fromHex() shouldBe expectedByteArray
}

should("return original value, when converting to hex and then from hex") {
val originalBytes = ByteArray(256) { (it - 128).toByte() }
val transformedBytes = originalBytes.toHex().fromHex()
transformedBytes shouldBe originalBytes
}

should("return original value, when converting from hex and then to hex") {
val originalHex = "0008101820283038404850586068707880889098a0a8b0b8c0c8d0d8e0e8f0f8"
val transformedHex = originalHex.fromHex().toHex()
transformedHex shouldBe originalHex
}
})
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package cash.z.ecc.android.bip39.utils

fun ByteArray.toHex(): String {
val sb = StringBuilder(size * 2)
for (b in this) {
val hexValue = b.let { if (it >= 0) it.toInt() else 256 + it }
.toString(16)
.let { if (it.length < 2) "0$it" else it }
sb.append(hexValue)
}
return sb.toString()
}

fun String.fromHex(): ByteArray {
val len = length
val data = ByteArray(len / 2)
var i = 0
while (i < len) {
data[i / 2] =
((this[i].digitToInt(16) shl 4) + this[i + 1].digitToInt(16)).toByte()
i += 2
}
return data
}

fun String.swap(srcWord: Int, destWord: Int = srcWord + 1): String {
if (srcWord >= destWord) throw IllegalArgumentException("srcWord must be less than destWord")
if (destWord > count { it == ' ' }) throw IllegalArgumentException("there aren't that many words")
return split(' ').let { words ->
words.reduceIndexed { i, result, word ->
val next = when (i) {
srcWord -> words[destWord]
destWord -> words[srcWord]
else -> word
}
if (srcWord == 0 && i == 1) "${words[destWord]} $next" else "$result $next"
}
}
}
Loading