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

[Th2 5143] problem when codec publishes event for book A with attached messages for book B #7

Merged
merged 8 commits into from
Dec 29, 2023
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
build/
.gradle/
.idea/
.idea/
bin/
2 changes: 1 addition & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
FROM gradle:7.5-jdk11 AS build
FROM gradle:7.6-jdk11 AS build
ARG release_version
COPY ./ .
RUN gradle --no-daemon clean build dockerPrepare -Prelease_version=${release_version}
Expand Down
6 changes: 5 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# th2-codec-json-dictionaryless v0.3.0
# th2-codec-json-dictionaryless v0.4.0
This microservice can encode and decode JSON messages.

## Configuration
Expand Down Expand Up @@ -81,6 +81,10 @@ spec:

##Changelog

### 0.4.0
+ Updated common: `5.7.2-dev`
+ Updated codec: `5.4.1-dev`

### 0.3.0
+ TH2 transport protocol support.

Expand Down
103 changes: 15 additions & 88 deletions build.gradle
Original file line number Diff line number Diff line change
@@ -1,101 +1,28 @@
plugins {
id 'com.palantir.docker' version '0.25.0'
id 'org.jetbrains.kotlin.jvm' version "${kotlin_version}"
id 'application'
id "org.owasp.dependencycheck" version "7.2.0"
id 'org.jetbrains.kotlin.kapt' version "${kotlin_version}"
}

dependencyCheck {
format='HTML'
failBuildOnCVSS=5
}

group = 'com.exactpro.th2'
version = release_version

sourceCompatibility = 11
targetCompatibility = 11

