diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 2bd5703df929c32cdef66c41e99cb66092c9adca..56c0e1b7d49ac9c19ac72b6e1bbc0d7be7b1191c 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -32,7 +32,7 @@ test: image: openjdk:11 stage: test services: - - name: "eclipse-mosquitto:1.6.9" + - name: "eclipse-mosquitto:1.6" alias: "mqtt" needs: - build diff --git a/.gitmodules b/.gitmodules index 0163ef86549d9ee0ba792961799f705881d1f893..58efd108e858ae06dde5f626286bd3d73f9dde4e 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,7 +1,4 @@ [submodule "relast-preprocessor"] path = relast-preprocessor url = ../relast-preprocessor.git - branch = jastadd-fix-inc-param-debug -[submodule "ragconnect.base/src/main/jastadd/mustache"] - path = ragconnect.base/src/main/jastadd/mustache - url = ../mustache + branch = develop diff --git a/libs/jastadd2.jar b/libs/jastadd2.jar new file mode 100644 index 0000000000000000000000000000000000000000..d615b895453d660f0e7397fffad58a05029169fd Binary files /dev/null and b/libs/jastadd2.jar differ diff --git a/pages/docs/changelog.md b/pages/docs/changelog.md new file mode 100644 index 0000000000000000000000000000000000000000..eb0fe4d555048fb90f71cec631baafeaef35a4d7 --- /dev/null +++ b/pages/docs/changelog.md @@ -0,0 +1,17 @@ +# Changelog + +## 0.3.1 + +- Full support for incremental dependency tracking +- Full support for subtree endpoint definitions ([#9](https://git-st.inf.tu-dresden.de/jastadd/ragconnect/-/issues/9)) +- Internal: Use updated gradle plugin for tests ([#18](https://git-st.inf.tu-dresden.de/jastadd/ragconnect/-/issues/18)) +- Bugfix [#22](https://git-st.inf.tu-dresden.de/jastadd/ragconnect/-/issues/22): Correct handling of malformed URIs passed when connecting an endpoint +- Bugfix [#23](https://git-st.inf.tu-dresden.de/jastadd/ragconnect/-/issues/23): Correct handling of OptComponents as endpoints +- Bugfix [#27](https://git-st.inf.tu-dresden.de/jastadd/ragconnect/-/issues/27): Correctly handle whitespaces in grammars + +## 0.3.0 + +- Added [API documentation](ragdoc/index.html) to documentation +- Add methods to `disconnect` an endpoint +- Internal: PoC for incremental dependency tracking and subtree endpoint definitions ([#14](https://git-st.inf.tu-dresden.de/jastadd/ragconnect/-/issues/14)) +- Bugfix [#17](https://git-st.inf.tu-dresden.de/jastadd/ragconnect/-/issues/17): Added missing support for `boolean` diff --git a/pages/mkdocs.yml b/pages/mkdocs.yml index a2f77dc9ba0b011450d8c6326ac3880998b1b793..6363c73ae7ac43b9c4d04c4eb0036ef36fb5019a 100644 --- a/pages/mkdocs.yml +++ b/pages/mkdocs.yml @@ -5,6 +5,7 @@ nav: - inner-workings.md - using.md - extending.md + - changelog.md - API documentation: ragdoc/index.html theme: name: readthedocs diff --git a/ragconnect.base/build.gradle b/ragconnect.base/build.gradle index 0a96c5864e96fd1746cd8b2f9e1fa66da21f46a7..77bafe579a620ca243e1061785fcf1ddef8a3108 100644 --- a/ragconnect.base/build.gradle +++ b/ragconnect.base/build.gradle @@ -27,11 +27,9 @@ repositories { dependencies { implementation project(':relast-preprocessor') - implementation group: 'org.apache.logging.log4j', name: 'log4j-api', version: "${log4j_version}" - 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.5' +// runtimeOnly group: 'org.jastadd', name: 'jastadd', version: '2.3.5' + runtimeOnly fileTree(include: ['jastadd2.jar'], dir: '../libs') api group: 'net.sf.beaver', name: 'beaver-rt', version: '0.9.11' } @@ -67,14 +65,12 @@ idea.module.generatedSourceDirs += genSrc jar { manifest { attributes "Main-Class": 'org.jastadd.ragconnect.compiler.Compiler' - - // Log4J + Java 11 compatibility, see https://stackoverflow.com/q/53049346/2493208 - attributes "Multi-Release": true } from { configurations.runtimeClasspath.collect { it.isDirectory() ? it : zipTree(it) } } + duplicatesStrategy = DuplicatesStrategy.EXCLUDE archiveBaseName = 'ragconnect' } @@ -82,7 +78,7 @@ jar { File preprocessorGrammar = file('../relast-preprocessor/src/main/jastadd/RelAst.relast') File ragConnectGrammar = file('./src/main/jastadd/RagConnect.relast') File intermediateGrammar = file('./src/main/jastadd/intermediate/MustacheNodes.relast') -File mustacheGrammar = file('./src/main/jastadd/mustache/Mustache.relast') +File mustacheGrammar = file('../relast-preprocessor/src/main/jastadd/mustache/Mustache.relast') task relast(type: JavaExec) { group = 'Build' main = "-jar" @@ -224,3 +220,4 @@ publishing { } publish.dependsOn jar +jar.dependsOn ":relast-preprocessor:jar" diff --git a/ragconnect.base/src/main/jastadd/Analysis.jrag b/ragconnect.base/src/main/jastadd/Analysis.jrag index f55044dddb1582d41689a138818ad2114d2d6fd7..e8afb8ba2d4bb1485be30b543812b48e291dd4b3 100644 --- a/ragconnect.base/src/main/jastadd/Analysis.jrag +++ b/ragconnect.base/src/main/jastadd/Analysis.jrag @@ -1,10 +1,10 @@ aspect Analysis { // --- lookupTokenEndpointDefinition --- inh java.util.List<TokenEndpointDefinition> TokenEndpointDefinition.lookupTokenEndpointDefinitions(TokenComponent token); - eq RagConnect.getEndpointDefinition().lookupTokenEndpointDefinitions(TokenComponent token) = lookupTokenEndpointDefinitions(token); + eq RagConnect.getConnectSpecificationFile().lookupTokenEndpointDefinitions(TokenComponent token) = lookupTokenEndpointDefinitions(token); syn java.util.List<TokenEndpointDefinition> RagConnect.lookupTokenEndpointDefinitions(TokenComponent token) { java.util.List<TokenEndpointDefinition> result = new java.util.ArrayList<>(); - for (EndpointDefinition def : getEndpointDefinitionList()) { + for (EndpointDefinition def : allEndpointDefinitionList()) { if (def.isTokenEndpointDefinition() && def.asTokenEndpointDefinition().getToken().equals(token)) { result.add(def.asTokenEndpointDefinition()); } @@ -14,10 +14,10 @@ aspect Analysis { // --- lookupTypeEndpointDefinition --- inh java.util.List<TypeEndpointDefinition> TypeEndpointDefinition.lookupTypeEndpointDefinitions(TypeComponent type); - eq RagConnect.getEndpointDefinition().lookupTypeEndpointDefinitions(TypeComponent type) = lookupTypeEndpointDefinitions(type); + eq RagConnect.getConnectSpecificationFile().lookupTypeEndpointDefinitions(TypeComponent type) = lookupTypeEndpointDefinitions(type); syn java.util.List<TypeEndpointDefinition> RagConnect.lookupTypeEndpointDefinitions(TypeComponent type) { java.util.List<TypeEndpointDefinition> result = new java.util.ArrayList<>(); - for (EndpointDefinition def : getEndpointDefinitionList()) { + for (EndpointDefinition def : allEndpointDefinitionList()) { if (def.isTypeEndpointDefinition() && def.asTypeEndpointDefinition().getType().equals(type)) { result.add(def.asTypeEndpointDefinition()); } @@ -27,8 +27,8 @@ aspect Analysis { // --- lookupDependencyDefinition --- inh DependencyDefinition DependencyDefinition.lookupDependencyDefinition(TypeDecl source, String id); - eq RagConnect.getDependencyDefinition().lookupDependencyDefinition(TypeDecl source, String id) { - for (DependencyDefinition def : getDependencyDefinitionList()) { + eq RagConnect.getConnectSpecificationFile().lookupDependencyDefinition(TypeDecl source, String id) { + for (DependencyDefinition def : allDependencyDefinitionList()) { if (def.getID().equals(id) && def.getSource().containingTypeDecl().equals(source)) { return def; } diff --git a/ragconnect.base/src/main/jastadd/Configuration.jadd b/ragconnect.base/src/main/jastadd/Configuration.jadd index 4116807c5b921b74bd645a992c849d841b43bcf2..e7e1268df443a278496a499c59e896d1ee27c80a 100644 --- a/ragconnect.base/src/main/jastadd/Configuration.jadd +++ b/ragconnect.base/src/main/jastadd/Configuration.jadd @@ -1,8 +1,10 @@ aspect Configuration { public static boolean ASTNode.loggingEnabledForReads = false; public static boolean ASTNode.loggingEnabledForWrites = false; + public static boolean ASTNode.loggingEnabledForIncremental = false; public static TypeDecl ASTNode.rootNode; public static boolean ASTNode.usesMqtt; public static boolean ASTNode.usesRest; public static boolean ASTNode.incrementalOptionActive; + public static boolean ASTNode.experimentalJastAdd329; } diff --git a/ragconnect.base/src/main/jastadd/NameResolution.jrag b/ragconnect.base/src/main/jastadd/NameResolution.jrag index 6b9171df4e85464b6711aa80e76b34f952d6864b..3b75bc0eb633830cb0e63c80d5d51e7d04e1b4f0 100644 --- a/ragconnect.base/src/main/jastadd/NameResolution.jrag +++ b/ragconnect.base/src/main/jastadd/NameResolution.jrag @@ -2,7 +2,7 @@ aspect NameResolution { refine RefResolverStubs eq EndpointDefinition.resolveMappingByToken(String id, int position) { // return a MappingDefinition - for (MappingDefinition mappingDefinition : ragconnect().getMappingDefinitionList()) { + for (MappingDefinition mappingDefinition : ragconnect().allMappingDefinitionList()) { if (mappingDefinition.getID().equals(id)) { return mappingDefinition; } diff --git a/ragconnect.base/src/main/jastadd/Navigation.jrag b/ragconnect.base/src/main/jastadd/Navigation.jrag index 5bddf79ea3c633d7fa5933dde4ab6b665000630d..d3890f7d22a195127e7688435f9168aa64a37eac 100644 --- a/ragconnect.base/src/main/jastadd/Navigation.jrag +++ b/ragconnect.base/src/main/jastadd/Navigation.jrag @@ -1,4 +1,7 @@ -aspect Navigation { +import java.util.List; +import java.util.ArrayList; + +aspect RagConnectNavigation { // --- program --- eq RagConnect.getChild().program() = getProgram(); @@ -9,15 +12,54 @@ aspect Navigation { eq RagConnect.getChild().ragconnect() = this; eq MRagConnect.getChild().ragconnect() = getRagConnect(); + // --- containedConnectSpecification --- + inh ConnectSpecification ASTNode.containedConnectSpecification(); + eq RagConnect.getChild().containedConnectSpecification() = null; + eq MRagConnect.getChild().containedConnectSpecification() = null; + eq Document.getChild().containedConnectSpecification() = null; + eq Program.getChild().containedConnectSpecification() = null; + eq ConnectSpecification.getChild().containedConnectSpecification() = this; + // --- containedFile - eq Grammar.getChild().containedFile() = null; eq RagConnect.getChild().containedFile() = null; eq MRagConnect.getChild().containedFile() = null; // --- containedFileName --- - eq Grammar.getChild().containedFileName() = null; // should be in PP - eq RagConnect.getChild().containedFileName() = getFileName(); - eq MRagConnect.getChild().containedFileName() = null; + eq ConnectSpecificationFile.containedFileName() = getFileName(); + refine Navigation eq ASTNode.containedFileName() { + if (containedFile() == null) { + return containedConnectSpecification().containedFileName(); + } + return refined(); +// return containedFile().getFileName(); + } + + //--- allEndpointDefinitionList --- + syn List<EndpointDefinition> RagConnect.allEndpointDefinitionList() { + List<EndpointDefinition> result = new ArrayList<>(); + for (var spec : getConnectSpecificationFileList()) { + spec.getEndpointDefinitionList().forEach(result::add); + } + return result; + } + + //--- allDependencyDefinitionList --- + syn List<DependencyDefinition> RagConnect.allDependencyDefinitionList() { + List<DependencyDefinition> result = new ArrayList<>(); + for (var spec : getConnectSpecificationFileList()) { + spec.getDependencyDefinitionList().forEach(result::add); + } + return result; + } + + //--- allMappingDefinitionList --- + syn List<MappingDefinition> RagConnect.allMappingDefinitionList() { + List<MappingDefinition> result = new ArrayList<>(); + for (var spec : getConnectSpecificationFileList()) { + spec.getMappingDefinitionList().forEach(result::add); + } + return result; + } // --- isTokenEndpointDefinition --- syn boolean EndpointDefinition.isTokenEndpointDefinition() = false; @@ -70,7 +112,7 @@ aspect Navigation { // --- 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()) { + for (EndpointDefinition endpointDefinition : ragconnect().allEndpointDefinitionList()) { if (endpointDefinition.isSendTokenEndpointDefinition() && endpointDefinition.asSendTokenEndpointDefinition().getToken().equals(this.getTarget())) { return endpointDefinition; @@ -96,4 +138,7 @@ aspect Navigation { // --- rootTypeComponents --- syn JastAddList<MTypeComponent> MHandler.rootTypeComponents() = mragconnect().getRootTypeComponents(); + + // --- isListComponent --- (defined in PP, but only on TypeComponent) + syn boolean Component.isListComponent() = false; } diff --git a/ragconnect.base/src/main/jastadd/RagConnect.relast b/ragconnect.base/src/main/jastadd/RagConnect.relast index 426b90ee22b0aeeb1a9d0cb7a5d77e52838bc0ff..309c4776d923a6afd7b98b7bec190d96db74f28e 100644 --- a/ragconnect.base/src/main/jastadd/RagConnect.relast +++ b/ragconnect.base/src/main/jastadd/RagConnect.relast @@ -1,4 +1,7 @@ -RagConnect ::= EndpointDefinition* DependencyDefinition* MappingDefinition* Program <FileName> ; +RagConnect ::= ConnectSpecificationFile* Program ; + +abstract ConnectSpecification ::= EndpointDefinition* DependencyDefinition* MappingDefinition* ; +ConnectSpecificationFile : ConnectSpecification ::= <FileName> ; abstract EndpointDefinition ::= <AlwaysApply:boolean> ; diff --git a/ragconnect.base/src/main/jastadd/intermediate/Generation.jadd b/ragconnect.base/src/main/jastadd/intermediate/Generation.jadd index 444f0214af4821f704a3307227c9f1b04b072e47..3b63bddfd2079518793308e0320fe2311724828e 100644 --- a/ragconnect.base/src/main/jastadd/intermediate/Generation.jadd +++ b/ragconnect.base/src/main/jastadd/intermediate/Generation.jadd @@ -62,12 +62,17 @@ aspect AttributesForMustache { syn String MEndpointDefinition.lastDefinitionToType() = lastDefinition().toType(); syn String MEndpointDefinition.lastResult() = lastDefinition().outputVarName(); syn String MEndpointDefinition.condition() { + // TODO probably, this has to be structured in a better way if (lastDefinition().mappingDef().getToType().isArray()) { return "java.util.Arrays.equals(" + preemptiveExpectedValue() + ", " + lastResult() + ")"; } if (endpointDef().isTokenEndpointDefinition() && token().isPrimitiveType() && lastDefinition().mappingDef().getToType().isPrimitiveType()) { return preemptiveExpectedValue() + " == " + lastResult(); } + if (endpointDef().isTypeEndpointDefinition() && type().isOptComponent()) { + // use "hasX()" instead of "getX() != null" for optionals + return "has" + typeName() + "()" + " && " + preemptiveExpectedValue() + ".equals(" + lastResult() + ")"; + } if (lastDefinition().mappingDef().getToType().isPrimitiveType() || lastDefinition().mappingDef().isDefaultMappingDefinition()) { return preemptiveExpectedValue() + " != null && " + preemptiveExpectedValue() + ".equals(" + lastResult() + ")"; } @@ -172,7 +177,7 @@ aspect AttributesForMustache { syn lazy MRagConnect RagConnect.toMustache() { MRagConnect result = new MRagConnect(); result.setRagConnect(this); - for (EndpointDefinition def : getEndpointDefinitionList()) { + for (EndpointDefinition def : allEndpointDefinitionList()) { if (def.isReceiveTokenEndpointDefinition()) { result.addTokenReceiveDefinition(def.asReceiveTokenEndpointDefinition().toMustache()); } else if (def.isSendTokenEndpointDefinition()) { @@ -188,7 +193,7 @@ aspect AttributesForMustache { for (MappingDefinition def : allMappingDefinitions()) { result.addMappingDefinition(def.toMustache()); } - for (DependencyDefinition def : getDependencyDefinitionList()) { + for (DependencyDefinition def : allDependencyDefinitionList()) { result.addDependencyDefinition(def.toMustache()); } for (TokenComponent token : getProgram().allTokenComponents()) { @@ -311,7 +316,7 @@ aspect AspectGeneration { aspect RelationGeneration { syn java.util.List<Relation> RagConnect.additionalRelations() { java.util.List<Relation> result = new java.util.ArrayList<>(); - for (DependencyDefinition dd : getDependencyDefinitionList()) { + for (DependencyDefinition dd : allDependencyDefinitionList()) { result.add(dd.getRelationToCreate()); } return result; diff --git a/ragconnect.base/src/main/jastadd/intermediate/Mappings.jrag b/ragconnect.base/src/main/jastadd/intermediate/Mappings.jrag index 93f74e51d8acbf140b56e99e279a337506c3a6c0..47379bd06921509023f686ab05621b63eb5729d9 100644 --- a/ragconnect.base/src/main/jastadd/intermediate/Mappings.jrag +++ b/ragconnect.base/src/main/jastadd/intermediate/Mappings.jrag @@ -298,7 +298,7 @@ aspect Mappings { syn java.util.List<MappingDefinition> RagConnect.allMappingDefinitions() { java.util.List<MappingDefinition> result = new java.util.ArrayList<>(); // user-defined mappings - getMappingDefinitionList().iterator().forEachRemaining(result::add); + allMappingDefinitionList().iterator().forEachRemaining(result::add); // byte[] <-> primitive conversion result.add(defaultBytesToBooleanMapping()); result.add(defaultBytesToIntMapping()); diff --git a/ragconnect.base/src/main/jastadd/intermediate2mustache/MustacheNodesToYAML.jrag b/ragconnect.base/src/main/jastadd/intermediate2mustache/MustacheNodesToYAML.jrag index 9de1c1e6ecf3e2f05580b3c324316708e353ad40..ef54a74e6fd57f11f17530e53524c63446277ca3 100644 --- a/ragconnect.base/src/main/jastadd/intermediate2mustache/MustacheNodesToYAML.jrag +++ b/ragconnect.base/src/main/jastadd/intermediate2mustache/MustacheNodesToYAML.jrag @@ -206,5 +206,5 @@ aspect Navigation { eq Document.getChild().program() = null; eq Document.getChild().ragconnect() = null; eq Document.getChild().containedFile() = null; - eq Document.getChild().containedFileName() = getFileName(); + eq Document.containedFileName() = getFileName(); } diff --git a/ragconnect.base/src/main/jastadd/mustache b/ragconnect.base/src/main/jastadd/mustache deleted file mode 160000 index c10bed0d03e3fa18b8133ce1de48de7646899615..0000000000000000000000000000000000000000 --- a/ragconnect.base/src/main/jastadd/mustache +++ /dev/null @@ -1 +0,0 @@ -Subproject commit c10bed0d03e3fa18b8133ce1de48de7646899615 diff --git a/ragconnect.base/src/main/jastadd/parser/Preamble.parser b/ragconnect.base/src/main/jastadd/parser/Preamble.parser index d701db19d6edb6d6c616bc79fc0145ea59d2713d..c157ae91f69b0e8d41c40a5bd7426bb2d7fae803 100644 --- a/ragconnect.base/src/main/jastadd/parser/Preamble.parser +++ b/ragconnect.base/src/main/jastadd/parser/Preamble.parser @@ -4,4 +4,4 @@ import org.jastadd.ragconnect.ast.*; :}; %goal goal; -%goal ragconnect; +%goal connect_specification_file; diff --git a/ragconnect.base/src/main/jastadd/parser/RagConnect.parser b/ragconnect.base/src/main/jastadd/parser/RagConnect.parser index a9d4809331c0ea20e11b0ec2a04dfd1f2c76e95b..eefb64e8ec713991b1c8d214025e71586ad4a645 100644 --- a/ragconnect.base/src/main/jastadd/parser/RagConnect.parser +++ b/ragconnect.base/src/main/jastadd/parser/RagConnect.parser @@ -1,9 +1,21 @@ -RagConnect ragconnect - = endpoint_definition.d ragconnect.r {: r.getEndpointDefinitionList().insertChild(d, 0); return r; :} - | dependency_definition.d ragconnect.r {: r.getDependencyDefinitionList().insertChild(d, 0); return r; :} - | mapping_definition.d ragconnect.r {: r.getMappingDefinitionList().insertChild(d, 0); return r; :} - | comment ragconnect.r {: return r; :} - | {: return new RagConnect(); :} +ConnectSpecificationFile connect_specification_file + = endpoint_definition.d connect_specification_file.r + {: + r.getEndpointDefinitionList().insertChild(d, 0); return r; + :} + | dependency_definition.d connect_specification_file.r + {: + r.getDependencyDefinitionList().insertChild(d, 0); return r; + :} + | mapping_definition.d connect_specification_file.r + {: + r.getMappingDefinitionList().insertChild(d, 0); return r; + :} + | comment connect_specification_file.r + {: + return r; + :} + | {: return new ConnectSpecificationFile(); :} ; %embed {: 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 88bfbdc1689fe0c8040efc952832c0bc9ac58b02..8035d76e424cd813e62c400ffd70f84a6167a98f 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 @@ -3,11 +3,11 @@ package org.jastadd.ragconnect.compiler; import beaver.Parser; import org.jastadd.option.BooleanOption; import org.jastadd.option.ValueOption; -import org.jastadd.relast.compiler.AbstractCompiler; -import org.jastadd.relast.compiler.CompilerException; import org.jastadd.ragconnect.ast.*; import org.jastadd.ragconnect.parser.RagConnectParser; import org.jastadd.ragconnect.scanner.RagConnectScanner; +import org.jastadd.relast.compiler.AbstractCompiler; +import org.jastadd.relast.compiler.CompilerException; import java.io.*; import java.nio.file.Files; @@ -15,6 +15,8 @@ import java.nio.file.Path; import java.nio.file.Paths; import java.nio.file.StandardCopyOption; import java.util.*; +import java.util.logging.Level; +import java.util.logging.Logger; public class Compiler extends AbstractCompiler { @@ -25,10 +27,14 @@ public class Compiler extends AbstractCompiler { private BooleanOption optionVerbose; private BooleanOption optionLogReads; private BooleanOption optionLogWrites; + private BooleanOption optionLogIncremental; + private BooleanOption optionExperimentalJastAdd329; private static final String OPTION_PROTOCOL_MQTT = "mqtt"; private static final String OPTION_PROTOCOL_REST = "rest"; + private final static Logger LOGGER = Logger.getLogger(Compiler.class.getName()); + public Compiler() { super("ragconnect", true); } @@ -43,8 +49,11 @@ public class Compiler extends AbstractCompiler { getConfiguration().printHelp(System.out); return 0; } + if (optionVerbose.value()) { + LOGGER.setLevel(Level.FINE); + } - printMessage("Running RagConnect " + readVersion()); + LOGGER.info(() -> "Running RagConnect " + readVersion()); if (!getConfiguration().outputDir().exists()) { try { @@ -61,10 +70,11 @@ public class Compiler extends AbstractCompiler { RagConnect ragConnect = parseProgram(getConfiguration().getFiles()); if (!ragConnect.errors().isEmpty()) { - System.err.println("Errors:"); + StringBuilder sb = new StringBuilder("Errors:\n"); for (ErrorMessage e : ragConnect.errors()) { - System.err.println(e); + sb.append(e).append("\n"); } + LOGGER.severe(sb::toString); System.exit(1); } @@ -76,7 +86,7 @@ public class Compiler extends AbstractCompiler { return 0; } - printMessage("Writing output files"); + LOGGER.fine("Writing output files"); final List<String> handlers = new ArrayList<>(); if (ASTNode.usesMqtt) { handlers.add("MqttHandler.jadd"); @@ -107,12 +117,11 @@ public class Compiler extends AbstractCompiler { } public static void main(String[] args) { - System.setProperty("java.util.logging.manager", "org.apache.logging.log4j.jul.LogManager"); System.setProperty("mustache.debug", "true"); try { new Compiler().run(args); } catch (CompilerException e) { - e.printStackTrace(); + LOGGER.log(Level.SEVERE, e.getMessage(), e); System.exit(1); } } @@ -137,12 +146,6 @@ public class Compiler extends AbstractCompiler { } } - private void printMessage(String message) { - if (optionVerbose.value()) { - System.out.println(message); - } - } - private void writeToFile(Path path, String str) throws CompilerException { try (BufferedWriter writer = Files.newBufferedWriter(path)) { writer.append(str); @@ -175,6 +178,12 @@ public class Compiler extends AbstractCompiler { optionLogWrites = addOption( new BooleanOption("logWrites", "Enable logging for every write.") .defaultValue(false)); + optionLogIncremental = addOption( + new BooleanOption("logIncremental", "Enable logging for observer in incremental dependency tracking.") + .defaultValue(false)); + optionExperimentalJastAdd329 = addOption( + new BooleanOption("experimental-jastadd-329", "Use trace events INC_FLUSH_START and INC_FLUSH_END (JastAdd issue #329).") + .defaultValue(false)); } private RagConnect parseProgram(Collection<String> files) throws CompilerException { @@ -195,14 +204,13 @@ public class Compiler extends AbstractCompiler { case "ast": case "relast": // processGrammar - parseGrammar(program, filename); + program.addGrammarFile(parseGrammar(filename)); atLeastOneGrammar = true; break; case "connect": case "ragconnect": // process ragConnect - RagConnect parsedRagConnect = parseRagConnect(program, filename); - mergeRagConnectDefinitions(ragConnect, parsedRagConnect); + ragConnect.addConnectSpecificationFile(parseConnectSpec(filename)); atLeastOneRagConnect = true; break; default: @@ -210,10 +218,10 @@ public class Compiler extends AbstractCompiler { } } if (!atLeastOneGrammar) { - System.err.println("No grammar file specified! (*.ast, *.relast)"); + LOGGER.severe(() -> "No grammar file specified! (*.ast, *.relast)"); } if (!atLeastOneRagConnect) { - System.err.println("No ragconnect file specified! (*.connect, *.ragconnect)"); + LOGGER.severe(() -> "No ragconnect file specified! (*.connect, *.ragconnect)"); } if (!atLeastOneGrammar && !atLeastOneRagConnect) { System.exit(1); @@ -226,39 +234,40 @@ public class Compiler extends AbstractCompiler { ragConnect.additionalRelations().forEach(ragConnectGrammarPart::addDeclaration); ASTNode.loggingEnabledForReads = optionLogReads.value(); ASTNode.loggingEnabledForWrites = optionLogWrites.value(); + ASTNode.loggingEnabledForIncremental = optionLogIncremental.value(); + ASTNode.experimentalJastAdd329 = optionExperimentalJastAdd329.value(); // reuse "--incremental" option of JastAdd ASTNode.incrementalOptionActive = getConfiguration().incremental() && getConfiguration().traceFlush(); - printMessage("ASTNode.incrementalOptionActive = " + ASTNode.incrementalOptionActive); + LOGGER.fine(() -> "ASTNode.incrementalOptionActive = " + ASTNode.incrementalOptionActive); ASTNode.usesMqtt = optionProtocols.hasValue(OPTION_PROTOCOL_MQTT); ASTNode.usesRest = optionProtocols.hasValue(OPTION_PROTOCOL_REST); return ragConnect; } - private void parseGrammar(Program program, String filename) throws CompilerException { + private GrammarFile parseGrammar(String filename) throws CompilerException { try (BufferedReader reader = Files.newBufferedReader(Paths.get(filename))) { RagConnectScanner scanner = new RagConnectScanner(reader); RagConnectParser parser = new RagConnectParser(); GrammarFile grammarFile = (GrammarFile) parser.parse(scanner); if (optionVerbose.value()) { - grammarFile.dumpTree(System.out); + LOGGER.fine(grammarFile::dumpTree); } - program.addGrammarFile(grammarFile); grammarFile.setFileName(toBaseName(filename)); + return grammarFile; } catch (IOException | Parser.Exception e) { throw new CompilerException("Could not parse grammar file " + filename, e); } } - private RagConnect parseRagConnect(Program program, String filename) throws CompilerException { + private ConnectSpecificationFile parseConnectSpec(String filename) throws CompilerException { try (BufferedReader reader = Files.newBufferedReader(Paths.get(filename))) { RagConnectScanner scanner = new RagConnectScanner(reader); RagConnectParser parser = new RagConnectParser(); - RagConnect ragConnect = (RagConnect) parser.parse(scanner, RagConnectParser.AltGoals.ragconnect); - ragConnect.setProgram(program); - ragConnect.setFileName(toBaseName(filename)); - return ragConnect; + ConnectSpecificationFile specificationFile = (ConnectSpecificationFile) parser.parse(scanner, RagConnectParser.AltGoals.connect_specification_file); + specificationFile.setFileName(toBaseName(filename)); + return specificationFile; } catch (IOException | Parser.Exception e) { throw new CompilerException("Could not parse connect file " + filename, e); } @@ -273,13 +282,6 @@ public class Compiler extends AbstractCompiler { return new File(filename).getName(); } - private void mergeRagConnectDefinitions(RagConnect ragConnect, RagConnect ragConnectToIntegrate) { - 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() { // System.out.println("Usage: java -jar ragconnect.jar [--option1] [--option2=value] ... <filename1> <filename2> ... "); // System.out.println("Options:"); diff --git a/ragconnect.base/src/main/java/org/jastadd/ragconnect/compiler/SimpleMain.java b/ragconnect.base/src/main/java/org/jastadd/ragconnect/compiler/SimpleMain.java deleted file mode 100644 index 83c282f205af2ff337c3eea7d2b1b7fda8e3cc47..0000000000000000000000000000000000000000 --- a/ragconnect.base/src/main/java/org/jastadd/ragconnect/compiler/SimpleMain.java +++ /dev/null @@ -1,81 +0,0 @@ -package org.jastadd.ragconnect.compiler; - -import org.jastadd.ragconnect.ast.Document; -import org.jastadd.ragconnect.ast.ListElement; -import org.jastadd.ragconnect.ast.MappingElement; - -/** - * Testing Ros2Rag without parser. - * - * @author rschoene - Initial contribution - */ -public class SimpleMain { - - private static void printManualYAML() { - Document doc = new Document(); - MappingElement root = new MappingElement(); - MappingElement firstLevel = new MappingElement(); - firstLevel.put("server", "tcp://localhost:1883"); - firstLevel.put("robot_speed_factor", ".7"); - - MappingElement theTopics = new MappingElement(); - theTopics.put("robotConfig", "robotconfig"); - theTopics.put("trajectory", "trajectory"); - theTopics.put("nextStep", "ros2rag/nextStep"); - firstLevel.put("topics", theTopics); - - firstLevel.put("zone_size", "0.5"); - - ListElement theZones = new ListElement(); - theZones.add("1 1"); - theZones.add("0 1"); - theZones.add("-1 1"); - firstLevel.put("zones", theZones); - - MappingElement pandaParts = new MappingElement(); - MappingElement thePanda = new MappingElement(); - thePanda.put("Link0", "panda_link0"); - thePanda.put("Link1", "panda_link1"); - thePanda.put("Link2", "panda_link2"); - thePanda.put("Link3", "panda_link3"); - thePanda.put("Link4", "panda_link4"); - thePanda.put("Link5", "panda_link5"); - thePanda.put("Link6", "panda_link6"); - thePanda.put("RightFinger", "panda_rightfinger"); - thePanda.put("LeftFinger", "panda_leftfinger"); - pandaParts.put("panda", thePanda); - firstLevel.put("parts", pandaParts); - - MappingElement endEffectorParts = new MappingElement(); - MappingElement endEffector = new MappingElement(); - endEffector.put("EndEffector", "panda_hand"); - endEffectorParts.put("panda", endEffector); - firstLevel.put("end_effectors", endEffectorParts); - - ListElement theGoalPoses = new ListElement(); - theGoalPoses.add(makePose("0.4 0.4 0.3")); - theGoalPoses.add(makePose("-0.4 0.4 0.3")); - theGoalPoses.add(makePose("-0.4 -0.4 0.3")); - theGoalPoses.add(makePose("0.4 0.4 0.3")); - theGoalPoses.add(makePose("-0.4 0.4 0.3")); - theGoalPoses.add(makePose("0.4 0.4 0.3")); - firstLevel.put("goal_poses", theGoalPoses); - - root.put("panda_mqtt_connector", firstLevel); - doc.setRootElement(root); - - System.out.println(doc.prettyPrint()); - } - - private static MappingElement makePose(String position) { - MappingElement goalPose = new MappingElement(); - goalPose.put("position", position); - goalPose.put("orientation", "1 1 0 0"); - goalPose.put("work", "20000"); - return goalPose; - } - - public static void main(String[] args) { - printManualYAML(); - } -} diff --git a/ragconnect.base/src/main/resources/MqttHandler.jadd b/ragconnect.base/src/main/resources/MqttHandler.jadd index ab56c0405dd518204378d840d85954e0e27b784f..f84d8657ca7db7be868205b11cd939f27c08965d 100644 --- a/ragconnect.base/src/main/resources/MqttHandler.jadd +++ b/ragconnect.base/src/main/resources/MqttHandler.jadd @@ -120,11 +120,17 @@ public class MqttHandler { } /** - * Sets the host (with default port) to receive messages from, and connects to it. + * Sets the host to receive messages from, and connects to it. + * @param host name of the host to connect to, format is either <code>"$name"</code> or <code>"$name:$port"</code> * @throws IOException if could not connect, or could not subscribe to a topic * @return self */ public MqttHandler setHost(String host) throws java.io.IOException { + if (host.contains(":")) { + int colon_index = host.indexOf(":"); + return setHost(host.substring(0, colon_index), + Integer.parseInt(host.substring(colon_index + 1))); + } return setHost(host, DEFAULT_PORT); } @@ -167,7 +173,11 @@ public class MqttHandler { } else { byte[] message = body.toByteArray(); for (java.util.function.Consumer<byte[]> callback : callbackList) { - callback.accept(message); + try { + callback.accept(message); + } catch (Exception e) { + logger.catching(e); + } } } ack.onSuccess(null); // always acknowledge message diff --git a/ragconnect.base/src/main/resources/handleUri.mustache b/ragconnect.base/src/main/resources/handleUri.mustache index 1a20e7c4df2a4c54ccba4c825fff55ca89a51dec..aa4176ef0b067bca3c54ca754096f633cadcfa71 100644 --- a/ragconnect.base/src/main/resources/handleUri.mustache +++ b/ragconnect.base/src/main/resources/handleUri.mustache @@ -1,4 +1,4 @@ -String scheme,host, path; +String scheme, host, path; java.net.URI uri; try { uri = new java.net.URI({{connectParameterName}}); @@ -9,3 +9,15 @@ try { System.err.println(e.getMessage()); // Maybe re-throw error? return false; } +if (scheme == null || scheme.isBlank()) { + System.err.println("Missing or empty scheme in " + uri); + return false; +} +if (host == null || host.isBlank()) { + System.err.println("Missing or empty host in " + uri); + return false; +} +if (path == null || path.isBlank()) { + System.err.println("Missing or empty path in " + uri); + return false; +} diff --git a/ragconnect.base/src/main/resources/log4j2.xml b/ragconnect.base/src/main/resources/log4j2.xml deleted file mode 100644 index 98cfd73c75df58d8598521bc10b043e214ec4ad8..0000000000000000000000000000000000000000 --- a/ragconnect.base/src/main/resources/log4j2.xml +++ /dev/null @@ -1,13 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<Configuration status="INFO"> - <Appenders> - <Console name="Console" target="SYSTEM_OUT"> - <PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/> - </Console> - </Appenders> - <Loggers> - <Root level="info"> - <AppenderRef ref="Console"/> - </Root> - </Loggers> -</Configuration> \ No newline at end of file diff --git a/ragconnect.base/src/main/resources/mappingApplication.mustache b/ragconnect.base/src/main/resources/mappingApplication.mustache index 064004b94886c155be883e7b186557c6fa87d38c..47ec31ee58b27485a51e2b7e3a7de196cbe130f3 100644 --- a/ragconnect.base/src/main/resources/mappingApplication.mustache +++ b/ragconnect.base/src/main/resources/mappingApplication.mustache @@ -3,6 +3,9 @@ try { {{#InnerMappingDefinitions}} {{^last}}{{toType}} {{/last}}{{outputVarName}} = {{methodName}}({{inputVarName}}); {{/InnerMappingDefinitions}} +} catch (RagConnectRejectMappingException e) { + // do not print message in case of rejection + {{preemptiveReturn}} } catch (Exception e) { e.printStackTrace(); {{preemptiveReturn}} diff --git a/ragconnect.base/src/main/resources/ragConnectVersion.properties b/ragconnect.base/src/main/resources/ragConnectVersion.properties index f1b4c621c5fc52474900a7a204a52a82baa0c87f..cc1f011163b2d40f2569f47f8c4151154d2fab63 100644 --- a/ragconnect.base/src/main/resources/ragConnectVersion.properties +++ b/ragconnect.base/src/main/resources/ragConnectVersion.properties @@ -1,2 +1,2 @@ -#Wed Apr 14 09:40:24 CEST 2021 -version=0.3.0 +#Thu Jun 03 11:17:05 CEST 2021 +version=0.3.1 diff --git a/ragconnect.base/src/main/resources/ragconnect.mustache b/ragconnect.base/src/main/resources/ragconnect.mustache index 2cc2423cc2008ea80f6e614cd0eabea471692cbe..50cd5cece4429e3529c64f5896548e50bbe564b0 100644 --- a/ragconnect.base/src/main/resources/ragconnect.mustache +++ b/ragconnect.base/src/main/resources/ragconnect.mustache @@ -17,6 +17,11 @@ aspect RagConnect { {{> sendDefinition}} {{/TypeSendDefinitions}} + class RagConnectRejectMappingException extends RuntimeException {} + private static void ASTNode.reject() { + throw new RagConnectRejectMappingException(); + } + {{#MappingDefinitions}} {{#isUsed}} {{> mappingDefinition}} @@ -46,13 +51,15 @@ aspect RagConnect { {{#incrementalOptionActive}} aspect RagConnectObserver { + class RagConnectObserver implements ASTState.Trace.Receiver { - ASTState.Trace.Receiver oldReceiver; + class RagConnectObserverEntry { final ConnectToken connectToken; final ASTNode node; final String attributeString; final Runnable attributeCall; + RagConnectObserverEntry(ConnectToken connectToken, ASTNode node, String attributeString, Runnable attributeCall) { this.connectToken = connectToken; this.node = node; @@ -60,16 +67,39 @@ aspect RagConnectObserver { this.attributeCall = attributeCall; } } + +{{#experimentalJastAdd329}} + class RagConnectObserverStartEntry { + final ASTNode node; + final String attributeString; + final Object flushIncToken; + RagConnectObserverStartEntry(ASTNode node, String attributeString, Object flushIncToken) { + this.node = node; + this.attributeString = attributeString; + this.flushIncToken = flushIncToken; + } + } +{{/experimentalJastAdd329}} + + ASTState.Trace.Receiver oldReceiver; + java.util.List<RagConnectObserverEntry> observedNodes = new java.util.ArrayList<>(); + +{{#experimentalJastAdd329}} + java.util.Set<RagConnectObserverEntry> entryQueue = new java.util.HashSet<>(); + RagConnectObserverStartEntry startEntry = null; +{{/experimentalJastAdd329}} + RagConnectObserver(ASTNode node) { // set the receiver. potentially dangerous because overriding existing receiver! oldReceiver = node.trace().getReceiver(); node.trace().setReceiver(this); } + void add(ConnectToken connectToken, ASTNode node, String attributeString, Runnable attributeCall) { - {{#loggingEnabledForWrites}} + {{#loggingEnabledForIncremental}} System.out.println("** observer add: " + node + " on " + attributeString); - {{/loggingEnabledForWrites}} + {{/loggingEnabledForIncremental}} observedNodes.add(new RagConnectObserverEntry(connectToken, node, attributeString, attributeCall)); } void remove(ConnectToken connectToken) { @@ -78,21 +108,56 @@ aspect RagConnectObserver { @Override public void accept(ASTState.Trace.Event event, ASTNode node, String attribute, Object params, Object value) { oldReceiver.accept(event, node, attribute, params, value); - // ignore all events but INC_FLUSH_ATTR +{{#experimentalJastAdd329}} + // react to INC_FLUSH_START and remember entry + if (event == ASTState.Trace.Event.INC_FLUSH_START && startEntry == null) { + {{#loggingEnabledForIncremental}} + System.out.println("** observer start: " + node + " on " + attribute); + {{/loggingEnabledForIncremental}} + startEntry = new RagConnectObserverStartEntry(node, attribute, value); + return; + } + + // react to INC_FLUSH_END and process queued entries, if it matches start entry + if (event == ASTState.Trace.Event.INC_FLUSH_END && + node == startEntry.node && + attribute == startEntry.attributeString && + value == startEntry.flushIncToken) { + // create a copy of the queue to avoid entering this again causing an endless recursion + RagConnectObserverEntry[] entriesToProcess = entryQueue.toArray(new RagConnectObserverEntry[entryQueue.size()]); + entryQueue.clear(); + startEntry = null; + {{#loggingEnabledForIncremental}} + System.out.println("** observer process (" + entriesToProcess.length + "): " + node + " on " + attribute); + {{/loggingEnabledForIncremental}} + for (RagConnectObserverEntry entry : entriesToProcess) { + entry.attributeCall.run(); + } + return; + } + +{{/experimentalJastAdd329}} + // ignore all other events but INC_FLUSH_ATTR if (event != ASTState.Trace.Event.INC_FLUSH_ATTR) { return; } - {{#loggingEnabledForWrites}} + + {{#loggingEnabledForIncremental}} System.out.println("** observer check INC_FLUSH_ATTR event: " + node + " on " + attribute); - {{/loggingEnabledForWrites}} + {{/loggingEnabledForIncremental}} // 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 - {{#loggingEnabledForWrites}} + {{#loggingEnabledForIncremental}} System.out.println("** observer hit: " + entry.node + " on " + entry.attributeString); - {{/loggingEnabledForWrites}} + {{/loggingEnabledForIncremental}} +{{#experimentalJastAdd329}} + entryQueue.add(entry); +{{/experimentalJastAdd329}} +{{^experimentalJastAdd329}} entry.attributeCall.run(); +{{/experimentalJastAdd329}} } } } diff --git a/ragconnect.tests/build.gradle b/ragconnect.tests/build.gradle index 30fb2237ee167f74879bbb8903553d4eaaf1ceb1..485a59d61efefe9f77592c1f62ca485db087da98 100644 --- a/ragconnect.tests/build.gradle +++ b/ragconnect.tests/build.gradle @@ -36,7 +36,8 @@ repositories { dependencies { implementation project(':ragconnect.base') - runtime group: 'org.jastadd', name: 'jastadd', version: '2.3.5' + runtimeOnly group: 'org.jastadd', name: 'jastadd', version: '2.3.5' +// runtimeOnly fileTree(include: ['jastadd2.jar'], dir: '../libs') 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' @@ -92,11 +93,13 @@ task allTests(type: Test, dependsOn: testClasses) { } task specificTest(type: Test, dependsOn: testClasses) { - description = 'Run test tagged with "NewTest"' + description = 'Run test tagged with tag given by "-PincludeTags="' group = 'verification' + String tags = project.hasProperty("includeTags") ? + project.property("includeTags") : '' useJUnitPlatform { - includeTags 'SpecificTest' + includeTags tags } } @@ -275,6 +278,7 @@ task compileIncremental(type: RagConnectTest) { inputFiles = [file('src/test/01-input/incremental/Test.relast'), file('src/test/01-input/incremental/Test.connect')] rootNode = 'A' + logWrites = true } relast { useJastAddNames = true @@ -342,6 +346,7 @@ task compileTreeIncremental(type: RagConnectTest) { inputFiles = [file('src/test/01-input/tree/Test.relast'), file('src/test/01-input/tree/Test.connect')] rootNode = 'Root' + logWrites = true } relast { useJastAddNames = true @@ -388,6 +393,7 @@ task compileTreeAllowedTokensIncremental(type: RagConnectTest) { inputFiles = [file('src/test/01-input/treeAllowedTokens/Test.relast'), file('src/test/01-input/treeAllowedTokens/Test.connect')] rootNode = 'Root' + logWrites = true } relast { useJastAddNames = true diff --git a/ragconnect.tests/src/test/01-input/errors/Errors.expected b/ragconnect.tests/src/test/01-input/errors/Errors.expected deleted file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000 diff --git a/ragconnect.tests/src/test/01-input/errors/Part.expected b/ragconnect.tests/src/test/01-input/errors/Part.expected new file mode 100644 index 0000000000000000000000000000000000000000..70ea4a4baeaffb5b35df672c03e90821eb3cec82 --- /dev/null +++ b/ragconnect.tests/src/test/01-input/errors/Part.expected @@ -0,0 +1,11 @@ +Part1.connect Line 3, column 1: Receive definition already defined for DoubledValue +Part1.connect Line 4, column 1: Receive definition already defined for DoubledValue +Part1.connect Line 10, column 1: Receiving target token must not be an NTA token! +Part1.connect Line 13, column 1: No suitable default mapping found for type java.util.List +Part1.connect Line 13, column 1: to-type of last mapping (java.util.List) not assignable to type of the Token (String)! +Part1.connect Line 16, column 1: to-type of last mapping (List) not assignable to type of the Token (String)! +Part1.connect Line 19, column 1: to-type of last mapping (int) not assignable to type of the Token (String)! +Part2.connect Line 5, column 1: Send definition already defined for DoubledValue +Part2.connect Line 6, column 1: Send definition already defined for DoubledValue +Part2.connect Line 17, column 1: The name of a dependency definition must not be equal to a list-node on the source +Part2.connect Line 22, column 1: Dependency definition already defined for D with name DoubledValue diff --git a/ragconnect.tests/src/test/01-input/errors/Part1.connect b/ragconnect.tests/src/test/01-input/errors/Part1.connect new file mode 100644 index 0000000000000000000000000000000000000000..a1be3918b36ee19561a278639555db14efb8da06 --- /dev/null +++ b/ragconnect.tests/src/test/01-input/errors/Part1.connect @@ -0,0 +1,33 @@ +// --- update receive definitions --- +// Error: there must not be two receive definitions for the same token +receive B.DoubledValue ; +receive B.DoubledValue using IntToInt ; + +// NOT HANDLED \\ Error: the token must be resolvable within the parent type +// NOT HANDLED \\ receive B.NonExisting ; + +// Error: the Token must not be a TokenNTA (i.e., check for !Token.getNTA()) +receive B.ErrorNTA ; + +// Error: from-type of first mapping must be byte[] or a supported primitive type +receive B.ErrorTypeOfFirstMapping using ListToList ; + +// Error: to-type of last mapping must be type of the Token +receive B.ErrorTypeOfLastMapping using StringToList ; + +// Error: types of mappings must match (modulo inheritance) +receive B.ErrorTypeMismatch using StringToList, IntToInt ; + +// --- update send definitions --- +// NOT HANDLED \\ Error: the token must be resolvable within the parent type +// NOT HANDLED \\ receive C.NonExisting ; + +// Error: Token must be a TokenNTA (i.e., check for Token.getNTA()) +send C.ErrorNotNTA ; + +// Error: from-type of first mapping must be type of Token +send C.ErrorTypeOfFirstMapping using IntToInt ; + +// Error: to-type of last mapping must be byte[] or a supported primitive type +send C.ErrorTypeOfLastMapping1 using StringToList ; +send C.ErrorTypeOfLastMapping2 ; diff --git a/ragconnect.tests/src/test/01-input/errors/Part2.connect b/ragconnect.tests/src/test/01-input/errors/Part2.connect new file mode 100644 index 0000000000000000000000000000000000000000..4d1148260a36855528b37f8b45020e076ff9ff1e --- /dev/null +++ b/ragconnect.tests/src/test/01-input/errors/Part2.connect @@ -0,0 +1,38 @@ +// Error: types of mappings must match (modulo inheritance) +send C.ErrorTypeMismatch using StringToList, IntToInt ; + +// Error: no more than one send mapping for each TokenComponent +send C.DoubledValue ; +send C.DoubledValue using IntToInt ; + +// --- dependency definitions --- +// NOT HANDLED \\ Error: Both, source and target must be resolvable within the parent type +// NOT HANDLED \\ D.SourceNonExistingTarget canDependOn D.NonExisting as NonExistingTarget ; +// NOT HANDLED \\ D.NonExisting canDependOn D.TargetNonExistingSource as NonExistingSource ; + +// Error: There must be a send update definition for the target token +D.SourceNoWriteDef canDependOn D.TargetNoWriteDef as NoWriteDef ; + +// Error: The name of a dependency definition must not be equal to a list-node on the source +D.SourceSameAsListNode canDependOn D.TargetSameAsListNode as MyList ; +send D.TargetSameAsListNode; + +// Error: There must not be two dependency definitions with the same name +D.SourceDoubledValue canDependOn D.TargetDoubledValue as DoubledValue ; +D.SourceDoubledValue canDependOn D.TargetDoubledValue as DoubledValue ; +send D.TargetDoubledValue; + +// --- mapping definitions --- +ListToList maps java.util.List<String> list to java.util.List<String> {: + return list; +:} + +StringToList maps String s to List<String> {: + java.util.List<String> result = new java.util.ArrayList<>(); + result.add(s); + return result; +:} + +IntToInt maps int number to int {: + return number + 1; +:} diff --git a/ragconnect.tests/src/test/01-input/errors/Errors.connect b/ragconnect.tests/src/test/01-input/errors/Standard.connect similarity index 100% rename from ragconnect.tests/src/test/01-input/errors/Errors.connect rename to ragconnect.tests/src/test/01-input/errors/Standard.connect diff --git a/ragconnect.tests/src/test/01-input/errors/Standard.expected b/ragconnect.tests/src/test/01-input/errors/Standard.expected new file mode 100644 index 0000000000000000000000000000000000000000..3ee660570525834a63c41f26820966a7504f7789 --- /dev/null +++ b/ragconnect.tests/src/test/01-input/errors/Standard.expected @@ -0,0 +1,11 @@ +Standard.connect Line 3, column 1: Receive definition already defined for DoubledValue +Standard.connect Line 4, column 1: Receive definition already defined for DoubledValue +Standard.connect Line 10, column 1: Receiving target token must not be an NTA token! +Standard.connect Line 13, column 1: No suitable default mapping found for type java.util.List +Standard.connect Line 13, column 1: to-type of last mapping (java.util.List) not assignable to type of the Token (String)! +Standard.connect Line 16, column 1: to-type of last mapping (List) not assignable to type of the Token (String)! +Standard.connect Line 19, column 1: to-type of last mapping (int) not assignable to type of the Token (String)! +Standard.connect Line 39, column 1: Send definition already defined for DoubledValue +Standard.connect Line 40, column 1: Send definition already defined for DoubledValue +Standard.connect Line 51, column 1: The name of a dependency definition must not be equal to a list-node on the source +Standard.connect Line 56, column 1: Dependency definition already defined for D with name DoubledValue diff --git a/ragconnect.tests/src/test/01-input/regression-tests/issue27/.gitignore b/ragconnect.tests/src/test/01-input/regression-tests/issue27/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..607b7610731b1ddf9dc05e605bd374a4b59ea360 --- /dev/null +++ b/ragconnect.tests/src/test/01-input/regression-tests/issue27/.gitignore @@ -0,0 +1 @@ +/*.noNewLine.* diff --git a/ragconnect.tests/src/test/01-input/regression-tests/issue27/README.md b/ragconnect.tests/src/test/01-input/regression-tests/issue27/README.md new file mode 100644 index 0000000000000000000000000000000000000000..96595af1b32ba8487f2e8e663a944b0be52dff28 --- /dev/null +++ b/ragconnect.tests/src/test/01-input/regression-tests/issue27/README.md @@ -0,0 +1,3 @@ +# Issue27 + +Regression test for failing parser when missing newline at end of specification. diff --git a/ragconnect.tests/src/test/01-input/regression-tests/issue27/Test.connect b/ragconnect.tests/src/test/01-input/regression-tests/issue27/Test.connect new file mode 100644 index 0000000000000000000000000000000000000000..28827bb62d7b801cf2f8bc605afc90c122f0cb6a --- /dev/null +++ b/ragconnect.tests/src/test/01-input/regression-tests/issue27/Test.connect @@ -0,0 +1 @@ +receive A.Name ; diff --git a/ragconnect.tests/src/test/01-input/regression-tests/issue27/Test.relast b/ragconnect.tests/src/test/01-input/regression-tests/issue27/Test.relast new file mode 100644 index 0000000000000000000000000000000000000000..4c479a5756a37e42c74459c22006912445baa9b3 --- /dev/null +++ b/ragconnect.tests/src/test/01-input/regression-tests/issue27/Test.relast @@ -0,0 +1 @@ +A ::= <Name:String> ; 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 cf5e02f956ae55258f08458bcb88130e1afca4b0..d9cf9d92a456a02cd2acba9e5f8990527d5842e9 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 @@ -2,7 +2,6 @@ package org.jastadd.ragconnect.tests; import defaultOnlyRead.ast.A; import defaultOnlyRead.ast.BoxedTypes; -import defaultOnlyRead.ast.MqttHandler; import defaultOnlyRead.ast.NativeTypes; import org.junit.jupiter.api.Test; @@ -10,7 +9,8 @@ import java.io.IOException; import java.nio.file.Paths; import java.util.concurrent.TimeUnit; -import static org.jastadd.ragconnect.tests.TestUtils.*; +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; @@ -68,39 +68,39 @@ public class DefaultOnlyReadTest extends AbstractMqttTest { protected void setupReceiverAndConnect(boolean writeCurrentValue) throws IOException { model.ragconnectSetupMqttWaitUntilReady(2, TimeUnit.SECONDS); - integers.connectBooleanValue(mqttUri(TOPIC_NATIVE_BOOLEAN)); - integers.connectIntValue(mqttUri(TOPIC_NATIVE_INT)); - integers.connectShortValue(mqttUri(TOPIC_NATIVE_SHORT)); - integers.connectLongValue(mqttUri(TOPIC_NATIVE_LONG)); - floats.connectFloatValue(mqttUri(TOPIC_NATIVE_FLOAT)); - floats.connectDoubleValue(mqttUri(TOPIC_NATIVE_DOUBLE)); - chars.connectCharValue(mqttUri(TOPIC_NATIVE_CHAR)); - chars.connectStringValue(mqttUri(TOPIC_NATIVE_STRING)); - - integers.connectBooleanValueTransformed(mqttUri(TOPIC_NATIVE_BOOLEAN)); - integers.connectIntValueTransformed(mqttUri(TOPIC_NATIVE_INT)); - integers.connectShortValueTransformed(mqttUri(TOPIC_NATIVE_SHORT)); - integers.connectLongValueTransformed(mqttUri(TOPIC_NATIVE_LONG)); - floats.connectFloatValueTransformed(mqttUri(TOPIC_NATIVE_FLOAT)); - floats.connectDoubleValueTransformed(mqttUri(TOPIC_NATIVE_DOUBLE)); - chars.connectCharValueTransformed(mqttUri(TOPIC_NATIVE_CHAR)); - chars.connectStringValueTransformed(mqttUri(TOPIC_NATIVE_STRING)); - - allBoxed.connectBooleanValue(mqttUri(TOPIC_BOXED_BOOLEAN)); - allBoxed.connectIntValue(mqttUri(TOPIC_BOXED_INTEGER)); - allBoxed.connectShortValue(mqttUri(TOPIC_BOXED_SHORT)); - allBoxed.connectLongValue(mqttUri(TOPIC_BOXED_LONG)); - allBoxed.connectFloatValue(mqttUri(TOPIC_BOXED_FLOAT)); - allBoxed.connectDoubleValue(mqttUri(TOPIC_BOXED_DOUBLE)); - allBoxed.connectCharValue(mqttUri(TOPIC_BOXED_CHARACTER)); - - allBoxed.connectBooleanValueTransformed(mqttUri(TOPIC_BOXED_BOOLEAN)); - allBoxed.connectIntValueTransformed(mqttUri(TOPIC_BOXED_INTEGER)); - allBoxed.connectShortValueTransformed(mqttUri(TOPIC_BOXED_SHORT)); - allBoxed.connectLongValueTransformed(mqttUri(TOPIC_BOXED_LONG)); - allBoxed.connectFloatValueTransformed(mqttUri(TOPIC_BOXED_FLOAT)); - allBoxed.connectDoubleValueTransformed(mqttUri(TOPIC_BOXED_DOUBLE)); - allBoxed.connectCharValueTransformed(mqttUri(TOPIC_BOXED_CHARACTER)); + assertTrue(integers.connectBooleanValue(mqttUri(TOPIC_NATIVE_BOOLEAN))); + assertTrue(integers.connectIntValue(mqttUri(TOPIC_NATIVE_INT))); + assertTrue(integers.connectShortValue(mqttUri(TOPIC_NATIVE_SHORT))); + assertTrue(integers.connectLongValue(mqttUri(TOPIC_NATIVE_LONG))); + assertTrue(floats.connectFloatValue(mqttUri(TOPIC_NATIVE_FLOAT))); + assertTrue(floats.connectDoubleValue(mqttUri(TOPIC_NATIVE_DOUBLE))); + assertTrue(chars.connectCharValue(mqttUri(TOPIC_NATIVE_CHAR))); + assertTrue(chars.connectStringValue(mqttUri(TOPIC_NATIVE_STRING))); + + assertTrue(integers.connectBooleanValueTransformed(mqttUri(TOPIC_NATIVE_BOOLEAN))); + assertTrue(integers.connectIntValueTransformed(mqttUri(TOPIC_NATIVE_INT))); + assertTrue(integers.connectShortValueTransformed(mqttUri(TOPIC_NATIVE_SHORT))); + assertTrue(integers.connectLongValueTransformed(mqttUri(TOPIC_NATIVE_LONG))); + assertTrue(floats.connectFloatValueTransformed(mqttUri(TOPIC_NATIVE_FLOAT))); + assertTrue(floats.connectDoubleValueTransformed(mqttUri(TOPIC_NATIVE_DOUBLE))); + assertTrue(chars.connectCharValueTransformed(mqttUri(TOPIC_NATIVE_CHAR))); + assertTrue(chars.connectStringValueTransformed(mqttUri(TOPIC_NATIVE_STRING))); + + assertTrue(allBoxed.connectBooleanValue(mqttUri(TOPIC_BOXED_BOOLEAN))); + assertTrue(allBoxed.connectIntValue(mqttUri(TOPIC_BOXED_INTEGER))); + assertTrue(allBoxed.connectShortValue(mqttUri(TOPIC_BOXED_SHORT))); + assertTrue(allBoxed.connectLongValue(mqttUri(TOPIC_BOXED_LONG))); + assertTrue(allBoxed.connectFloatValue(mqttUri(TOPIC_BOXED_FLOAT))); + assertTrue(allBoxed.connectDoubleValue(mqttUri(TOPIC_BOXED_DOUBLE))); + assertTrue(allBoxed.connectCharValue(mqttUri(TOPIC_BOXED_CHARACTER))); + + assertTrue(allBoxed.connectBooleanValueTransformed(mqttUri(TOPIC_BOXED_BOOLEAN))); + assertTrue(allBoxed.connectIntValueTransformed(mqttUri(TOPIC_BOXED_INTEGER))); + assertTrue(allBoxed.connectShortValueTransformed(mqttUri(TOPIC_BOXED_SHORT))); + assertTrue(allBoxed.connectLongValueTransformed(mqttUri(TOPIC_BOXED_LONG))); + assertTrue(allBoxed.connectFloatValueTransformed(mqttUri(TOPIC_BOXED_FLOAT))); + assertTrue(allBoxed.connectDoubleValueTransformed(mqttUri(TOPIC_BOXED_DOUBLE))); + assertTrue(allBoxed.connectCharValueTransformed(mqttUri(TOPIC_BOXED_CHARACTER))); } @Override 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 c18b185503053ec03428f620ea1aaa5df2505354..d8ce0c083148b671590c6129d16f8d3ed071e313 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 @@ -137,39 +137,39 @@ public class DefaultOnlyWriteTest extends AbstractMqttTest { dataNormal = createReceiver(false); dataTransformed = createReceiver(true); - nativeIntegers.connectBooleanValue(mqttUri(TOPIC_NATIVE_BOOLEAN), writeCurrentValue); - nativeIntegers.connectIntValue(mqttUri(TOPIC_NATIVE_INT), writeCurrentValue); - nativeIntegers.connectShortValue(mqttUri(TOPIC_NATIVE_SHORT), writeCurrentValue); - nativeIntegers.connectLongValue(mqttUri(TOPIC_NATIVE_LONG), writeCurrentValue); - nativeFloats.connectFloatValue(mqttUri(TOPIC_NATIVE_FLOAT), writeCurrentValue); - nativeFloats.connectDoubleValue(mqttUri(TOPIC_NATIVE_DOUBLE), writeCurrentValue); - nativeChars.connectCharValue(mqttUri(TOPIC_NATIVE_CHAR), writeCurrentValue); - nativeChars.connectStringValue(mqttUri(TOPIC_NATIVE_STRING), writeCurrentValue); - - nativeIntegers.connectBooleanValueTransformed(mqttUri(TOPIC_NATIVE_BOOLEAN_TRANSFORMED), writeCurrentValue); - nativeIntegers.connectIntValueTransformed(mqttUri(TOPIC_NATIVE_INT_TRANSFORMED), writeCurrentValue); - nativeIntegers.connectShortValueTransformed(mqttUri(TOPIC_NATIVE_SHORT_TRANSFORMED), writeCurrentValue); - nativeIntegers.connectLongValueTransformed(mqttUri(TOPIC_NATIVE_LONG_TRANSFORMED), writeCurrentValue); - nativeFloats.connectFloatValueTransformed(mqttUri(TOPIC_NATIVE_FLOAT_TRANSFORMED), writeCurrentValue); - nativeFloats.connectDoubleValueTransformed(mqttUri(TOPIC_NATIVE_DOUBLE_TRANSFORMED), writeCurrentValue); - nativeChars.connectCharValueTransformed(mqttUri(TOPIC_NATIVE_CHAR_TRANSFORMED), writeCurrentValue); - nativeChars.connectStringValueTransformed(mqttUri(TOPIC_NATIVE_STRING_TRANSFORMED), writeCurrentValue); - - boxedIntegers.connectBooleanValue(mqttUri(TOPIC_BOXED_BOOLEAN), writeCurrentValue); - boxedIntegers.connectIntValue(mqttUri(TOPIC_BOXED_INTEGER), writeCurrentValue); - boxedIntegers.connectShortValue(mqttUri(TOPIC_BOXED_SHORT), writeCurrentValue); - boxedIntegers.connectLongValue(mqttUri(TOPIC_BOXED_LONG), writeCurrentValue); - boxedFloats.connectFloatValue(mqttUri(TOPIC_BOXED_FLOAT), writeCurrentValue); - boxedFloats.connectDoubleValue(mqttUri(TOPIC_BOXED_DOUBLE), writeCurrentValue); - boxedChars.connectCharValue(mqttUri(TOPIC_BOXED_CHARACTER), writeCurrentValue); - - boxedIntegers.connectBooleanValueTransformed(mqttUri(TOPIC_BOXED_BOOLEAN_TRANSFORMED), writeCurrentValue); - boxedIntegers.connectIntValueTransformed(mqttUri(TOPIC_BOXED_INTEGER_TRANSFORMED), writeCurrentValue); - boxedIntegers.connectShortValueTransformed(mqttUri(TOPIC_BOXED_SHORT_TRANSFORMED), writeCurrentValue); - boxedIntegers.connectLongValueTransformed(mqttUri(TOPIC_BOXED_LONG_TRANSFORMED), writeCurrentValue); - boxedFloats.connectFloatValueTransformed(mqttUri(TOPIC_BOXED_FLOAT_TRANSFORMED), writeCurrentValue); - boxedFloats.connectDoubleValueTransformed(mqttUri(TOPIC_BOXED_DOUBLE_TRANSFORMED), writeCurrentValue); - boxedChars.connectCharValueTransformed(mqttUri(TOPIC_BOXED_CHARACTER_TRANSFORMED), writeCurrentValue); + assertTrue(nativeIntegers.connectBooleanValue(mqttUri(TOPIC_NATIVE_BOOLEAN), writeCurrentValue)); + assertTrue(nativeIntegers.connectIntValue(mqttUri(TOPIC_NATIVE_INT), writeCurrentValue)); + assertTrue(nativeIntegers.connectShortValue(mqttUri(TOPIC_NATIVE_SHORT), writeCurrentValue)); + assertTrue(nativeIntegers.connectLongValue(mqttUri(TOPIC_NATIVE_LONG), writeCurrentValue)); + assertTrue(nativeFloats.connectFloatValue(mqttUri(TOPIC_NATIVE_FLOAT), writeCurrentValue)); + assertTrue(nativeFloats.connectDoubleValue(mqttUri(TOPIC_NATIVE_DOUBLE), writeCurrentValue)); + assertTrue(nativeChars.connectCharValue(mqttUri(TOPIC_NATIVE_CHAR), writeCurrentValue)); + assertTrue(nativeChars.connectStringValue(mqttUri(TOPIC_NATIVE_STRING), writeCurrentValue)); + + assertTrue(nativeIntegers.connectBooleanValueTransformed(mqttUri(TOPIC_NATIVE_BOOLEAN_TRANSFORMED), writeCurrentValue)); + assertTrue(nativeIntegers.connectIntValueTransformed(mqttUri(TOPIC_NATIVE_INT_TRANSFORMED), writeCurrentValue)); + assertTrue(nativeIntegers.connectShortValueTransformed(mqttUri(TOPIC_NATIVE_SHORT_TRANSFORMED), writeCurrentValue)); + assertTrue(nativeIntegers.connectLongValueTransformed(mqttUri(TOPIC_NATIVE_LONG_TRANSFORMED), writeCurrentValue)); + assertTrue(nativeFloats.connectFloatValueTransformed(mqttUri(TOPIC_NATIVE_FLOAT_TRANSFORMED), writeCurrentValue)); + assertTrue(nativeFloats.connectDoubleValueTransformed(mqttUri(TOPIC_NATIVE_DOUBLE_TRANSFORMED), writeCurrentValue)); + assertTrue(nativeChars.connectCharValueTransformed(mqttUri(TOPIC_NATIVE_CHAR_TRANSFORMED), writeCurrentValue)); + assertTrue(nativeChars.connectStringValueTransformed(mqttUri(TOPIC_NATIVE_STRING_TRANSFORMED), writeCurrentValue)); + + assertTrue(boxedIntegers.connectBooleanValue(mqttUri(TOPIC_BOXED_BOOLEAN), writeCurrentValue)); + assertTrue(boxedIntegers.connectIntValue(mqttUri(TOPIC_BOXED_INTEGER), writeCurrentValue)); + assertTrue(boxedIntegers.connectShortValue(mqttUri(TOPIC_BOXED_SHORT), writeCurrentValue)); + assertTrue(boxedIntegers.connectLongValue(mqttUri(TOPIC_BOXED_LONG), writeCurrentValue)); + assertTrue(boxedFloats.connectFloatValue(mqttUri(TOPIC_BOXED_FLOAT), writeCurrentValue)); + assertTrue(boxedFloats.connectDoubleValue(mqttUri(TOPIC_BOXED_DOUBLE), writeCurrentValue)); + assertTrue(boxedChars.connectCharValue(mqttUri(TOPIC_BOXED_CHARACTER), writeCurrentValue)); + + assertTrue(boxedIntegers.connectBooleanValueTransformed(mqttUri(TOPIC_BOXED_BOOLEAN_TRANSFORMED), writeCurrentValue)); + assertTrue(boxedIntegers.connectIntValueTransformed(mqttUri(TOPIC_BOXED_INTEGER_TRANSFORMED), writeCurrentValue)); + assertTrue(boxedIntegers.connectShortValueTransformed(mqttUri(TOPIC_BOXED_SHORT_TRANSFORMED), writeCurrentValue)); + assertTrue(boxedIntegers.connectLongValueTransformed(mqttUri(TOPIC_BOXED_LONG_TRANSFORMED), writeCurrentValue)); + assertTrue(boxedFloats.connectFloatValueTransformed(mqttUri(TOPIC_BOXED_FLOAT_TRANSFORMED), writeCurrentValue)); + assertTrue(boxedFloats.connectDoubleValueTransformed(mqttUri(TOPIC_BOXED_DOUBLE_TRANSFORMED), writeCurrentValue)); + assertTrue(boxedChars.connectCharValueTransformed(mqttUri(TOPIC_BOXED_CHARACTER_TRANSFORMED), writeCurrentValue)); } private ReceiverData createReceiver(boolean transformed) { diff --git a/ragconnect.tests/src/test/java/org/jastadd/ragconnect/tests/Errors.java b/ragconnect.tests/src/test/java/org/jastadd/ragconnect/tests/Errors.java index cc0596482e7559166947febb30144118ab4dbe10..4d32adff23abd12f2052f320466b79dc0f8673f5 100644 --- a/ragconnect.tests/src/test/java/org/jastadd/ragconnect/tests/Errors.java +++ b/ragconnect.tests/src/test/java/org/jastadd/ragconnect/tests/Errors.java @@ -2,7 +2,6 @@ package org.jastadd.ragconnect.tests; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; -import org.jastadd.ragconnect.compiler.Compiler; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; @@ -10,12 +9,14 @@ import org.junit.jupiter.api.Test; import java.io.File; import java.io.IOException; import java.nio.charset.Charset; +import java.nio.file.Path; +import java.nio.file.Paths; import java.util.Arrays; import java.util.Collections; import java.util.List; import java.util.stream.Collectors; -import static org.jastadd.ragconnect.tests.TestUtils.exec; +import static org.assertj.core.api.Assertions.assertThat; import static org.jastadd.ragconnect.tests.TestUtils.readFile; import static org.junit.jupiter.api.Assertions.assertTrue; @@ -23,8 +24,10 @@ public class Errors { private static final Logger logger = LogManager.getLogger(Errors.class); private static final String FILENAME_PATTERN = "$FILENAME"; - private static final String INPUT_DIRECTORY = "./src/test/01-input/errors/"; - private static final String OUTPUT_DIRECTORY = "./src/test/02-after-ragconnect/errors/"; + private static final String ERROR_DIRECTORY = "errors/"; + private static final String OUTPUT_DIRECTORY = TestUtils.OUTPUT_DIRECTORY_PREFIX + ERROR_DIRECTORY; + + private static final String DEFAULT_GRAMMAR_NAME = "Errors"; @BeforeAll public static void createOutputDirectory() { @@ -34,40 +37,31 @@ public class Errors { @Test void testStandardErrors() throws IOException { - test("Errors", "A"); + test("Standard", "A","Standard"); + } + + @Test + void testTwoPartsErrors() throws IOException { + test("Part", "A","Part1", "Part2"); } @SuppressWarnings("SameParameterValue") - private void test(String name, String rootNode) throws IOException { - String grammarFile = INPUT_DIRECTORY + name + ".relast"; - String ragconnectFile = INPUT_DIRECTORY + name + ".connect"; - String outFile = OUTPUT_DIRECTORY + name + ".out"; - String expectedFile = INPUT_DIRECTORY + name + ".expected"; + private void test(String expectedName, String rootNode, String... connectNames) throws IOException { + String grammarFile = ERROR_DIRECTORY + DEFAULT_GRAMMAR_NAME + ".relast"; + List<String> connectFiles = Arrays.stream(connectNames) + .map(connectName -> ERROR_DIRECTORY + connectName + ".connect") + .collect(Collectors.toList()); + Path outPath = TestUtils.runCompiler(grammarFile, connectFiles, rootNode, ERROR_DIRECTORY, 1); - try { - logger.debug("user.dir: {}", System.getProperty("user.dir")); - String[] args = { - "--o=" + OUTPUT_DIRECTORY, - grammarFile, - ragconnectFile, - "--rootNode=" + rootNode, - "--verbose" - }; - int returnValue = exec(Compiler.class, args, new File(outFile)); - Assertions.assertEquals(1, returnValue, "RagConnect did not return with value 1"); - } catch (IOException | InterruptedException e) { - e.printStackTrace(); - } + final String startOfErrorsPattern = "SEVERE: Errors:"; + String out = readFile(outPath, Charset.defaultCharset()); + assertThat(out).contains(startOfErrorsPattern); + out = out.substring(out.indexOf(startOfErrorsPattern) + 16); - String out = readFile(outFile, Charset.defaultCharset()); - String expected = readFile(expectedFile, Charset.defaultCharset()); -// if (inFiles.size() == 1) { - expected = expected.replace(FILENAME_PATTERN, name); -// } else { -// for (int i = 0; i < inFiles.size(); i++) { -// expected = expected.replace(FILENAME_PATTERN + (i + 1), inFiles.get(i)); -// } -// } + Path expectedPath = Paths.get(TestUtils.INPUT_DIRECTORY_PREFIX) + .resolve(ERROR_DIRECTORY) + .resolve(expectedName + ".expected"); + String expected = readFile(expectedPath, Charset.defaultCharset()); List<String> outList = Arrays.asList(out.split("\n")); Collections.sort(outList); List<String> expectedList = Arrays.stream(expected.split("\n")) @@ -75,10 +69,9 @@ public class Errors { .filter(s -> !s.isEmpty() && !s.startsWith("//")) .collect(Collectors.toList()); - // FIXME errors not handled correctly at the moment -// Assertions.assertLinesMatch(expectedList, outList); + Assertions.assertLinesMatch(expectedList, outList); - logger.info("ragconnect for " + name + " returned:\n{}", out); + logger.info("ragconnect for " + expectedName + " returned:\n{}", out); } } 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 17bc074545fd2815c750d957dd1038586c5ff018..5ad824bcd8de42d998d7825c6930892ecc57e37d 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 @@ -97,9 +97,9 @@ public class ExampleTest extends AbstractMqttTest { } }); - robotArm.connectAppropriateSpeed(mqttUri(TOPIC_CONFIG), writeCurrentValue); - link1.connectCurrentPosition(mqttUri(TOPIC_JOINT1)); - link2.connectCurrentPosition(mqttUri(TOPIC_JOINT2)); + assertTrue(robotArm.connectAppropriateSpeed(mqttUri(TOPIC_CONFIG), writeCurrentValue)); + assertTrue(link1.connectCurrentPosition(mqttUri(TOPIC_JOINT1))); + assertTrue(link2.connectCurrentPosition(mqttUri(TOPIC_JOINT2))); } @Override 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 43fe8b349e2f10568238042276faf2d43c74271d..580c4fc81a2952f0042eb273ffcb9be35b0a3df5 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,6 +3,7 @@ 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; @@ -16,6 +17,7 @@ import static org.junit.jupiter.api.Assertions.assertTrue; * * @author rschoene - Initial contribution */ +@Tag("Incremental") public class IncrementalDependencyTest extends AbstractMqttTest { private static final String TOPIC_IN = "in/a"; @@ -71,10 +73,10 @@ public class IncrementalDependencyTest extends AbstractMqttTest { dataB2.lastStringValue = TestUtils.DefaultMappings.BytesToString(bytes); }); - model.connectInput(mqttUri(TOPIC_IN)); - model.connectOutputOnA(mqttUri(TOPIC_OUT_A), writeCurrentValue); - b1.connectOutputOnB(mqttUri(TOPIC_OUT_B1), writeCurrentValue); - b2.connectOutputOnB(mqttUri(TOPIC_OUT_B2), writeCurrentValue); + assertTrue(model.connectInput(mqttUri(TOPIC_IN))); + assertTrue(model.connectOutputOnA(mqttUri(TOPIC_OUT_A), writeCurrentValue)); + assertTrue(b1.connectOutputOnB(mqttUri(TOPIC_OUT_B1), writeCurrentValue)); + assertTrue(b2.connectOutputOnB(mqttUri(TOPIC_OUT_B2), writeCurrentValue)); } @Override 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 7f83e3387688f578e47f6ac67c14e5f7fb26a688..52d750223efb102f73e5f63d83aaf8c85ae6847f 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 @@ -89,29 +89,29 @@ public class MappingTest extends AbstractMqttTest { data.lastNativeBooleanValue = TestUtils.DefaultMappings.BytesToBool(bytes); }); - natives.connectWriteIntValue(mqttUri(TOPIC_WRITE_NATIVE_INT), writeCurrentValue); - natives.connectWriteShortValue(mqttUri(TOPIC_WRITE_NATIVE_SHORT), writeCurrentValue); - natives.connectWriteLongValue(mqttUri(TOPIC_WRITE_NATIVE_LONG), writeCurrentValue); - natives.connectWriteFloatValue(mqttUri(TOPIC_WRITE_NATIVE_FLOAT), writeCurrentValue); - natives.connectWriteDoubleValue(mqttUri(TOPIC_WRITE_NATIVE_DOUBLE), writeCurrentValue); - natives.connectWriteCharValue(mqttUri(TOPIC_WRITE_NATIVE_CHAR), writeCurrentValue); - natives.connectWriteBooleanValue(mqttUri(TOPIC_WRITE_NATIVE_BOOLEAN), writeCurrentValue); - - natives.connectIntValue(mqttUri(TOPIC_INPUT)); - natives.connectShortValue(mqttUri(TOPIC_INPUT)); - natives.connectLongValue(mqttUri(TOPIC_INPUT)); - natives.connectFloatValue(mqttUri(TOPIC_INPUT)); - natives.connectDoubleValue(mqttUri(TOPIC_INPUT)); - natives.connectCharValue(mqttUri(TOPIC_INPUT)); - natives.connectBooleanValue(mqttUri(TOPIC_INPUT)); - - boxes.connectIntValue(mqttUri(TOPIC_INPUT)); - boxes.connectShortValue(mqttUri(TOPIC_INPUT)); - boxes.connectLongValue(mqttUri(TOPIC_INPUT)); - boxes.connectFloatValue(mqttUri(TOPIC_INPUT)); - boxes.connectDoubleValue(mqttUri(TOPIC_INPUT)); - boxes.connectCharValue(mqttUri(TOPIC_INPUT)); - boxes.connectBooleanValue(mqttUri(TOPIC_INPUT)); + assertTrue(natives.connectWriteIntValue(mqttUri(TOPIC_WRITE_NATIVE_INT), writeCurrentValue)); + assertTrue(natives.connectWriteShortValue(mqttUri(TOPIC_WRITE_NATIVE_SHORT), writeCurrentValue)); + assertTrue(natives.connectWriteLongValue(mqttUri(TOPIC_WRITE_NATIVE_LONG), writeCurrentValue)); + assertTrue(natives.connectWriteFloatValue(mqttUri(TOPIC_WRITE_NATIVE_FLOAT), writeCurrentValue)); + assertTrue(natives.connectWriteDoubleValue(mqttUri(TOPIC_WRITE_NATIVE_DOUBLE), writeCurrentValue)); + assertTrue(natives.connectWriteCharValue(mqttUri(TOPIC_WRITE_NATIVE_CHAR), writeCurrentValue)); + assertTrue(natives.connectWriteBooleanValue(mqttUri(TOPIC_WRITE_NATIVE_BOOLEAN), writeCurrentValue)); + + assertTrue(natives.connectIntValue(mqttUri(TOPIC_INPUT))); + assertTrue(natives.connectShortValue(mqttUri(TOPIC_INPUT))); + assertTrue(natives.connectLongValue(mqttUri(TOPIC_INPUT))); + assertTrue(natives.connectFloatValue(mqttUri(TOPIC_INPUT))); + assertTrue(natives.connectDoubleValue(mqttUri(TOPIC_INPUT))); + assertTrue(natives.connectCharValue(mqttUri(TOPIC_INPUT))); + assertTrue(natives.connectBooleanValue(mqttUri(TOPIC_INPUT))); + + assertTrue(boxes.connectIntValue(mqttUri(TOPIC_INPUT))); + assertTrue(boxes.connectShortValue(mqttUri(TOPIC_INPUT))); + assertTrue(boxes.connectLongValue(mqttUri(TOPIC_INPUT))); + assertTrue(boxes.connectFloatValue(mqttUri(TOPIC_INPUT))); + assertTrue(boxes.connectDoubleValue(mqttUri(TOPIC_INPUT))); + assertTrue(boxes.connectCharValue(mqttUri(TOPIC_INPUT))); + assertTrue(boxes.connectBooleanValue(mqttUri(TOPIC_INPUT))); } @Override diff --git a/ragconnect.tests/src/test/java/org/jastadd/ragconnect/tests/MqttHandlerTest.java b/ragconnect.tests/src/test/java/org/jastadd/ragconnect/tests/MqttHandlerTest.java new file mode 100644 index 0000000000000000000000000000000000000000..091990a64a31c01a6f2c59b934cfe15b6fb76ece --- /dev/null +++ b/ragconnect.tests/src/test/java/org/jastadd/ragconnect/tests/MqttHandlerTest.java @@ -0,0 +1,72 @@ +package org.jastadd.ragconnect.tests; + +import example.ast.MqttHandler; +import org.junit.jupiter.api.Tag; +import org.junit.jupiter.api.Test; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.TimeUnit; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.fail; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; + +/** + * Testing the {@link MqttHandler} used in the "example" test case. + * + * @author rschoene - Initial contribution + */ +@Tag("mqtt") +public class MqttHandlerTest { + + @Test + public void defaultBehaviour() { + MqttHandler handler = new MqttHandler(); + try { + handler.setHost(TestUtils.getMqttHost()); + } catch (IOException e) { + fail("Fail during setHost", e); + } + boolean ready = handler.waitUntilReady(2, TimeUnit.SECONDS); + assertTrue(ready); + handler.close(); + } + + @Test + public void testWelcomeMessage() throws Exception { + MqttHandler welcomeMessageSubscriber = new MqttHandler(); + List<String> receivedMessages = new ArrayList<>(); + welcomeMessageSubscriber.setHost(TestUtils.getMqttHost()); + assertTrue(welcomeMessageSubscriber.waitUntilReady(2, TimeUnit.SECONDS)); + welcomeMessageSubscriber.newConnection("components", bytes -> receivedMessages.add(new String(bytes))); + assertThat(receivedMessages).isEmpty(); + + MqttHandler handler = new MqttHandler(); + handler.setHost(TestUtils.getMqttHost()); + assertTrue(handler.waitUntilReady(2, TimeUnit.SECONDS)); + TestUtils.waitForMqtt(); + + assertEquals(1, receivedMessages.size()); + } + + @Test + public void testDontSendWelcomeMessage() throws Exception { + MqttHandler welcomeMessageSubscriber = new MqttHandler(); + List<String> receivedMessages = new ArrayList<>(); + welcomeMessageSubscriber.setHost(TestUtils.getMqttHost()); + assertTrue(welcomeMessageSubscriber.waitUntilReady(2, TimeUnit.SECONDS)); + welcomeMessageSubscriber.newConnection("components", bytes -> receivedMessages.add(new String(bytes))); + assertThat(receivedMessages).isEmpty(); + + MqttHandler handler = new MqttHandler().dontSendWelcomeMessage(); + handler.setHost(TestUtils.getMqttHost()); + assertTrue(handler.waitUntilReady(2, TimeUnit.SECONDS)); + TestUtils.waitForMqtt(); + + assertThat(receivedMessages).isEmpty(); + } + +} 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 889ce0531a6b61196856f40c5045920517b8dfd3..76eac958448c69e0ac1158074a4ddac12f4027f9 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 @@ -100,15 +100,15 @@ public class Read1Write2Test extends AbstractMqttTest { dataOther2.lastStringValue = TestUtils.DefaultMappings.BytesToString(bytes); }); - onSameNonterminal.connectInput(mqttUri(TOPIC_SAME_READ)); - onSameNonterminal.connectOutInteger(mqttUri(TOPIC_SAME_WRITE_INT), writeCurrentValue); - onSameNonterminal.connectOutString(mqttUri(TOPIC_SAME_WRITE_STRING), writeCurrentValue); - - onDifferentNonterminal.connectInput(mqttUri(TOPIC_DIFFERENT_READ)); - other1.connectOutInteger(mqttUri(TOPIC_DIFFERENT_WRITE1_INT), writeCurrentValue); - other1.connectOutString(mqttUri(TOPIC_DIFFERENT_WRITE1_STRING), writeCurrentValue); - other2.connectOutInteger(mqttUri(TOPIC_DIFFERENT_WRITE2_INT), writeCurrentValue); - other2.connectOutString(mqttUri(TOPIC_DIFFERENT_WRITE2_STRING), writeCurrentValue); + assertTrue(onSameNonterminal.connectInput(mqttUri(TOPIC_SAME_READ))); + assertTrue(onSameNonterminal.connectOutInteger(mqttUri(TOPIC_SAME_WRITE_INT), writeCurrentValue)); + assertTrue(onSameNonterminal.connectOutString(mqttUri(TOPIC_SAME_WRITE_STRING), writeCurrentValue)); + + assertTrue(onDifferentNonterminal.connectInput(mqttUri(TOPIC_DIFFERENT_READ))); + assertTrue(other1.connectOutInteger(mqttUri(TOPIC_DIFFERENT_WRITE1_INT), writeCurrentValue)); + assertTrue(other1.connectOutString(mqttUri(TOPIC_DIFFERENT_WRITE1_STRING), writeCurrentValue)); + assertTrue(other2.connectOutInteger(mqttUri(TOPIC_DIFFERENT_WRITE2_INT), writeCurrentValue)); + assertTrue(other2.connectOutString(mqttUri(TOPIC_DIFFERENT_WRITE2_STRING), writeCurrentValue)); } @Override 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 f0f634c8e031bcadac54b09dd644d34c1f2a8dff..f6a0d33a4b70689a1c883f866d33442defd2b786 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 @@ -89,14 +89,14 @@ public class Read2Write1Test extends AbstractMqttTest { dataOther2.lastIntValue = TestUtils.DefaultMappings.BytesToInt(bytes); }); - onSameNonterminal.connectInput1(mqttUri(TOPIC_SAME_READ1)); - onSameNonterminal.connectInput2(mqttUri(TOPIC_SAME_READ2)); - onSameNonterminal.connectOutInteger(mqttUri(TOPIC_SAME_WRITE_INT), writeCurrentValue); - - onDifferentNonterminal.connectInput1(mqttUri(TOPIC_DIFFERENT_READ1)); - onDifferentNonterminal.connectInput2(mqttUri(TOPIC_DIFFERENT_READ2)); - other1.connectOutInteger(mqttUri(TOPIC_DIFFERENT_WRITE1_INT), writeCurrentValue); - other2.connectOutInteger(mqttUri(TOPIC_DIFFERENT_WRITE2_INT), writeCurrentValue); + assertTrue(onSameNonterminal.connectInput1(mqttUri(TOPIC_SAME_READ1))); + assertTrue(onSameNonterminal.connectInput2(mqttUri(TOPIC_SAME_READ2))); + assertTrue(onSameNonterminal.connectOutInteger(mqttUri(TOPIC_SAME_WRITE_INT), writeCurrentValue)); + + assertTrue(onDifferentNonterminal.connectInput1(mqttUri(TOPIC_DIFFERENT_READ1))); + assertTrue(onDifferentNonterminal.connectInput2(mqttUri(TOPIC_DIFFERENT_READ2))); + assertTrue(other1.connectOutInteger(mqttUri(TOPIC_DIFFERENT_WRITE1_INT), writeCurrentValue)); + assertTrue(other2.connectOutInteger(mqttUri(TOPIC_DIFFERENT_WRITE2_INT), writeCurrentValue)); } @Override diff --git a/ragconnect.tests/src/test/java/org/jastadd/ragconnect/tests/RegressionTests.java b/ragconnect.tests/src/test/java/org/jastadd/ragconnect/tests/RegressionTests.java new file mode 100644 index 0000000000000000000000000000000000000000..67c82177d96fe34c6379b9d62537f785292827df --- /dev/null +++ b/ragconnect.tests/src/test/java/org/jastadd/ragconnect/tests/RegressionTests.java @@ -0,0 +1,65 @@ +package org.jastadd.ragconnect.tests; + +import org.junit.jupiter.api.Test; +import via.ast.A; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.nio.file.StandardOpenOption; +import java.util.Collections; + +import static org.junit.jupiter.api.Assertions.*; + +/** + * Regression tests for fixed issues. + * + * @author rschoene - Initial contribution + */ +public class RegressionTests { + + private static final String REGRESSION_TEST_OUTPUT_DIRECTORY = "regression-test/"; + + @Test + public void issue22() { + // use model of "via" test case as it uses both mqtt and rest as protocols + A a = new A(); + try { + // should fail because of missing scheme + assertFalse(a.connectBoth2BothInput("missing/scheme")); + + // should fail because of missing host + assertFalse(a.connectBoth2BothInput("mqtt://")); + + // should fail because of missing part + assertFalse(a.connectBoth2BothInput("mqtt://localhost")); + + // should fail because of unknown scheme + assertFalse(a.connectBoth2BothInput("badScheme://host/some/topic")); + } catch (IOException e) { + fail(e); + } + } + + @Test + public void issue27() throws IOException { + String grammarFile = "regression-tests/issue27/Test.relast"; + String connectFile = "regression-tests/issue27/Test.connect"; + grammarFile = ensureNoTrailingNewLine(grammarFile); + connectFile = ensureNoTrailingNewLine(connectFile); + TestUtils.runCompiler(grammarFile, Collections.singletonList(connectFile), "A", REGRESSION_TEST_OUTPUT_DIRECTORY, 0); + } + + private String ensureNoTrailingNewLine(String inputFileSuffix) throws IOException { + int dotIndex = inputFileSuffix.lastIndexOf('.'); + String outFileSuffix = inputFileSuffix.substring(0, dotIndex) + ".noNewLine" + inputFileSuffix.substring(dotIndex); + Path inputPath = Paths.get(TestUtils.INPUT_DIRECTORY_PREFIX).resolve(inputFileSuffix); + Path outputPath = Paths.get(TestUtils.INPUT_DIRECTORY_PREFIX).resolve(outFileSuffix); + + String content = Files.readString(inputPath); + Files.writeString(outputPath, content.stripTrailing(), StandardOpenOption.CREATE); + + return outFileSuffix; + } +} 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 776e7a01b5f2c683c09cb2dfd3b3e496f41110ad..c09059c8a66ca1cba262843ce30d4ce8ad0bc663 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,13 +1,22 @@ package org.jastadd.ragconnect.tests; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.jastadd.ragconnect.compiler.Compiler; +import org.junit.jupiter.api.Assertions; + 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.ArrayList; +import java.util.List; import java.util.concurrent.TimeUnit; +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.Assertions.fail; /** @@ -17,7 +26,10 @@ import static org.junit.jupiter.api.Assertions.fail; */ public class TestUtils { + private static final Logger logger = LogManager.getLogger(TestUtils.class); public static final double DELTA = 0.001d; + public static final String INPUT_DIRECTORY_PREFIX = "./src/test/01-input/"; + public static final String OUTPUT_DIRECTORY_PREFIX = "./src/test/02-after-ragconnect/"; public static String getMqttHost() { if (System.getenv("GITLAB_CI") != null) { @@ -41,6 +53,41 @@ public class TestUtils { return 1883; } + public static Path runCompiler(String grammarFile, Iterable<String> connectFiles, String rootNode, String outputDirectory, int expectedReturnValue) { + + assertThat(connectFiles).isNotEmpty(); + + Path outPath = Paths.get(OUTPUT_DIRECTORY_PREFIX) + .resolve(outputDirectory) + .resolve("Compiler.out"); + ensureCreated(outPath.getParent()); + + try { + logger.debug("user.dir: {}", System.getProperty("user.dir")); + List<String> args = new ArrayList<>() {{ + add("--o=" + OUTPUT_DIRECTORY_PREFIX + outputDirectory); + add("--rootNode=" + rootNode); + add("--verbose"); + add(INPUT_DIRECTORY_PREFIX + grammarFile); + }}; + connectFiles.forEach(connectFile -> args.add(INPUT_DIRECTORY_PREFIX + connectFile)); + + int returnValue = exec(Compiler.class, args.toArray(new String[0]), outPath.toFile()); + Assertions.assertEquals(expectedReturnValue, returnValue, "RagConnect did not return with value " + expectedReturnValue); + } catch (IOException | InterruptedException e) { + fail(e); + } + return outPath; + } + + private static void ensureCreated(Path directory) { + File directoryFile = directory.toFile(); + if (directoryFile.exists() && directoryFile.isDirectory()) { + return; + } + assertTrue(directoryFile.mkdirs()); + } + public static int exec(Class<?> klass, String[] args, File err) throws IOException, InterruptedException { String javaHome = System.getProperty("java.home"); @@ -79,14 +126,14 @@ public class TestUtils { } } - public static String readFile(String path, Charset encoding) + public static String readFile(Path path, Charset encoding) throws IOException { - byte[] encoded = Files.readAllBytes(Paths.get(path)); + byte[] encoded = Files.readAllBytes(path); return new String(encoded, encoding); } static void waitForMqtt() throws InterruptedException { - TimeUnit.SECONDS.sleep(2); + TimeUnit.MILLISECONDS.sleep(1500); } @SuppressWarnings({"unused", "rawtypes"}) 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 b22a2fb6ac2d4fcfe5c78332f64a5ec6025613d9..6d99149688b33d8401037fb358f736c2509b0921 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 @@ -87,12 +87,12 @@ public class TokenValueSendTest extends AbstractMqttTest { dataThreeOther.lastStringValue = TestUtils.DefaultMappings.BytesToString(bytes); }); - one.connectValue(mqttUri(TOPIC_SEND_ONE), writeCurrentValue); - two.connectValue(mqttUri(TOPIC_RECEIVE_TWO)); - two.connectValue(mqttUri(TOPIC_SEND_TWO), writeCurrentValue); - three.connectValue(mqttUri(TOPIC_RECEIVE_THREE_VALUE)); - three.connectValue(mqttUri(TOPIC_SEND_THREE_VALUE), writeCurrentValue); - three.connectOtherOutput(mqttUri(TOPIC_SEND_THREE_OTHER), writeCurrentValue); + assertTrue(one.connectValue(mqttUri(TOPIC_SEND_ONE), writeCurrentValue)); + assertTrue(two.connectValue(mqttUri(TOPIC_RECEIVE_TWO))); + assertTrue(two.connectValue(mqttUri(TOPIC_SEND_TWO), writeCurrentValue)); + assertTrue(three.connectValue(mqttUri(TOPIC_RECEIVE_THREE_VALUE))); + assertTrue(three.connectValue(mqttUri(TOPIC_SEND_THREE_VALUE), writeCurrentValue)); + assertTrue(three.connectOtherOutput(mqttUri(TOPIC_SEND_THREE_OTHER), writeCurrentValue)); } @Override 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 index 5dd1b1504701b0c5499e7277b8287e1b66a9e5a5..0edfbd6bee0b412158a799ef388901e62d398495 100644 --- a/ragconnect.tests/src/test/java/org/jastadd/ragconnect/tests/TreeAllowedTokensIncrementalTest.java +++ b/ragconnect.tests/src/test/java/org/jastadd/ragconnect/tests/TreeAllowedTokensIncrementalTest.java @@ -18,7 +18,8 @@ import static org.junit.jupiter.api.Assertions.assertTrue; * * @author rschoene - Initial contribution */ -@Tag("SpecificTest") +@Tag("Incremental") +@Tag("Tree") public class TreeAllowedTokensIncrementalTest extends AbstractTreeAllowedTokensTest { private Root model; @@ -42,6 +43,8 @@ public class TreeAllowedTokensIncrementalTest extends AbstractTreeAllowedTokensT receiverRoot = new ReceiverRoot(); model.addReceiverRoot((ReceiverRoot) receiverRoot); + + model.ragconnectCheckIncremental(); } @Override @@ -58,14 +61,14 @@ public class TreeAllowedTokensIncrementalTest extends AbstractTreeAllowedTokensT 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); + assertTrue(senderRoot.connectInput1WhenFlagIsFalse(mqttUri(TOPIC_INPUT1FALSE))); + assertTrue(senderRoot.connectInput1WhenFlagIsTrue(mqttUri(TOPIC_INPUT1TRUE))); + assertTrue(senderRoot.connectInput2(mqttUri(TOPIC_INPUT2))); + assertTrue(senderRoot.connectInput3(mqttUri(TOPIC_INPUT3))); + assertTrue(receiverRoot.connectAlfa(mqttUri(TOPIC_ALFA))); + assertTrue(receiverRoot.connectAlfaPrimitive(mqttUri(TOPIC_ALFA_PRIMITIVE))); + assertTrue(senderRoot.connectAlfa(mqttUri(TOPIC_ALFA), writeCurrentValue)); + assertTrue(senderRoot.connectAlfaPrimitive(mqttUri(TOPIC_ALFA_PRIMITIVE), writeCurrentValue)); } @Override 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 index c3b91a04f45a47250f2cdf557575c5c48ac09c05..9780d56daaa807a13082e9776fa45b1ec4eee5a3 100644 --- a/ragconnect.tests/src/test/java/org/jastadd/ragconnect/tests/TreeAllowedTokensManualTest.java +++ b/ragconnect.tests/src/test/java/org/jastadd/ragconnect/tests/TreeAllowedTokensManualTest.java @@ -1,5 +1,6 @@ package org.jastadd.ragconnect.tests; +import org.junit.jupiter.api.Tag; import org.junit.jupiter.api.Test; import treeAllowedTokens.ast.*; @@ -18,6 +19,7 @@ import static org.junit.jupiter.api.Assertions.*; * * @author rschoene - Initial contribution */ +@Tag("Tree") public class TreeAllowedTokensManualTest extends AbstractTreeAllowedTokensTest { private Root model; @@ -63,14 +65,14 @@ public class TreeAllowedTokensManualTest extends AbstractTreeAllowedTokensTest { 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); + assertTrue(senderRoot.connectInput1WhenFlagIsFalse(mqttUri(TOPIC_INPUT1FALSE))); + assertTrue(senderRoot.connectInput1WhenFlagIsTrue(mqttUri(TOPIC_INPUT1TRUE))); + assertTrue(senderRoot.connectInput2(mqttUri(TOPIC_INPUT2))); + assertTrue(senderRoot.connectInput3(mqttUri(TOPIC_INPUT3))); + assertTrue(receiverRoot.connectAlfa(mqttUri(TOPIC_ALFA))); + assertTrue(receiverRoot.connectAlfaPrimitive(mqttUri(TOPIC_ALFA_PRIMITIVE))); + assertTrue(senderRoot.connectAlfa(mqttUri(TOPIC_ALFA), writeCurrentValue)); + assertTrue(senderRoot.connectAlfaPrimitive(mqttUri(TOPIC_ALFA_PRIMITIVE), writeCurrentValue)); } @Override 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 index e0d7c817e372395adf98565b5a44347335a2eb45..9d455b6abe09809c0277c71dd3f8028f05d63da3 100644 --- a/ragconnect.tests/src/test/java/org/jastadd/ragconnect/tests/TreeIncrementalTest.java +++ b/ragconnect.tests/src/test/java/org/jastadd/ragconnect/tests/TreeIncrementalTest.java @@ -1,5 +1,6 @@ package org.jastadd.ragconnect.tests; +import org.junit.jupiter.api.Tag; import org.junit.jupiter.api.Test; import treeInc.ast.*; @@ -17,6 +18,8 @@ import static org.junit.jupiter.api.Assertions.*; * * @author rschoene - Initial contribution */ +@Tag("Tree") +@Tag("Incremental") public class TreeIncrementalTest extends AbstractTreeTest { private Root model; @@ -53,8 +56,8 @@ public class TreeIncrementalTest extends AbstractTreeTest { 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); + assertTrue(receiverRoot.connectAlfa(mqttUri(TOPIC_ALFA))); + assertTrue(senderRoot.connectAlfa(mqttUri(TOPIC_ALFA), writeCurrentValue)); } @Override 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 index 060317dfd749f0815af9fe42d1cb9553fe9034ae..10c73aeff57d6752c8f6b903acbde2dd9d93aa8b 100644 --- a/ragconnect.tests/src/test/java/org/jastadd/ragconnect/tests/TreeManualTest.java +++ b/ragconnect.tests/src/test/java/org/jastadd/ragconnect/tests/TreeManualTest.java @@ -1,5 +1,6 @@ package org.jastadd.ragconnect.tests; +import org.junit.jupiter.api.Tag; import org.junit.jupiter.api.Test; import tree.ast.MqttHandler; import tree.ast.ReceiverRoot; @@ -19,6 +20,7 @@ import static org.junit.jupiter.api.Assertions.assertTrue; * * @author rschoene - Initial contribution */ +@Tag("Tree") public class TreeManualTest extends AbstractTreeTest { private Root model; @@ -56,8 +58,8 @@ public class TreeManualTest extends AbstractTreeTest { 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); + assertTrue(receiverRoot.connectAlfa(mqttUri(TOPIC_ALFA))); + assertTrue(senderRoot.connectAlfa(mqttUri(TOPIC_ALFA), writeCurrentValue)); } @Override diff --git a/ragconnect.tests/src/test/java/org/jastadd/ragconnect/tests/TutorialTest.java b/ragconnect.tests/src/test/java/org/jastadd/ragconnect/tests/TutorialTest.java index 6e66c761ffe4b5e6045d567cc1bdf9a14dea4de0..64ad5fbd147ba6c7e22d24ba7f92fe8d7114ced7 100644 --- a/ragconnect.tests/src/test/java/org/jastadd/ragconnect/tests/TutorialTest.java +++ b/ragconnect.tests/src/test/java/org/jastadd/ragconnect/tests/TutorialTest.java @@ -6,6 +6,7 @@ import tutorial.ast.B; import java.io.IOException; import static org.jastadd.ragconnect.tests.TestUtils.mqttUri; +import static org.junit.jupiter.api.Assertions.assertTrue; /** * Testcase "Tutorial". @@ -38,10 +39,10 @@ public class TutorialTest extends AbstractMqttTest { // b2.OutputOnB -> a.Input b2.addDependencyB(a); - a.connectInput(mqttUri("topic/for/input")); - a.connectOutputOnA(mqttUri("a/out"), true); - b1.connectOutputOnB(mqttUri("b1/out"), true); - b2.connectOutputOnB(mqttUri("b2/out"), false); + assertTrue(a.connectInput(mqttUri("topic/for/input"))); + assertTrue(a.connectOutputOnA(mqttUri("a/out"), true)); + assertTrue(b1.connectOutputOnB(mqttUri("b1/out"), true)); + assertTrue(b2.connectOutputOnB(mqttUri("b2/out"), false)); } @Override 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 5433514398ea8ec3037f95fbc1c63bbb6a1cf2be..7ab46f7616a1cf90737c2e0b3ff752f553d38292 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 @@ -106,18 +106,18 @@ public class ViaTest extends AbstractMqttTest { 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); + assertTrue(model.connectMqtt2MqttInput(mqttUri(TOPIC_MQTT_2_MQTT_RECEIVE))); + assertTrue(model.connectMqtt2MqttOutput(mqttUri(TOPIC_MQTT_2_MQTT_SEND), writeCurrentValue)); + assertTrue(model.connectMqtt2RestInput(mqttUri(TOPIC_MQTT_2_REST_RECEIVE))); + assertTrue(model.connectMqtt2RestOutput(restUri(PATH_MQTT_2_REST_SEND, REST_PORT), writeCurrentValue)); + assertTrue(model.connectRest2MqttInput(restUri(PATH_REST_2_MQTT_RECEIVE, REST_PORT))); + assertTrue(model.connectRest2MqttOutput(mqttUri(TOPIC_REST_2_MQTT_SEND), writeCurrentValue)); + assertTrue(model.connectRest2RestInput(restUri(PATH_REST_2_REST_RECEIVE, REST_PORT))); + assertTrue(model.connectRest2RestOutput(restUri(PATH_REST_2_REST_SEND, REST_PORT), writeCurrentValue)); + assertTrue(model.connectBoth2BothInput(mqttUri(TOPIC_BOTH_MQTT_RECEIVE))); + assertTrue(model.connectBoth2BothInput(restUri(PATH_BOTH_REST_RECEIVE, REST_PORT))); + assertTrue(model.connectBoth2MqttOutput(mqttUri(TOPIC_BOTH_2_MQTT_SEND), writeCurrentValue)); + assertTrue(model.connectBoth2RestOutput(restUri(PATH_BOTH_2_REST_SEND, REST_PORT), writeCurrentValue)); } @Override diff --git a/relast-preprocessor b/relast-preprocessor index b538a7f709167c5f56fe65e6d9e9f02179cacaef..02f8e35993dc3f62ab49e94f69a6dc27170660da 160000 --- a/relast-preprocessor +++ b/relast-preprocessor @@ -1 +1 @@ -Subproject commit b538a7f709167c5f56fe65e6d9e9f02179cacaef +Subproject commit 02f8e35993dc3f62ab49e94f69a6dc27170660da diff --git a/settings.gradle b/settings.gradle index e7769874a5f3186274ceecbcd445feeb656cf9a4..8a597cfa491920744bb8b5e1d3f103fb4fc95bb1 100644 --- a/settings.gradle +++ b/settings.gradle @@ -1,3 +1,9 @@ +pluginManagement { + plugins { + id 'org.jastadd' version '1.13.3' + } +} + rootProject.name = 'ragconnect' include 'relast-preprocessor'