Skip to content

Commit a428107

Browse files
[GH-43] Fix: codec can't encode native fix boolean values: Y, N (#44)
1 parent 8a2556b commit a428107

File tree

4 files changed

+164
-3
lines changed

4 files changed

+164
-3
lines changed

README.md

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# th2-codec-fix-ng 0.1.4
1+
# th2-codec-fix-ng 0.1.5
22

33
This codec can be used in dirty mode for decoding and encoding messages via the FIX protocol.
44

@@ -130,6 +130,15 @@ Component benchmark results available [here](docs/benchmarks/jmh-benchmark.md).
130130

131131
## Release notes
132132

133+
### 0.1.5
134+
135+
+ Fixes:
136+
+ [Codec can't encode native fix boolean values: Y, N](https://github.com/th2-net/th2-codec-fix-ng/issues/43)
137+
+ Updated:
138+
+ kotlin: `2.2.0`
139+
+ kotlin-logging: `7.0.7`
140+
+ commons-beanutils: `1.11.0`
141+
133142
### 0.1.4
134143

135144
+ Fixes:

gradle.properties

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
kotlin.code.style=official
2-
release_version=0.1.4
2+
release_version=0.1.5
33
vcs_url=https://github.com/th2-net/th2-codec-fix-ng

src/main/kotlin/com/exactpro/th2/codec/fixng/FixNgCodec.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -518,7 +518,9 @@ class FixNgCodec(dictionary: IDictionaryStructure, settings: FixNgCodecSettings)
518518
LocalTime::class.java -> MultiConverter.convert<LocalTime>(value, LocalTime::class.java)
519519
java.lang.Boolean::class.java -> when {
520520
value.equals("true", true) -> true
521+
value.equals("Y", true) -> true // https://github.com/th2-net/th2-codec-fix-ng/issues/43
521522
value.equals("false", true) -> false
523+
value.equals("N", true) -> false // https://github.com/th2-net/th2-codec-fix-ng/issues/43
522524
else -> handleError(isDirty, context, "Wrong boolean value in ${field.primitiveType.name} field '$field.name'. Value: $value.", value)
523525
}
524526
else -> {

src/test/kotlin/com/exactpro/th2/codec/fixng/FixNgCodecTest.kt

Lines changed: 151 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ import org.junit.jupiter.api.assertNotNull
3535
import org.junit.jupiter.api.function.Executable
3636
import org.junit.jupiter.params.ParameterizedTest
3737
import org.junit.jupiter.params.provider.Arguments
38+
import org.junit.jupiter.params.provider.CsvSource
3839
import org.junit.jupiter.params.provider.MethodSource
3940
import org.junit.jupiter.params.provider.ValueSource
4041
import java.math.BigDecimal
@@ -881,6 +882,127 @@ class FixNgCodecTest {
881882
parsedMessage = parsedMessageWithTimezone
882883
)
883884

885+
@ParameterizedTest
886+
@MethodSource("configs")
887+
// https://github.com/th2-net/th2-codec-fix-ng/issues/43
888+
fun `encode true boolean`(isDirty: Boolean, delimiter: Char) =
889+
encodeTest(MSG_LOGON, isDirty, delimiter, parsedMessage = parsedLogon)
890+
891+
@ParameterizedTest
892+
@CsvSource(
893+
ignoreLeadingAndTrailingWhitespace = false, value = [
894+
"true,,true",
895+
"true,,TrUe",
896+
"true,|,true",
897+
"true,|,TrUe",
898+
"false,,true",
899+
"false,,TrUe",
900+
"false,|,true",
901+
"false,|,TrUe",
902+
]
903+
)
904+
// https://github.com/th2-net/th2-codec-fix-ng/issues/43
905+
fun `encode true string`(isDirty: Boolean, delimiter: Char, value: String) = with(parsedLogon) {
906+
body.set("ResetSeqNumFlag", value)
907+
encodeTest(
908+
expectedRawMessage = MSG_LOGON,
909+
dirtyMode = isDirty,
910+
delimiter = delimiter,
911+
parsedMessage = this
912+
)
913+
}
914+
915+
@ParameterizedTest
916+
@MethodSource("configs")
917+
// https://github.com/th2-net/th2-codec-fix-ng/issues/43
918+
fun `encode false boolean`(isDirty: Boolean, delimiter: Char) = with(parsedLogon) {
919+
body.set("ResetSeqNumFlag", false)
920+
encodeTest(
921+
expectedRawMessage = MSG_LOGON
922+
.replace("141=Y", "141=N")
923+
.replace("10=213", "10=202"),
924+
dirtyMode = isDirty,
925+
delimiter = delimiter,
926+
parsedMessage = this
927+
)
928+
}
929+
930+
@ParameterizedTest
931+
@CsvSource(
932+
ignoreLeadingAndTrailingWhitespace = false, value = [
933+
"true,,false",
934+
"true,,FaLsE",
935+
"true,|,false",
936+
"true,|,FaLsE",
937+
"false,,false",
938+
"false,,FaLsE",
939+
"false,|,false",
940+
"false,|,FaLsE",
941+
]
942+
)
943+
// https://github.com/th2-net/th2-codec-fix-ng/issues/43
944+
fun `encode false string`(isDirty: Boolean, delimiter: Char, value: String) = with(parsedLogon) {
945+
body.set("ResetSeqNumFlag", value)
946+
encodeTest(
947+
expectedRawMessage = MSG_LOGON
948+
.replace("141=Y", "141=N")
949+
.replace("10=213", "10=202"),
950+
dirtyMode = isDirty,
951+
delimiter = delimiter,
952+
parsedMessage = this
953+
)
954+
}
955+
956+
@ParameterizedTest
957+
@CsvSource(
958+
ignoreLeadingAndTrailingWhitespace = false, value = [
959+
"true,,y",
960+
"true,,Y",
961+
"true,|,y",
962+
"true,|,Y",
963+
"false,,y",
964+
"false,,Y",
965+
"false,|,y",
966+
"false,|,Y",
967+
]
968+
)
969+
// https://github.com/th2-net/th2-codec-fix-ng/issues/43
970+
fun `encode Y string`(isDirty: Boolean, delimiter: Char, value: String) = with(parsedLogon) {
971+
body.set("ResetSeqNumFlag", value)
972+
encodeTest(
973+
expectedRawMessage = MSG_LOGON,
974+
dirtyMode = isDirty,
975+
delimiter = delimiter,
976+
parsedMessage = this
977+
)
978+
}
979+
980+
@ParameterizedTest
981+
@CsvSource(
982+
ignoreLeadingAndTrailingWhitespace = false, value = [
983+
"true,,n",
984+
"true,,N",
985+
"true,|,n",
986+
"true,|,N",
987+
"false,,n",
988+
"false,,N",
989+
"false,|,n",
990+
"false,|,N",
991+
]
992+
)
993+
// https://github.com/th2-net/th2-codec-fix-ng/issues/43
994+
fun `encode N string`(isDirty: Boolean, delimiter: Char, value: String) = with(parsedLogon) {
995+
body.set("ResetSeqNumFlag", value)
996+
encodeTest(
997+
expectedRawMessage = MSG_LOGON
998+
.replace("141=Y", "141=N")
999+
.replace("10=213", "10=202"),
1000+
dirtyMode = isDirty,
1001+
delimiter = delimiter,
1002+
parsedMessage = this
1003+
)
1004+
}
1005+
8841006
private fun createCodec(delimiter: Char = '', decodeValuesToStrings: Boolean = false): FixNgCodec {
8851007
return FixNgCodec(dictionary, FixNgCodecSettings(
8861008
dictionary = "",
@@ -1029,7 +1151,7 @@ class FixNgCodecTest {
10291151
"Expected text doesn't match to actual warning, index: $index"
10301152
}.startsWith(DIRTY_MODE_WARNING_PREFIX + expected)
10311153
}
1032-
}.toList<Executable>()
1154+
}.toList()
10331155
)
10341156
}
10351157
}
@@ -1246,6 +1368,32 @@ class FixNgCodecTest {
12461368
)
12471369
)
12481370

