2019-12-18 08:09:13 -08:00
|
|
|
package cash.z.ecc.android.integration
|
|
|
|
|
|
|
|
import android.content.Context
|
|
|
|
import androidx.test.ext.junit.runners.AndroidJUnit4
|
|
|
|
import androidx.test.platform.app.InstrumentationRegistry
|
2019-12-23 11:21:38 -08:00
|
|
|
import cash.z.ecc.android.lockbox.LockBox
|
|
|
|
import cash.z.ecc.kotlin.mnemonic.Mnemonics
|
2020-06-10 04:49:38 -07:00
|
|
|
import cash.z.ecc.android.sdk.Initializer
|
2021-04-21 15:04:50 -07:00
|
|
|
import cash.z.ecc.android.sdk.type.ZcashNetwork
|
2019-12-23 11:21:38 -08:00
|
|
|
import okio.Buffer
|
|
|
|
import okio.GzipSink
|
|
|
|
import okio.Okio
|
|
|
|
import org.junit.Assert.assertEquals
|
|
|
|
import org.junit.Assert.assertTrue
|
2019-12-18 08:09:13 -08:00
|
|
|
import org.junit.Before
|
2019-12-23 11:21:38 -08:00
|
|
|
import org.junit.Test
|
2019-12-18 08:09:13 -08:00
|
|
|
import org.junit.runner.RunWith
|
|
|
|
|
|
|
|
@RunWith(AndroidJUnit4::class)
|
|
|
|
class IntegrationTest {
|
|
|
|
|
|
|
|
private lateinit var appContext: Context
|
2021-04-21 15:04:50 -07:00
|
|
|
private val network = ZcashNetwork.Testnet
|
2019-12-23 11:21:38 -08:00
|
|
|
private val mnemonics = Mnemonics()
|
|
|
|
private val phrase =
|
|
|
|
"human pulse approve subway climb stairs mind gentle raccoon warfare fog roast sponsor" +
|
|
|
|
" under absorb spirit hurdle animal original honey owner upper empower describe"
|
2019-12-18 08:09:13 -08:00
|
|
|
|
|
|
|
@Before
|
|
|
|
fun start() {
|
|
|
|
appContext = InstrumentationRegistry.getInstrumentation().targetContext
|
|
|
|
}
|
2019-12-23 11:21:38 -08:00
|
|
|
|
|
|
|
@Test
|
|
|
|
fun testSeed_generation() {
|
|
|
|
val seed = mnemonics.toSeed(phrase.toCharArray())
|
|
|
|
assertEquals(
|
|
|
|
"Generated incorrect BIP-39 seed!",
|
|
|
|
"f4e3d38d9c244da7d0407e19a93c80429614ee82dcf62c141235751c9f1228905d12a1f275f" +
|
|
|
|
"5c22f6fb7fcd9e0a97f1676e0eec53fdeeeafe8ce8aa39639b9fe",
|
|
|
|
seed.toHex()
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
|
|
|
@Test
|
|
|
|
fun testSeed_storage() {
|
|
|
|
val seed = mnemonics.toSeed(phrase.toCharArray())
|
|
|
|
val lb = LockBox(appContext)
|
|
|
|
lb.setBytes("seed", seed)
|
|
|
|
assertTrue(seed.contentEquals(lb.getBytes("seed")!!))
|
|
|
|
}
|
|
|
|
|
|
|
|
@Test
|
|
|
|
fun testPhrase_storage() {
|
|
|
|
val lb = LockBox(appContext)
|
|
|
|
val phraseChars = phrase.toCharArray()
|
|
|
|
lb.setCharsUtf8("phrase", phraseChars)
|
|
|
|
assertTrue(phraseChars.contentEquals(lb.getCharsUtf8("phrase")!!))
|
|
|
|
}
|
|
|
|
|
|
|
|
@Test
|
|
|
|
fun testPhrase_maxLengthStorage() {
|
|
|
|
val lb = LockBox(appContext)
|
|
|
|
// find and expose the max length
|
|
|
|
var acceptedSize = 256
|
|
|
|
while (acceptedSize > 0) {
|
|
|
|
try {
|
|
|
|
lb.setCharsUtf8("temp", nextString(acceptedSize).toCharArray())
|
|
|
|
break
|
|
|
|
} catch (t: Throwable) {
|
|
|
|
}
|
|
|
|
acceptedSize--
|
|
|
|
}
|
|
|
|
|
|
|
|
val maxSeedPhraseLength = 8 * 24 + 23 //215 (max length of each word is 8)
|
|
|
|
assertTrue(
|
|
|
|
"LockBox does not support the maximum length seed phrase." +
|
|
|
|
" Expected: $maxSeedPhraseLength but was: $acceptedSize",
|
|
|
|
acceptedSize > maxSeedPhraseLength
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
|
|
|
@Test
|
|
|
|
fun testAddress() {
|
|
|
|
val seed = mnemonics.toSeed(phrase.toCharArray())
|
2020-10-07 17:10:45 -07:00
|
|
|
val initializer = Initializer(appContext) { config ->
|
2021-04-21 15:04:50 -07:00
|
|
|
config.newWallet(seed, network)
|
2019-12-23 11:21:38 -08:00
|
|
|
}
|
|
|
|
assertEquals(
|
|
|
|
"Generated incorrect z-address!",
|
|
|
|
"zs1gn2ah0zqhsxnrqwuvwmgxpl5h3ha033qexhsz8tems53fw877f4gug353eefd6z8z3n4zxty65c",
|
2021-04-21 15:04:50 -07:00
|
|
|
initializer.rustBackend.getShieldedAddress()
|
2019-12-23 11:21:38 -08:00
|
|
|
)
|
2021-04-21 15:04:50 -07:00
|
|
|
initializer.erase()
|
2019-12-23 11:21:38 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private fun ByteArray.toHex(): String {
|
|
|
|
val sb = StringBuilder(size * 2)
|
|
|
|
for (b in this)
|
|
|
|
sb.append(String.format("%02x", b))
|
|
|
|
return sb.toString()
|
|
|
|
}
|
|
|
|
|
|
|
|
fun String.gzip(): ByteArray {
|
|
|
|
val result = Buffer()
|
|
|
|
val sink = Okio.buffer(GzipSink(result))
|
|
|
|
sink.use {
|
|
|
|
sink.write(toByteArray())
|
|
|
|
}
|
|
|
|
return result.readByteArray()
|
|
|
|
}
|
|
|
|
|
|
|
|
fun nextString(length: Int): String {
|
|
|
|
val allowedChars = "ACGT"
|
|
|
|
return (1..length)
|
|
|
|
.map { allowedChars.random() }
|
|
|
|
.joinToString("")
|
|
|
|
}
|
2019-12-18 08:09:13 -08:00
|
|
|
}
|