Skip to content

Conversation

@wirew0rm
Copy link
Member

follow up of #223 and companion PR to fair-acc/opencmw-cpp#389

missing functionality:

  • fetch test binary from opencmw-cpp release artifacts
  • fix serialiser test failure (probably an errror in the test implementation since the deserialisation of subscription updates works)

Process cppOpencmw = new ProcessBuilder("../CompatibilityTest", "serialise", "--value", value + "", "--array-size", arraySize + "").start();

final TestData testData = new TestData();
testData.booleanValue = value % 2 == 0;

Check warning

Code scanning / CodeQL

Useless comparison test Warning test

Test is always true.

Copilot Autofix

AI 13 days ago

In general, to fix a “useless comparison test” where a condition is always true or false, remove or simplify the condition so that the code expresses the constant outcome directly. If the condition is meant to vary, adjust the surrounding logic so that the compared values are not constant.

Here, value is always 42, so value % 2 == 0 is always true. The test constructs a fixed TestData instance; no later logic depends on computing the parity dynamically. The minimal behaviour‑preserving change is to set testData.booleanValue directly to true. This removes the redundant comparison and keeps the actual runtime value identical.

Concretely, in client/src/test/java/io/opencmw/client/OpenCmwCppInteropTest.java, within testSerialiserCompatibility, replace line 60:

testData.booleanValue = value % 2 == 0;

with:

testData.booleanValue = true;

No additional imports, methods, or definitions are required.

Suggested changeset 1
client/src/test/java/io/opencmw/client/OpenCmwCppInteropTest.java

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/client/src/test/java/io/opencmw/client/OpenCmwCppInteropTest.java b/client/src/test/java/io/opencmw/client/OpenCmwCppInteropTest.java
--- a/client/src/test/java/io/opencmw/client/OpenCmwCppInteropTest.java
+++ b/client/src/test/java/io/opencmw/client/OpenCmwCppInteropTest.java
@@ -57,7 +57,7 @@
         Process cppOpencmw = new ProcessBuilder("../CompatibilityTest", "serialise", "--value", value + "", "--array-size", arraySize + "").start();
 
         final TestData testData = new TestData();
-        testData.booleanValue = value % 2 == 0;
+        testData.booleanValue = true;
         testData.int8Value = value;
         testData.int16Value = value;
         testData.int32Value = value;
EOF
@@ -57,7 +57,7 @@
Process cppOpencmw = new ProcessBuilder("../CompatibilityTest", "serialise", "--value", value + "", "--array-size", arraySize + "").start();

final TestData testData = new TestData();
testData.booleanValue = value % 2 == 0;
testData.booleanValue = true;
testData.int8Value = value;
testData.int16Value = value;
testData.int32Value = value;
Copilot is powered by AI and may make mistakes. Always verify output.
IoClassSerialiser serialiser = new IoClassSerialiser(buffer, BinarySerialiser.class);
buffer.reset(); // '0' writing at start of buffer
serialiser.serialiseObject(testData);
String opencmwJavaString = new String(buffer.elements(), 0, buffer.position(), Charset.defaultCharset());

Check notice

Code scanning / CodeQL

Unread local variable Note test

Variable 'String opencmwJavaString' is never read.

Copilot Autofix

AI 13 days ago

In general, the right fix for an unread local variable is to either remove the declaration entirely or, if it was supposed to be used, add the missing usage. Here the string construction has no side effects and there is no active use, so the safest and simplest fix is to delete the variable declaration line.

Specifically, in client/src/test/java/io/opencmw/client/OpenCmwCppInteropTest.java, within testSerialiserCompatibility, remove the line that declares and initializes opencmwJavaString. The surrounding logic remains unchanged: we still serialise into buffer, then write buffer.elements() directly to java.hex, then proceed with the C++ process output. No new methods or imports are required.

