From bdd8f2e8fce458a3e593f6e37c5bf9689fe7fc57 Mon Sep 17 00:00:00 2001 From: Andrii Landiak Date: Mon, 6 Nov 2023 09:17:11 +0200 Subject: [PATCH 1/6] Rewrite logic to correct handle specific symbols after json.stringify --- .../rule/engine/rest/TbHttpClient.java | 12 ++- .../rule/engine/rest/TbHttpClientTest.java | 73 ++++++++++++++----- 2 files changed, 64 insertions(+), 21 deletions(-) diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/rest/TbHttpClient.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/rest/TbHttpClient.java index 0c9eca5f0a..70564c9ecf 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/rest/TbHttpClient.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/rest/TbHttpClient.java @@ -242,12 +242,16 @@ public class TbHttpClient { return uri; } - private String getData(TbMsg msg) { - String data = msg.getData(); + private String getData(TbMsg tbMsg) { + return parseJsonStringToPlainText(tbMsg.getData(), config.isTrimDoubleQuotes()); + } - if (config.isTrimDoubleQuotes()) { + protected String parseJsonStringToPlainText(String data, boolean parseToJson) { + if (data.startsWith("\"") && data.endsWith("\"") && data.length() >= 2) { final String dataBefore = data; - data = data.replaceAll("^\"|\"$", ""); + try { + data = JacksonUtil.fromString(data, String.class); + } catch (Exception ignored) {} log.trace("Trimming double quotes. Before trim: [{}], after trim: [{}]", dataBefore, data); } diff --git a/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/rest/TbHttpClientTest.java b/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/rest/TbHttpClientTest.java index 48aca3b573..ee73aa46b6 100644 --- a/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/rest/TbHttpClientTest.java +++ b/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/rest/TbHttpClientTest.java @@ -18,17 +18,20 @@ package org.thingsboard.rule.engine.rest; import io.netty.channel.EventLoopGroup; import io.netty.channel.nio.NioEventLoopGroup; -import org.assertj.core.api.Assertions; import org.awaitility.Awaitility; -import org.junit.After; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; import org.mockito.ArgumentCaptor; import org.mockito.Mockito; import org.mockserver.integration.ClientAndServer; import org.springframework.util.LinkedMultiValueMap; import org.springframework.web.client.AsyncRestTemplate; +import org.thingsboard.common.util.JacksonUtil; import org.thingsboard.rule.engine.api.TbContext; import org.thingsboard.server.common.data.id.DeviceId; import org.thingsboard.server.common.data.id.EntityId; @@ -40,14 +43,18 @@ import java.net.URI; import java.util.List; import java.util.Map; import java.util.concurrent.TimeUnit; +import java.util.stream.Stream; import static org.assertj.core.api.Assertions.assertThatThrownBy; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.instanceOf; import static org.hamcrest.Matchers.is; import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyBoolean; +import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.BDDMockito.willCallRealMethod; +import static org.mockito.Mockito.lenient; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; @@ -61,13 +68,13 @@ public class TbHttpClientTest { EventLoopGroup eventLoop; TbHttpClient client; - @Before + @BeforeEach public void setUp() throws Exception { client = mock(TbHttpClient.class); - willCallRealMethod().given(client).getSharedOrCreateEventLoopGroup(any()); + when(client.getSharedOrCreateEventLoopGroup(any())).thenCallRealMethod(); } - @After + @AfterEach public void tearDown() throws Exception { if (eventLoop != null) { eventLoop.shutdownGracefully(); @@ -91,7 +98,7 @@ public class TbHttpClientTest { Mockito.when(client.buildEncodedUri(any())).thenCallRealMethod(); String url = "http://localhost:8080/"; URI uri = client.buildEncodedUri(url); - Assert.assertEquals(url, uri.toString()); + Assertions.assertEquals(url, uri.toString()); } @Test @@ -114,7 +121,7 @@ public class TbHttpClientTest { String url = "http://192.168.1.1/data?d={\"a\": 12}"; String expected = "http://192.168.1.1/data?d=%7B%22a%22:%2012%7D"; URI uri = client.buildEncodedUri(url); - Assert.assertEquals(expected, uri.toString()); + Assertions.assertEquals(expected, uri.toString()); } @Test @@ -152,7 +159,7 @@ public class TbHttpClientTest { ); var ctx = mock(TbContext.class); - when(ctx.transformMsg( + lenient().when(ctx.transformMsg( eq(msg), eq(msg.getMetaData()), eq(msg.getData()) @@ -160,7 +167,7 @@ public class TbHttpClientTest { var capturedData = ArgumentCaptor.forClass(String.class); - when(ctx.transformMsg( + lenient().when(ctx.transformMsg( eq(msg), any(), capturedData.capture() @@ -183,7 +190,7 @@ public class TbHttpClientTest { verify(ctx, times(1)).tellSuccess(any()); verify(ctx, times(0)).tellFailure(any(), any()); - Assert.assertEquals(successResponseBody, capturedData.getValue()); + Assertions.assertEquals(successResponseBody, capturedData.getValue()); } private ClientAndServer setUpDummyServer(String host, String path, String paramKey, String paramVal, String successResponseBody) { @@ -219,9 +226,41 @@ public class TbHttpClientTest { Map data = metaData.getData(); - Assertions.assertThat(data).hasSize(2); - Assertions.assertThat(data.get("Content-Type")).isEqualTo("binary"); - Assertions.assertThat(data.get("Set-Cookie")).isEqualTo("[\"sap-context=sap-client=075; path=/\",\"sap-token=sap-client=075; path=/\"]"); + Assertions.assertEquals(2, data.size()); + Assertions.assertEquals(data.get("Content-Type"), "binary"); + Assertions.assertEquals(data.get("Set-Cookie"), "[\"sap-context=sap-client=075; path=/\",\"sap-token=sap-client=075; path=/\"]"); } -} \ No newline at end of file + @ParameterizedTest + @MethodSource("provideParameters") + public void testParseJsonStringToPlainText(String original) { + Mockito.when(client.parseJsonStringToPlainText(anyString(), anyBoolean())).thenCallRealMethod(); + + String serialized = JacksonUtil.toString(original); + Assertions.assertNotNull(serialized); + Assertions.assertEquals(original, client.parseJsonStringToPlainText(serialized, true)); + } + + private static Stream provideParameters() { + return Stream.of(Arguments.of("false"), + Arguments.of("\""), + Arguments.of("\"\""), + Arguments.of("\"\"\""), + Arguments.of("\"This is a string with double quotes\""), + Arguments.of("Path: /home/developer/test.txt"), + Arguments.of("First line\nSecond line\n\nFourth line"), + Arguments.of("Before\rAfter"), + Arguments.of("Tab\tSeparated\tValues"), + Arguments.of("Test\bbackspace"), + Arguments.of("[]"), + Arguments.of("[1, 2, 3]"), + Arguments.of("{\"key\": \"value\"}"), + Arguments.of("{\n\"temperature\": 25.5,\n\"humidity\": 50.2\n\"}"), + Arguments.of("Expression: (a + b) * c"), + Arguments.of("世界"), + Arguments.of("Україна"), + Arguments.of("\u1F1FA\u1F1E6"), + Arguments.of("🇺🇦") + ); + } +} From 4ca4973b58fa725c386be27d45e12731b18a0ca5 Mon Sep 17 00:00:00 2001 From: Andrii Landiak Date: Mon, 6 Nov 2023 09:18:30 +0200 Subject: [PATCH 2/6] Add paramether of config to handle if need to process parse to json or not --- .../java/org/thingsboard/rule/engine/rest/TbHttpClient.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/rest/TbHttpClient.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/rest/TbHttpClient.java index 70564c9ecf..6cfb64cc19 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/rest/TbHttpClient.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/rest/TbHttpClient.java @@ -247,7 +247,7 @@ public class TbHttpClient { } protected String parseJsonStringToPlainText(String data, boolean parseToJson) { - if (data.startsWith("\"") && data.endsWith("\"") && data.length() >= 2) { + if (parseToJson && data.startsWith("\"") && data.endsWith("\"") && data.length() >= 2) { final String dataBefore = data; try { data = JacksonUtil.fromString(data, String.class); From fb8b21187840eb4d1d6aed6212a0456425351fd5 Mon Sep 17 00:00:00 2001 From: Andrii Landiak Date: Mon, 6 Nov 2023 13:09:00 +0200 Subject: [PATCH 3/6] Add upgrade script for TbRestApiCallNode --- .../rule/engine/rest/TbHttpClient.java | 2 +- .../rule/engine/rest/TbRestApiCallNode.java | 23 +++++++++++++++++++ .../rest/TbRestApiCallNodeConfiguration.java | 4 ++-- 3 files changed, 26 insertions(+), 3 deletions(-) diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/rest/TbHttpClient.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/rest/TbHttpClient.java index 6cfb64cc19..90e5fb1d11 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/rest/TbHttpClient.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/rest/TbHttpClient.java @@ -243,7 +243,7 @@ public class TbHttpClient { } private String getData(TbMsg tbMsg) { - return parseJsonStringToPlainText(tbMsg.getData(), config.isTrimDoubleQuotes()); + return parseJsonStringToPlainText(tbMsg.getData(), config.isParseToPlainText()); } protected String parseJsonStringToPlainText(String data, boolean parseToJson) { diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/rest/TbRestApiCallNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/rest/TbRestApiCallNode.java index 281f65e1e4..a37310331e 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/rest/TbRestApiCallNode.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/rest/TbRestApiCallNode.java @@ -15,6 +15,8 @@ */ package org.thingsboard.rule.engine.rest; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.node.ObjectNode; import lombok.extern.slf4j.Slf4j; import org.thingsboard.rule.engine.api.RuleNode; import org.thingsboard.rule.engine.api.TbContext; @@ -23,6 +25,7 @@ import org.thingsboard.rule.engine.api.TbNodeException; import org.thingsboard.rule.engine.api.util.TbNodeUtils; import org.thingsboard.rule.engine.external.TbAbstractExternalNode; import org.thingsboard.server.common.data.plugin.ComponentType; +import org.thingsboard.server.common.data.util.TbPair; import org.thingsboard.server.common.msg.TbMsg; @Slf4j @@ -30,6 +33,7 @@ import org.thingsboard.server.common.msg.TbMsg; type = ComponentType.EXTERNAL, name = "rest api call", configClazz = TbRestApiCallNodeConfiguration.class, + version = 1, nodeDescription = "Invoke REST API calls to external REST server", nodeDetails = "Will invoke REST API call GET | POST | PUT | DELETE to external REST server. " + "Message payload added into Request body. Configured attributes can be added into Headers from Message Metadata." + @@ -45,6 +49,8 @@ import org.thingsboard.server.common.msg.TbMsg; ) public class TbRestApiCallNode extends TbAbstractExternalNode { + static final String PARSE_TO_PLAIN_TEXT = "parseToPlainText"; + static final String TRIM_DOUBLE_QUOTES = "trimDoubleQuotes"; protected TbHttpClient httpClient; @Override @@ -72,4 +78,21 @@ public class TbRestApiCallNode extends TbAbstractExternalNode { } } + @Override + public TbPair upgrade(int fromVersion, JsonNode oldConfiguration) throws TbNodeException { + boolean hasChanges = false; + switch (fromVersion) { + case 0: + if (!oldConfiguration.has(PARSE_TO_PLAIN_TEXT) && oldConfiguration.has(TRIM_DOUBLE_QUOTES)) { + hasChanges = true; + ((ObjectNode) oldConfiguration).put(PARSE_TO_PLAIN_TEXT, oldConfiguration.get(TRIM_DOUBLE_QUOTES).booleanValue()); + ((ObjectNode) oldConfiguration).remove(TRIM_DOUBLE_QUOTES); + } + break; + default: + break; + } + return new TbPair<>(hasChanges, oldConfiguration); + } + } diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/rest/TbRestApiCallNodeConfiguration.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/rest/TbRestApiCallNodeConfiguration.java index 3fb28d474b..1ab4c8d0f8 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/rest/TbRestApiCallNodeConfiguration.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/rest/TbRestApiCallNodeConfiguration.java @@ -37,7 +37,7 @@ public class TbRestApiCallNodeConfiguration implements NodeConfiguration Date: Mon, 6 Nov 2023 13:22:21 +0200 Subject: [PATCH 4/6] Add test on upgrade script for TbRestApiCallNode --- .../engine/rest/TbRestApiCallNodeTest.java | 23 ++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/rest/TbRestApiCallNodeTest.java b/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/rest/TbRestApiCallNodeTest.java index 705f298513..0a71a799fc 100644 --- a/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/rest/TbRestApiCallNodeTest.java +++ b/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/rest/TbRestApiCallNodeTest.java @@ -16,6 +16,7 @@ package org.thingsboard.rule.engine.rest; import com.datastax.oss.driver.api.core.uuid.Uuids; +import com.fasterxml.jackson.databind.JsonNode; import org.apache.http.HttpException; import org.apache.http.HttpRequest; import org.apache.http.HttpResponse; @@ -26,6 +27,7 @@ import org.apache.http.protocol.HttpContext; import org.apache.http.protocol.HttpRequestHandler; import org.junit.After; import org.junit.Test; +import org.junit.jupiter.api.Assertions; import org.junit.runner.RunWith; import org.mockito.ArgumentCaptor; import org.mockito.Mock; @@ -39,6 +41,7 @@ import org.thingsboard.server.common.data.id.EntityId; import org.thingsboard.server.common.data.id.RuleChainId; import org.thingsboard.server.common.data.id.RuleNodeId; import org.thingsboard.server.common.data.msg.TbMsgType; +import org.thingsboard.server.common.data.util.TbPair; import org.thingsboard.server.common.msg.TbMsg; import org.thingsboard.server.common.msg.TbMsgDataType; import org.thingsboard.server.common.msg.TbMsgMetaData; @@ -91,7 +94,9 @@ public class TbRestApiCallNodeTest { @After public void teardown() { - server.stop(); + if (server != null) { + server.stop(); + } } @Test @@ -211,4 +216,20 @@ public class TbRestApiCallNodeTest { assertEquals(TbMsg.EMPTY_JSON_OBJECT, dataCaptor.getValue()); } + @Test + public void givenOldConfig_whenUpgrade_thenShouldReturnTrueResultWithNewConfig() throws Exception { + var defaultConfig = new TbRestApiCallNodeConfiguration().defaultConfiguration(); + var node = new TbRestApiCallNode(); + String oldConfig = "{\"restEndpointUrlPattern\":\"http://localhost/api\",\"requestMethod\":\"POST\"," + + "\"useSimpleClientHttpFactory\":false,\"ignoreRequestBody\":false,\"enableProxy\":false," + + "\"useSystemProxyProperties\":false,\"proxyScheme\":null,\"proxyHost\":null,\"proxyPort\":0," + + "\"proxyUser\":null,\"proxyPassword\":null,\"readTimeoutMs\":0,\"maxParallelRequestsCount\":0," + + "\"headers\":{\"Content-Type\":\"application/json\"},\"useRedisQueueForMsgPersistence\":false," + + "\"trimQueue\":null,\"maxQueueSize\":null,\"credentials\":{\"type\":\"anonymous\"},\"trimDoubleQuotes\":true}"; + JsonNode configJson = JacksonUtil.toJsonNode(oldConfig); + TbPair upgrade = node.upgrade(0, configJson); + Assertions.assertTrue(upgrade.getFirst()); + Assertions.assertTrue(JacksonUtil.treeToValue(upgrade.getSecond(), defaultConfig.getClass()).isParseToPlainText()); + } + } From 950f4a184fe849fd030c6b22e3a03e46483692af Mon Sep 17 00:00:00 2001 From: Andrii Landiak Date: Mon, 6 Nov 2023 13:23:57 +0200 Subject: [PATCH 5/6] Fix TbHttpClientTest --- .../org/thingsboard/rule/engine/rest/TbHttpClientTest.java | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/rest/TbHttpClientTest.java b/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/rest/TbHttpClientTest.java index ee73aa46b6..37aba7d9cb 100644 --- a/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/rest/TbHttpClientTest.java +++ b/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/rest/TbHttpClientTest.java @@ -54,7 +54,6 @@ import static org.mockito.ArgumentMatchers.anyBoolean; import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.BDDMockito.willCallRealMethod; -import static org.mockito.Mockito.lenient; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; @@ -159,7 +158,7 @@ public class TbHttpClientTest { ); var ctx = mock(TbContext.class); - lenient().when(ctx.transformMsg( + when(ctx.transformMsg( eq(msg), eq(msg.getMetaData()), eq(msg.getData()) @@ -167,7 +166,7 @@ public class TbHttpClientTest { var capturedData = ArgumentCaptor.forClass(String.class); - lenient().when(ctx.transformMsg( + when(ctx.transformMsg( eq(msg), any(), capturedData.capture() From cb2d95cdf6dcefbf8e2f414183c06da4dfb16226 Mon Sep 17 00:00:00 2001 From: Andrii Landiak Date: Tue, 7 Nov 2023 14:34:28 +0200 Subject: [PATCH 6/6] After review: update logic for method invoc, update parametrized test --- .../rule/engine/rest/TbHttpClient.java | 13 ++++--- .../rule/engine/rest/TbHttpClientTest.java | 37 ++++--------------- 2 files changed, 15 insertions(+), 35 deletions(-) diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/rest/TbHttpClient.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/rest/TbHttpClient.java index 90e5fb1d11..1a2984ef4f 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/rest/TbHttpClient.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/rest/TbHttpClient.java @@ -194,7 +194,7 @@ public class TbHttpClient { config.isIgnoreRequestBody()) { entity = new HttpEntity<>(headers); } else { - entity = new HttpEntity<>(getData(msg), headers); + entity = new HttpEntity<>(getData(msg, config.isIgnoreRequestBody(), config.isParseToPlainText()), headers); } URI uri = buildEncodedUri(endpointUrl); @@ -242,12 +242,15 @@ public class TbHttpClient { return uri; } - private String getData(TbMsg tbMsg) { - return parseJsonStringToPlainText(tbMsg.getData(), config.isParseToPlainText()); + private String getData(TbMsg tbMsg, boolean ignoreBody, boolean parseToPlainText) { + if (!ignoreBody && parseToPlainText) { + return parseJsonStringToPlainText(tbMsg.getData()); + } + return tbMsg.getData(); } - protected String parseJsonStringToPlainText(String data, boolean parseToJson) { - if (parseToJson && data.startsWith("\"") && data.endsWith("\"") && data.length() >= 2) { + protected String parseJsonStringToPlainText(String data) { + if (data.startsWith("\"") && data.endsWith("\"") && data.length() >= 2) { final String dataBefore = data; try { data = JacksonUtil.fromString(data, String.class); diff --git a/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/rest/TbHttpClientTest.java b/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/rest/TbHttpClientTest.java index 37aba7d9cb..d71d4aacbe 100644 --- a/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/rest/TbHttpClientTest.java +++ b/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/rest/TbHttpClientTest.java @@ -24,8 +24,7 @@ import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.Arguments; -import org.junit.jupiter.params.provider.MethodSource; +import org.junit.jupiter.params.provider.ValueSource; import org.mockito.ArgumentCaptor; import org.mockito.Mockito; import org.mockserver.integration.ClientAndServer; @@ -43,14 +42,12 @@ import java.net.URI; import java.util.List; import java.util.Map; import java.util.concurrent.TimeUnit; -import java.util.stream.Stream; import static org.assertj.core.api.Assertions.assertThatThrownBy; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.instanceOf; import static org.hamcrest.Matchers.is; import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.anyBoolean; import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.BDDMockito.willCallRealMethod; @@ -231,35 +228,15 @@ public class TbHttpClientTest { } @ParameterizedTest - @MethodSource("provideParameters") + @ValueSource(strings = { "false", "\"", "\"\"", "\"This is a string with double quotes\"", "Path: /home/developer/test.txt", + "First line\nSecond line\n\nFourth line", "Before\rAfter", "Tab\tSeparated\tValues", "Test\bbackspace", "[]", + "[1, 2, 3]", "{\"key\": \"value\"}", "{\n\"temperature\": 25.5,\n\"humidity\": 50.2\n\"}", "Expression: (a + b) * c", + "世界", "Україна", "\u1F1FA\u1F1E6", "🇺🇦"}) public void testParseJsonStringToPlainText(String original) { - Mockito.when(client.parseJsonStringToPlainText(anyString(), anyBoolean())).thenCallRealMethod(); + Mockito.when(client.parseJsonStringToPlainText(anyString())).thenCallRealMethod(); String serialized = JacksonUtil.toString(original); Assertions.assertNotNull(serialized); - Assertions.assertEquals(original, client.parseJsonStringToPlainText(serialized, true)); - } - - private static Stream provideParameters() { - return Stream.of(Arguments.of("false"), - Arguments.of("\""), - Arguments.of("\"\""), - Arguments.of("\"\"\""), - Arguments.of("\"This is a string with double quotes\""), - Arguments.of("Path: /home/developer/test.txt"), - Arguments.of("First line\nSecond line\n\nFourth line"), - Arguments.of("Before\rAfter"), - Arguments.of("Tab\tSeparated\tValues"), - Arguments.of("Test\bbackspace"), - Arguments.of("[]"), - Arguments.of("[1, 2, 3]"), - Arguments.of("{\"key\": \"value\"}"), - Arguments.of("{\n\"temperature\": 25.5,\n\"humidity\": 50.2\n\"}"), - Arguments.of("Expression: (a + b) * c"), - Arguments.of("世界"), - Arguments.of("Україна"), - Arguments.of("\u1F1FA\u1F1E6"), - Arguments.of("🇺🇦") - ); + Assertions.assertEquals(original, client.parseJsonStringToPlainText(serialized)); } }