From 65b95acb554cb177cfe04d377074e0407f0a495d Mon Sep 17 00:00:00 2001 From: DualFroz Date: Thu, 10 Sep 2026 22:11:23 +0200 Subject: [PATCH] test(codec): cover ByteCursorTest --- .../kestrel/store/codec/ByteCursorTest.kt | 73 ++++++++++++++++++ .../kotlin/kestrel/store/codec/Crc32CTest.kt | 33 ++++++++ .../kestrel/store/codec/KeyCodecTest.kt | Bin 0 -> 6860 bytes 3 files changed, 106 insertions(+) create mode 100644 src/test/kotlin/kestrel/store/codec/ByteCursorTest.kt create mode 100644 src/test/kotlin/kestrel/store/codec/Crc32CTest.kt create mode 100644 src/test/kotlin/kestrel/store/codec/KeyCodecTest.kt diff --git a/src/test/kotlin/kestrel/store/codec/ByteCursorTest.kt b/src/test/kotlin/kestrel/store/codec/ByteCursorTest.kt new file mode 100644 index 0000000..26c43f1 --- /dev/null +++ b/src/test/kotlin/kestrel/store/codec/ByteCursorTest.kt @@ -0,0 +1,73 @@ +package kestrel.store.codec + +import kotlin.test.Test +import kotlin.test.assertEquals +import kotlin.test.assertFailsWith +import kotlin.test.assertFalse +import kotlin.test.assertTrue + +class ByteCursorTest { + @Test + fun writesAndReadsVarIntsAcrossByteBoundaries() { + val samples = listOf(0L, 1L, 127L, 128L, 300L, 16384L, Int.MAX_VALUE.toLong(), Long.MAX_VALUE) + val writer = ByteWriter() + for (sample in samples) writer.writeVarInt(sample) + val reader = ByteReader(writer.toByteArray()) + for (sample in samples) assertEquals(sample, reader.readVarInt()) + assertFalse(reader.hasRemaining()) + } + + @Test + fun zigZagRoundTripsNegativeAndPositiveValues() { + val samples = listOf(0L, -1L, 1L, -64L, 64L, Long.MIN_VALUE, Long.MAX_VALUE) + val writer = ByteWriter() + for (sample in samples) writer.writeZigZag(sample) + val reader = ByteReader(writer.toByteArray()) + for (sample in samples) assertEquals(sample, reader.readZigZag()) + } + + @Test + fun negativeNumbersUseFewerBytesThanUnsignedVarIntWouldViaZigZag() { + val writer = ByteWriter() + writer.writeZigZag(-1L) + assertEquals(1, writer.length) + } + + @Test + fun fixedWidthLongAndDoubleRoundTrip() { + val writer = ByteWriter() + writer.writeFixedLong(-42L) + writer.writeFixedDouble(3.14159) + val reader = ByteReader(writer.toByteArray()) + assertEquals(-42L, reader.readFixedLong()) + assertEquals(3.14159, reader.readFixedDouble()) + } + + @Test + fun lengthPrefixedBytesRoundTrip() { + val writer = ByteWriter() + writer.writeLengthPrefixed(byteArrayOf(1, 2, 3)) + writer.writeLengthPrefixed(ByteArray(0)) + writer.writeByte(9) + val reader = ByteReader(writer.toByteArray()) + assertTrue(reader.readLengthPrefixed().contentEquals(byteArrayOf(1, 2, 3))) + assertTrue(reader.readLengthPrefixed().contentEquals(ByteArray(0))) + assertEquals(9, reader.readByte()) + } + + @Test + fun readingPastEndThrows() { + val reader = ByteReader(byteArrayOf(1)) + reader.readByte() + assertFailsWith { reader.readByte() } + } + + @Test + fun growsBufferBeyondInitialCapacity() { + val writer = ByteWriter(2) + repeat(500) { writer.writeByte(it and 0xFF) } + assertEquals(500, writer.length) + val reader = ByteReader(writer.toByteArray()) + repeat(500) { assertEquals(it and 0xFF, reader.readByte()) } + } +} diff --git a/src/test/kotlin/kestrel/store/codec/Crc32CTest.kt b/src/test/kotlin/kestrel/store/codec/Crc32CTest.kt new file mode 100644 index 0000000..4312025 --- /dev/null +++ b/src/test/kotlin/kestrel/store/codec/Crc32CTest.kt @@ -0,0 +1,33 @@ +package kestrel.store.codec + +import kotlin.test.Test +import kotlin.test.assertEquals +import kotlin.test.assertNotEquals + +class Crc32CTest { + @Test + fun sameBytesProduceSameChecksum() { + val a = "hello kestrel".toByteArray() + val b = "hello kestrel".toByteArray() + assertEquals(Crc32C.of(a), Crc32C.of(b)) + } + + @Test + fun differentBytesProduceDifferentChecksum() { + assertNotEquals(Crc32C.of("hello".toByteArray()), Crc32C.of("hellp".toByteArray())) + } + + @Test + fun detectsSingleBitFlip() { + val original = ByteArray(4096) { (it % 251).toByte() } + val corrupted = original.copyOf() + corrupted[2000] = (corrupted[2000].toInt() xor 0x01).toByte() + assertNotEquals(Crc32C.of(original), Crc32C.of(corrupted)) + } + + @Test + fun offsetAndLengthCoverOnlyTheRequestedSlice() { + val buffer = "xxhelloxx".toByteArray() + assertEquals(Crc32C.of("hello".toByteArray()), Crc32C.of(buffer, 2, 5)) + } +} diff --git a/src/test/kotlin/kestrel/store/codec/KeyCodecTest.kt b/src/test/kotlin/kestrel/store/codec/KeyCodecTest.kt new file mode 100644 index 0000000000000000000000000000000000000000..95fcfedb7cd7c77cb28d35b7887564f84608edef GIT binary patch literal 6860 zcmdT}ZExE)5bo#v3c?sr8FN@UZCbckfjO-+7;}>%@zQNYQP2`?bCpF;qJy}F|NHJp zN+KiKjk65s+*+1I@<`tE+zT&D7JX(jPCoNoWjvv|k{PFwjCpi$AQnrRDe@P)W^}>S zoSul;8y<-TOT0EE7MzY`#F95m@uJBU2~*H3maM8qsS=UWjHR($&LEHAlUe_$a?~3Q-6-h*{&ZmJEgpK&ogX!5SN%UQ(q47k@gtJt)2MX5L{${T! z?6JAqFjaiUGb8NqMWZOMPuSSyf-|$=;P5FuZtODVH_A-YvbeSy`&oLJt`%K^R<}oc zy;gg_L5KGkMgJUJoHtJcq*ojCj{w^yJ zc$bcWWriNo?v%u%Kt3QK@GvO2NO_8{jP$lM`$n&0bD)2Gnt~KGzyXc~#-3*}&+?P? z;D$x&Y_;H-i1a4=Q6}^JQq0o4pT?J9oP19a;C5P}-a*r403Sb>^041)F%gq`4N z7~bZp1C^0QQ*hZMna+a4?k7-``yGL^bD!~k)Na#-yyowuNY#i>Rp7{hAQFH+pF6s{ zla&fZl&oN|?(Pbm=}ueK~d~+I;4d_6-BzQFy8Dt98Ha)UT?Bak=-uz~5&0K--qn8Rq0U|*D za?SJC^Gv2Pkuw1fTGPn*Z7}4)QbzL{QDTs?E&cGqTDKPhVi?vS2Hk3T-hHRg;Wwe!i?8=P&$OBJQU5Iz8#)@y6TU98z4gNGp@8lbZ`e8%?CWf zVHYkTx(56f4fs3qQ&c0Z|GSZnfwP#Qc=t`*&FXgo@8zxE5B6r|CHTeTJ<#77G-`Mo zXAC9-bbupM@a)L9sge&mKpg7;K^zaRBY~R^!GOY5Rvxx+e%rnFE?7|HWQ{Xj>2&$~ zblm0o_VC@1ZIu~!>AM{}Ez@jB`Gh@8)w8Y=qb8euBUh7z)3d=Z{qgW>@M(BWzfZm?6l*ddOg>mIhdZGCrsIrIcRgmG3U#)q`ba%C8B@Kej*Y~*Op zx?e%sT@$e_4S!Y7!@aSUb?r#Xkrw~Xj9*mqp!Jjt*w!Zc(s%s`Zk53v~0CPBF2u;Kr0c zh4c*%G5HCH>H{BK^K7l=kpB;$qE{mr_J%FE8!?Ot%nCqFrcCGi45{W&0fJFYQN@h( zijKCNXp5CzJU5wLkvBqWZ-!UyVOx+YyH=WQIb0}CRV6@nU%+hVfTasGdN)|4G23d} z(pqy7#%io%I_tvA4m9w@Cv%~&1gA|L%4Vl{$TMXWfaSGJR*Mv1N|BydEE5c3@`$H1 zHOHNKkUe=q#;aw*iNq4zOA@r0Hh!>runl~QjE88G36Iz+=LC=<=2#i&nMkY)IJtRA zJzAT74yldKVC_YL@is4U{w5$`LC(4T8cfEXcJ~w>HA-imbYnlwXz3kw?Bx4^b;^