Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

DOPE-246: added integration tests with test containers #62

Merged
merged 17 commits into from
Nov 27, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
17 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion .github/workflows/kotlin_ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,5 +32,7 @@ jobs:
run: ./gradlew build
- name: Run ktlint
run: ./gradlew ktlintCheck
- name: Run tests
- name: Run unit tests
run: ./gradlew test
- name: Run integration tests
run: ./gradlew integrationTest
martinagallati-ergon marked this conversation as resolved.
Show resolved Hide resolved
29 changes: 28 additions & 1 deletion core/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ plugins {
kotlin("jvm") version "1.9.22"
id("org.jlleitschuh.gradle.ktlint") version "11.5.1"
`maven-publish`
idea
martinagallati-ergon marked this conversation as resolved.
Show resolved Hide resolved
}

group = "com.github.ergon"
Expand Down Expand Up @@ -33,7 +34,10 @@ repositories {

dependencies {
testImplementation(kotlin("test"))
testImplementation("org.testcontainers:testcontainers:1.19.0")
testImplementation("org.testcontainers:couchbase:1.20.3")
implementation("com.couchbase.client:kotlin-client:1.4.0")
implementation("org.slf4j:slf4j-api:2.0.9")
pgruntz marked this conversation as resolved.
Show resolved Hide resolved
implementation("org.slf4j:slf4j-simple:2.0.9")
implementation(kotlin("reflect"))
}

Expand All @@ -55,3 +59,26 @@ kotlin {
languageVersion.set(JavaLanguageVersion.of(17))
}
}

sourceSets {
create("integrationTest") {
kotlin {
srcDir("src/integrationTest/kotlin")
}
compileClasspath += sourceSets["main"].compileClasspath + sourceSets["test"].compileClasspath
runtimeClasspath += sourceSets["main"].runtimeClasspath + sourceSets["test"].runtimeClasspath
}
}

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

