aboutsummaryrefslogtreecommitdiff
path: root/okio/src/commonTest/kotlin/okio/AbstractBufferedSinkTest.kt
diff options
context:
space:
mode:
Diffstat (limited to 'okio/src/commonTest/kotlin/okio/AbstractBufferedSinkTest.kt')
-rw-r--r--okio/src/commonTest/kotlin/okio/AbstractBufferedSinkTest.kt261
1 files changed, 261 insertions, 0 deletions
diff --git a/okio/src/commonTest/kotlin/okio/AbstractBufferedSinkTest.kt b/okio/src/commonTest/kotlin/okio/AbstractBufferedSinkTest.kt
new file mode 100644
index 00000000..49bff8d9
--- /dev/null
+++ b/okio/src/commonTest/kotlin/okio/AbstractBufferedSinkTest.kt
@@ -0,0 +1,261 @@
+/*
+ * Copyright (C) 2019 Square, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package okio
+
+import okio.ByteString.Companion.decodeHex
+import okio.ByteString.Companion.encodeUtf8
+import kotlin.math.pow
+import kotlin.test.Test
+import kotlin.test.assertEquals
+import kotlin.test.assertFailsWith
+
+class BufferSinkTest : AbstractBufferedSinkTest(BufferedSinkFactory.BUFFER)
+class RealBufferedSinkTest : AbstractBufferedSinkTest(BufferedSinkFactory.REAL_BUFFERED_SINK)
+
+abstract class AbstractBufferedSinkTest internal constructor(
+ factory: BufferedSinkFactory
+) {
+ private val data: Buffer = Buffer()
+ private val sink: BufferedSink = factory.create(data)
+
+ @Test fun writeNothing() {
+ sink.writeUtf8("")
+ sink.flush()
+ assertEquals(0, data.size)
+ }
+
+ @Test fun writeBytes() {
+ sink.writeByte(0xab)
+ sink.writeByte(0xcd)
+ sink.flush()
+ assertEquals("[hex=abcd]", data.toString())
+ }
+
+ @Test fun writeLastByteInSegment() {
+ sink.writeUtf8("a".repeat(Segment.SIZE - 1))
+ sink.writeByte(0x20)
+ sink.writeByte(0x21)
+ sink.flush()
+ assertEquals(listOf(Segment.SIZE, 1), segmentSizes(data))
+ assertEquals("a".repeat(Segment.SIZE - 1), data.readUtf8(Segment.SIZE - 1L))
+ assertEquals("[text= !]", data.toString())
+ }
+
+ @Test fun writeShort() {
+ sink.writeShort(0xabcd)
+ sink.writeShort(0x4321)
+ sink.flush()
+ assertEquals("[hex=abcd4321]", data.toString())
+ }
+
+ @Test fun writeShortLe() {
+ sink.writeShortLe(0xcdab)
+ sink.writeShortLe(0x2143)
+ sink.flush()
+ assertEquals("[hex=abcd4321]", data.toString())
+ }
+
+ @Test fun writeInt() {
+ sink.writeInt(-0x543210ff)
+ sink.writeInt(-0x789abcdf)
+ sink.flush()
+ assertEquals("[hex=abcdef0187654321]", data.toString())
+ }
+
+ @Test fun writeLastIntegerInSegment() {
+ sink.writeUtf8("a".repeat(Segment.SIZE - 4))
+ sink.writeInt(-0x543210ff)
+ sink.writeInt(-0x789abcdf)
+ sink.flush()
+ assertEquals(listOf(Segment.SIZE, 4), segmentSizes(data))
+ assertEquals("a".repeat(Segment.SIZE - 4), data.readUtf8(Segment.SIZE - 4L))
+ assertEquals("[hex=abcdef0187654321]", data.toString())
+ }
+
+ @Test fun writeIntegerDoesNotQuiteFitInSegment() {
+ sink.writeUtf8("a".repeat(Segment.SIZE - 3))
+ sink.writeInt(-0x543210ff)
+ sink.writeInt(-0x789abcdf)
+ sink.flush()
+ assertEquals(listOf(Segment.SIZE - 3, 8), segmentSizes(data))
+ assertEquals("a".repeat(Segment.SIZE - 3), data.readUtf8(Segment.SIZE - 3L))
+ assertEquals("[hex=abcdef0187654321]", data.toString())
+ }
+
+ @Test fun writeIntLe() {
+ sink.writeIntLe(-0x543210ff)
+ sink.writeIntLe(-0x789abcdf)
+ sink.flush()
+ assertEquals("[hex=01efcdab21436587]", data.toString())
+ }
+
+ @Test fun writeLong() {
+ sink.writeLong(-0x543210fe789abcdfL)
+ sink.writeLong(-0x350145414f4ea400L)
+ sink.flush()
+ assertEquals("[hex=abcdef0187654321cafebabeb0b15c00]", data.toString())
+ }
+
+ @Test fun writeLongLe() {
+ sink.writeLongLe(-0x543210fe789abcdfL)
+ sink.writeLongLe(-0x350145414f4ea400L)
+ sink.flush()
+ assertEquals("[hex=2143658701efcdab005cb1b0bebafeca]", data.toString())
+ }
+
+ @Test fun writeByteString() {
+ sink.write("təˈranəˌsôr".encodeUtf8())
+ sink.flush()
+ assertEquals("74c999cb8872616ec999cb8c73c3b472".decodeHex(), data.readByteString())
+ }
+
+ @Test fun writeByteStringOffset() {
+ sink.write("təˈranəˌsôr".encodeUtf8(), 5, 5)
+ sink.flush()
+ assertEquals("72616ec999".decodeHex(), data.readByteString())
+ }
+
+ @Test fun writeSegmentedByteString() {
+ sink.write(Buffer().write("təˈranəˌsôr".encodeUtf8()).snapshot())
+ sink.flush()
+ assertEquals("74c999cb8872616ec999cb8c73c3b472".decodeHex(), data.readByteString())
+ }
+
+ @Test fun writeSegmentedByteStringOffset() {
+ sink.write(Buffer().write("təˈranəˌsôr".encodeUtf8()).snapshot(), 5, 5)
+ sink.flush()
+ assertEquals("72616ec999".decodeHex(), data.readByteString())
+ }
+
+ @Test fun writeStringUtf8() {
+ sink.writeUtf8("təˈranəˌsôr")
+ sink.flush()
+ assertEquals("74c999cb8872616ec999cb8c73c3b472".decodeHex(), data.readByteString())
+ }
+
+ @Test fun writeSubstringUtf8() {
+ sink.writeUtf8("təˈranəˌsôr", 3, 7)
+ sink.flush()
+ assertEquals("72616ec999".decodeHex(), data.readByteString())
+ }
+
+ @Test fun writeAll() {
+ val source = Buffer().writeUtf8("abcdef")
+
+ assertEquals(6, sink.writeAll(source))
+ assertEquals(0, source.size)
+ sink.flush()
+ assertEquals("abcdef", data.readUtf8())
+ }
+
+ @Test fun writeSource() {
+ val source = Buffer().writeUtf8("abcdef")
+
+ // Force resolution of the Source method overload.
+ sink.write(source as Source, 4)
+ sink.flush()
+ assertEquals("abcd", data.readUtf8())
+ assertEquals("ef", source.readUtf8())
+ }
+
+ @Test fun writeSourceReadsFully() {
+ val source = object : Source by Buffer() {
+ override fun read(sink: Buffer, byteCount: Long): Long {
+ sink.writeUtf8("abcd")
+ return 4
+ }
+ }
+
+ sink.write(source, 8)
+ sink.flush()
+ assertEquals("abcdabcd", data.readUtf8())
+ }
+
+ @Test fun writeSourcePropagatesEof() {
+ val source: Source = Buffer().writeUtf8("abcd")
+
+ assertFailsWith<EOFException> {
+ sink.write(source, 8)
+ }
+
+ // Ensure that whatever was available was correctly written.
+ sink.flush()
+ assertEquals("abcd", data.readUtf8())
+ }
+
+ @Test fun writeSourceWithZeroIsNoOp() {
+ // This test ensures that a zero byte count never calls through to read the source. It may be
+ // tied to something like a socket which will potentially block trying to read a segment when
+ // ultimately we don't want any data.
+ val source = object : Source by Buffer() {
+ override fun read(sink: Buffer, byteCount: Long): Long {
+ throw AssertionError()
+ }
+ }
+ sink.write(source, 0)
+ assertEquals(0, data.size)
+ }
+
+ @Test fun writeAllExhausted() {
+ val source = Buffer()
+ assertEquals(0, sink.writeAll(source))
+ assertEquals(0, source.size)
+ }
+
+ @Test fun closeEmitsBufferedBytes() {
+ sink.writeByte('a'.toInt())
+ sink.close()
+ assertEquals('a', data.readByte().toChar())
+ }
+
+ @Test fun longDecimalString() {
+ assertLongDecimalString(0)
+ assertLongDecimalString(Long.MIN_VALUE)
+ assertLongDecimalString(Long.MAX_VALUE)
+
+ for (i in 1..19) {
+ val value = 10.0.pow(i).toLong()
+ assertLongDecimalString(value - 1)
+ assertLongDecimalString(value)
+ }
+ }
+
+ private fun assertLongDecimalString(value: Long) {
+ sink.writeDecimalLong(value).writeUtf8("zzz").flush()
+ val expected = "${value}zzz"
+ val actual = data.readUtf8()
+ assertEquals(expected, actual, "$value expected $expected but was $actual")
+ }
+
+ @Test fun longHexString() {
+ assertLongHexString(0)
+ assertLongHexString(Long.MIN_VALUE)
+ assertLongHexString(Long.MAX_VALUE)
+
+ for (i in 0..62) {
+ assertLongHexString((1L shl i) - 1)
+ assertLongHexString(1L shl i)
+ }
+ }
+
+ private fun assertLongHexString(value: Long) {
+ sink.writeHexadecimalUnsignedLong(value).writeUtf8("zzz").flush()
+ val expected = "${value.toHexString()}zzz"
+ val actual = data.readUtf8()
+ assertEquals(expected, actual, "$value expected $expected but was $actual")
+ }
+}