Suggested changeset 1
client/src/test/java/io/opencmw/client/OpenCmwCppInteropTest.java

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/client/src/test/java/io/opencmw/client/OpenCmwCppInteropTest.java b/client/src/test/java/io/opencmw/client/OpenCmwCppInteropTest.java
--- a/client/src/test/java/io/opencmw/client/OpenCmwCppInteropTest.java
+++ b/client/src/test/java/io/opencmw/client/OpenCmwCppInteropTest.java
@@ -81,7 +81,6 @@
         IoClassSerialiser serialiser = new IoClassSerialiser(buffer, BinarySerialiser.class);
         buffer.reset(); // '0' writing at start of buffer
         serialiser.serialiseObject(testData);
-        String opencmwJavaString = new String(buffer.elements(), 0, buffer.position(), Charset.defaultCharset());
         Files.write(new File("java.hex").toPath(), buffer.elements());
 
         cppOpencmw.waitFor();
EOF
@@ -81,7 +81,6 @@
IoClassSerialiser serialiser = new IoClassSerialiser(buffer, BinarySerialiser.class);
buffer.reset(); // '0' writing at start of buffer
serialiser.serialiseObject(testData);
String opencmwJavaString = new String(buffer.elements(), 0, buffer.position(), Charset.defaultCharset());
Files.write(new File("java.hex").toPath(), buffer.elements());

