Skip to content

Commit 735562e

Browse files
committed
test(opencode): add tests for Fiat, VersionedMessage, instructions, and utilities
- Fiat: construction, arithmetic, comparison, rounding, currency conversion - VersionedMessageV0: encoding structure, determinism, size validation - CompiledInstruction: encode/fromList roundtrip, compile/decompile roundtrip - CurrencyCode: fractionDigits for all 8 special-cased currencies - Result extensions: filter and filterIsInstance - Double/String utils: roundTo, toLocaleAwareDoubleOrNull, padded - ProgramAddresses, SysVar, SodiumError, SwapMetadata
1 parent 5310020 commit 735562e

11 files changed

Lines changed: 1198 additions & 0 deletions

File tree

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
package com.getcode.opencode.internal.extensions
2+
3+
import com.getcode.opencode.model.financial.CurrencyCode
4+
import kotlin.test.Test
5+
import kotlin.test.assertEquals
6+
7+
class CurrencyCodeExtensionsTest {
8+
9+
@Test
10+
fun afnHasZeroFractionDigits() {
11+
assertEquals(0, CurrencyCode.AFN.fractionDigits)
12+
}
13+
14+
@Test
15+
fun copHasZeroFractionDigits() {
16+
assertEquals(0, CurrencyCode.COP.fractionDigits)
17+
}
18+
19+
@Test
20+
fun idrHasZeroFractionDigits() {
21+
assertEquals(0, CurrencyCode.IDR.fractionDigits)
22+
}
23+
24+
@Test
25+
fun irrHasZeroFractionDigits() {
26+
assertEquals(0, CurrencyCode.IRR.fractionDigits)
27+
}
28+
29+
@Test
30+
fun mgaHasZeroFractionDigits() {
31+
assertEquals(0, CurrencyCode.MGA.fractionDigits)
32+
}
33+
34+
@Test
35+
fun mruHasZeroFractionDigits() {
36+
assertEquals(0, CurrencyCode.MRU.fractionDigits)
37+
}
38+
39+
@Test
40+
fun tzsHasZeroFractionDigits() {
41+
assertEquals(0, CurrencyCode.TZS.fractionDigits)
42+
}
43+
44+
@Test
45+
fun uyuHasZeroFractionDigits() {
46+
assertEquals(0, CurrencyCode.UYU.fractionDigits)
47+
}
48+
49+
@Test
50+
fun usdHasTwoFractionDigits() {
51+
assertEquals(2, CurrencyCode.USD.fractionDigits)
52+
}
53+
54+
@Test
55+
fun eurHasTwoFractionDigits() {
56+
assertEquals(2, CurrencyCode.EUR.fractionDigits)
57+
}
58+
59+
@Test
60+
fun jpyHasZeroFractionDigits() {
61+
assertEquals(0, CurrencyCode.JPY.fractionDigits)
62+
}
63+
64+
@Test
65+
fun kwdHasThreeFractionDigits() {
66+
assertEquals(3, CurrencyCode.KWD.fractionDigits)
67+
}
68+
69+
@Test
70+
fun gbpHasTwoFractionDigits() {
71+
assertEquals(2, CurrencyCode.GBP.fractionDigits)
72+
}
73+
}
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
package com.getcode.opencode.internal.extensions
2+
3+
import kotlin.test.Test
4+
import kotlin.test.assertEquals
5+
import kotlin.test.assertTrue
6+
7+
class ResultExtensionsTest {
8+
9+
// --- filter ---
10+
11+
@Test
12+
fun filterPassingPredicateReturnsSuccess() {
13+
val result = Result.success(42).filter { it > 0 }
14+
assertEquals(42, result.getOrThrow())
15+
}
16+
17+
@Test
18+
fun filterFailingPredicateReturnsFailure() {
19+
val result = Result.success(42).filter { it > 100 }
20+
assertTrue(result.isFailure)
21+
}
22+
23+
@Test
24+
fun filterOnFailurePropagatesFailure() {
25+
val original = Result.failure<Int>(IllegalStateException("boom"))
26+
val result = original.filter { true }
27+
assertTrue(result.isFailure)
28+
assertTrue(result.exceptionOrNull() is IllegalStateException)
29+
}
30+
31+
// --- filterIsInstance ---
32+
33+
@Test
34+
fun filterIsInstanceMatchingTypeReturnsSuccess() {
35+
val result: Result<Any> = Result.success("hello")
36+
val filtered = result.filterIsInstance<String>()
37+
assertEquals("hello", filtered.getOrThrow())
38+
}
39+
40+
@Test
41+
fun filterIsInstanceNonMatchingTypeReturnsFailure() {
42+
val result: Result<Any> = Result.success(42)
43+
val filtered = result.filterIsInstance<String>()
44+
assertTrue(filtered.isFailure)
45+
}
46+
47+
@Test
48+
fun filterIsInstanceOnFailurePropagatesException() {
49+
val original = Result.failure<Any>(IllegalArgumentException("bad"))
50+
val filtered = original.filterIsInstance<String>()
51+
assertTrue(filtered.isFailure)
52+
assertTrue(filtered.exceptionOrNull() is IllegalArgumentException)
53+
}
54+
55+
@Test
56+
fun filterIsInstanceSubtype() {
57+
val result: Result<Any> = Result.success(RuntimeException("test"))
58+
val filtered = result.filterIsInstance<Exception>()
59+
assertTrue(filtered.isSuccess)
60+
}
61+
}
Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
1+
package com.getcode.opencode.internal.solana.programs
2+
3+
import com.getcode.solana.keys.LENGTH_32
4+
import com.getcode.solana.keys.base58
5+
import kotlin.test.Test
6+
import kotlin.test.assertEquals
7+
import kotlin.test.assertTrue
8+
9+
class ProgramAddressesTest {
10+
11+
@Test
12+
fun `ComputeBudgetProgram address is correct`() {
13+
assertEquals(
14+
"ComputeBudget111111111111111111111111111111",
15+
ComputeBudgetProgram.address.base58()
16+
)
17+
}
18+
19+
@Test
20+
fun `AssociatedTokenProgram address is correct`() {
21+
assertEquals(
22+
"ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL",
23+
AssociatedTokenProgram.address.base58()
24+
)
25+
}
26+
27+
@Test
28+
fun `MemoProgram address is correct`() {
29+
assertEquals(
30+
"Memo1UhkJRfHyvLMcVucJwxXeuD728EqVDDwQDxFMNo",
31+
MemoProgram.address.base58()
32+
)
33+
}
34+
35+
@Test
36+
fun `SystemProgram address is all zeros`() {
37+
val bytes = SystemProgram.address.bytes
38+
assertEquals(LENGTH_32, bytes.size)
39+
assertTrue(bytes.all { it == 0.toByte() })
40+
}
41+
42+
@Test
43+
fun `TimelockProgram address is correct`() {
44+
assertEquals(
45+
"time2Z2SCnn3qYg3ULKVtdkh8YmZ5jFdKicnA1W2YnJ",
46+
TimelockProgram.address.base58()
47+
)
48+
}
49+
50+
@Test
51+
fun `TimelockProgram legacyAddress is correct`() {
52+
assertEquals(
53+
"timeDBoQGL52du9K7EtrhkJSqpiFapE9dHrmDVkuZx6",
54+
TimelockProgram.legacyAddress.base58()
55+
)
56+
}
57+
58+
@Test
59+
fun `SwapValidatorProgram address is correct`() {
60+
assertEquals(
61+
"sWvA66HNNvgamibZe88v3NN5nQwE8tp3KitfViFjukA",
62+
SwapValidatorProgram.address.base58()
63+
)
64+
}
65+
66+
@Test
67+
fun `TokenProgram address is correct`() {
68+
assertEquals(
69+
"TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA",
70+
TokenProgram.address.base58()
71+
)
72+
}
73+
74+
@Test
75+
fun `CurrencyCreatorProgram address is correct`() {
76+
assertEquals(
77+
"ccJYP5gjZqcEHaphcxAZvkxCrnTVfYMjyhSYkpQtf8Z",
78+
CurrencyCreatorProgram.address.base58()
79+
)
80+
}
81+
82+
@Test
83+
fun `UsdfProgram address is correct`() {
84+
assertEquals(
85+
"usdfcP2V1bh1Lz7Y87pxR4zJd3wnVtssJ6GeSHFeZeu",
86+
UsdfProgram.address.base58()
87+
)
88+
}
89+
90+
@Test
91+
fun `VirtualMachineProgram address is correct`() {
92+
assertEquals(
93+
"vmZ1WUq8SxjBWcaeTCvgJRZbS84R61uniFsQy5YMRTJ",
94+
VirtualMachineProgram.address.base58()
95+
)
96+
}
97+
98+
// Command enum entry counts
99+
100+
@Test
101+
fun `ComputeBudgetProgram Command has 4 entries`() {
102+
assertEquals(4, ComputeBudgetProgram.Command.entries.size)
103+
}
104+
105+
@Test
106+
fun `TokenProgram Command has 2 entries with correct values`() {
107+
val entries = TokenProgram.Command.entries
108+
assertEquals(2, entries.size)
109+
assertEquals(3.toByte(), TokenProgram.Command.transfer.value)
110+
assertEquals(9.toByte(), TokenProgram.Command.closeAccount.value)
111+
}
112+
113+
@Test
114+
fun `SystemProgram Command has 12 entries`() {
115+
assertEquals(12, SystemProgram.Command.entries.size)
116+
}
117+
118+
@Test
119+
fun `CurrencyCreatorProgram Command has 5 entries`() {
120+
assertEquals(5, CurrencyCreatorProgram.Command.entries.size)
121+
}
122+
123+
@Test
124+
fun `UsdfProgram Command has 2 entries with correct values`() {
125+
val entries = UsdfProgram.Command.entries
126+
assertEquals(2, entries.size)
127+
assertEquals(2.toByte(), UsdfProgram.Command.swap.value)
128+
assertEquals(3.toByte(), UsdfProgram.Command.transfer.value)
129+
}
130+
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
package com.getcode.opencode.internal.solana.programs
2+
3+
import com.getcode.solana.keys.LENGTH_32
4+
import kotlin.test.Test
5+
import kotlin.test.assertEquals
6+
7+
class SysVarTest {
8+
9+
@Test
10+
fun `SysVar enum has 9 entries`() {
11+
assertEquals(9, SysVar.entries.size)
12+
}
13+
14+
@Test
15+
fun `SysVar rent address is a valid 32-byte PublicKey`() {
16+
val address = SysVar.rent.address()
17+
assertEquals(LENGTH_32, address.bytes.size)
18+
}
19+
20+
@Test
21+
fun `SysVar clock address is a valid 32-byte PublicKey`() {
22+
val address = SysVar.clock.address()
23+
assertEquals(LENGTH_32, address.bytes.size)
24+
}
25+
}
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
package com.getcode.opencode.model.core.errors
2+
3+
import kotlin.test.Test
4+
import kotlin.test.assertIs
5+
import kotlin.test.assertNull
6+
import kotlin.test.assertSame
7+
8+
class SodiumErrorTest {
9+
10+
@Test
11+
fun `ConversionToCurveFailed is a Throwable`() {
12+
val error = SodiumError.ConversionToCurveFailed()
13+
assertIs<Throwable>(error)
14+
}
15+
16+
@Test
17+
fun `SharedKeyFailed is a Throwable`() {
18+
val error = SodiumError.SharedKeyFailed()
19+
assertIs<Throwable>(error)
20+
}
21+
22+
@Test
23+
fun `EncryptionFailed is a Throwable`() {
24+
val error = SodiumError.EncryptionFailed()
25+
assertIs<Throwable>(error)
26+
}
27+
28+
@Test
29+
fun `DecryptionFailed is a Throwable`() {
30+
val error = SodiumError.DecryptionFailed()
31+
assertIs<Throwable>(error)
32+
}
33+
34+
@Test
35+
fun `cause is propagated for ConversionToCurveFailed`() {
36+
val root = RuntimeException("test")
37+
val error = SodiumError.ConversionToCurveFailed(root)
38+
assertSame(root, error.cause)
39+
}
40+
41+
@Test
42+
fun `cause is propagated for SharedKeyFailed`() {
43+
val root = RuntimeException("test")
44+
val error = SodiumError.SharedKeyFailed(root)
45+
assertSame(root, error.cause)
46+
}
47+
48+
@Test
49+
fun `cause is propagated for EncryptionFailed`() {
50+
val root = RuntimeException("test")
51+
val error = SodiumError.EncryptionFailed(root)
52+
assertSame(root, error.cause)
53+
}
54+
55+
@Test
56+
fun `cause is propagated for DecryptionFailed`() {
57+
val root = RuntimeException("test")
58+
val error = SodiumError.DecryptionFailed(root)
59+
assertSame(root, error.cause)
60+
}
61+
62+
@Test
63+
fun `null cause works for all error types`() {
64+
assertNull(SodiumError.ConversionToCurveFailed().cause)
65+
assertNull(SodiumError.SharedKeyFailed().cause)
66+
assertNull(SodiumError.EncryptionFailed().cause)
67+
assertNull(SodiumError.DecryptionFailed().cause)
68+
}
69+
}

0 commit comments

Comments
 (0)