IO: fix writeByte BufferOverflowException
it is important to setup buffer's positions again after suspension
it is not the case if we don't hold writing state during suspension
diff --git a/core/kotlinx-coroutines-io/src/main/kotlin/kotlinx/coroutines/experimental/io/ByteBufferChannel.kt b/core/kotlinx-coroutines-io/src/main/kotlin/kotlinx/coroutines/experimental/io/ByteBufferChannel.kt
index 765f3c4..f2e7312 100644
--- a/core/kotlinx-coroutines-io/src/main/kotlin/kotlinx/coroutines/experimental/io/ByteBufferChannel.kt
+++ b/core/kotlinx-coroutines-io/src/main/kotlin/kotlinx/coroutines/experimental/io/ByteBufferChannel.kt
@@ -708,6 +708,7 @@
throw t
}
+ buffer.prepareBuffer(writeByteOrder, writePosition, c.availableForWrite)
tryWriteByte(buffer, b, c)
}
@@ -752,6 +753,7 @@
throw t
}
+ buffer.prepareBuffer(writeByteOrder, writePosition, c.availableForWrite)
tryWriteShort(buffer, s, c)
}
@@ -793,6 +795,7 @@
throw t
}
+ prepareBuffer(writeByteOrder, writePosition, c.availableForWrite)
if (!tryWriteInt(i, c)) {
writeIntSuspend(i, c)
}
@@ -829,6 +832,8 @@
private tailrec suspend fun ByteBuffer.writeLongSuspend(l: Long, c: RingBufferCapacity) {
writeSuspend(8)
+
+ prepareBuffer(writeByteOrder, writePosition, c.availableForWrite)
if (!tryWriteLong(l, c)) {
writeLongSuspend(l, c)
}
diff --git a/core/kotlinx-coroutines-io/src/test/kotlin/kotlinx/coroutines/experimental/io/ByteBufferChannelScenarioTest.kt b/core/kotlinx-coroutines-io/src/test/kotlin/kotlinx/coroutines/experimental/io/ByteBufferChannelScenarioTest.kt
index f8a6999..910408e 100644
--- a/core/kotlinx-coroutines-io/src/test/kotlin/kotlinx/coroutines/experimental/io/ByteBufferChannelScenarioTest.kt
+++ b/core/kotlinx-coroutines-io/src/test/kotlin/kotlinx/coroutines/experimental/io/ByteBufferChannelScenarioTest.kt
@@ -338,4 +338,105 @@
finish(5)
}
+
+ @Test
+ fun testWriteByteSuspend() = runBlocking {
+ launch(coroutineContext) {
+ expect(1)
+ ch.writeByte(1)
+ ch.writeFully(ByteArray(ch.availableForWrite))
+ expect(2)
+ ch.writeByte(1)
+ expect(5)
+ ch.close()
+ }
+
+ yield()
+ expect(3)
+ yield()
+ expect(4)
+ yield()
+
+ ch.readByte()
+ yield()
+
+ ch.readRemaining()
+ finish(6)
+ }
+
+ @Test
+ fun testWriteShortSuspend() = runBlocking {
+ launch(coroutineContext) {
+ expect(1)
+ ch.writeByte(1)
+ ch.writeFully(ByteArray(ch.availableForWrite))
+ expect(2)
+ ch.writeShort(1)
+ expect(5)
+ ch.close()
+ }
+
+ yield()
+ expect(3)
+ yield()
+ expect(4)
+ yield()
+
+ ch.readShort()
+ yield()
+
+ ch.readRemaining()
+ finish(6)
+ }
+
+ @Test
+ fun testWriteIntSuspend() = runBlocking {
+ launch(coroutineContext) {
+ expect(1)
+ ch.writeByte(1)
+ ch.writeFully(ByteArray(ch.availableForWrite))
+ expect(2)
+ ch.writeInt(1)
+ expect(5)
+ ch.close()
+ }
+
+ yield()
+ expect(3)
+ yield()
+ expect(4)
+ yield()
+
+ ch.readInt()
+ yield()
+
+ ch.readRemaining()
+ finish(6)
+ }
+
+ @Test
+ fun testWriteLongSuspend() = runBlocking {
+ launch(coroutineContext) {
+ expect(1)
+ ch.writeByte(1)
+ ch.writeFully(ByteArray(ch.availableForWrite))
+ expect(2)
+ ch.writeLong(1)
+ expect(5)
+ ch.close()
+ }
+
+ yield()
+ expect(3)
+ yield()
+ expect(4)
+ yield()
+
+ ch.readLong()
+ yield()
+
+ ch.readRemaining()
+ finish(6)
+ }
+
}
\ No newline at end of file