diff --git a/ros2rag.base/src/main/jastadd/Navigation.jrag b/ros2rag.base/src/main/jastadd/Navigation.jrag index ce2029496eebf41a537d8f72554e8ddb2021a675..49b86d0e08ba75d817cf2e53255f8ae0c2ae9edf 100644 --- a/ros2rag.base/src/main/jastadd/Navigation.jrag +++ b/ros2rag.base/src/main/jastadd/Navigation.jrag @@ -15,6 +15,10 @@ aspect Navigation { syn boolean Component.isTypeComponent() = false; eq TypeComponent.isTypeComponent() = true; + // --- asTypeComponent (should be in preprocessor) --- + syn TypeComponent Component.asTypeComponent() = null; + eq TypeComponent.asTypeComponent() = this; + // --- isWriteToMqttDefinition --- syn boolean UpdateDefinition.isWriteToMqttDefinition() = false; eq WriteToMqttDefinition.isWriteToMqttDefinition() = true; @@ -38,4 +42,10 @@ aspect Navigation { // --- isDefaultMappingDefinition --- syn boolean MappingDefinition.isDefaultMappingDefinition() = false; eq DefaultMappingDefinition.isDefaultMappingDefinition() = true; + + // --- allTokenComponents --- + coll java.util.Set<TokenComponent> Program.allTokenComponents() [new java.util.HashSet<>()] root Program; + TokenComponent contributes this + to Program.allTokenComponents() + for program(); } diff --git a/ros2rag.base/src/main/jastadd/backend/Generation.jadd b/ros2rag.base/src/main/jastadd/backend/Generation.jadd index 7a134eceef421988a9de954ffa86c3778a891069..82c1ae0fb08f342d296bb3395dfa86499c282a55 100644 --- a/ros2rag.base/src/main/jastadd/backend/Generation.jadd +++ b/ros2rag.base/src/main/jastadd/backend/Generation.jadd @@ -101,6 +101,9 @@ aspect AspectGeneration { for (DependencyDefinition def : getDependencyDefinitionList()) { def.generateAspect(sb); } + for (TokenComponent token : getProgram().allTokenComponents()) { + token.generateAspect(sb); + } sb.append("}\n"); } @@ -235,27 +238,40 @@ aspect AspectGeneration { .append(dependencyMethod()).append("(").append(sourceParentTypeName).append(" source) {\n"); sb.append(ind(2)).append("add").append(internalRelationPrefix()).append("Source(source);\n"); sb.append(ind(1)).append("}\n\n"); + } + + void TokenComponent.generateAspect(StringBuilder sb) { + if (getDependencySourceDefinitionList().isEmpty()) { return; } + String parentTypeName = containingTypeDecl().getName(); // virtual setter - sb.append(ind(1)).append("public ").append(sourceParentTypeName).append(" ") - .append(sourceParentTypeName).append(".set").append(getSource().getName()).append("("); - getSource().getJavaTypeUse().generateAbstractGrammar(sb); + sb.append(ind(1)).append("public ").append(parentTypeName).append(" ") + .append(parentTypeName).append(".set").append(getName()).append("("); + getJavaTypeUse().generateAbstractGrammar(sb); sb.append(" value) {\n"); - sb.append(ind(2)).append("set").append(internalTokenName()).append("(value);\n"); - sb.append(ind(2)).append("for (").append(targetParentTypeName).append(" target : get") - .append(internalRelationPrefix()).append("TargetList()) {\n"); - sb.append(ind(3)).append("if (target.").append(targetUpdateDefinition().updateMethod()).append("()) {\n"); - sb.append(ind(4)).append("target.").append(targetUpdateDefinition().writeMethod()).append("();\n"); - sb.append(ind(3)).append("}\n"); - sb.append(ind(2)).append("}\n"); + sb.append(ind(2)).append("set").append(internalName()).append("(value);\n"); + + for (DependencyDefinition dependencyDefinition : getDependencySourceDefinitionList()) { + String targetParentTypeName = dependencyDefinition.getTarget().containingTypeDecl().getName(); + sb.append(ind(2)).append("for (").append(targetParentTypeName).append(" target : get") + .append(dependencyDefinition.internalRelationPrefix()).append("TargetList()) {\n"); + sb.append(ind(3)).append("if (target.") + .append(dependencyDefinition.targetUpdateDefinition().updateMethod()) + .append("()) {\n"); + sb.append(ind(4)).append("target.") + .append(dependencyDefinition.targetUpdateDefinition().writeMethod()) + .append("();\n"); + sb.append(ind(3)).append("}\n"); + sb.append(ind(2)).append("}\n"); + } sb.append(ind(2)).append("return this;\n"); sb.append(ind(1)).append("}\n\n"); // virtual getter sb.append(ind(1)).append("public "); - getSource().getJavaTypeUse().generateAbstractGrammar(sb); - sb.append(" ").append(sourceParentTypeName).append(".get").append(getSource().getName()).append("() {\n"); - sb.append(ind(2)).append("return get").append(internalTokenName()).append("();\n"); + getJavaTypeUse().generateAbstractGrammar(sb); + sb.append(" ").append(parentTypeName).append(".get").append(getName()).append("() {\n"); + sb.append(ind(2)).append("return get").append(internalName()).append("();\n"); sb.append(ind(1)).append("}\n\n"); } } diff --git a/ros2rag.tests/build.gradle b/ros2rag.tests/build.gradle index aacd38d9fa69572ce03b2b45b0baa8927f416adb..7561d38d8b2fc37740be070ce5f31559f36d08f1 100644 --- a/ros2rag.tests/build.gradle +++ b/ros2rag.tests/build.gradle @@ -73,7 +73,6 @@ task preprocessExampleTest(type: JavaExec, group: 'verification') { } task compileExampleTest(type: RelastTest) { - verbose = true useJastAddNames = true jastAddList = 'JastAddList' relastFiles 'src/test/02-after-ros2rag/example/Grammar.relast' @@ -106,7 +105,6 @@ task preprocessDefaultOnlyReadTest(type: JavaExec, group: 'verification') { } task compileDefaultOnlyReadTest(type: RelastTest) { - verbose = true useJastAddNames = true jastAddList = 'JastAddList' relastFiles 'src/test/02-after-ros2rag/defaultOnlyRead/Grammar.relast' @@ -119,6 +117,38 @@ task compileDefaultOnlyReadTest(type: RelastTest) { test.dependsOn compileDefaultOnlyReadTest compileDefaultOnlyReadTest.dependsOn preprocessDefaultOnlyReadTest +// --- Test: default-only-write --- +task preprocessDefaultOnlyWriteTest(type: JavaExec, group: 'verification') { + doFirst { + delete 'src/test/02-after-ros2rag/defaultOnlyWrite/Grammar.relast', + 'src/test/02-after-ros2rag/defaultOnlyWrite/MqttUpdater.java', + 'src/test/02-after-ros2rag/defaultOnlyWrite/ROS2RAG.jadd' + } + + classpath = sourceSets.main.runtimeClasspath + main = 'org.jastadd.ros2rag.compiler.Compiler' + //noinspection GroovyAssignabilityCheck + args '--outputDir=src/test/02-after-ros2rag/defaultOnlyWrite', + '--inputGrammar=src/test/01-input/defaultOnlyWrite/Example.relast', + '--inputRos2Rag=src/test/01-input/defaultOnlyWrite/Example.ros2rag', + '--rootNode=A', + '--verbose' +} + +task compileDefaultOnlyWriteTest(type: RelastTest) { + useJastAddNames = true + jastAddList = 'JastAddList' + relastFiles 'src/test/02-after-ros2rag/defaultOnlyWrite/Grammar.relast' + grammarName = 'src/test/03-after-relast/defaultOnlyWrite/defaultOnlyWrite' + packageName = 'defaultOnlyWrite.ast' + moreInputFiles 'src/test/01-input/defaultOnlyWrite/Example.jadd', + 'src/test/02-after-ros2rag/defaultOnlyWrite/MqttUpdater.jadd', + 'src/test/02-after-ros2rag/defaultOnlyWrite/ROS2RAG.jadd' +} + +test.dependsOn compileDefaultOnlyWriteTest +compileDefaultOnlyWriteTest.dependsOn preprocessDefaultOnlyWriteTest + clean { delete 'src/test/02-after-ros2rag/*/', 'src/test/03-after-relast/*/' } diff --git a/ros2rag.tests/src/test/01-input/defaultOnlyRead/README.md b/ros2rag.tests/src/test/01-input/defaultOnlyRead/README.md new file mode 100644 index 0000000000000000000000000000000000000000..ee05db648e9204945245cd42ad8d802d2cdab887 --- /dev/null +++ b/ros2rag.tests/src/test/01-input/defaultOnlyRead/README.md @@ -0,0 +1,3 @@ +# Default Only Read + +Idea: Use only `ReadFromMqttDefinition`, test all default mapping definitions from `byte[]` to primitive (and boxed) types diff --git a/ros2rag.tests/src/test/01-input/defaultOnlyWrite/Example.jadd b/ros2rag.tests/src/test/01-input/defaultOnlyWrite/Example.jadd new file mode 100644 index 0000000000000000000000000000000000000000..49bbf604d398f7a9d92e879b2b515c9e83dd3182 --- /dev/null +++ b/ros2rag.tests/src/test/01-input/defaultOnlyWrite/Example.jadd @@ -0,0 +1,49 @@ +aspect Computation { + // native types, synthesized + syn int NativeTypesSyn.getIntValue() = Integer.parseInt(getDriverSyn()); + syn short NativeTypesSyn.getShortValue() = Short.parseShort(getDriverSyn()); + syn long NativeTypesSyn.getLongValue() = Long.parseLong(getDriverSyn()); + syn float NativeTypesSyn.getFloatValue() = Float.parseFloat(getDriverSyn()); + syn double NativeTypesSyn.getDoubleValue() = Double.parseDouble(getDriverSyn()); + syn char NativeTypesSyn.getCharValue() = getDriverSyn().charAt(0); + syn String NativeTypesSyn.getStringValue() = new String(getDriverSyn()); + + // boxed types, synthesized + syn Integer BoxedTypesSyn.getIntValue() = Integer.valueOf(getDriverSyn()); + syn Short BoxedTypesSyn.getShortValue() = Short.valueOf(getDriverSyn()); + syn Long BoxedTypesSyn.getLongValue() = Long.valueOf(getDriverSyn()); + syn Float BoxedTypesSyn.getFloatValue() = Float.valueOf(getDriverSyn()); + syn Double BoxedTypesSyn.getDoubleValue() = Double.valueOf(getDriverSyn()); + syn Character BoxedTypesSyn.getCharValue() = getDriverSyn().charAt(0); + +// --- inherited attributes not supported --- +// // native types, inherited +// inh int NativeTypesInh.getIntValue(); +// eq A.getNativeTypesInh().getIntValue() = Integer.parseInt(getDriverInh()); +// inh short NativeTypesInh.getShortValue(); +// eq A.getNativeTypesInh().getShortValue() = Short.parseShort(getDriverInh()); +// inh long NativeTypesInh.getLongValue(); +// eq A.getNativeTypesInh().getLongValue() = Long.parseLong(getDriverInh()); +// inh float NativeTypesInh.getFloatValue(); +// eq A.getNativeTypesInh().getFloatValue() = Float.parseFloat(getDriverInh()); +// inh double NativeTypesInh.getDoubleValue(); +// eq A.getNativeTypesInh().getDoubleValue() = Double.parseDouble(getDriverInh()); +// inh char NativeTypesInh.getCharValue(); +// eq A.getNativeTypesInh().getCharValue() = getDriverInh().charAt(0); +// inh String NativeTypesInh.getStringValue(); +// eq A.getNativeTypesInh().getStringValue() = new String(getDriverInh()); +// +// // boxed types, inherited +// inh Integer BoxedTypesInh.getIntValue(); +// eq A.getBoxedTypesInh().getIntValue() = Integer.valueOf(getDriverInh()); +// inh Short BoxedTypesInh.getShortValue(); +// eq A.getBoxedTypesInh().getShortValue() = Short.valueOf(getDriverInh()); +// inh Long BoxedTypesInh.getLongValue(); +// eq A.getBoxedTypesInh().getLongValue() = Long.valueOf(getDriverInh()); +// inh Float BoxedTypesInh.getFloatValue(); +// eq A.getBoxedTypesInh().getFloatValue() = Float.valueOf(getDriverInh()); +// inh Double BoxedTypesInh.getDoubleValue(); +// eq A.getBoxedTypesInh().getDoubleValue() = Double.valueOf(getDriverInh()); +// inh Character BoxedTypesInh.getCharValue(); +// eq A.getBoxedTypesInh().getCharValue() = getDriverInh().charAt(0); +} diff --git a/ros2rag.tests/src/test/01-input/defaultOnlyWrite/Example.relast b/ros2rag.tests/src/test/01-input/defaultOnlyWrite/Example.relast new file mode 100644 index 0000000000000000000000000000000000000000..e0fd7829b88b8fac04b64393e0262c69b4ac6a62 --- /dev/null +++ b/ros2rag.tests/src/test/01-input/defaultOnlyWrite/Example.relast @@ -0,0 +1,11 @@ +A ::= NativeTypesSyn* BoxedTypesSyn* <DriverInh:String>; +// native types, synthesized +NativeTypesSyn ::= <DriverSyn:String> /<IntValue:int>/ /<ShortValue:short>/ /<LongValue:long>/ /<FloatValue:float>/ /<DoubleValue:double>/ /<CharValue:char>/ /<StringValue:String>/ ; +// boxed types, synthesized +BoxedTypesSyn ::= <DriverSyn:String> /<IntValue:Integer>/ /<ShortValue:Short>/ /<LongValue:Long>/ /<FloatValue:Float>/ /<DoubleValue:Double>/ /<CharValue:Character>/ ; + +// --- inherited attributes not supported --- +//// native types, inherited +//NativeTypesInh ::= /<IntValue:int>/ /<ShortValue:short>/ /<LongValue:long>/ /<FloatValue:float>/ /<DoubleValue:double>/ /<CharValue:char>/ /<StringValue:String>/ ; +//// boxed types, inherited +//BoxedTypesInh ::= /<IntValue:Integer>/ /<ShortValue:Short>/ /<LongValue:Long>/ /<FloatValue:Float>/ /<DoubleValue:Double>/ /<CharValue:Character>/ ; diff --git a/ros2rag.tests/src/test/01-input/defaultOnlyWrite/Example.ros2rag b/ros2rag.tests/src/test/01-input/defaultOnlyWrite/Example.ros2rag new file mode 100644 index 0000000000000000000000000000000000000000..924cbe1732be63b1c75c05c75a86cd531fc0525d --- /dev/null +++ b/ros2rag.tests/src/test/01-input/defaultOnlyWrite/Example.ros2rag @@ -0,0 +1,51 @@ +// --- update definitions --- +// native types, synthesized +write NativeTypesSyn.IntValue; +write NativeTypesSyn.ShortValue; +write NativeTypesSyn.LongValue; +write NativeTypesSyn.FloatValue; +write NativeTypesSyn.DoubleValue; +write NativeTypesSyn.CharValue; +write NativeTypesSyn.StringValue; + +// boxed types, synthesized +write BoxedTypesSyn.IntValue; +write BoxedTypesSyn.ShortValue; +write BoxedTypesSyn.LongValue; +write BoxedTypesSyn.FloatValue; +write BoxedTypesSyn.DoubleValue; +write BoxedTypesSyn.CharValue; + +// --- dependency definitions --- +NativeTypesSyn.IntValue canDependOn NativeTypesSyn.DriverSyn as nativeIntDependency; +NativeTypesSyn.ShortValue canDependOn NativeTypesSyn.DriverSyn as nativeShortDependency; +NativeTypesSyn.LongValue canDependOn NativeTypesSyn.DriverSyn as nativeLongDependency; +NativeTypesSyn.FloatValue canDependOn NativeTypesSyn.DriverSyn as nativeFloatDependency; +NativeTypesSyn.DoubleValue canDependOn NativeTypesSyn.DriverSyn as nativeDoubleDependency; +NativeTypesSyn.CharValue canDependOn NativeTypesSyn.DriverSyn as nativeCharDependency; +NativeTypesSyn.StringValue canDependOn NativeTypesSyn.DriverSyn as nativeStringDependency; +BoxedTypesSyn.IntValue canDependOn BoxedTypesSyn.DriverSyn as boxedIntDependency; +BoxedTypesSyn.ShortValue canDependOn BoxedTypesSyn.DriverSyn as boxedShortDependency; +BoxedTypesSyn.LongValue canDependOn BoxedTypesSyn.DriverSyn as boxedLongDependency; +BoxedTypesSyn.FloatValue canDependOn BoxedTypesSyn.DriverSyn as boxedFloatDependency; +BoxedTypesSyn.DoubleValue canDependOn BoxedTypesSyn.DriverSyn as boxedDoubleDependency; +BoxedTypesSyn.CharValue canDependOn BoxedTypesSyn.DriverSyn as boxedCharDependency; + + +// --- inherited attributes not supported --- +//// native types, inherited +//write NativeTypesInh.IntValue; +//write NativeTypesInh.ShortValue; +//write NativeTypesInh.LongValue; +//write NativeTypesInh.FloatValue; +//write NativeTypesInh.DoubleValue; +//write NativeTypesInh.CharValue; +//write NativeTypesInh.StringValue; +// +//// boxed types, inherited +//write BoxedTypesInh.IntValue; +//write BoxedTypesInh.ShortValue; +//write BoxedTypesInh.LongValue; +//write BoxedTypesInh.FloatValue; +//write BoxedTypesInh.DoubleValue; +//write BoxedTypesInh.CharValue; diff --git a/ros2rag.tests/src/test/01-input/defaultOnlyWrite/README.md b/ros2rag.tests/src/test/01-input/defaultOnlyWrite/README.md new file mode 100644 index 0000000000000000000000000000000000000000..1bcc8d61a7854b7f9ef4bc1694f4f81caaac2aed --- /dev/null +++ b/ros2rag.tests/src/test/01-input/defaultOnlyWrite/README.md @@ -0,0 +1,3 @@ +# Default Only Write + +Idea: Use only `WriteToMqttDefintion`, test all default mapping definitions from primitive (and boxed) types to `byte[]`. diff --git a/ros2rag.tests/src/test/01-input/example/README.md b/ros2rag.tests/src/test/01-input/example/README.md new file mode 100644 index 0000000000000000000000000000000000000000..7665b437a513602587474904ef08135efee13b44 --- /dev/null +++ b/ros2rag.tests/src/test/01-input/example/README.md @@ -0,0 +1,3 @@ +# Example + +Idea: Use the motivating example from our paper as a test case, including one read, one write update definition diff --git a/ros2rag.tests/src/test/java/org/jastadd/ros2rag/tests/DefaultOnlyWriteTest.java b/ros2rag.tests/src/test/java/org/jastadd/ros2rag/tests/DefaultOnlyWriteTest.java new file mode 100644 index 0000000000000000000000000000000000000000..d3225495b9cce550db8991c7720c03f26b426fd5 --- /dev/null +++ b/ros2rag.tests/src/test/java/org/jastadd/ros2rag/tests/DefaultOnlyWriteTest.java @@ -0,0 +1,319 @@ +package org.jastadd.ros2rag.tests; + +import defaultOnlyWrite.ast.A; +import defaultOnlyWrite.ast.BoxedTypesSyn; +import defaultOnlyWrite.ast.MqttUpdater; +import defaultOnlyWrite.ast.NativeTypesSyn; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.Test; + +import java.io.IOException; +import java.util.concurrent.TimeUnit; + +import static org.junit.Assert.*; + +/** + * Test case "defaultOnlyRead". + * + * @author rschoene - Initial contribution + */ +public class DefaultOnlyWriteTest { + + private static final String TOPIC_NATIVE_INT = "native/int"; + private static final String TOPIC_NATIVE_SHORT = "native/short"; + private static final String TOPIC_NATIVE_LONG = "native/long"; + private static final String TOPIC_NATIVE_FLOAT = "native/float"; + private static final String TOPIC_NATIVE_DOUBLE = "native/double"; + private static final String TOPIC_NATIVE_CHAR = "native/char"; + private static final String TOPIC_NATIVE_STRING = "native/string"; + + private static final String TOPIC_BOXED_INTEGER = "boxed/Integer"; + private static final String TOPIC_BOXED_SHORT = "boxed/Short"; + private static final String TOPIC_BOXED_LONG = "boxed/Long"; + private static final String TOPIC_BOXED_FLOAT = "boxed/Float"; + private static final String TOPIC_BOXED_DOUBLE = "boxed/Double"; + private static final String TOPIC_BOXED_CHARACTER = "boxed/Character"; + + private A model; + private NativeTypesSyn nativeIntegers; + private NativeTypesSyn nativeFloats; + private NativeTypesSyn nativeChars; + private BoxedTypesSyn boxedIntegers; + private BoxedTypesSyn boxedFloats; + private BoxedTypesSyn boxedChars; + private MqttUpdater receiver; + private ReceiverData data; + + @AfterEach + public void closeConnections() { + if (receiver != null) { + receiver.close(); + } + if (model != null) { + model.MqttCloseConnections(); + } + } + + + @Test + public void buildModel() { + createModel(); + } + + @Test + public void communicateSendInitialValue() throws IOException, InterruptedException { + createModel(); + setData("1", "1.1", "ab"); + setupReceiverAndConnect(true); + + // check initial value + TimeUnit.SECONDS.sleep(2); + checkData(1, 1, 1.1, 'a', "ab"); + + // set new value + setData("2", "2.2", "cd"); + + // check new value + TimeUnit.SECONDS.sleep(2); + checkData(2, 2, 2.2, 'c', "cd"); + + // set new value + setData("3", "3.2", "ee"); + + // check new value + TimeUnit.SECONDS.sleep(2); + checkData(3, 3, 3.2, 'e', "ee"); + } + + @Test + public void communicateOnlyUpdatedValue() throws IOException, InterruptedException { + createModel(); + setData("1", "1.1", "ab"); + setupReceiverAndConnect(false); + + // check initial value (will be default values) + TimeUnit.SECONDS.sleep(2); + checkData(0, null, null, null, null); + + // set new value + setData("2", "2.2", "cd"); + + // check new value + TimeUnit.SECONDS.sleep(2); + checkData(1, 2, 2.2, 'c', "cd"); + + // set new value + setData("3", "3.2", "ee"); + + // check new value + TimeUnit.SECONDS.sleep(2); + checkData(2, 3, 3.2, 'e', "ee"); + } + + private void createModel() { + model = new A(); + + nativeIntegers = new NativeTypesSyn(); + nativeFloats = new NativeTypesSyn(); + nativeChars = new NativeTypesSyn(); + model.addNativeTypesSyn(nativeIntegers); + model.addNativeTypesSyn(nativeFloats); + model.addNativeTypesSyn(nativeChars); + + boxedIntegers = new BoxedTypesSyn(); + boxedFloats = new BoxedTypesSyn(); + boxedChars = new BoxedTypesSyn(); + model.addBoxedTypesSyn(boxedIntegers); + model.addBoxedTypesSyn(boxedFloats); + model.addBoxedTypesSyn(boxedChars); + } + + private void setupReceiverAndConnect(boolean writeCurrentValue) throws IOException { + model.MqttSetHost(TestUtils.getMqttHost()); + assertTrue(model.MqttWaitUntilReady(2, TimeUnit.SECONDS)); + + receiver = new MqttUpdater().dontSendWelcomeMessage().setHost(TestUtils.getMqttHost()); + assertTrue(receiver.waitUntilReady(2, TimeUnit.SECONDS)); + + nativeIntegers.addNativeIntDependency(nativeIntegers); + nativeIntegers.addNativeShortDependency(nativeIntegers); + nativeIntegers.addNativeLongDependency(nativeIntegers); + nativeFloats.addNativeFloatDependency(nativeFloats); + nativeFloats.addNativeDoubleDependency(nativeFloats); + nativeChars.addNativeCharDependency(nativeChars); + nativeChars.addNativeStringDependency(nativeChars); + + boxedIntegers.addBoxedIntDependency(boxedIntegers); + boxedIntegers.addBoxedShortDependency(boxedIntegers); + boxedIntegers.addBoxedLongDependency(boxedIntegers); + boxedFloats.addBoxedFloatDependency(boxedFloats); + boxedFloats.addBoxedDoubleDependency(boxedFloats); + boxedChars.addBoxedCharDependency(boxedChars); + + data = new ReceiverData(); + + receiver.newConnection(TOPIC_NATIVE_INT, bytes -> { + data.numberOfNativeIntValues += 1; + data.lastNativeIntValue = java.nio.ByteBuffer.wrap(bytes).getInt(); + }); + receiver.newConnection(TOPIC_NATIVE_SHORT, bytes -> { + data.numberOfNativeShortValues += 1; + data.lastNativeShortValue = java.nio.ByteBuffer.wrap(bytes).getShort(); + }); + receiver.newConnection(TOPIC_NATIVE_LONG, bytes -> { + data.numberOfNativeLongValues += 1; + data.lastNativeLongValue = java.nio.ByteBuffer.wrap(bytes).getLong(); + }); + receiver.newConnection(TOPIC_NATIVE_FLOAT, bytes -> { + data.numberOfNativeFloatValues += 1; + data.lastNativeFloatValue = java.nio.ByteBuffer.wrap(bytes).getFloat(); + }); + receiver.newConnection(TOPIC_NATIVE_DOUBLE, bytes -> { + data.numberOfNativeDoubleValues += 1; + data.lastNativeDoubleValue = java.nio.ByteBuffer.wrap(bytes).getDouble(); + }); + receiver.newConnection(TOPIC_NATIVE_CHAR, bytes -> { + data.numberOfNativeCharValues += 1; + data.lastNativeCharValue = java.nio.ByteBuffer.wrap(bytes).getChar(); + }); + receiver.newConnection(TOPIC_NATIVE_STRING, bytes -> { + data.numberOfNativeStringValues += 1; + data.lastNativeStringValue = new String(bytes); + }); + receiver.newConnection(TOPIC_BOXED_INTEGER, bytes -> { + data.numberOfBoxedIntValues += 1; + data.lastBoxedIntValue = java.nio.ByteBuffer.wrap(bytes).getInt(); + }); + receiver.newConnection(TOPIC_BOXED_SHORT, bytes -> { + data.numberOfBoxedShortValues += 1; + data.lastBoxedShortValue = java.nio.ByteBuffer.wrap(bytes).getShort(); + }); + receiver.newConnection(TOPIC_BOXED_LONG, bytes -> { + data.numberOfBoxedLongValues += 1; + data.lastBoxedLongValue = java.nio.ByteBuffer.wrap(bytes).getLong(); + }); + receiver.newConnection(TOPIC_BOXED_FLOAT, bytes -> { + data.numberOfBoxedFloatValues += 1; + data.lastBoxedFloatValue = java.nio.ByteBuffer.wrap(bytes).getFloat(); + }); + receiver.newConnection(TOPIC_BOXED_DOUBLE, bytes -> { + data.numberOfBoxedDoubleValues += 1; + data.lastBoxedDoubleValue = java.nio.ByteBuffer.wrap(bytes).getDouble(); + }); + receiver.newConnection(TOPIC_BOXED_CHARACTER, bytes -> { + data.numberOfBoxedCharValues += 1; + data.lastBoxedCharValue = java.nio.ByteBuffer.wrap(bytes).getChar(); + }); + + nativeIntegers.connectIntValue(TOPIC_NATIVE_INT, writeCurrentValue); + nativeIntegers.connectShortValue(TOPIC_NATIVE_SHORT, writeCurrentValue); + nativeIntegers.connectLongValue(TOPIC_NATIVE_LONG, writeCurrentValue); + nativeFloats.connectFloatValue(TOPIC_NATIVE_FLOAT, writeCurrentValue); + nativeFloats.connectDoubleValue(TOPIC_NATIVE_DOUBLE, writeCurrentValue); + nativeChars.connectCharValue(TOPIC_NATIVE_CHAR, writeCurrentValue); + nativeChars.connectStringValue(TOPIC_NATIVE_STRING, writeCurrentValue); + boxedIntegers.connectIntValue(TOPIC_BOXED_INTEGER, writeCurrentValue); + boxedIntegers.connectShortValue(TOPIC_BOXED_SHORT, writeCurrentValue); + boxedIntegers.connectLongValue(TOPIC_BOXED_LONG, writeCurrentValue); + boxedFloats.connectFloatValue(TOPIC_BOXED_FLOAT, writeCurrentValue); + boxedFloats.connectDoubleValue(TOPIC_BOXED_DOUBLE, writeCurrentValue); + boxedChars.connectCharValue(TOPIC_BOXED_CHARACTER, writeCurrentValue); + } + + private void setData(String integerDriver, String floatDriver, String stringDriver) { + nativeIntegers.setDriverSyn(integerDriver); + nativeFloats.setDriverSyn(floatDriver); + nativeChars.setDriverSyn(stringDriver); + + boxedIntegers.setDriverSyn(integerDriver); + boxedFloats.setDriverSyn(floatDriver); + boxedChars.setDriverSyn(stringDriver); + } + + private void checkData(int expectedNumberOfValues, + Integer expectedInt, Double expectedDouble, + Character expectedChar, String expectedString) { + assertEquals(expectedNumberOfValues, data.numberOfNativeIntValues); + assertEquals(expectedNumberOfValues, data.numberOfNativeShortValues); + assertEquals(expectedNumberOfValues, data.numberOfNativeLongValues); + assertEquals(expectedNumberOfValues, data.numberOfNativeFloatValues); + assertEquals(expectedNumberOfValues, data.numberOfNativeDoubleValues); + assertEquals(expectedNumberOfValues, data.numberOfNativeCharValues); + assertEquals(expectedNumberOfValues, data.numberOfNativeStringValues); + + assertEquals(expectedNumberOfValues, data.numberOfBoxedIntValues); + assertEquals(expectedNumberOfValues, data.numberOfBoxedShortValues); + assertEquals(expectedNumberOfValues, data.numberOfBoxedLongValues); + assertEquals(expectedNumberOfValues, data.numberOfBoxedFloatValues); + assertEquals(expectedNumberOfValues, data.numberOfBoxedDoubleValues); + assertEquals(expectedNumberOfValues, data.numberOfBoxedCharValues); + + if (expectedInt != null) { + assertEquals(expectedInt.intValue(), data.lastNativeIntValue); + assertEquals(expectedInt.shortValue(), data.lastNativeShortValue); + assertEquals(expectedInt.longValue(), data.lastNativeLongValue); + assertEquals(expectedInt.intValue(), data.lastBoxedIntValue.intValue()); + assertEquals(expectedInt.shortValue(), data.lastBoxedShortValue.shortValue()); + assertEquals(expectedInt.longValue(), data.lastBoxedLongValue.longValue()); + } else { + assertEquals(0, data.lastNativeIntValue); + assertEquals(0, data.lastNativeShortValue); + assertEquals(0, data.lastNativeLongValue); + assertNull(data.lastBoxedIntValue); + assertNull(data.lastBoxedShortValue); + assertNull(data.lastBoxedLongValue); + } + + if (expectedDouble != null) { + assertEquals(expectedDouble.floatValue(), data.lastNativeFloatValue, TestUtils.DELTA); + assertEquals(expectedDouble, data.lastNativeDoubleValue, TestUtils.DELTA); + assertEquals(expectedDouble.floatValue(), data.lastBoxedFloatValue, TestUtils.DELTA); + assertEquals(expectedDouble, data.lastBoxedDoubleValue, TestUtils.DELTA); + } else { + assertEquals(0f, data.lastNativeFloatValue, TestUtils.DELTA); + assertEquals(0d, data.lastNativeDoubleValue, TestUtils.DELTA); + assertNull(data.lastBoxedFloatValue); + assertNull(data.lastBoxedDoubleValue); + } + + if (expectedChar != null) { + assertEquals(expectedChar.charValue(), data.lastNativeCharValue); + assertEquals(expectedChar, data.lastBoxedCharValue); + } else { + assertEquals('\0', data.lastNativeCharValue); + assertNull(data.lastBoxedCharValue); + } + assertEquals(expectedString, data.lastNativeStringValue); + } + + private static class ReceiverData { + int lastNativeIntValue; + int numberOfNativeIntValues = 0; + short lastNativeShortValue; + int numberOfNativeShortValues = 0; + long lastNativeLongValue; + int numberOfNativeLongValues = 0; + float lastNativeFloatValue; + int numberOfNativeFloatValues = 0; + double lastNativeDoubleValue; + int numberOfNativeDoubleValues = 0; + char lastNativeCharValue; + int numberOfNativeCharValues = 0; + String lastNativeStringValue; + int numberOfNativeStringValues = 0; + + Integer lastBoxedIntValue; + int numberOfBoxedIntValues = 0; + Short lastBoxedShortValue; + int numberOfBoxedShortValues = 0; + Long lastBoxedLongValue; + int numberOfBoxedLongValues = 0; + Float lastBoxedFloatValue; + int numberOfBoxedFloatValues = 0; + Double lastBoxedDoubleValue; + int numberOfBoxedDoubleValues = 0; + Character lastBoxedCharValue; + int numberOfBoxedCharValues = 0; + } + +}