Skip to content

Commit

Permalink
Introducing integration testing
Browse files Browse the repository at this point in the history
* Added new source set for integration tests
* Implemented database integration tests
* Fixed issues related to undocumented API updates
* Minor upgrades and improvements
  • Loading branch information
a2xchip committed Jan 21, 2025
1 parent 28adad7 commit 01d3db1
Show file tree
Hide file tree
Showing 9 changed files with 670 additions and 73 deletions.
30 changes: 29 additions & 1 deletion build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ val spaceMavenRepositoryUrl: String by project
val sonatypeUsername: String by project
val sonatypePassword: String by project
val sdkVersion: String by project
val junitVersion: String by project

group = "com.jeliuc"
version = System.getenv("SDK_VERSION") ?: sdkVersion
Expand All @@ -33,18 +34,45 @@ repositories {
mavenCentral()
}

sourceSets {
create("integrationTest") {
kotlin.srcDir("src/integrationTest/kotlin")
resources.srcDir("src/integrationTest/resources")

compileClasspath += sourceSets["main"].output
runtimeClasspath += output + compileClasspath
}
}

dependencies {
testImplementation("org.junit.jupiter:junit-jupiter:5.11.4")
testImplementation("org.junit.jupiter:junit-jupiter:$junitVersion")
testRuntimeOnly("org.junit.platform:junit-platform-launcher")
testImplementation("org.jetbrains.kotlin:kotlin-test")
testImplementation("io.ktor:ktor-client-mock:$ktorVersion")

dokkaHtmlPlugin("org.jetbrains.dokka:versioning-plugin:2.0.0")

implementation("io.ktor:ktor-client-core:$ktorVersion")
implementation("io.ktor:ktor-client-cio:$ktorVersion")
implementation("io.ktor:ktor-client-content-negotiation:$ktorVersion")
implementation("io.ktor:ktor-serialization-kotlinx-json:$ktorVersion")
implementation("org.jetbrains.kotlinx:kotlinx-datetime-jvm:$dateTimeVersion")

add("integrationTestImplementation", kotlin("test"))
add("integrationTestImplementation", "org.junit.jupiter:junit-jupiter:5.10.0")
add("integrationTestRuntimeOnly", "org.junit.platform:junit-platform-launcher")
}

configurations["integrationTestImplementation"].extendsFrom(configurations["testImplementation"])
configurations["integrationTestRuntimeOnly"].extendsFrom(configurations["testRuntimeOnly"])

tasks.register<Test>("integrationTest") {
description = "Runs integration tests."
group = "verification"
testClassesDirs = sourceSets["integrationTest"].output.classesDirs
classpath = sourceSets["integrationTest"].runtimeClasspath
useJUnitPlatform()
shouldRunAfter(tasks.named("test"))
}