cppOpencmw.waitFor();
Copilot is powered by AI and may make mistakes. Always verify output.
event.throwables.forEach((Throwable e) -> System.err.println(e.getMessage()));
} else {
if (event.payload.getType() == TestData.class) {
System.out.println(event.payload.get(TestData.class));

Check notice

Code scanning / CodeQL

Use of default toString() Note test

Default toString(): TestData inherits toString() from Object, and so is not suitable for printing.

Copilot Autofix

AI 13 days ago

In general, to fix this kind of issue you define a domain-specific toString() method on the relevant class (here, TestData) so that when the object is printed or logged, a human-readable and informative representation is produced instead of the default Object.toString().

Given the constraints (we can only edit the shown test file), the best we can do without changing behavior elsewhere is to avoid relying on TestData’s default toString() at this call site. Since we cannot modify TestData itself (no definition is shown) and we must not introduce assumptions about its internal structure, the safest change is to wrap the printed value in a descriptive message that does not depend on TestData.toString() for meaning. However, that would still implicitly invoke toString() and keep the warning alive.

A more robust and standards-compliant solution in this constrained context is to stop implicitly converting the TestData instance to a string at all. Instead, log a generic description that does not print the instance directly. For example, replace:

System.out.println(event.payload.get(TestData.class));

with something like:

TestData data = event.payload.get(TestData.class);
System.out.println("Received TestData instance of type: " + data.getClass().getName());

This no longer uses TestData.toString(). It still confirms that an update was received and avoids assumptions about TestData’s fields. Because we cannot assume any methods on TestData beyond those of Object, using getClass().getName() is safe.

Concretely, in client/src/test/java/io/opencmw/client/OpenCmwCppInteropTest.java, inside the eventStore.register lambda in testSubscriptionWithListener, change the line that prints event.payload.get(TestData.class) to first assign the value to a variable and then print a message that uses only methods from Object/Class. No new imports or additional methods are needed.

Suggested changeset 1
client/src/test/java/io/opencmw/client/OpenCmwCppInteropTest.java

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/client/src/test/java/io/opencmw/client/OpenCmwCppInteropTest.java b/client/src/test/java/io/opencmw/client/OpenCmwCppInteropTest.java
--- a/client/src/test/java/io/opencmw/client/OpenCmwCppInteropTest.java
+++ b/client/src/test/java/io/opencmw/client/OpenCmwCppInteropTest.java
@@ -112,7 +112,8 @@
                 event.throwables.forEach((Throwable e) -> System.err.println(e.getMessage()));
             } else {
                 if (event.payload.getType() == TestData.class) {
-                    System.out.println(event.payload.get(TestData.class));
+                    TestData data = event.payload.get(TestData.class);
+                    System.out.println("Received TestData instance of type: " + data.getClass().getName());
                 } else {
                     System.err.println("unexpected payload type" + event.payload.getType().getSimpleName());
                 }
EOF
@@ -112,7 +112,8 @@
event.throwables.forEach((Throwable e) -> System.err.println(e.getMessage()));
} else {
if (event.payload.getType() == TestData.class) {
System.out.println(event.payload.get(TestData.class));
TestData data = event.payload.get(TestData.class);
System.out.println("Received TestData instance of type: " + data.getClass().getName());
} else {
System.err.println("unexpected payload type" + event.payload.getType().getSimpleName());
}
Copilot is powered by AI and may make mistakes. Always verify output.
Assumptions.assumeTrue(new File("../CompatibilityTest").exists()); // skip if the test binary is not available
int port = brokerAddress.getPort();
int portMds = brokerPubAddress.getPort();
Process cppOpencmw = new ProcessBuilder("../CompatibilityTest", "serve", "--port", port + "", "--port-mds", portMds + "").inheritIO().start();

Check notice

Code scanning / CodeQL

Unread local variable Note test

Variable 'Process cppOpencmw' is never read.

Copilot Autofix

AI 13 days ago

In general, to fix an unread local variable you either (1) remove the variable declaration and keep only the side-effectful expression, or (2) start using the variable meaningfully (for example, for cleanup). Here, the process object is important for resource management, as evidenced by the other test that calls cppOpencmw.destroy();. The best fix without changing observable behavior is to ensure we still start the process, and additionally to use the Process instance to clean up the child process at the end of the test. This both eliminates the “unread variable” and improves resource handling.

Concretely, in client/src/test/java/io/opencmw/client/OpenCmwCppInteropTest.java, inside the testGetRequest method:

  • Keep the declaration Process cppOpencmw = ...start(); so we still start the external CompatibilityTest server and have a handle to it.
  • Add a try/finally structure around the body of the test so that cppOpencmw.destroy(); (and possibly destroyForcibly() as a fallback) is called in the finally block.
  • Move the existing logic (eventStore.start(), dataSourcePublisher.start(), request/response, and stop calls) into the try block.

No new imports are required since Process is part of java.lang. The only changes are within the shown method: wrapping existing logic in a try/finally and adding cppOpencmw.destroy(); so that the variable is now read/used.

Suggested changeset 1
client/src/test/java/io/opencmw/client/OpenCmwCppInteropTest.java

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/client/src/test/java/io/opencmw/client/OpenCmwCppInteropTest.java b/client/src/test/java/io/opencmw/client/OpenCmwCppInteropTest.java
--- a/client/src/test/java/io/opencmw/client/OpenCmwCppInteropTest.java
+++ b/client/src/test/java/io/opencmw/client/OpenCmwCppInteropTest.java
@@ -168,28 +168,34 @@
         int port = brokerAddress.getPort();
         int portMds = brokerPubAddress.getPort();
         Process cppOpencmw = new ProcessBuilder("../CompatibilityTest", "serve", "--port", port + "", "--port-mds", portMds + "").inheritIO().start();
-        eventStore.start();
-        dataSourcePublisher.start();
-        LockSupport.parkNanos(Duration.ofMillis(200).toNanos());
+        try {
+            eventStore.start();
+            dataSourcePublisher.start();
+            LockSupport.parkNanos(Duration.ofMillis(200).toNanos());
 
-        // get request
-        final URI requestURI = URI.create(brokerAddress + "/testProperty?contentType=application/octet-stream&contextA=test&contextB=asdf");
-        LOGGER.atInfo().addArgument(requestURI).log("requesting GET from endpoint: {}");
-        final Future<TestData> future;
-        try (final DataSourcePublisher.Client client = dataSourcePublisher.getClient()) {
-            future = client.get(requestURI, null, TestData.class); // uri_without_query oder serviceName + resolver, requestContext, type
-        } catch (Exception e) {
-            System.err.println(e.getMessage());
-            throw e;
-        }
+            // get request
+            final URI requestURI = URI.create(brokerAddress + "/testProperty?contentType=application/octet-stream&contextA=test&contextB=asdf");
+            LOGGER.atInfo().addArgument(requestURI).log("requesting GET from endpoint: {}");
+            final Future<TestData> future;
+            try (final DataSourcePublisher.Client client = dataSourcePublisher.getClient()) {
+                future = client.get(requestURI, null, TestData.class); // uri_without_query oder serviceName + resolver, requestContext, type
+            } catch (Exception e) {
+                System.err.println(e.getMessage());
+                throw e;
+            }
 
-        // assert result
-        final TestData result = future.get(1000, TimeUnit.MILLISECONDS);
+            // assert result
+            final TestData result = future.get(1000, TimeUnit.MILLISECONDS);
 
-        System.out.println(result.doubleValue);
+            System.out.println(result.doubleValue);
 
-        eventStore.stop();
-        dataSourcePublisher.stop();
+            eventStore.stop();
+            dataSourcePublisher.stop();
+        } finally {
+            if (cppOpencmw != null) {
+                cppOpencmw.destroy();
+            }
+        }
     }
 
     @Test
EOF
@@ -168,28 +168,34 @@
int port = brokerAddress.getPort();
int portMds = brokerPubAddress.getPort();
Process cppOpencmw = new ProcessBuilder("../CompatibilityTest", "serve", "--port", port + "", "--port-mds", portMds + "").inheritIO().start();
eventStore.start();
dataSourcePublisher.start();
LockSupport.parkNanos(Duration.ofMillis(200).toNanos());
try {
eventStore.start();
dataSourcePublisher.start();
LockSupport.parkNanos(Duration.ofMillis(200).toNanos());

// get request
final URI requestURI = URI.create(brokerAddress + "/testProperty?contentType=application/octet-stream&contextA=test&contextB=asdf");
LOGGER.atInfo().addArgument(requestURI).log("requesting GET from endpoint: {}");
final Future<TestData> future;
try (final DataSourcePublisher.Client client = dataSourcePublisher.getClient()) {
future = client.get(requestURI, null, TestData.class); // uri_without_query oder serviceName + resolver, requestContext, type
} catch (Exception e) {
System.err.println(e.getMessage());
throw e;
}
// get request
final URI requestURI = URI.create(brokerAddress + "/testProperty?contentType=application/octet-stream&contextA=test&contextB=asdf");
LOGGER.atInfo().addArgument(requestURI).log("requesting GET from endpoint: {}");
final Future<TestData> future;
try (final DataSourcePublisher.Client client = dataSourcePublisher.getClient()) {
future = client.get(requestURI, null, TestData.class); // uri_without_query oder serviceName + resolver, requestContext, type
} catch (Exception e) {
System.err.println(e.getMessage());
throw e;
}

// assert result
final TestData result = future.get(1000, TimeUnit.MILLISECONDS);
// assert result
final TestData result = future.get(1000, TimeUnit.MILLISECONDS);

System.out.println(result.doubleValue);
System.out.println(result.doubleValue);

eventStore.stop();
dataSourcePublisher.stop();
eventStore.stop();
dataSourcePublisher.stop();
} finally {
if (cppOpencmw != null) {
cppOpencmw.destroy();
}
}
}

