-
Notifications
You must be signed in to change notification settings - Fork 12
feat: introduce e2e test infrastructure for sink #22
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
Merged
Changes from 8 commits
Commits
Show all changes
12 commits
Select commit
Hold shift + click to select a range
ab74a63
feat: introduce e2e test infrastructure for sink
fbiville 778c3db
feat: implement sink connector registration
fbiville 4c39d37
feat: support session injection for sink tests
fbiville 4d0c37c
feat: simplify extension by dynamically resolving the annotation fiel…
fbiville eb4dbee
fix: do not make neo4j external URI mandatory in source tests
fbiville 2f23235
test: align source and sink tests
fbiville 44aa93d
test: add coverage on map helper
fbiville 7e4ad95
test: add simple e2e test for sink
fbiville c1cc357
fix: review feedback
fbiville 4289848
fix: more review feedback
fbiville 24d60d6
build: downgrade to lowest support connect/kafka versions
fbiville 8430f63
fix: clarify intent of eagerly validated annotation members
fbiville File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
78 changes: 78 additions & 0 deletions
78
sink/src/test/kotlin/org/neo4j/connectors/kafka/sink/Neo4jSinkIT.kt
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,78 @@ | ||
| /* | ||
| * Copyright (c) "Neo4j" | ||
| * Neo4j Sweden AB [http://neo4j.com] | ||
| * | ||
| * 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 org.neo4j.connectors.kafka.sink | ||
|
|
||
| import io.confluent.connect.avro.AvroData | ||
| import kotlin.time.Duration.Companion.seconds | ||
| import kotlin.time.toJavaDuration | ||
| import org.apache.avro.generic.GenericData | ||
| import org.apache.avro.generic.GenericRecord | ||
| import org.apache.kafka.clients.producer.KafkaProducer | ||
| import org.apache.kafka.clients.producer.ProducerRecord | ||
| import org.apache.kafka.connect.data.Schema | ||
| import org.apache.kafka.connect.data.SchemaBuilder | ||
| import org.awaitility.Awaitility.await | ||
| import org.junit.jupiter.api.Test | ||
| import org.junit.jupiter.api.TestInfo | ||
| import org.neo4j.connectors.kafka.testing.sink.Neo4jSink | ||
| import org.neo4j.connectors.kafka.testing.sink.TopicProducer | ||
| import org.neo4j.driver.Session | ||
|
|
||
| class Neo4jSinkIT { | ||
|
|
||
| companion object { | ||
| const val TOPIC = "persons" | ||
| } | ||
|
|
||
| @Neo4jSink( | ||
| topics = [TOPIC], | ||
| queries = | ||
| [ | ||
| "MERGE (p:Person {name: event.name, surname: event.surname, executionId: event.executionId})"]) | ||
| @Test | ||
| fun `writes messages to Neo4j`( | ||
| @TopicProducer producer: KafkaProducer<String, GenericRecord>, | ||
| session: Session, | ||
| testInfo: TestInfo | ||
| ) { | ||
| val executionId = testInfo.displayName + System.currentTimeMillis() | ||
| val avroRecord = | ||
| GenericData.Record( | ||
| AvroData(20) | ||
| .fromConnectSchema( | ||
| SchemaBuilder.struct() | ||
| .field("name", Schema.STRING_SCHEMA) | ||
| .field("surname", Schema.STRING_SCHEMA) | ||
| .field("executionId", Schema.STRING_SCHEMA) | ||
| .build())) | ||
| avroRecord.put("name", "Ali") | ||
| avroRecord.put("surname", "İnce") | ||
fbiville marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| avroRecord.put("executionId", executionId) | ||
| val record = ProducerRecord<String, GenericRecord>(TOPIC, avroRecord) | ||
|
|
||
| producer.send(record) | ||
|
|
||
| await().atMost(30.seconds.toJavaDuration()).until { | ||
| session | ||
| .run( | ||
| "MATCH (p:Person {name: \$name, surname: \$surname, executionId: \$executionId}) RETURN count(p) = 1 AS result", | ||
| mapOf("name" to "Ali", "surname" to "İnce", "executionId" to executionId)) | ||
| .single()["result"] | ||
| .asBoolean() | ||
| } | ||
| } | ||
| } | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
40 changes: 40 additions & 0 deletions
40
testing/src/main/kotlin/org/neo4j/connectors/kafka/testing/AnnotationSupport.kt
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,40 @@ | ||
| /* | ||
| * Copyright (c) "Neo4j" | ||
| * Neo4j Sweden AB [http://neo4j.com] | ||
| * | ||
| * 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 org.neo4j.connectors.kafka.testing | ||
|
|
||
| import kotlin.jvm.optionals.getOrNull | ||
| import org.junit.jupiter.api.extension.ExtensionContext | ||
| import org.junit.platform.commons.support.AnnotationSupport | ||
|
|
||
| internal object AnnotationSupport { | ||
|
|
||
| inline fun <reified T : Annotation> findAnnotation(context: ExtensionContext?): T? { | ||
| var current = context | ||
| while (current != null) { | ||
| val annotation = | ||
| AnnotationSupport.findAnnotation( | ||
| current.requiredTestMethod, | ||
| T::class.java, | ||
| ) | ||
| if (annotation.isPresent) { | ||
| return annotation.get() | ||
| } | ||
| current = current.parent.getOrNull() | ||
| } | ||
| return null | ||
| } | ||
| } |
68 changes: 68 additions & 0 deletions
68
testing/src/main/kotlin/org/neo4j/connectors/kafka/testing/AnnotationValueResolver.kt
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,68 @@ | ||
| /* | ||
| * Copyright (c) "Neo4j" | ||
| * Neo4j Sweden AB [http://neo4j.com] | ||
| * | ||
| * 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 org.neo4j.connectors.kafka.testing | ||
|
|
||
| import org.neo4j.connectors.kafka.testing.WordSupport.camelCaseToUpperSnakeCase | ||
|
|
||
| internal const val DEFAULT_TO_ENV = "___UNSET___" | ||
|
|
||
| /** | ||
| * AnnotationValueResolver resolves an annotation attribute value in at most two steps. If the value | ||
| * has been explicitly initialized on the annotation T, it is returned. If the value holds a | ||
| * specific default value, the resolver will look for the corresponding environment variable and | ||
| * return the value. The environment variable name results from the camel case to upper snake case | ||
| * conversion operated on the attribute name. | ||
| */ | ||
| internal class AnnotationValueResolver<T : Annotation>( | ||
| private val name: String, | ||
| private val envAccessor: (String) -> String?, | ||
| ) { | ||
| private val fieldValueOf: (T) -> String = resolveFieldAccessor(name) | ||
|
|
||
| private val envVarName = camelCaseToUpperSnakeCase(name) | ||
|
|
||
| /** Determines whether the value is resolvable. */ | ||
| fun isValid(annotation: T): Boolean { | ||
| return fieldValueOf(annotation) != DEFAULT_TO_ENV || envAccessor(envVarName) != null | ||
| } | ||
|
|
||
| /** | ||
| * Resolves the value of the provided annotation's attribute. This assumes [isValid] has been | ||
| * called first and returned true. | ||
| */ | ||
| fun resolve(annotation: T): String { | ||
| val fieldValue = fieldValueOf(annotation) | ||
| if (fieldValue != DEFAULT_TO_ENV) { | ||
| return fieldValue | ||
| } | ||
| return envAccessor(envVarName)!! | ||
| } | ||
|
|
||
| fun errorMessage(): String { | ||
| return "Both annotation field $name and environment variable $envVarName are unset. Please specify one" | ||
| } | ||
|
|
||
| override fun toString(): String { | ||
| return "EnvBackedSetting(name='$name', envVarName='$envVarName')" | ||
| } | ||
|
|
||
| private fun resolveFieldAccessor(name: String): (T) -> String { | ||
| return { annotation -> | ||
| annotation::class.members.first { member -> member.name == name }.call(annotation) as String | ||
| } | ||
| } | ||
| } |
32 changes: 32 additions & 0 deletions
32
testing/src/main/kotlin/org/neo4j/connectors/kafka/testing/MapSupport.kt
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,32 @@ | ||
| /* | ||
| * Copyright (c) "Neo4j" | ||
| * Neo4j Sweden AB [http://neo4j.com] | ||
| * | ||
| * 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 org.neo4j.connectors.kafka.testing | ||
|
|
||
| import java.lang.IllegalStateException | ||
|
|
||
| internal object MapSupport { | ||
|
|
||
| @Suppress("UNCHECKED_CAST") | ||
| fun <K, Any> MutableMap<K, Any>.nestUnder(key: K, values: Map<K, Any>): MutableMap<K, Any> { | ||
| val map = this[key] | ||
| if (map !is Map<*, *>) { | ||
| throw IllegalStateException("entry at key $key is not a mutable map") | ||
| } | ||
| (map as MutableMap<K, Any>).putAll(values) | ||
| return this | ||
| } | ||
| } |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.