diff --git a/libs/jastadd2.jar b/libs/jastadd2.jar deleted file mode 100644 index 6c69edae63a847e4274af7405c754b31b0518d3b..0000000000000000000000000000000000000000 Binary files a/libs/jastadd2.jar and /dev/null differ diff --git a/pages/docs/extending.md b/pages/docs/extending.md index 246b7a7527016298320fb89220988ccd6399fe49..61cabca224b7834f08cca7d96f3913c7cb9feb37 100644 --- a/pages/docs/extending.md +++ b/pages/docs/extending.md @@ -28,5 +28,58 @@ In `ragconnect.base/src/main/java/org/jastadd/ragconnect/compiler/Compiler.java` - Set the flag `usesABC` if the choice is given. - Add code to add the handler to the list `handlers` if the choice is given, i.e., if `ASTNode.usesABC` -Furthermore, new test cases are appreciated. They can be added in the [ragconnect.rests repository](https://git-st.inf.tu-dresden.de/jastadd/ragconnect-tests) +Furthermore, new test cases are appreciated, see [below](#writing-tests). +## Writing Tests + +To add new tests, have a look at the module `ragconnect.tests`. +It has three parts: +1) In `src/test/01-input/*` are the [specifications](#specifications) that are going to be compiled (in principle using the steps described in [the guide to add RagConnect](adding)). +2) In `src/test/java`, the jUnit 5 [test classes](#test-classes) are implemented. They mostly correspond 1-to-1 to a directory of the first part. +3) In `build.gradle` the [instructions how to compile](#buildgradle) the specifications using the gradle plugin [PreprocessorPlugin][preprocessor-plugin] (`org.jastadd.preprocessor:testing`). + +### Specifications + +Every specification must have at least a `README.md` to describe the purpose of the test, a grammar `Test.relast`, and a RagConnect specification `Test.connect`. +Usually an aspect file `Test.jadd` is included. + +### Test Classes + +Based on jUnit 5, the test classes testing some behaviour. If sending and/or receiving functionality is used, consider extending `AbstractMqttTest` in order to avoid duplicate code. In case of extending this class, please order the methods according to their lifecycle, i.e.: +- createModel +- setupReceiverAndConnect +- communicateSendInitialValue +- communicateOnlyUpdatedValue +- closeConnections + +Within `AbstractMqttTest`, an `MqttHandler` named `publisher` is available to publish content. +Some convenience methods are provided in `TestUtils`, e.g., the `DefaultMappings`, and `mqttUri` to prepend `"mqtt://"` and the correct host for the mqtt broker (`localhost` or a CI-specific host). +All tests are required to run both locally, and within the CI. + +### build.gradle + +Use the [PreprocessorPlugin][preprocessor-plugin], the build process can be written concisely in three parts per task: + +```groovy +task compileTreeAllowedTokens(type: RagConnectTest) { + ragconnect { + outputDir = file('src/test/02-after-ragconnect/treeAllowedTokens') + inputFiles = [file('src/test/01-input/treeAllowedTokens/Test.relast'), + file('src/test/01-input/treeAllowedTokens/Test.connect'), + file('src/test/01-input/treeAllowedTokens/TestDependencies.connect')] + rootNode = 'Root' + } + relast { + useJastAddNames = true + grammarName = 'src/test/03-after-relast/treeAllowedTokens/treeAllowedTokens' + serializer = 'jackson' + } + jastadd { + jastAddList = 'JastAddList' + packageName = 'treeAllowedTokens.ast' + inputFiles = [file('src/test/01-input/treeAllowedTokens/Test.jadd')] + } +} +``` + +[preprocessor-plugin]: https://git-st.inf.tu-dresden.de/jastadd/testing diff --git a/ragconnect.base/build.gradle b/ragconnect.base/build.gradle index b3e89a6a7fe602f4bfa87611e3002e99b446f7c6..0a96c5864e96fd1746cd8b2f9e1fa66da21f46a7 100644 --- a/ragconnect.base/build.gradle +++ b/ragconnect.base/build.gradle @@ -31,7 +31,7 @@ dependencies { implementation group: 'org.apache.logging.log4j', name: 'log4j-core', version: "${log4j_version}" implementation group: 'org.apache.logging.log4j', name: 'log4j-jul', version: "${log4j_version}" implementation group: 'com.github.spullara.mustache.java', name: 'compiler', version: "${mustache_java_version}" - runtimeOnly group: 'org.jastadd', name: 'jastadd', version: '2.3.4' + runtimeOnly group: 'org.jastadd', name: 'jastadd', version: '2.3.5' api group: 'net.sf.beaver', name: 'beaver-rt', version: '0.9.11' } diff --git a/ragconnect.base/src/main/jastadd/Analysis.jrag b/ragconnect.base/src/main/jastadd/Analysis.jrag index f686d3af0009baa0382e8ec3ba2d548b797e85a6..f55044dddb1582d41689a138818ad2114d2d6fd7 100644 --- a/ragconnect.base/src/main/jastadd/Analysis.jrag +++ b/ragconnect.base/src/main/jastadd/Analysis.jrag @@ -86,4 +86,13 @@ aspect Analysis { // --- needProxyToken --- syn boolean TokenComponent.needProxyToken() = !getDependencySourceDefinitionList().isEmpty() || getTokenEndpointDefinitionList().stream().anyMatch(TokenEndpointDefinition::shouldSendValue); + + // --- effectiveUsedAt --- + coll Set<EndpointDefinition> MappingDefinition.effectiveUsedAt() + [new java.util.HashSet<EndpointDefinition>()] + root RagConnect; + EndpointDefinition contributes this + to MappingDefinition.effectiveUsedAt() + for each effectiveMappings(); + } diff --git a/ragconnect.base/src/main/jastadd/Errors.jrag b/ragconnect.base/src/main/jastadd/Errors.jrag index c3ecc643a4edc8319da82f49438dc46f167a3618..1aa3666c2b19bf446667f1a763bfb4824aa44f25 100644 --- a/ragconnect.base/src/main/jastadd/Errors.jrag +++ b/ragconnect.base/src/main/jastadd/Errors.jrag @@ -32,10 +32,6 @@ aspect Errors { when isAlreadyDefined() to RagConnect.errors(); - SendTypeEndpointDefinition contributes error("At least one mapping needs to be used") - when effectiveMappings().isEmpty() - to RagConnect.errors(); - DependencyDefinition contributes error("Dependency definition already defined for " + getSource().containingTypeDecl().getName() + " with name " + getID()) when isAlreadyDefined() to RagConnect.errors(); @@ -43,10 +39,6 @@ aspect Errors { DependencyDefinition contributes error("The name of a dependency definition must not be equal to a list-node on the source") when isAlreadyDefinedAsList() to RagConnect.errors(); - - DependencyDefinition contributes error("There must be a send endpoint definition targeting " + getSource().parentTypeypeAndName() + " for dependency definition " + getID()) - when targetEndpointDefinition() == null - to RagConnect.errors(); } aspect ErrorHelpers { @@ -58,7 +50,7 @@ aspect ErrorHelpers { } return false; } - syn String TokenComponent.parentTypeypeAndName() = containingTypeDecl().getName() + "." + getName(); + syn String TokenComponent.parentTypeDeclAndName() = containingTypeDecl().getName() + "." + getName(); } aspect ErrorMessage { diff --git a/ragconnect.base/src/main/jastadd/NameResolution.jrag b/ragconnect.base/src/main/jastadd/NameResolution.jrag index 253f1dabf8ed0f15e2483aafde9144d992d87cf2..6b9171df4e85464b6711aa80e76b34f952d6864b 100644 --- a/ragconnect.base/src/main/jastadd/NameResolution.jrag +++ b/ragconnect.base/src/main/jastadd/NameResolution.jrag @@ -27,4 +27,20 @@ aspect NameResolution { return null; } + refine RefResolverStubs eq ASTNode.globallyResolveComponentByToken(String id) { + // return a Component. id is of the form 'parent_type_name + "." + child_type_name' + int dotIndex = id.indexOf("."); + String parentTypeName = id.substring(0, dotIndex); + String childTypeName = id.substring(dotIndex + 1); + TypeDecl type = program().resolveTypeDecl(parentTypeName); + // iterate over components and find the matching typeComponent + for (Component comp : type.getComponentList()) { + if (comp.getName().equals(childTypeName)) { + return comp; + } + } + System.err.println("Could not resolve Component '" + id + "'."); + return null; + } + } diff --git a/ragconnect.base/src/main/jastadd/Navigation.jrag b/ragconnect.base/src/main/jastadd/Navigation.jrag index c6432a14d9258795f1f402366ec5c418993d4aa1..5bddf79ea3c633d7fa5933dde4ab6b665000630d 100644 --- a/ragconnect.base/src/main/jastadd/Navigation.jrag +++ b/ragconnect.base/src/main/jastadd/Navigation.jrag @@ -68,12 +68,16 @@ aspect Navigation { eq SendTypeEndpointDefinition.asSendTypeEndpointDefinition() = this; // --- targetEndpointDefinition --- - syn SendTokenEndpointDefinition DependencyDefinition.targetEndpointDefinition() { + syn EndpointDefinition DependencyDefinition.targetEndpointDefinition() { // resolve definition in here, as we do not need resolveMethod in any other place (yet) for (EndpointDefinition endpointDefinition : ragconnect().getEndpointDefinitionList()) { if (endpointDefinition.isSendTokenEndpointDefinition() && endpointDefinition.asSendTokenEndpointDefinition().getToken().equals(this.getTarget())) { - return endpointDefinition.asSendTokenEndpointDefinition(); + return endpointDefinition; + } + if (endpointDefinition.isSendTypeEndpointDefinition() && + endpointDefinition.asSendTypeEndpointDefinition().getType().equals(this.getTarget())) { + return endpointDefinition; } } return null; diff --git a/ragconnect.base/src/main/jastadd/RagConnect.relast b/ragconnect.base/src/main/jastadd/RagConnect.relast index bd3e5c0d964881a7d7d49a68da83f1b27b79d0a7..426b90ee22b0aeeb1a9d0cb7a5d77e52838bc0ff 100644 --- a/ragconnect.base/src/main/jastadd/RagConnect.relast +++ b/ragconnect.base/src/main/jastadd/RagConnect.relast @@ -18,7 +18,7 @@ SendTypeEndpointDefinition : TypeEndpointDefinition; DependencyDefinition ::= <ID>; rel DependencyDefinition.Source <-> TokenComponent.DependencySourceDefinition*; -rel DependencyDefinition.Target -> TokenComponent; +rel DependencyDefinition.Target -> Component; MappingDefinition ::= <ID> FromType:MappingDefinitionType <FromVariableName> ToType:MappingDefinitionType <Content> ; abstract MappingDefinitionType ::= ; diff --git a/ragconnect.base/src/main/jastadd/intermediate/Generation.jadd b/ragconnect.base/src/main/jastadd/intermediate/Generation.jadd index 00ef291fa015596647a6f15756ce6f4380929501..444f0214af4821f704a3307227c9f1b04b072e47 100644 --- a/ragconnect.base/src/main/jastadd/intermediate/Generation.jadd +++ b/ragconnect.base/src/main/jastadd/intermediate/Generation.jadd @@ -22,12 +22,15 @@ aspect AttributesForMustache { syn String MEndpointDefinition.firstInputVarName(); syn String MEndpointDefinition.parentTypeName(); syn String MEndpointDefinition.entityName(); + syn String MEndpointDefinition.updateMethod(); + syn String MEndpointDefinition.writeMethod(); eq MEndpointDefinition.getInnerMappingDefinition(int i).isLast() = i == getNumInnerMappingDefinition() - 1; eq MEndpointDefinition.getInnerMappingDefinition(int i).inputVarName() = i == 0 ? firstInputVarName() : getInnerMappingDefinition(i - 1).outputVarName(); syn String MEndpointDefinition.connectParameterName() = "uriString"; syn String MEndpointDefinition.connectMethod() = "connect" + entityName(); + syn boolean MEndpointDefinition.isTypeEndpointDefinition() = endpointDef().isTypeEndpointDefinition(); syn String MEndpointDefinition.disconnectMethod() { // if both (send and receive) are defined for the token, ensure methods with different names @@ -54,6 +57,7 @@ aspect AttributesForMustache { syn boolean MEndpointDefinition.alwaysApply() = endpointDef().getAlwaysApply(); syn String MEndpointDefinition.tokenName() = token().getName(); syn String MEndpointDefinition.typeName() = type().getName(); + syn String MEndpointDefinition.typeDeclName() = type().getTypeDecl().getName(); syn MInnerMappingDefinition MEndpointDefinition.lastDefinition() = getInnerMappingDefinition(getNumInnerMappingDefinition() - 1); syn String MEndpointDefinition.lastDefinitionToType() = lastDefinition().toType(); syn String MEndpointDefinition.lastResult() = lastDefinition().outputVarName(); @@ -61,7 +65,7 @@ aspect AttributesForMustache { if (lastDefinition().mappingDef().getToType().isArray()) { return "java.util.Arrays.equals(" + preemptiveExpectedValue() + ", " + lastResult() + ")"; } - if (token().isPrimitiveType() && lastDefinition().mappingDef().getToType().isPrimitiveType()) { + if (endpointDef().isTokenEndpointDefinition() && token().isPrimitiveType() && lastDefinition().mappingDef().getToType().isPrimitiveType()) { return preemptiveExpectedValue() + " == " + lastResult(); } if (lastDefinition().mappingDef().getToType().isPrimitiveType() || lastDefinition().mappingDef().isDefaultMappingDefinition()) { @@ -91,36 +95,40 @@ aspect AttributesForMustache { eq MTokenReceiveDefinition.preemptiveReturn() = "return;"; eq MTokenReceiveDefinition.endpointDef() = getReceiveTokenEndpointDefinition(); eq MTokenReceiveDefinition.firstInputVarName() = "message"; + eq MTokenReceiveDefinition.updateMethod() = null; + eq MTokenReceiveDefinition.writeMethod() = null; // --- MTokenSendDefinition --- eq MTokenSendDefinition.preemptiveExpectedValue() = lastValue(); eq MTokenSendDefinition.preemptiveReturn() = "return false;"; eq MTokenSendDefinition.endpointDef() = getSendTokenEndpointDefinition(); eq MTokenSendDefinition.firstInputVarName() = "get" + tokenName() + "()"; + eq MTokenSendDefinition.updateMethod() = "_update_" + tokenName(); + eq MTokenSendDefinition.writeMethod() = "_writeLastValue_" + tokenName(); syn String MTokenSendDefinition.sender() = "_sender_" + tokenName(); syn String MTokenSendDefinition.lastValue() = "_lastValue" + tokenName(); - syn String MTokenSendDefinition.updateMethod() = "_update_" + tokenName(); - syn String MTokenSendDefinition.writeMethod() = "_writeLastValue_" + tokenName(); syn String MTokenSendDefinition.tokenResetMethod() = "get" + tokenName() + "_reset"; syn boolean MTokenSendDefinition.shouldSendValue() = endpointDef().asTokenEndpointDefinition().shouldSendValue(); // MTypeReceiveDefinition - eq MTypeReceiveDefinition.preemptiveExpectedValue() = null; - eq MTypeReceiveDefinition.preemptiveReturn() = null; + eq MTypeReceiveDefinition.preemptiveExpectedValue() = "get" + typeName() + "()"; + eq MTypeReceiveDefinition.preemptiveReturn() = "return;"; eq MTypeReceiveDefinition.endpointDef() = getReceiveTypeEndpointDefinition(); - eq MTypeReceiveDefinition.firstInputVarName() = null; + eq MTypeReceiveDefinition.firstInputVarName() = "message"; + eq MTypeReceiveDefinition.updateMethod() = null; + eq MTypeReceiveDefinition.writeMethod() = null; // MTypeSendDefinition - eq MTypeSendDefinition.preemptiveExpectedValue() = null; - eq MTypeSendDefinition.preemptiveReturn() = null; + eq MTypeSendDefinition.preemptiveExpectedValue() = lastValue(); + eq MTypeSendDefinition.preemptiveReturn() = "return false;"; eq MTypeSendDefinition.endpointDef() = getSendTypeEndpointDefinition(); - eq MTypeSendDefinition.firstInputVarName() = null; + eq MTypeSendDefinition.firstInputVarName() = "get" + typeName() + "()"; + eq MTypeSendDefinition.updateMethod() = "_update_" + typeName(); + eq MTypeSendDefinition.writeMethod() = "_writeLastValue_" + typeName(); syn String MTypeSendDefinition.sender() = "_sender_" + typeName(); syn String MTypeSendDefinition.lastValue() = "_lastValue" + typeName(); - syn String MTypeSendDefinition.updateMethod() = "_update_" + typeName(); - syn String MTypeSendDefinition.writeMethod() = "_writeLastValue_" + typeName(); syn String MTypeSendDefinition.tokenResetMethod() = "get" + typeName() + "_reset"; syn boolean MTypeSendDefinition.shouldSendValue() = endpointDef().asTypeEndpointDefinition().shouldSendValue(); @@ -130,13 +138,14 @@ aspect AttributesForMustache { syn String MMappingDefinition.fromType() = getMappingDefinition().getFromType().prettyPrint(); syn String MMappingDefinition.fromVariableName() = getMappingDefinition().getFromVariableName(); syn String MMappingDefinition.content() = getMappingDefinition().getContent(); + syn boolean MMappingDefinition.isUsed() = !getMappingDefinition().effectiveUsedAt().isEmpty(); // --- MDependencyDefinition --- syn String MDependencyDefinition.targetParentTypeName() = getDependencyDefinition().getTarget().containingTypeDecl().getName(); syn String MDependencyDefinition.dependencyMethod() = "add" + capitalize(getDependencyDefinition().getID()); syn String MDependencyDefinition.sourceParentTypeName() = getDependencyDefinition().getSource().containingTypeDecl().getName(); syn String MDependencyDefinition.internalRelationPrefix() = "_internal_" + getDependencyDefinition().getID(); - syn nta MTokenSendDefinition MDependencyDefinition.targetEndpointDefinition() { + syn nta MEndpointDefinition MDependencyDefinition.targetEndpointDefinition() { return getDependencyDefinition().targetEndpointDefinition().toMustache(); } @@ -208,6 +217,7 @@ aspect AttributesForMustache { } } + public abstract MEndpointDefinition EndpointDefinition.toMustache(); syn lazy MTokenReceiveDefinition ReceiveTokenEndpointDefinition.toMustache() { MTokenReceiveDefinition result = new MTokenReceiveDefinition(); result.setReceiveTokenEndpointDefinition(this); diff --git a/ragconnect.base/src/main/jastadd/intermediate/Mappings.jrag b/ragconnect.base/src/main/jastadd/intermediate/Mappings.jrag index 3479f11728195a2480109343e05292ccb1c6a45e..93f74e51d8acbf140b56e99e279a337506c3a6c0 100644 --- a/ragconnect.base/src/main/jastadd/intermediate/Mappings.jrag +++ b/ragconnect.base/src/main/jastadd/intermediate/Mappings.jrag @@ -10,9 +10,9 @@ aspect DefaultMappings { new JavaMappingDefinitionType(new SimpleJavaTypeUse(typeName)); } - private DefaultMappingDefinition RagConnect.baseDefaultMappingDefinition(String fromTypeName, String toTypeName, String content) { + private DefaultMappingDefinition RagConnect.createDefaultMappingDefinition(String prefix, String fromTypeName, String toTypeName, String content) { DefaultMappingDefinition result = new DefaultMappingDefinition(); - result.setID("_Default" + baseDefaultMappingTypeNamePart(fromTypeName) + "To" + baseDefaultMappingTypeNamePart(toTypeName) + "Mapping"); + result.setID(prefix + baseDefaultMappingTypeNamePart(fromTypeName) + "To" + baseDefaultMappingTypeNamePart(toTypeName) + "Mapping"); result.setFromType(baseDefaultMappingTypeFromName(fromTypeName)); result.setFromVariableName("input"); result.setToType(baseDefaultMappingTypeFromName(toTypeName)); @@ -20,6 +20,14 @@ aspect DefaultMappings { return result; } + private DefaultMappingDefinition RagConnect.baseDefaultMappingDefinition(String fromTypeName, String toTypeName, String content) { + return createDefaultMappingDefinition("_Default", fromTypeName, toTypeName, content); + } + + private DefaultMappingDefinition RagConnect.treeDefaultMappingDefinition(String fromTypeName, String toTypeName, String content) { + return createDefaultMappingDefinition("_TreeDefault", fromTypeName, toTypeName, content); + } + syn nta DefaultMappingDefinition RagConnect.defaultBytesToBooleanMapping() = baseDefaultMappingDefinition( "byte[]", "boolean", "return input[0] == (byte) 1;"); syn nta DefaultMappingDefinition RagConnect.defaultBytesToIntMapping() = baseDefaultMappingDefinition( @@ -37,6 +45,28 @@ aspect DefaultMappings { syn nta DefaultMappingDefinition RagConnect.defaultBytesToStringMapping() = baseDefaultMappingDefinition( "byte[]", "String", "return new String(input);"); + syn nta DefaultMappingDefinition RagConnect.defaultBytesToTreeMapping(String typeName) { + return treeDefaultMappingDefinition("byte[]", typeName, + "String content = new String(input);\n" + + "com.fasterxml.jackson.databind.ObjectMapper mapper = new com.fasterxml.jackson.databind.ObjectMapper();\n" + + "com.fasterxml.jackson.core.JsonFactory factory = new com.fasterxml.jackson.core.JsonFactory();\n" + + "com.fasterxml.jackson.core.JsonParser parser = factory.createParser(content);\n" + + typeName + " result = " + typeName + ".deserialize((com.fasterxml.jackson.databind.JsonNode)mapper.readTree(parser));\n" + + "parser.close();\n" + + "return result;" + ); + } + syn nta DefaultMappingDefinition RagConnect.defaultTreeToBytesMapping(String typeName) { + return treeDefaultMappingDefinition(typeName, "byte[]", + "java.io.ByteArrayOutputStream outputStream = new java.io.ByteArrayOutputStream();\n" + + "com.fasterxml.jackson.core.JsonFactory factory = new com.fasterxml.jackson.core.JsonFactory();\n" + + "com.fasterxml.jackson.core.JsonGenerator generator = factory.createGenerator(outputStream, com.fasterxml.jackson.core.JsonEncoding.UTF8);\n"+ + "input.serialize(generator);\n" + + "generator.flush();\n" + + "return outputStream.toString().getBytes();" + ); + } + syn nta DefaultMappingDefinition RagConnect.defaultBooleanToBytesMapping() = baseDefaultMappingDefinition( "boolean", "byte[]", "return java.nio.ByteBuffer.allocate(1).put((byte) (input ? 1 : 0)).array();"); syn nta DefaultMappingDefinition RagConnect.defaultIntToBytesMapping() = baseDefaultMappingDefinition( @@ -155,7 +185,13 @@ aspect Mappings { case "char": case "Character": return ragconnect().defaultBytesToCharMapping(); case "String": return ragconnect().defaultBytesToStringMapping(); - default: return null; + default: + try { + TypeDecl typeDecl = program().resolveTypeDecl(targetTypeName()); + return ragconnect().defaultBytesToTreeMapping(typeDecl.getName()); + } catch (Exception ignore) {} + System.err.println("Could not find suitable default mapping for " + targetTypeName() + " on " + this); + return null; } } // --- suitableSendDefaultMapping --- @@ -176,7 +212,13 @@ aspect Mappings { case "char": case "Character": return ragconnect().defaultCharToBytesMapping(); case "String": return ragconnect().defaultStringToBytesMapping(); - default: return null; + default: + try { + TypeDecl typeDecl = program().resolveTypeDecl(targetTypeName()); + return ragconnect().defaultTreeToBytesMapping(typeDecl.getName()); + } catch (Exception ignore) {} + System.err.println("Could not find suitable default mapping for " + targetTypeName() + " on " + this); + return null; } } @@ -188,7 +230,9 @@ aspect Mappings { getMappingList().get(0).getFromType().prettyPrint(); } eq ReceiveTypeEndpointDefinition.targetTypeName() { - return getMappingList().get(0).getFromType().prettyPrint(); + return getMappingList().isEmpty() ? + getType().getTypeDecl().getName() : + getMappingList().get(0).getFromType().prettyPrint(); } eq SendTokenEndpointDefinition.targetTypeName() { return getMappingList().isEmpty() ? @@ -196,7 +240,9 @@ aspect Mappings { getMappingList().get(getMappingList().size() - 1).getToType().prettyPrint(); } eq SendTypeEndpointDefinition.targetTypeName() { - return getMappingList().get(getMappingList().size() - 1).getToType().prettyPrint(); + return getMappingList().isEmpty() ? + getType().getTypeDecl().getName() : + getMappingList().get(getMappingList().size() - 1).getToType().prettyPrint(); } // eq ReceiveFromRestDefinition.suitableDefaultMapping() { @@ -251,8 +297,9 @@ aspect Mappings { // --- allMappingDefinitions --- syn java.util.List<MappingDefinition> RagConnect.allMappingDefinitions() { java.util.List<MappingDefinition> result = new java.util.ArrayList<>(); + // user-defined mappings getMappingDefinitionList().iterator().forEachRemaining(result::add); - // byte[] conversion + // byte[] <-> primitive conversion result.add(defaultBytesToBooleanMapping()); result.add(defaultBytesToIntMapping()); result.add(defaultBytesToShortMapping()); @@ -269,6 +316,11 @@ aspect Mappings { result.add(defaultDoubleToBytesMapping()); result.add(defaultCharToBytesMapping()); result.add(defaultStringToBytesMapping()); + // byte[] <-> tree conversion + for (TypeDecl typeDecl : getProgram().typeDecls()) { + result.add(defaultBytesToTreeMapping(typeDecl.getName())); + result.add(defaultTreeToBytesMapping(typeDecl.getName())); + } // // string conversion // result.add(defaultStringToBooleanMapping()); // result.add(defaultStringToIntMapping()); diff --git a/ragconnect.base/src/main/jastadd/parser/RagConnect.parser b/ragconnect.base/src/main/jastadd/parser/RagConnect.parser index 4094bfa23d62f87540939f2619274ade313f6db4..a9d4809331c0ea20e11b0ec2a04dfd1f2c76e95b 100644 --- a/ragconnect.base/src/main/jastadd/parser/RagConnect.parser +++ b/ragconnect.base/src/main/jastadd/parser/RagConnect.parser @@ -51,11 +51,11 @@ ArrayList string_list ; DependencyDefinition dependency_definition - = ID.target_type DOT ID.target_token CAN_DEPEND_ON ID.source_type DOT ID.source_token AS ID.id SCOL + = ID.target_type DOT ID.target_component CAN_DEPEND_ON ID.source_type DOT ID.source_token AS ID.id SCOL {: DependencyDefinition result = new DependencyDefinition(); result.setSource(TokenComponent.createRef(source_type + "." + source_token)); - result.setTarget(TokenComponent.createRef(target_type + "." + target_token)); + result.setTarget(Component.createRef(target_type + "." + target_component)); result.setID(id); return result; :} diff --git a/ragconnect.base/src/main/java/org/jastadd/ragconnect/compiler/Compiler.java b/ragconnect.base/src/main/java/org/jastadd/ragconnect/compiler/Compiler.java index 95e08da36c6f2f3becf3f9f009aec443a3c4d5fa..88bfbdc1689fe0c8040efc952832c0bc9ac58b02 100644 --- a/ragconnect.base/src/main/java/org/jastadd/ragconnect/compiler/Compiler.java +++ b/ragconnect.base/src/main/java/org/jastadd/ragconnect/compiler/Compiler.java @@ -274,9 +274,10 @@ public class Compiler extends AbstractCompiler { } private void mergeRagConnectDefinitions(RagConnect ragConnect, RagConnect ragConnectToIntegrate) { - ragConnect.setEndpointDefinitionList(ragConnectToIntegrate.getEndpointDefinitionList()); - ragConnect.setMappingDefinitionList(ragConnectToIntegrate.getMappingDefinitionList()); - ragConnect.setDependencyDefinitionList(ragConnectToIntegrate.getDependencyDefinitionList()); + ragConnectToIntegrate.getEndpointDefinitionList().forEach(ragConnect::addEndpointDefinition); + ragConnectToIntegrate.getMappingDefinitionList().forEach(ragConnect::addMappingDefinition); + ragConnectToIntegrate.getDependencyDefinitionList().forEach(ragConnect::addDependencyDefinition); + ragConnect.setFileName(ragConnect.getFileName().isEmpty() ? ragConnectToIntegrate.getFileName() : ragConnect.getFileName() + " + " + ragConnectToIntegrate.getFileName()); } // protected void printUsage() { diff --git a/ragconnect.base/src/main/resources/mappingDefinition.mustache b/ragconnect.base/src/main/resources/mappingDefinition.mustache index fe26e949b7a8e446bf97947e1632624741a83726..47a9381e2e017b8cc7b7264db6784f2bab1227d2 100644 --- a/ragconnect.base/src/main/resources/mappingDefinition.mustache +++ b/ragconnect.base/src/main/resources/mappingDefinition.mustache @@ -1,3 +1,3 @@ protected static {{toType}} ASTNode.{{methodName}}({{fromType}} {{fromVariableName}}) throws Exception { - {{{content}}}{{!maybe print line by line to get better indentation}} + {{{content}}} } diff --git a/ragconnect.base/src/main/resources/ragconnect.mustache b/ragconnect.base/src/main/resources/ragconnect.mustache index 41cde06f025abc9663ce1acae3ee7549f5987956..2cc2423cc2008ea80f6e614cd0eabea471692cbe 100644 --- a/ragconnect.base/src/main/resources/ragconnect.mustache +++ b/ragconnect.base/src/main/resources/ragconnect.mustache @@ -18,7 +18,9 @@ aspect RagConnect { {{/TypeSendDefinitions}} {{#MappingDefinitions}} + {{#isUsed}} {{> mappingDefinition}} + {{/isUsed}} {{/MappingDefinitions}} {{#DependencyDefinitions}} @@ -65,7 +67,9 @@ aspect RagConnectObserver { node.trace().setReceiver(this); } void add(ConnectToken connectToken, ASTNode node, String attributeString, Runnable attributeCall) { - System.out.println("** observer add " + node + " on " + attributeString); + {{#loggingEnabledForWrites}} + System.out.println("** observer add: " + node + " on " + attributeString); + {{/loggingEnabledForWrites}} observedNodes.add(new RagConnectObserverEntry(connectToken, node, attributeString, attributeCall)); } void remove(ConnectToken connectToken) { @@ -78,12 +82,16 @@ aspect RagConnectObserver { if (event != ASTState.Trace.Event.INC_FLUSH_ATTR) { return; } - System.out.println("** observer check INC_FLUSH_ATTR event"); + {{#loggingEnabledForWrites}} + System.out.println("** observer check INC_FLUSH_ATTR event: " + node + " on " + attribute); + {{/loggingEnabledForWrites}} // iterate through list, if matching pair. could maybe be more efficient. for (RagConnectObserverEntry entry : observedNodes) { if (entry.node.equals(node) && entry.attributeString.equals(attribute)) { // hit. call the attribute/nta-token - System.out.println("** observer hit " + entry.node + " on " + entry.attributeString); + {{#loggingEnabledForWrites}} + System.out.println("** observer hit: " + entry.node + " on " + entry.attributeString); + {{/loggingEnabledForWrites}} entry.attributeCall.run(); } } diff --git a/ragconnect.base/src/main/resources/receiveDefinition.mustache b/ragconnect.base/src/main/resources/receiveDefinition.mustache index 96333bd3497e9468ab99ebae1aaf6e63951fc7f0..10f519129c8dec8abe587a1bcb5876c4c0224745 100644 --- a/ragconnect.base/src/main/resources/receiveDefinition.mustache +++ b/ragconnect.base/src/main/resources/receiveDefinition.mustache @@ -3,9 +3,12 @@ public boolean {{parentTypeName}}.{{connectMethod}}(String {{connectParameterNam java.util.function.Consumer<byte[]> consumer = message -> { {{> mappingApplication}} {{#loggingEnabledForReads}} - System.out.println("[Receive] " + {{connectParameterName}} + " -> {{tokenName}} = " + {{lastResult}}); + System.out.println("[Receive] " + {{connectParameterName}} + " -> {{entityName}} = " + {{lastResult}}); {{/loggingEnabledForReads}} - set{{tokenName}}({{lastResult}}); + {{#isTypeEndpointDefinition}} + {{lastResult}}.treeResolveAll(); + {{/isTypeEndpointDefinition}} + set{{entityName}}({{lastResult}}); }; ConnectToken connectToken; switch (scheme) { diff --git a/ragconnect.base/src/main/resources/sendDefinition.mustache b/ragconnect.base/src/main/resources/sendDefinition.mustache index bee941ff75a105431db457c64ff24b769439a179..62cfb7d5016fe5ed6ac2abadab45e9fdc3a45228 100644 --- a/ragconnect.base/src/main/resources/sendDefinition.mustache +++ b/ragconnect.base/src/main/resources/sendDefinition.mustache @@ -16,7 +16,7 @@ public boolean {{parentTypeName}}.{{connectMethod}}(String {{connectParameterNam final String topic = {{mqttHandlerAttribute}}().extractTopic(uri); {{sender}} = () -> { {{#loggingEnabledForWrites}} - System.out.println("[Send] {{tokenName}} = " + get{{tokenName}}() + " -> " + {{connectParameterName}}); + System.out.println("[Send] {{entityName}} = " + get{{entityName}}() + " -> " + {{connectParameterName}}); {{/loggingEnabledForWrites}} handler.publish(topic, {{lastValue}}); }; @@ -45,7 +45,7 @@ public boolean {{parentTypeName}}.{{connectMethod}}(String {{connectParameterNam connectTokens.computeIfAbsent(this, astNode -> new java.util.HashMap<java.net.URI, ConnectToken>()) .put(uri, connectToken); {{#incrementalOptionActive}} - _ragConnectObserver().add(connectToken, this, "{{parentTypeName}}.get{{tokenName}}()", () -> { + _ragConnectObserver().add(connectToken, this, "get{{entityName}}", () -> { if (this.{{updateMethod}}()) { this.{{writeMethod}}(); } diff --git a/ragconnect.tests/build.gradle b/ragconnect.tests/build.gradle index 28b71c074898d85d9546772476e56baae6a2e034..30fb2237ee167f74879bbb8903553d4eaaf1ceb1 100644 --- a/ragconnect.tests/build.gradle +++ b/ragconnect.tests/build.gradle @@ -36,13 +36,16 @@ repositories { dependencies { implementation project(':ragconnect.base') -// runtime group: 'org.jastadd', name: 'jastadd', version: '2.3.4' - runtime fileTree(include: ['jastadd2.jar'], dir: '../libs/') + runtime group: 'org.jastadd', name: 'jastadd', version: '2.3.5' testImplementation group: 'org.junit.jupiter', name: 'junit-jupiter-api', version: '5.4.0' testRuntimeOnly group: 'org.junit.jupiter', name: 'junit-jupiter-engine', version: '5.4.0' testImplementation group: 'org.assertj', name: 'assertj-core', version: '3.12.1' + // jackson (for serialization of types) + implementation group: 'com.fasterxml.jackson.core', name: 'jackson-core', version: '2.12.1' + implementation group: 'com.fasterxml.jackson.core', name: 'jackson-databind', version: '2.12.1' + // mqtt testImplementation group: 'org.fusesource.mqtt-client', name: 'mqtt-client', version: '1.15' @@ -51,6 +54,7 @@ dependencies { testImplementation group: 'org.apache.logging.log4j', name: 'log4j-slf4j-impl', version: '2.11.2' testImplementation group: 'org.glassfish.jersey.core', name: 'jersey-client', version: '2.31' testImplementation group: 'org.glassfish.jersey.inject', name: 'jersey-hk2', version: '2.31' + testImplementation group: 'javax.activation', name: 'activation', version: '1.1.1' testImplementation group: 'net.sf.beaver', name: 'beaver-rt', version: '0.9.11' api group: 'com.google.protobuf', name: 'protobuf-java', version: '3.0.0' @@ -309,3 +313,95 @@ task compileMapping(type: RagConnectTest) { inputFiles = [file('src/test/01-input/mapping/Test.jadd')] } } + +// --- Test: tree-manual --- +task compileTreeManual(type: RagConnectTest, dependsOn: ':ragconnect.base:compileJava') { + ragconnect { + outputDir = file('src/test/02-after-ragconnect/tree') + inputFiles = [file('src/test/01-input/tree/Test.relast'), + file('src/test/01-input/tree/Test.connect'), + file('src/test/01-input/tree/TestDependencies.connect')] + rootNode = 'Root' + } + relast { + useJastAddNames = true + grammarName = 'src/test/03-after-relast/tree/tree' + serializer = 'jackson' + } + jastadd { + jastAddList = 'JastAddList' + packageName = 'tree.ast' + inputFiles = [file('src/test/01-input/tree/Test.jadd')] + } +} + +// --- Test: tree-incremental --- +task compileTreeIncremental(type: RagConnectTest) { + ragconnect { + outputDir = file('src/test/02-after-ragconnect/treeInc') + inputFiles = [file('src/test/01-input/tree/Test.relast'), + file('src/test/01-input/tree/Test.connect')] + rootNode = 'Root' + } + relast { + useJastAddNames = true + grammarName = 'src/test/03-after-relast/treeInc/treeInc' + serializer = 'jackson' + } + jastadd { + jastAddList = 'JastAddList' + packageName = 'treeInc.ast' + inputFiles = [file('src/test/01-input/tree/Test.jadd')] + extraOptions = ['--tracing=cache,flush', + '--incremental=param', + '--cache=all', + '--rewrite=cnta', + '--flush=full'] + } +} + +// --- Test: tree-allowed-tokens --- +task compileTreeAllowedTokens(type: RagConnectTest) { + ragconnect { + outputDir = file('src/test/02-after-ragconnect/treeAllowedTokens') + inputFiles = [file('src/test/01-input/treeAllowedTokens/Test.relast'), + file('src/test/01-input/treeAllowedTokens/Test.connect'), + file('src/test/01-input/treeAllowedTokens/TestDependencies.connect')] + rootNode = 'Root' + } + relast { + useJastAddNames = true + grammarName = 'src/test/03-after-relast/treeAllowedTokens/treeAllowedTokens' + serializer = 'jackson' + } + jastadd { + jastAddList = 'JastAddList' + packageName = 'treeAllowedTokens.ast' + inputFiles = [file('src/test/01-input/treeAllowedTokens/Test.jadd')] + } +} + +// --- Test: tree-allowed-tokens-incremental --- +task compileTreeAllowedTokensIncremental(type: RagConnectTest) { + ragconnect { + outputDir = file('src/test/02-after-ragconnect/treeAllowedTokensInc') + inputFiles = [file('src/test/01-input/treeAllowedTokens/Test.relast'), + file('src/test/01-input/treeAllowedTokens/Test.connect')] + rootNode = 'Root' + } + relast { + useJastAddNames = true + grammarName = 'src/test/03-after-relast/treeAllowedTokensInc/treeAllowedTokensInc' + serializer = 'jackson' + } + jastadd { + jastAddList = 'JastAddList' + packageName = 'treeAllowedTokensInc.ast' + inputFiles = [file('src/test/01-input/treeAllowedTokens/Test.jadd')] + extraOptions = ['--tracing=cache,flush', + '--incremental=param', + '--cache=all', + '--rewrite=cnta', + '--flush=full'] + } +} diff --git a/ragconnect.tests/src/test/01-input/tree/README.md b/ragconnect.tests/src/test/01-input/tree/README.md new file mode 100644 index 0000000000000000000000000000000000000000..060a0e39663f01d33bffb960c316c7de8da59f68 --- /dev/null +++ b/ragconnect.tests/src/test/01-input/tree/README.md @@ -0,0 +1,4 @@ +# Tree + +Idea: send and receive subtrees, test different relations within the subtree which was sent. +Once without incremental evaluation (i.e., using manual dependencies), and the other time with incremental evaluation diff --git a/ragconnect.tests/src/test/01-input/tree/Test.connect b/ragconnect.tests/src/test/01-input/tree/Test.connect new file mode 100644 index 0000000000000000000000000000000000000000..857f6297f12249451b026051201ebfc004c2f6a6 --- /dev/null +++ b/ragconnect.tests/src/test/01-input/tree/Test.connect @@ -0,0 +1,2 @@ +send tree SenderRoot.Alfa ; +receive tree ReceiverRoot.Alfa ; diff --git a/ragconnect.tests/src/test/01-input/tree/Test.jadd b/ragconnect.tests/src/test/01-input/tree/Test.jadd new file mode 100644 index 0000000000000000000000000000000000000000..c9e47ed7d9c0402992882e3d60a78f08044bf063 --- /dev/null +++ b/ragconnect.tests/src/test/01-input/tree/Test.jadd @@ -0,0 +1,81 @@ +aspect Computation { + syn Alfa SenderRoot.getAlfa() { + Alfa result = new Alfa(); + for (int i = 0; i < 4; i++) { + result.addBravo(new Bravo().setID(i)); + result.addCharlie(new Charlie().setID(i)); + result.addDelta(new Delta().setID(i)); + } + Bravo inputBravo = result.getBravo(getInput()); + Charlie inputCharlie = result.getCharlie(getInput()); + Delta inputDelta = result.getDelta(getInput()); + + // rel Alfa.MyBravo -> Bravo ; + result.setMyBravo(inputBravo); + // rel Alfa.OptionalBravo? -> Bravo ; + result.setOptionalBravo(inputBravo); + // rel Alfa.MultiBravo* -> Bravo ; + result.addMultiBravo(inputBravo); + result.addMultiBravo(result.getBravo(getInput() + 1)); + + // rel Charlie.MyAlfa? -> Alfa ; + inputCharlie.setMyAlfa(result); + + // rel Alfa.SingleBi1Delta <-> Delta.SingleBack1Alfa? ; + result.setSingleBi1Delta(inputDelta); + // rel Alfa.MultiBi2Delta* <-> Delta.SingleBack2Alfa? ; + result.addMultiBi2Delta(inputDelta); + result.addMultiBi2Delta(result.getDelta(getInput() + 1)); + // rel Alfa.MultiBi3Delta* <-> Delta.MultiBack3Alfa* ; + result.addMultiBi3Delta(inputDelta); + result.addMultiBi3Delta(result.getDelta(getInput() + 1)); + + // rel Alfa.Myself -> Alfa ; + result.setMyself(result); + + // rel Bravo.MyCharlie -> Charlie ; + for (int i = 0; i < 4; i++) { + if (i == getInput()) { + result.getBravo(i).setMyCharlie(inputCharlie); + } else { + result.getBravo(i).setMyCharlie(result.getCharlie(0)); + } + } + // rel Bravo.OptionalCharlie? -> Charlie ; + inputBravo.setOptionalCharlie(inputCharlie); + // rel Bravo.MultiCharlie* -> Charlie ; + inputBravo.addMultiCharlie(inputCharlie); + inputBravo.addMultiCharlie(result.getCharlie(getInput() + 1)); + + // rel Bravo.SingleBi1Delta? <-> Delta.SingleBack1Bravo? ; + inputBravo.setSingleBi1Delta(inputDelta); + // rel Bravo.MultiBi2Delta* <-> Delta.SingleBack2Bravo? ; + inputBravo.addMultiBi2Delta(inputDelta); + inputBravo.addMultiBi2Delta(result.getDelta(getInput() + 1)); + // rel Bravo.MultiBi3Delta* <-> Delta.MultiBack3Bravo* ; + inputBravo.addMultiBi3Delta(inputDelta); + inputBravo.addMultiBi3Delta(result.getDelta(getInput() + 1)); + result.getBravo(getInput() + 1).addMultiBi3Delta(inputDelta); + result.getBravo(getInput() + 1).addMultiBi3Delta(result.getDelta(getInput() + 1)); + + return result; + } + + syn boolean ASTNode.isNameable() = false; + eq Nameable.isNameable() = true; +} + +aspect Testing { + class ReceiverRoot implements org.jastadd.ragconnect.tests.AbstractTreeTest.TestWrapperReceiverRoot {} + class Alfa implements org.jastadd.ragconnect.tests.AbstractTreeTest.TestWrapperAlfa {} + class Bravo implements org.jastadd.ragconnect.tests.AbstractTreeTest.TestWrapperBravo {} + class Charlie implements org.jastadd.ragconnect.tests.AbstractTreeTest.TestWrapperCharlie {} + class Delta implements org.jastadd.ragconnect.tests.AbstractTreeTest.TestWrapperDelta {} +} + +aspect NameResolution { + @Override + protected String Nameable.customID() { + return getClass().getSimpleName() + getID(); + } +} diff --git a/ragconnect.tests/src/test/01-input/tree/Test.relast b/ragconnect.tests/src/test/01-input/tree/Test.relast new file mode 100644 index 0000000000000000000000000000000000000000..f65444660383fa1f44d3b4519f01d16098164bf3 --- /dev/null +++ b/ragconnect.tests/src/test/01-input/tree/Test.relast @@ -0,0 +1,36 @@ +Root ::= SenderRoot* ReceiverRoot* ; + +Nameable ::= <ID:int> ; +SenderRoot : Nameable ::= <Input:int> /Alfa/ ; + +ReceiverRoot : Nameable ::= Alfa ; +Alfa : Nameable ::= <Value:String> Bravo* Charlie* Delta* ; + +Bravo : Nameable ; +Charlie : Nameable ; +Delta : Nameable ; + +rel Alfa.Myself -> Alfa ; + +// Alfa -> Bravo +rel Alfa.MyBravo -> Bravo ; +rel Alfa.OptionalBravo? -> Bravo ; +rel Alfa.MultiBravo* -> Bravo ; + +// Charlie -> Alfa +rel Charlie.MyAlfa? -> Alfa ; + +// Alfa <-> Delta +rel Alfa.SingleBi1Delta <-> Delta.SingleBack1Alfa? ; +rel Alfa.MultiBi2Delta* <-> Delta.SingleBack2Alfa? ; +rel Alfa.MultiBi3Delta* <-> Delta.MultiBack3Alfa* ; + +// Bravo -> Charlie +rel Bravo.MyCharlie -> Charlie ; +rel Bravo.OptionalCharlie? -> Charlie ; +rel Bravo.MultiCharlie* -> Charlie ; + +// Bravo <-> Delta +rel Bravo.SingleBi1Delta? <-> Delta.SingleBack1Bravo? ; +rel Bravo.MultiBi2Delta* <-> Delta.SingleBack2Bravo? ; +rel Bravo.MultiBi3Delta* <-> Delta.MultiBack3Bravo* ; diff --git a/ragconnect.tests/src/test/01-input/tree/TestDependencies.connect b/ragconnect.tests/src/test/01-input/tree/TestDependencies.connect new file mode 100644 index 0000000000000000000000000000000000000000..aa5df696a54404332115d0069279a07f886f2e22 --- /dev/null +++ b/ragconnect.tests/src/test/01-input/tree/TestDependencies.connect @@ -0,0 +1 @@ +SenderRoot.Alfa canDependOn SenderRoot.Input as InputDependency ; diff --git a/ragconnect.tests/src/test/01-input/treeAllowedTokens/README.md b/ragconnect.tests/src/test/01-input/treeAllowedTokens/README.md new file mode 100644 index 0000000000000000000000000000000000000000..c215115106a71daf358568368426b33421cfdd65 --- /dev/null +++ b/ragconnect.tests/src/test/01-input/treeAllowedTokens/README.md @@ -0,0 +1,4 @@ +# Tree Allowed Tokens + +Idea: send and receive subtrees, test different token types within the subtree which was sent. +Once without incremental evaluation (i.e., using manual dependencies), and the other time with incremental evaluation diff --git a/ragconnect.tests/src/test/01-input/treeAllowedTokens/Test.connect b/ragconnect.tests/src/test/01-input/treeAllowedTokens/Test.connect new file mode 100644 index 0000000000000000000000000000000000000000..d872ce56c59097e678e6cff0b25ec422130b6129 --- /dev/null +++ b/ragconnect.tests/src/test/01-input/treeAllowedTokens/Test.connect @@ -0,0 +1,26 @@ +send tree SenderRoot.Alfa ; +receive tree ReceiverRoot.Alfa ; + +receive SenderRoot.Input1WhenFlagIsTrue ; +receive SenderRoot.Input1WhenFlagIsFalse ; +receive SenderRoot.Input2 ; +receive SenderRoot.Input3 ; + +send tree SenderRoot.AlfaPrimitive using Alfa2String ; +receive tree ReceiverRoot.AlfaPrimitive using String2Alfa ; + +Alfa2String maps Alfa alfa to String {: + StringBuilder sb = new StringBuilder(); + sb.append(alfa.getID()).append(":").append(alfa.getStringValue()).append(";"); + return sb.toString(); +:} + +String2Alfa maps String s to Alfa {: + int colonIndex = s.indexOf(":"); + int id = Integer.parseInt(s.substring(0, colonIndex)); + String value = s.substring(colonIndex + 1, s.length() - 1); + Alfa result = new Alfa(); + result.setID(id); + result.setStringValue(value); + return result; +:} diff --git a/ragconnect.tests/src/test/01-input/treeAllowedTokens/Test.jadd b/ragconnect.tests/src/test/01-input/treeAllowedTokens/Test.jadd new file mode 100644 index 0000000000000000000000000000000000000000..e5f8750c50a076498fea4398899fbebb5999620e --- /dev/null +++ b/ragconnect.tests/src/test/01-input/treeAllowedTokens/Test.jadd @@ -0,0 +1,48 @@ +aspect Computation { + syn Alfa SenderRoot.getAlfa() { + Alfa result = new Alfa(); + + // Inputs: <Flag:boolean> <Input1WhenFlagIsTrue:int> <Input1WhenFlagIsFalse:int> <Input2:String> <Input3:double> + + result.setBooleanValue(getFlag()); // boolean + result.setIntValue(getFlag() ? getInput1WhenFlagIsTrue() : getInput1WhenFlagIsFalse()); // int + result.setShortValue((short) (getFlag() ? getInput1WhenFlagIsTrue() : getInput1WhenFlagIsFalse())); // short + result.setLongValue(getFlag() ? getInput1WhenFlagIsTrue() : getInput1WhenFlagIsFalse()); // long + result.setFloatValue((float) getInput3()); // float + result.setDoubleValue(getInput3()); // double + result.setCharValue(getInput2().charAt(0)); // char + result.setStringValue(getInput2()); // String + // needed format: 2011-12-03T10:15:30Z + result.setInstantValue(java.time.Instant.parse(getInput2())); // java.time.Instant + // setting days + result.setPeriodValue(java.time.Period.of(0, 0, getFlag() ? getInput1WhenFlagIsTrue() : getInput1WhenFlagIsFalse())); // java.time.Period + result.setEnumValue(getFlag() ? MyEnum.TRUE : MyEnum.FALSE); // MyEnum + + return result; + } + + syn Alfa SenderRoot.getAlfaPrimitive() { + Alfa result = new Alfa(); + result.setStringValue(getInput2()); + return result; + } + + syn boolean ASTNode.isNameable() = false; + eq Nameable.isNameable() = true; +} + +aspect Enum { + public enum MyEnum { FALSE, TRUE; } +} +aspect Testing { + class ReceiverRoot implements org.jastadd.ragconnect.tests.AbstractTreeAllowedTokensTest.TestWrapperReceiverRoot {} + class Alfa implements org.jastadd.ragconnect.tests.AbstractTreeAllowedTokensTest.TestWrapperAlfa {} +} + +aspect NameResolution { + // this should most likely be generated + @Override + protected String Alfa.customID() { + return "0"; + } +} diff --git a/ragconnect.tests/src/test/01-input/treeAllowedTokens/Test.relast b/ragconnect.tests/src/test/01-input/treeAllowedTokens/Test.relast new file mode 100644 index 0000000000000000000000000000000000000000..591ebb22441a29b5a8561b0ea539367a44d9d2e8 --- /dev/null +++ b/ragconnect.tests/src/test/01-input/treeAllowedTokens/Test.relast @@ -0,0 +1,8 @@ +Root ::= SenderRoot* ReceiverRoot* ; + +Nameable ::= <ID:int> ; +SenderRoot : Nameable ::= <Flag:boolean> <Input1WhenFlagIsTrue:int> <Input1WhenFlagIsFalse:int> <Input2:String> <Input3:double> /Alfa/ /AlfaPrimitive:Alfa/ ; + +ReceiverRoot : Nameable ::= Alfa AlfaPrimitive:Alfa ; + +Alfa : Nameable ::= <BooleanValue:boolean> <IntValue:int> <ShortValue:short> <LongValue:long> <FloatValue:float> <DoubleValue:double> <CharValue:char> <StringValue:String> <InstantValue:java.time.Instant> <PeriodValue:java.time.Period> <EnumValue:MyEnum> ; diff --git a/ragconnect.tests/src/test/01-input/treeAllowedTokens/TestDependencies.connect b/ragconnect.tests/src/test/01-input/treeAllowedTokens/TestDependencies.connect new file mode 100644 index 0000000000000000000000000000000000000000..afa4a832ca4bde7ca584c8b1d8f0fa69ee0955a8 --- /dev/null +++ b/ragconnect.tests/src/test/01-input/treeAllowedTokens/TestDependencies.connect @@ -0,0 +1,7 @@ +SenderRoot.Alfa canDependOn SenderRoot.Flag as FlagDependency ; +SenderRoot.Alfa canDependOn SenderRoot.Input1WhenFlagIsTrue as Input1WhenFlagIsTrueDependency ; +SenderRoot.Alfa canDependOn SenderRoot.Input1WhenFlagIsFalse as Input1WhenFlagIsFalseDependency ; +SenderRoot.Alfa canDependOn SenderRoot.Input2 as Input2Dependency ; +SenderRoot.Alfa canDependOn SenderRoot.Input3 as Input3Dependency ; + +SenderRoot.AlfaPrimitive canDependOn SenderRoot.Input2 as PrimitiveInput2Dependency ; diff --git a/ragconnect.tests/src/test/java/org/jastadd/ragconnect/tests/AbstractMqttTest.java b/ragconnect.tests/src/test/java/org/jastadd/ragconnect/tests/AbstractMqttTest.java index 36baf2cf5ffda1fbb6225daf8f054a40c3a2c331..f2f5ddee691854ef40f8b3ede6820a38e0262c2b 100644 --- a/ragconnect.tests/src/test/java/org/jastadd/ragconnect/tests/AbstractMqttTest.java +++ b/ragconnect.tests/src/test/java/org/jastadd/ragconnect/tests/AbstractMqttTest.java @@ -1,10 +1,7 @@ package org.jastadd.ragconnect.tests; import defaultOnlyRead.ast.MqttHandler; -import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.api.Tag; -import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.*; import java.io.IOException; import java.util.concurrent.TimeUnit; @@ -18,20 +15,22 @@ import java.util.concurrent.TimeUnit; public abstract class AbstractMqttTest { static boolean checkDone = false; - static Boolean checkResult; + static boolean checkResult; + static MqttHandler publisher; @BeforeAll - public static void checkMqttConnection() { + public static void createPublishAndOnceCheckMqttConnection() { + try { + publisher = new MqttHandler("Publisher") + .dontSendWelcomeMessage() + .setHost(TestUtils.getMqttHost()); + checkResult = true; + } catch (IOException e) { + checkResult = false; + } if (!checkDone) { checkDone = true; - try { - checkResult = new MqttHandler() - .dontSendWelcomeMessage() - .setHost(TestUtils.getMqttHost()) - .waitUntilReady(2, TimeUnit.SECONDS); - } catch (IOException e) { - checkResult = false; - } + checkResult &= publisher.waitUntilReady(2, TimeUnit.SECONDS); } if (!checkResult) { throw new IllegalStateException("Mqtt Broker not ready!"); @@ -52,6 +51,10 @@ public abstract class AbstractMqttTest { communicateSendInitialValue(); } + /** + * Actual test code for communication when sending initial value. + * @throws InterruptedException because of TestUtils.waitForMqtt() + */ protected abstract void communicateSendInitialValue() throws InterruptedException; @Tag("mqtt") @@ -63,9 +66,15 @@ public abstract class AbstractMqttTest { communicateOnlyUpdatedValue(); } + /** + * Actual test code for communication without sending any value upon connecting. + * @throws InterruptedException because of TestUtils.waitForMqtt() + */ protected abstract void communicateOnlyUpdatedValue() throws InterruptedException; - + /** + * Create the model, and set required default values. + */ protected abstract void createModel(); /** @@ -79,7 +88,7 @@ public abstract class AbstractMqttTest { * * And then add dependencies, initialise receiver, add connections to those receivers, * and finally call generated connect* methods on model elements. - * @param writeCurrentValue + * @param writeCurrentValue if the initial/current value shall be sent upon connecting */ protected abstract void setupReceiverAndConnect(boolean writeCurrentValue) throws IOException; @@ -101,4 +110,11 @@ public abstract class AbstractMqttTest { */ protected abstract void closeConnections(); + @AfterAll + public static void closePublisher() { + if (publisher != null) { + publisher.close(); + } + } + } diff --git a/ragconnect.tests/src/test/java/org/jastadd/ragconnect/tests/AbstractTreeAllowedTokensTest.java b/ragconnect.tests/src/test/java/org/jastadd/ragconnect/tests/AbstractTreeAllowedTokensTest.java new file mode 100644 index 0000000000000000000000000000000000000000..e87a298fe92e0019fa7da2012d6630590d7a348e --- /dev/null +++ b/ragconnect.tests/src/test/java/org/jastadd/ragconnect/tests/AbstractTreeAllowedTokensTest.java @@ -0,0 +1,216 @@ +package org.jastadd.ragconnect.tests; + +import java.io.IOException; +import java.time.Instant; +import java.time.Period; + +import static org.junit.jupiter.api.Assertions.*; + +/** + * Base class for test cases "tree allowed tokens manual" and "tree allowed tokens incremental". + * + * @author rschoene - Initial contribution + */ +public abstract class AbstractTreeAllowedTokensTest extends AbstractMqttTest { + + protected static final String TOPIC_INPUT1TRUE = "input1/true"; + protected static final String TOPIC_INPUT1FALSE = "input1/false"; + protected static final String TOPIC_INPUT2 = "input2"; + protected static final String TOPIC_INPUT3 = "input3"; + protected static final String TOPIC_ALFA = "alfa"; + protected static final String TOPIC_ALFA_PRIMITIVE = "primitive"; + + protected static final String INSTANT_A = "1999-12-03T10:15:30Z"; + protected static final String INSTANT_B = "2011-12-03T10:15:30Z"; + protected static final String INSTANT_C = "2012-12-03T10:15:30Z"; + + protected TestWrapperReceiverRoot receiverRoot; + + public interface TestWrapperReceiverRoot { + TestWrapperAlfa getAlfa(); + TestWrapperAlfa getAlfaPrimitive(); + boolean connectAlfa(String mqttUri) throws IOException; + boolean connectAlfaPrimitive(String mqttUri) throws IOException; + } + public interface TestWrapperAlfa { + boolean getBooleanValue(); + int getIntValue(); + short getShortValue(); + long getLongValue(); + float getFloatValue(); + double getDoubleValue(); + String getStringValue(); + char getCharValue(); + Instant getInstantValue(); + Period getPeriodValue(); + } + + @Override + protected void communicateSendInitialValue() throws InterruptedException { + checkTree(1, false, 0, INSTANT_A, 0); + checkPrimitiveTree(1, INSTANT_A); + + // flag: false. sendInput1WhenFalse(2) + sendInput1WhenFalse(2); + checkTree(2, false, 2, INSTANT_A, 0); + checkPrimitiveTree(1, INSTANT_A); + + // flag: false. setFlag(false) -> no change + setFlag(false); + checkTree(2, false, 2, INSTANT_A, 0); + checkPrimitiveTree(1, INSTANT_A); + + // flag: false. setFlag(true) + setFlag(true); + checkTree(3, true, 0, INSTANT_A, 0); + checkPrimitiveTree(1, INSTANT_A); + + // flag: true. sendInput1WhenFalse(3) -> no change + sendInput1WhenFalse(3); + checkTree(3, true, 0, INSTANT_A, 0); + checkPrimitiveTree(1, INSTANT_A); + + // flag: true. sendInput1WhenTrue(4) + sendInput1WhenTrue(4); + checkTree(4, true, 4, INSTANT_A, 0); + checkPrimitiveTree(1, INSTANT_A); + + // sendInput2(INSTANT_B) + sendInput2(INSTANT_B); + checkTree(5, true, 4, INSTANT_B, 0); + checkPrimitiveTree(2, INSTANT_B); + + // sendInput2(INSTANT_B) -> no change + sendInput2(INSTANT_B); + checkTree(5, true, 4, INSTANT_B, 0); + checkPrimitiveTree(2, INSTANT_B); + + // sendInput3(5.1) + sendInput3(5.1); + checkTree(6, true, 4, INSTANT_B, 5.1); + checkPrimitiveTree(2, INSTANT_B); + + // sendInput3(5.1) -> no change + sendInput3(5.1); + checkTree(6, true, 4, INSTANT_B, 5.1); + checkPrimitiveTree(2, INSTANT_B); + } + + @Override + protected void communicateOnlyUpdatedValue() throws InterruptedException { + checkTree(0, false, null, null, 0); + checkPrimitiveTree(0, null); + + // flag: false. sendInput1WhenFalse(12) + sendInput1WhenFalse(12); + checkTree(1, false, 12, INSTANT_A, 0); + checkPrimitiveTree(0, null); + + // flag: false. setFlag(false) -> no change + setFlag(false); + checkTree(1, false, 12, INSTANT_A, 0); + checkPrimitiveTree(0, null); + + // flag: false. setFlag(true) + setFlag(true); + checkTree(2, true, 0, INSTANT_A, 0); + checkPrimitiveTree(0, null); + + // flag: true. sendInput1WhenFalse(13) -> no change + sendInput1WhenFalse(13); + checkTree(2, true, 0, INSTANT_A, 0); + checkPrimitiveTree(0, null); + + // flag: true. sendInput1WhenTrue(14) + sendInput1WhenTrue(14); + checkTree(3, true, 14, INSTANT_A, 0); + checkPrimitiveTree(0, null); + + // sendInput2(INSTANT_C) + sendInput2(INSTANT_C); + checkTree(4, true, 14, INSTANT_C, 0); + checkPrimitiveTree(1, INSTANT_C); + + // sendInput2(INSTANT_C) -> no change + sendInput2(INSTANT_C); + checkTree(4, true, 14, INSTANT_C, 0); + checkPrimitiveTree(1, INSTANT_C); + + // sendInput3(15.1) + sendInput3(15.1); + checkTree(5, true, 14, INSTANT_C, 15.1); + checkPrimitiveTree(1, INSTANT_C); + + // sendInput3(15.1) -> no change + sendInput3(15.1); + checkTree(5, true, 14, INSTANT_C, 15.1); + checkPrimitiveTree(1, INSTANT_C); + } + + protected void sendInput1WhenFalse(int value) { + publisher.publish(TOPIC_INPUT1FALSE, TestUtils.DefaultMappings.IntToBytes(value)); + } + + protected void sendInput1WhenTrue(int value) { + publisher.publish(TOPIC_INPUT1TRUE, TestUtils.DefaultMappings.IntToBytes(value)); + } + + protected void sendInput2(String value) { + publisher.publish(TOPIC_INPUT2, TestUtils.DefaultMappings.StringToBytes(value)); + } + + protected void sendInput3(double value) { + publisher.publish(TOPIC_INPUT3, TestUtils.DefaultMappings.DoubleToBytes(value)); + } + + protected abstract void setFlag(boolean value); + + protected void checkTree(int expectedCount, boolean expectedBooleanValue, Integer expectedIntValue, String expectedStringValue, double expectedDoubleValue) throws InterruptedException { + TestUtils.waitForMqtt(); + + assertEquals(expectedCount, data.numberOfTrees); + if (expectedStringValue == null) { + assertNull(receiverRoot.getAlfa()); + } else { + assertNotNull(receiverRoot.getAlfa()); + TestWrapperAlfa alfa = receiverRoot.getAlfa(); + + assertEquals(expectedBooleanValue, alfa.getBooleanValue()); + assertEquals(expectedIntValue, alfa.getIntValue()); + assertEquals(expectedIntValue.shortValue(), alfa.getShortValue()); + assertEquals(expectedIntValue.longValue(), alfa.getLongValue()); + + assertEquals(expectedDoubleValue, alfa.getFloatValue(), TestUtils.DELTA); + assertEquals(expectedDoubleValue, alfa.getDoubleValue(), TestUtils.DELTA); + + assertEquals(expectedStringValue, alfa.getStringValue()); + assertEquals(expectedStringValue.charAt(0), alfa.getCharValue()); + assertEquals(Instant.parse(expectedStringValue), alfa.getInstantValue()); + assertEquals(Period.of(0, 0, expectedIntValue), alfa.getPeriodValue()); + + checkMyEnum(alfa, expectedBooleanValue); + } + } + + protected void checkPrimitiveTree(int expectedCount, String expectedStringValue) { + assertEquals(expectedCount, data.numberOfPrimitiveTrees); + if (expectedStringValue == null) { + assertNull(receiverRoot.getAlfaPrimitive()); + } else { + assertNotNull(receiverRoot.getAlfaPrimitive()); + + TestWrapperAlfa alfaPrimitive = receiverRoot.getAlfaPrimitive(); + assertEquals(expectedStringValue, alfaPrimitive.getStringValue()); + } + } + + protected abstract void checkMyEnum(TestWrapperAlfa alfa, boolean expectedBooleanValue); + + protected ReceiverData data; + + protected static class ReceiverData { + int numberOfTrees = 0; + int numberOfPrimitiveTrees = 0; + } + +} diff --git a/ragconnect.tests/src/test/java/org/jastadd/ragconnect/tests/AbstractTreeTest.java b/ragconnect.tests/src/test/java/org/jastadd/ragconnect/tests/AbstractTreeTest.java new file mode 100644 index 0000000000000000000000000000000000000000..069f622c84cf95508575143b3b9d23288f42bc4a --- /dev/null +++ b/ragconnect.tests/src/test/java/org/jastadd/ragconnect/tests/AbstractTreeTest.java @@ -0,0 +1,206 @@ +package org.jastadd.ragconnect.tests; + +import java.io.IOException; +import java.util.List; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.*; + +/** + * Base class for test cases "tree manual" and "tree incremental". + * + * @author rschoene - Initial contribution + */ +public abstract class AbstractTreeTest extends AbstractMqttTest { + protected static final String TOPIC_ALFA = "alfa"; + protected ReceiverData data; + protected TestWrapperReceiverRoot receiverRoot; + + public interface TestWrapperReceiverRoot { + TestWrapperAlfa getAlfa(); + boolean connectAlfa(String mqttUri) throws IOException; + } + public interface TestWrapperAlfa { + TestWrapperBravo getBravo(int i); + int getNumBravo(); + int getNumCharlie(); + int getNumDelta(); + + TestWrapperAlfa getMyself(); + TestWrapperBravo getMyBravo(); + boolean hasOptionalBravo(); + TestWrapperBravo getOptionalBravo(); + TestWrapperCharlie getCharlie(int i); + TestWrapperDelta getDelta(int i); + <T extends TestWrapperBravo> List<T> getMultiBravoList(); + } + public interface TestWrapperBravo { + + TestWrapperCharlie getMyCharlie(); + boolean hasOptionalCharlie(); + TestWrapperCharlie getOptionalCharlie(); + <T extends TestWrapperCharlie> List<T> getMultiCharlieList(); + boolean hasSingleBi1Delta(); + TestWrapperDelta getSingleBi1Delta(); + <T extends TestWrapperDelta> List<T> getMultiBi2DeltaList(); + <T extends TestWrapperDelta> List<T> getMultiBi3DeltaList(); + } + public interface TestWrapperCharlie { + boolean hasMyAlfa(); + TestWrapperAlfa getMyAlfa(); + } + public interface TestWrapperDelta { + boolean hasSingleBack1Alfa(); + TestWrapperAlfa getSingleBack1Alfa(); + boolean hasSingleBack2Alfa(); + TestWrapperAlfa getSingleBack2Alfa(); + <T extends TestWrapperAlfa> List<T> getMultiBack3AlfaList(); + boolean hasSingleBack1Bravo(); + TestWrapperBravo getSingleBack1Bravo(); + TestWrapperBravo getSingleBack2Bravo(); + boolean hasSingleBack2Bravo(); + <T extends TestWrapperBravo> List<T> getMultiBack3BravoList(); + } + + @Override + protected void communicateSendInitialValue() throws InterruptedException { + checkTree(1, 0); + + setInput(1); + checkTree(2, 1); + + setInput(1); + checkTree(2, 1); + + setInput(2); + checkTree(3, 2); + } + + @Override + protected void communicateOnlyUpdatedValue() throws InterruptedException { + checkTree(0, null); + + setInput(1); + checkTree(1, 1); + + setInput(1); + checkTree(1, 1); + + setInput(2); + checkTree(2, 2); + } + + protected abstract void setInput(int input); + + protected void checkTree(int expectedCount, Integer expectedInput) throws InterruptedException { + TestUtils.waitForMqtt(); + + assertEquals(expectedCount, data.numberOfTrees); + if (expectedInput == null) { + assertNull(receiverRoot.getAlfa()); + } else { + assertNotNull(receiverRoot.getAlfa()); + TestWrapperAlfa alfa = receiverRoot.getAlfa(); + assertEquals(4, alfa.getNumBravo()); + assertEquals(4, alfa.getNumCharlie()); + assertEquals(4, alfa.getNumDelta()); + + TestWrapperBravo inputBravo = alfa.getBravo(expectedInput); + TestWrapperCharlie inputCharlie = alfa.getCharlie(expectedInput); + TestWrapperDelta inputDelta = alfa.getDelta(expectedInput); + + // Alfa -> Alfa + assertEquals(alfa, alfa.getMyself()); + + // Alfa -> Bravo + assertEquals(inputBravo, alfa.getMyBravo()); + assertTrue(alfa.hasOptionalBravo()); + assertEquals(inputBravo, alfa.getOptionalBravo()); + assertThat(alfa.getMultiBravoList()).containsExactly( + inputBravo, alfa.getBravo(expectedInput + 1)); + + // Charlie -> Alfa + for (int i = 0; i < 4; i++) { + TestWrapperCharlie Charlie = alfa.getCharlie(i); + if (i == expectedInput) { + assertTrue(Charlie.hasMyAlfa()); + assertEquals(alfa, Charlie.getMyAlfa()); + } else { + assertFalse(Charlie.hasMyAlfa()); + } + } + + // Alfa <-> Delta + for (int i = 0; i < 4; i++) { + TestWrapperDelta Delta = alfa.getDelta(i); + if (i == expectedInput) { + assertTrue(Delta.hasSingleBack1Alfa()); + assertEquals(alfa, Delta.getSingleBack1Alfa()); + } else { + assertFalse(Delta.hasSingleBack1Alfa()); + } + if (i == expectedInput || i == expectedInput + 1) { + assertTrue(Delta.hasSingleBack2Alfa()); + assertEquals(alfa, Delta.getSingleBack2Alfa()); + assertThat(Delta.getMultiBack3AlfaList()).containsExactly(alfa); + } else { + assertFalse(Delta.hasSingleBack2Alfa()); + assertThat(Delta.getMultiBack3AlfaList()).isEmpty(); + } + } + + // Bravo -> Charlie + for (int i = 0; i < 4; i++) { + TestWrapperBravo Bravo = alfa.getBravo(i); + + if (i == expectedInput) { + assertEquals(inputCharlie, Bravo.getMyCharlie()); + assertTrue(Bravo.hasOptionalCharlie()); + assertEquals(inputCharlie, Bravo.getOptionalCharlie()); + assertThat(Bravo.getMultiCharlieList()).containsExactly( + inputCharlie, alfa.getCharlie(expectedInput + 1)); + } else { + assertEquals(alfa.getCharlie(0), Bravo.getMyCharlie()); + assertFalse(Bravo.hasOptionalCharlie()); + assertThat(Bravo.getMultiCharlieList()).isEmpty(); + } + } + + // Bravo <-> Delta + for (int i = 0; i < 4; i++) { + TestWrapperBravo Bravo = alfa.getBravo(i); + TestWrapperDelta Delta = alfa.getDelta(i); + + if (i == expectedInput) { + assertTrue(Bravo.hasSingleBi1Delta()); + assertTrue(Delta.hasSingleBack1Bravo()); + assertEquals(inputDelta, Bravo.getSingleBi1Delta()); + assertEquals(inputBravo, Delta.getSingleBack1Bravo()); + assertThat(Bravo.getMultiBi2DeltaList()).containsExactly( + inputDelta, alfa.getDelta(expectedInput + 1)); + } else { + assertFalse(Bravo.hasSingleBi1Delta()); + assertFalse(Delta.hasSingleBack1Bravo()); + assertThat(Bravo.getMultiBi2DeltaList()).isEmpty(); + } + if (i == expectedInput || i == expectedInput + 1) { + assertThat(Bravo.getMultiBi3DeltaList()).containsExactly( + inputDelta, alfa.getDelta(expectedInput + 1)); + assertTrue(Delta.hasSingleBack2Bravo()); + assertEquals(inputBravo, Delta.getSingleBack2Bravo()); + assertThat(Delta.getMultiBack3BravoList()).containsExactly( + inputBravo, alfa.getBravo(expectedInput + 1)); + } else { + assertThat(Bravo.getMultiBi3DeltaList()).isEmpty(); + assertFalse(Delta.hasSingleBack2Bravo()); + assertThat(Delta.getMultiBack3BravoList()).isEmpty(); + } + } + } + } + + protected static class ReceiverData { + int numberOfTrees = 0; + } + +} diff --git a/ragconnect.tests/src/test/java/org/jastadd/ragconnect/tests/DefaultOnlyReadTest.java b/ragconnect.tests/src/test/java/org/jastadd/ragconnect/tests/DefaultOnlyReadTest.java index 844f35d61b64364aa271a82fe770401f7ab8ba5f..cf5e02f956ae55258f08458bcb88130e1afca4b0 100644 --- a/ragconnect.tests/src/test/java/org/jastadd/ragconnect/tests/DefaultOnlyReadTest.java +++ b/ragconnect.tests/src/test/java/org/jastadd/ragconnect/tests/DefaultOnlyReadTest.java @@ -4,11 +4,13 @@ import defaultOnlyRead.ast.A; import defaultOnlyRead.ast.BoxedTypes; import defaultOnlyRead.ast.MqttHandler; import defaultOnlyRead.ast.NativeTypes; +import org.junit.jupiter.api.Test; import java.io.IOException; +import java.nio.file.Paths; import java.util.concurrent.TimeUnit; -import static org.jastadd.ragconnect.tests.TestUtils.mqttUri; +import static org.jastadd.ragconnect.tests.TestUtils.*; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertTrue; @@ -41,7 +43,13 @@ public class DefaultOnlyReadTest extends AbstractMqttTest { private NativeTypes floats; private NativeTypes chars; private BoxedTypes allBoxed; - private MqttHandler sender; + + @Test + public void checkNotJacksonReference() { + testJaddContainReferenceToJackson( + Paths.get("src", "test", + "02-after-ragconnect", "defaultOnlyRead", "RagConnect.jadd"), false); + } @Override protected void createModel() { @@ -93,9 +101,6 @@ public class DefaultOnlyReadTest extends AbstractMqttTest { allBoxed.connectFloatValueTransformed(mqttUri(TOPIC_BOXED_FLOAT)); allBoxed.connectDoubleValueTransformed(mqttUri(TOPIC_BOXED_DOUBLE)); allBoxed.connectCharValueTransformed(mqttUri(TOPIC_BOXED_CHARACTER)); - - sender = new MqttHandler().dontSendWelcomeMessage().setHost(TestUtils.getMqttHost()); - assertTrue(sender.waitUntilReady(2, TimeUnit.SECONDS)); } @Override @@ -114,22 +119,22 @@ public class DefaultOnlyReadTest extends AbstractMqttTest { final char expectedCharValue = 'c'; final String expectedStringValue = "6.3"; - sender.publish(TOPIC_NATIVE_BOOLEAN, TestUtils.DefaultMappings.BoolToBytes(expectedBooleanValue)); - sender.publish(TOPIC_NATIVE_INT, TestUtils.DefaultMappings.IntToBytes(expectedIntValue)); - sender.publish(TOPIC_NATIVE_SHORT, TestUtils.DefaultMappings.ShortToBytes(expectedShortValue)); - sender.publish(TOPIC_NATIVE_LONG, TestUtils.DefaultMappings.LongToBytes(expectedLongValue)); - sender.publish(TOPIC_NATIVE_FLOAT, TestUtils.DefaultMappings.FloatToBytes(expectedFloatValue)); - sender.publish(TOPIC_NATIVE_DOUBLE, TestUtils.DefaultMappings.DoubleToBytes(expectedDoubleValue)); - sender.publish(TOPIC_NATIVE_CHAR, TestUtils.DefaultMappings.CharToBytes(expectedCharValue)); - sender.publish(TOPIC_NATIVE_STRING, TestUtils.DefaultMappings.StringToBytes(expectedStringValue)); - - sender.publish(TOPIC_BOXED_BOOLEAN, TestUtils.DefaultMappings.BoolToBytes(expectedBooleanValue)); - sender.publish(TOPIC_BOXED_INTEGER, TestUtils.DefaultMappings.IntToBytes(expectedIntValue)); - sender.publish(TOPIC_BOXED_SHORT, TestUtils.DefaultMappings.ShortToBytes(expectedShortValue)); - sender.publish(TOPIC_BOXED_LONG, TestUtils.DefaultMappings.LongToBytes(expectedLongValue)); - sender.publish(TOPIC_BOXED_FLOAT, TestUtils.DefaultMappings.FloatToBytes(expectedFloatValue)); - sender.publish(TOPIC_BOXED_DOUBLE, TestUtils.DefaultMappings.DoubleToBytes(expectedDoubleValue)); - sender.publish(TOPIC_BOXED_CHARACTER, TestUtils.DefaultMappings.CharToBytes(expectedCharValue)); + publisher.publish(TOPIC_NATIVE_BOOLEAN, TestUtils.DefaultMappings.BoolToBytes(expectedBooleanValue)); + publisher.publish(TOPIC_NATIVE_INT, TestUtils.DefaultMappings.IntToBytes(expectedIntValue)); + publisher.publish(TOPIC_NATIVE_SHORT, TestUtils.DefaultMappings.ShortToBytes(expectedShortValue)); + publisher.publish(TOPIC_NATIVE_LONG, TestUtils.DefaultMappings.LongToBytes(expectedLongValue)); + publisher.publish(TOPIC_NATIVE_FLOAT, TestUtils.DefaultMappings.FloatToBytes(expectedFloatValue)); + publisher.publish(TOPIC_NATIVE_DOUBLE, TestUtils.DefaultMappings.DoubleToBytes(expectedDoubleValue)); + publisher.publish(TOPIC_NATIVE_CHAR, TestUtils.DefaultMappings.CharToBytes(expectedCharValue)); + publisher.publish(TOPIC_NATIVE_STRING, TestUtils.DefaultMappings.StringToBytes(expectedStringValue)); + + publisher.publish(TOPIC_BOXED_BOOLEAN, TestUtils.DefaultMappings.BoolToBytes(expectedBooleanValue)); + publisher.publish(TOPIC_BOXED_INTEGER, TestUtils.DefaultMappings.IntToBytes(expectedIntValue)); + publisher.publish(TOPIC_BOXED_SHORT, TestUtils.DefaultMappings.ShortToBytes(expectedShortValue)); + publisher.publish(TOPIC_BOXED_LONG, TestUtils.DefaultMappings.LongToBytes(expectedLongValue)); + publisher.publish(TOPIC_BOXED_FLOAT, TestUtils.DefaultMappings.FloatToBytes(expectedFloatValue)); + publisher.publish(TOPIC_BOXED_DOUBLE, TestUtils.DefaultMappings.DoubleToBytes(expectedDoubleValue)); + publisher.publish(TOPIC_BOXED_CHARACTER, TestUtils.DefaultMappings.CharToBytes(expectedCharValue)); TestUtils.waitForMqtt(); @@ -170,9 +175,6 @@ public class DefaultOnlyReadTest extends AbstractMqttTest { @Override public void closeConnections() { - if (sender != null) { - sender.close(); - } if (model != null) { model.ragconnectCloseConnections(); } diff --git a/ragconnect.tests/src/test/java/org/jastadd/ragconnect/tests/DefaultOnlyWriteTest.java b/ragconnect.tests/src/test/java/org/jastadd/ragconnect/tests/DefaultOnlyWriteTest.java index a5d20afb5a2b98ee5e9aef0fac0102ecced2b15a..c18b185503053ec03428f620ea1aaa5df2505354 100644 --- a/ragconnect.tests/src/test/java/org/jastadd/ragconnect/tests/DefaultOnlyWriteTest.java +++ b/ragconnect.tests/src/test/java/org/jastadd/ragconnect/tests/DefaultOnlyWriteTest.java @@ -4,11 +4,13 @@ import defaultOnlyWrite.ast.A; import defaultOnlyWrite.ast.BoxedTypesSyn; import defaultOnlyWrite.ast.MqttHandler; import defaultOnlyWrite.ast.NativeTypesSyn; +import org.junit.jupiter.api.Test; import java.io.IOException; +import java.nio.file.Paths; import java.util.concurrent.TimeUnit; -import static org.jastadd.ragconnect.tests.TestUtils.mqttUri; +import static org.jastadd.ragconnect.tests.TestUtils.*; import static org.junit.jupiter.api.Assertions.*; /** @@ -63,6 +65,13 @@ public class DefaultOnlyWriteTest extends AbstractMqttTest { private ReceiverData dataNormal; private ReceiverData dataTransformed; + @Test + public void checkNotJacksonReference() { + testJaddContainReferenceToJackson( + Paths.get("src", "test", + "02-after-ragconnect", "defaultOnlyWrite", "RagConnect.jadd"), false); + } + @Override protected void createModel() { model = new A(); diff --git a/ragconnect.tests/src/test/java/org/jastadd/ragconnect/tests/ExampleTest.java b/ragconnect.tests/src/test/java/org/jastadd/ragconnect/tests/ExampleTest.java index c3fae394f191920fdfdbe9be818a0393516faa9d..17bc074545fd2815c750d957dd1038586c5ff018 100644 --- a/ragconnect.tests/src/test/java/org/jastadd/ragconnect/tests/ExampleTest.java +++ b/ragconnect.tests/src/test/java/org/jastadd/ragconnect/tests/ExampleTest.java @@ -251,13 +251,13 @@ public class ExampleTest extends AbstractMqttTest { createModel(); setupReceiverAndConnect(false); - handler.publish(TOPIC_JOINT1, "not-a-pandaLinkState".getBytes()); + publisher.publish(TOPIC_JOINT1, "not-a-pandaLinkState".getBytes()); assertEquals(0, data.numberOfConfigs); assertTrue(data.failedLastConversion); } private void sendData(String topic, float x, float y, float z) { - handler.publish(topic, RobotState.newBuilder() + publisher.publish(topic, RobotState.newBuilder() .setPosition(RobotState.Position.newBuilder().setX(x).setY(y).setZ(z).build()) .build() .toByteArray() diff --git a/ragconnect.tests/src/test/java/org/jastadd/ragconnect/tests/IncrementalDependencyTest.java b/ragconnect.tests/src/test/java/org/jastadd/ragconnect/tests/IncrementalDependencyTest.java index e7d6555ef302f59f8ada8d77a9e6a33c262910cc..43fe8b349e2f10568238042276faf2d43c74271d 100644 --- a/ragconnect.tests/src/test/java/org/jastadd/ragconnect/tests/IncrementalDependencyTest.java +++ b/ragconnect.tests/src/test/java/org/jastadd/ragconnect/tests/IncrementalDependencyTest.java @@ -3,7 +3,6 @@ package org.jastadd.ragconnect.tests; import incremental.ast.A; import incremental.ast.B; import incremental.ast.MqttHandler; -import org.junit.jupiter.api.Tag; import java.io.IOException; import java.util.concurrent.TimeUnit; @@ -144,7 +143,7 @@ public class IncrementalDependencyTest extends AbstractMqttTest { } private void sendData(String input) throws InterruptedException { - handler.publish(TOPIC_IN, input.getBytes()); + publisher.publish(TOPIC_IN, input.getBytes()); TestUtils.waitForMqtt(); } diff --git a/ragconnect.tests/src/test/java/org/jastadd/ragconnect/tests/MappingTest.java b/ragconnect.tests/src/test/java/org/jastadd/ragconnect/tests/MappingTest.java index 2c7cd6ccf9d0a2ac3ce353fcc025881938194191..7f83e3387688f578e47f6ac67c14e5f7fb26a688 100644 --- a/ragconnect.tests/src/test/java/org/jastadd/ragconnect/tests/MappingTest.java +++ b/ragconnect.tests/src/test/java/org/jastadd/ragconnect/tests/MappingTest.java @@ -168,7 +168,7 @@ public class MappingTest extends AbstractMqttTest { private void sendAndSetData(String driver, String input) { natives.setDriver(driver); - handler.publish(TOPIC_INPUT, input.getBytes()); + publisher.publish(TOPIC_INPUT, input.getBytes()); } private void checkSendData(int expectedNumberOfValues, int expectedInt, short expectedShort, long expectedLong, float expectedFloat, double expectedDouble, char expectedChar, int expectedNumberOfBooleanValues, boolean expectedBoolean) throws InterruptedException { diff --git a/ragconnect.tests/src/test/java/org/jastadd/ragconnect/tests/Read1Write2Test.java b/ragconnect.tests/src/test/java/org/jastadd/ragconnect/tests/Read1Write2Test.java index 57db1a70581249d94023a3865264085d4cfa1334..889ce0531a6b61196856f40c5045920517b8dfd3 100644 --- a/ragconnect.tests/src/test/java/org/jastadd/ragconnect/tests/Read1Write2Test.java +++ b/ragconnect.tests/src/test/java/org/jastadd/ragconnect/tests/Read1Write2Test.java @@ -174,8 +174,8 @@ public class Read1Write2Test extends AbstractMqttTest { } private void sendData(String inputSame, String inputDifferent) { - handler.publish(TOPIC_SAME_READ, inputSame.getBytes()); - handler.publish(TOPIC_DIFFERENT_READ, inputDifferent.getBytes()); + publisher.publish(TOPIC_SAME_READ, inputSame.getBytes()); + publisher.publish(TOPIC_DIFFERENT_READ, inputDifferent.getBytes()); } private void setDataOnlySame(String inputSame) { diff --git a/ragconnect.tests/src/test/java/org/jastadd/ragconnect/tests/Read2Write1Test.java b/ragconnect.tests/src/test/java/org/jastadd/ragconnect/tests/Read2Write1Test.java index 048528bd895d45d4a296907cb4580b72f07f5b02..f0f634c8e031bcadac54b09dd644d34c1f2a8dff 100644 --- a/ragconnect.tests/src/test/java/org/jastadd/ragconnect/tests/Read2Write1Test.java +++ b/ragconnect.tests/src/test/java/org/jastadd/ragconnect/tests/Read2Write1Test.java @@ -167,14 +167,14 @@ public class Read2Write1Test extends AbstractMqttTest { private void sendData(boolean useSameInput1, String inputSame, boolean useDifferentInput1, String inputDifferent) { - handler.publish(useSameInput1 ? TOPIC_SAME_READ1 : TOPIC_SAME_READ2, + publisher.publish(useSameInput1 ? TOPIC_SAME_READ1 : TOPIC_SAME_READ2, inputSame.getBytes()); - handler.publish(useDifferentInput1 ? TOPIC_DIFFERENT_READ1 : TOPIC_DIFFERENT_READ2, + publisher.publish(useDifferentInput1 ? TOPIC_DIFFERENT_READ1 : TOPIC_DIFFERENT_READ2, inputDifferent.getBytes()); } private void setDataOnlySame(String inputSame) { - handler.publish(TOPIC_SAME_READ1, inputSame.getBytes()); + publisher.publish(TOPIC_SAME_READ1, inputSame.getBytes()); } private void checkData(int numberOfSameValues, Integer lastSameIntValue, diff --git a/ragconnect.tests/src/test/java/org/jastadd/ragconnect/tests/TestUtils.java b/ragconnect.tests/src/test/java/org/jastadd/ragconnect/tests/TestUtils.java index 5958b395d7920e70e71bfa6a4f49866dfce4c087..776e7a01b5f2c683c09cb2dfd3b3e496f41110ad 100644 --- a/ragconnect.tests/src/test/java/org/jastadd/ragconnect/tests/TestUtils.java +++ b/ragconnect.tests/src/test/java/org/jastadd/ragconnect/tests/TestUtils.java @@ -1,14 +1,15 @@ package org.jastadd.ragconnect.tests; -import defaultOnlyRead.ast.ASTNode; - import java.io.File; import java.io.IOException; import java.nio.charset.Charset; import java.nio.file.Files; +import java.nio.file.Path; import java.nio.file.Paths; import java.util.concurrent.TimeUnit; +import static org.junit.jupiter.api.Assertions.fail; + /** * Utility methods for tests. * @@ -63,6 +64,21 @@ public class TestUtils { return process.exitValue(); } + public static void testJaddContainReferenceToJackson(Path path, boolean shouldContain) { + try { + String content = Files.readString(path); + boolean actualContain = content.contains("com.fasterxml.jackson.databind.ObjectMapper"); + if (actualContain && !shouldContain) { + fail(path + " should not depend on jackson library, but does"); + } + if (!actualContain && shouldContain) { + fail(path + " does not depend on jackson library"); + } + } catch (IOException e) { + fail(e); + } + } + public static String readFile(String path, Charset encoding) throws IOException { byte[] encoded = Files.readAllBytes(Paths.get(path)); @@ -74,10 +90,64 @@ public class TestUtils { } @SuppressWarnings({"unused", "rawtypes"}) - static class DefaultMappings extends ASTNode { + static class DefaultMappings { + static class ReadNode extends defaultOnlyRead.ast.ASTNode { + public static boolean _apply__DefaultBytesToBooleanMapping(byte[] input) throws Exception { + return defaultOnlyRead.ast.ASTNode._apply__DefaultBytesToBooleanMapping(input); + } + public static int _apply__DefaultBytesToIntMapping(byte[] input) throws Exception { + return defaultOnlyRead.ast.ASTNode._apply__DefaultBytesToIntMapping(input); + } + public static short _apply__DefaultBytesToShortMapping(byte[] input) throws Exception { + return defaultOnlyRead.ast.ASTNode._apply__DefaultBytesToShortMapping(input); + } + public static long _apply__DefaultBytesToLongMapping(byte[] input) throws Exception { + return defaultOnlyRead.ast.ASTNode._apply__DefaultBytesToLongMapping(input); + } + public static float _apply__DefaultBytesToFloatMapping(byte[] input) throws Exception { + return defaultOnlyRead.ast.ASTNode._apply__DefaultBytesToFloatMapping(input); + } + public static double _apply__DefaultBytesToDoubleMapping(byte[] input) throws Exception { + return defaultOnlyRead.ast.ASTNode._apply__DefaultBytesToDoubleMapping(input); + } + public static char _apply__DefaultBytesToCharMapping(byte[] input) throws Exception { + return defaultOnlyRead.ast.ASTNode._apply__DefaultBytesToCharMapping(input); + } + public static String _apply__DefaultBytesToStringMapping(byte[] input) throws Exception { + return defaultOnlyRead.ast.ASTNode._apply__DefaultBytesToStringMapping(input); + } + } + + static class WriteNode extends defaultOnlyWrite.ast.ASTNode { + public static byte[] _apply__DefaultBooleanToBytesMapping(boolean input) throws Exception { + return defaultOnlyWrite.ast.ASTNode._apply__DefaultBooleanToBytesMapping(input); + } + public static byte[] _apply__DefaultIntToBytesMapping(int input) throws Exception { + return defaultOnlyWrite.ast.ASTNode._apply__DefaultIntToBytesMapping(input); + } + public static byte[] _apply__DefaultShortToBytesMapping(short input) throws Exception { + return defaultOnlyWrite.ast.ASTNode._apply__DefaultShortToBytesMapping(input); + } + public static byte[] _apply__DefaultLongToBytesMapping(long input) throws Exception { + return defaultOnlyWrite.ast.ASTNode._apply__DefaultLongToBytesMapping(input); + } + public static byte[] _apply__DefaultFloatToBytesMapping(float input) throws Exception { + return defaultOnlyWrite.ast.ASTNode._apply__DefaultFloatToBytesMapping(input); + } + public static byte[] _apply__DefaultDoubleToBytesMapping(double input) throws Exception { + return defaultOnlyWrite.ast.ASTNode._apply__DefaultDoubleToBytesMapping(input); + } + public static byte[] _apply__DefaultCharToBytesMapping(char input) throws Exception { + return defaultOnlyWrite.ast.ASTNode._apply__DefaultCharToBytesMapping(input); + } + public static byte[] _apply__DefaultStringToBytesMapping(String input) throws Exception { + return defaultOnlyWrite.ast.ASTNode._apply__DefaultStringToBytesMapping(input); + } + } + public static boolean BytesToBool(byte[] input) { try { - return _apply__DefaultBytesToBooleanMapping(input); + return ReadNode._apply__DefaultBytesToBooleanMapping(input); } catch (Exception e) { e.printStackTrace(); return false; @@ -85,7 +155,7 @@ public class TestUtils { } public static int BytesToInt(byte[] input) { try { - return _apply__DefaultBytesToIntMapping(input); + return ReadNode._apply__DefaultBytesToIntMapping(input); } catch (Exception e) { e.printStackTrace(); return 0; @@ -93,7 +163,7 @@ public class TestUtils { } public static short BytesToShort(byte[] input) { try { - return _apply__DefaultBytesToShortMapping(input); + return ReadNode._apply__DefaultBytesToShortMapping(input); } catch (Exception e) { e.printStackTrace(); return 0; @@ -101,7 +171,7 @@ public class TestUtils { } public static long BytesToLong(byte[] input) { try { - return _apply__DefaultBytesToLongMapping(input); + return ReadNode._apply__DefaultBytesToLongMapping(input); } catch (Exception e) { e.printStackTrace(); return 0; @@ -109,7 +179,7 @@ public class TestUtils { } public static float BytesToFloat(byte[] input) { try { - return _apply__DefaultBytesToFloatMapping(input); + return ReadNode._apply__DefaultBytesToFloatMapping(input); } catch (Exception e) { e.printStackTrace(); return 0; @@ -117,7 +187,7 @@ public class TestUtils { } public static double BytesToDouble(byte[] input) { try { - return _apply__DefaultBytesToDoubleMapping(input); + return ReadNode._apply__DefaultBytesToDoubleMapping(input); } catch (Exception e) { e.printStackTrace(); return 0; @@ -125,7 +195,7 @@ public class TestUtils { } public static char BytesToChar(byte[] input) { try { - return _apply__DefaultBytesToCharMapping(input); + return ReadNode._apply__DefaultBytesToCharMapping(input); } catch (Exception e) { e.printStackTrace(); return 0; @@ -133,7 +203,7 @@ public class TestUtils { } public static String BytesToString(byte[] input) { try { - return _apply__DefaultBytesToStringMapping(input); + return ReadNode._apply__DefaultBytesToStringMapping(input); } catch (Exception e) { e.printStackTrace(); return null; @@ -141,7 +211,7 @@ public class TestUtils { } public static byte[] BoolToBytes(boolean input) { try { - return _apply__DefaultBooleanToBytesMapping(input); + return WriteNode._apply__DefaultBooleanToBytesMapping(input); } catch (Exception e) { e.printStackTrace(); return null; @@ -149,7 +219,7 @@ public class TestUtils { } public static byte[] IntToBytes(int input) { try { - return _apply__DefaultIntToBytesMapping(input); + return WriteNode._apply__DefaultIntToBytesMapping(input); } catch (Exception e) { e.printStackTrace(); return null; @@ -157,7 +227,7 @@ public class TestUtils { } public static byte[] ShortToBytes(short input) { try { - return _apply__DefaultShortToBytesMapping(input); + return WriteNode._apply__DefaultShortToBytesMapping(input); } catch (Exception e) { e.printStackTrace(); return null; @@ -165,7 +235,7 @@ public class TestUtils { } public static byte[] LongToBytes(long input) { try { - return _apply__DefaultLongToBytesMapping(input); + return WriteNode._apply__DefaultLongToBytesMapping(input); } catch (Exception e) { e.printStackTrace(); return null; @@ -173,7 +243,7 @@ public class TestUtils { } public static byte[] FloatToBytes(float input) { try { - return _apply__DefaultFloatToBytesMapping(input); + return WriteNode._apply__DefaultFloatToBytesMapping(input); } catch (Exception e) { e.printStackTrace(); return null; @@ -181,7 +251,7 @@ public class TestUtils { } public static byte[] DoubleToBytes(double input) { try { - return _apply__DefaultDoubleToBytesMapping(input); + return WriteNode._apply__DefaultDoubleToBytesMapping(input); } catch (Exception e) { e.printStackTrace(); return null; @@ -189,7 +259,7 @@ public class TestUtils { } public static byte[] CharToBytes(char input) { try { - return _apply__DefaultCharToBytesMapping(input); + return WriteNode._apply__DefaultCharToBytesMapping(input); } catch (Exception e) { e.printStackTrace(); return null; @@ -197,7 +267,7 @@ public class TestUtils { } public static byte[] StringToBytes(String input) { try { - return _apply__DefaultStringToBytesMapping(input); + return WriteNode._apply__DefaultStringToBytesMapping(input); } catch (Exception e) { e.printStackTrace(); return null; diff --git a/ragconnect.tests/src/test/java/org/jastadd/ragconnect/tests/TokenValueSendTest.java b/ragconnect.tests/src/test/java/org/jastadd/ragconnect/tests/TokenValueSendTest.java index 8c8c461df4bfdc8e2d21b9520815fb20807ae240..b22a2fb6ac2d4fcfe5c78332f64a5ec6025613d9 100644 --- a/ragconnect.tests/src/test/java/org/jastadd/ragconnect/tests/TokenValueSendTest.java +++ b/ragconnect.tests/src/test/java/org/jastadd/ragconnect/tests/TokenValueSendTest.java @@ -226,8 +226,8 @@ public class TokenValueSendTest extends AbstractMqttTest { } private void sendData(String inputTwo, String inputThree) { - handler.publish(TOPIC_RECEIVE_TWO, inputTwo.getBytes()); - handler.publish(TOPIC_RECEIVE_THREE_VALUE, inputThree.getBytes()); + publisher.publish(TOPIC_RECEIVE_TWO, inputTwo.getBytes()); + publisher.publish(TOPIC_RECEIVE_THREE_VALUE, inputThree.getBytes()); } private void setData(String inputOne, String inputTwo, String inputThree) { diff --git a/ragconnect.tests/src/test/java/org/jastadd/ragconnect/tests/TreeAllowedTokensIncrementalTest.java b/ragconnect.tests/src/test/java/org/jastadd/ragconnect/tests/TreeAllowedTokensIncrementalTest.java new file mode 100644 index 0000000000000000000000000000000000000000..5dd1b1504701b0c5499e7277b8287e1b66a9e5a5 --- /dev/null +++ b/ragconnect.tests/src/test/java/org/jastadd/ragconnect/tests/TreeAllowedTokensIncrementalTest.java @@ -0,0 +1,89 @@ +package org.jastadd.ragconnect.tests; + +import org.junit.jupiter.api.Tag; +import org.junit.jupiter.api.Test; +import treeAllowedTokensInc.ast.*; + +import java.io.IOException; +import java.nio.file.Paths; +import java.util.concurrent.TimeUnit; + +import static org.jastadd.ragconnect.tests.TestUtils.mqttUri; +import static org.jastadd.ragconnect.tests.TestUtils.testJaddContainReferenceToJackson; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; + +/** + * Test case "tree allowed tokens incremental" + * + * @author rschoene - Initial contribution + */ +@Tag("SpecificTest") +public class TreeAllowedTokensIncrementalTest extends AbstractTreeAllowedTokensTest { + + private Root model; + private SenderRoot senderRoot; + private MqttHandler handler; + + @Test + public void checkJacksonReference() { + testJaddContainReferenceToJackson( + Paths.get("src", "test", + "02-after-ragconnect", "treeAllowedTokens", "RagConnect.jadd"), true); + } + + @Override + protected void createModel() { + model = new Root(); + senderRoot = new SenderRoot(); + senderRoot.setFlag(false); + senderRoot.setInput2(INSTANT_A); + model.addSenderRoot(senderRoot); + + receiverRoot = new ReceiverRoot(); + model.addReceiverRoot((ReceiverRoot) receiverRoot); + } + + @Override + protected void setupReceiverAndConnect(boolean writeCurrentValue) throws IOException { + model.ragconnectSetupMqttWaitUntilReady(2, TimeUnit.SECONDS); + + handler = new MqttHandler().dontSendWelcomeMessage().setHost(TestUtils.getMqttHost()); + assertTrue(handler.waitUntilReady(2, TimeUnit.SECONDS)); + + // no dependencies + + data = new ReceiverData(); + handler.newConnection(TOPIC_ALFA, bytes -> data.numberOfTrees += 1); + handler.newConnection(TOPIC_ALFA_PRIMITIVE, bytes -> data.numberOfPrimitiveTrees += 1); + + // connect. important: first receiver, then sender. to not miss initial value. + senderRoot.connectInput1WhenFlagIsFalse(mqttUri(TOPIC_INPUT1FALSE)); + senderRoot.connectInput1WhenFlagIsTrue(mqttUri(TOPIC_INPUT1TRUE)); + senderRoot.connectInput2(mqttUri(TOPIC_INPUT2)); + senderRoot.connectInput3(mqttUri(TOPIC_INPUT3)); + receiverRoot.connectAlfa(mqttUri(TOPIC_ALFA)); + receiverRoot.connectAlfaPrimitive(mqttUri(TOPIC_ALFA_PRIMITIVE)); + senderRoot.connectAlfa(mqttUri(TOPIC_ALFA), writeCurrentValue); + senderRoot.connectAlfaPrimitive(mqttUri(TOPIC_ALFA_PRIMITIVE), writeCurrentValue); + } + + @Override + protected void closeConnections() { + if (handler != null) { + handler.close(); + } + if (model != null) { + model.ragconnectCloseConnections(); + } + } + + protected void setFlag(boolean value) { + senderRoot.setFlag(value); + } + + @Override + protected void checkMyEnum(TestWrapperAlfa alfa, boolean expectedBooleanValue) { + assertEquals(expectedBooleanValue ? MyEnum.TRUE : MyEnum.FALSE, ((Alfa) alfa).getEnumValue()); + } +} diff --git a/ragconnect.tests/src/test/java/org/jastadd/ragconnect/tests/TreeAllowedTokensManualTest.java b/ragconnect.tests/src/test/java/org/jastadd/ragconnect/tests/TreeAllowedTokensManualTest.java new file mode 100644 index 0000000000000000000000000000000000000000..c3b91a04f45a47250f2cdf557575c5c48ac09c05 --- /dev/null +++ b/ragconnect.tests/src/test/java/org/jastadd/ragconnect/tests/TreeAllowedTokensManualTest.java @@ -0,0 +1,94 @@ +package org.jastadd.ragconnect.tests; + +import org.junit.jupiter.api.Test; +import treeAllowedTokens.ast.*; + +import java.io.IOException; +import java.nio.file.Paths; +import java.time.Instant; +import java.time.Period; +import java.util.concurrent.TimeUnit; + +import static org.jastadd.ragconnect.tests.TestUtils.mqttUri; +import static org.jastadd.ragconnect.tests.TestUtils.testJaddContainReferenceToJackson; +import static org.junit.jupiter.api.Assertions.*; + +/** + * Test case "tree allowed tokens manual" + * + * @author rschoene - Initial contribution + */ +public class TreeAllowedTokensManualTest extends AbstractTreeAllowedTokensTest { + + private Root model; + private SenderRoot senderRoot; + private MqttHandler handler; + + @Test + public void checkJacksonReference() { + testJaddContainReferenceToJackson( + Paths.get("src", "test", + "02-after-ragconnect", "treeAllowedTokens", "RagConnect.jadd"), true); + } + + @Override + protected void createModel() { + model = new Root(); + senderRoot = new SenderRoot(); + senderRoot.setFlag(false); + senderRoot.setInput2(INSTANT_A); + model.addSenderRoot(senderRoot); + + receiverRoot = new ReceiverRoot(); + model.addReceiverRoot((ReceiverRoot) receiverRoot); + } + + @Override + protected void setupReceiverAndConnect(boolean writeCurrentValue) throws IOException { + model.ragconnectSetupMqttWaitUntilReady(2, TimeUnit.SECONDS); + + handler = new MqttHandler().dontSendWelcomeMessage().setHost(TestUtils.getMqttHost()); + assertTrue(handler.waitUntilReady(2, TimeUnit.SECONDS)); + + // add dependencies + senderRoot.addFlagDependency(senderRoot); + senderRoot.addInput1WhenFlagIsFalseDependency(senderRoot); + senderRoot.addInput1WhenFlagIsTrueDependency(senderRoot); + senderRoot.addInput2Dependency(senderRoot); + senderRoot.addInput3Dependency(senderRoot); + senderRoot.addPrimitiveInput2Dependency(senderRoot); + + data = new ReceiverData(); + handler.newConnection(TOPIC_ALFA, bytes -> data.numberOfTrees += 1); + handler.newConnection(TOPIC_ALFA_PRIMITIVE, bytes -> data.numberOfPrimitiveTrees += 1); + + // connect. important: first receiver, then sender. to not miss initial value. + senderRoot.connectInput1WhenFlagIsFalse(mqttUri(TOPIC_INPUT1FALSE)); + senderRoot.connectInput1WhenFlagIsTrue(mqttUri(TOPIC_INPUT1TRUE)); + senderRoot.connectInput2(mqttUri(TOPIC_INPUT2)); + senderRoot.connectInput3(mqttUri(TOPIC_INPUT3)); + receiverRoot.connectAlfa(mqttUri(TOPIC_ALFA)); + receiverRoot.connectAlfaPrimitive(mqttUri(TOPIC_ALFA_PRIMITIVE)); + senderRoot.connectAlfa(mqttUri(TOPIC_ALFA), writeCurrentValue); + senderRoot.connectAlfaPrimitive(mqttUri(TOPIC_ALFA_PRIMITIVE), writeCurrentValue); + } + + @Override + protected void closeConnections() { + if (handler != null) { + handler.close(); + } + if (model != null) { + model.ragconnectCloseConnections(); + } + } + + protected void setFlag(boolean value) { + senderRoot.setFlag(value); + } + + @Override + protected void checkMyEnum(TestWrapperAlfa alfa, boolean expectedBooleanValue) { + assertEquals(expectedBooleanValue ? MyEnum.TRUE : MyEnum.FALSE, ((Alfa) alfa).getEnumValue()); + } +} diff --git a/ragconnect.tests/src/test/java/org/jastadd/ragconnect/tests/TreeIncrementalTest.java b/ragconnect.tests/src/test/java/org/jastadd/ragconnect/tests/TreeIncrementalTest.java new file mode 100644 index 0000000000000000000000000000000000000000..e0d7c817e372395adf98565b5a44347335a2eb45 --- /dev/null +++ b/ragconnect.tests/src/test/java/org/jastadd/ragconnect/tests/TreeIncrementalTest.java @@ -0,0 +1,73 @@ +package org.jastadd.ragconnect.tests; + +import org.junit.jupiter.api.Test; +import treeInc.ast.*; + +import java.io.IOException; +import java.nio.file.Paths; +import java.util.concurrent.TimeUnit; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.jastadd.ragconnect.tests.TestUtils.mqttUri; +import static org.jastadd.ragconnect.tests.TestUtils.testJaddContainReferenceToJackson; +import static org.junit.jupiter.api.Assertions.*; + +/** + * Test case "tree incremental" + * + * @author rschoene - Initial contribution + */ +public class TreeIncrementalTest extends AbstractTreeTest { + + private Root model; + private SenderRoot senderRoot; + private MqttHandler handler; + + @Test + public void checkJacksonReference() { + testJaddContainReferenceToJackson( + Paths.get("src", "test", + "02-after-ragconnect", "treeInc", "RagConnect.jadd"), true); + } + + @Override + protected void createModel() { + model = new Root(); + senderRoot = new SenderRoot(); + model.addSenderRoot(senderRoot); + + receiverRoot = new ReceiverRoot(); + model.addReceiverRoot((ReceiverRoot) receiverRoot); + } + + @Override + protected void setupReceiverAndConnect(boolean writeCurrentValue) throws IOException { + model.ragconnectSetupMqttWaitUntilReady(2, TimeUnit.SECONDS); + + handler = new MqttHandler().dontSendWelcomeMessage().setHost(TestUtils.getMqttHost()); + assertTrue(handler.waitUntilReady(2, TimeUnit.SECONDS)); + + // no dependencies + + data = new ReceiverData(); + handler.newConnection(TOPIC_ALFA, bytes -> data.numberOfTrees += 1); + + // connect. important: first receiver, then sender. to not miss initial value. + receiverRoot.connectAlfa(mqttUri(TOPIC_ALFA)); + senderRoot.connectAlfa(mqttUri(TOPIC_ALFA), writeCurrentValue); + } + + @Override + protected void closeConnections() { + if (handler != null) { + handler.close(); + } + if (model != null) { + model.ragconnectCloseConnections(); + } + } + + protected void setInput(int input) { + senderRoot.setInput(input); + } +} diff --git a/ragconnect.tests/src/test/java/org/jastadd/ragconnect/tests/TreeManualTest.java b/ragconnect.tests/src/test/java/org/jastadd/ragconnect/tests/TreeManualTest.java new file mode 100644 index 0000000000000000000000000000000000000000..060317dfd749f0815af9fe42d1cb9553fe9034ae --- /dev/null +++ b/ragconnect.tests/src/test/java/org/jastadd/ragconnect/tests/TreeManualTest.java @@ -0,0 +1,76 @@ +package org.jastadd.ragconnect.tests; + +import org.junit.jupiter.api.Test; +import tree.ast.MqttHandler; +import tree.ast.ReceiverRoot; +import tree.ast.Root; +import tree.ast.SenderRoot; + +import java.io.IOException; +import java.nio.file.Paths; +import java.util.concurrent.TimeUnit; + +import static org.jastadd.ragconnect.tests.TestUtils.mqttUri; +import static org.jastadd.ragconnect.tests.TestUtils.testJaddContainReferenceToJackson; +import static org.junit.jupiter.api.Assertions.assertTrue; + +/** + * Test case "tree manual" + * + * @author rschoene - Initial contribution + */ +public class TreeManualTest extends AbstractTreeTest { + + private Root model; + private SenderRoot senderRoot; + private MqttHandler handler; + + @Test + public void checkJacksonReference() { + testJaddContainReferenceToJackson( + Paths.get("src", "test", + "02-after-ragconnect", "tree", "RagConnect.jadd"), true); + } + + @Override + protected void createModel() { + model = new Root(); + senderRoot = new SenderRoot(); + model.addSenderRoot(senderRoot); + + receiverRoot = new ReceiverRoot(); + model.addReceiverRoot((ReceiverRoot) receiverRoot); + } + + @Override + protected void setupReceiverAndConnect(boolean writeCurrentValue) throws IOException { + model.ragconnectSetupMqttWaitUntilReady(2, TimeUnit.SECONDS); + + handler = new MqttHandler().dontSendWelcomeMessage().setHost(TestUtils.getMqttHost()); + assertTrue(handler.waitUntilReady(2, TimeUnit.SECONDS)); + + // add dependencies + senderRoot.addInputDependency(senderRoot); + + data = new ReceiverData(); + handler.newConnection(TOPIC_ALFA, bytes -> data.numberOfTrees += 1); + + // connect. important: first receiver, then sender. to not miss initial value. + receiverRoot.connectAlfa(mqttUri(TOPIC_ALFA)); + senderRoot.connectAlfa(mqttUri(TOPIC_ALFA), writeCurrentValue); + } + + @Override + protected void closeConnections() { + if (handler != null) { + handler.close(); + } + if (model != null) { + model.ragconnectCloseConnections(); + } + } + + protected void setInput(int input) { + senderRoot.setInput(input); + } +} diff --git a/ragconnect.tests/src/test/java/org/jastadd/ragconnect/tests/ViaTest.java b/ragconnect.tests/src/test/java/org/jastadd/ragconnect/tests/ViaTest.java index 766208f725c6a73c6dd391a20cd0b105ac894a77..5433514398ea8ec3037f95fbc1c63bbb6a1cf2be 100644 --- a/ragconnect.tests/src/test/java/org/jastadd/ragconnect/tests/ViaTest.java +++ b/ragconnect.tests/src/test/java/org/jastadd/ragconnect/tests/ViaTest.java @@ -57,16 +57,68 @@ public class ViaTest extends AbstractMqttTest { private WebTarget senderBoth2Rest; @Override - public void closeConnections() { - if (handler != null) { - handler.close(); - } - if (model != null) { - model.ragconnectCloseConnections(); - } + protected void createModel() { + // Setting value for Input without dependencies does not trigger any updates + model = new A(); + model.setMqtt2MqttInput("100"); + model.setRest2RestInput("200"); + model.setMqtt2RestInput("300"); + model.setRest2MqttInput("400"); + model.setBoth2BothInput("500"); } + @Override + protected void setupReceiverAndConnect(boolean writeCurrentValue) throws IOException { + model.ragconnectSetupMqttWaitUntilReady(2, TimeUnit.SECONDS); + + handler = new MqttHandler().dontSendWelcomeMessage().setHost(TestUtils.getMqttHost()); + assertTrue(handler.waitUntilReady(2, TimeUnit.SECONDS)); + + model.addDependencyMqtt2Mqtt(model); + model.addDependencyRest2Rest(model); + model.addDependencyMqtt2Rest(model); + model.addDependencyRest2Mqtt(model); + model.addDependencyBoth2Mqtt(model); + model.addDependencyBoth2Rest(model); + + dataMqtt2Mqtt = new ReceiverData(); + dataRest2Mqtt = new ReceiverData(); + dataBoth2Mqtt = new ReceiverData(); + + handler.newConnection(TOPIC_MQTT_2_MQTT_SEND, bytes -> { + dataMqtt2Mqtt.numberOfStringValues += 1; + dataMqtt2Mqtt.lastStringValue = TestUtils.DefaultMappings.BytesToString(bytes); + }); + handler.newConnection(TOPIC_REST_2_MQTT_SEND, bytes -> { + dataRest2Mqtt.numberOfStringValues += 1; + dataRest2Mqtt.lastStringValue = TestUtils.DefaultMappings.BytesToString(bytes); + }); + handler.newConnection(TOPIC_BOTH_2_MQTT_SEND, bytes -> { + dataBoth2Mqtt.numberOfStringValues += 1; + dataBoth2Mqtt.lastStringValue = TestUtils.DefaultMappings.BytesToString(bytes); + }); + + Client client = ClientBuilder.newClient(); + dataRest2Rest = client.target(REST_SERVER_BASE_URL + PATH_REST_2_REST_SEND); + dataMqtt2Rest = client.target(REST_SERVER_BASE_URL + PATH_MQTT_2_REST_SEND); + dataBoth2Rest = client.target(REST_SERVER_BASE_URL + PATH_BOTH_2_REST_SEND); + senderRest2Rest = client.target(REST_SERVER_BASE_URL + PATH_REST_2_REST_RECEIVE); + senderRest2Mqtt = client.target(REST_SERVER_BASE_URL + PATH_REST_2_MQTT_RECEIVE); + senderBoth2Rest = client.target(REST_SERVER_BASE_URL + PATH_BOTH_REST_RECEIVE); + model.connectMqtt2MqttInput(mqttUri(TOPIC_MQTT_2_MQTT_RECEIVE)); + model.connectMqtt2MqttOutput(mqttUri(TOPIC_MQTT_2_MQTT_SEND), writeCurrentValue); + model.connectMqtt2RestInput(mqttUri(TOPIC_MQTT_2_REST_RECEIVE)); + model.connectMqtt2RestOutput(restUri(PATH_MQTT_2_REST_SEND, REST_PORT), writeCurrentValue); + model.connectRest2MqttInput(restUri(PATH_REST_2_MQTT_RECEIVE, REST_PORT)); + model.connectRest2MqttOutput(mqttUri(TOPIC_REST_2_MQTT_SEND), writeCurrentValue); + model.connectRest2RestInput(restUri(PATH_REST_2_REST_RECEIVE, REST_PORT)); + model.connectRest2RestOutput(restUri(PATH_REST_2_REST_SEND, REST_PORT), writeCurrentValue); + model.connectBoth2BothInput(mqttUri(TOPIC_BOTH_MQTT_RECEIVE)); + model.connectBoth2BothInput(restUri(PATH_BOTH_REST_RECEIVE, REST_PORT)); + model.connectBoth2MqttOutput(mqttUri(TOPIC_BOTH_2_MQTT_SEND), writeCurrentValue); + model.connectBoth2RestOutput(restUri(PATH_BOTH_2_REST_SEND, REST_PORT), writeCurrentValue); + } @Override protected void communicateSendInitialValue() throws InterruptedException { @@ -212,16 +264,26 @@ public class ViaTest extends AbstractMqttTest { "512-B2R-ToRest"); } + @Override + public void closeConnections() { + if (handler != null) { + handler.close(); + } + if (model != null) { + model.ragconnectCloseConnections(); + } + } + private void sendData(String inputMqtt2Mqtt, String inputRest2Rest, String inputMqtt2Rest, String inputRest2Mqtt) { - handler.publish(TOPIC_MQTT_2_MQTT_RECEIVE, inputMqtt2Mqtt.getBytes()); + publisher.publish(TOPIC_MQTT_2_MQTT_RECEIVE, inputMqtt2Mqtt.getBytes()); senderRest2Rest.request().put(Entity.entity(inputRest2Rest, MediaType.TEXT_PLAIN_TYPE)); - handler.publish(TOPIC_MQTT_2_REST_RECEIVE, inputMqtt2Rest.getBytes()); + publisher.publish(TOPIC_MQTT_2_REST_RECEIVE, inputMqtt2Rest.getBytes()); senderRest2Mqtt.request().put(Entity.entity(inputRest2Mqtt, MediaType.TEXT_PLAIN_TYPE)); } private void sendDataForBoth(String input, boolean useMqtt) { if (useMqtt) { - handler.publish(TOPIC_BOTH_MQTT_RECEIVE, input.getBytes()); + publisher.publish(TOPIC_BOTH_MQTT_RECEIVE, input.getBytes()); } else { senderBoth2Rest.request().put(Entity.entity(input, MediaType.TEXT_PLAIN_TYPE)); } @@ -248,70 +310,6 @@ public class ViaTest extends AbstractMqttTest { return dataBoth2Rest.request().get().readEntity(String.class); } - @Override - protected void createModel() { - // Setting value for Input without dependencies does not trigger any updates - model = new A(); - model.setMqtt2MqttInput("100"); - model.setRest2RestInput("200"); - model.setMqtt2RestInput("300"); - model.setRest2MqttInput("400"); - model.setBoth2BothInput("500"); - } - - @Override - protected void setupReceiverAndConnect(boolean writeCurrentValue) throws IOException { - model.ragconnectSetupMqttWaitUntilReady(2, TimeUnit.SECONDS); - - handler = new MqttHandler().dontSendWelcomeMessage().setHost(TestUtils.getMqttHost()); - assertTrue(handler.waitUntilReady(2, TimeUnit.SECONDS)); - - model.addDependencyMqtt2Mqtt(model); - model.addDependencyRest2Rest(model); - model.addDependencyMqtt2Rest(model); - model.addDependencyRest2Mqtt(model); - model.addDependencyBoth2Mqtt(model); - model.addDependencyBoth2Rest(model); - - dataMqtt2Mqtt = new ReceiverData(); - dataRest2Mqtt = new ReceiverData(); - dataBoth2Mqtt = new ReceiverData(); - - handler.newConnection(TOPIC_MQTT_2_MQTT_SEND, bytes -> { - dataMqtt2Mqtt.numberOfStringValues += 1; - dataMqtt2Mqtt.lastStringValue = TestUtils.DefaultMappings.BytesToString(bytes); - }); - handler.newConnection(TOPIC_REST_2_MQTT_SEND, bytes -> { - dataRest2Mqtt.numberOfStringValues += 1; - dataRest2Mqtt.lastStringValue = TestUtils.DefaultMappings.BytesToString(bytes); - }); - handler.newConnection(TOPIC_BOTH_2_MQTT_SEND, bytes -> { - dataBoth2Mqtt.numberOfStringValues += 1; - dataBoth2Mqtt.lastStringValue = TestUtils.DefaultMappings.BytesToString(bytes); - }); - - Client client = ClientBuilder.newClient(); - dataRest2Rest = client.target(REST_SERVER_BASE_URL + PATH_REST_2_REST_SEND); - dataMqtt2Rest = client.target(REST_SERVER_BASE_URL + PATH_MQTT_2_REST_SEND); - dataBoth2Rest = client.target(REST_SERVER_BASE_URL + PATH_BOTH_2_REST_SEND); - senderRest2Rest = client.target(REST_SERVER_BASE_URL + PATH_REST_2_REST_RECEIVE); - senderRest2Mqtt = client.target(REST_SERVER_BASE_URL + PATH_REST_2_MQTT_RECEIVE); - senderBoth2Rest = client.target(REST_SERVER_BASE_URL + PATH_BOTH_REST_RECEIVE); - - model.connectMqtt2MqttInput(mqttUri(TOPIC_MQTT_2_MQTT_RECEIVE)); - model.connectMqtt2MqttOutput(mqttUri(TOPIC_MQTT_2_MQTT_SEND), writeCurrentValue); - model.connectMqtt2RestInput(mqttUri(TOPIC_MQTT_2_REST_RECEIVE)); - model.connectMqtt2RestOutput(restUri(PATH_MQTT_2_REST_SEND, REST_PORT), writeCurrentValue); - model.connectRest2MqttInput(restUri(PATH_REST_2_MQTT_RECEIVE, REST_PORT)); - model.connectRest2MqttOutput(mqttUri(TOPIC_REST_2_MQTT_SEND), writeCurrentValue); - model.connectRest2RestInput(restUri(PATH_REST_2_REST_RECEIVE, REST_PORT)); - model.connectRest2RestOutput(restUri(PATH_REST_2_REST_SEND, REST_PORT), writeCurrentValue); - model.connectBoth2BothInput(mqttUri(TOPIC_BOTH_MQTT_RECEIVE)); - model.connectBoth2BothInput(restUri(PATH_BOTH_REST_RECEIVE, REST_PORT)); - model.connectBoth2MqttOutput(mqttUri(TOPIC_BOTH_2_MQTT_SEND), writeCurrentValue); - model.connectBoth2RestOutput(restUri(PATH_BOTH_2_REST_SEND, REST_PORT), writeCurrentValue); - } - private static class ReceiverData { String lastStringValue; int numberOfStringValues = 0;