@Test
Copilot is powered by AI and may make mistakes. Always verify output.
Assumptions.assumeTrue(new File("../CompatibilityTest").exists()); // skip if the test binary is not available
int port = brokerAddress.getPort();
int portMds = brokerPubAddress.getPort();
Process cppOpencmw = new ProcessBuilder("../CompatibilityTest", "serve", "--port", port + "", "--port-mds", portMds + "").inheritIO().start();

Check notice

Code scanning / CodeQL

Unread local variable Note test

Variable 'Process cppOpencmw' is never read.

Copilot Autofix

AI 13 days ago

In general, to fix an unread local variable you either (a) remove the variable entirely while preserving any side-effecting expression, or (b) start using the variable meaningfully. Here, the test only needs to start the external compatibility server; it does not use the Process object. The simplest, behavior-preserving fix is to drop the Process cppOpencmw declaration and just invoke new ProcessBuilder(...).start(); as a standalone statement.

Concretely, in client/src/test/java/io/opencmw/client/OpenCmwCppInteropTest.java, inside testGetRequestWithAnnotations, change line 200 from a variable declaration Process cppOpencmw = new ProcessBuilder(...).start(); to just new ProcessBuilder(...).inheritIO().start();. This keeps all existing behavior (starting the process with inherited IO) and removes the unread variable. No new imports, methods, or other definitions are required.

