aboutsummaryrefslogtreecommitdiff
path: root/okio/src/commonTest
diff options
context:
space:
mode:
Diffstat (limited to 'okio/src/commonTest')
-rw-r--r--okio/src/commonTest/kotlin/okio/AbstractBufferedSinkTest.kt67
-rw-r--r--okio/src/commonTest/kotlin/okio/AbstractBufferedSourceTest.kt305
-rw-r--r--okio/src/commonTest/kotlin/okio/AbstractFileSystemTest.kt670
-rw-r--r--okio/src/commonTest/kotlin/okio/BufferCommonTest.kt2
-rw-r--r--okio/src/commonTest/kotlin/okio/BufferedSourceFactory.kt16
-rw-r--r--okio/src/commonTest/kotlin/okio/ByteStringMoreTests.kt (renamed from okio/src/commonTest/kotlin/okio/FakeClock.kt)25
-rw-r--r--okio/src/commonTest/kotlin/okio/ByteStringTest.kt144
-rw-r--r--okio/src/commonTest/kotlin/okio/CommonBufferTest.kt61
-rw-r--r--okio/src/commonTest/kotlin/okio/CommonOptionsTest.kt205
-rw-r--r--okio/src/commonTest/kotlin/okio/CommonRealBufferedSinkTest.kt20
-rw-r--r--okio/src/commonTest/kotlin/okio/CommonRealBufferedSourceTest.kt6
-rw-r--r--okio/src/commonTest/kotlin/okio/FakeFileSystemTest.kt304
-rw-r--r--okio/src/commonTest/kotlin/okio/ForwardingFileSystemTest.kt146
-rw-r--r--okio/src/commonTest/kotlin/okio/ForwardingSourceTest.kt53
-rw-r--r--okio/src/commonTest/kotlin/okio/HashingSinkTest.kt4
-rw-r--r--okio/src/commonTest/kotlin/okio/HashingSourceTest.kt12
-rw-r--r--okio/src/commonTest/kotlin/okio/HashingTest.kt4
-rw-r--r--okio/src/commonTest/kotlin/okio/OkioTesting.kt (renamed from okio/src/commonTest/kotlin/okio/util.kt)37
-rw-r--r--okio/src/commonTest/kotlin/okio/PathTest.kt520
-rw-r--r--okio/src/commonTest/kotlin/okio/SystemFileSystemTest.kt28
-rw-r--r--okio/src/commonTest/kotlin/okio/UnsafeCursorTest.kt11
-rw-r--r--okio/src/commonTest/kotlin/okio/Utf8KotlinTest.kt16
-rw-r--r--okio/src/commonTest/kotlin/okio/time.kt39
23 files changed, 1064 insertions, 1631 deletions
diff --git a/okio/src/commonTest/kotlin/okio/AbstractBufferedSinkTest.kt b/okio/src/commonTest/kotlin/okio/AbstractBufferedSinkTest.kt
index 49bff8d9..e922d5f2 100644
--- a/okio/src/commonTest/kotlin/okio/AbstractBufferedSinkTest.kt
+++ b/okio/src/commonTest/kotlin/okio/AbstractBufferedSinkTest.kt
@@ -16,18 +16,17 @@
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
+import okio.ByteString.Companion.decodeHex
+import okio.ByteString.Companion.encodeUtf8
class BufferSinkTest : AbstractBufferedSinkTest(BufferedSinkFactory.BUFFER)
class RealBufferedSinkTest : AbstractBufferedSinkTest(BufferedSinkFactory.REAL_BUFFERED_SINK)
abstract class AbstractBufferedSinkTest internal constructor(
- factory: BufferedSinkFactory
+ factory: BufferedSinkFactory,
) {
private val data: Buffer = Buffer()
private val sink: BufferedSink = factory.create(data)
@@ -217,26 +216,60 @@ abstract class AbstractBufferedSinkTest internal constructor(
}
@Test fun closeEmitsBufferedBytes() {
- sink.writeByte('a'.toInt())
+ sink.writeByte('a'.code)
sink.close()
- assertEquals('a', data.readByte().toChar())
+ assertEquals('a', data.readByte().toInt().toChar())
}
+ /**
+ * This test hard codes the results of Long.toString() because that function rounds large values
+ * when using Kotlin/JS IR. https://youtrack.jetbrains.com/issue/KT-39891
+ */
@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)
- }
+ assertLongDecimalString("0", 0)
+ assertLongDecimalString("-9223372036854775808", Long.MIN_VALUE)
+ assertLongDecimalString("9223372036854775807", Long.MAX_VALUE)
+ assertLongDecimalString("9", 9L)
+ assertLongDecimalString("99", 99L)
+ assertLongDecimalString("999", 999L)
+ assertLongDecimalString("9999", 9999L)
+ assertLongDecimalString("99999", 99999L)
+ assertLongDecimalString("999999", 999999L)
+ assertLongDecimalString("9999999", 9999999L)
+ assertLongDecimalString("99999999", 99999999L)
+ assertLongDecimalString("999999999", 999999999L)
+ assertLongDecimalString("9999999999", 9999999999L)
+ assertLongDecimalString("99999999999", 99999999999L)
+ assertLongDecimalString("999999999999", 999999999999L)
+ assertLongDecimalString("9999999999999", 9999999999999L)
+ assertLongDecimalString("99999999999999", 99999999999999L)
+ assertLongDecimalString("999999999999999", 999999999999999L)
+ assertLongDecimalString("9999999999999999", 9999999999999999L)
+ assertLongDecimalString("99999999999999999", 99999999999999999L)
+ assertLongDecimalString("999999999999999999", 999999999999999999L)
+ assertLongDecimalString("10", 10L)
+ assertLongDecimalString("100", 100L)
+ assertLongDecimalString("1000", 1000L)
+ assertLongDecimalString("10000", 10000L)
+ assertLongDecimalString("100000", 100000L)
+ assertLongDecimalString("1000000", 1000000L)
+ assertLongDecimalString("10000000", 10000000L)
+ assertLongDecimalString("100000000", 100000000L)
+ assertLongDecimalString("1000000000", 1000000000L)
+ assertLongDecimalString("10000000000", 10000000000L)
+ assertLongDecimalString("100000000000", 100000000000L)
+ assertLongDecimalString("1000000000000", 1000000000000L)
+ assertLongDecimalString("10000000000000", 10000000000000L)
+ assertLongDecimalString("100000000000000", 100000000000000L)
+ assertLongDecimalString("1000000000000000", 1000000000000000L)
+ assertLongDecimalString("10000000000000000", 10000000000000000L)
+ assertLongDecimalString("100000000000000000", 100000000000000000L)
+ assertLongDecimalString("1000000000000000000", 1000000000000000000L)
}
- private fun assertLongDecimalString(value: Long) {
+ private fun assertLongDecimalString(string: String, value: Long) {
sink.writeDecimalLong(value).writeUtf8("zzz").flush()
- val expected = "${value}zzz"
+ val expected = "${string}zzz"
val actual = data.readUtf8()
assertEquals(expected, actual, "$value expected $expected but was $actual")
}
diff --git a/okio/src/commonTest/kotlin/okio/AbstractBufferedSourceTest.kt b/okio/src/commonTest/kotlin/okio/AbstractBufferedSourceTest.kt
index b15d369c..70d76cb6 100644
--- a/okio/src/commonTest/kotlin/okio/AbstractBufferedSourceTest.kt
+++ b/okio/src/commonTest/kotlin/okio/AbstractBufferedSourceTest.kt
@@ -16,14 +16,13 @@
package okio
-import okio.ByteString.Companion.decodeHex
-import okio.ByteString.Companion.encodeUtf8
import kotlin.test.Test
import kotlin.test.assertEquals
import kotlin.test.assertFailsWith
import kotlin.test.assertFalse
import kotlin.test.assertTrue
-import kotlin.test.fail
+import okio.ByteString.Companion.decodeHex
+import okio.ByteString.Companion.encodeUtf8
class BufferSourceTest : AbstractBufferedSourceTest(BufferedSourceFactory.BUFFER)
class RealBufferedSourceTest : AbstractBufferedSourceTest(BufferedSourceFactory.REAL_BUFFERED_SOURCE)
@@ -33,7 +32,7 @@ class PeekBufferTest : AbstractBufferedSourceTest(BufferedSourceFactory.PEEK_BUF
class PeekBufferedSourceTest : AbstractBufferedSourceTest(BufferedSourceFactory.PEEK_BUFFERED_SOURCE)
abstract class AbstractBufferedSourceTest internal constructor(
- private val factory: BufferedSourceFactory
+ private val factory: BufferedSourceFactory,
) {
private val sink: BufferedSink
private val source: BufferedSource
@@ -111,8 +110,8 @@ abstract class AbstractBufferedSourceTest internal constructor(
0x87.toByte(),
0x65.toByte(),
0x43.toByte(),
- 0x21.toByte()
- )
+ 0x21.toByte(),
+ ),
)
sink.emit()
assertEquals(-0x543210ff, source.readInt().toLong())
@@ -130,8 +129,8 @@ abstract class AbstractBufferedSourceTest internal constructor(
0x87.toByte(),
0x65.toByte(),
0x43.toByte(),
- 0x21.toByte()
- )
+ 0x21.toByte(),
+ ),
)
sink.emit()
assertEquals(0x10efcdab, source.readIntLe().toLong())
@@ -184,8 +183,8 @@ abstract class AbstractBufferedSourceTest internal constructor(
0x12.toByte(),
0x23.toByte(),
0x34.toByte(),
- 0x45.toByte()
- )
+ 0x45.toByte(),
+ ),
)
sink.emit()
assertEquals(-0x543210ef789abcdfL, source.readLong())
@@ -211,8 +210,8 @@ abstract class AbstractBufferedSourceTest internal constructor(
0x12.toByte(),
0x23.toByte(),
0x34.toByte(),
- 0x45.toByte()
- )
+ 0x45.toByte(),
+ ),
)
sink.emit()
assertEquals(0x2143658710efcdabL, source.readLongLe())
@@ -231,8 +230,8 @@ abstract class AbstractBufferedSourceTest internal constructor(
0x87.toByte(),
0x65.toByte(),
0x43.toByte(),
- 0x21.toByte()
- )
+ 0x21.toByte(),
+ ),
)
sink.emit()
source.skip((Segment.SIZE - 7).toLong())
@@ -341,14 +340,14 @@ abstract class AbstractBufferedSourceTest internal constructor(
// Verify we read all that we could from the source.
assertArrayEquals(
byteArrayOf(
- 'H'.toByte(),
- 'e'.toByte(),
- 'l'.toByte(),
- 'l'.toByte(),
- 'o'.toByte(),
- 0
+ 'H'.code.toByte(),
+ 'e'.code.toByte(),
+ 'l'.code.toByte(),
+ 'l'.code.toByte(),
+ 'o'.code.toByte(),
+ 0,
),
- array
+ array,
)
}
@@ -360,11 +359,11 @@ abstract class AbstractBufferedSourceTest internal constructor(
val read = source.read(sink)
if (factory.isOneByteAtATime) {
assertEquals(1, read.toLong())
- val expected = byteArrayOf('a'.toByte(), 0, 0)
+ val expected = byteArrayOf('a'.code.toByte(), 0, 0)
assertArrayEquals(expected, sink)
} else {
assertEquals(3, read.toLong())
- val expected = byteArrayOf('a'.toByte(), 'b'.toByte(), 'c'.toByte())
+ val expected = byteArrayOf('a'.code.toByte(), 'b'.code.toByte(), 'c'.code.toByte())
assertArrayEquals(expected, sink)
}
}
@@ -377,11 +376,12 @@ abstract class AbstractBufferedSourceTest internal constructor(
val read = source.read(sink)
if (factory.isOneByteAtATime) {
assertEquals(1, read.toLong())
- val expected = byteArrayOf('a'.toByte(), 0, 0, 0, 0)
+ val expected = byteArrayOf('a'.code.toByte(), 0, 0, 0, 0)
assertArrayEquals(expected, sink)
} else {
assertEquals(4, read.toLong())
- val expected = byteArrayOf('a'.toByte(), 'b'.toByte(), 'c'.toByte(), 'd'.toByte(), 0)
+ val expected =
+ byteArrayOf('a'.code.toByte(), 'b'.code.toByte(), 'c'.code.toByte(), 'd'.code.toByte(), 0)
assertArrayEquals(expected, sink)
}
}
@@ -394,11 +394,12 @@ abstract class AbstractBufferedSourceTest internal constructor(
val read = source.read(sink, 2, 3)
if (factory.isOneByteAtATime) {
assertEquals(1, read.toLong())
- val expected = byteArrayOf(0, 0, 'a'.toByte(), 0, 0, 0, 0)
+ val expected = byteArrayOf(0, 0, 'a'.code.toByte(), 0, 0, 0, 0)
assertArrayEquals(expected, sink)
} else {
assertEquals(3, read.toLong())
- val expected = byteArrayOf(0, 0, 'a'.toByte(), 'b'.toByte(), 'c'.toByte(), 0, 0)
+ val expected =
+ byteArrayOf(0, 0, 'a'.code.toByte(), 'b'.code.toByte(), 'c'.code.toByte(), 0, 0)
assertArrayEquals(expected, sink)
}
}
@@ -491,9 +492,9 @@ abstract class AbstractBufferedSourceTest internal constructor(
sink.writeUtf8("c")
sink.emit()
source.skip(1)
- assertEquals('b'.toLong(), (source.readByte() and 0xff).toLong())
+ assertEquals('b'.code.toLong(), (source.readByte() and 0xff).toLong())
source.skip((Segment.SIZE - 2).toLong())
- assertEquals('b'.toLong(), (source.readByte() and 0xff).toLong())
+ assertEquals('b'.code.toLong(), (source.readByte() and 0xff).toLong())
source.skip(1)
assertTrue(source.exhausted())
}
@@ -501,7 +502,6 @@ abstract class AbstractBufferedSourceTest internal constructor(
@Test fun skipInsufficientData() {
sink.writeUtf8("a")
sink.emit()
-
assertFailsWith<EOFException> {
source.skip(2)
}
@@ -509,61 +509,61 @@ abstract class AbstractBufferedSourceTest internal constructor(
@Test fun indexOf() {
// The segment is empty.
- assertEquals(-1, source.indexOf('a'.toByte()))
+ assertEquals(-1, source.indexOf('a'.code.toByte()))
// The segment has one value.
sink.writeUtf8("a") // a
sink.emit()
- assertEquals(0, source.indexOf('a'.toByte()))
- assertEquals(-1, source.indexOf('b'.toByte()))
+ assertEquals(0, source.indexOf('a'.code.toByte()))
+ assertEquals(-1, source.indexOf('b'.code.toByte()))
// The segment has lots of data.
sink.writeUtf8("b".repeat(Segment.SIZE - 2)) // ab...b
sink.emit()
- assertEquals(0, source.indexOf('a'.toByte()))
- assertEquals(1, source.indexOf('b'.toByte()))
- assertEquals(-1, source.indexOf('c'.toByte()))
+ assertEquals(0, source.indexOf('a'.code.toByte()))
+ assertEquals(1, source.indexOf('b'.code.toByte()))
+ assertEquals(-1, source.indexOf('c'.code.toByte()))
// The segment doesn't start at 0, it starts at 2.
source.skip(2) // b...b
- assertEquals(-1, source.indexOf('a'.toByte()))
- assertEquals(0, source.indexOf('b'.toByte()))
- assertEquals(-1, source.indexOf('c'.toByte()))
+ assertEquals(-1, source.indexOf('a'.code.toByte()))
+ assertEquals(0, source.indexOf('b'.code.toByte()))
+ assertEquals(-1, source.indexOf('c'.code.toByte()))
// The segment is full.
sink.writeUtf8("c") // b...bc
sink.emit()
- assertEquals(-1, source.indexOf('a'.toByte()))
- assertEquals(0, source.indexOf('b'.toByte()))
- assertEquals((Segment.SIZE - 3).toLong(), source.indexOf('c'.toByte()))
+ assertEquals(-1, source.indexOf('a'.code.toByte()))
+ assertEquals(0, source.indexOf('b'.code.toByte()))
+ assertEquals((Segment.SIZE - 3).toLong(), source.indexOf('c'.code.toByte()))
// The segment doesn't start at 2, it starts at 4.
source.skip(2) // b...bc
- assertEquals(-1, source.indexOf('a'.toByte()))
- assertEquals(0, source.indexOf('b'.toByte()))
- assertEquals((Segment.SIZE - 5).toLong(), source.indexOf('c'.toByte()))
+ assertEquals(-1, source.indexOf('a'.code.toByte()))
+ assertEquals(0, source.indexOf('b'.code.toByte()))
+ assertEquals((Segment.SIZE - 5).toLong(), source.indexOf('c'.code.toByte()))
// Two segments.
sink.writeUtf8("d") // b...bcd, d is in the 2nd segment.
sink.emit()
- assertEquals((Segment.SIZE - 4).toLong(), source.indexOf('d'.toByte()))
- assertEquals(-1, source.indexOf('e'.toByte()))
+ assertEquals((Segment.SIZE - 4).toLong(), source.indexOf('d'.code.toByte()))
+ assertEquals(-1, source.indexOf('e'.code.toByte()))
}
@Test fun indexOfByteWithStartOffset() {
sink.writeUtf8("a").writeUtf8("b".repeat(Segment.SIZE)).writeUtf8("c")
sink.emit()
- assertEquals(-1, source.indexOf('a'.toByte(), 1))
- assertEquals(15, source.indexOf('b'.toByte(), 15))
+ assertEquals(-1, source.indexOf('a'.code.toByte(), 1))
+ assertEquals(15, source.indexOf('b'.code.toByte(), 15))
}
@Test fun indexOfByteWithBothOffsets() {
if (factory.isOneByteAtATime) {
- // When run on Travis this causes out-of-memory errors.
+ // When run on CI this causes out-of-memory errors.
return
}
- val a = 'a'.toByte()
- val c = 'c'.toByte()
+ val a = 'a'.code.toByte()
+ val c = 'c'.code.toByte()
val size = Segment.SIZE * 5
val bytes = ByteArray(size) { a }
@@ -585,7 +585,7 @@ abstract class AbstractBufferedSourceTest internal constructor(
size - Segment.SIZE + 1,
size - 3,
size - 2,
- size - 1
+ size - 1,
)
// In each iteration, we write c to the known point and then search for it using different
@@ -615,17 +615,11 @@ abstract class AbstractBufferedSourceTest internal constructor(
@Test fun indexOfByteInvalidBoundsThrows() {
sink.writeUtf8("abc")
sink.emit()
-
- try {
- source.indexOf('a'.toByte(), -1)
- fail("Expected failure: fromIndex < 0")
- } catch (expected: IllegalArgumentException) {
+ assertFailsWith<IllegalArgumentException>("Expected failure: fromIndex < 0") {
+ source.indexOf('a'.code.toByte(), -1)
}
-
- try {
- source.indexOf('a'.toByte(), 10, 0)
- fail("Expected failure: fromIndex > toIndex")
- } catch (expected: IllegalArgumentException) {
+ assertFailsWith<IllegalArgumentException>("Expected failure: fromIndex > toIndex") {
+ source.indexOf('a'.code.toByte(), 10, 0)
}
}
@@ -649,55 +643,55 @@ abstract class AbstractBufferedSourceTest internal constructor(
sink.emit()
assertEquals(
(Segment.SIZE - 3).toLong(),
- source.indexOf("aabc".encodeUtf8(), (Segment.SIZE - 4).toLong())
+ source.indexOf("aabc".encodeUtf8(), (Segment.SIZE - 4).toLong()),
)
assertEquals(
(Segment.SIZE - 3).toLong(),
- source.indexOf("aabc".encodeUtf8(), (Segment.SIZE - 3).toLong())
+ source.indexOf("aabc".encodeUtf8(), (Segment.SIZE - 3).toLong()),
)
assertEquals(
(Segment.SIZE - 2).toLong(),
- source.indexOf("abcd".encodeUtf8(), (Segment.SIZE - 2).toLong())
+ source.indexOf("abcd".encodeUtf8(), (Segment.SIZE - 2).toLong()),
)
assertEquals(
(Segment.SIZE - 2).toLong(),
- source.indexOf("abc".encodeUtf8(), (Segment.SIZE - 2).toLong())
+ source.indexOf("abc".encodeUtf8(), (Segment.SIZE - 2).toLong()),
)
assertEquals(
(Segment.SIZE - 2).toLong(),
- source.indexOf("abc".encodeUtf8(), (Segment.SIZE - 2).toLong())
+ source.indexOf("abc".encodeUtf8(), (Segment.SIZE - 2).toLong()),
)
assertEquals(
(Segment.SIZE - 2).toLong(),
- source.indexOf("ab".encodeUtf8(), (Segment.SIZE - 2).toLong())
+ source.indexOf("ab".encodeUtf8(), (Segment.SIZE - 2).toLong()),
)
assertEquals(
(Segment.SIZE - 2).toLong(),
- source.indexOf("a".encodeUtf8(), (Segment.SIZE - 2).toLong())
+ source.indexOf("a".encodeUtf8(), (Segment.SIZE - 2).toLong()),
)
assertEquals(
(Segment.SIZE - 1).toLong(),
- source.indexOf("bc".encodeUtf8(), (Segment.SIZE - 2).toLong())
+ source.indexOf("bc".encodeUtf8(), (Segment.SIZE - 2).toLong()),
)
assertEquals(
(Segment.SIZE - 1).toLong(),
- source.indexOf("b".encodeUtf8(), (Segment.SIZE - 2).toLong())
+ source.indexOf("b".encodeUtf8(), (Segment.SIZE - 2).toLong()),
)
assertEquals(
Segment.SIZE.toLong(),
- source.indexOf("c".encodeUtf8(), (Segment.SIZE - 2).toLong())
+ source.indexOf("c".encodeUtf8(), (Segment.SIZE - 2).toLong()),
)
assertEquals(
Segment.SIZE.toLong(),
- source.indexOf("c".encodeUtf8(), Segment.SIZE.toLong())
+ source.indexOf("c".encodeUtf8(), Segment.SIZE.toLong()),
)
assertEquals(
(Segment.SIZE + 1).toLong(),
- source.indexOf("d".encodeUtf8(), (Segment.SIZE - 2).toLong())
+ source.indexOf("d".encodeUtf8(), (Segment.SIZE - 2).toLong()),
)
assertEquals(
(Segment.SIZE + 1).toLong(),
- source.indexOf("d".encodeUtf8(), (Segment.SIZE + 1).toLong())
+ source.indexOf("d".encodeUtf8(), (Segment.SIZE + 1).toLong()),
)
}
@@ -723,19 +717,15 @@ abstract class AbstractBufferedSourceTest internal constructor(
}
@Test fun indexOfByteStringInvalidArgumentsThrows() {
- try {
+ var e = assertFailsWith<IllegalArgumentException> {
source.indexOf(ByteString.of())
- fail()
- } catch (e: IllegalArgumentException) {
- assertEquals("bytes is empty", e.message)
}
+ assertEquals("bytes is empty", e.message)
- try {
+ e = assertFailsWith<IllegalArgumentException> {
source.indexOf("hi".encodeUtf8(), -1)
- fail()
- } catch (e: IllegalArgumentException) {
- assertEquals("fromIndex < 0: -1", e.message)
}
+ assertEquals("fromIndex < 0: -1", e.message)
}
/**
@@ -781,10 +771,10 @@ abstract class AbstractBufferedSourceTest internal constructor(
@Test fun indexOfByteWithFromIndex() {
sink.writeUtf8("aaa")
sink.emit()
- assertEquals(0, source.indexOf('a'.toByte()))
- assertEquals(0, source.indexOf('a'.toByte(), 0))
- assertEquals(1, source.indexOf('a'.toByte(), 1))
- assertEquals(2, source.indexOf('a'.toByte(), 2))
+ assertEquals(0, source.indexOf('a'.code.toByte()))
+ assertEquals(0, source.indexOf('a'.code.toByte(), 0))
+ assertEquals(1, source.indexOf('a'.code.toByte(), 1))
+ assertEquals(2, source.indexOf('a'.code.toByte(), 2))
}
@Test fun indexOfByteStringWithFromIndex() {
@@ -857,35 +847,29 @@ abstract class AbstractBufferedSourceTest internal constructor(
}
@Test fun longHexStringTooLongThrows() {
- try {
- sink.writeUtf8("fffffffffffffffff")
- sink.emit()
+ sink.writeUtf8("fffffffffffffffff")
+ sink.emit()
+
+ val e = assertFailsWith<NumberFormatException> {
source.readHexadecimalUnsignedLong()
- fail()
- } catch (e: NumberFormatException) {
- assertEquals("Number too large: fffffffffffffffff", e.message)
}
+ assertEquals("Number too large: fffffffffffffffff", e.message)
}
@Test fun longHexStringTooShortThrows() {
- try {
- sink.writeUtf8(" ")
- sink.emit()
+ sink.writeUtf8(" ")
+ sink.emit()
+
+ val e = assertFailsWith<NumberFormatException> {
source.readHexadecimalUnsignedLong()
- fail()
- } catch (e: NumberFormatException) {
- assertEquals("Expected leading [0-9a-fA-F] character but was 0x20", e.message)
}
+ assertEquals("Expected leading [0-9a-fA-F] character but was 0x20", e.message)
}
@Test fun longHexEmptySourceThrows() {
- try {
- sink.writeUtf8("")
- sink.emit()
- source.readHexadecimalUnsignedLong()
- fail()
- } catch (expected: EOFException) {
- }
+ sink.writeUtf8("")
+ sink.emit()
+ assertFailsWith<EOFException> { source.readHexadecimalUnsignedLong() }
}
@Test fun longDecimalString() {
@@ -918,60 +902,74 @@ abstract class AbstractBufferedSourceTest internal constructor(
}
@Test fun longDecimalStringTooLongThrows() {
- try {
- sink.writeUtf8("12345678901234567890") // Too many digits.
- sink.emit()
+ sink.writeUtf8("12345678901234567890") // Too many digits.
+ sink.emit()
+
+ val e = assertFailsWith<NumberFormatException> {
source.readDecimalLong()
- fail()
- } catch (e: NumberFormatException) {
- assertEquals("Number too large: 12345678901234567890", e.message)
}
+ assertEquals("Number too large: 12345678901234567890", e.message)
}
@Test fun longDecimalStringTooHighThrows() {
- try {
- sink.writeUtf8("9223372036854775808") // Right size but cannot fit.
- sink.emit()
+ sink.writeUtf8("9223372036854775808") // Right size but cannot fit.
+ sink.emit()
+
+ val e = assertFailsWith<NumberFormatException> {
source.readDecimalLong()
- fail()
- } catch (e: NumberFormatException) {
- assertEquals("Number too large: 9223372036854775808", e.message)
}
+ assertEquals("Number too large: 9223372036854775808", e.message)
}
@Test fun longDecimalStringTooLowThrows() {
- try {
- sink.writeUtf8("-9223372036854775809") // Right size but cannot fit.
- sink.emit()
+ sink.writeUtf8("-9223372036854775809") // Right size but cannot fit.
+ sink.emit()
+
+ val e = assertFailsWith<NumberFormatException> {
source.readDecimalLong()
- fail()
- } catch (e: NumberFormatException) {
- assertEquals("Number too large: -9223372036854775809", e.message)
}
+ assertEquals("Number too large: -9223372036854775809", e.message)
}
@Test fun longDecimalStringTooShortThrows() {
- try {
- sink.writeUtf8(" ")
- sink.emit()
+ sink.writeUtf8(" ")
+ sink.emit()
+
+ val e = assertFailsWith<NumberFormatException> {
source.readDecimalLong()
- fail()
- } catch (e: NumberFormatException) {
- assertEquals("Expected leading [0-9] or '-' character but was 0x20", e.message)
}
+ assertEquals("Expected a digit or '-' but was 0x20", e.message)
}
@Test fun longDecimalEmptyThrows() {
- try {
- sink.writeUtf8("")
- sink.emit()
+ sink.writeUtf8("")
+ sink.emit()
+ assertFailsWith<EOFException> {
+ source.readDecimalLong()
+ }
+ }
+
+ @Test fun longDecimalLoneDashThrows() {
+ sink.writeUtf8("-")
+ sink.emit()
+ assertFailsWith<EOFException> {
+ source.readDecimalLong()
+ }
+ }
+
+ @Test fun longDecimalDashFollowedByNonDigitThrows() {
+ sink.writeUtf8("- ")
+ sink.emit()
+ assertFailsWith<NumberFormatException> {
source.readDecimalLong()
- fail()
- } catch (expected: EOFException) {
}
}
@Test fun codePoints() {
+ // TODO: remove this suppression once this issue is fixed.
+ // https://youtrack.jetbrains.com/issue/KT-60212
+ if (isWasm()) return
+
sink.write("7f".decodeHex())
sink.emit()
assertEquals(0x7f, source.readUtf8CodePoint().toLong())
@@ -1000,21 +998,24 @@ abstract class AbstractBufferedSourceTest internal constructor(
val options = Options.of(
"ROCK".encodeUtf8(),
"SCISSORS".encodeUtf8(),
- "PAPER".encodeUtf8()
+ "PAPER".encodeUtf8(),
)
sink.writeUtf8("PAPER,SCISSORS,ROCK")
sink.emit()
assertEquals(2, source.select(options).toLong())
- assertEquals(','.toLong(), source.readByte().toLong())
+ assertEquals(','.code.toLong(), source.readByte().toLong())
assertEquals(1, source.select(options).toLong())
- assertEquals(','.toLong(), source.readByte().toLong())
+ assertEquals(','.code.toLong(), source.readByte().toLong())
assertEquals(0, source.select(options).toLong())
assertTrue(source.exhausted())
}
/** Note that this test crashes the VM on Android. */
@Test fun selectSpanningMultipleSegments() {
+ if (factory.isOneByteAtATime && isBrowser()) {
+ return // This test times out on browsers.
+ }
val commonPrefix = randomBytes(Segment.SIZE + 10)
val a = Buffer().write(commonPrefix).writeUtf8("a").readByteString()
val bc = Buffer().write(commonPrefix).writeUtf8("bc").readByteString()
@@ -1036,7 +1037,7 @@ abstract class AbstractBufferedSourceTest internal constructor(
val options = Options.of(
"ROCK".encodeUtf8(),
"SCISSORS".encodeUtf8(),
- "PAPER".encodeUtf8()
+ "PAPER".encodeUtf8(),
)
sink.writeUtf8("SPOCK")
@@ -1049,7 +1050,7 @@ abstract class AbstractBufferedSourceTest internal constructor(
val options = Options.of(
"abcd".encodeUtf8(),
"abce".encodeUtf8(),
- "abcc".encodeUtf8()
+ "abcc".encodeUtf8(),
)
sink.writeUtf8("abcc").writeUtf8("abcd").writeUtf8("abce")
@@ -1063,7 +1064,7 @@ abstract class AbstractBufferedSourceTest internal constructor(
val options = Options.of(
"abcd".encodeUtf8(),
"abce".encodeUtf8(),
- "abcc".encodeUtf8()
+ "abcc".encodeUtf8(),
)
sink.writeUtf8("abc")
sink.emit()
@@ -1075,7 +1076,7 @@ abstract class AbstractBufferedSourceTest internal constructor(
val options = Options.of(
"abcd".encodeUtf8(),
"abc".encodeUtf8(),
- "abcde".encodeUtf8()
+ "abcde".encodeUtf8(),
)
sink.writeUtf8("abcdef")
sink.emit()
@@ -1086,7 +1087,7 @@ abstract class AbstractBufferedSourceTest internal constructor(
@Test fun selectFromEmptySource() {
val options = Options.of(
"abc".encodeUtf8(),
- "def".encodeUtf8()
+ "def".encodeUtf8(),
)
assertEquals(-1, source.select(options).toLong())
}
@@ -1132,6 +1133,10 @@ abstract class AbstractBufferedSourceTest internal constructor(
}
@Test fun peekLarge() {
+ if (factory.isOneByteAtATime) {
+ // When run on CI this causes out-of-memory errors.
+ return
+ }
sink.writeUtf8("abcdef")
sink.writeUtf8("g".repeat(2 * Segment.SIZE))
sink.writeUtf8("hij")
@@ -1163,12 +1168,10 @@ abstract class AbstractBufferedSourceTest internal constructor(
assertEquals("def", source.readUtf8(3))
- try {
+ val e = assertFailsWith<IllegalStateException> {
peek.readUtf8()
- fail()
- } catch (e: IllegalStateException) {
- assertEquals("Peek source is invalid because upstream source was used", e.message)
}
+ assertEquals("Peek source is invalid because upstream source was used", e.message)
}
@Test fun peekSegmentThenInvalid() {
@@ -1186,12 +1189,10 @@ abstract class AbstractBufferedSourceTest internal constructor(
// Skip the rest of the buffered data
peek.skip(peek.buffer.size)
- try {
+ val e = assertFailsWith<IllegalStateException> {
peek.readByte()
- fail()
- } catch (e: IllegalStateException) {
- assertEquals("Peek source is invalid because upstream source was used", e.message)
}
+ assertEquals("Peek source is invalid because upstream source was used", e.message)
}
@Test fun peekDoesntReadTooMuch() {
diff --git a/okio/src/commonTest/kotlin/okio/AbstractFileSystemTest.kt b/okio/src/commonTest/kotlin/okio/AbstractFileSystemTest.kt
deleted file mode 100644
index 669138f5..00000000
--- a/okio/src/commonTest/kotlin/okio/AbstractFileSystemTest.kt
+++ /dev/null
@@ -1,670 +0,0 @@
-/*
- * Copyright (C) 2020 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 kotlinx.datetime.Clock
-import kotlinx.datetime.Instant
-import okio.ByteString.Companion.toByteString
-import okio.Path.Companion.toPath
-import okio.fakefilesystem.FakeFileSystem
-import kotlin.random.Random
-import kotlin.test.BeforeTest
-import kotlin.test.Ignore
-import kotlin.test.Test
-import kotlin.test.assertEquals
-import kotlin.test.assertFailsWith
-import kotlin.test.assertFalse
-import kotlin.test.assertNull
-import kotlin.test.assertTrue
-import kotlin.time.ExperimentalTime
-import kotlin.time.seconds
-
-/** This test assumes that okio-files/ is the current working directory when executed. */
-@ExperimentalTime
-@ExperimentalFileSystem
-abstract class AbstractFileSystemTest(
- val clock: Clock,
- val fileSystem: FileSystem,
- val windowsLimitations: Boolean,
- temporaryDirectory: Path
-) {
- val base: Path = temporaryDirectory / "${this::class.simpleName}-${randomToken()}"
- private val isJs = fileSystem::class.simpleName?.startsWith("NodeJs") ?: false
-
- @BeforeTest
- fun setUp() {
- fileSystem.createDirectory(base)
- }
-
- @Test
- fun canonicalizeDotReturnsCurrentWorkingDirectory() {
- if (fileSystem is FakeFileSystem || fileSystem is ForwardingFileSystem) return
- val cwd = fileSystem.canonicalize(".".toPath())
- val cwdString = cwd.toString()
- assertTrue(cwdString) {
- cwdString.endsWith("okio${Path.DIRECTORY_SEPARATOR}okio") ||
- cwdString.endsWith("${Path.DIRECTORY_SEPARATOR}okio-parent-okio-test") || // JS
- cwdString.contains("/CoreSimulator/Devices/") || // iOS simulator.
- cwdString == "/" // Android emulator.
- }
- }
-
- @Test
- fun canonicalizeNoSuchFile() {
- assertFailsWith<FileNotFoundException> {
- fileSystem.canonicalize(base / "no-such-file")
- }
- }
-
- @Test
- fun list() {
- val target = base / "list"
- target.writeUtf8("hello, world!")
- val entries = fileSystem.list(base)
- assertTrue(entries.toString()) { target in entries }
- }
-
- @Test
- fun listResultsAreSorted() {
- val fileA = base / "a"
- val fileB = base / "b"
- val fileC = base / "c"
- val fileD = base / "d"
-
- // Create files in a different order than the sorted order, so a file system that returns files
- // in creation-order or reverse-creation order won't pass by accident.
- fileD.writeUtf8("fileD")
- fileB.writeUtf8("fileB")
- fileC.writeUtf8("fileC")
- fileA.writeUtf8("fileA")
-
- val entries = fileSystem.list(base)
- assertEquals(entries, listOf(fileA, fileB, fileC, fileD))
- }
-
- @Test
- fun listNoSuchDirectory() {
- assertFailsWith<FileNotFoundException> {
- fileSystem.list(base / "no-such-directory")
- }
- }
-
- @Test
- fun listFile() {
- val target = base / "list"
- target.writeUtf8("hello, world!")
- assertFailsWith<IOException> {
- fileSystem.list(target)
- }
- }
-
- @Test
- fun fileSourceNoSuchDirectory() {
- assertFailsWith<FileNotFoundException> {
- fileSystem.source(base / "no-such-directory" / "file")
- }
- }
-
- @Test
- fun fileSource() {
- val path = base / "file-source"
- path.writeUtf8("hello, world!")
-
- val source = fileSystem.source(path)
- val buffer = Buffer()
- assertTrue(source.read(buffer, 100L) == 13L)
- assertEquals(-1L, source.read(buffer, 100L))
- assertEquals("hello, world!", buffer.readUtf8())
- source.close()
- }
-
- @Test
- fun readPath() {
- val path = base / "read-path"
- val string = "hello, read with a Path"
- path.writeUtf8(string)
-
- val result = fileSystem.read(path) {
- assertEquals("hello", readUtf8(5))
- assertEquals(", read with ", readUtf8(12))
- assertEquals("a Path", readUtf8())
- return@read "success"
- }
- assertEquals("success", result)
- }
-
- @Test
- fun fileSink() {
- val path = base / "file-sink"
- val sink = fileSystem.sink(path)
- val buffer = Buffer().writeUtf8("hello, world!")
- sink.write(buffer, buffer.size)
- sink.close()
- assertTrue(path in fileSystem.list(base))
- assertEquals(0, buffer.size)
- assertEquals("hello, world!", path.readUtf8())
- }
-
- @Test
- fun writePath() {
- val path = base / "write-path"
- val content = fileSystem.write(path) {
- val string = "hello, write with a Path"
- writeUtf8(string)
- return@write string
- }
- assertTrue(path in fileSystem.list(base))
- assertEquals(content, path.readUtf8())
- }
-
- @Test
- fun appendingSinkAppendsToExistingFile() {
- val path = base / "appending-sink-appends-to-existing-file"
- path.writeUtf8("hello, world!\n")
- val sink = fileSystem.appendingSink(path)
- val buffer = Buffer().writeUtf8("this is added later!")
- sink.write(buffer, buffer.size)
- sink.close()
- assertTrue(path in fileSystem.list(base))
- assertEquals("hello, world!\nthis is added later!", path.readUtf8())
- }
-
- @Test
- fun appendingSinkDoesNotImpactExistingFile() {
- val path = base / "appending-sink-does-not-impact-existing-file"
- path.writeUtf8("hello, world!\n")
- val sink = fileSystem.appendingSink(path)
- assertEquals("hello, world!\n", path.readUtf8())
- sink.close()
- assertEquals("hello, world!\n", path.readUtf8())
- }
-
- @Test
- fun appendingSinkCreatesNewFile() {
- val path = base / "appending-sink-creates-new-file"
- val sink = fileSystem.appendingSink(path)
- val buffer = Buffer().writeUtf8("this is all there is!")
- sink.write(buffer, buffer.size)
- sink.close()
- assertTrue(path in fileSystem.list(base))
- assertEquals("this is all there is!", path.readUtf8())
- }
-
- @Test
- fun fileSinkFlush() {
- val path = base / "file-sink"
- val sink = fileSystem.sink(path)
-
- val buffer = Buffer().writeUtf8("hello,")
- sink.write(buffer, buffer.size)
- sink.flush()
- assertEquals("hello,", path.readUtf8())
-
- buffer.writeUtf8(" world!")
- sink.write(buffer, buffer.size)
- sink.close()
- assertEquals("hello, world!", path.readUtf8())
- }
-
- @Test
- fun fileSinkNoSuchDirectory() {
- assertFailsWith<FileNotFoundException> {
- fileSystem.sink(base / "no-such-directory" / "file")
- }
- }
-
- @Test
- fun createDirectory() {
- val path = base / "create-directory"
- fileSystem.createDirectory(path)
- assertTrue(path in fileSystem.list(base))
- }
-
- @Test
- fun createDirectoryAlreadyExists() {
- val path = base / "already-exists"
- fileSystem.createDirectory(path)
- assertFailsWith<IOException> {
- fileSystem.createDirectory(path)
- }
- }
-
- @Test
- fun createDirectoryParentDirectoryDoesNotExist() {
- val path = base / "no-such-directory" / "created"
- assertFailsWith<IOException> {
- fileSystem.createDirectory(path)
- }
- }
-
- @Test
- fun createDirectoriesSingle() {
- val path = base / "create-directories-single"
- fileSystem.createDirectories(path)
- assertTrue(path in fileSystem.list(base))
- assertTrue(fileSystem.metadata(path).isDirectory)
- }
-
- @Test
- fun createDirectoriesAlreadyExists() {
- val path = base / "already-exists"
- fileSystem.createDirectory(path)
- fileSystem.createDirectories(path)
- assertTrue(fileSystem.metadata(path).isDirectory)
- }
-
- @Test
- fun createDirectoriesParentDirectoryDoesNotExist() {
- fileSystem.createDirectories(base / "a" / "b" / "c")
- assertTrue(base / "a" in fileSystem.list(base))
- assertTrue(base / "a" / "b" in fileSystem.list(base / "a"))
- assertTrue(base / "a" / "b" / "c" in fileSystem.list(base / "a" / "b"))
- assertTrue(fileSystem.metadata(base / "a" / "b" / "c").isDirectory)
- }
-
- @Test
- fun createDirectoriesParentIsFile() {
- val file = base / "simple-file"
- file.writeUtf8("just a file")
- assertFailsWith<IOException> {
- fileSystem.createDirectories(file / "child")
- }
- }
-
- @Test
- fun atomicMoveFile() {
- val source = base / "source"
- source.writeUtf8("hello, world!")
- val target = base / "target"
- fileSystem.atomicMove(source, target)
- assertEquals("hello, world!", target.readUtf8())
- assertTrue(source !in fileSystem.list(base))
- assertTrue(target in fileSystem.list(base))
- }
-
- @Test
- fun atomicMoveDirectory() {
- val source = base / "source"
- fileSystem.createDirectory(source)
- val target = base / "target"
- fileSystem.atomicMove(source, target)
- assertTrue(source !in fileSystem.list(base))
- assertTrue(target in fileSystem.list(base))
- }
-
- @Test
- fun atomicMoveSourceIsTarget() {
- val source = base / "source"
- source.writeUtf8("hello, world!")
- fileSystem.atomicMove(source, source)
- assertEquals("hello, world!", source.readUtf8())
- assertTrue(source in fileSystem.list(base))
- }
-
- @Test
- fun atomicMoveClobberExistingFile() {
- val source = base / "source"
- source.writeUtf8("hello, world!")
- val target = base / "target"
- target.writeUtf8("this file will be clobbered!")
- fileSystem.atomicMove(source, target)
- assertEquals("hello, world!", target.readUtf8())
- assertTrue(source !in fileSystem.list(base))
- assertTrue(target in fileSystem.list(base))
- }
-
- @Test
- fun atomicMoveSourceDoesNotExist() {
- val source = base / "source"
- val target = base / "target"
- assertFailsWith<FileNotFoundException> {
- fileSystem.atomicMove(source, target)
- }
- }
-
- @Test
- fun atomicMoveSourceIsFileAndTargetIsDirectory() {
- val source = base / "source"
- source.writeUtf8("hello, world!")
- val target = base / "target"
- fileSystem.createDirectory(target)
- assertFailsWith<IOException> {
- fileSystem.atomicMove(source, target)
- }
- }
-
- @Test
- fun atomicMoveSourceIsDirectoryAndTargetIsFile() {
- val source = base / "source"
- fileSystem.createDirectory(source)
- val target = base / "target"
- target.writeUtf8("hello, world!")
- expectIOExceptionOnEverythingButWindows {
- fileSystem.atomicMove(source, target)
- }
- }
-
- @Test
- fun copyFile() {
- val source = base / "source"
- source.writeUtf8("hello, world!")
- val target = base / "target"
- fileSystem.copy(source, target)
- assertTrue(target in fileSystem.list(base))
- assertEquals("hello, world!", source.readUtf8())
- assertEquals("hello, world!", target.readUtf8())
- }
-
- @Test
- fun copySourceDoesNotExist() {
- val source = base / "source"
- val target = base / "target"
- assertFailsWith<FileNotFoundException> {
- fileSystem.copy(source, target)
- }
- assertFalse(target in fileSystem.list(base))
- }
-
- @Test
- fun copyTargetIsClobbered() {
- val source = base / "source"
- source.writeUtf8("hello, world!")
- val target = base / "target"
- target.writeUtf8("this file will be clobbered!")
- fileSystem.copy(source, target)
- assertTrue(target in fileSystem.list(base))
- assertEquals("hello, world!", target.readUtf8())
- }
-
- @Test
- fun deleteFile() {
- val path = base / "delete-file"
- path.writeUtf8("delete me")
- fileSystem.delete(path)
- assertTrue(path !in fileSystem.list(base))
- }
-
- @Test
- fun deleteEmptyDirectory() {
- val path = base / "delete-empty-directory"
- fileSystem.createDirectory(path)
- fileSystem.delete(path)
- assertTrue(path !in fileSystem.list(base))
- }
-
- @Test
- fun deleteFailsOnNoSuchFile() {
- val path = base / "no-such-file"
- // TODO(jwilson): fix Windows to throw FileNotFoundException on deleting an absent file.
- if (windowsLimitations) {
- assertFailsWith<IOException> {
- fileSystem.delete(path)
- }
- } else {
- assertFailsWith<FileNotFoundException> {
- fileSystem.delete(path)
- }
- }
- }
-
- @Test
- fun deleteFailsOnNonemptyDirectory() {
- val path = base / "non-empty-directory"
- fileSystem.createDirectory(path)
- (path / "file.txt").writeUtf8("inside directory")
- assertFailsWith<IOException> {
- fileSystem.delete(path)
- }
- }
-
- @Test
- fun deleteRecursivelyFile() {
- val path = base / "delete-recursively-file"
- path.writeUtf8("delete me")
- fileSystem.deleteRecursively(path)
- assertTrue(path !in fileSystem.list(base))
- }
-
- @Test
- fun deleteRecursivelyEmptyDirectory() {
- val path = base / "delete-recursively-empty-directory"
- fileSystem.createDirectory(path)
- fileSystem.deleteRecursively(path)
- assertTrue(path !in fileSystem.list(base))
- }
-
- @Test
- fun deleteRecursivelyFailsOnNoSuchFile() {
- val path = base / "no-such-file"
- assertFailsWith<FileNotFoundException> {
- fileSystem.deleteRecursively(path)
- }
- }
-
- @Test
- fun deleteRecursivelyNonemptyDirectory() {
- val path = base / "delete-recursively-non-empty-directory"
- fileSystem.createDirectory(path)
- (path / "file.txt").writeUtf8("inside directory")
- fileSystem.deleteRecursively(path)
- assertTrue(path !in fileSystem.list(base))
- assertTrue((path / "file.txt") !in fileSystem.list(base))
- }
-
- @Test
- fun deleteRecursivelyDeepHierarchy() {
- fileSystem.createDirectory(base / "a")
- fileSystem.createDirectory(base / "a" / "b")
- fileSystem.createDirectory(base / "a" / "b" / "c")
- (base / "a" / "b" / "c" / "d.txt").writeUtf8("inside deep hierarchy")
- fileSystem.deleteRecursively(base / "a")
- assertEquals(fileSystem.list(base), listOf())
- }
-
- @Test
- fun fileMetadata() {
- val minTime = clock.now().minFileSystemTime()
- val path = base / "file-metadata"
- path.writeUtf8("hello, world!")
- val maxTime = clock.now().maxFileSystemTime()
-
- val metadata = fileSystem.metadata(path)
- assertTrue(metadata.isRegularFile)
- assertFalse(metadata.isDirectory)
- assertEquals(13, metadata.size)
- assertInRange(metadata.createdAt, minTime, maxTime)
- assertInRange(metadata.lastModifiedAt, minTime, maxTime)
- assertInRange(metadata.lastAccessedAt, minTime, maxTime)
- }
-
- @Test
- fun directoryMetadata() {
- val minTime = clock.now().minFileSystemTime()
- val path = base / "directory-metadata"
- fileSystem.createDirectory(path)
- val maxTime = clock.now().maxFileSystemTime()
-
- val metadata = fileSystem.metadata(path)
- assertFalse(metadata.isRegularFile)
- assertTrue(metadata.isDirectory)
- // Note that the size check is omitted; we'd expect null but the JVM returns values like 64.
- assertInRange(metadata.createdAt, minTime, maxTime)
- assertInRange(metadata.lastModifiedAt, minTime, maxTime)
- assertInRange(metadata.lastAccessedAt, minTime, maxTime)
- }
-
- @Test
- fun absentMetadataOrNull() {
- val path = base / "no-such-file"
- assertNull(fileSystem.metadataOrNull(path))
- }
-
- @Test
- @Ignore
- fun inaccessibleMetadata() {
- // TODO(swankjesse): configure a test directory in CI that exists, but that this process doesn't
- // have permission to read metadata of. Perhaps a file in another user's /home directory?
- }
-
- @Test
- fun absentMetadata() {
- val path = base / "no-such-file"
- assertFailsWith<FileNotFoundException> {
- fileSystem.metadata(path)
- }
- }
-
- @Test
- fun fileExists() {
- val path = base / "file-exists"
- assertFalse(fileSystem.exists(path))
- path.writeUtf8("hello, world!")
- assertTrue(fileSystem.exists(path))
- }
-
- @Test
- fun directoryExists() {
- val path = base / "directory-exists"
- assertFalse(fileSystem.exists(path))
- fileSystem.createDirectory(path)
- assertTrue(fileSystem.exists(path))
- }
-
- @Test
- fun deleteOpenForWritingFailsOnWindows() {
- val file = base / "file.txt"
- expectIOExceptionOnWindows(exceptJs = true) {
- fileSystem.sink(file).use {
- fileSystem.delete(file)
- }
- }
- }
-
- @Test
- fun deleteOpenForReadingFailsOnWindows() {
- val file = base / "file.txt"
- file.writeUtf8("abc")
- expectIOExceptionOnWindows(exceptJs = true) {
- fileSystem.source(file).use {
- fileSystem.delete(file)
- }
- }
- }
-
- @Test
- fun renameSourceIsOpenFailsOnWindows() {
- val from = base / "from.txt"
- val to = base / "to.txt"
- from.writeUtf8("source file")
- to.writeUtf8("target file")
- expectIOExceptionOnWindows(exceptJs = true) {
- fileSystem.source(from).use {
- fileSystem.atomicMove(from, to)
- }
- }
- }
-
- @Test
- fun renameTargetIsOpenFailsOnWindows() {
- val from = base / "from.txt"
- val to = base / "to.txt"
- from.writeUtf8("source file")
- to.writeUtf8("target file")
- expectIOExceptionOnWindows {
- fileSystem.source(to).use {
- fileSystem.atomicMove(from, to)
- }
- }
- }
-
- @Test
- fun deleteContentsOfParentOfFileOpenForReadingFailsOnWindows() {
- val parentA = (base / "a")
- fileSystem.createDirectory(parentA)
- val parentAB = parentA / "b"
- fileSystem.createDirectory(parentAB)
- val parentABC = parentAB / "c"
- fileSystem.createDirectory(parentABC)
- val file = parentABC / "file.txt"
- file.writeUtf8("child file")
- expectIOExceptionOnWindows {
- fileSystem.source(file).use {
- fileSystem.delete(file)
- fileSystem.delete(parentABC)
- fileSystem.delete(parentAB)
- fileSystem.delete(parentA)
- }
- }
- }
-
- private fun expectIOExceptionOnWindows(exceptJs: Boolean = false, block: () -> Unit) {
- val expectCrash = windowsLimitations && (!isJs || !exceptJs)
- try {
- block()
- assertFalse(expectCrash)
- } catch (_: IOException) {
- assertTrue(expectCrash)
- }
- }
-
- private fun expectIOExceptionOnEverythingButWindows(block: () -> Unit) {
- try {
- block()
- assertTrue(windowsLimitations)
- } catch (e: IOException) {
- assertFalse(windowsLimitations)
- }
- }
-
- private fun randomToken() = Random.nextBytes(16).toByteString(0, 16).hex()
-
- fun Path.readUtf8(): String {
- return fileSystem.source(this).buffer().use {
- it.readUtf8()
- }
- }
-
- fun Path.writeUtf8(string: String) {
- fileSystem.sink(this).buffer().use {
- it.writeUtf8(string)
- }
- }
-
- /**
- * Returns the earliest file system time that could be recorded for an event occurring at this
- * instant. This truncates fractional seconds because most host file systems do not use precise
- * timestamps for file metadata.
- */
- private fun Instant.minFileSystemTime(): Instant {
- return Instant.fromEpochSeconds(epochSeconds)
- }
-
- /**
- * Returns the latest file system time that could be recorded for an event occurring at this
- * instant. This adds 2 seconds and truncates fractional seconds because file systems may defer
- * assigning the timestamp.
- *
- * https://docs.microsoft.com/en-us/windows/win32/sysinfo/file-times
- */
- private fun Instant.maxFileSystemTime(): Instant {
- return Instant.fromEpochSeconds(plus(2.seconds).epochSeconds)
- }
-
- private fun assertInRange(sampled: Instant?, minTime: Instant, maxTime: Instant) {
- if (sampled == null) return
- assertTrue("expected $sampled in $minTime..$maxTime") { sampled in minTime..maxTime }
- }
-}
diff --git a/okio/src/commonTest/kotlin/okio/BufferCommonTest.kt b/okio/src/commonTest/kotlin/okio/BufferCommonTest.kt
index 842faffe..cc946883 100644
--- a/okio/src/commonTest/kotlin/okio/BufferCommonTest.kt
+++ b/okio/src/commonTest/kotlin/okio/BufferCommonTest.kt
@@ -15,9 +15,9 @@
*/
package okio
-import okio.ByteString.Companion.encodeUtf8
import kotlin.test.Test
import kotlin.test.assertEquals
+import okio.ByteString.Companion.encodeUtf8
class BufferCommonTest {
diff --git a/okio/src/commonTest/kotlin/okio/BufferedSourceFactory.kt b/okio/src/commonTest/kotlin/okio/BufferedSourceFactory.kt
index b9836202..173bb841 100644
--- a/okio/src/commonTest/kotlin/okio/BufferedSourceFactory.kt
+++ b/okio/src/commonTest/kotlin/okio/BufferedSourceFactory.kt
@@ -19,7 +19,7 @@ package okio
interface BufferedSourceFactory {
class Pipe(
var sink: BufferedSink,
- var source: BufferedSource
+ var source: BufferedSource,
)
val isOneByteAtATime: Boolean
@@ -36,7 +36,7 @@ interface BufferedSourceFactory {
val buffer = Buffer()
return Pipe(
buffer,
- buffer
+ buffer,
)
}
}
@@ -51,7 +51,7 @@ interface BufferedSourceFactory {
val buffer = Buffer()
return Pipe(
buffer,
- (buffer as Source).buffer()
+ (buffer as Source).buffer(),
)
}
}
@@ -79,7 +79,7 @@ interface BufferedSourceFactory {
if (result > 0L) sink.write(box.copy(), result)
return result
}
- }.buffer()
+ }.buffer(),
)
}
}
@@ -104,7 +104,7 @@ interface BufferedSourceFactory {
}
}
}.buffer(),
- buffer
+ buffer,
)
}
}
@@ -118,7 +118,7 @@ interface BufferedSourceFactory {
val buffer = Buffer()
return Pipe(
buffer,
- buffer.peek()
+ buffer.peek(),
)
}
}
@@ -133,7 +133,7 @@ interface BufferedSourceFactory {
val buffer = Buffer()
return Pipe(
buffer,
- (buffer as Source).buffer().peek()
+ (buffer as Source).buffer().peek(),
)
}
}
@@ -144,7 +144,7 @@ interface BufferedSourceFactory {
arrayOf(ONE_BYTE_AT_A_TIME_BUFFERED_SOURCE),
arrayOf(ONE_BYTE_AT_A_TIME_BUFFER),
arrayOf(PEEK_BUFFER),
- arrayOf(PEEK_BUFFERED_SOURCE)
+ arrayOf(PEEK_BUFFERED_SOURCE),
)
}
}
diff --git a/okio/src/commonTest/kotlin/okio/FakeClock.kt b/okio/src/commonTest/kotlin/okio/ByteStringMoreTests.kt
index 31cf5503..d9721d16 100644
--- a/okio/src/commonTest/kotlin/okio/FakeClock.kt
+++ b/okio/src/commonTest/kotlin/okio/ByteStringMoreTests.kt
@@ -1,11 +1,11 @@
/*
- * Copyright (C) 2020 Square, Inc.
+ * Copyright (C) 2022 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
+ * 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,
@@ -13,20 +13,17 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package okio
-
-import kotlinx.datetime.Clock
-import kotlinx.datetime.Instant
-import kotlin.time.Duration
-import kotlin.time.ExperimentalTime
-@ExperimentalTime
-internal class FakeClock : Clock {
- var time = Instant.parse("2021-01-01T00:00:00Z")
+package okio
- override fun now() = time
+import kotlin.test.Test
+import kotlin.test.assertEquals
+import okio.ByteString.Companion.toByteString
- fun sleep(duration: Duration) {
- time = time.plus(duration)
+class ByteStringMoreTests {
+ @Test fun arrayToByteString() {
+ val actual = byteArrayOf(1, 2, 3, 4).toByteString()
+ val expected = ByteString.of(1, 2, 3, 4)
+ assertEquals(actual, expected)
}
}
diff --git a/okio/src/commonTest/kotlin/okio/ByteStringTest.kt b/okio/src/commonTest/kotlin/okio/ByteStringTest.kt
index c75c4581..9866e14b 100644
--- a/okio/src/commonTest/kotlin/okio/ByteStringTest.kt
+++ b/okio/src/commonTest/kotlin/okio/ByteStringTest.kt
@@ -16,10 +16,6 @@
package okio
-import okio.ByteString.Companion.decodeBase64
-import okio.ByteString.Companion.decodeHex
-import okio.ByteString.Companion.encodeUtf8
-import okio.internal.commonAsUtf8ToByteArray
import kotlin.random.Random
import kotlin.test.Test
import kotlin.test.assertEquals
@@ -29,6 +25,11 @@ import kotlin.test.assertNotEquals
import kotlin.test.assertSame
import kotlin.test.assertTrue
import kotlin.test.fail
+import okio.ByteString.Companion.decodeBase64
+import okio.ByteString.Companion.decodeHex
+import okio.ByteString.Companion.encodeUtf8
+import okio.ByteString.Companion.toByteString
+import okio.internal.commonAsUtf8ToByteArray
class ByteStringTest : AbstractByteStringTest(ByteStringFactory.BYTE_STRING)
class SegmentedByteStringTest : AbstractByteStringTest(ByteStringFactory.SEGMENTED_BYTE_STRING)
@@ -36,14 +37,14 @@ class ByteStringOneBytePerSegmentTest : AbstractByteStringTest(ByteStringFactory
class OkioEncoderTest : AbstractByteStringTest(ByteStringFactory.OKIO_ENCODER)
abstract class AbstractByteStringTest internal constructor(
- private val factory: ByteStringFactory
+ private val factory: ByteStringFactory,
) {
@Test fun get() {
val actual = factory.encodeUtf8("abc")
assertEquals(3, actual.size)
- assertEquals(actual[0], 'a'.toByte())
- assertEquals(actual[1], 'b'.toByte())
- assertEquals(actual[2], 'c'.toByte())
+ assertEquals(actual[0], 'a'.code.toByte())
+ assertEquals(actual[1], 'b'.code.toByte())
+ assertEquals(actual[2], 'c'.code.toByte())
try {
actual[-1]
fail("no index out of bounds: -1")
@@ -214,7 +215,7 @@ abstract class AbstractByteStringTest internal constructor(
(
"d09dd0b020d0b1d0b5d180d0b5d0b3d18320d0bfd183d181" +
"d182d18bd0bdd0bdd18bd18520d0b2d0bed0bbd0bd"
- ).decodeHex()
+ ).decodeHex(),
)
assertEquals(byteString.utf8(), bronzeHorseman)
}
@@ -277,7 +278,7 @@ abstract class AbstractByteStringTest internal constructor(
assertEquals("AAAA", factory.encodeUtf8("\u0000\u0000\u0000").base64())
assertEquals(
"SG93IG1hbnkgbGluZXMgb2YgY29kZSBhcmUgdGhlcmU/ICdib3V0IDIgbWlsbGlvbi4=",
- factory.encodeUtf8("How many lines of code are there? 'bout 2 million.").base64()
+ factory.encodeUtf8("How many lines of code are there? 'bout 2 million.").base64(),
)
}
@@ -288,7 +289,7 @@ abstract class AbstractByteStringTest internal constructor(
assertEquals("AAAA", factory.encodeUtf8("\u0000\u0000\u0000").base64Url())
assertEquals(
"SG93IG1hbnkgbGluZXMgb2YgY29kZSBhcmUgdGhlcmU_ICdib3V0IDIgbWlsbGlvbi4=",
- factory.encodeUtf8("How many lines of code are there? 'bout 2 million.").base64Url()
+ factory.encodeUtf8("How many lines of code are there? 'bout 2 million.").base64Url(),
)
}
@@ -313,7 +314,7 @@ abstract class AbstractByteStringTest internal constructor(
(
"V2hhdCdzIHRvIGJlIHNjYXJlZCBhYm91dD8gSXQncyBqdXN0IGEgbGl0dGxlIGhpY2" +
"N1cCBpbiB0aGUgcG93ZXIuLi4="
- ).decodeBase64()!!.utf8()
+ ).decodeBase64()!!.utf8(),
)
// Uses two encoding styles. Malformed, but supported as a side-effect.
assertEquals("ffffff".decodeHex(), "__//".decodeBase64())
@@ -358,11 +359,11 @@ abstract class AbstractByteStringTest internal constructor(
@Test fun toStringOnShortText() {
assertEquals(
"[text=Tyrannosaur]",
- factory.encodeUtf8("Tyrannosaur").toString()
+ factory.encodeUtf8("Tyrannosaur").toString(),
)
assertEquals(
"[text=təˈranəˌsôr]",
- factory.decodeHex("74c999cb8872616ec999cb8c73c3b472").toString()
+ factory.decodeHex("74c999cb8872616ec999cb8c73c3b472").toString(),
)
}
@@ -379,7 +380,7 @@ abstract class AbstractByteStringTest internal constructor(
assertEquals(
"[size=517 text=Um, I'll tell you the problem with the scientific power that " +
"you…]",
- factory.encodeUtf8(raw).toString()
+ factory.encodeUtf8(raw).toString(),
)
val war = (
"Սm, I'll 𝓽𝖾ll ᶌօ𝘂 ᴛℎ℮ 𝜚𝕣०bl𝖾m wі𝕥𝒽 𝘵𝘩𝐞 𝓼𝙘𝐢𝔢𝓷𝗍𝜄𝚏𝑖c 𝛠𝝾w𝚎𝑟 𝕥h⍺𝞃 𝛄𝓸𝘂'𝒓𝗲 υ𝖘𝓲𝗇ɡ 𝕙𝚎𝑟e, " +
@@ -392,7 +393,7 @@ abstract class AbstractByteStringTest internal constructor(
assertEquals(
"[size=1496 text=Սm, I'll 𝓽𝖾ll ᶌօ𝘂 ᴛℎ℮ 𝜚𝕣०bl𝖾m wі𝕥𝒽 𝘵𝘩𝐞 𝓼𝙘𝐢𝔢𝓷𝗍𝜄𝚏𝑖c 𝛠𝝾w𝚎𝑟 𝕥h⍺𝞃 " +
"𝛄𝓸𝘂…]",
- factory.encodeUtf8(war).toString()
+ factory.encodeUtf8(war).toString(),
)
}
@@ -400,7 +401,7 @@ abstract class AbstractByteStringTest internal constructor(
// Instead of emitting a literal newline in the toString(), these are escaped as "\n".
assertEquals(
"[text=a\\r\\nb\\nc\\rd\\\\e]",
- factory.encodeUtf8("a\r\nb\nc\rd\\e").toString()
+ factory.encodeUtf8("a\r\nb\nc\rd\\e").toString(),
)
}
@@ -408,13 +409,13 @@ abstract class AbstractByteStringTest internal constructor(
val byteString = factory.decodeHex(
"" +
"60b420bb3851d9d47acb933dbe70399bf6c92da33af01d4fb770e98c0325f41d3ebaf8986da712c82bcd4d55" +
- "4bf0b54023c29b624de9ef9c2f931efc580f9afb"
+ "4bf0b54023c29b624de9ef9c2f931efc580f9afb",
)
assertEquals(
"[hex=" +
"60b420bb3851d9d47acb933dbe70399bf6c92da33af01d4fb770e98c0325f41d3ebaf8986da712c82bcd4d55" +
"4bf0b54023c29b624de9ef9c2f931efc580f9afb]",
- byteString.toString()
+ byteString.toString(),
)
}
@@ -422,13 +423,13 @@ abstract class AbstractByteStringTest internal constructor(
val byteString = factory.decodeHex(
"" +
"60b420bb3851d9d47acb933dbe70399bf6c92da33af01d4fb770e98c0325f41d3ebaf8986da712c82bcd4d55" +
- "4bf0b54023c29b624de9ef9c2f931efc580f9afba1"
+ "4bf0b54023c29b624de9ef9c2f931efc580f9afba1",
)
assertEquals(
"[size=65 hex=" +
"60b420bb3851d9d47acb933dbe70399bf6c92da33af01d4fb770e98c0325f41d3ebaf8986da712c82bcd4d55" +
"4bf0b54023c29b624de9ef9c2f931efc580f9afb…]",
- byteString.toString()
+ byteString.toString(),
)
}
@@ -441,7 +442,7 @@ abstract class AbstractByteStringTest internal constructor(
factory.decodeHex("80"),
factory.decodeHex("81"),
factory.decodeHex("fe"),
- factory.decodeHex("ff")
+ factory.decodeHex("ff"),
)
val sortedByteStrings = originalByteStrings.toMutableList()
@@ -479,7 +480,7 @@ abstract class AbstractByteStringTest internal constructor(
factory.decodeHex("010101"),
factory.decodeHex("7f0000"),
factory.decodeHex("7f0000ffff"),
- factory.decodeHex("ffffff")
+ factory.decodeHex("ffffff"),
)
val sortedByteStrings = originalByteStrings.toMutableList()
@@ -496,4 +497,101 @@ abstract class AbstractByteStringTest internal constructor(
assertEquals("0e4dd66217fc8d2e298b78c8cd9392870dcd065d0ff675d0edff5bcd227837e9", sha256().hex())
assertEquals("483676b93c4417198b465083d196ec6a9fab8d004515874b8ff47e041f5f56303cc08179625030b8b5b721c09149a18f0f59e64e7ae099518cea78d3d83167e1", sha512().hex())
}
+
+ @Test fun copyInto() {
+ val byteString = factory.encodeUtf8("abcdefgh")
+ val byteArray = "WwwwXxxxYyyyZzzz".encodeToByteArray()
+ byteString.copyInto(target = byteArray, byteCount = 5)
+ assertEquals("abcdexxxYyyyZzzz", byteArray.decodeToString())
+ }
+
+ @Test fun copyIntoFullRange() {
+ val byteString = factory.encodeUtf8("abcdefghijklmnop")
+ val byteArray = "WwwwXxxxYyyyZzzz".encodeToByteArray()
+ byteString.copyInto(target = byteArray, byteCount = 16)
+ assertEquals("abcdefghijklmnop", byteArray.decodeToString())
+ }
+
+ @Test fun copyIntoWithTargetOffset() {
+ val byteString = factory.encodeUtf8("abcdefgh")
+ val byteArray = "WwwwXxxxYyyyZzzz".encodeToByteArray()
+ byteString.copyInto(target = byteArray, targetOffset = 11, byteCount = 5)
+ assertEquals("WwwwXxxxYyyabcde", byteArray.decodeToString())
+ }
+
+ @Test fun copyIntoWithSourceOffset() {
+ val byteString = factory.encodeUtf8("abcdefgh")
+ val byteArray = "WwwwXxxxYyyyZzzz".encodeToByteArray()
+ byteString.copyInto(offset = 3, target = byteArray, byteCount = 5)
+ assertEquals("defghxxxYyyyZzzz", byteArray.decodeToString())
+ }
+
+ @Test fun copyIntoWithAllParameters() {
+ val byteString = factory.encodeUtf8("abcdefgh")
+ val byteArray = "WwwwXxxxYyyyZzzz".encodeToByteArray()
+ byteString.copyInto(offset = 3, target = byteArray, targetOffset = 11, byteCount = 5)
+ assertEquals("WwwwXxxxYyydefgh", byteArray.decodeToString())
+ }
+
+ @Test fun copyIntoBoundsChecks() {
+ val byteString = factory.encodeUtf8("abcdefgh")
+ val byteArray = "WwwwXxxxYyyyZzzz".encodeToByteArray()
+ assertFailsWith<IndexOutOfBoundsException> {
+ byteString.copyInto(offset = -1, target = byteArray, targetOffset = 1, byteCount = 1)
+ }
+ assertFailsWith<IndexOutOfBoundsException> {
+ byteString.copyInto(offset = 9, target = byteArray, targetOffset = 0, byteCount = 0)
+ }
+ assertFailsWith<IndexOutOfBoundsException> {
+ byteString.copyInto(offset = 1, target = byteArray, targetOffset = -1, byteCount = 1)
+ }
+ assertFailsWith<IndexOutOfBoundsException> {
+ byteString.copyInto(offset = 1, target = byteArray, targetOffset = 17, byteCount = 1)
+ }
+ assertFailsWith<IndexOutOfBoundsException> {
+ byteString.copyInto(offset = 7, target = byteArray, targetOffset = 1, byteCount = 2)
+ }
+ assertFailsWith<IndexOutOfBoundsException> {
+ byteString.copyInto(offset = 1, target = byteArray, targetOffset = 15, byteCount = 2)
+ }
+ }
+
+ @Test fun copyEmptyAtBounds() {
+ val byteString = factory.encodeUtf8("abcdefgh")
+ val byteArray = "WwwwXxxxYyyyZzzz".encodeToByteArray()
+ byteString.copyInto(offset = 0, target = byteArray, targetOffset = 0, byteCount = 0)
+ assertEquals("WwwwXxxxYyyyZzzz", byteArray.decodeToString())
+ byteString.copyInto(offset = 0, target = byteArray, targetOffset = 16, byteCount = 0)
+ assertEquals("WwwwXxxxYyyyZzzz", byteArray.decodeToString())
+ byteString.copyInto(offset = 8, target = byteArray, targetOffset = 0, byteCount = 0)
+ assertEquals("WwwwXxxxYyyyZzzz", byteArray.decodeToString())
+ }
+
+ @Test
+ fun ofCopy() {
+ val bytes = "Hello, World!".encodeToByteArray()
+ val byteString = ByteString.of(*bytes)
+ // Verify that the bytes were copied out.
+ bytes[4] = 'a'.code.toByte()
+ assertEquals("Hello, World!", byteString.utf8())
+ }
+
+ @Test
+ fun ofCopyRange() {
+ val bytes = "Hello, World!".encodeToByteArray()
+ val byteString: ByteString = bytes.toByteString(2, 9)
+ // Verify that the bytes were copied out.
+ bytes[4] = 'a'.code.toByte()
+ assertEquals("llo, Worl", byteString.utf8())
+ }
+
+ @Test
+ fun getByteOutOfBounds() {
+ val byteString = factory.decodeHex("ab12")
+ try {
+ byteString[2]
+ fail()
+ } catch (expected: IndexOutOfBoundsException) {
+ }
+ }
}
diff --git a/okio/src/commonTest/kotlin/okio/CommonBufferTest.kt b/okio/src/commonTest/kotlin/okio/CommonBufferTest.kt
index 292e3c5c..0dbaf021 100644
--- a/okio/src/commonTest/kotlin/okio/CommonBufferTest.kt
+++ b/okio/src/commonTest/kotlin/okio/CommonBufferTest.kt
@@ -15,13 +15,13 @@
*/
package okio
-import okio.ByteString.Companion.decodeHex
import kotlin.random.Random
import kotlin.test.Test
import kotlin.test.assertEquals
import kotlin.test.assertFailsWith
import kotlin.test.assertFalse
import kotlin.test.assertTrue
+import okio.ByteString.Companion.decodeHex
/**
* Tests solely for the behavior of Buffer's implementation. For generic BufferedSink or
@@ -48,22 +48,22 @@ class CommonBufferTest {
assertEquals("[size=0]", Buffer().toString())
assertEquals(
"[text=a\\r\\nb\\nc\\rd\\\\e]",
- Buffer().writeUtf8("a\r\nb\nc\rd\\e").toString()
+ Buffer().writeUtf8("a\r\nb\nc\rd\\e").toString(),
)
assertEquals(
"[text=Tyrannosaur]",
- Buffer().writeUtf8("Tyrannosaur").toString()
+ Buffer().writeUtf8("Tyrannosaur").toString(),
)
assertEquals(
"[text=təˈranəˌsôr]",
Buffer()
.write("74c999cb8872616ec999cb8c73c3b472".decodeHex())
- .toString()
+ .toString(),
)
assertEquals(
"[hex=0000000000000000000000000000000000000000000000000000000000000000000000000000" +
"0000000000000000000000000000000000000000000000000000]",
- Buffer().write(ByteArray(64)).toString()
+ Buffer().write(ByteArray(64)).toString(),
)
}
@@ -127,10 +127,16 @@ class CommonBufferTest {
val segmentSizes = moveBytesBetweenBuffers('a'.repeat(size), 'b'.repeat(size))
assertEquals(
listOf(
- Segment.SIZE, Segment.SIZE, Segment.SIZE, 1,
- Segment.SIZE, Segment.SIZE, Segment.SIZE, 1
+ Segment.SIZE,
+ Segment.SIZE,
+ Segment.SIZE,
+ 1,
+ Segment.SIZE,
+ Segment.SIZE,
+ Segment.SIZE,
+ 1,
),
- segmentSizes
+ segmentSizes,
)
}
@@ -240,14 +246,14 @@ class CommonBufferTest {
buffer.writeUtf8('b'.repeat(halfSegment))
buffer.writeUtf8('c'.repeat(halfSegment))
buffer.writeUtf8('d'.repeat(halfSegment))
- assertEquals(0, buffer.indexOf('a'.toByte(), 0))
- assertEquals((halfSegment - 1).toLong(), buffer.indexOf('a'.toByte(), (halfSegment - 1).toLong()))
- assertEquals(halfSegment.toLong(), buffer.indexOf('b'.toByte(), (halfSegment - 1).toLong()))
- assertEquals((halfSegment * 2).toLong(), buffer.indexOf('c'.toByte(), (halfSegment - 1).toLong()))
- assertEquals((halfSegment * 3).toLong(), buffer.indexOf('d'.toByte(), (halfSegment - 1).toLong()))
- assertEquals((halfSegment * 3).toLong(), buffer.indexOf('d'.toByte(), (halfSegment * 2).toLong()))
- assertEquals((halfSegment * 3).toLong(), buffer.indexOf('d'.toByte(), (halfSegment * 3).toLong()))
- assertEquals((halfSegment * 4 - 1).toLong(), buffer.indexOf('d'.toByte(), (halfSegment * 4 - 1).toLong()))
+ assertEquals(0, buffer.indexOf('a'.code.toByte(), 0))
+ assertEquals((halfSegment - 1).toLong(), buffer.indexOf('a'.code.toByte(), (halfSegment - 1).toLong()))
+ assertEquals(halfSegment.toLong(), buffer.indexOf('b'.code.toByte(), (halfSegment - 1).toLong()))
+ assertEquals((halfSegment * 2).toLong(), buffer.indexOf('c'.code.toByte(), (halfSegment - 1).toLong()))
+ assertEquals((halfSegment * 3).toLong(), buffer.indexOf('d'.code.toByte(), (halfSegment - 1).toLong()))
+ assertEquals((halfSegment * 3).toLong(), buffer.indexOf('d'.code.toByte(), (halfSegment * 2).toLong()))
+ assertEquals((halfSegment * 3).toLong(), buffer.indexOf('d'.code.toByte(), (halfSegment * 3).toLong()))
+ assertEquals((halfSegment * 4 - 1).toLong(), buffer.indexOf('d'.code.toByte(), (halfSegment * 4 - 1).toLong()))
}
@Test fun byteAt() {
@@ -255,11 +261,11 @@ class CommonBufferTest {
buffer.writeUtf8("a")
buffer.writeUtf8('b'.repeat(Segment.SIZE))
buffer.writeUtf8("c")
- assertEquals('a'.toLong(), buffer[0].toLong())
- assertEquals('a'.toLong(), buffer[0].toLong()) // getByte doesn't mutate!
- assertEquals('c'.toLong(), buffer[buffer.size - 1].toLong())
- assertEquals('b'.toLong(), buffer[buffer.size - 2].toLong())
- assertEquals('b'.toLong(), buffer[buffer.size - 3].toLong())
+ assertEquals('a'.code.toLong(), buffer[0].toLong())
+ assertEquals('a'.code.toLong(), buffer[0].toLong()) // getByte doesn't mutate!
+ assertEquals('c'.code.toLong(), buffer[buffer.size - 1].toLong())
+ assertEquals('b'.code.toLong(), buffer[buffer.size - 2].toLong())
+ assertEquals('b'.code.toLong(), buffer[buffer.size - 3].toLong())
}
@Test fun getByteOfEmptyBuffer() {
@@ -279,7 +285,8 @@ class CommonBufferTest {
}
@Suppress("ReplaceAssertBooleanWithAssertEquality")
- @Test fun equalsAndHashCodeEmpty() {
+ @Test
+ fun equalsAndHashCodeEmpty() {
val a = Buffer()
val b = Buffer()
assertTrue(a == b)
@@ -287,7 +294,8 @@ class CommonBufferTest {
}
@Suppress("ReplaceAssertBooleanWithAssertEquality")
- @Test fun equalsAndHashCode() {
+ @Test
+ fun equalsAndHashCode() {
val a = Buffer().writeUtf8("dog")
val b = Buffer().writeUtf8("hotdog")
assertFalse(a == b)
@@ -299,7 +307,8 @@ class CommonBufferTest {
}
@Suppress("ReplaceAssertBooleanWithAssertEquality")
- @Test fun equalsAndHashCodeSpanningSegments() {
+ @Test
+ fun equalsAndHashCodeSpanningSegments() {
val data = ByteArray(1024 * 1024)
val dice = Random(0)
dice.nextBytes(data)
@@ -323,13 +332,13 @@ class CommonBufferTest {
val write1 = Buffer().writeUtf8(
'a'.repeat(Segment.SIZE) +
'b'.repeat(Segment.SIZE) +
- 'c'.repeat(Segment.SIZE)
+ 'c'.repeat(Segment.SIZE),
)
val source = Buffer().writeUtf8(
'a'.repeat(Segment.SIZE) +
'b'.repeat(Segment.SIZE) +
- 'c'.repeat(Segment.SIZE)
+ 'c'.repeat(Segment.SIZE),
)
val mockSink = MockSink()
diff --git a/okio/src/commonTest/kotlin/okio/CommonOptionsTest.kt b/okio/src/commonTest/kotlin/okio/CommonOptionsTest.kt
index bb45321d..ae8156d6 100644
--- a/okio/src/commonTest/kotlin/okio/CommonOptionsTest.kt
+++ b/okio/src/commonTest/kotlin/okio/CommonOptionsTest.kt
@@ -15,11 +15,11 @@
*/
package okio
-import okio.ByteString.Companion.encodeUtf8
import kotlin.test.Test
import kotlin.test.assertEquals
import kotlin.test.assertFailsWith
import kotlin.test.fail
+import okio.ByteString.Companion.encodeUtf8
class CommonOptionsTest {
/** Confirm that options prefers the first-listed option, not the longest or shortest one. */
@@ -32,12 +32,13 @@ class CommonOptionsTest {
assertEquals(
utf8Options("hotdog", "hoth", "hot").trieString(),
"""
- |hot
- | -> 2
- | d
- | og -> 0
- | h -> 1
- |""".trimMargin()
+ |hot
+ | -> 2
+ | d
+ | og -> 0
+ | h -> 1
+ |
+ """.trimMargin(),
)
}
@@ -70,81 +71,82 @@ class CommonOptionsTest {
"connectTimeout",
"readTimeout",
"writeTimeout",
- "pingInterval"
+ "pingInterval",
)
assertEquals(
options.trieString(),
"""
- |a
- | uthenticator -> 17
- |c
- | a
- | che -> 9
- | e
- | rtificate
- | C
- | hainCleaner -> 13
- | P
- | inner -> 15
- | o
- | n
- | nect
- | T
- | imeout -> 23
- | i
- | on
- | P
- | ool -> 18
- | S
- | pecs -> 3
- | o
- | kieJar -> 8
- |d
- | i
- | spatcher -> 0
- | n
- | s -> 19
- |e
- | ventListenerFactory -> 6
- |f
- | ollow
- | R
- | edirects -> 21
- | S
- | slRedirects -> 20
- |h
- | ostnameVerifier -> 14
- |i
- | nter
- | c
- | eptors -> 4
- | n
- | alCache -> 10
- |n
- | etworkInterceptors -> 5
- |p
- | i
- | ngInterval -> 26
- | r
- | o
- | t
- | ocols -> 2
- | x
- | y -> 1
- |r
- | e
- | a
- | dTimeout -> 24
- | t
- | ryOnConnectionFailure -> 22
- |s
- | o
- | cketFactory -> 11
- | s
- | lSocketFactory -> 12
- |w
- | riteTimeout -> 25
- |""".trimMargin()
+ |a
+ | uthenticator -> 17
+ |c
+ | a
+ | che -> 9
+ | e
+ | rtificate
+ | C
+ | hainCleaner -> 13
+ | P
+ | inner -> 15
+ | o
+ | n
+ | nect
+ | T
+ | imeout -> 23
+ | i
+ | on
+ | P
+ | ool -> 18
+ | S
+ | pecs -> 3
+ | o
+ | kieJar -> 8
+ |d
+ | i
+ | spatcher -> 0
+ | n
+ | s -> 19
+ |e
+ | ventListenerFactory -> 6
+ |f
+ | ollow
+ | R
+ | edirects -> 21
+ | S
+ | slRedirects -> 20
+ |h
+ | ostnameVerifier -> 14
+ |i
+ | nter
+ | c
+ | eptors -> 4
+ | n
+ | alCache -> 10
+ |n
+ | etworkInterceptors -> 5
+ |p
+ | i
+ | ngInterval -> 26
+ | r
+ | o
+ | t
+ | ocols -> 2
+ | x
+ | y -> 1
+ |r
+ | e
+ | a
+ | dTimeout -> 24
+ | t
+ | ryOnConnectionFailure -> 22
+ |s
+ | o
+ | cketFactory -> 11
+ | s
+ | lSocketFactory -> 12
+ |w
+ | riteTimeout -> 25
+ |
+ """.trimMargin(),
)
assertSelect("", -1, options)
assertSelect("a", -1, options)
@@ -212,10 +214,11 @@ class CommonOptionsTest {
assertEquals(
options.trieString(),
"""
- |abc
- | -> 1
- | A -> 0
- |""".trimMargin()
+ |abc
+ | -> 1
+ | A -> 0
+ |
+ """.trimMargin(),
)
assertSelect("abc", 1, options)
assertSelect("abcA", 0, options)
@@ -228,35 +231,39 @@ class CommonOptionsTest {
assertEquals(
utf8Options("a", "ab", "abc", "abcd", "abcde").trieString(),
"""
- |a -> 0
- |""".trimMargin()
+ |a -> 0
+ |
+ """.trimMargin(),
)
assertEquals(
utf8Options("abc", "a", "ab", "abe", "abcd", "abcf").trieString(),
"""
- |a
- | -> 1
- | bc -> 0
- |""".trimMargin()
+ |a
+ | -> 1
+ | bc -> 0
+ |
+ """.trimMargin(),
)
assertEquals(
utf8Options("abc", "ab", "a").trieString(),
"""
- |a
- | -> 2
- | b
- | -> 1
- | c -> 0
- |""".trimMargin()
+ |a
+ | -> 2
+ | b
+ | -> 1
+ | c -> 0
+ |
+ """.trimMargin(),
)
assertEquals(
utf8Options("abcd", "abce", "abc", "abcf", "abcg").trieString(),
"""
- |abc
- | -> 2
- | d -> 0
- | e -> 1
- |""".trimMargin()
+ |abc
+ | -> 2
+ | d -> 0
+ | e -> 1
+ |
+ """.trimMargin(),
)
}
diff --git a/okio/src/commonTest/kotlin/okio/CommonRealBufferedSinkTest.kt b/okio/src/commonTest/kotlin/okio/CommonRealBufferedSinkTest.kt
index abbbae8b..eec7607a 100644
--- a/okio/src/commonTest/kotlin/okio/CommonRealBufferedSinkTest.kt
+++ b/okio/src/commonTest/kotlin/okio/CommonRealBufferedSinkTest.kt
@@ -47,7 +47,7 @@ class CommonRealBufferedSinkTest {
@Test fun bufferedSinkFlush() {
val sink = Buffer()
val bufferedSink = (sink as Sink).buffer()
- bufferedSink.writeByte('a'.toInt())
+ bufferedSink.writeByte('a'.code)
assertEquals(0, sink.size)
bufferedSink.flush()
assertEquals(0, bufferedSink.buffer.size)
@@ -93,9 +93,9 @@ class CommonRealBufferedSinkTest {
@Test fun closeWithExceptionWhenWriting() {
val mockSink = MockSink()
- mockSink.scheduleThrow(0, IOException())
+ mockSink.scheduleThrow(0, IOException("boom"))
val bufferedSink = mockSink.buffer()
- bufferedSink.writeByte('a'.toInt())
+ bufferedSink.writeByte('a'.code)
assertFailsWith<IOException> {
bufferedSink.close()
}
@@ -105,9 +105,9 @@ class CommonRealBufferedSinkTest {
@Test fun closeWithExceptionWhenClosing() {
val mockSink = MockSink()
- mockSink.scheduleThrow(1, IOException())
+ mockSink.scheduleThrow(1, IOException("boom"))
val bufferedSink = mockSink.buffer()
- bufferedSink.writeByte('a'.toInt())
+ bufferedSink.writeByte('a'.code)
assertFailsWith<IOException> {
bufferedSink.close()
}
@@ -120,7 +120,7 @@ class CommonRealBufferedSinkTest {
mockSink.scheduleThrow(0, IOException("first"))
mockSink.scheduleThrow(1, IOException("second"))
val bufferedSink = mockSink.buffer()
- bufferedSink.writeByte('a'.toInt())
+ bufferedSink.writeByte('a'.code)
try {
bufferedSink.close()
fail()
@@ -134,12 +134,12 @@ class CommonRealBufferedSinkTest {
@Test fun operationsAfterClose() {
val mockSink = MockSink()
val bufferedSink = mockSink.buffer()
- bufferedSink.writeByte('a'.toInt())
+ bufferedSink.writeByte('a'.code)
bufferedSink.close()
// Test a sample set of methods.
assertFailsWith<IllegalStateException> {
- bufferedSink.writeByte('a'.toInt())
+ bufferedSink.writeByte('a'.code)
}
assertFailsWith<IllegalStateException> {
@@ -186,7 +186,7 @@ class CommonRealBufferedSinkTest {
val write3 = Buffer().writeUtf8("c".repeat(Segment.SIZE))
val source = Buffer().writeUtf8(
- "${"a".repeat(Segment.SIZE)}${"b".repeat(Segment.SIZE)}${"c".repeat(Segment.SIZE)}"
+ "${"a".repeat(Segment.SIZE)}${"b".repeat(Segment.SIZE)}${"c".repeat(Segment.SIZE)}",
)
val mockSink = MockSink()
@@ -196,7 +196,7 @@ class CommonRealBufferedSinkTest {
mockSink.assertLog(
"write($write1, ${write1.size})",
"write($write2, ${write2.size})",
- "write($write3, ${write3.size})"
+ "write($write3, ${write3.size})",
)
}
}
diff --git a/okio/src/commonTest/kotlin/okio/CommonRealBufferedSourceTest.kt b/okio/src/commonTest/kotlin/okio/CommonRealBufferedSourceTest.kt
index 4663919a..6756c5a5 100644
--- a/okio/src/commonTest/kotlin/okio/CommonRealBufferedSourceTest.kt
+++ b/okio/src/commonTest/kotlin/okio/CommonRealBufferedSourceTest.kt
@@ -36,7 +36,7 @@ class CommonRealBufferedSourceTest {
).buffer()
assertEquals(6, buffer.size)
- assertEquals(-1, bufferedSource.indexOf('e'.toByte(), 0, 4))
+ assertEquals(-1, bufferedSource.indexOf('e'.code.toByte(), 0, 4))
assertEquals(2, buffer.size)
}
@@ -141,7 +141,7 @@ class CommonRealBufferedSourceTest {
val write3 = Buffer().writeUtf8("c".repeat(Segment.SIZE))
val source = Buffer().writeUtf8(
- "${"a".repeat(Segment.SIZE)}${"b".repeat(Segment.SIZE)}${"c".repeat(Segment.SIZE)}"
+ "${"a".repeat(Segment.SIZE)}${"b".repeat(Segment.SIZE)}${"c".repeat(Segment.SIZE)}",
)
val mockSink = MockSink()
@@ -150,7 +150,7 @@ class CommonRealBufferedSourceTest {
mockSink.assertLog(
"write($write1, ${write1.size})",
"write($write2, ${write2.size})",
- "write($write3, ${write3.size})"
+ "write($write3, ${write3.size})",
)
}
}
diff --git a/okio/src/commonTest/kotlin/okio/FakeFileSystemTest.kt b/okio/src/commonTest/kotlin/okio/FakeFileSystemTest.kt
deleted file mode 100644
index f57ecd64..00000000
--- a/okio/src/commonTest/kotlin/okio/FakeFileSystemTest.kt
+++ /dev/null
@@ -1,304 +0,0 @@
-/*
- * Copyright (C) 2020 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.Path.Companion.toPath
-import okio.fakefilesystem.FakeFileSystem
-import kotlin.test.Test
-import kotlin.test.assertEquals
-import kotlin.test.assertFailsWith
-import kotlin.test.assertTrue
-import kotlin.time.ExperimentalTime
-import kotlin.time.minutes
-
-@ExperimentalTime
-@ExperimentalFileSystem
-class FakeWindowsFileSystemTest : FakeFileSystemTest(
- clock = FakeClock(),
- windowsLimitations = true,
- temporaryDirectory = "C:\\".toPath(),
-)
-
-@ExperimentalTime
-@ExperimentalFileSystem
-class FakeUnixFileSystemTest : FakeFileSystemTest(
- clock = FakeClock(),
- windowsLimitations = false,
- temporaryDirectory = "/".toPath(),
-)
-
-@ExperimentalTime
-@ExperimentalFileSystem
-abstract class FakeFileSystemTest internal constructor(
- clock: FakeClock,
- windowsLimitations: Boolean,
- temporaryDirectory: Path
-) : AbstractFileSystemTest(
- clock = clock,
- fileSystem = FakeFileSystem(windowsLimitations, clock = clock),
- windowsLimitations = windowsLimitations,
- temporaryDirectory = temporaryDirectory
-) {
- private val fakeFileSystem: FakeFileSystem = fileSystem as FakeFileSystem
- private val fakeClock: FakeClock = clock
-
- @Test
- fun openPathsIncludesOpenSink() {
- val openPath = base / "open-file"
- val sink = fileSystem.sink(openPath)
- assertEquals(openPath, fakeFileSystem.openPaths.single())
- sink.close()
- assertTrue(fakeFileSystem.openPaths.isEmpty())
- }
-
- @Test
- fun openPathsIncludesOpenSource() {
- val openPath = base / "open-file"
- openPath.writeUtf8("hello, world!")
- assertTrue(fakeFileSystem.openPaths.isEmpty())
- val source = fileSystem.source(openPath)
- assertEquals(openPath, fakeFileSystem.openPaths.single())
- source.close()
- assertTrue(fakeFileSystem.openPaths.isEmpty())
- }
-
- @Test
- fun openPathsIsOpenOrder() {
- val fileA = base / "a"
- val fileB = base / "b"
- val fileC = base / "c"
- val fileD = base / "d"
-
- assertEquals(fakeFileSystem.openPaths, listOf())
- val sinkD = fileSystem.sink(fileD)
- assertEquals(fakeFileSystem.openPaths, listOf(fileD))
- val sinkB = fileSystem.sink(fileB)
- assertEquals(fakeFileSystem.openPaths, listOf(fileD, fileB))
- val sinkC = fileSystem.sink(fileC)
- assertEquals(fakeFileSystem.openPaths, listOf(fileD, fileB, fileC))
- val sinkA = fileSystem.sink(fileA)
- assertEquals(fakeFileSystem.openPaths, listOf(fileD, fileB, fileC, fileA))
- val sinkB2 = fileSystem.sink(fileB)
- assertEquals(fakeFileSystem.openPaths, listOf(fileD, fileB, fileC, fileA, fileB))
- sinkD.close()
- assertEquals(fakeFileSystem.openPaths, listOf(fileB, fileC, fileA, fileB))
- sinkB2.close()
- assertEquals(fakeFileSystem.openPaths, listOf(fileB, fileC, fileA))
- sinkB.close()
- assertEquals(fakeFileSystem.openPaths, listOf(fileC, fileA))
- sinkC.close()
- assertEquals(fakeFileSystem.openPaths, listOf(fileA))
- sinkA.close()
- assertEquals(fakeFileSystem.openPaths, listOf())
- }
-
- @Test
- fun allPathsIncludesFile() {
- val file = base / "all-files-includes-file"
- file.writeUtf8("hello, world!")
- assertEquals(fakeFileSystem.allPaths, setOf(base, file))
- }
-
- @Test
- fun allPathsIsSorted() {
- val fileA = base / "a"
- val fileB = base / "b"
- val fileC = base / "c"
- val fileD = base / "d"
-
- // Create files in a different order than the sorted order, so a file system that returns files
- // in creation-order or reverse-creation order won't pass by accident.
- fileD.writeUtf8("fileD")
- fileB.writeUtf8("fileB")
- fileC.writeUtf8("fileC")
- fileA.writeUtf8("fileA")
-
- assertEquals(fakeFileSystem.allPaths.toList(), listOf(base, fileA, fileB, fileC, fileD))
- }
-
- @Test
- fun allPathsIncludesDirectory() {
- val dir = base / "all-files-includes-directory"
- fileSystem.createDirectory(dir)
- assertEquals(fakeFileSystem.allPaths, setOf(base, dir))
- }
-
- @Test
- fun allPathsDoesNotIncludeDeletedFile() {
- val file = base / "all-files-does-not-include-deleted-file"
- file.writeUtf8("hello, world!")
- fileSystem.delete(file)
- assertEquals(fakeFileSystem.allPaths, setOf(base))
- }
-
- @Test
- fun allPathsDoesNotIncludeDeletedOpenFile() {
- if (windowsLimitations) return // Can't delete open files with Windows' limitations.
-
- val file = base / "all-files-does-not-include-deleted-open-file"
- val sink = fileSystem.sink(file)
- assertEquals(fakeFileSystem.allPaths, setOf(base, file))
- fileSystem.delete(file)
- assertEquals(fakeFileSystem.allPaths, setOf(base))
- sink.close()
- }
-
- @Test
- fun fileLastAccessedTime() {
- val path = base / "file-last-accessed-time"
-
- fakeClock.sleep(1.minutes)
- path.writeUtf8("hello, world!")
- val createdAt = clock.now()
-
- fakeClock.sleep(1.minutes)
- path.writeUtf8("hello again!")
- val modifiedAt = clock.now()
-
- fakeClock.sleep(1.minutes)
- path.readUtf8()
- val accessedAt = clock.now()
-
- val metadata = fileSystem.metadata(path)
- assertEquals(createdAt, metadata.createdAt)
- assertEquals(modifiedAt, metadata.lastModifiedAt)
- assertEquals(accessedAt, metadata.lastAccessedAt)
- }
-
- @Test
- fun directoryLastAccessedTime() {
- val path = base / "directory-last-accessed-time"
-
- fakeClock.sleep(1.minutes)
- fileSystem.createDirectory(path)
- val createdAt = clock.now()
-
- fakeClock.sleep(1.minutes)
- (path / "child").writeUtf8("hello world!")
- val modifiedAt = clock.now()
-
- fakeClock.sleep(1.minutes)
- fileSystem.list(path)
- val accessedAt = clock.now()
-
- val metadata = fileSystem.metadata(path)
- assertEquals(createdAt, metadata.createdAt)
- assertEquals(modifiedAt, metadata.lastModifiedAt)
- assertEquals(accessedAt, metadata.lastAccessedAt)
- }
-
- @Test
- fun checkNoOpenFilesThrowsOnOpenSource() {
- val path = base / "check-no-open-files-open-source"
- path.writeUtf8("hello, world!")
- val exception = fileSystem.source(path).use { source ->
- assertFailsWith<IllegalStateException> {
- fakeFileSystem.checkNoOpenFiles()
- }
- }
-
- assertEquals(
- """
- |expected 0 open files, but found:
- | $path
- """.trimMargin(),
- exception.message
- )
- assertEquals("file opened for reading here", exception.cause?.message)
-
- // Now that the source is closed this is safe.
- fakeFileSystem.checkNoOpenFiles()
- }
-
- @Test
- fun checkNoOpenFilesThrowsOnOpenSink() {
- val path = base / "check-no-open-files-open-sink"
- val exception = fileSystem.sink(path).use { source ->
- assertFailsWith<IllegalStateException> {
- fakeFileSystem.checkNoOpenFiles()
- }
- }
-
- assertEquals(
- """
- |expected 0 open files, but found:
- | $path
- """.trimMargin(),
- exception.message
- )
- assertEquals("file opened for writing here", exception.cause?.message)
-
- // Now that the source is closed this is safe.
- fakeFileSystem.checkNoOpenFiles()
- }
-
- @Test
- fun createDirectoriesForVolumeLetterRoot() {
- val path = "X:\\".toPath()
- fileSystem.createDirectories(path)
- assertTrue(fileSystem.metadata(path).isDirectory)
- }
-
- @Test
- fun createDirectoriesForChildOfVolumeLetterRoot() {
- val path = "X:\\path".toPath()
- fileSystem.createDirectories(path)
- assertTrue(fileSystem.metadata(path).isDirectory)
- }
-
- @Test
- fun createDirectoriesForUnixRoot() {
- val path = "/".toPath()
- fileSystem.createDirectories(path)
- assertTrue(fileSystem.metadata(path).isDirectory)
- }
-
- @Test
- fun createDirectoriesForChildOfUnixRoot() {
- val path = "/path".toPath()
- fileSystem.createDirectories(path)
- assertTrue(fileSystem.metadata(path).isDirectory)
- }
-
- @Test
- fun createDirectoriesForUncRoot() {
- val path = "\\\\server".toPath()
- fileSystem.createDirectories(path)
- assertTrue(fileSystem.metadata(path).isDirectory)
- }
-
- @Test
- fun createDirectoriesForChildOfUncRoot() {
- val path = "\\\\server\\project".toPath()
- fileSystem.createDirectories(path)
- assertTrue(fileSystem.metadata(path).isDirectory)
- }
-
- @Test
- fun workingDirectoryMustBeAbsolute() {
- val exception = assertFailsWith<IllegalArgumentException> {
- FakeFileSystem(workingDirectory = "some/relative/path".toPath())
- }
- assertEquals("expected an absolute path but was some/relative/path", exception.message)
- }
-
- @Test
- fun metadataForRootsGeneratedOnDemand() {
- assertTrue(fileSystem.metadata("X:\\".toPath()).isDirectory)
- assertTrue(fileSystem.metadata("/".toPath()).isDirectory)
- assertTrue(fileSystem.metadata("\\\\server".toPath()).isDirectory)
- }
-}
diff --git a/okio/src/commonTest/kotlin/okio/ForwardingFileSystemTest.kt b/okio/src/commonTest/kotlin/okio/ForwardingFileSystemTest.kt
deleted file mode 100644
index 2f9669d5..00000000
--- a/okio/src/commonTest/kotlin/okio/ForwardingFileSystemTest.kt
+++ /dev/null
@@ -1,146 +0,0 @@
-/*
- * Copyright (C) 2020 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 kotlinx.datetime.Clock
-import okio.Path.Companion.toPath
-import okio.fakefilesystem.FakeFileSystem
-import kotlin.test.Test
-import kotlin.test.assertEquals
-import kotlin.test.assertFailsWith
-import kotlin.test.assertTrue
-import kotlin.time.ExperimentalTime
-
-@ExperimentalTime
-@ExperimentalFileSystem
-class ForwardingFileSystemTest : AbstractFileSystemTest(
- clock = Clock.System,
- fileSystem = object : ForwardingFileSystem(FakeFileSystem()) {},
- windowsLimitations = false,
- temporaryDirectory = "/".toPath()
-) {
- @Test
- fun pathBlocking() {
- val forwardingFileSystem = object : ForwardingFileSystem(fileSystem) {
- override fun delete(path: Path) {
- throw IOException("synthetic failure!")
- }
-
- override fun onPathParameter(path: Path, functionName: String, parameterName: String): Path {
- if (path.name.contains("blocked")) throw IOException("blocked path!")
- return path
- }
- }
-
- forwardingFileSystem.createDirectory(base / "okay")
- assertFailsWith<IOException> {
- forwardingFileSystem.createDirectory(base / "blocked")
- }
- }
-
- @Test
- fun operationBlocking() {
- val forwardingFileSystem = object : ForwardingFileSystem(fileSystem) {
- override fun onPathParameter(path: Path, functionName: String, parameterName: String): Path {
- if (functionName == "delete") throw IOException("blocked operation!")
- return path
- }
- }
-
- forwardingFileSystem.createDirectory(base / "operation-blocking")
- assertFailsWith<IOException> {
- forwardingFileSystem.delete(base / "operation-blocking")
- }
- }
-
- @Test
- fun pathMapping() {
- val prefix = "/mapped"
- val source = base / "source"
- val mappedSource = (prefix + source).toPath()
- val target = base / "target"
- val mappedTarget = (prefix + target).toPath()
-
- source.writeUtf8("hello, world!")
-
- val forwardingFileSystem = object : ForwardingFileSystem(fileSystem) {
- override fun onPathParameter(path: Path, functionName: String, parameterName: String): Path {
- return path.toString().removePrefix(prefix).toPath()
- }
-
- override fun onPathResult(path: Path, functionName: String): Path {
- return (prefix + path).toPath()
- }
- }
-
- forwardingFileSystem.copy(mappedSource, mappedTarget)
- assertTrue(target in fileSystem.list(base))
- assertTrue(mappedTarget in forwardingFileSystem.list(base))
- assertEquals("hello, world!", source.readUtf8())
- assertEquals("hello, world!", target.readUtf8())
- }
-
- /**
- * Path mapping might impact the sort order. Confirm that list() returns elements in sorted order
- * even if that order is different in the delegate file system.
- */
- @Test
- fun pathMappingImpactedBySorting() {
- val az = base / "az"
- val by = base / "by"
- val cx = base / "cx"
- az.writeUtf8("az")
- by.writeUtf8("by")
- cx.writeUtf8("cx")
-
- val forwardingFileSystem = object : ForwardingFileSystem(fileSystem) {
- override fun onPathResult(path: Path, functionName: String): Path {
- return path.parent!! / path.name.reversed()
- }
- }
-
- assertEquals(fileSystem.list(base), listOf(base / "az", base / "by", base / "cx"))
- assertEquals(forwardingFileSystem.list(base), listOf(base / "xc", base / "yb", base / "za"))
- }
-
- @Test
- fun copyIsNotForwarded() {
- val log = mutableListOf<String>()
-
- val delegate = object : ForwardingFileSystem(fileSystem) {
- override fun copy(source: Path, target: Path) {
- throw AssertionError("unexpected call to copy()")
- }
- }
-
- val forwardingFileSystem = object : ForwardingFileSystem(delegate) {
- override fun onPathParameter(path: Path, functionName: String, parameterName: String): Path {
- log += "$functionName($parameterName=$path)"
- return path
- }
- }
-
- val source = base / "source"
- source.writeUtf8("hello, world!")
- val target = base / "target"
- forwardingFileSystem.copy(source, target)
- assertTrue(target in fileSystem.list(base))
- assertEquals("hello, world!", source.readUtf8())
- assertEquals("hello, world!", target.readUtf8())
-
- assertEquals(log, listOf("source(file=$source)", "sink(file=$target)"))
- }
-}
diff --git a/okio/src/commonTest/kotlin/okio/ForwardingSourceTest.kt b/okio/src/commonTest/kotlin/okio/ForwardingSourceTest.kt
new file mode 100644
index 00000000..70c3fa45
--- /dev/null
+++ b/okio/src/commonTest/kotlin/okio/ForwardingSourceTest.kt
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2022 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 kotlin.test.Test
+import kotlin.test.assertEquals
+import kotlin.test.assertTrue
+
+class ForwardingSourceTest {
+ val source = Buffer().writeUtf8("Delegate")
+
+ @Test
+ fun testForwardingSourceOverrides() {
+ val forwarder = "Forwarder"
+ val newSource = Buffer().writeUtf8(forwarder)
+ val forwardingSource = object : ForwardingSource(source) {
+ override fun read(sink: Buffer, byteCount: Long): Long {
+ return newSource.read(sink, byteCount)
+ }
+ }
+
+ assertEquals("Forwarder", forwardingSource.buffer().readUtf8())
+ }
+
+ @Test
+ fun testForwardingSourceDelegates() {
+ val forwardingSource = object : ForwardingSource(source) {
+ }
+
+ assertEquals("Delegate", forwardingSource.buffer().readUtf8())
+ }
+
+ @Test
+ fun testToString() {
+ val forwardingSource = object : ForwardingSource(source) {
+ }
+
+ assertTrue(forwardingSource.toString().endsWith("([text=Delegate])"))
+ }
+}
diff --git a/okio/src/commonTest/kotlin/okio/HashingSinkTest.kt b/okio/src/commonTest/kotlin/okio/HashingSinkTest.kt
index db1aeeec..bb88be7a 100644
--- a/okio/src/commonTest/kotlin/okio/HashingSinkTest.kt
+++ b/okio/src/commonTest/kotlin/okio/HashingSinkTest.kt
@@ -15,14 +15,14 @@
*/
package okio
+import kotlin.test.Test
+import kotlin.test.assertEquals
import okio.HashingSink.Companion.hmacSha1
import okio.HashingSink.Companion.hmacSha256
import okio.HashingSink.Companion.hmacSha512
import okio.HashingSink.Companion.sha1
import okio.HashingSink.Companion.sha256
import okio.HashingSink.Companion.sha512
-import kotlin.test.Test
-import kotlin.test.assertEquals
class HashingSinkTest {
private val source = Buffer()
diff --git a/okio/src/commonTest/kotlin/okio/HashingSourceTest.kt b/okio/src/commonTest/kotlin/okio/HashingSourceTest.kt
index 83e2e264..7111edf4 100644
--- a/okio/src/commonTest/kotlin/okio/HashingSourceTest.kt
+++ b/okio/src/commonTest/kotlin/okio/HashingSourceTest.kt
@@ -15,15 +15,15 @@
*/
package okio
+import kotlin.test.Test
+import kotlin.test.assertEquals
+import kotlin.test.fail
import okio.HashingSource.Companion.hmacSha1
import okio.HashingSource.Companion.hmacSha256
import okio.HashingSource.Companion.hmacSha512
import okio.HashingSource.Companion.md5
import okio.HashingSource.Companion.sha1
import okio.HashingSource.Companion.sha256
-import kotlin.test.Test
-import kotlin.test.assertEquals
-import kotlin.test.fail
class HashingSourceTest {
private val source = Buffer()
@@ -82,11 +82,11 @@ class HashingSourceTest {
val hashingSource = sha256(source)
val bufferedSource = hashingSource.buffer()
source.writeUtf8("a")
- assertEquals('a'.toLong(), bufferedSource.readUtf8CodePoint().toLong())
+ assertEquals('a'.code.toLong(), bufferedSource.readUtf8CodePoint().toLong())
source.writeUtf8("b")
- assertEquals('b'.toLong(), bufferedSource.readUtf8CodePoint().toLong())
+ assertEquals('b'.code.toLong(), bufferedSource.readUtf8CodePoint().toLong())
source.writeUtf8("c")
- assertEquals('c'.toLong(), bufferedSource.readUtf8CodePoint().toLong())
+ assertEquals('c'.code.toLong(), bufferedSource.readUtf8CodePoint().toLong())
assertEquals(HashingTest.SHA256_abc, hashingSource.hash)
}
diff --git a/okio/src/commonTest/kotlin/okio/HashingTest.kt b/okio/src/commonTest/kotlin/okio/HashingTest.kt
index 1cae58d0..d290dc0c 100644
--- a/okio/src/commonTest/kotlin/okio/HashingTest.kt
+++ b/okio/src/commonTest/kotlin/okio/HashingTest.kt
@@ -15,10 +15,10 @@
*/
package okio
-import okio.ByteString.Companion.decodeHex
-import okio.ByteString.Companion.encodeUtf8
import kotlin.test.Test
import kotlin.test.assertEquals
+import okio.ByteString.Companion.decodeHex
+import okio.ByteString.Companion.encodeUtf8
class HashingTest {
@Test fun byteStringMd5() {
diff --git a/okio/src/commonTest/kotlin/okio/util.kt b/okio/src/commonTest/kotlin/okio/OkioTesting.kt
index 953eef88..8dbdd2a1 100644
--- a/okio/src/commonTest/kotlin/okio/util.kt
+++ b/okio/src/commonTest/kotlin/okio/OkioTesting.kt
@@ -16,11 +16,6 @@
package okio
import kotlin.random.Random
-import kotlin.test.assertEquals
-
-fun Char.repeat(count: Int): String {
- return toString().repeat(count)
-}
fun segmentSizes(buffer: Buffer): List<Int> {
var segment = buffer.head ?: return emptyList()
@@ -34,17 +29,6 @@ fun segmentSizes(buffer: Buffer): List<Int> {
return sizes
}
-fun assertArrayEquals(a: ByteArray, b: ByteArray) {
- assertEquals(a.contentToString(), b.contentToString())
-}
-
-fun randomBytes(length: Int): ByteString {
- val random = Random(0)
- val randomBytes = ByteArray(length)
- random.nextBytes(randomBytes)
- return ByteString.of(*randomBytes)
-}
-
fun bufferWithRandomSegmentLayout(dice: Random, data: ByteArray): Buffer {
val result = Buffer()
@@ -92,3 +76,24 @@ fun makeSegments(source: ByteString): ByteString {
}
return buffer.snapshot()
}
+
+/**
+ * Returns a string with all '\' slashes replaced with '/' slashes. This is useful for test
+ * assertions that intend to ignore slashes.
+ */
+fun Path.withUnixSlashes(): String {
+ return toString().replace('\\', '/')
+}
+
+expect fun assertRelativeTo(
+ a: Path,
+ b: Path,
+ bRelativeToA: Path,
+ sameAsNio: Boolean = true,
+)
+
+expect fun assertRelativeToFails(
+ a: Path,
+ b: Path,
+ sameAsNio: Boolean = true,
+): IllegalArgumentException
diff --git a/okio/src/commonTest/kotlin/okio/PathTest.kt b/okio/src/commonTest/kotlin/okio/PathTest.kt
index 92754a78..cb2920d7 100644
--- a/okio/src/commonTest/kotlin/okio/PathTest.kt
+++ b/okio/src/commonTest/kotlin/okio/PathTest.kt
@@ -15,18 +15,21 @@
*/
package okio
-import okio.Path.Companion.toPath
import kotlin.test.Test
import kotlin.test.assertEquals
import kotlin.test.assertFalse
+import kotlin.test.assertNotEquals
import kotlin.test.assertNull
import kotlin.test.assertTrue
+import okio.Path.Companion.toPath
-@ExperimentalFileSystem
class PathTest {
@Test
fun unixRoot() {
- val path = "/".toPath("/")
+ val path = "/".toPath()
+ assertEquals(path, path.normalized())
+ assertEquals(path, path.root)
+ assertEquals(listOf(), path.segments)
assertEquals("/", path.toString())
assertNull(path.parent)
assertNull(path.volumeLetter)
@@ -37,9 +40,12 @@ class PathTest {
@Test
fun unixAbsolutePath() {
- val path = "/home/jesse/todo.txt".toPath("/")
+ val path = "/home/jesse/todo.txt".toPath()
+ assertEquals(path, path.normalized())
+ assertEquals("/".toPath(), path.root)
+ assertEquals(listOf("home", "jesse", "todo.txt"), path.segments)
assertEquals("/home/jesse/todo.txt", path.toString())
- assertEquals("/home/jesse".toPath("/"), path.parent)
+ assertEquals("/home/jesse".toPath(), path.parent)
assertNull(path.volumeLetter)
assertEquals("todo.txt", path.name)
assertTrue(path.isAbsolute)
@@ -48,9 +54,12 @@ class PathTest {
@Test
fun unixRelativePath() {
- val path = "project/todo.txt".toPath("/")
+ val path = "project/todo.txt".toPath()
+ assertEquals(path, path.normalized())
+ assertNull(path.root)
+ assertEquals(listOf("project", "todo.txt"), path.segments)
assertEquals("project/todo.txt", path.toString())
- assertEquals("project".toPath("/"), path.parent)
+ assertEquals("project".toPath(), path.parent)
assertNull(path.volumeLetter)
assertEquals("todo.txt", path.name)
assertFalse(path.isAbsolute)
@@ -59,9 +68,12 @@ class PathTest {
@Test
fun unixRelativePathWithDots() {
- val path = "../../project/todo.txt".toPath("/")
+ val path = "../../project/todo.txt".toPath()
+ assertEquals(path, path.normalized())
+ assertNull(path.root)
+ assertEquals(listOf("..", "..", "project", "todo.txt"), path.segments)
assertEquals("../../project/todo.txt", path.toString())
- assertEquals("../../project".toPath("/"), path.parent)
+ assertEquals("../../project".toPath(), path.parent)
assertNull(path.volumeLetter)
assertEquals("todo.txt", path.name)
assertFalse(path.isAbsolute)
@@ -70,7 +82,10 @@ class PathTest {
@Test
fun unixRelativeSeriesOfDotDots() {
- val path = "../../..".toPath("/")
+ val path = "../../..".toPath()
+ assertEquals(path, path.normalized())
+ assertNull(path.root)
+ assertEquals(listOf("..", "..", ".."), path.segments)
assertEquals("../../..", path.toString())
assertNull(path.parent)
assertNull(path.volumeLetter)
@@ -81,7 +96,10 @@ class PathTest {
@Test
fun unixAbsoluteSeriesOfDotDots() {
- val path = "/../../..".toPath("/")
+ val path = "/../../..".toPath()
+ assertEquals(path, path.normalized())
+ assertEquals("/".toPath(), path.root)
+ assertEquals(listOf(), path.segments)
assertEquals("/", path.toString())
assertNull(path.parent)
assertNull(path.volumeLetter)
@@ -92,7 +110,10 @@ class PathTest {
@Test
fun unixAbsoluteSingleDot() {
- val path = "/.".toPath("/")
+ val path = "/.".toPath()
+ assertEquals(path, path.normalized())
+ assertEquals("/".toPath(), path.root)
+ assertEquals(listOf(), path.segments)
assertEquals("/", path.toString())
assertNull(path.parent)
assertNull(path.volumeLetter)
@@ -103,7 +124,10 @@ class PathTest {
@Test
fun unixRelativeDoubleDots() {
- val path = "..".toPath("/")
+ val path = "..".toPath()
+ assertEquals(path, path.normalized())
+ assertNull(path.root)
+ assertEquals(listOf(".."), path.segments)
assertEquals("..", path.toString())
assertNull(path.parent)
assertNull(path.volumeLetter)
@@ -114,7 +138,10 @@ class PathTest {
@Test
fun unixRelativeSingleDot() {
- val path = ".".toPath("/")
+ val path = ".".toPath()
+ assertEquals(path, path.normalized())
+ assertNull(path.root)
+ assertEquals(listOf("."), path.segments)
assertEquals(".", path.toString())
assertNull(path.parent)
assertNull(path.volumeLetter)
@@ -125,7 +152,10 @@ class PathTest {
@Test
fun windowsVolumeLetter() {
- val path = "C:\\".toPath("\\")
+ val path = "C:\\".toPath()
+ assertEquals(path, path.normalized())
+ assertEquals("C:\\".toPath(), path.root)
+ assertEquals(listOf(), path.segments)
assertEquals("C:\\", path.toString())
assertNull(path.parent)
assertEquals('C', path.volumeLetter)
@@ -136,9 +166,12 @@ class PathTest {
@Test
fun windowsAbsolutePathWithVolumeLetter() {
- val path = "C:\\Windows\\notepad.exe".toPath("\\")
+ val path = "C:\\Windows\\notepad.exe".toPath()
+ assertEquals(path, path.normalized())
+ assertEquals("C:\\".toPath(), path.root)
+ assertEquals(listOf("Windows", "notepad.exe"), path.segments)
assertEquals("C:\\Windows\\notepad.exe", path.toString())
- assertEquals("C:\\Windows".toPath("\\"), path.parent)
+ assertEquals("C:\\Windows".toPath(), path.parent)
assertEquals('C', path.volumeLetter)
assertEquals("notepad.exe", path.name)
assertTrue(path.isAbsolute)
@@ -147,7 +180,10 @@ class PathTest {
@Test
fun windowsAbsolutePath() {
- val path = "\\".toPath("\\")
+ val path = "\\".toPath()
+ assertEquals(path, path.normalized())
+ assertEquals("\\".toPath(), path.root)
+ assertEquals(listOf(), path.segments)
assertEquals("\\", path.toString())
assertEquals(null, path.parent)
assertNull(path.volumeLetter)
@@ -158,9 +194,12 @@ class PathTest {
@Test
fun windowsAbsolutePathWithoutVolumeLetter() {
- val path = "\\Windows\\notepad.exe".toPath("\\")
+ val path = "\\Windows\\notepad.exe".toPath()
+ assertEquals(path, path.normalized())
+ assertEquals("\\".toPath(), path.root)
+ assertEquals(listOf("Windows", "notepad.exe"), path.segments)
assertEquals("\\Windows\\notepad.exe", path.toString())
- assertEquals("\\Windows".toPath("\\"), path.parent)
+ assertEquals("\\Windows".toPath(), path.parent)
assertNull(path.volumeLetter)
assertEquals("notepad.exe", path.name)
assertTrue(path.isAbsolute)
@@ -169,9 +208,12 @@ class PathTest {
@Test
fun windowsRelativePathWithVolumeLetter() {
- val path = "C:Windows\\notepad.exe".toPath("\\")
+ val path = "C:Windows\\notepad.exe".toPath()
+ assertEquals(path, path.normalized())
+ assertNull(path.root)
+ assertEquals(listOf("C:Windows", "notepad.exe"), path.segments)
assertEquals("C:Windows\\notepad.exe", path.toString())
- assertEquals("C:Windows".toPath("\\"), path.parent)
+ assertEquals("C:Windows".toPath(), path.parent)
assertEquals('C', path.volumeLetter)
assertEquals("notepad.exe", path.name)
assertFalse(path.isAbsolute)
@@ -180,7 +222,10 @@ class PathTest {
@Test
fun windowsVolumeLetterRelative() {
- val path = "C:".toPath("\\")
+ val path = "C:".toPath()
+ assertEquals(path, path.normalized())
+ assertNull(path.root)
+ assertEquals(listOf("C:"), path.segments)
assertEquals("C:", path.toString())
assertNull(path.parent)
assertEquals('C', path.volumeLetter)
@@ -191,9 +236,12 @@ class PathTest {
@Test
fun windowsRelativePath() {
- val path = "Windows\\notepad.exe".toPath("\\")
+ val path = "Windows\\notepad.exe".toPath()
+ assertEquals(path, path.normalized())
+ assertNull(path.root)
+ assertEquals(listOf("Windows", "notepad.exe"), path.segments)
assertEquals("Windows\\notepad.exe", path.toString())
- assertEquals("Windows".toPath("\\"), path.parent)
+ assertEquals("Windows".toPath(), path.parent)
assertNull(path.volumeLetter)
assertEquals("notepad.exe", path.name)
assertFalse(path.isAbsolute)
@@ -202,7 +250,10 @@ class PathTest {
@Test
fun windowsUncServer() {
- val path = "\\\\server".toPath("\\")
+ val path = "\\\\server".toPath()
+ assertEquals(path, path.normalized())
+ assertEquals("\\\\server".toPath(), path.root)
+ assertEquals(listOf(), path.segments)
assertEquals("\\\\server", path.toString())
assertNull(path.parent)
assertNull(path.volumeLetter)
@@ -213,9 +264,12 @@ class PathTest {
@Test
fun windowsUncAbsolutePath() {
- val path = "\\\\server\\project\\notes.txt".toPath("\\")
+ val path = "\\\\server\\project\\notes.txt".toPath()
+ assertEquals(path, path.normalized())
+ assertEquals("\\\\server".toPath(), path.root)
+ assertEquals(listOf("project", "notes.txt"), path.segments)
assertEquals("\\\\server\\project\\notes.txt", path.toString())
- assertEquals("\\\\server\\project".toPath("\\"), path.parent)
+ assertEquals("\\\\server\\project".toPath(), path.parent)
assertNull(path.volumeLetter)
assertEquals("notes.txt", path.name)
assertTrue(path.isAbsolute)
@@ -227,34 +281,42 @@ class PathTest {
val root = "/".toPath()
assertEquals("/home".toPath(), root / "home")
assertEquals("/home/jesse".toPath(), root / "home" / "jesse")
- assertEquals("/home".toPath(), root / "home" / "jesse" / "..")
- assertEquals("/home/jake".toPath(), root / "home" / "jesse" / ".." / "jake")
+ assertEquals("/home/jesse/..".toPath(), root / "home" / "jesse" / "..")
+ assertEquals("/home/jesse/../jake".toPath(), root / "home" / "jesse" / ".." / "jake")
}
@Test
fun relativePathTraversalWithDivOperator() {
- val cwd = ".".toPath("/")
- assertEquals("home".toPath("/"), cwd / "home")
- assertEquals("home/jesse".toPath("/"), cwd / "home" / "jesse")
- assertEquals("home".toPath("/"), cwd / "home" / "jesse" / "..")
- assertEquals("home/jake".toPath("/"), cwd / "home" / "jesse" / ".." / "jake")
+ val slash = Path.DIRECTORY_SEPARATOR
+ val cwd = ".".toPath()
+ assertEquals("home".toPath(), cwd / "home")
+ assertEquals("home${slash}jesse".toPath(), cwd / "home" / "jesse")
+ assertEquals("home${slash}jesse$slash..".toPath(), cwd / "home" / "jesse" / "..")
+ assertEquals(
+ "home${slash}jesse$slash..${slash}jake".toPath(),
+ cwd / "home" / "jesse" / ".." / "jake",
+ )
}
@Test
fun relativePathTraversalWithDots() {
- val cwd = ".".toPath("/")
- assertEquals("..".toPath("/"), cwd / "..")
- assertEquals("../..".toPath("/"), cwd / ".." / "..")
- assertEquals("../../etc".toPath("/"), cwd / ".." / ".." / "etc")
- assertEquals("../../etc/passwd".toPath("/"), cwd / ".." / ".." / "etc" / "passwd")
+ val slash = Path.DIRECTORY_SEPARATOR
+ val cwd = ".".toPath()
+ assertEquals("..".toPath(), cwd / "..")
+ assertEquals("..$slash..".toPath(), cwd / ".." / "..")
+ assertEquals("..$slash..${slash}etc".toPath(), cwd / ".." / ".." / "etc")
+ assertEquals(
+ "..$slash..${slash}etc${slash}passwd".toPath(),
+ cwd / ".." / ".." / "etc" / "passwd",
+ )
}
@Test
fun pathTraversalBaseIgnoredIfChildIsAnAbsolutePath() {
- assertEquals("/home".toPath(), "".toPath("/") / "/home")
- assertEquals("/home".toPath(), "relative".toPath("/") / "/home")
- assertEquals("/home".toPath(), "/base".toPath("/") / "/home")
- assertEquals("/home".toPath(), "/".toPath("/") / "/home")
+ assertEquals("/home".toPath(), "".toPath() / "/home")
+ assertEquals("/home".toPath(), "relative".toPath() / "/home")
+ assertEquals("/home".toPath(), "/base".toPath() / "/home")
+ assertEquals("/home".toPath(), "/".toPath() / "/home")
}
@Test
@@ -264,6 +326,11 @@ class PathTest {
assertEquals("/a", "/a/".toPath().toString())
assertEquals("/a/b/c", "/a/b/c".toPath().toString())
assertEquals("/a/b/c", "/a/b/c/".toPath().toString())
+ assertEquals("/", "/".toPath(normalize = true).toString())
+ assertEquals("/a", "/a".toPath(normalize = true).toString())
+ assertEquals("/a", "/a/".toPath(normalize = true).toString())
+ assertEquals("/a/b/c", "/a/b/c".toPath(normalize = true).toString())
+ assertEquals("/a/b/c", "/a/b/c/".toPath(normalize = true).toString())
}
@Test
@@ -272,6 +339,10 @@ class PathTest {
assertEquals("/", "/../".toPath().toString())
assertEquals("/", "/../..".toPath().toString())
assertEquals("/", "/../../".toPath().toString())
+ assertEquals("/", "/..".toPath(normalize = true).toString())
+ assertEquals("/", "/../".toPath(normalize = true).toString())
+ assertEquals("/", "/../..".toPath(normalize = true).toString())
+ assertEquals("/", "/../../".toPath(normalize = true).toString())
}
@Test
@@ -281,6 +352,11 @@ class PathTest {
assertEquals("/a", "/a//".toPath().toString())
assertEquals("/a", "//a//".toPath().toString())
assertEquals("/a/b", "/a/b//".toPath().toString())
+ assertEquals("/", "//".toPath(normalize = true).toString())
+ assertEquals("/a", "//a".toPath(normalize = true).toString())
+ assertEquals("/a", "/a//".toPath(normalize = true).toString())
+ assertEquals("/a", "//a//".toPath(normalize = true).toString())
+ assertEquals("/a/b", "/a/b//".toPath(normalize = true).toString())
}
@Test
@@ -294,6 +370,15 @@ class PathTest {
assertEquals("/a", "//a/./".toPath().toString())
assertEquals("/a", "//a/./.".toPath().toString())
assertEquals("/a/b", "/a/./b/".toPath().toString())
+ assertEquals("/", "/./".toPath(normalize = true).toString())
+ assertEquals("/a", "/./a".toPath(normalize = true).toString())
+ assertEquals("/a", "/a/./".toPath(normalize = true).toString())
+ assertEquals("/a", "/a//.".toPath(normalize = true).toString())
+ assertEquals("/a", "/./a//".toPath(normalize = true).toString())
+ assertEquals("/a", "/a/.".toPath(normalize = true).toString())
+ assertEquals("/a", "//a/./".toPath(normalize = true).toString())
+ assertEquals("/a", "//a/./.".toPath(normalize = true).toString())
+ assertEquals("/a/b", "/a/./b/".toPath(normalize = true).toString())
}
@Test
@@ -305,20 +390,37 @@ class PathTest {
assertEquals("a/b", "a/b/".toPath().toString())
assertEquals("a/b/c/d", "a/b/c/d".toPath().toString())
assertEquals("a/b/c/d", "a/b/c/d/".toPath().toString())
+ assertEquals(".", "".toPath(normalize = true).toString())
+ assertEquals(".", ".".toPath(normalize = true).toString())
+ assertEquals("a", "a/".toPath(normalize = true).toString())
+ assertEquals("a/b", "a/b".toPath(normalize = true).toString())
+ assertEquals("a/b", "a/b/".toPath(normalize = true).toString())
+ assertEquals("a/b/c/d", "a/b/c/d".toPath(normalize = true).toString())
+ assertEquals("a/b/c/d", "a/b/c/d/".toPath(normalize = true).toString())
}
@Test
fun stringToRelativePathWithTraversal() {
assertEquals("..", "..".toPath().toString())
assertEquals("..", "../".toPath().toString())
- assertEquals(".", "a/..".toPath().toString())
- assertEquals(".", "a/../".toPath().toString())
- assertEquals("..", "a/../..".toPath().toString())
- assertEquals("..", "a/../../".toPath().toString())
- assertEquals("../..", "a/../../..".toPath().toString())
+ assertEquals("a/..", "a/..".toPath().toString())
+ assertEquals("a/..", "a/../".toPath().toString())
+ assertEquals("a/../..", "a/../..".toPath().toString())
+ assertEquals("a/../..", "a/../../".toPath().toString())
+ assertEquals("a/../../..", "a/../../..".toPath().toString())
assertEquals("../../b", "../../b".toPath().toString())
- assertEquals("../../b", "a/../../../b".toPath().toString())
- assertEquals("../../c", "a/../../../b/../c".toPath().toString())
+ assertEquals("a/../../../b", "a/../../../b".toPath().toString())
+ assertEquals("a/../../../b/../c", "a/../../../b/../c".toPath().toString())
+ assertEquals("..", "..".toPath(normalize = true).toString())
+ assertEquals("..", "../".toPath(normalize = true).toString())
+ assertEquals(".", "a/..".toPath(normalize = true).toString())
+ assertEquals(".", "a/../".toPath(normalize = true).toString())
+ assertEquals("..", "a/../..".toPath(normalize = true).toString())
+ assertEquals("..", "a/../../".toPath(normalize = true).toString())
+ assertEquals("../..", "a/../../..".toPath(normalize = true).toString())
+ assertEquals("../../b", "../../b".toPath(normalize = true).toString())
+ assertEquals("../../b", "a/../../../b".toPath(normalize = true).toString())
+ assertEquals("../../c", "a/../../../b/../c".toPath(normalize = true).toString())
}
@Test
@@ -328,6 +430,11 @@ class PathTest {
assertEquals("a/b", "a/b//".toPath().toString())
assertEquals("a/b", "a//b//".toPath().toString())
assertEquals("a/b/c", "a/b/c//".toPath().toString())
+ assertEquals("a", "a//".toPath(normalize = true).toString())
+ assertEquals("a/b", "a//b".toPath(normalize = true).toString())
+ assertEquals("a/b", "a/b//".toPath(normalize = true).toString())
+ assertEquals("a/b", "a//b//".toPath(normalize = true).toString())
+ assertEquals("a/b/c", "a/b/c//".toPath(normalize = true).toString())
}
@Test
@@ -335,7 +442,7 @@ class PathTest {
assertEquals(".", ".".toPath().toString())
assertEquals(".", "./".toPath().toString())
assertEquals(".", "././".toPath().toString())
- assertEquals(".", "././a/..".toPath().toString())
+ assertEquals("a/..", "././a/..".toPath().toString())
assertEquals("a", "a/./".toPath().toString())
assertEquals("a/b", "a/./b".toPath().toString())
assertEquals("a/b", "a/b/./".toPath().toString())
@@ -345,6 +452,19 @@ class PathTest {
assertEquals("a/b", "a//b/./".toPath().toString())
assertEquals("a/b", "a//b/./.".toPath().toString())
assertEquals("a/b/c", "a/b/./c/".toPath().toString())
+ assertEquals(".", ".".toPath(normalize = true).toString())
+ assertEquals(".", "./".toPath(normalize = true).toString())
+ assertEquals(".", "././".toPath(normalize = true).toString())
+ assertEquals(".", "././a/..".toPath(normalize = true).toString())
+ assertEquals("a", "a/./".toPath(normalize = true).toString())
+ assertEquals("a/b", "a/./b".toPath(normalize = true).toString())
+ assertEquals("a/b", "a/b/./".toPath(normalize = true).toString())
+ assertEquals("a/b", "a/b//.".toPath(normalize = true).toString())
+ assertEquals("a/b", "a/./b//".toPath(normalize = true).toString())
+ assertEquals("a/b", "a/b/.".toPath(normalize = true).toString())
+ assertEquals("a/b", "a//b/./".toPath(normalize = true).toString())
+ assertEquals("a/b", "a//b/./.".toPath(normalize = true).toString())
+ assertEquals("a/b/c", "a/b/./c/".toPath(normalize = true).toString())
}
@Test
@@ -359,7 +479,299 @@ class PathTest {
@Test
fun windowsPathTraversalUp() {
- assertEquals("C:\\z".toPath(), "C:\\x\\y\\..\\..\\..\\z".toPath())
- assertEquals("C:..\\z".toPath(), "C:x\\y\\..\\..\\..\\z".toPath())
+ assertEquals("C:\\x\\y\\..\\..\\..\\z".toPath(), "C:\\x\\y\\..\\..\\..\\z".toPath())
+ assertEquals("C:x\\y\\..\\..\\..\\z".toPath(), "C:x\\y\\..\\..\\..\\z".toPath())
+ assertEquals("C:\\z".toPath(), "C:\\x\\y\\..\\..\\..\\z".toPath(normalize = true))
+ assertEquals("C:..\\z".toPath(), "C:x\\y\\..\\..\\..\\z".toPath(normalize = true))
+ }
+
+ @Test
+ fun samePathDifferentSlashesAreNotEqual() {
+ assertNotEquals("/a".toPath(), "\\b".toPath())
+ assertNotEquals("a/b".toPath(), "a\\b".toPath())
+ }
+
+ @Test
+ fun samePathNoSlashesAreEqual() {
+ assertEquals("a".toPath().parent!!, "a".toPath().parent!!)
+ assertEquals("a/b".toPath().parent!!, "a\\b".toPath().parent!!)
+ }
+
+ @Test
+ fun relativeToWindowsPaths() {
+ val a = "C:\\Windows\\notepad.exe".toPath()
+ val b = "C:\\".toPath()
+ assertRelativeTo(a, b, "..\\..".toPath(), sameAsNio = false)
+ assertRelativeTo(b, a, "Windows\\notepad.exe".toPath(), sameAsNio = false)
+
+ val c = "C:\\Windows\\".toPath()
+ val d = "C:\\Windows".toPath()
+ assertRelativeTo(c, d, ".".toPath())
+ assertRelativeTo(d, c, ".".toPath())
+
+ val e = "C:\\Windows\\Downloads\\".toPath()
+ val f = "C:\\Windows\\Documents\\Hello.txt".toPath()
+ assertRelativeTo(e, f, "..\\Documents\\Hello.txt".toPath(), sameAsNio = false)
+ assertRelativeTo(f, e, "..\\..\\Downloads".toPath(), sameAsNio = false)
+
+ val g = "C:\\Windows\\".toPath()
+ val h = "D:\\Windows\\".toPath()
+ assertRelativeToFails(g, h, sameAsNio = false)
+ assertRelativeToFails(h, g, sameAsNio = false)
+ }
+
+ @Test
+ fun relativeToWindowsUncPaths() {
+ val a = "\\\\localhost\\c$\\development\\schema.proto".toPath()
+ val b = "\\\\localhost\\c$\\project\\notes.txt".toPath()
+ assertRelativeTo(a, b, "..\\..\\project\\notes.txt".toPath(), sameAsNio = false)
+ assertRelativeTo(b, a, "..\\..\\development\\schema.proto".toPath(), sameAsNio = false)
+
+ val c = "C:\\Windows\\".toPath()
+ val d = "\\\\localhost\\c$\\project\\notes.txt".toPath()
+ assertRelativeToFails(c, d, sameAsNio = false)
+ assertRelativeToFails(d, c, sameAsNio = false)
+ }
+
+ @Test
+ fun absoluteUnixRoot() {
+ val a = "/Users/jesse/hello.txt".toPath()
+ val b = "/".toPath()
+ assertRelativeTo(a, b, "../../..".toPath())
+ assertRelativeTo(b, a, "Users/jesse/hello.txt".toPath())
+
+ val c = "/Users/jesse/hello.txt".toPath()
+ val d = "/Admin/Secret".toPath()
+ assertRelativeTo(c, d, "../../../Admin/Secret".toPath())
+ assertRelativeTo(d, c, "../../Users/jesse/hello.txt".toPath())
+
+ val e = "/Users/".toPath()
+ val f = "/Users".toPath()
+ assertRelativeTo(e, f, ".".toPath())
+ assertRelativeTo(f, e, ".".toPath())
+ }
+
+ // Note that we handle the normalized version of the paths when computing relative paths.
+ @Test
+ fun relativeToUnnormalizedPath() {
+ val a = "Users/../a".toPath() // `a` if normalized.
+ val b = "Users/b/../c".toPath() // `Users/c` if normalized.
+ assertRelativeToFails(a, b, sameAsNio = false)
+ assertRelativeToFails(b, a, sameAsNio = false)
+ assertRelativeTo(a.normalized(), b.normalized(), "../Users/c".toPath())
+ assertRelativeTo(b.normalized(), a.normalized(), "../../a".toPath())
+ }
+
+ @Test
+ fun relativeToNormalizedPath() {
+ val a = "Users/../a".toPath(normalize = true) // results to `a`.
+ val b = "Users/b/../c".toPath(normalize = true) // results to `Users/c`.
+ assertRelativeTo(a, b, "../Users/c".toPath())
+ assertRelativeTo(b, a, "../../a".toPath())
+ }
+
+ @Test
+ fun absoluteToRelative() {
+ val a = "/Users/jesse/hello.txt".toPath()
+ val b = "Desktop/goodbye.txt".toPath()
+
+ var exception = assertRelativeToFails(a, b)
+ assertEquals(
+ "Paths of different roots cannot be relative to each other: " +
+ "Desktop/goodbye.txt and /Users/jesse/hello.txt",
+ exception.message,
+ )
+
+ exception = assertRelativeToFails(b, a)
+ assertEquals(
+ "Paths of different roots cannot be relative to each other: " +
+ "/Users/jesse/hello.txt and Desktop/goodbye.txt",
+ exception.message,
+ )
+ }
+
+ @Test
+ fun absoluteToAbsolute() {
+ val a = "/Users/jesse/hello.txt".toPath()
+ val b = "/Users/benoit/Desktop/goodbye.txt".toPath()
+ assertRelativeTo(a, b, "../../benoit/Desktop/goodbye.txt".toPath())
+ assertRelativeTo(b, a, "../../../jesse/hello.txt".toPath())
+ }
+
+ @Test
+ fun absoluteToSelf() {
+ val a = "/Users/jesse/hello.txt".toPath()
+ assertRelativeTo(a, a, ".".toPath())
+
+ val b = "/Users/benoit/../jesse/hello.txt".toPath()
+ // NIO normalizes.
+ assertRelativeTo(a, b, "../../benoit/../jesse/hello.txt".toPath(), sameAsNio = false)
+ assertRelativeToFails(b, a, sameAsNio = false)
+ assertRelativeTo(b.normalized(), a, ".".toPath())
+ assertRelativeTo(a, b.normalized(), ".".toPath())
+ }
+
+ @Test
+ fun relativeToSelf() {
+ val a = "Desktop/hello.txt".toPath()
+ assertRelativeTo(a, a, ".".toPath())
+
+ val b = "Documents/../Desktop/hello.txt".toPath()
+ // NIO normalizes.
+ assertRelativeTo(a, b, "../../Documents/../Desktop/hello.txt".toPath(), sameAsNio = false)
+ assertRelativeToFails(b, a, sameAsNio = false)
+ assertRelativeTo(a, b.normalized(), ".".toPath())
+ assertRelativeTo(b.normalized(), a, ".".toPath())
+ }
+
+ @Test
+ fun relativeToRelative() {
+ val a = "Desktop/documents/resume.txt".toPath()
+ val b = "Desktop/documents/2021/taxes.txt".toPath()
+ assertRelativeTo(a, b, "../2021/taxes.txt".toPath(), sameAsNio = false)
+ assertRelativeTo(b, a, "../../resume.txt".toPath(), sameAsNio = false)
+
+ val c = "documents/resume.txt".toPath()
+ val d = "downloads/2021/taxes.txt".toPath()
+ assertRelativeTo(c, d, "../../downloads/2021/taxes.txt".toPath(), sameAsNio = false)
+ assertRelativeTo(d, c, "../../../documents/resume.txt".toPath(), sameAsNio = false)
+ }
+
+ @Test
+ fun relativeToRelativeWithMiddleDots() {
+ val a = "Desktop/documents/a...n".toPath()
+ val b = "Desktop/documents/m...z".toPath()
+ assertRelativeTo(a, b, "../m...z".toPath())
+ assertRelativeTo(b, a, "../a...n".toPath())
+ }
+
+ @Test
+ fun relativeToRelativeWithMiddleDotsInCommonPrefix() {
+ val a = "Desktop/documents/a...n/red".toPath()
+ val b = "Desktop/documents/a...m/blue".toPath()
+ assertRelativeTo(a, b, "../../a...m/blue".toPath())
+ assertRelativeTo(b, a, "../../a...n/red".toPath())
+ }
+
+ @Test
+ fun relativeToRelativeWithUpNavigationPrefix() {
+ // We can't navigate from 'taxes' to 'resumes' because we don't know the name of 'Documents'.
+ // /Users/jwilson/Documents/2021/Current
+ // /Users/jwilson/Documents/resumes
+ // /Users/jwilson/taxes
+ val a = "../../resumes".toPath()
+ val b = "../../../taxes".toPath()
+ assertRelativeTo(a, b, "../../taxes".toPath())
+ assertRelativeToFails(b, a, sameAsNio = false)
+ }
+
+ @Test
+ fun relativeToRelativeDifferentSlashes() {
+ val a = "Desktop/documents/resume.txt".toPath()
+ val b = "Desktop\\documents\\2021\\taxes.txt".toPath()
+ assertRelativeTo(a, b, "../2021/taxes.txt".toPath(), sameAsNio = false)
+ assertRelativeTo(b, a, "..\\..\\resume.txt".toPath(), sameAsNio = false)
+
+ val c = "documents/resume.txt".toPath()
+ val d = "downloads\\2021\\taxes.txt".toPath()
+ assertRelativeTo(c, d, "../../downloads/2021/taxes.txt".toPath(), sameAsNio = false)
+ assertRelativeTo(d, c, "..\\..\\..\\documents\\resume.txt".toPath(), sameAsNio = false)
+ }
+
+ @Test
+ fun windowsUncPathsDoNotDotDot() {
+ assertEquals(
+ """\\localhost\c$\Windows""",
+ """\\localhost\c$\Windows""".toPath().toString(),
+ )
+ assertEquals(
+ """\\127.0.0.1\c$\Windows""",
+ """\\127.0.0.1\c$\Windows""".toPath().toString(),
+ )
+ assertEquals(
+ """\\127.0.0.1\c$\Windows\..\Windows""",
+ """\\127.0.0.1\c$\Windows\..\Windows""".toPath().toString(),
+ )
+ assertEquals(
+ """\\127.0.0.1\..\localhost\c$\Windows""",
+ """\\127.0.0.1\..\localhost\c$\Windows""".toPath().toString(),
+ )
+ assertEquals(
+ """\\127.0.0.1\c$\..\d$""",
+ """\\127.0.0.1\c$\..\d$""".toPath().toString(),
+ )
+
+ assertEquals(
+ """\\localhost\c$\Windows""",
+ """\\localhost\c$\Windows""".toPath(normalize = true).toString(),
+ )
+ assertEquals(
+ """\\127.0.0.1\c$\Windows""",
+ """\\127.0.0.1\c$\Windows""".toPath(normalize = true).toString(),
+ )
+ assertEquals(
+ """\\127.0.0.1\c$\Windows""",
+ """\\127.0.0.1\c$\Windows\..\Windows""".toPath(normalize = true).toString(),
+ )
+ assertEquals(
+ """\\127.0.0.1\localhost\c$\Windows""",
+ """\\127.0.0.1\..\localhost\c$\Windows""".toPath(normalize = true).toString(),
+ )
+ assertEquals(
+ """\\127.0.0.1\d$""",
+ """\\127.0.0.1\c$\..\d$""".toPath(normalize = true).toString(),
+ )
+ assertEquals(
+ """\\127.0.0.1\c$""",
+ """\\..\127.0.0.1\..\c$""".toPath(normalize = true).toString(),
+ )
+ }
+
+ @Test fun normalizeAbsolute() {
+ assertEquals("/", "/.".toPath(normalize = true).toString())
+ assertEquals("/", "/.".toPath(normalize = false).toString())
+ assertEquals("/", "/..".toPath(normalize = true).toString())
+ assertEquals("/", "/..".toPath(normalize = false).toString())
+ assertEquals("/", "/../..".toPath(normalize = true).toString())
+ assertEquals("/", "/../..".toPath(normalize = false).toString())
+
+ assertEquals("/a/b", "/a/./b".toPath(normalize = true).toString())
+ assertEquals("/a/b", "/a/./b".toPath(normalize = false).toString())
+ assertEquals("/a/.../b", "/a/..././b".toPath(normalize = true).toString())
+ assertEquals("/a/.../b", "/a/..././b".toPath(normalize = false).toString())
+ assertEquals("/", "/a/..".toPath(normalize = true).toString())
+ assertEquals("/a/..", "/a/..".toPath(normalize = false).toString())
+ assertEquals("/b", "/../a/../b".toPath(normalize = true).toString())
+ assertEquals("/a/../b", "/../a/../b".toPath(normalize = false).toString())
+ }
+
+ @Test fun normalizeRelative() {
+ assertEquals(".", ".".toPath(normalize = true).toString())
+ assertEquals(".", ".".toPath(normalize = false).toString())
+ assertEquals("..", "..".toPath(normalize = true).toString())
+ assertEquals("..", "..".toPath(normalize = false).toString())
+ assertEquals("../..", "../..".toPath(normalize = true).toString())
+ assertEquals("../..", "../..".toPath(normalize = false).toString())
+
+ assertEquals("a/b", "a/./b".toPath(normalize = true).toString())
+ assertEquals("a/b", "a/./b".toPath(normalize = false).toString())
+ assertEquals("a/.../b", "a/..././b".toPath(normalize = true).toString())
+ assertEquals("a/.../b", "a/..././b".toPath(normalize = false).toString())
+ assertEquals(".", "a/..".toPath(normalize = true).toString())
+ assertEquals("a/..", "a/..".toPath(normalize = false).toString())
+ assertEquals("../b", "../a/../b".toPath(normalize = true).toString())
+ assertEquals("../a/../b", "../a/../b".toPath(normalize = false).toString())
+ }
+
+ @Test fun normalized() {
+ val normalizedRoot = "/".toPath()
+ assertEquals(normalizedRoot, "/a/..".toPath(normalize = true))
+ assertEquals(normalizedRoot, "/a/..".toPath(normalize = false).normalized())
+ assertEquals(normalizedRoot, "/a/..".toPath(normalize = true).normalized())
+
+ val normalizedRelative = "../b".toPath()
+ assertEquals(normalizedRelative, "../a/../b".toPath(normalize = true))
+ assertEquals(normalizedRelative, "../a/../b".toPath(normalize = false).normalized())
+ assertEquals(normalizedRelative, "../a/../b".toPath(normalize = true).normalized())
}
}
diff --git a/okio/src/commonTest/kotlin/okio/SystemFileSystemTest.kt b/okio/src/commonTest/kotlin/okio/SystemFileSystemTest.kt
deleted file mode 100644
index df1d620a..00000000
--- a/okio/src/commonTest/kotlin/okio/SystemFileSystemTest.kt
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * Copyright (C) 2020 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 kotlinx.datetime.Clock
-import kotlin.time.ExperimentalTime
-
-@ExperimentalTime
-@ExperimentalFileSystem
-class SystemFileSystemTest : AbstractFileSystemTest(
- clock = Clock.System,
- fileSystem = FileSystem.SYSTEM,
- windowsLimitations = Path.DIRECTORY_SEPARATOR == "\\",
- temporaryDirectory = FileSystem.SYSTEM_TEMPORARY_DIRECTORY
-)
diff --git a/okio/src/commonTest/kotlin/okio/UnsafeCursorTest.kt b/okio/src/commonTest/kotlin/okio/UnsafeCursorTest.kt
index 680ebdc2..10290eac 100644
--- a/okio/src/commonTest/kotlin/okio/UnsafeCursorTest.kt
+++ b/okio/src/commonTest/kotlin/okio/UnsafeCursorTest.kt
@@ -17,6 +17,7 @@ package okio
import kotlin.test.Test
import kotlin.test.assertEquals
+import kotlin.test.assertTrue
class UnsafeCursorTest {
@Test fun acquireForRead() {
@@ -43,7 +44,7 @@ class UnsafeCursorTest {
val cursor = buffer.readAndWriteUnsafe()
try {
while (cursor.next() != -1) {
- cursor.data!!.fill('z'.toByte(), cursor.start, cursor.end)
+ cursor.data!!.fill('z'.code.toByte(), cursor.start, cursor.end)
}
} finally {
cursor.close()
@@ -58,7 +59,7 @@ class UnsafeCursorTest {
val cursor = buffer.readAndWriteUnsafe()
try {
cursor.expandBuffer(100)
- cursor.data!!.fill('z'.toByte(), cursor.start, cursor.start + 100)
+ cursor.data!!.fill('z'.code.toByte(), cursor.start, cursor.start + 100)
cursor.resizeBuffer(100L)
} finally {
cursor.close()
@@ -77,11 +78,15 @@ class UnsafeCursorTest {
val cursor = buffer.readAndWriteUnsafe()
try {
cursor.resizeBuffer(100L)
- cursor.data!!.fill('z'.toByte(), cursor.start, cursor.end)
+ cursor.data!!.fill('z'.code.toByte(), cursor.start, cursor.end)
} finally {
cursor.close()
}
assertEquals("z".repeat(100), buffer.readUtf8())
}
+
+ @Test fun testUnsafeCursorIsClosable() {
+ assertTrue(Closeable::class.isInstance(Buffer.UnsafeCursor()))
+ }
}
diff --git a/okio/src/commonTest/kotlin/okio/Utf8KotlinTest.kt b/okio/src/commonTest/kotlin/okio/Utf8KotlinTest.kt
index 1ade4179..337fe83a 100644
--- a/okio/src/commonTest/kotlin/okio/Utf8KotlinTest.kt
+++ b/okio/src/commonTest/kotlin/okio/Utf8KotlinTest.kt
@@ -16,17 +16,17 @@
package okio
-import okio.ByteString.Companion.decodeHex
-import okio.internal.commonAsUtf8ToByteArray
import kotlin.test.Test
import kotlin.test.assertEquals
import kotlin.test.assertFailsWith
+import okio.ByteString.Companion.decodeHex
+import okio.internal.commonAsUtf8ToByteArray
class Utf8KotlinTest {
@Test fun oneByteCharacters() {
assertEncoded("00", 0x00) // Smallest 1-byte character.
- assertEncoded("20", ' '.toInt())
- assertEncoded("7e", '~'.toInt())
+ assertEncoded("20", ' '.code)
+ assertEncoded("7e", '~'.code)
assertEncoded("7f", 0x7f) // Largest 1-byte character.
}
@@ -90,10 +90,10 @@ class Utf8KotlinTest {
@Test fun highSurrogateFollowedByNonSurrogate() {
assertStringEncoded("3fee8080", "\ud800\ue000") // "?\ue000": Following character is too high.
- assertCodePointDecoded("f090ee8080", REPLACEMENT_CODE_POINT, '\ue000'.toInt())
+ assertCodePointDecoded("f090ee8080", REPLACEMENT_CODE_POINT, '\ue000'.code)
assertStringEncoded("3f61", "\ud800\u0061") // "?a": Following character is too low.
- assertCodePointDecoded("f09061", REPLACEMENT_CODE_POINT, 'a'.toInt())
+ assertCodePointDecoded("f09061", REPLACEMENT_CODE_POINT, 'a'.code)
}
@Test fun doubleLowSurrogate() {
@@ -113,7 +113,7 @@ class Utf8KotlinTest {
@Test fun writeSurrogateCodePoint() {
assertStringEncoded("ed9fbf", "\ud7ff") // Below lowest surrogate is okay.
- assertCodePointDecoded("ed9fbf", '\ud7ff'.toInt())
+ assertCodePointDecoded("ed9fbf", '\ud7ff'.code)
assertStringEncoded("3f", "\ud800") // Lowest surrogate gets '?'.
assertCodePointDecoded("eda080", REPLACEMENT_CODE_POINT)
@@ -122,7 +122,7 @@ class Utf8KotlinTest {
assertCodePointDecoded("edbfbf", REPLACEMENT_CODE_POINT)
assertStringEncoded("ee8080", "\ue000") // Above highest surrogate is okay.
- assertCodePointDecoded("ee8080", '\ue000'.toInt())
+ assertCodePointDecoded("ee8080", '\ue000'.code)
}
@Test fun size() {
diff --git a/okio/src/commonTest/kotlin/okio/time.kt b/okio/src/commonTest/kotlin/okio/time.kt
deleted file mode 100644
index 36fdf94a..00000000
--- a/okio/src/commonTest/kotlin/okio/time.kt
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Copyright (C) 2020 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 kotlinx.datetime.Instant
-
-@ExperimentalFileSystem
-internal val FileMetadata.createdAt: Instant?
- get() {
- val createdAt = createdAtMillis ?: return null
- return Instant.fromEpochMilliseconds(createdAt)
- }
-
-@ExperimentalFileSystem
-internal val FileMetadata.lastModifiedAt: Instant?
- get() {
- val lastModifiedAt = lastModifiedAtMillis ?: return null
- return Instant.fromEpochMilliseconds(lastModifiedAt)
- }
-
-@ExperimentalFileSystem
-internal val FileMetadata.lastAccessedAt: Instant?
- get() {
- val lastAccessedAt = lastAccessedAtMillis ?: return null
- return Instant.fromEpochMilliseconds(lastAccessedAt)
- }