tasks.test {
Expand Down
3 changes: 2 additions & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,11 @@ kotlin.code.style=official
ktorVersion=3.0.3
dateTimeVersion=0.6.1
sdkVersion=0.3.0
junitVersion=5.11.4
spaceUsername=
spacePassword=
spaceMavenRepositoryUrl=
sonatypeUsername=
sonatypePassword=
org.jetbrains.dokka.experimental.gradle.pluginMode=V2Enabled
org.jetbrains.dokka.experimental.gradle.pluginMode.noWarn=true
org.jetbrains.dokka.experimental.gradle.pluginMode.noWarn=true
174 changes: 174 additions & 0 deletions src/integrationTest/kotlin/DatabasesIntegrationTest.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,174 @@
package com.jeliuc.turso.sdk

import com.jeliuc.turso.sdk.model.ConfigurationResponse
import com.jeliuc.turso.sdk.model.CreateDatabase
import com.jeliuc.turso.sdk.model.CreateDatabaseResponse
import com.jeliuc.turso.sdk.model.DatabaseUsageResponse
import com.jeliuc.turso.sdk.model.DeleteDatabaseResponse
import com.jeliuc.turso.sdk.model.InstanceResponse
import com.jeliuc.turso.sdk.model.ListDatabasesResponse
import com.jeliuc.turso.sdk.model.ListInstancesResponse
import com.jeliuc.turso.sdk.model.RetrieveDatabaseResponse
import com.jeliuc.turso.sdk.model.StatsResponse
import com.jeliuc.turso.sdk.model.UpdateConfigurationRequest
import com.jeliuc.turso.sdk.resource.databases
import io.ktor.client.engine.cio.CIO
import kotlinx.coroutines.runBlocking
import kotlin.test.Test
import kotlin.test.assertEquals
import kotlin.test.assertIs
import kotlin.test.assertNotNull
import kotlin.test.assertTrue

class DatabasesIntegrationTest {
val token by lazy {
System.getenv("TURSO_TOKEN")
}

val organization by lazy {
System.getenv("TURSO_ORGANIZATION")
}

val group = "default"

val newDatabaseName = "integration-test-db"

/**
* Manipulate Databases suite
*
* * Creates new database
* * List databases and find in list newly created database
* * Retrieve database by name
* * Retrieve configuration
* * Update configuration
* * Retrieve usage
* * Stats
* * List instances
* * Retrieve instance
* * Delete database
*
*/
@Test
fun `can manipulate database`() {
val client = TursoClient.using(CIO.create(), token)

val newDatabase =
CreateDatabase(
name = newDatabaseName,
group = group,
isSchema = false,
sizeLimit = "2M",
)

val createDatabaseResponse =
runBlocking {
client.databases.create(
organization,
newDatabase,
)
}

assertIs<CreateDatabaseResponse>(createDatabaseResponse, "Not create database response")

val listOfAvailableDatabases =
runBlocking {
client.databases.list(organization)
}

assertIs<ListDatabasesResponse>(listOfAvailableDatabases, "Not list databases response")
assertNotNull(listOfAvailableDatabases.databases.firstOrNull { it.name == newDatabaseName }, "New database is not in the list")

val retrievedResponse =
runBlocking {
client.databases.retrieve(
organization,
newDatabaseName,
)
}

assertIs<RetrieveDatabaseResponse>(retrievedResponse, "Not retrieve database response")
assertEquals(newDatabaseName, retrievedResponse.database.name, "Incorrect db name retrieved")

val configuration =
runBlocking {
client.databases.retrieveConfiguration(organization, newDatabaseName)
}

assertIs<ConfigurationResponse>(configuration, "Not a configuration response")

val configurationUpdate =
UpdateConfigurationRequest(
blockReads = false,
blockWrites = false,
sizeLimit = "1M",
allowAttach = false,
)

val updateConfigurationResponse =
runBlocking {
client.databases.updateConfiguration(organization, newDatabaseName, configurationUpdate)
}

assertIs<ConfigurationResponse>(updateConfigurationResponse, "Not a configuration update response")

val retrievedConfiguration =
runBlocking {
client.databases.retrieveConfiguration(
organization,
newDatabaseName,
)
}

assertIs<ConfigurationResponse>(retrievedConfiguration, "No a configuration response")

val retrievedUsage =
runBlocking {
client.databases.usage(
organization,
newDatabaseName,
)
}

assertIs<DatabaseUsageResponse>(retrievedUsage, "Not a usage response")

val statsResponse =
runBlocking {
client.databases.stats(organization, newDatabaseName)
}

assertIs<StatsResponse>(statsResponse, "Not a stats response")

val instances =
runBlocking {
client.databases.listInstances(
organization,
newDatabaseName,
)
}

assertIs<ListInstancesResponse>(instances, "Can't deserialize list instances response")
assertTrue(instances.instances.size > 0, "Zero instances")

val instanceName = instances.instances.first()!!.name
val retrievedInstance =
runBlocking {
client.databases.retrieveInstance(
organization,
newDatabaseName,
instanceName,
)
}

assertIs<InstanceResponse>(retrievedInstance, "Not an instance response")

val deleteResponse =
runBlocking {
client.databases.delete(
organization,
newDatabaseName,
)
}

assertIs<DeleteDatabaseResponse>(deleteResponse, "Not a delete response")
}
}
10 changes: 7 additions & 3 deletions src/main/kotlin/model/Database.kt
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,8 @@ data class ConfigurationResponse(

@Serializable
data class UpdateConfigurationRequest(
@SerialName("block_reads") val blockReads: Boolean,
@SerialName("block_writes") val blockWrites: Boolean,
@SerialName("size_limit") val sizeLimit: String,
@SerialName("allow_attach") val allowAttach: Boolean,
)
Expand All @@ -99,6 +101,7 @@ data class Usage(
@SerialName("rows_read") val rowsRead: Long,
@SerialName("rows_written") val rowsWritten: Long,
@SerialName("storage_bytes") val storageBytes: Long,
@SerialName("bytes_synced") val bytesSynced: Long,
)

@Serializable
Expand All @@ -111,7 +114,7 @@ data class InstanceUsage(
data class Instances<T>(
@SerialName("uuid") val uuid: String,
@SerialName("instances") val instances: List<T>,
@SerialName("total") val total: Usage,
@SerialName("usage") val usage: InstanceUsage,
)

@Serializable
Expand All @@ -125,7 +128,8 @@ data class Instance(

@Serializable
data class DatabaseUsageResponse(
@SerialName("database") val database: Instances<InstanceUsage>,
// @SerialName("database") val database: Instances<InstanceUsage>,
@SerialName("total") val total: Usage,
)

@Serializable
Expand All @@ -145,7 +149,7 @@ data class InstanceResponse(

@Serializable
data class StatsResponse(
@SerialName("top_queries") val topQueries: List<QueryStatistics>,
@SerialName("top_queries") val topQueries: List<QueryStatistics>? = null,
)

@Serializable
Expand Down
3 changes: 1 addition & 2 deletions src/main/kotlin/model/Organization.kt
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,6 @@ data class OrganizationDatabaseUsage(
data class DatabaseUsage(
@SerialName("uuid") val uuid: String,
@SerialName("instances") val instances: List<InstanceUsage>,
@SerialName("total") val total: Usage,
)

@Serializable
Expand All @@ -109,9 +108,9 @@ data class OrganizationUsage(
@SerialName("rows_written") val rowsWritten: Long,
@SerialName("databases") val databases: Int,
@SerialName("locations") val locations: Int,
@SerialName("storage") val storage: Long,
@SerialName("groups") val groups: Int,
@SerialName("bytes_synced") val bytesSynced: Long,
@SerialName("storage_bytes") val storage: Long,
)

@Serializable
Expand Down
8 changes: 7 additions & 1 deletion src/test/kotlin/resource/DatabasesTest.kt
Original file line number Diff line number Diff line change
Expand Up @@ -230,7 +230,13 @@ class DatabasesTest {
@Test
fun `can update database configuration`() {
runBlocking {
val configurationUpdate = UpdateConfigurationRequest(sizeLimit = "20M", allowAttach = true)
val configurationUpdate =
UpdateConfigurationRequest(
blockReads = true,
blockWrites = false,
sizeLimit = "20M",
allowAttach = true,
)
val configuration = client(mockEngine()).databases.updateConfiguration("test", "test-database", configurationUpdate)
assertIs<ConfigurationResponse>(configuration)
}
Expand Down
22 changes: 1 addition & 21 deletions src/test/resources/fixtures/database/list.json
Original file line number Diff line number Diff line change
Expand Up @@ -59,26 +59,6 @@
"sleeping": false,
"archived": false,
"schema": null
},
{
"Name": "some-org",
"DbId": "7984ca66-28b0-4244-8ba9-392e5c835fc6",
"Hostname": "some-org-a2xchip.turso.io",
"is_schema": false,
"block_reads": false,
"block_writes": false,
"allow_attach": false,
"regions": [
"otp"
],
"primaryRegion": "otp",
"type": "logical",
"hostname": "some-org-a2xchip.turso.io",
"version": "0.24.29",
"group": "default",
"sleeping": false,
"archived": false,
"schema": "3ffbf4dd-958d-4c87-b89d-3bf1499c7a94"
}
]
}
}
29 changes: 1 addition & 28 deletions src/test/resources/fixtures/database/usage.json
Original file line number Diff line number Diff line change
@@ -1,28 +1 @@
{
"database": {
"uuid": "0eb771dd-6906-11ee-8553-eaa7715aeaf2",
"instances": [
{
"uuid": "cd831986-94e5-11ee-a6fe-7a52e1f7759a",
"usage": {
"rows_read": 0,
"rows_written": 0,
"storage_bytes": 4096
}
},
{
"uuid": "0be90471-6906-11ee-8553-eaa7715aeaf2",
"usage": {
"rows_read": 0,
"rows_written": 0,
"storage_bytes": 4096
}
}
],
"total": {
"rows_read": 0,
"rows_written": 0,
"storage_bytes": 8192
}
}
}
{"database":{"uuid":"4f0d8f65-e2e8-4ce8-8af5-6da211188b35","instances":[{"uuid":"9f182703-bfd7-11ee-897f-822b15a0bd8c","usage":{"rows_read":0,"rows_written":0,"storage_bytes":4096,"bytes_synced":0}}],"usage":{"rows_read":0,"rows_written":0,"storage_bytes":4096,"bytes_synced":0}},"instances":{"9f182703-bfd7-11ee-897f-822b15a0bd8c":{"rows_read":0,"rows_written":0,"storage_bytes":4096,"bytes_synced":0}},"total":{"rows_read":0,"rows_written":0,"storage_bytes":4096,"bytes_synced":0}}
Loading

0 comments on commit 01d3db1

Please sign in to comment.