Skip to content

Commit

Permalink
tests: first pass on unit testing
Browse files Browse the repository at this point in the history
  • Loading branch information
JustPyrrha committed Aug 4, 2024
1 parent 55b9cf9 commit 51b3333
Show file tree
Hide file tree
Showing 8 changed files with 315 additions and 2 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ jobs:
run: chmod +x gradlew

- name: Build and Test
run: ./gradlew build test spotlessCheck
run: ./gradlew build test spotlessCheck koverXmlReport

publish:
name: Publish
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/pullrequest-build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,4 +27,4 @@ jobs:
run: chmod +x gradlew

- name: Build, Test, and Check
run: ./gradlew build test spotlessCheck
run: ./gradlew build test spotlessCheck koverXmlReport
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,5 @@
build/
docs-publishing/
runs/
logs/
*.iml
4 changes: 4 additions & 0 deletions build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ plugins {
alias(libs.plugins.changelog)
alias(libs.plugins.dokka)
alias(libs.plugins.minotaur)
alias(libs.plugins.kotlinx.kover)

`maven-publish`
}
Expand All @@ -38,7 +39,10 @@ dependencies {
modImplementation(libs.fabric.loader)
modImplementation(fabricApi.module("fabric-networking-api-v1", libs.versions.fabricApi.get()))
implementation(libs.kotlinx.serializationCore)

testImplementation(libs.kotlin.test)
testImplementation(libs.kotlin.test.junit5)
testImplementation(libs.junit.params)
}

