chore: improve activation code parsing robustness #143
2 changed files with 88 additions and 5 deletions
|
@ -9,15 +9,27 @@ data class ActivationCode(
|
||||||
companion object {
|
companion object {
|
||||||
fun fromString(input: String): ActivationCode {
|
fun fromString(input: String): ActivationCode {
|
||||||
val components = input.removePrefix("LPA:").split('$')
|
val components = input.removePrefix("LPA:").split('$')
|
||||||
if (components.size < 2 || components[0] != "1") {
|
.map { it.trim().ifEmpty { null } }
|
||||||
|
if (components.size < 2 || components[0] != "1" || components[1].isNullOrEmpty()) {
|
||||||
throw IllegalArgumentException("Invalid activation code format")
|
throw IllegalArgumentException("Invalid activation code format")
|
||||||
}
|
}
|
||||||
return ActivationCode(
|
return ActivationCode(
|
||||||
address = components[1].trim(),
|
components[1]!!,
|
||||||
matchingId = components.getOrNull(2)?.trim()?.ifBlank { null },
|
components.getOrNull(2),
|
||||||
oid = components.getOrNull(3)?.trim()?.ifBlank { null },
|
components.getOrNull(3),
|
||||||
confirmationCodeRequired = components.getOrNull(4)?.trim() == "1"
|
components.getOrNull(4) == "1"
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun toString(): String {
|
||||||
|
val parts = buildList {
|
||||||
|
add("1")
|
||||||
|
add(address)
|
||||||
|
add(matchingId ?: "")
|
||||||
|
add(oid ?: "")
|
||||||
|
add(if (confirmationCodeRequired) "1" else "")
|
||||||
|
}
|
||||||
|
return parts.joinToString("$").trimEnd('$')
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -0,0 +1,71 @@
|
||||||
|
package im.angry.openeuicc.util
|
||||||
|
|
||||||
|
import org.junit.Assert.assertEquals
|
||||||
|
import org.junit.Assert.assertThrows
|
||||||
|
import org.junit.Assert.assertTrue
|
||||||
|
import org.junit.Test
|
||||||
|
|
||||||
|
class ActivationCodeTest {
|
||||||
|
/**
|
||||||
|
* @see {https://www.gsma.com/esim/wp-content/uploads/2020/06/SGP.22-v2.2.2.pdf#page=112}
|
||||||
|
*/
|
||||||
|
@Suppress("SpellCheckingInspection")
|
||||||
|
private val expectedFixtures = mapOf(
|
||||||
|
// if SM-DP+ OID and Confirmation Code Required Flag are not present
|
||||||
|
Pair(
|
||||||
|
"1\$SMDP.GSMA.COM\$04386-AGYFT-A74Y8-3F815",
|
||||||
|
ActivationCode("SMDP.GSMA.COM", "04386-AGYFT-A74Y8-3F815", null, false)
|
||||||
|
),
|
||||||
|
// if SM-DP+ OID is not present and Confirmation Code Required Flag is present
|
||||||
|
Pair(
|
||||||
|
"1\$SMDP.GSMA.COM\$04386-AGYFT-A74Y8-3F815\$\$1",
|
||||||
|
ActivationCode("SMDP.GSMA.COM", "04386-AGYFT-A74Y8-3F815", null, true)
|
||||||
|
),
|
||||||
|
// if SM-DP+ OID and Confirmation Code Required flag are present
|
||||||
|
Pair(
|
||||||
|
"1\$SMDP.GSMA.COM\$04386-AGYFT-A74Y8-3F815\$1.3.6.1.4.1.31746\$1",
|
||||||
|
ActivationCode("SMDP.GSMA.COM", "04386-AGYFT-A74Y8-3F815", "1.3.6.1.4.1.31746", true)
|
||||||
|
),
|
||||||
|
// if SM-DP+ OID is present and Confirmation Code Required Flag is not present
|
||||||
|
Pair(
|
||||||
|
"1\$SMDP.GSMA.COM\$04386-AGYFT-A74Y8-3F815\$1.3.6.1.4.1.31746",
|
||||||
|
ActivationCode("SMDP.GSMA.COM", "04386-AGYFT-A74Y8-3F815", "1.3.6.1.4.1.31746", false)
|
||||||
|
),
|
||||||
|
// if SM-DP+ OID is present, Activation token is left blank and Confirmation Code Required Flag is not present
|
||||||
|
Pair(
|
||||||
|
"1\$SMDP.GSMA.COM\$\$1.3.6.1.4.1.31746",
|
||||||
|
ActivationCode("SMDP.GSMA.COM", null, "1.3.6.1.4.1.31746", false)
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
@Suppress("SpellCheckingInspection")
|
||||||
|
private val unexpectedFixtures = listOf(
|
||||||
|
"", "LPA:",
|
||||||
|
"1", "LPA:1",
|
||||||
|
"1$", "LPA:1$",
|
||||||
|
"1$$", "LPA:1$$",
|
||||||
|
"2\$SMDP.GSMA.COM", "LPA:2\$SMDP.GSMA.COM",
|
||||||
|
)
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testParsing() {
|
||||||
|
for ((input, expected) in expectedFixtures) {
|
||||||
|
val actual = ActivationCode.fromString(input)
|
||||||
|
assertEquals(expected.address, actual.address)
|
||||||
|
assertEquals(expected.matchingId, actual.matchingId)
|
||||||
|
assertEquals(expected.oid, actual.oid)
|
||||||
|
assertEquals(expected.confirmationCodeRequired, actual.confirmationCodeRequired)
|
||||||
|
assertEquals(input, expected.toString())
|
||||||
|
assertTrue(expected == actual)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testUnexpected() {
|
||||||
|
for (fixture in unexpectedFixtures) {
|
||||||
|
assertThrows(IllegalArgumentException::class.java) {
|
||||||
|
ActivationCode.fromString(fixture)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Add table
Reference in a new issue