repositories {
mavenCentral()

maven {
name 'Sonatype_snapshots'
url 'https://s01.oss.sonatype.org/content/repositories/snapshots/'
}

maven {
name 'Sonatype_releases'
url 'https://s01.oss.sonatype.org/content/repositories/releases/'
buildscript {
repositories {
gradlePluginPortal()
maven {
url = "https://s01.oss.sonatype.org/content/repositories/snapshots/"
}
}

mavenLocal()

configurations.configureEach {
resolutionStrategy.cacheChangingModulesFor 0, 'seconds'
resolutionStrategy.cacheDynamicVersionsFor 0, 'seconds'
dependencies {
classpath "com.exactpro.th2:th2-gradle-plugin:0.0.1-dev-5915968839-41381e5-SNAPSHOT"
}
}

jar {
manifest {
attributes(
'Created-By': "${System.getProperty('java.version')} (${System.getProperty('java.vendor')})",
'Specification-Title': '',
'Specification-Vendor': 'Exactpro Systems LLC',
'Implementation-Title': project.archivesBaseName,
'Implementation-Vendor': 'Exactpro Systems LLC',
'Implementation-Vendor-Id': 'com.exactpro',
'Implementation-Version': project.version
)
}
}
apply plugin: "com.exactpro.th2.common-conventions"
apply plugin: "com.exactpro.th2.docker-conventions"

apply plugin: 'kotlin-kapt'

dependencies {
api platform("com.exactpro.th2:bom:4.2.0")
api platform("com.exactpro.th2:bom:4.5.0")

implementation "com.exactpro.th2:common:5.3.0-json-raw-body-5242142633-7ac1672-SNAPSHOT" //FIXME: migrate to release
implementation "com.exactpro.th2:codec:5.3.0-new-proto-5241354905-69d03b5-SNAPSHOT" //FIXME: migrate to release
implementation "com.exactpro.th2:common:5.7.2-dev"
implementation "com.exactpro.th2:codec:5.4.1-TH2-5143-+"

Nikita-Smirnov-Exactpro marked this conversation as resolved.
Show resolved Hide resolved
implementation "com.fasterxml.jackson.core:jackson-databind"

testImplementation "org.jetbrains.kotlin:kotlin-test-junit5:$kotlin_version"

compileOnly "com.google.auto.service:auto-service:1.1.0"
kapt "com.google.auto.service:auto-service:1.1.0"
}

application {
mainClassName 'com.exactpro.th2.codec.MainKt'
}

applicationName = 'service'

distTar {
archiveName "${applicationName}.tar"
}

dockerPrepare {
dependsOn distTar
}

docker {
copySpec.from(tarTree("$buildDir/distributions/${applicationName}.tar"))
}

compileKotlin {
kotlinOptions {
jvmTarget = "11"
}
}

compileTestKotlin {
kotlinOptions {
jvmTarget = "11"
}
}

test {
useJUnitPlatform()
}
4 changes: 2 additions & 2 deletions gradle.properties
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
kotlin.code.style=official
kotlin_version=1.6.21
release_version=0.3.0
release_version=0.4.0
app_main_class=com.exactpro.th2.codec.MainKt
2 changes: 1 addition & 1 deletion gradle/wrapper/gradle-wrapper.properties
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-7.5-all.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-7.6-all.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
Empty file modified gradlew
100644 → 100755
Empty file.
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2022-2022 Exactpro (Exactpro Systems Limited)
* Copyright 2022-2023 Exactpro (Exactpro Systems Limited)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand All @@ -22,7 +22,7 @@ import com.google.auto.service.AutoService

@AutoService(IPipelineCodecFactory::class)
class JsonCodecFactory: IPipelineCodecFactory {
override val protocol: String = PROTOCOL
override val protocols: Set<String> get() = PROTOCOLS

override val settingsClass: Class<out IPipelineCodecSettings>
get() = JsonPipelineCodecSettings::class.java
Expand All @@ -33,5 +33,6 @@ class JsonCodecFactory: IPipelineCodecFactory {

companion object {
const val PROTOCOL = "json"
private val PROTOCOLS = setOf(PROTOCOL)
}
}
13 changes: 7 additions & 6 deletions src/main/kotlin/com/exactpro/th2/codec/json/JsonPipelineCodec.kt
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
package com.exactpro.th2.codec.json

import com.exactpro.th2.codec.api.IPipelineCodec
import com.exactpro.th2.codec.api.IReportingContext
import com.exactpro.th2.codec.json.JsonCodecFactory.Companion.PROTOCOL
import com.exactpro.th2.common.grpc.Direction as ProtoDirection
import com.exactpro.th2.common.grpc.EventID as ProtoEventID
Expand Down Expand Up @@ -47,7 +48,7 @@ class JsonPipelineCodec(settings: JsonPipelineCodecSettings): IPipelineCodec {
}
}

override fun decode(messageGroup: ProtoMessageGroup): ProtoMessageGroup {
override fun decode(messageGroup: ProtoMessageGroup, context: IReportingContext): ProtoMessageGroup {
val builder = ProtoMessageGroup.newBuilder()

for (message in messageGroup.messagesList) {
Expand Down Expand Up @@ -85,7 +86,7 @@ class JsonPipelineCodec(settings: JsonPipelineCodecSettings): IPipelineCodec {
return builder.build()
}

override fun encode(messageGroup: ProtoMessageGroup): ProtoMessageGroup {
override fun encode(messageGroup: ProtoMessageGroup, context: IReportingContext): ProtoMessageGroup {
val builder = ProtoMessageGroup.newBuilder()

for (message in messageGroup.messagesList) {
Expand Down Expand Up @@ -116,9 +117,9 @@ class JsonPipelineCodec(settings: JsonPipelineCodecSettings): IPipelineCodec {
return builder.build()
}

override fun decode(messageGroup: MessageGroup): MessageGroup = MessageGroup(
override fun decode(messageGroup: MessageGroup, context: IReportingContext): MessageGroup = MessageGroup(
messageGroup.messages.map {
if (it !is RawMessage || it.protocol.isNotBlank() && it.protocol != PROTOCOL) {
if (it !is RawMessage || (it.protocol.isNotBlank() && it.protocol != PROTOCOL)) {
it
} else {
val messageType = when (it.id.direction) {
Expand All @@ -134,9 +135,9 @@ class JsonPipelineCodec(settings: JsonPipelineCodecSettings): IPipelineCodec {
}
)

override fun encode(messageGroup: MessageGroup): MessageGroup = MessageGroup(
override fun encode(messageGroup: MessageGroup, context: IReportingContext): MessageGroup = MessageGroup(
messageGroup.messages.map {
if (it !is ParsedMessage && it.protocol.isNotBlank() && it.protocol != PROTOCOL) {
if (it !is ParsedMessage || (it.protocol.isNotBlank() && it.protocol != PROTOCOL)) {
it
} else {
require(it.id.direction in VALID_DIRECTIONS) { "Unsupported message direction: ${it.id.direction}" }
Expand Down
69 changes: 61 additions & 8 deletions src/test/kotlin/com/exactpro/th2/codec/json/DecodeTest.kt
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

package com.exactpro.th2.codec.json

import com.exactpro.th2.codec.api.impl.ReportingContext
import com.exactpro.th2.codec.json.JsonCodecFactory.Companion.PROTOCOL
import com.exactpro.th2.common.grpc.Direction as ProtoDirection
import com.exactpro.th2.common.grpc.MessageGroup as ProtoMessageGroup
Expand All @@ -31,10 +32,11 @@ import org.junit.jupiter.api.Test
import java.time.Instant
import kotlin.test.assertEquals
import kotlin.test.assertNotNull
import kotlin.test.assertSame

class DecodeTest {

private val settings = JsonPipelineCodecSettings(true, true)
private val settings = JsonPipelineCodecSettings(encodeTypeInfo = true, decodeTypeInfo = true)
private val codec = JsonPipelineCodec(settings)

@Test
Expand All @@ -47,7 +49,7 @@ class DecodeTest {
}
val messageGroup = ProtoMessageGroup.newBuilder().addMessages(ProtoAnyMessage.newBuilder().setRawMessage(message)).build()

val decodedMessage = codec.decode(messageGroup).getMessages(0).message
val decodedMessage = codec.decode(messageGroup, ReportingContext()).getMessages(0).message

assertEquals("value", decodedMessage.getString("stringField"))
assertEquals("number(123)", decodedMessage.getString("intField"))
Expand All @@ -69,6 +71,57 @@ class DecodeTest {
assertEquals(decodedMessage.parentEventId.id, eventId)
}

@Test
fun testTransportAnyProtocolDecodeTest() {

val messageA = ParsedMessage(
eventId = EventId(eventId, "book_1", "scope_1", Instant.now()),
protocol = PROTOCOL,
type = "type_1",
body = mapOf("fieldA" to "valueA")
)
val messageB = ParsedMessage(
eventId = EventId(eventId, "book_1", "scope_1", Instant.now()),
protocol = "",
type = "type_1",
body = mapOf("fieldB" to "valueB")
)
val messageC = ParsedMessage(
eventId = EventId(eventId, "book_1", "scope_1", Instant.now()),
protocol = "test-protocol",
type = "type_1",
body = mapOf("fieldC" to "valueC")
)
val messageD = RawMessage(
eventId = EventId(eventId, "book_1", "scope_1", Instant.now()),
protocol = PROTOCOL,
body = Unpooled.wrappedBuffer("""{"fieldD":"valueD"}""".toByteArray())
)
val messageE = RawMessage(
eventId = EventId(eventId, "book_1", "scope_1", Instant.now()),
protocol = "",
body = Unpooled.wrappedBuffer("""{"fieldE":"valueE"}""".toByteArray())
)
val messageF = RawMessage(
eventId = EventId(eventId, "book_1", "scope_1", Instant.now()),
protocol = "test-protocol",
body = Unpooled.wrappedBuffer("""{"fieldF":"valueF"}""".toByteArray())
)

val group = MessageGroup(listOf(messageA, messageB, messageC, messageD, messageE, messageF))

val encoded = codec.decode(group, ReportingContext())
assertEquals(6, encoded.messages.size)
assertSame(messageA, encoded.messages[0])
assertSame(messageB, encoded.messages[1])
assertSame(messageC, encoded.messages[2])
assertEquals(mapOf("fieldD" to "valueD"), encoded.messages[3].body)
assertEquals(PROTOCOL, encoded.messages[3].protocol)
assertEquals(mapOf("fieldE" to "valueE"), encoded.messages[4].body)
assertEquals(PROTOCOL, encoded.messages[4].protocol)
assertSame(messageF, encoded.messages[5])
}

@Test
fun testTransportDecodeJsonRequest() {

Expand All @@ -81,32 +134,32 @@ class DecodeTest {

val group = MessageGroup(listOf(message))

val decodedMessage = codec.decode(group).messages[0] as ParsedMessage
val decodedMessage = codec.decode(group, ReportingContext()).messages[0] as ParsedMessage
val body = decodedMessage.body

assertEquals("value", body["stringField"])

assertEquals("number(123)", body["intField"])
assertEquals("number(123.1)", body["decimalField"])

val objectTest = body["object"] as Map<String, Any>
val objectTest = body["object"] as Map<*, *>
assertNotNull(objectTest)
assertEquals("objectFieldValue", objectTest["objectField"])

val list = body["primitiveList"] as List<Any>
val list = body["primitiveList"] as List<*>
assertNotNull(list)
assertEquals(4, list.size)
assertEquals("number(1)", list[0])

val objectList = body["objectList"] as List<Any>
val objectList = body["objectList"] as List<*>
assertNotNull(objectList)
assertEquals(2, objectList.size)

val listObject = objectList[1] as Map<String, Any>
val listObject = objectList[1] as Map<*, *>
assertEquals("boolean(true)", listObject["anotherObjectField"])

objectList.forEach {
val obj = it as Map<String, Any>
val obj = it as Map<*, *>
assertNotNull(obj)
assertEquals(1, obj.size)
}
Expand Down
Loading
Loading