This is an automated email from the ASF dual-hosted git repository. chrisdutz pushed a commit to branch develop in repository https://gitbox.apache.org/repos/asf/plc4x.git
commit f61231d06ac4b968d366ef98fcb5021b4c92aa60 Author: Christofer Dutz <[email protected]> AuthorDate: Tue Jun 23 19:13:39 2026 +0200 feat: Added string support to the Simulated driver. --- .../java/simulated/connection/SimulatedDevice.java | 34 ++++++++++++++++++- .../simulated/connection/SimulatedDeviceTest.java | 38 ++++++++++++++++++++++ 2 files changed, 71 insertions(+), 1 deletion(-) diff --git a/plc4j/drivers/simulated/src/main/java/org/apache/plc4x/java/simulated/connection/SimulatedDevice.java b/plc4j/drivers/simulated/src/main/java/org/apache/plc4x/java/simulated/connection/SimulatedDevice.java index ed43d8509b..4f5d2147a0 100644 --- a/plc4j/drivers/simulated/src/main/java/org/apache/plc4x/java/simulated/connection/SimulatedDevice.java +++ b/plc4j/drivers/simulated/src/main/java/org/apache/plc4x/java/simulated/connection/SimulatedDevice.java @@ -26,6 +26,8 @@ import org.apache.plc4x.java.api.value.PlcValue; import org.apache.plc4x.java.simulated.readwrite.DataItem; import org.apache.plc4x.java.simulated.readwrite.SimulatedDataTypeSizes; import org.apache.plc4x.java.simulated.tag.SimulatedTag; +import org.apache.plc4x.java.spi.values.PlcList; +import org.apache.plc4x.java.spi.values.PlcSTRING; import org.apache.plc4x.java.spi.buffers.api.exceptions.BufferException; import org.apache.plc4x.java.spi.buffers.bytebased.ReadBufferByteBased; import org.apache.plc4x.java.spi.buffers.bytebased.WriteBufferByteBased; @@ -35,8 +37,10 @@ import org.slf4j.LoggerFactory; import java.security.SecureRandom; import java.time.Duration; +import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; +import java.util.List; import java.util.IdentityHashMap; import java.util.Map; import java.util.Objects; @@ -130,8 +134,26 @@ public class SimulatedDevice { } private PlcValue randomValue(SimulatedTag tag) { - short tagDataTypeSize = SimulatedDataTypeSizes.valueOf(tag.getPlcValueType().name()).getDataTypeSize(); int numElements = tag.getArrayInfo().isEmpty() ? 1 : tag.getArrayInfo().get(0).getSize(); + // Strings are length-prefixed, so feeding random bytes to the parser almost always + // yields a bogus length and a BufferException (which would surface as NOT_FOUND). + // Generate a valid random string directly instead - mirrors how the write path + // special-cases STRING/WSTRING in set(). + switch (tag.getPlcValueType()) { + case STRING: + case WSTRING: + if (numElements == 1) { + return new PlcSTRING(randomString()); + } + List<PlcValue> elements = new ArrayList<>(numElements); + for (int i = 0; i < numElements; i++) { + elements.add(new PlcSTRING(randomString())); + } + return new PlcList(elements); + default: + break; + } + short tagDataTypeSize = SimulatedDataTypeSizes.valueOf(tag.getPlcValueType().name()).getDataTypeSize(); byte[] b = new byte[tagDataTypeSize * numElements]; random.nextBytes(b); ReadBufferByteBased io = new ReadBufferByteBased(b); @@ -142,6 +164,16 @@ public class SimulatedDevice { } } + private String randomString() { + final String alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; + int length = 1 + random.nextInt(10); + StringBuilder sb = new StringBuilder(length); + for (int i = 0; i < length; i++) { + sb.append(alphabet.charAt(random.nextInt(alphabet.length()))); + } + return sb.toString(); + } + @Override public String toString() { return name; diff --git a/plc4j/drivers/simulated/src/test/java/org/apache/plc4x/java/simulated/connection/SimulatedDeviceTest.java b/plc4j/drivers/simulated/src/test/java/org/apache/plc4x/java/simulated/connection/SimulatedDeviceTest.java index 1f3187e23a..84361a2af2 100644 --- a/plc4j/drivers/simulated/src/test/java/org/apache/plc4x/java/simulated/connection/SimulatedDeviceTest.java +++ b/plc4j/drivers/simulated/src/test/java/org/apache/plc4x/java/simulated/connection/SimulatedDeviceTest.java @@ -19,6 +19,7 @@ package org.apache.plc4x.java.simulated.connection; import org.apache.plc4x.java.spi.values.PlcLINT; +import org.apache.plc4x.java.spi.values.PlcList; import org.apache.plc4x.java.api.value.PlcValue; import org.apache.plc4x.java.simulated.tag.SimulatedTag; import org.junit.jupiter.api.Test; @@ -39,6 +40,43 @@ public class SimulatedDeviceTest { assertTrue(value.isPresent()); } + @Test + public void randomString() { + SimulatedDevice device = new SimulatedDevice("foobar"); + SimulatedTag tag = SimulatedTag.of("RANDOM/foo:STRING"); + + // Random STRING values must be generated directly rather than parsed from random bytes + // (which would fail and yield an empty/NOT_FOUND result). + Optional<PlcValue> value = device.get(tag); + + assertTrue(value.isPresent()); + assertNotNull(value.get().getString()); + assertFalse(value.get().getString().isEmpty()); + } + + @Test + public void randomWString() { + SimulatedDevice device = new SimulatedDevice("foobar"); + SimulatedTag tag = SimulatedTag.of("RANDOM/foo:WSTRING"); + + Optional<PlcValue> value = device.get(tag); + + assertTrue(value.isPresent()); + assertFalse(value.get().getString().isEmpty()); + } + + @Test + public void randomStringArray() { + SimulatedDevice device = new SimulatedDevice("foobar"); + SimulatedTag tag = SimulatedTag.of("RANDOM/foo:STRING[3]"); + + Optional<PlcValue> value = device.get(tag); + + assertTrue(value.isPresent()); + assertInstanceOf(PlcList.class, value.get()); + assertEquals(3, ((PlcList) value.get()).getLength()); + } + @Test public void read() { SimulatedDevice device = new SimulatedDevice("foobar");
