From 93cbeb98fba6ec35570193443e42328a49336629 Mon Sep 17 00:00:00 2001 From: Rahul Behera Date: Tue, 6 Feb 2024 00:02:52 -0800 Subject: [PATCH] fragmented read buffer fixes & native buffer fix (#54) * fragmented read buffer fixes * add 10s timeout to browser * add more information for failed tests * fix native write(buffer) issue --- build.gradle.kts | 9 ++++- karma.config.d/karma.conf.js | 5 +++ .../ditchoom/buffer/FragmentedReadBuffer.kt | 40 ++++++++++++------- .../buffer/FragmentedReadBufferTests.kt | 26 ++++++++++++ .../com/ditchoom/buffer/NativeBuffer.kt | 2 +- 5 files changed, 65 insertions(+), 17 deletions(-) create mode 100644 karma.config.d/karma.conf.js diff --git a/build.gradle.kts b/build.gradle.kts index 87eab0b..d49386e 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -52,7 +52,14 @@ kotlin { js(IR) { moduleName = "buffer-kt" browser { binaries.library() } - nodejs { binaries.library() } + nodejs { + binaries.library() + testTask { + useMocha { + timeout = "10s" + } + } + } } } diff --git a/karma.config.d/karma.conf.js b/karma.config.d/karma.conf.js new file mode 100644 index 0000000..e651f5c --- /dev/null +++ b/karma.config.d/karma.conf.js @@ -0,0 +1,5 @@ +config.client = config.client || {} +config.client.mocha = config.client.mocha || {} +config.client.mocha.timeout = 10000 +config.browserNoActivityTimeout = 10000 +config.browserDisconnectTimeout = 10000 diff --git a/src/commonMain/kotlin/com/ditchoom/buffer/FragmentedReadBuffer.kt b/src/commonMain/kotlin/com/ditchoom/buffer/FragmentedReadBuffer.kt index e05fc0e..3162d7b 100644 --- a/src/commonMain/kotlin/com/ditchoom/buffer/FragmentedReadBuffer.kt +++ b/src/commonMain/kotlin/com/ditchoom/buffer/FragmentedReadBuffer.kt @@ -9,9 +9,7 @@ class FragmentedReadBuffer( private val first: ReadBuffer, private val second: ReadBuffer ) : ReadBuffer { - private val firstInitialPosition = first.position() private val firstInitialLimit = first.limit() - private val secondInitialPosition = second.position() private val secondInitialLimit = second.limit() private var currentPosition = 0 private var currentLimit = firstInitialLimit + secondInitialLimit @@ -37,8 +35,8 @@ class FragmentedReadBuffer( override fun resetForRead() { currentPosition = 0 - first.position(firstInitialPosition) - second.position(secondInitialPosition) + first.resetForRead() + second.resetForRead() } override fun readByte(): Byte { @@ -143,19 +141,31 @@ class FragmentedReadBuffer( out += second } } + fun toSingleBuffer(zone: AllocationZone = AllocationZone.Heap): PlatformBuffer { + val firstLimit = firstInitialLimit + val secondLimit = secondInitialLimit + val initialPosition = position() + val buffer = PlatformBuffer.allocate(firstLimit + secondLimit - initialPosition, zone) + buffer.write(first) + buffer.write(second) + buffer.position(initialPosition) + return buffer + } } fun List.toComposableBuffer(): ReadBuffer { - return when (size) { - 1 -> { - first() - } - - else -> { - FragmentedReadBuffer( - first(), - subList(1, size).toComposableBuffer() - ) - } + if (isEmpty()) { + return ReadBuffer.EMPTY_BUFFER + } + if (size == 1) { + return first() + } + if (size == 2) { + return FragmentedReadBuffer(first(), get(1)) } + val half = size / 2 + return FragmentedReadBuffer( + subList(0, half).toComposableBuffer(), + subList(half, size).toComposableBuffer() + ) } diff --git a/src/commonTest/kotlin/com/ditchoom/buffer/FragmentedReadBufferTests.kt b/src/commonTest/kotlin/com/ditchoom/buffer/FragmentedReadBufferTests.kt index 02eb085..131eadf 100644 --- a/src/commonTest/kotlin/com/ditchoom/buffer/FragmentedReadBufferTests.kt +++ b/src/commonTest/kotlin/com/ditchoom/buffer/FragmentedReadBufferTests.kt @@ -413,4 +413,30 @@ class FragmentedReadBufferTests { assertEquals("", composableBuffer.readUtf8Line().toString()) assertTrue { composableBuffer.remaining() == 0 } } + + @Test + fun largeFragmentedBuffer() { + val buffers = mutableListOf() + var indexCount = 0 + do { // 64 byte chunks + val buffer = PlatformBuffer.allocate(64) + repeat(64 / 4) { + buffer.writeInt(indexCount++) + } + buffers += buffer + } while (indexCount < 1024 * 1024) + val fragmentedBuffer = buffers.toComposableBuffer() as FragmentedReadBuffer + fragmentedBuffer.resetForRead() + repeat(indexCount) { + assertEquals(it, fragmentedBuffer.readInt(), "failed to read byte on fragmented at $indexCount") + } + assertEquals(0, fragmentedBuffer.remaining(), "fragmented should have 0 remaining") + fragmentedBuffer.resetForRead() + val combined = fragmentedBuffer.toSingleBuffer() + assertEquals(indexCount * 4, combined.remaining(), "failed to validate remaining") + repeat(indexCount) { + assertEquals(it, combined.readInt(), "failed to read byte on combined at $indexCount") + } + assertEquals(0, combined.remaining(), "combined should have 0 remaining") + } } diff --git a/src/nativeMain/kotlin/com/ditchoom/buffer/NativeBuffer.kt b/src/nativeMain/kotlin/com/ditchoom/buffer/NativeBuffer.kt index bf2021a..55d3a01 100644 --- a/src/nativeMain/kotlin/com/ditchoom/buffer/NativeBuffer.kt +++ b/src/nativeMain/kotlin/com/ditchoom/buffer/NativeBuffer.kt @@ -74,7 +74,7 @@ data class NativeBuffer( writeBytes(buffer.data) buffer.data.size } else { - val numBytes = remaining() + val numBytes = buffer.remaining() writeBytes(buffer.readByteArray(numBytes)) numBytes }