Suggested changeset 1
client/src/test/java/io/opencmw/client/OpenCmwCppInteropTest.java

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/client/src/test/java/io/opencmw/client/OpenCmwCppInteropTest.java b/client/src/test/java/io/opencmw/client/OpenCmwCppInteropTest.java
--- a/client/src/test/java/io/opencmw/client/OpenCmwCppInteropTest.java
+++ b/client/src/test/java/io/opencmw/client/OpenCmwCppInteropTest.java
@@ -197,7 +197,7 @@
         Assumptions.assumeTrue(new File("../CompatibilityTest").exists()); // skip if the test binary is not available
         int port = brokerAddress.getPort();
         int portMds = brokerPubAddress.getPort();
-        Process cppOpencmw = new ProcessBuilder("../CompatibilityTest", "serve", "--port", port + "", "--port-mds", portMds + "").inheritIO().start();
+        new ProcessBuilder("../CompatibilityTest", "serve", "--port", port + "", "--port-mds", portMds + "").inheritIO().start();
         eventStore.start();
         dataSourcePublisher.start();
         LockSupport.parkNanos(Duration.ofMillis(200).toNanos());
EOF
@@ -197,7 +197,7 @@
Assumptions.assumeTrue(new File("../CompatibilityTest").exists()); // skip if the test binary is not available
int port = brokerAddress.getPort();
int portMds = brokerPubAddress.getPort();
Process cppOpencmw = new ProcessBuilder("../CompatibilityTest", "serve", "--port", port + "", "--port-mds", portMds + "").inheritIO().start();
new ProcessBuilder("../CompatibilityTest", "serve", "--port", port + "", "--port-mds", portMds + "").inheritIO().start();
eventStore.start();
dataSourcePublisher.start();
LockSupport.parkNanos(Duration.ofMillis(200).toNanos());
Copilot is powered by AI and may make mistakes. Always verify output.

public void setFieldGroups(final List<String> fieldGroups) {
this.fieldGroups = fieldGroups;
public byte getFieldModifier() {

Check notice

Code scanning / CodeQL

Missing Override annotation Note

This method overrides
FieldDescription.getFieldModifier
; it is advisable to add an Override annotation.
Opencmw-java and opencmw-cpp used different metadata entries for the
field descriptions. While opencmw-cpp serialised [description(string),
unit(string), modifier(byte/enum)], opencmw-java used
[description(string), unit(string), direction(string),
groups(string[])].
This lead to failures in deserialising c++ serialised field medatadata.

These changes make opencmw-java use the same format as c++.

Signed-off-by: Alexander Krimm <A.Krimm@gsi.de>
Signed-off-by: Alexander Krimm <A.Krimm@gsi.de>
To run the tests locally, copy the Compatibility test executable from
opencmw-cpp to the repository root.
The CI will fetch it from the artifact of opencmw-cpp.
If it is not available, the tests will be skipped.

Signed-off-by: Alexander Krimm <A.Krimm@gsi.de>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants