Commit 07e46089 authored by René Schöne's avatar René Schöne
Browse files

Integrated default mapping definitions.

- supported types: int, short, long, float, double, char, and all their boxed variants, and String
- default mapping definitions are NTAs which get reused for every update definition that needs them
- change generated check for not always apply (case for boxed types)
- cleanup parser
parent 16a5550d
Pipeline #6816 passed with stage
in 2 minutes and 32 seconds
......@@ -4,8 +4,9 @@ aspect Analysis {
syn boolean JavaTypeUse.isPrimitiveType() = false;
eq SimpleJavaTypeUse.isPrimitiveType() {
switch(getName()) {
case "short":
case "int":
case "short":
case "long":
case "float":
case "double":
case "char":
......
......@@ -34,4 +34,8 @@ aspect Navigation {
}
return null;
}
// --- isDefaultMappingDefinition ---
syn boolean MappingDefinition.isDefaultMappingDefinition() = false;
eq DefaultMappingDefinition.isDefaultMappingDefinition() = true;
}
......@@ -95,7 +95,7 @@ aspect AspectGeneration {
for (UpdateDefinition def : getUpdateDefinitionList()) {
def.generateAspect(sb);
}
for (MappingDefinition def : getMappingDefinitionList()) {
for (MappingDefinition def : allMappingDefinitions()) {
def.generateAspect(sb);
}
for (DependencyDefinition def : getDependencyDefinitionList()) {
......@@ -112,11 +112,11 @@ aspect AspectGeneration {
final String resultVariablePrefix = "result"; // we do not need "_" here, because methodName begins with one
String inputVariableName = initialInputVariableName;
// last variable need to be declared before begin of try
MappingDefinition lastDefinition = getMappingList().get(getMappingList().size() - 1);
MappingDefinition lastDefinition = effectiveMappings().get(effectiveMappings().size() - 1);
sb.append(ind(indent)).append(lastDefinition.getToType().prettyPrint()).append(" ")
.append(resultVariablePrefix).append(lastDefinition.methodName()).append(";\n");
sb.append(ind(indent)).append("try {\n");
for (MappingDefinition mappingDefinition : getMappingList()) {
for (MappingDefinition mappingDefinition : effectiveMappings()) {
String resultVariableName = resultVariablePrefix + mappingDefinition.methodName();
sb.append(ind(indent + 1));
if (mappingDefinition != lastDefinition) {
......@@ -135,6 +135,9 @@ aspect AspectGeneration {
sb.append(ind(indent)).append("if (").append(preemptiveExpectedValue());
if (getToken().isPrimitiveType()) {
sb.append(" == ").append(inputVariableName);
} else if (effectiveMappings().get(effectiveMappings().size() - 1).isDefaultMappingDefinition()) {
sb.append(" != null && ").append(preemptiveExpectedValue()).append(".equals(")
.append(inputVariableName).append(")");
} else {
sb.append(" != null ? ").append(preemptiveExpectedValue()).append(".equals(")
.append(inputVariableName).append(")").append(" : ")
......
aspect DefaultMappings {
private DefaultMappingDefinition Ros2Rag.baseDefaultMappingDefinitionFromBytes(String typeName) {
DefaultMappingDefinition result = new DefaultMappingDefinition();
result.setID("_DefaultBytesTo" + Character.toUpperCase(typeName.charAt(0)) + typeName.substring(1) + "Mapping");
result.setFromType(new JavaArrayMappingDefinitionType(new SimpleJavaTypeUse("byte")));
result.setFromVariableName("bytes");
result.setToType(new JavaMappingDefinitionType(new SimpleJavaTypeUse(typeName)));
return result;
}
private DefaultMappingDefinition Ros2Rag.baseDefaultMappingDefinitionToBytes(String typeName) {
DefaultMappingDefinition result = new DefaultMappingDefinition();
result.setID("_Default" + Character.toUpperCase(typeName.charAt(0)) + typeName.substring(1) + "ToBytesMapping");
result.setFromType(new JavaMappingDefinitionType(new SimpleJavaTypeUse(typeName)));
result.setFromVariableName("input");
result.setToType(new JavaArrayMappingDefinitionType(new SimpleJavaTypeUse("byte")));
return result;
}
syn nta DefaultMappingDefinition Ros2Rag.defaultBytesToIntMapping() {
DefaultMappingDefinition result = baseDefaultMappingDefinitionFromBytes("int");
result.setContent("return java.nio.ByteBuffer.wrap(bytes).getInt();");
return result;
}
syn nta DefaultMappingDefinition Ros2Rag.defaultBytesToShortMapping() {
DefaultMappingDefinition result = baseDefaultMappingDefinitionFromBytes("short");
result.setContent("return java.nio.ByteBuffer.wrap(bytes).getShort();");
return result;
}
syn nta DefaultMappingDefinition Ros2Rag.defaultBytesToLongMapping() {
DefaultMappingDefinition result = baseDefaultMappingDefinitionFromBytes("long");
result.setContent("return java.nio.ByteBuffer.wrap(bytes).getLong();");
return result;
}
syn nta DefaultMappingDefinition Ros2Rag.defaultBytesToFloatMapping() {
DefaultMappingDefinition result = baseDefaultMappingDefinitionFromBytes("float");
result.setContent("return java.nio.ByteBuffer.wrap(bytes).getFloat();");
return result;
}
syn nta DefaultMappingDefinition Ros2Rag.defaultBytesToDoubleMapping() {
DefaultMappingDefinition result = baseDefaultMappingDefinitionFromBytes("double");
result.setContent("return java.nio.ByteBuffer.wrap(bytes).getDouble();");
return result;
}
syn nta DefaultMappingDefinition Ros2Rag.defaultBytesToCharMapping() {
DefaultMappingDefinition result = baseDefaultMappingDefinitionFromBytes("char");
result.setContent("return java.nio.ByteBuffer.wrap(bytes).getChar();");
return result;
}
syn nta DefaultMappingDefinition Ros2Rag.defaultBytesToStringMapping() {
DefaultMappingDefinition result = baseDefaultMappingDefinitionFromBytes("String");
result.setContent("return new String(bytes);");
return result;
}
syn nta DefaultMappingDefinition Ros2Rag.defaultIntToBytesMapping() {
DefaultMappingDefinition result = baseDefaultMappingDefinitionToBytes("int");
result.setContent("return java.nio.ByteBuffer.allocate(4).putInt(input).array();");
return result;
}
syn nta DefaultMappingDefinition Ros2Rag.defaultShortToBytesMapping() {
DefaultMappingDefinition result = baseDefaultMappingDefinitionToBytes("short");
result.setContent("return java.nio.ByteBuffer.allocate(2).putShort(input).array();");
return result;
}
syn nta DefaultMappingDefinition Ros2Rag.defaultLongToBytesMapping() {
DefaultMappingDefinition result = baseDefaultMappingDefinitionToBytes("long");
result.setContent("return java.nio.ByteBuffer.allocate(8).putLong(input).array();");
return result;
}
syn nta DefaultMappingDefinition Ros2Rag.defaultFloatToBytesMapping() {
DefaultMappingDefinition result = baseDefaultMappingDefinitionToBytes("float");
result.setContent("return java.nio.ByteBuffer.allocate(4).putFloat(input).array();");
return result;
}
syn nta DefaultMappingDefinition Ros2Rag.defaultDoubleToBytesMapping() {
DefaultMappingDefinition result = baseDefaultMappingDefinitionToBytes("double");
result.setContent("return java.nio.ByteBuffer.allocate(8).putDouble(input).array();");
return result;
}
syn nta DefaultMappingDefinition Ros2Rag.defaultCharToBytesMapping() {
DefaultMappingDefinition result = baseDefaultMappingDefinitionToBytes("char");
result.setContent("return java.nio.ByteBuffer.allocate(2).putChar(input).array();");
return result;
}
syn nta DefaultMappingDefinition Ros2Rag.defaultStringToBytesMapping() {
DefaultMappingDefinition result = baseDefaultMappingDefinitionToBytes("String");
result.setContent("return input.getBytes();");
return result;
}
}
aspect Mappings {
// --- effectiveMappings ---
syn java.util.List<MappingDefinition> UpdateDefinition.effectiveMappings();
eq ReadFromMqttDefinition.effectiveMappings() {
// if there is a first mapping, check if its input type is byte[].
// or if no mappings are specified.
// then prepend the suitable default mapping
java.util.List<MappingDefinition> result;
if (getMappingList().size() == 0 || !getMappingList().get(0).getFromType().isByteArray()) {
result = new java.util.ArrayList();
result.add(suitableDefaultMapping());
result.addAll(getMappingList());
} else {
result = getMappingList();
}
return result;
}
eq WriteToMqttDefinition.effectiveMappings() {
// if there is a mapping, check if the output type of the last mapping is byte[].
// or if no mappings are specified.
// then append the suitable default mapping
java.util.List<MappingDefinition> result;
int numMappings = getMappingList().size();
if (numMappings == 0 || !getMappingList().get(numMappings - 1).getToType().isByteArray()) {
result = new java.util.ArrayList();
result.addAll(getMappingList());
result.add(suitableDefaultMapping());
} else {
result = getMappingList();
}
return result;
}
// --- suitableDefaultMapping ---
syn DefaultMappingDefinition UpdateDefinition.suitableDefaultMapping();
eq ReadFromMqttDefinition.suitableDefaultMapping() {
String typeName = getToken().getJavaTypeUse().getName();
switch(typeName) {
case "int":
case "Integer": return ros2rag().defaultBytesToIntMapping();
case "short":
case "Short": return ros2rag().defaultBytesToShortMapping();
case "long":
case "Long": return ros2rag().defaultBytesToLongMapping();
case "float":
case "Float": return ros2rag().defaultBytesToFloatMapping();
case "double":
case "Double": return ros2rag().defaultBytesToDoubleMapping();
case "char":
case "Character": return ros2rag().defaultBytesToCharMapping();
case "String": return ros2rag().defaultBytesToStringMapping();
default: return null;
}
}
eq WriteToMqttDefinition.suitableDefaultMapping() {
String typeName = getToken().getJavaTypeUse().getName();
switch(typeName) {
case "int":
case "Integer": return ros2rag().defaultIntToBytesMapping();
case "short":
case "Short": return ros2rag().defaultShortToBytesMapping();
case "long":
case "Long": return ros2rag().defaultLongToBytesMapping();
case "float":
case "Float": return ros2rag().defaultFloatToBytesMapping();
case "double":
case "Double": return ros2rag().defaultDoubleToBytesMapping();
case "char":
case "Character": return ros2rag().defaultCharToBytesMapping();
case "String": return ros2rag().defaultStringToBytesMapping();
default: return null;
}
}
// --- isByteArray ---
syn boolean MappingDefinitionType.isByteArray() = false;
eq JavaArrayMappingDefinitionType.isByteArray() = getType().getName().equals("byte");
// --- allMappingDefinitions ---
syn java.util.List<MappingDefinition> Ros2Rag.allMappingDefinitions() {
java.util.List<MappingDefinition> result = new java.util.ArrayList<>();
getMappingDefinitionList().iterator().forEachRemaining(result::add);
result.add(defaultBytesToIntMapping());
result.add(defaultBytesToShortMapping());
result.add(defaultBytesToLongMapping());
result.add(defaultBytesToFloatMapping());
result.add(defaultBytesToDoubleMapping());
result.add(defaultBytesToCharMapping());
result.add(defaultBytesToStringMapping());
result.add(defaultIntToBytesMapping());
result.add(defaultShortToBytesMapping());
result.add(defaultLongToBytesMapping());
result.add(defaultFloatToBytesMapping());
result.add(defaultDoubleToBytesMapping());
result.add(defaultCharToBytesMapping());
result.add(defaultStringToBytesMapping());
return result;
}
}
......@@ -12,8 +12,6 @@ Ros2Rag ros2rag
}
:} ;
// read Joint.CurrentPosition using LinkStateToIntPosition ;
// write RobotArm._AppropriateSpeed using CreateSpeedMessage ;
UpdateDefinition update_definition
= READ ID.type_name DOT ID.token_name SCOL
{:
......@@ -52,7 +50,6 @@ ArrayList string_list
| string_list COMMA ID
;
// RobotArm._AppropriateSpeed canDependOn Joint.CurrentPosition as dependency1 ;
DependencyDefinition dependency_definition
= ID.target_type DOT ID.target_token CAN_DEPEND_ON ID.source_type DOT ID.source_token AS ID.id SCOL
{:
......@@ -64,10 +61,6 @@ DependencyDefinition dependency_definition
:}
;
//LinkStateToIntPosition maps protobuf panda.Linkstate.PandaLinkState x to IntPosition y {
// panda.Linkstate.PandaLinkState.Position p = x.getPos();
// y = IntPosition.of((int) p.getPositionX(), (int) p.getPositionY(), (int) p.getPositionZ());
//}
MappingDefinition mapping_definition
= ID.id MAPS mapping_type.from_type ID.from_name TO mapping_type.to_type MAPPING_CONTENT.content
{:
......
......@@ -54,6 +54,7 @@ protobuf {
}
}
// --- Test: Example ---
task preprocessExampleTest(type: JavaExec, group: 'verification') {
doFirst {
delete 'src/test/02-after-ros2rag/example/Grammar.relast',
......@@ -70,22 +71,6 @@ task preprocessExampleTest(type: JavaExec, group: 'verification') {
'--rootNode=Model'
}
//task compileExampleTest(type: JavaExec, group: 'verification') {
//
// doFirst {
// delete 'src/test/java-gen/example'
// }
//
// classpath = sourceSets.main.runtimeClasspath
// main = 'org.jastadd.JastAdd'
// //noinspection GroovyAssignabilityCheck
// args '--o=src/test/java-gen/', '--package=example.ast',
// 'src/test/jastadd-gen/example/Grammar.relast',
// 'src/test/jastadd-gen/example/MqttUpdater.java',
// 'src/test/jastadd-gen/example/ROS2RAG.jadd',
// 'src/test/jastadd/Example.jadd'
//}
task compileExampleTest(type: RelastTest) {
verbose = true
useJastAddNames = true
......@@ -101,6 +86,38 @@ task compileExampleTest(type: RelastTest) {
test.dependsOn compileExampleTest
compileExampleTest.dependsOn preprocessExampleTest
// --- Test: default-only-read ---
task preprocessDefaultOnlyReadTest(type: JavaExec, group: 'verification') {
doFirst {
delete 'src/test/02-after-ros2rag/defaultOnlyRead/Grammar.relast',
'src/test/02-after-ros2rag/defaultOnlyRead/MqttUpdater.java',
'src/test/02-after-ros2rag/defaultOnlyRead/ROS2RAG.jadd'
}
classpath = sourceSets.main.runtimeClasspath
main = 'org.jastadd.ros2rag.compiler.Compiler'
//noinspection GroovyAssignabilityCheck
args '--outputDir=src/test/02-after-ros2rag/defaultOnlyRead',
'--inputGrammar=src/test/01-input/defaultOnlyRead/Example.relast',
'--inputRos2Rag=src/test/01-input/defaultOnlyRead/Example.ros2rag',
'--rootNode=A',
'--verbose'
}
task compileDefaultOnlyReadTest(type: RelastTest) {
verbose = true
useJastAddNames = true
jastAddList = 'JastAddList'
relastFiles 'src/test/02-after-ros2rag/defaultOnlyRead/Grammar.relast'
grammarName = 'src/test/03-after-relast/defaultOnlyRead/defaultOnlyRead'
packageName = 'defaultOnlyRead.ast'
moreInputFiles 'src/test/02-after-ros2rag/defaultOnlyRead/MqttUpdater.jadd',
'src/test/02-after-ros2rag/defaultOnlyRead/ROS2RAG.jadd'
}
test.dependsOn compileDefaultOnlyReadTest
compileDefaultOnlyReadTest.dependsOn preprocessDefaultOnlyReadTest
clean {
delete 'src/test/02-after-ros2rag/example/', 'src/test/03-after-relast/example/'
delete 'src/test/02-after-ros2rag/*/', 'src/test/03-after-relast/*/'
}
A ::= NativeTypes* BoxedTypes* ;
NativeTypes ::= <IntValue:int> <ShortValue:short> <LongValue:long> <FloatValue:float> <DoubleValue:double> <CharValue:char> <StringValue:String> ;
BoxedTypes ::= <IntValue:Integer> <ShortValue:Short> <LongValue:Long> <FloatValue:Float> <DoubleValue:Double> <CharValue:Character> ;
// --- update definitions ---
read NativeTypes.IntValue;
read NativeTypes.ShortValue;
read NativeTypes.LongValue;
read NativeTypes.FloatValue;
read NativeTypes.DoubleValue;
read NativeTypes.CharValue;
read NativeTypes.StringValue;
read BoxedTypes.IntValue;
read BoxedTypes.ShortValue;
read BoxedTypes.LongValue;
read BoxedTypes.FloatValue;
read BoxedTypes.DoubleValue;
read BoxedTypes.CharValue;
package org.jastadd.ros2rag.tests;
import defaultOnlyRead.ast.A;
import defaultOnlyRead.ast.BoxedTypes;
import defaultOnlyRead.ast.MqttUpdater;
import defaultOnlyRead.ast.NativeTypes;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Test;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.util.concurrent.TimeUnit;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
/**
* Test case "defaultOnlyRead".
*
* @author rschoene - Initial contribution
*/
public class DefaultOnlyReadTest {
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 NativeTypes integers;
private NativeTypes floats;
private NativeTypes chars;
private BoxedTypes allBoxed;
private MqttUpdater sender;
@AfterEach
public void closeConnections() {
if (sender != null) {
sender.close();
}
if (model != null) {
model.MqttCloseConnections();
}
}
@Test
public void buildModel() {
createModel();
}
@Test
public void communicate() throws IOException, InterruptedException {
createModel();
model.MqttSetHost(TestUtils.getMqttHost());
assertTrue(model.MqttWaitUntilReady(2, TimeUnit.SECONDS));
integers.connectIntValue(TOPIC_NATIVE_INT);
integers.connectShortValue(TOPIC_NATIVE_SHORT);
integers.connectLongValue(TOPIC_NATIVE_LONG);
floats.connectFloatValue(TOPIC_NATIVE_FLOAT);
floats.connectDoubleValue(TOPIC_NATIVE_DOUBLE);
chars.connectCharValue(TOPIC_NATIVE_CHAR);
chars.connectStringValue(TOPIC_NATIVE_STRING);
allBoxed.connectIntValue(TOPIC_BOXED_INTEGER);
allBoxed.connectShortValue(TOPIC_BOXED_SHORT);
allBoxed.connectLongValue(TOPIC_BOXED_LONG);
allBoxed.connectFloatValue(TOPIC_BOXED_FLOAT);
allBoxed.connectDoubleValue(TOPIC_BOXED_DOUBLE);
allBoxed.connectCharValue(TOPIC_BOXED_CHARACTER);
sender = new MqttUpdater().dontSendWelcomeMessage().setHost(TestUtils.getMqttHost());
assertTrue(sender.waitUntilReady(2, TimeUnit.SECONDS));
final int expectedIntValue = 1;
final short expectedShortValue = 2;
final long expectedLongValue = 3L;
final float expectedFloatValue = 4.1f;
final double expectedDoubleValue = 5.2;
final char expectedCharValue = 'c';
final String expectedStringValue = "6.3";
sender.publish(TOPIC_NATIVE_INT, ByteBuffer.allocate(4).putInt(expectedIntValue).array());
sender.publish(TOPIC_NATIVE_SHORT, ByteBuffer.allocate(2).putShort(expectedShortValue).array());
sender.publish(TOPIC_NATIVE_LONG, ByteBuffer.allocate(8).putLong(expectedLongValue).array());
sender.publish(TOPIC_NATIVE_FLOAT, ByteBuffer.allocate(4).putFloat(expectedFloatValue).array());
sender.publish(TOPIC_NATIVE_DOUBLE, ByteBuffer.allocate(8).putDouble(expectedDoubleValue).array());
sender.publish(TOPIC_NATIVE_CHAR, ByteBuffer.allocate(2).putChar(expectedCharValue).array());
sender.publish(TOPIC_NATIVE_STRING, expectedStringValue.getBytes());
sender.publish(TOPIC_BOXED_INTEGER, ByteBuffer.allocate(4).putInt(expectedIntValue).array());
sender.publish(TOPIC_BOXED_SHORT, ByteBuffer.allocate(2).putShort(expectedShortValue).array());
sender.publish(TOPIC_BOXED_LONG, ByteBuffer.allocate(8).putLong(expectedLongValue).array());
sender.publish(TOPIC_BOXED_FLOAT, ByteBuffer.allocate(4).putFloat(expectedFloatValue).array());
sender.publish(TOPIC_BOXED_DOUBLE, ByteBuffer.allocate(8).putDouble(expectedDoubleValue).array());
sender.publish(TOPIC_BOXED_CHARACTER, ByteBuffer.allocate(2).putChar(expectedCharValue).array());
TimeUnit.SECONDS.sleep(2);
assertEquals(expectedIntValue, integers.getIntValue());
assertEquals(expectedShortValue, integers.getShortValue());
assertEquals(expectedLongValue, integers.getLongValue());
assertEquals(expectedFloatValue, floats.getFloatValue(), TestUtils.DELTA);
assertEquals(expectedDoubleValue, floats.getDoubleValue(), TestUtils.DELTA);
assertEquals(expectedCharValue, chars.getCharValue());
assertEquals(expectedStringValue, chars.getStringValue());
assertEquals(expectedIntValue, allBoxed.getIntValue().intValue());
assertEquals(expectedShortValue, allBoxed.getShortValue().shortValue());
assertEquals(expectedLongValue, allBoxed.getLongValue().longValue());
assertEquals(expectedFloatValue, allBoxed.getFloatValue(), TestUtils.DELTA);
assertEquals(expectedDoubleValue, allBoxed.getDoubleValue(), TestUtils.DELTA);
assertEquals(expectedCharValue, allBoxed.getCharValue().charValue());
}
private void createModel() {
model = new A();
integers = new NativeTypes();
model.addNativeTypes(integers);
floats = new NativeTypes();
model.addNativeTypes(floats);
chars = new NativeTypes();
model.addNativeTypes(chars);
allBoxed = new BoxedTypes();
model.addBoxedTypes(allBoxed);
}
}
......@@ -9,7 +9,6 @@ import org.junit.jupiter.api.Test;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import static org.junit.Assert.*;
......@@ -21,20 +20,21 @@ import static org.junit.Assert.*;
*/
public class ExampleTest {
private static final double DELTA = 0.001d;
private static final String TOPIC_CONFIG = "robot/config";
private static final String TOPIC_JOINT1 = "robot/arm/joint1";
private Model model;
private RobotArm robotArm;
private Joint joint1;
private CountDownLatch stop;
private MqttUpdater receiver;
@AfterEach
public void signalCondition() {
if (stop != null) {
stop.countDown();
public void closeConnections() {
if (receiver != null) {
receiver.close();
}
if (model != null) {
model.MqttCloseConnections();
}
}
......@@ -48,10 +48,7 @@ public class ExampleTest {
createModel();
List<RobotConfig> receivedConfigs = new ArrayList<>();
CountDownLatch start = new CountDownLatch(1);
stop = new CountDownLatch(1);
createListenerThread(receivedConfigs, start, stop);
start.await();
createListener(receivedConfigs);
model.MqttSetHost(TestUtils.getMqttHost());
assertTrue(model.MqttWaitUntilReady(2, TimeUnit.SECONDS));
......@@ -68,39 +65,28 @@ public class ExampleTest {
// there should be two configs received by now (the initial one, and the updated)
assertEquals(2, receivedConfigs.size());
RobotConfig actualInitialConfig = receivedConfigs.get(0);
assertEquals(robotArm.speedLow(), actualInitialConfig.getSpeed(), DELTA);
assertEquals(robotArm.speedLow(), actualInitialConfig.getSpeed(), TestUtils.DELTA);
RobotConfig actualUpdatedConfig = receivedConfigs.get(1);
assertEquals(robotArm.speedHigh(), actualUpdatedConfig.getSpeed(), DELTA);
model.MqttCloseConnections();
assertEquals(robotArm.speedHigh(), actualUpdatedConfig.getSpeed(), TestUtils.DELTA);
}
private void createListenerThread(List<RobotConfig> receivedConfigs,
CountDownLatch startCondition, CountDownLatch stopCondition) {
new Thread(() -> {
MqttUpdater receiver = new MqttUpdater("receiver");
try {
receiver.setHost(TestUtils.getMqttHost(), TestUtils.getMqttDefaultPort());
} catch (IOException e) {
fail("Could not set host: " + e.getMessage());
}
assertTrue(receiver.waitUntilReady(2, TimeUnit.SECONDS));
receiver.newConnection(TOPIC_CONFIG, bytes -> {
try {
RobotConfig config = RobotConfig.parseFrom(bytes);
receivedConfigs.add(config);
} catch (InvalidProtocolBufferException e) {
fail("Received bad config: " + e.getMessage());
}
});
startCondition.countDown();
private void createListener(List<RobotConfig> receivedConfigs) {
receiver = new MqttUpdater("receiver");
try {
receiver.setHost(TestUtils.getMqttHost(), TestUtils.getMqttDefaultPort());
} catch (IOException e) {
fail("Could not set host: " + e.getMessage());