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 {
|
||||
fun fromString(input: String): ActivationCode {
|
||||
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")
|
||||
}
|
||||
return ActivationCode(
|
||||
address = components[1].trim(),
|
||||
matchingId = components.getOrNull(2)?.trim()?.ifBlank { null },
|
||||
oid = components.getOrNull(3)?.trim()?.ifBlank { null },
|
||||
confirmationCodeRequired = components.getOrNull(4)?.trim() == "1"
|
||||
components[1]!!,
|
||||
components.getOrNull(2),
|
||||
components.getOrNull(3),
|
||||
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