Skip to content

Commit

Permalink
Adopt Burst for parameterized tests (#1534)
Browse files Browse the repository at this point in the history
It supports Kotlin/Multiplatform.

https://github.com/cashapp/burst

Co-authored-by: Jesse Wilson <jwilson@squareup.com>
  • Loading branch information
swankjesse and squarejesse authored Oct 17, 2024
1 parent c43c9a6 commit 6bcd3cf
Show file tree
Hide file tree
Showing 17 changed files with 335 additions and 532 deletions.
1 change: 1 addition & 0 deletions build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ plugins {
buildscript {
dependencies {
classpath(libs.android.gradle.plugin)
classpath(libs.burst.gradle.plugin)
classpath(libs.dokka)
classpath(libs.jmh.gradle.plugin)
classpath(libs.binaryCompatibilityValidator)
Expand Down
1 change: 1 addition & 0 deletions gradle/libs.versions.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ androidx-test-ext-junit = { module = "androidx.test.ext:junit", version = "1.2.1
androidx-test-runner = { module = "androidx.test:runner", version = "1.5.2" }
binaryCompatibilityValidator = { module = "org.jetbrains.kotlinx.binary-compatibility-validator:org.jetbrains.kotlinx.binary-compatibility-validator.gradle.plugin", version = "0.16.3" }
bnd = { module = "biz.aQute.bnd:biz.aQute.bnd.gradle", version = "7.0.0" }
burst-gradle-plugin = { module = "app.cash.burst:burst-gradle-plugin", version = "0.5.0" }
dokka = { module = "org.jetbrains.dokka:dokka-gradle-plugin", version = "1.9.20" }
jmh-core = { module = "org.openjdk.jmh:jmh-core", version.ref = "jmh" }
jmh-generator = { module = "org.openjdk.jmh:jmh-generator-annprocess", version.ref = "jmh" }
Expand Down
1 change: 1 addition & 0 deletions okio/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import org.jetbrains.kotlin.gradle.plugin.mpp.TestExecutable

plugins {
kotlin("multiplatform")
id("app.cash.burst")
id("org.jetbrains.dokka")
id("com.vanniktech.maven.publish.base")
id("build-support")
Expand Down
222 changes: 101 additions & 121 deletions okio/src/commonTest/kotlin/okio/BufferedSourceFactory.kt
Original file line number Diff line number Diff line change
Expand Up @@ -16,135 +16,115 @@

package okio

interface BufferedSourceFactory {
class Pipe(
var sink: BufferedSink,
var source: BufferedSource,
)

val isOneByteAtATime: Boolean

fun pipe(): Pipe

companion object {
val BUFFER: BufferedSourceFactory = object : BufferedSourceFactory {

override val isOneByteAtATime: Boolean
get() = false

override fun pipe(): Pipe {
val buffer = Buffer()
return Pipe(
buffer,
buffer,
)
}
enum class BufferedSourceFactory {
BUFFER {
override val isOneByteAtATime: Boolean
get() = false

override fun pipe(): Pipe {
val buffer = Buffer()
return Pipe(
buffer,
buffer,
)
}

val REAL_BUFFERED_SOURCE: BufferedSourceFactory = object :
BufferedSourceFactory {

override val isOneByteAtATime: Boolean
get() = false

override fun pipe(): Pipe {
val buffer = Buffer()
return Pipe(
buffer,
(buffer as Source).buffer(),
)
}
},

REAL_BUFFERED_SOURCE {
override val isOneByteAtATime: Boolean
get() = false

override fun pipe(): Pipe {
val buffer = Buffer()
return Pipe(
buffer,
(buffer as Source).buffer(),
)
}

/**
* A factory deliberately written to create buffers whose internal segments are always 1 byte
* long. We like testing with these segments because are likely to trigger bugs!
*/
val ONE_BYTE_AT_A_TIME_BUFFERED_SOURCE: BufferedSourceFactory = object :
BufferedSourceFactory {

override val isOneByteAtATime: Boolean
get() = true

override fun pipe(): Pipe {
val buffer = Buffer()
return Pipe(
buffer,
object : Source by buffer {
override fun read(sink: Buffer, byteCount: Long): Long {
// Read one byte into a new buffer, then clone it so that the segment is shared.
// Shared segments cannot be compacted so we'll get a long chain of short segments.
},

/**
* A factory deliberately written to create buffers whose internal segments are always 1 byte
* long. We like testing with these segments because are likely to trigger bugs!
*/
ONE_BYTE_AT_A_TIME_BUFFERED_SOURCE {
override val isOneByteAtATime: Boolean
get() = true

override fun pipe(): Pipe {
val buffer = Buffer()
return Pipe(
buffer,
object : Source by buffer {
override fun read(sink: Buffer, byteCount: Long): Long {
// Read one byte into a new buffer, then clone it so that the segment is shared.
// Shared segments cannot be compacted so we'll get a long chain of short segments.
val box = Buffer()
val result = buffer.read(box, minOf(byteCount, 1L))
if (result > 0L) sink.write(box.copy(), result)
return result
}
}.buffer(),
)
}
},

ONE_BYTE_AT_A_TIME_BUFFER {
override val isOneByteAtATime: Boolean
get() = true

override fun pipe(): Pipe {
val buffer = Buffer()
return Pipe(
object : Sink by buffer {
override fun write(source: Buffer, byteCount: Long) {
// Write each byte into a new buffer, then clone it so that the segments are shared.
// Shared segments cannot be compacted so we'll get a long chain of short segments.
for (i in 0 until byteCount) {
val box = Buffer()
val result = buffer.read(box, minOf(byteCount, 1L))
if (result > 0L) sink.write(box.copy(), result)
return result
box.write(source, 1)
buffer.write(box.copy(), 1)
}
}.buffer(),
)
}
}
}.buffer(),
buffer,
)
}

val ONE_BYTE_AT_A_TIME_BUFFER: BufferedSourceFactory = object :
BufferedSourceFactory {

override val isOneByteAtATime: Boolean
get() = true

override fun pipe(): Pipe {
val buffer = Buffer()
return Pipe(
object : Sink by buffer {
override fun write(source: Buffer, byteCount: Long) {
// Write each byte into a new buffer, then clone it so that the segments are shared.
// Shared segments cannot be compacted so we'll get a long chain of short segments.
for (i in 0 until byteCount) {
val box = Buffer()
box.write(source, 1)
buffer.write(box.copy(), 1)
}
}
}.buffer(),
buffer,
)
}
},

PEEK_BUFFER {
override val isOneByteAtATime: Boolean
get() = false

override fun pipe(): Pipe {
val buffer = Buffer()
return Pipe(
buffer,
buffer.peek(),
)
}

val PEEK_BUFFER: BufferedSourceFactory = object : BufferedSourceFactory {

override val isOneByteAtATime: Boolean
get() = false

override fun pipe(): Pipe {
val buffer = Buffer()
return Pipe(
buffer,
buffer.peek(),
)
}
},

PEEK_BUFFERED_SOURCE {
override val isOneByteAtATime: Boolean
get() = false

override fun pipe(): Pipe {
val buffer = Buffer()
return Pipe(
buffer,
(buffer as Source).buffer().peek(),
)
}
},
;

val PEEK_BUFFERED_SOURCE: BufferedSourceFactory = object :
BufferedSourceFactory {
abstract val isOneByteAtATime: Boolean

override val isOneByteAtATime: Boolean
get() = false
abstract fun pipe(): Pipe

override fun pipe(): Pipe {
val buffer = Buffer()
return Pipe(
buffer,
(buffer as Source).buffer().peek(),
)
}
}

val PARAMETERIZED_TEST_VALUES = mutableListOf<Array<Any>>(
arrayOf(BUFFER),
arrayOf(REAL_BUFFERED_SOURCE),
arrayOf(ONE_BYTE_AT_A_TIME_BUFFERED_SOURCE),
arrayOf(ONE_BYTE_AT_A_TIME_BUFFER),
arrayOf(PEEK_BUFFER),
arrayOf(PEEK_BUFFERED_SOURCE),
)
}
class Pipe(
var sink: BufferedSink,
var source: BufferedSource,
)
}
12 changes: 2 additions & 10 deletions okio/src/jvmTest/kotlin/okio/AwaitSignalTest.kt
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
*/
package okio

import app.cash.burst.Burst
import java.io.InterruptedIOException
import java.util.concurrent.TimeUnit
import java.util.concurrent.locks.Condition
Expand All @@ -25,11 +26,8 @@ import org.junit.Assert.assertEquals
import org.junit.Assert.assertTrue
import org.junit.Assert.fail
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.runners.Parameterized
import org.junit.runners.Parameterized.Parameters

@RunWith(Parameterized::class)
@Burst
class AwaitSignalTest(
factory: TimeoutFactory,
) {
Expand Down Expand Up @@ -215,10 +213,4 @@ class AwaitSignalTest(
TimeUnit.MILLISECONDS,
)
}

companion object {
@Parameters(name = "{0}")
@JvmStatic
fun parameters(): List<Array<out Any?>> = TimeoutFactory.entries.map { arrayOf(it) }
}
}
21 changes: 5 additions & 16 deletions okio/src/jvmTest/kotlin/okio/BufferCursorKotlinTest.kt
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
*/
package okio

import app.cash.burst.Burst
import kotlin.test.assertEquals
import kotlin.test.assertFalse
import kotlin.test.assertNotSame
Expand All @@ -24,23 +25,11 @@ import okio.Buffer.UnsafeCursor
import okio.TestUtil.deepCopy
import org.junit.Assume.assumeTrue
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.runners.Parameterized
import org.junit.runners.Parameterized.Parameter
import org.junit.runners.Parameterized.Parameters

@RunWith(Parameterized::class)
class BufferCursorKotlinTest {
companion object {
@Parameters(name = "{0}")
@JvmStatic
fun parameters(): List<Array<out Any?>> {
return BufferFactory.values().map { arrayOf(it) }
}
}

@Parameter lateinit var bufferFactory: BufferFactory

@Burst
class BufferCursorKotlinTest(
private val bufferFactory: BufferFactory,
) {
@Test fun acquireReadOnlyDoesNotCopySharedDataArray() {
val buffer = deepCopy(bufferFactory.newBuffer())
assumeTrue(buffer.size > 0L)
Expand Down
18 changes: 2 additions & 16 deletions okio/src/jvmTest/kotlin/okio/BufferCursorTest.kt
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
*/
package okio

import app.cash.burst.Burst
import java.util.Arrays
import okio.ByteString.Companion.of
import okio.TestUtil.SEGMENT_SIZE
Expand All @@ -27,11 +28,8 @@ import org.junit.Assert.assertNull
import org.junit.Assert.fail
import org.junit.Assume.assumeTrue
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.runners.Parameterized
import org.junit.runners.Parameterized.Parameters

@RunWith(Parameterized::class)
@Burst
class BufferCursorTest(
private var bufferFactory: BufferFactory,
) {
Expand Down Expand Up @@ -444,16 +442,4 @@ class BufferCursorTest(
assertEquals(originalSize, cursor.offset)
}
}

companion object {
@JvmStatic
@Parameters(name = "{0}")
fun parameters(): List<Array<Any>> {
val result = mutableListOf<Array<Any>>()
for (bufferFactory in BufferFactory.values()) {
result += arrayOf(bufferFactory)
}
return result
}
}
}
Loading

0 comments on commit 6bcd3cf

Please sign in to comment.