tasks {
Expand Down
5 changes: 5 additions & 0 deletions libs.versions.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@ fabricApi = "0.100.7+1.21" # https://github.com/FabricMC/fabric/releases
fabricKotlin = "1.11.0+kotlin.2.0.0" # https://github.com/FabricMC/fabric-language-kotlin/releases
fabricLoader = "0.16.0" # https://github.com/FabricMC/fabric-loader/releases
fabricLoom = "1.7-SNAPSHOT" # https://github.com/FabricMC/fabric-loom/releases
junit-params = "5.10.1" # check which version of junit-jupiter-api/engine kotlin-test adds
kotlin = "2.0.0"
kotlinx-kover = "0.8.3" #https://github.com/Kotlin/kotlinx-kover/releases
kotlinxSerialization = "1.7.1" # https://github.com/Kotlin/kotlinx.serialization/releases
minecraft = "1.21"
minotaur = "2.8.7" # https://github.com/modrinth/minotaur/releases
Expand All @@ -16,7 +18,9 @@ dokka-pluginBase = { group = "org.jetbrains.dokka", name = "dokka-base", version
dokka-pluginVersioning = { group = "org.jetbrains.dokka", name = "versioning-plugin", version.ref = "dokka" }
fabric-kotlin = { group = "net.fabricmc", name = "fabric-language-kotlin", version.ref = "fabricKotlin" }
fabric-loader = { group = "net.fabricmc", name = "fabric-loader", version.ref = "fabricLoader" }
junit-params = { group = "org.junit.jupiter", name = "junit-jupiter-params", version.ref = "junit-params" }
kotlin-test = { group = "org.jetbrains.kotlin", name = "kotlin-test" }
kotlin-test-junit5 = { group = "org.jetbrains.kotlin", name = "kotlin-test-junit5" }
kotlinx-serializationCore = { group = "org.jetbrains.kotlinx", name = "kotlinx-serialization-core", version.ref = "kotlinxSerialization" }
minecraft = { group = "com.mojang", name = "minecraft", version.ref = "minecraft" }

Expand All @@ -25,6 +29,7 @@ changelog = { id = "org.jetbrains.changelog", version.ref = "changelog" }
dokka = { id = "org.jetbrains.dokka", version.ref = "dokka" }
kotlin = { id = "org.jetbrains.kotlin.jvm", version.ref = "kotlin" }
kotlin-serialization = { id = "org.jetbrains.kotlin.plugin.serialization", version.ref = "kotlin" }
kotlinx-kover = { id = "org.jetbrains.kotlinx.kover", version.ref = "kotlinx-kover" }
loom = { id = "fabric-loom", version.ref = "fabricLoom" }
minotaur = { id = "com.modrinth.minotaur", version.ref = "minotaur" }
spotless = { id = "com.diffplug.spotless", version.ref = "spotless" }
217 changes: 217 additions & 0 deletions src/test/kotlin/EncodeDecodeTests.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,217 @@
/*
* Copyright (C) 2024 Wanderia - All Rights Reserved
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
@file:OptIn(ExperimentalSerializationApi::class)

import dev.wanderia.netlib.format.decodeFrom
import dev.wanderia.netlib.format.encodeTo
import dev.wanderia.netlib.payload.api.PayloadChannel
import java.util.UUID
import java.util.stream.Stream
import kotlin.random.Random
import kotlinx.serialization.ExperimentalSerializationApi
import kotlinx.serialization.Serializable
import net.fabricmc.fabric.api.networking.v1.PacketByteBufs
import org.junit.jupiter.api.Assertions.assertEquals
import org.junit.jupiter.params.ParameterizedTest
import org.junit.jupiter.params.provider.Arguments
import org.junit.jupiter.params.provider.MethodSource

class EncodeDecodeTests {

@Serializable
data class TestDataA(
val boolean: Boolean?,
val byte: Byte?,
val char: Char?,
val double: Double?,
val float: Float?,
val int: Int?,
val long: Long?,
val short: Short?,
val string: String?,
val enum: PayloadChannel?
)

@Serializable
data class TestDataB(
val booleanCollection: List<Boolean>,
val byteCollection: List<Byte>,
val charCollection: List<Char>,
val doubleCollection: List<Double>,
val floatCollection: List<Float>,
val intCollection: List<Int>,
val longCollection: List<Long>,
val shortCollection: List<Short>,
val stringCollection: List<String>,
val enumCollection: List<PayloadChannel>
)

@Serializable
data class TestDataC(
val structureA: TestDataA,
val structureB: TestDataB,
val collectionA: List<TestDataA>,
val collectionB: List<TestDataB>,
)

@ParameterizedTest
@MethodSource("testDataAProvider")
fun `should encode and decode values`(data: TestDataA) {
// given
val buf = PacketByteBufs.create()

// when
encodeTo(buf, data)

// then
assertEquals(data, decodeFrom<TestDataA>(buf))
}

@ParameterizedTest
@MethodSource("testDataBProvider")
fun `should encode and decode collections`(data: TestDataB) {
// given
val buf = PacketByteBufs.create()

// when
encodeTo(buf, data)

// then
assertEquals(data, decodeFrom<TestDataB>(buf))
}

@ParameterizedTest
@MethodSource("testDataCProvider")
fun `should encode and decode structures`(data: TestDataC) {
// given
val buf = PacketByteBufs.create()

// when
encodeTo(buf, data)

// then
assertEquals(data, decodeFrom<TestDataC>(buf))
}

companion object {
@JvmStatic
fun testDataAProvider(): Stream<Arguments> =
Stream.of(
Arguments.of(randomDataA(0)),
Arguments.of(randomDataA(1)),
Arguments.of(randomDataA(2)),
Arguments.of(randomDataA(3)),
Arguments.of(randomDataA(4)),
)

@JvmStatic
fun testDataBProvider(): Stream<Arguments> =
Stream.of(
Arguments.of(randomDataB()),
Arguments.of(randomDataB()),
Arguments.of(randomDataB()),
Arguments.of(randomDataB()),
Arguments.of(randomDataB()),
)

@JvmStatic
fun testDataCProvider(): Stream<Arguments> =
Stream.of(
Arguments.of(randomDataC()),
Arguments.of(randomDataC()),
Arguments.of(randomDataC()),
Arguments.of(randomDataC()),
Arguments.of(randomDataC()),
)

@JvmStatic
fun randomDataA(index: Int): TestDataA =
TestDataA(
boolean = listOf(null, true, false)[index.coerceIn(0, 2)],
byte =
listOf(null, 0b0, 0b1, (Byte.MIN_VALUE..Byte.MAX_VALUE).random().toByte())[
index.coerceIn(0, 3)],
char =
listOf(null, ('a'..'z').random(), (Char.MIN_VALUE..Char.MAX_VALUE).random())[
index.coerceIn(0, 2)],
double = listOf(null, 0.0, -1.0, 1.0, Random.nextDouble())[index.coerceIn(0, 4)],
float = listOf(null, 0f, -1f, 1f, Random.nextFloat())[index.coerceIn(0, 4)],
int = listOf(null, 0, -1, 1, Random.nextInt())[index.coerceIn(0, 4)],
long = listOf(null, 0L, -1L, 1L, Random.nextLong())[index.coerceIn(0, 4)],
short =
listOf(
null,
0.toShort(),
(-1).toShort(),
1.toShort(),
(Short.MIN_VALUE..Short.MAX_VALUE).random().toShort()
)[index.coerceIn(0, 4)],
string = listOf(null, "", UUID.randomUUID().toString())[index.coerceIn(0, 2)],
enum =
listOf(
null,
PayloadChannel.ClientboundPlay,
PayloadChannel.ServerboundPlay,
PayloadChannel.ClientboundConfiguration,
PayloadChannel.ServerboundConfiguration
)[index.coerceIn(0, 4)],
)

@JvmStatic
fun randomDataB(): TestDataB =
TestDataB(
booleanCollection = listOf(true, false),
byteCollection =
listOf(0b0, 0b1, (Byte.MIN_VALUE..Byte.MAX_VALUE).random().toByte()),
charCollection =
listOf(('a'..'z').random(), (Char.MIN_VALUE..Char.MAX_VALUE).random()),
doubleCollection = listOf(0.0, -1.0, 1.0, Random.nextDouble()),
floatCollection = listOf(0f, -1f, 1f, Random.nextFloat()),
intCollection = listOf(0, -1, 1, Random.nextInt()),
longCollection = listOf(0L, -1L, 1L, Random.nextLong()),
shortCollection =
listOf(
0.toShort(),
(-1).toShort(),
1.toShort(),
(Short.MIN_VALUE..Short.MAX_VALUE).random().toShort()
),
stringCollection = listOf("", UUID.randomUUID().toString()),
enumCollection =
listOf(
PayloadChannel.ClientboundPlay,
PayloadChannel.ServerboundPlay,
PayloadChannel.ClientboundConfiguration,
PayloadChannel.ServerboundConfiguration
),
)

@JvmStatic
fun randomDataC(): TestDataC =
TestDataC(
structureA = randomDataA(Random.nextInt(5)),
structureB = randomDataB(),
collectionA =
listOf(
randomDataA(Random.nextInt(5)),
randomDataA(Random.nextInt(5)),
randomDataA(Random.nextInt(5)),
randomDataA(Random.nextInt(5)),
randomDataA(Random.nextInt(5))
),
collectionB =
listOf(
randomDataB(),
randomDataB(),
randomDataB(),
randomDataB(),
randomDataB()
),
)
}
}
48 changes: 48 additions & 0 deletions src/test/kotlin/SerializerTests.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
/*
* Copyright (C) 2024 Wanderia - All Rights Reserved
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
@file:OptIn(ExperimentalSerializationApi::class)

import dev.wanderia.netlib.format.PacketByteBufDecoder
import dev.wanderia.netlib.format.PacketByteBufEncoder
import dev.wanderia.netlib.serializers.IdentifierSerializer
import dev.wanderia.netlib.serializers.UUIDSerializer
import java.util.*
import kotlin.test.Test
import kotlin.test.assertEquals
import kotlinx.serialization.ExperimentalSerializationApi
import net.fabricmc.fabric.api.networking.v1.PacketByteBufs
import net.minecraft.resources.ResourceLocation

class SerializerTests {

@Test
fun `identifiers should serialize and deserialize`() {
// given
val buf = PacketByteBufs.create()
val id = ResourceLocation.parse("test")

// when
IdentifierSerializer.serialize(PacketByteBufEncoder(buf), id)

// then
assertEquals(id, IdentifierSerializer.deserialize(PacketByteBufDecoder(buf)))
}

@Test
fun `uuids should serialize and deserialize`() {
// given
val buf = PacketByteBufs.create()
val uuid = UUID.randomUUID()

// when
UUIDSerializer.serialize(PacketByteBufEncoder(buf), uuid)

// then
assertEquals(uuid, UUIDSerializer.deserialize(PacketByteBufDecoder(buf)))
}
}
38 changes: 38 additions & 0 deletions src/test/kotlin/SerializersModuleTests.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
/*
* Copyright (C) 2024 Wanderia - All Rights Reserved
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
@file:OptIn(ExperimentalSerializationApi::class)

import dev.wanderia.netlib.format.decodeFrom
import dev.wanderia.netlib.format.encodeTo
import java.util.UUID
import kotlin.test.Test
import kotlin.test.assertEquals
import kotlinx.serialization.Contextual
import kotlinx.serialization.ExperimentalSerializationApi
import kotlinx.serialization.Serializable
import net.fabricmc.fabric.api.networking.v1.PacketByteBufs
import net.minecraft.resources.ResourceLocation

class SerializersModuleTests {

@Serializable
data class TestData(@Contextual val identifier: ResourceLocation, @Contextual val uuid: UUID)

@Test
fun `should use contextual serializers`() {
// given
val buf = PacketByteBufs.create()
val testData = TestData(ResourceLocation.parse("test"), UUID.randomUUID())

// when
encodeTo(buf, testData)

// then
assertEquals(testData, decodeFrom<TestData>(buf))
}
}

0 comments on commit 51b3333

Please sign in to comment.