generated from SpineEventEngine/template
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Implement tests for interdependent fields
- Loading branch information
1 parent
12328d6
commit c04d6c7
Showing
5 changed files
with
358 additions
and
3 deletions.
There are no files selected for viewing
102 changes: 102 additions & 0 deletions
102
java-tests/validating/src/test/kotlin/io/spine/test/options/goes/GoesMutualITest.kt
This file contains 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,102 @@ | ||
/* | ||
* Copyright 2024, TeamDev. All rights reserved. | ||
* | ||
* 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 | ||
* | ||
* https://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Redistribution and use in source and/or binary forms, with or without | ||
* modification, must retain the above copyright notice and the following | ||
* disclaimer. | ||
* | ||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
*/ | ||
|
||
package io.spine.test.options.goes | ||
|
||
import com.google.protobuf.Message | ||
import com.google.protobuf.util.Timestamps | ||
import io.spine.test.tools.validate.EnumForGoes | ||
import io.spine.test.tools.validate.MutualMessageCompanion | ||
import io.spine.validate.ValidationException | ||
import org.junit.jupiter.api.DisplayName | ||
import org.junit.jupiter.api.Test | ||
import org.junit.jupiter.api.assertDoesNotThrow | ||
import org.junit.jupiter.api.assertThrows | ||
import org.junit.jupiter.params.ParameterizedTest | ||
import org.junit.jupiter.params.provider.MethodSource | ||
|
||
@DisplayName("`(goes)` constraint should") | ||
internal class GoesMutualITest { | ||
|
||
@MethodSource("io.spine.test.options.goes.TestDataMutual#interdependentFields") | ||
@ParameterizedTest(name = "throw if one of mutually dependent `{1}` and `{3}` fields is not set") | ||
fun throwIfOneOfMutuallyDependentFieldsNotSet( | ||
message: Class<out Message>, | ||
fieldName1: String, | ||
fieldValue1: Any, | ||
fieldName2: String, | ||
fieldValue2: Any | ||
) { | ||
val descriptor = message.protoDescriptor() | ||
|
||
val field1 = descriptor.findFieldByName(fieldName1)!! | ||
val protoValue1 = protoValue(field1, fieldValue1) | ||
assertThrows<ValidationException> { | ||
message.newBuilder() | ||
.setField(field1, protoValue1) | ||
.build() | ||
} | ||
|
||
val field2 = descriptor.findFieldByName(fieldName2)!! | ||
val protoValue2 = protoValue(field2, fieldValue2) | ||
assertThrows<ValidationException> { | ||
message.newBuilder() | ||
.setField(field2, protoValue2) | ||
.build() | ||
} | ||
} | ||
|
||
@MethodSource("io.spine.test.options.goes.TestDataMutual#interdependentFields") | ||
@ParameterizedTest(name = "not throw if both mutually dependent `{1}` and `{3}` fields are set") | ||
fun notThrowIfBothMutuallyDependentFieldsSet( | ||
message: Class<out Message>, | ||
fieldName1: String, | ||
fieldValue1: Any, | ||
fieldName2: String, | ||
fieldValue2: Any | ||
) { | ||
val descriptor = message.protoDescriptor() | ||
val field1 = descriptor.findFieldByName(fieldName1)!! | ||
val protoValue1 = protoValue(field1, fieldValue1) | ||
val field2 = descriptor.findFieldByName(fieldName2)!! | ||
val protoValue2 = protoValue(field2, fieldValue2) | ||
assertDoesNotThrow { | ||
message.newBuilder() | ||
.setField(field1, protoValue1) | ||
.setField(field2, protoValue2) | ||
.build() | ||
} | ||
} | ||
|
||
@MethodSource("io.spine.test.options.goes.TestDataMutual#messagesWithInterdependentFields") | ||
@ParameterizedTest(name = "not throw if both mutually dependent fields are not set") | ||
fun notThrowIfBothMutuallyDependentFieldsNotSet(message: Class<out Message>) { | ||
assertDoesNotThrow { | ||
message.newBuilder() | ||
.build() | ||
} | ||
} | ||
} |
This file contains 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
118 changes: 118 additions & 0 deletions
118
java-tests/validating/src/test/kotlin/io/spine/test/options/goes/TestDataMutual.kt
This file contains 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,118 @@ | ||
/* | ||
* Copyright 2024, TeamDev. All rights reserved. | ||
* | ||
* 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 | ||
* | ||
* https://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Redistribution and use in source and/or binary forms, with or without | ||
* modification, must retain the above copyright notice and the following | ||
* disclaimer. | ||
* | ||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
*/ | ||
|
||
package io.spine.test.options.goes | ||
|
||
import com.google.protobuf.ByteString | ||
import com.google.protobuf.Message | ||
import com.google.protobuf.util.Timestamps | ||
import io.spine.test.tools.validate.EnumForGoes | ||
import io.spine.test.tools.validate.MutualBytesCompanion | ||
import io.spine.test.tools.validate.MutualEnumCompanion | ||
import io.spine.test.tools.validate.MutualMapCompanion | ||
import io.spine.test.tools.validate.MutualMessageCompanion | ||
import io.spine.test.tools.validate.MutualRepeatedCompanion | ||
import io.spine.test.tools.validate.MutualStringCompanion | ||
import kotlin.reflect.KClass | ||
import org.junit.jupiter.api.Named.named | ||
import org.junit.jupiter.params.provider.Arguments.arguments | ||
|
||
/** | ||
* Provides data for parameterized [GoesMutualITest]. | ||
*/ | ||
@Suppress("unused") | ||
internal object TestDataMutual { | ||
|
||
private val fieldValues = listOf( | ||
MutualMessageCompanion::class to Timestamps.now(), | ||
MutualEnumCompanion::class to EnumForGoes.EFG_ITEM1.valueDescriptor, | ||
MutualStringCompanion::class to "some companion text", | ||
MutualBytesCompanion::class to ByteString.copyFromUtf8("some companion data"), | ||
MutualRepeatedCompanion::class to listOf(1L, 2L, 3L), | ||
MutualMapCompanion::class to mapOf("key" to 32), | ||
) | ||
|
||
/** | ||
* Test data for [GoesITest.notThrowIfOnlyCompanionFieldSet]. | ||
*/ | ||
@JvmStatic | ||
fun messagesWithInterdependentFields() = fieldValues.map { it.first.java } | ||
|
||
/** | ||
* Test data for [GoesITest.notThrowIfBothTargetAndCompanionFieldsSet]. | ||
*/ | ||
@JvmStatic | ||
fun interdependentFields() = fieldValues.flatMap { (messageClass, companionValue) -> | ||
val companionType = messageClass.typeUnderTest() | ||
fieldValues.map { (fieldClass, fieldValue) -> | ||
val companionName = fieldClass.companionName() | ||
val fieldType = fieldClass.typeUnderTest() | ||
val fieldName = fieldClass.fieldName() | ||
arguments( | ||
messageClass.java, | ||
named(companionType, companionName), | ||
companionValue, | ||
named(fieldType, fieldName), | ||
fieldValue | ||
) | ||
} | ||
} | ||
} | ||
|
||
/** | ||
* Extracts a simple name of the field type, which is under test from this [KClass]. | ||
* | ||
* This extension relies on naming consistency within `goes_mutual.proto` message stubs. | ||
* So, the message name shows a data type of the companion field. | ||
* | ||
* For example, `MutualStringCompanion` becomes just `string`. | ||
*/ | ||
private fun KClass<out Message>.typeUnderTest() = simpleName!! | ||
.substringAfter("Mutual") | ||
.substringBefore("Companion") | ||
.lowercase() | ||
|
||
/** | ||
* Extracts a simple field name of the field, which declares a dependency | ||
* on another field (companion). | ||
* | ||
* This extension relies on naming consistency within `goes_mutual.proto` message stubs. | ||
* So, each target field (with the option) is named as following: `{data_type}_field`. | ||
* | ||
* For example, `MutualStringCompanion` becomes `string_field`. | ||
*/ | ||
private fun KClass<out Message>.fieldName() = "${typeUnderTest()}_field" | ||
|
||
/** | ||
* Extracts a simple companion field name of the field, which declares a dependency | ||
* on another field. | ||
* | ||
* This extension relies on naming consistency within `goes_mutual.proto` message stubs. | ||
* So, each target field (with the option) is named as following: `{data_type}_companion`. | ||
* | ||
* For example, `MutualStringCompanion` becomes `string_companion`. | ||
*/ | ||
private fun KClass<out Message>.companionName() = "${typeUnderTest()}_companion" |
134 changes: 134 additions & 0 deletions
134
java-tests/validating/src/testFixtures/proto/spine/test/tools/validate/goes_mutual.proto
This file contains 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,134 @@ | ||
/* | ||
* Copyright 2024, TeamDev. All rights reserved. | ||
* | ||
* 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 | ||
* | ||
* https://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Redistribution and use in source and/or binary forms, with or without | ||
* modification, must retain the above copyright notice and the following | ||
* disclaimer. | ||
* | ||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
*/ | ||
syntax = "proto3"; | ||
|
||
package spine.test.tools.validate; | ||
|
||
import "spine/options.proto"; | ||
|
||
option (type_url_prefix) = "type.spine.io"; | ||
option java_package = "io.spine.test.tools.validate"; | ||
option java_outer_classname = "GoesMutualProto"; | ||
option java_multiple_files = true; | ||
|
||
import "spine/test/tools/validate/goes_values.proto"; | ||
import "google/protobuf/timestamp.proto"; | ||
|
||
message MutualMessageCompanion { | ||
google.protobuf.Timestamp message_companion = 1 [(goes).with = "message_field"]; | ||
google.protobuf.Timestamp enum_companion = 2 [(goes).with = "enum_field"]; | ||
google.protobuf.Timestamp string_companion = 3 [(goes).with = "string_field"]; | ||
google.protobuf.Timestamp bytes_companion = 4 [(goes).with = "bytes_field"]; | ||
google.protobuf.Timestamp repeated_companion = 5 [(goes).with = "repeated_field"]; | ||
google.protobuf.Timestamp map_companion = 6 [(goes).with = "map_field"]; | ||
|
||
google.protobuf.Timestamp message_field = 7 [(goes).with = "message_companion"]; | ||
EnumForGoes enum_field = 8 [(goes).with = "enum_companion"]; | ||
string string_field = 9 [(goes).with = "string_companion"]; | ||
bytes bytes_field = 10 [(goes).with = "bytes_companion"]; | ||
repeated int64 repeated_field = 11 [(goes).with = "repeated_companion"]; | ||
map<string, int32> map_field = 12 [(goes).with = "map_companion"]; | ||
} | ||
|
||
message MutualEnumCompanion { | ||
EnumForGoes message_companion = 1 [(goes).with = "message_field"]; | ||
EnumForGoes enum_companion = 2 [(goes).with = "enum_field"]; | ||
EnumForGoes string_companion = 3 [(goes).with = "string_field"]; | ||
EnumForGoes bytes_companion = 4 [(goes).with = "bytes_field"]; | ||
EnumForGoes repeated_companion = 5 [(goes).with = "repeated_field"]; | ||
EnumForGoes map_companion = 6 [(goes).with = "map_field"]; | ||
|
||
google.protobuf.Timestamp message_field = 7 [(goes).with = "message_companion"]; | ||
EnumForGoes enum_field = 8 [(goes).with = "enum_companion"]; | ||
string string_field = 9 [(goes).with = "string_companion"]; | ||
bytes bytes_field = 10 [(goes).with = "bytes_companion"]; | ||
repeated int64 repeated_field = 11 [(goes).with = "repeated_companion"]; | ||
map<string, int32> map_field = 12 [(goes).with = "map_companion"]; | ||
} | ||
|
||
message MutualStringCompanion { | ||
string message_companion = 1 [(goes).with = "message_field"]; | ||
string enum_companion = 2 [(goes).with = "enum_field"]; | ||
string string_companion = 3 [(goes).with = "string_field"]; | ||
string bytes_companion = 4 [(goes).with = "bytes_field"]; | ||
string repeated_companion = 5 [(goes).with = "repeated_field"]; | ||
string map_companion = 6 [(goes).with = "map_field"]; | ||
|
||
google.protobuf.Timestamp message_field = 7 [(goes).with = "message_companion"]; | ||
EnumForGoes enum_field = 8 [(goes).with = "enum_companion"]; | ||
string string_field = 9 [(goes).with = "string_companion"]; | ||
bytes bytes_field = 10 [(goes).with = "bytes_companion"]; | ||
repeated int64 repeated_field = 11 [(goes).with = "repeated_companion"]; | ||
map<string, int32> map_field = 12 [(goes).with = "map_companion"]; | ||
} | ||
|
||
message MutualBytesCompanion { | ||
bytes message_companion = 1 [(goes).with = "message_field"]; | ||
bytes enum_companion = 2 [(goes).with = "enum_field"]; | ||
bytes string_companion = 3 [(goes).with = "string_field"]; | ||
bytes bytes_companion = 4 [(goes).with = "bytes_field"]; | ||
bytes repeated_companion = 5 [(goes).with = "repeated_field"]; | ||
bytes map_companion = 6 [(goes).with = "map_field"]; | ||
|
||
google.protobuf.Timestamp message_field = 7 [(goes).with = "message_companion"]; | ||
EnumForGoes enum_field = 8 [(goes).with = "enum_companion"]; | ||
string string_field = 9 [(goes).with = "string_companion"]; | ||
bytes bytes_field = 10 [(goes).with = "bytes_companion"]; | ||
repeated int64 repeated_field = 11 [(goes).with = "repeated_companion"]; | ||
map<string, int32> map_field = 12 [(goes).with = "map_companion"]; | ||
} | ||
|
||
message MutualRepeatedCompanion { | ||
repeated int64 message_companion = 1 [(goes).with = "message_field"]; | ||
repeated int64 enum_companion = 2 [(goes).with = "enum_field"]; | ||
repeated int64 string_companion = 3 [(goes).with = "string_field"]; | ||
repeated int64 bytes_companion = 4 [(goes).with = "bytes_field"]; | ||
repeated int64 repeated_companion = 5 [(goes).with = "repeated_field"]; | ||
repeated int64 map_companion = 6 [(goes).with = "map_field"]; | ||
|
||
google.protobuf.Timestamp message_field = 7 [(goes).with = "message_companion"]; | ||
EnumForGoes enum_field = 8 [(goes).with = "enum_companion"]; | ||
string string_field = 9 [(goes).with = "string_companion"]; | ||
bytes bytes_field = 10 [(goes).with = "bytes_companion"]; | ||
repeated int64 repeated_field = 11 [(goes).with = "repeated_companion"]; | ||
map<string, int32> map_field = 12 [(goes).with = "map_companion"]; | ||
} | ||
|
||
message MutualMapCompanion { | ||
map<string, int32> message_companion = 1 [(goes).with = "message_field"]; | ||
map<string, int32> enum_companion = 2 [(goes).with = "enum_field"]; | ||
map<string, int32> string_companion = 3 [(goes).with = "string_field"]; | ||
map<string, int32> bytes_companion = 4 [(goes).with = "bytes_field"]; | ||
map<string, int32> repeated_companion = 5 [(goes).with = "repeated_field"]; | ||
map<string, int32> map_companion = 6 [(goes).with = "map_field"]; | ||
|
||
google.protobuf.Timestamp message_field = 7 [(goes).with = "message_companion"]; | ||
EnumForGoes enum_field = 8 [(goes).with = "enum_companion"]; | ||
string string_field = 9 [(goes).with = "string_companion"]; | ||
bytes bytes_field = 10 [(goes).with = "bytes_companion"]; | ||
repeated int64 repeated_field = 11 [(goes).with = "repeated_companion"]; | ||
map<string, int32> map_field = 12 [(goes).with = "map_companion"]; | ||
} |
This file contains 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