SubwayTooter-Android-App/base/src/test/java/jp/juggler/BinPackTest.kt

170 lines
6.1 KiB
Kotlin

package jp.juggler
import jp.juggler.util.data.BinPackList
import jp.juggler.util.data.BinPackMap
import jp.juggler.util.data.decodeBinPack
import jp.juggler.util.data.encodeBinPack
import kotlin.test.DefaultAsserter.assertEquals
import kotlin.test.DefaultAsserter.assertNotNull
import kotlin.test.DefaultAsserter.assertTrue
import kotlin.test.Test
import kotlin.test.assertContentEquals
class BinPackTest {
@Test
fun testTypes() {
fun ByteArray.dump() = joinToString(" ") { "%d".format(it) }
fun encodeDecode(v: Any?, expected: Any? = v) {
val encoded = v.encodeBinPack()
val decoded = encoded.decodeBinPack()
val message = "($v ${v?.javaClass?.simpleName}) dump=${encoded.dump()}"
when {
expected is ByteArray -> assertContentEquals(
expected,
decoded as? ByteArray,
"${v?.javaClass?.simpleName} $v",
)
v is Set<*> -> {
val decodedSet = (decoded as? BinPackList)?.toSet()
assertNotNull("$message decoded?", decodedSet)
assertEquals("$message same size", v.size, decodedSet!!.size)
assertTrue("$message containsAll 1", v.containsAll(decodedSet))
assertTrue("$message containsAll 2", decodedSet.containsAll(v))
}
else -> assertEquals(
message,
expected,
decoded
)
}
}
encodeDecode(null)
encodeDecode(true)
encodeDecode(false)
encodeDecode(ByteArray(0))
encodeDecode(ByteArray(1) { it.toByte() })
encodeDecode(ByteArray(3) { it.toByte() })
encodeDecode("")
encodeDecode("日本語")
encodeDecode(emptyArray<Any?>(), BinPackList())
encodeDecode(emptyList<Any?>(), BinPackList())
encodeDecode(emptySet<Any?>(), BinPackList())
encodeDecode(arrayOf<Any?>(null), BinPackList(null))
encodeDecode(listOf<Any?>(null), BinPackList(null))
encodeDecode(setOf<Any?>(null))
encodeDecode(arrayOf("a"), BinPackList("a"))
encodeDecode(listOf("a"), BinPackList("a"))
encodeDecode(setOf("a"))
encodeDecode(emptyMap<Any?, Any?>(), BinPackMap())
encodeDecode(mapOf<Any?, Any?>(null to null), BinPackMap(null to null))
encodeDecode(mapOf<Any?, Any?>(1 to 1), BinPackMap(1 to 1))
fun doubleStepSequence(start: Double, endInclusive: Double, step: Double) =
sequence {
var v = start
while (true) {
yield(v)
val newValue = v + step
// 範囲を超えたか、オーバーフローで同じ値になるか
if (newValue > endInclusive || newValue == v) break
v = newValue
}
}
fun floatStepSequence(start: Float, endInclusive: Float, step: Float) =
sequence {
var v = start
while (true) {
yield(v)
val newValue = v + step
// 範囲を超えたか、オーバーフローで同じ値になるか
if (newValue > endInclusive || newValue == v) break
v = newValue
}
}
// - ビット数の多い数値型は適当に端折るが、下位ビットが毎回同じにならないよう stepを工夫する
encodeDecode(0.0)
encodeDecode(Double.NaN)
encodeDecode(Double.NEGATIVE_INFINITY)
encodeDecode(Double.POSITIVE_INFINITY)
encodeDecode(Double.MIN_VALUE) // nealy 0 positive value
encodeDecode(-Double.MAX_VALUE) // negative min end
encodeDecode(Double.MAX_VALUE)
run {
var callCount = 0
for (n in doubleStepSequence(
-Double.MAX_VALUE,
Double.MAX_VALUE,
Double.MAX_VALUE / (256 - 7 - Double.MIN_VALUE)
)) {
encodeDecode(n)
++callCount
}
assertEquals("callCount", 498, callCount)
}
encodeDecode(0f)
encodeDecode(Float.NaN)
encodeDecode(Float.NEGATIVE_INFINITY)
encodeDecode(Float.POSITIVE_INFINITY)
encodeDecode(Float.MIN_VALUE) // nealy 0 positive value
encodeDecode(-Float.MAX_VALUE) // negative min end
encodeDecode(Float.MAX_VALUE)
run {
var callCount = 0
for (n in floatStepSequence(
-Float.MAX_VALUE,
Float.MAX_VALUE,
Float.MAX_VALUE / (256 - 7 - Float.MIN_VALUE)
)) {
encodeDecode(n)
++callCount
}
assertEquals("callCount", 499, callCount)
}
// - ByteとShortにはIntRangeと同等のクラスがない
encodeDecode(0.toByte())
encodeDecode(Byte.MIN_VALUE)
encodeDecode(Byte.MAX_VALUE)
for (n in Byte.MIN_VALUE.toInt()..Byte.MAX_VALUE.toInt()) {
encodeDecode(n.toByte())
}
encodeDecode(0.toShort())
encodeDecode(Short.MIN_VALUE)
encodeDecode(Short.MAX_VALUE)
for (n in Short.MIN_VALUE.toInt()..Short.MAX_VALUE.toInt() step 1.shl(Short.SIZE_BITS - 8) - 7) {
encodeDecode(n.toShort())
}
encodeDecode(0.toChar())
encodeDecode(Char.MIN_VALUE)
encodeDecode(Char.MAX_VALUE)
for (n in Char.MIN_VALUE..Char.MAX_VALUE step 1.shl(Char.SIZE_BITS - 8) - 7) {
encodeDecode(n)
}
encodeDecode(0)
encodeDecode(Int.MIN_VALUE)
encodeDecode(Int.MAX_VALUE)
for (n in Int.MIN_VALUE..Int.MAX_VALUE step 1.shl(Int.SIZE_BITS - 8) - 7) {
encodeDecode(n)
}
encodeDecode(0.toLong())
encodeDecode(Long.MIN_VALUE)
encodeDecode(Long.MAX_VALUE)
for (n in Long.MIN_VALUE..Long.MAX_VALUE step 1L.shl(Long.SIZE_BITS - 8) - 7) {
encodeDecode(n)
}
}
}