idea.module {
testSources.from(sourceSets["integrationTest"].kotlin.srcDirs)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
package ch.ergon.dope.clauses

import ch.ergon.dope.QueryBuilder
import ch.ergon.dope.integrationTest.BaseIntegrationTest
import ch.ergon.dope.integrationTest.TestCouchbaseDatabase.idField
import ch.ergon.dope.integrationTest.TestCouchbaseDatabase.resetDatabase
import ch.ergon.dope.integrationTest.TestCouchbaseDatabase.testBucket
import ch.ergon.dope.integrationTest.toMapValues
import ch.ergon.dope.integrationTest.tryUntil
import ch.ergon.dope.resolvable.expression.unaliased.type.arithmetic.add
import ch.ergon.dope.resolvable.expression.unaliased.type.relational.isEqualTo
import ch.ergon.dope.resolvable.fromable.useKeys
import kotlin.test.AfterTest
import kotlin.test.Test
import kotlin.test.assertEquals

class DeleteIntegrationTest : BaseIntegrationTest() {
@AfterTest
fun reset() {
resetDatabase()
martinagallati-ergon marked this conversation as resolved.
Show resolved Hide resolved
}

@Test
fun `delete single document and return id field`() {
val dopeQuery = QueryBuilder()
.deleteFrom(
testBucket.useKeys("employee:1"),
)
.returning(
idField,
).build()

tryUntil {
martinagallati-ergon marked this conversation as resolved.
Show resolved Hide resolved
val queryResult = queryWithoutParameters(dopeQuery)
martinagallati-ergon marked this conversation as resolved.
Show resolved Hide resolved
val result = queryResult.toMapValues()

assertEquals(1, result["id"])
}
}

@Test
fun `delete every document in bucket`() {
val deleteEverythingDopeQuery = QueryBuilder()
.deleteFrom(
testBucket,
)
.where(
1.add(1).isEqualTo(2),
martinagallati-ergon marked this conversation as resolved.
Show resolved Hide resolved
)
.returning(
idField,
).build()

val selectEverythingDopeQuery = QueryBuilder()
.selectFrom(
testBucket,
).build()

tryUntil {
val selectBeforeDeleteQueryResult = queryWithoutParameters(selectEverythingDopeQuery)
martinagallati-ergon marked this conversation as resolved.
Show resolved Hide resolved
val deleteQueryResult = queryWithoutParameters(deleteEverythingDopeQuery)
val selectAfterDeleteQueryResult = queryWithoutParameters(selectEverythingDopeQuery)

assertEquals(15, selectBeforeDeleteQueryResult.rows.size)
martinagallati-ergon marked this conversation as resolved.
Show resolved Hide resolved
assertEquals(15, deleteQueryResult.rows.size)
assertEquals(0, selectAfterDeleteQueryResult.rows.size)
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
package ch.ergon.dope.clauses

import ch.ergon.dope.QueryBuilder
import ch.ergon.dope.integrationTest.BaseIntegrationTest
import ch.ergon.dope.integrationTest.TestCouchbaseDatabase.testBucket
import ch.ergon.dope.integrationTest.toMapValues
import ch.ergon.dope.integrationTest.tryUntil
import ch.ergon.dope.resolvable.clause.model.OrderByType.ASC
import ch.ergon.dope.resolvable.clause.model.OrderByType.DESC
import ch.ergon.dope.resolvable.clause.model.joinHint.HashOrNestedLoopHint.NESTED_LOOP
import ch.ergon.dope.resolvable.clause.model.joinHint.indexHint
import ch.ergon.dope.resolvable.expression.alias
import ch.ergon.dope.resolvable.expression.unaliased.type.Field
import ch.ergon.dope.resolvable.expression.unaliased.type.meta.meta
import ch.ergon.dope.resolvable.expression.unaliased.type.relational.isEqualTo
import ch.ergon.dope.validtype.StringType
import kotlin.test.Test
import kotlin.test.assertEquals

class JoinIntegrationTest : BaseIntegrationTest() {
@Test
fun `join all orders on employee id`() {
val employeeAlias = testBucket.alias("e")
martinagallati-ergon marked this conversation as resolved.
Show resolved Hide resolved
val orderAlias = testBucket.alias("o")
martinagallati-ergon marked this conversation as resolved.
Show resolved Hide resolved
val employeeNameField = Field<StringType>("name", employeeAlias.alias)
val orderNumberField = Field<StringType>("orderNumber", orderAlias.alias)
val orderEmployeeIdField = Field<StringType>("employee", orderAlias.alias)
val dopeQuery = QueryBuilder()
.select(
employeeNameField,
orderNumberField,
)
.from(
employeeAlias,
)
.join(
orderAlias,
orderEmployeeIdField.isEqualTo(meta(employeeAlias).id),
).orderBy(
orderNumberField,
ASC,
).build()

tryUntil {
martinagallati-ergon marked this conversation as resolved.
Show resolved Hide resolved
val queryResult = queryWithoutParameters(dopeQuery)

martinagallati-ergon marked this conversation as resolved.
Show resolved Hide resolved
assertEquals(5, queryResult.rows.size)
assertEquals(mapOf("name" to "employee1", "orderNumber" to "order1"), queryResult.toMapValues(rowNumber = 0))
assertEquals(mapOf("name" to "employee2", "orderNumber" to "order2"), queryResult.toMapValues(rowNumber = 1))
assertEquals(mapOf("name" to "employee3", "orderNumber" to "order3"), queryResult.toMapValues(rowNumber = 2))
assertEquals(mapOf("name" to "employee4", "orderNumber" to "order4"), queryResult.toMapValues(rowNumber = 3))
assertEquals(mapOf("name" to "employee5", "orderNumber" to "order5"), queryResult.toMapValues(rowNumber = 4))
}
}

@Test
fun `join documents with multiple joins`() {
val employeeAlias = testBucket.alias("e")
martinagallati-ergon marked this conversation as resolved.
Show resolved Hide resolved
val clientAlias = testBucket.alias("c")
val orderAlias = testBucket.alias("o")
val employeeNameField = Field<StringType>("name", employeeAlias.alias)
val clientNameField = Field<StringType>("name", clientAlias.alias)
val orderNumberField = Field<StringType>("orderNumber", orderAlias.alias)
val orderEmployeeIdField = Field<StringType>("employee", orderAlias.alias)
val orderClientIdField = Field<StringType>("client", orderAlias.alias)
val dopeQuery = QueryBuilder()
.select(
orderNumberField,
employeeNameField.alias("employeeName"),
clientNameField.alias("clientName"),
)
.from(
orderAlias,
)
.join(
employeeAlias,
orderEmployeeIdField.isEqualTo(meta(employeeAlias).id),
hashOrNestedLoopHint = NESTED_LOOP,
)
.innerJoin(
clientAlias,
orderClientIdField.isEqualTo(meta(clientAlias).id),
keysOrIndexHint = indexHint(),
).orderBy(
orderNumberField,
DESC,
)
.build()

tryUntil {
martinagallati-ergon marked this conversation as resolved.
Show resolved Hide resolved
val queryResult = queryWithoutParameters(dopeQuery)

assertEquals(5, queryResult.rows.size)
assertEquals(
mapOf("employeeName" to "employee5", "orderNumber" to "order5", "clientName" to "client5"),
queryResult.toMapValues(rowNumber = 0),
)
assertEquals(
mapOf("employeeName" to "employee4", "orderNumber" to "order4", "clientName" to "client4"),
queryResult.toMapValues(rowNumber = 1),
)
assertEquals(
mapOf("employeeName" to "employee3", "orderNumber" to "order3", "clientName" to "client3"),
queryResult.toMapValues(rowNumber = 2),
)
assertEquals(
mapOf("employeeName" to "employee2", "orderNumber" to "order2", "clientName" to "client2"),
queryResult.toMapValues(rowNumber = 3),
)
assertEquals(
mapOf("employeeName" to "employee1", "orderNumber" to "order1", "clientName" to "client1"),
queryResult.toMapValues(rowNumber = 4),
)
}
}
}
Loading