1371+
private val parsedLogon = ParsedMessage(
1372+
MessageId("test_alias", Direction.OUTGOING, 0L, Instant.now(), emptyList()),
1373+
EventId("test_id", "test_book", "test_scope", Instant.now()),
1374+
"Logon",
1375+
mutableMapOf(),
1376+
PROTOCOL,
1377+
mutableMapOf(
1378+
"header" to mutableMapOf(
1379+
"MsgSeqNum" to 1,
1380+
"SenderCompID" to "SENDER",
1381+
"SendingTime" to "2025-07-01T03:30:59.831",
1382+
"TargetCompID" to "RECEIVER",
1383+
"BeginString" to "FIXT.1.1",
1384+
"BodyLength" to 82,
1385+
"MsgType" to "Logon"
1386+
),
1387+
"EncryptMethod" to 0,
1388+
"HeartBtInt" to 30,
1389+
"ResetSeqNumFlag" to true,
1390+
"DefaultApplVerID" to "9",
1391+
"trailer" to mutableMapOf(
1392+
"CheckSum" to "229"
1393+
)
1394+
)
1395+
)
1396+
12491397
@Suppress("UNCHECKED_CAST")
12501398
private infix fun Map<String, Any?>.map(name: String): Map<String, Any?> = get(name) as Map<String, Any?>
12511399
@Suppress("UNCHECKED_CAST")
@@ -1268,6 +1416,8 @@ class FixNgCodecTest {
12681416
private const val VALUE_TOO_BIG_CHECK_SUM = "999"
12691417
private const val VALUE_INCORRECT_CHECK_SUM = "255"
12701418

1419+
private const val MSG_LOGON = "8=FIXT.1.19=8235=A49=SENDER56=RECEIVER34=152=20250701-03:30:59.83198=0108=30141=Y1137=910=213"
1420+
12711421
private const val MSG_CORRECT = "8=FIXT.1.19=29535=849=SENDER56=RECEIVER34=1094752=20230419-10:36:07.41508817=49550466211=zSuNbrBIZyVljs41=zSuNbrBIZyVljs37=49415882150=039=0151=50014=50048=NWDR22=8453=2448=NGALL1FX01447=D452=76448=0447=P452=31=test40=A59=054=B55=ABC38=50044=100047=50060=20180205-10:38:08.00000810=191"
12721422
private const val MSG_WITH_SHORT_CHECK_SUM = "8=FIXT.1.19=29635=849=SENDER56=RECEIVER34=1094752=20230419-10:36:07.41508817=495504699911=zSuNbrBIZyVljs41=zSuNbrBIZyVljs37=49415882150=039=0151=50014=50048=NWDR22=8453=2448=NGALL1FX01447=D452=76448=0447=P452=31=test40=A59=054=B55=ABC38=50044=100047=50060=20180205-10:38:08.00000810=$VALUE_SHORT_CHECK_SUM"
12731423
private const val MSG_WITH_TOO_BIG_CHECK_SUM = "8=FIXT.1.19=29535=849=SENDER56=RECEIVER34=1094752=20230419-10:36:07.41508817=49550466211=zSuNbrBIZyVljs41=zSuNbrBIZyVljs37=49415882150=039=0151=50014=50048=NWDR22=8453=2448=NGALL1FX01447=D452=76448=0447=P452=31=test40=A59=054=B55=ABC38=50044=100047=50060=20180205-10:38:08.00000810=$VALUE_TOO_BIG_CHECK_SUM"

0 commit comments

Comments
 (0)