Skip to content
Snippets Groups Projects
Commit 3d6f61cd authored by René Schöne's avatar René Schöne
Browse files

Add tests to this repo again.

parent c2531c48
No related branches found
No related tags found
No related merge requests found
Showing
with 744 additions and 0 deletions
File added
build
src/gen-res/
src/gen/
out/
*.class
buildscript {
repositories.mavenCentral()
dependencies {
classpath 'org.jastadd:jastaddgradle:1.13.3'
classpath fileTree(include: ['buildSrc.jar'], dir: '../libs')
}
}
import org.jastadd.relast.plugin.RelastPlugin
import org.jastadd.relast.plugin.RelastTest
plugins {
id 'java'
id 'java-library'
id 'idea'
id 'com.github.ben-manes.versions' version '0.36.0'
id 'com.google.protobuf' version "0.8.14"
}
apply plugin: 'jastadd'
apply plugin: RelastPlugin
group = 'de.tudresden.inf.st'
repositories {
mavenCentral()
jcenter()
}
dependencies {
implementation project(':ragconnect.base')
runtime group: 'org.jastadd', name: 'jastadd', version: '2.3.4'
testImplementation group: 'org.junit.jupiter', name: 'junit-jupiter-api', version: '5.4.0'
testRuntimeOnly group: 'org.junit.jupiter', name: 'junit-jupiter-engine', version: '5.4.0'
testImplementation group: 'org.assertj', name: 'assertj-core', version: '3.12.1'
// mqtt
testImplementation group: 'org.fusesource.mqtt-client', name: 'mqtt-client', version: '1.15'
// rest and client
testImplementation group: 'com.sparkjava', name: 'spark-core', version: '2.9.2'
testImplementation group: 'org.apache.logging.log4j', name: 'log4j-slf4j-impl', version: '2.11.2'
testImplementation group: 'org.glassfish.jersey.core', name: 'jersey-client', version: '2.31'
testImplementation group: 'org.glassfish.jersey.inject', name: 'jersey-hk2', version: '2.31'
testImplementation group: 'net.sf.beaver', name: 'beaver-rt', version: '0.9.11'
api group: 'com.google.protobuf', name: 'protobuf-java', version: '3.0.0'
}
test {
useJUnitPlatform {
excludeTags 'mqtt'
}
maxHeapSize = '1G'
}
protobuf {
protoc {
// The artifact spec for the Protobuf Compiler
artifact = 'com.google.protobuf:protoc:3.0.0'
}
}
task allTests(type: Test, dependsOn: testClasses) {
description = 'Run every test'
group = 'verification'
useJUnitPlatform {
includeTags 'mqtt'
}
}
relastTest {
//noinspection GroovyAssignabilityCheck
compilerLocation = '../libs/relast.jar'
}
File genSrc = file("src/test/java-gen")
sourceSets.test.java.srcDir genSrc
idea.module.generatedSourceDirs += genSrc
clean {
delete 'src/test/02-after-ragconnect/*/', 'src/test/03-after-relast/*/', 'src/test/java-gen/*/'
}
// --- Test: Example ---
task preprocessExampleTest(type: JavaExec, group: 'verification') {
doFirst {
delete 'src/test/02-after-ragconnect/example/Test.relast',
'src/test/02-after-ragconnect/example/MqttHandler.jadd',
'src/test/02-after-ragconnect/example/RagConnect.jadd'
}
classpath = sourceSets.main.runtimeClasspath
main = 'org.jastadd.ragconnect.compiler.Compiler'
args '--o=src/test/02-after-ragconnect/example',
'src/test/01-input/example/Test.relast',
'src/test/01-input/example/Test.connect',
'--rootNode=Model',
'--logReads', '--logWrites'
}
task compileExampleTest(type: RelastTest) {
useJastAddNames = true
jastAddList = 'JastAddList'
relastFiles 'src/test/02-after-ragconnect/example/Test.relast',
'src/test/02-after-ragconnect/example/RagConnect.relast'
grammarName = 'src/test/03-after-relast/example/example'
packageName = 'example.ast'
moreInputFiles 'src/test/01-input/example/Test.jadd',
'src/test/02-after-ragconnect/example/MqttHandler.jadd',
'src/test/02-after-ragconnect/example/RagConnect.jadd'
}
compileTestJava.dependsOn compileExampleTest
compileExampleTest.dependsOn preprocessExampleTest
// --- Test: default-only-read ---
task preprocessDefaultOnlyReadTest(type: JavaExec, group: 'verification') {
doFirst {
delete 'src/test/02-after-ragconnect/defaultOnlyRead/Test.relast',
'src/test/02-after-ragconnect/defaultOnlyRead/MqttHandler.jadd',
'src/test/02-after-ragconnect/defaultOnlyRead/RagConnect.jadd'
}
classpath = sourceSets.main.runtimeClasspath
main = 'org.jastadd.ragconnect.compiler.Compiler'
args '--o=src/test/02-after-ragconnect/defaultOnlyRead',
'src/test/01-input/defaultOnlyRead/Test.relast',
'src/test/01-input/defaultOnlyRead/Test.connect',
'--rootNode=A'
}
task compileDefaultOnlyReadTest(type: RelastTest) {
useJastAddNames = true
jastAddList = 'JastAddList'
relastFiles 'src/test/02-after-ragconnect/defaultOnlyRead/Test.relast',
'src/test/02-after-ragconnect/defaultOnlyRead/RagConnect.relast'
grammarName = 'src/test/03-after-relast/defaultOnlyRead/defaultOnlyRead'
packageName = 'defaultOnlyRead.ast'
moreInputFiles 'src/test/02-after-ragconnect/defaultOnlyRead/MqttHandler.jadd',
'src/test/02-after-ragconnect/defaultOnlyRead/RagConnect.jadd'
}
compileTestJava.dependsOn compileDefaultOnlyReadTest
compileDefaultOnlyReadTest.dependsOn preprocessDefaultOnlyReadTest
// --- Test: default-only-write ---
task preprocessDefaultOnlyWriteTest(type: JavaExec, group: 'verification') {
doFirst {
delete 'src/test/02-after-ragconnect/defaultOnlyWrite/Test.relast',
'src/test/02-after-ragconnect/defaultOnlyWrite/MqttHandler.jadd',
'src/test/02-after-ragconnect/defaultOnlyWrite/RagConnect.jadd'
}
classpath = sourceSets.main.runtimeClasspath
main = 'org.jastadd.ragconnect.compiler.Compiler'
args '--o=src/test/02-after-ragconnect/defaultOnlyWrite',
'src/test/01-input/defaultOnlyWrite/Test.relast',
'src/test/01-input/defaultOnlyWrite/Test.connect',
'--rootNode=A'
}
task compileDefaultOnlyWriteTest(type: RelastTest) {
useJastAddNames = true
jastAddList = 'JastAddList'
relastFiles 'src/test/02-after-ragconnect/defaultOnlyWrite/Test.relast',
'src/test/02-after-ragconnect/defaultOnlyWrite/RagConnect.relast'
grammarName = 'src/test/03-after-relast/defaultOnlyWrite/defaultOnlyWrite'
packageName = 'defaultOnlyWrite.ast'
moreInputFiles 'src/test/01-input/defaultOnlyWrite/Test.jadd',
'src/test/02-after-ragconnect/defaultOnlyWrite/MqttHandler.jadd',
'src/test/02-after-ragconnect/defaultOnlyWrite/RagConnect.jadd'
}
compileTestJava.dependsOn compileDefaultOnlyWriteTest
compileDefaultOnlyWriteTest.dependsOn preprocessDefaultOnlyWriteTest
// --- Test: read1write2 ---
task preprocessRead1Write2Test(type: JavaExec, group: 'verification') {
doFirst {
delete 'src/test/02-after-ragconnect/read1write2/Test.relast',
'src/test/02-after-ragconnect/read1write2/MqttHandler.jadd',
'src/test/02-after-ragconnect/read1write2/RagConnect.jadd'
}
classpath = sourceSets.main.runtimeClasspath
main = 'org.jastadd.ragconnect.compiler.Compiler'
args '--o=src/test/02-after-ragconnect/read1write2',
'src/test/01-input/read1write2/Test.relast',
'src/test/01-input/read1write2/Test.connect',
'--rootNode=A'
}
task compileRead1Write2Test(type: RelastTest) {
useJastAddNames = true
jastAddList = 'JastAddList'
relastFiles 'src/test/02-after-ragconnect/read1write2/Test.relast',
'src/test/02-after-ragconnect/read1write2/RagConnect.relast'
grammarName = 'src/test/03-after-relast/read1write2/read1write2'
packageName = 'read1write2.ast'
moreInputFiles 'src/test/01-input/read1write2/Test.jadd',
'src/test/02-after-ragconnect/read1write2/MqttHandler.jadd',
'src/test/02-after-ragconnect/read1write2/RagConnect.jadd'
}
compileTestJava.dependsOn compileRead1Write2Test
compileRead1Write2Test.dependsOn preprocessRead1Write2Test
// --- Test: read2write1 ---
task preprocessRead2Write1Test(type: JavaExec, group: 'verification') {
doFirst {
delete 'src/test/02-after-ragconnect/read2write1/Test.relast',
'src/test/02-after-ragconnect/read2write1/MqttHandler.jadd',
'src/test/02-after-ragconnect/read2write1/RagConnect.jadd'
}
classpath = sourceSets.main.runtimeClasspath
main = 'org.jastadd.ragconnect.compiler.Compiler'
args '--o=src/test/02-after-ragconnect/read2write1',
'src/test/01-input/read2write1/Test.relast',
'src/test/01-input/read2write1/Test.connect',
'--rootNode=A'
}
task compileRead2Write1Test(type: RelastTest) {
useJastAddNames = true
jastAddList = 'JastAddList'
relastFiles 'src/test/02-after-ragconnect/read2write1/Test.relast',
'src/test/02-after-ragconnect/read2write1/RagConnect.relast'
grammarName = 'src/test/03-after-relast/read2write1/read2write1'
packageName = 'read2write1.ast'
moreInputFiles 'src/test/01-input/read2write1/Test.jadd',
'src/test/02-after-ragconnect/read2write1/MqttHandler.jadd',
'src/test/02-after-ragconnect/read2write1/RagConnect.jadd'
}
compileTestJava.dependsOn compileRead2Write1Test
compileRead2Write1Test.dependsOn preprocessRead2Write1Test
// --- Test: via ---
task preprocessViaTest(type: JavaExec, group: 'verification') {
doFirst {
delete 'src/test/02-after-ragconnect/via/Test.relast',
'src/test/02-after-ragconnect/via/MqttHandler.jadd',
'src/test/02-after-ragconnect/via/RestHandler.jadd',
'src/test/02-after-ragconnect/via/RagConnect.jadd'
}
classpath = sourceSets.main.runtimeClasspath
main = 'org.jastadd.ragconnect.compiler.Compiler'
args '--o=src/test/02-after-ragconnect/via',
'src/test/01-input/via/Test.relast',
'src/test/01-input/via/Test.connect',
'--rootNode=A',
'--protocols=mqtt,rest'
}
task compileViaTest(type: RelastTest) {
useJastAddNames = true
jastAddList = 'JastAddList'
relastFiles 'src/test/02-after-ragconnect/via/Test.relast',
'src/test/02-after-ragconnect/via/RagConnect.relast'
grammarName = 'src/test/03-after-relast/via/via'
packageName = 'via.ast'
moreInputFiles 'src/test/01-input/via/Test.jadd',
'src/test/02-after-ragconnect/via/MqttHandler.jadd',
'src/test/02-after-ragconnect/via/RestHandler.jadd',
'src/test/02-after-ragconnect/via/RagConnect.jadd'
}
compileTestJava.dependsOn compileViaTest
compileViaTest.dependsOn preprocessViaTest
// --- Test: token-value-send ---
task preprocessTokenValueSendTest(type: JavaExec, group: 'verification') {
doFirst {
delete 'src/test/02-after-ragconnect/tokenValueSend/Test.relast',
'src/test/02-after-ragconnect/tokenValueSend/MqttHandler.jadd',
'src/test/02-after-ragconnect/tokenValueSend/RestHandler.jadd',
'src/test/02-after-ragconnect/tokenValueSend/RagConnect.jadd'
}
classpath = sourceSets.main.runtimeClasspath
main = 'org.jastadd.ragconnect.compiler.Compiler'
args '--o=src/test/02-after-ragconnect/tokenValueSend',
'src/test/01-input/tokenValueSend/Test.relast',
'src/test/01-input/tokenValueSend/Test.connect',
'--rootNode=A'
}
task compileTokenValueSendTest(type: RelastTest) {
useJastAddNames = true
jastAddList = 'JastAddList'
relastFiles 'src/test/02-after-ragconnect/tokenValueSend/Test.relast',
'src/test/02-after-ragconnect/tokenValueSend/RagConnect.relast'
grammarName = 'src/test/03-after-relast/tokenValueSend/tokenValueSend'
packageName = 'tokenValueSend.ast'
moreInputFiles 'src/test/01-input/tokenValueSend/Test.jadd',
'src/test/02-after-ragconnect/tokenValueSend/MqttHandler.jadd',
'src/test/02-after-ragconnect/tokenValueSend/RagConnect.jadd'
}
compileTestJava.dependsOn compileTokenValueSendTest
compileTokenValueSendTest.dependsOn preprocessTokenValueSendTest
// --- Test: tutorial ---
task preprocessTutorialTest(type: JavaExec, group: 'verification') {
doFirst {
delete 'src/test/02-after-ragconnect/tutorial/Test.relast',
'src/test/02-after-ragconnect/tutorial/MqttHandler.jadd',
'src/test/02-after-ragconnect/tutorial/RagConnect.jadd'
}
classpath = sourceSets.main.runtimeClasspath
main = 'org.jastadd.ragconnect.compiler.Compiler'
args '--o=src/test/02-after-ragconnect/tutorial',
'src/test/01-input/tutorial/Test.relast',
'src/test/01-input/tutorial/Test.connect',
'--rootNode=A'
}
task compileTutorialTest(type: RelastTest) {
useJastAddNames = true
jastAddList = 'JastAddList'
relastFiles 'src/test/02-after-ragconnect/tutorial/Test.relast',
'src/test/02-after-ragconnect/tutorial/RagConnect.relast'
grammarName = 'src/test/03-after-relast/tutorial/tutorial'
packageName = 'tutorial.ast'
moreInputFiles 'src/test/01-input/tutorial/Test.jadd',
'src/test/02-after-ragconnect/tutorial/MqttHandler.jadd',
'src/test/02-after-ragconnect/tutorial/RagConnect.jadd'
}
compileTestJava.dependsOn compileTutorialTest
compileTutorialTest.dependsOn preprocessTutorialTest
# Default Only Read
Idea: Use only `ReadFromMqttDefinition`, test all default mapping definitions from `byte[]` to primitive (and boxed) types
// --- update definitions ---
receive NativeTypes.IntValue;
receive NativeTypes.ShortValue;
receive NativeTypes.LongValue;
receive NativeTypes.FloatValue;
receive NativeTypes.DoubleValue;
receive NativeTypes.CharValue;
receive NativeTypes.StringValue;
receive BoxedTypes.IntValue;
receive BoxedTypes.ShortValue;
receive BoxedTypes.LongValue;
receive BoxedTypes.FloatValue;
receive BoxedTypes.DoubleValue;
receive BoxedTypes.CharValue;
A ::= NativeTypes* BoxedTypes* ;
NativeTypes ::= <IntValue:int> <ShortValue:short> <LongValue:long> <FloatValue:float> <DoubleValue:double> <CharValue:char> <StringValue:String> ;
BoxedTypes ::= <IntValue:Integer> <ShortValue:Short> <LongValue:Long> <FloatValue:Float> <DoubleValue:Double> <CharValue:Character> ;
# Default Only Write
Idea: Use only `WriteToMqttDefintion`, test all default mapping definitions from primitive (and boxed) types to `byte[]`.
// --- update definitions ---
// native types, synthesized
send NativeTypesSyn.IntValue;
send NativeTypesSyn.ShortValue;
send NativeTypesSyn.LongValue;
send NativeTypesSyn.FloatValue;
send NativeTypesSyn.DoubleValue;
send NativeTypesSyn.CharValue;
send NativeTypesSyn.StringValue;
// boxed types, synthesized
send BoxedTypesSyn.IntValue;
send BoxedTypesSyn.ShortValue;
send BoxedTypesSyn.LongValue;
send BoxedTypesSyn.FloatValue;
send BoxedTypesSyn.DoubleValue;
send BoxedTypesSyn.CharValue;
// --- dependency definitions ---
NativeTypesSyn.IntValue canDependOn NativeTypesSyn.DriverSyn as nativeIntDependency;
NativeTypesSyn.ShortValue canDependOn NativeTypesSyn.DriverSyn as nativeShortDependency;
NativeTypesSyn.LongValue canDependOn NativeTypesSyn.DriverSyn as nativeLongDependency;
NativeTypesSyn.FloatValue canDependOn NativeTypesSyn.DriverSyn as nativeFloatDependency;
NativeTypesSyn.DoubleValue canDependOn NativeTypesSyn.DriverSyn as nativeDoubleDependency;
NativeTypesSyn.CharValue canDependOn NativeTypesSyn.DriverSyn as nativeCharDependency;
NativeTypesSyn.StringValue canDependOn NativeTypesSyn.DriverSyn as nativeStringDependency;
BoxedTypesSyn.IntValue canDependOn BoxedTypesSyn.DriverSyn as boxedIntDependency;
BoxedTypesSyn.ShortValue canDependOn BoxedTypesSyn.DriverSyn as boxedShortDependency;
BoxedTypesSyn.LongValue canDependOn BoxedTypesSyn.DriverSyn as boxedLongDependency;
BoxedTypesSyn.FloatValue canDependOn BoxedTypesSyn.DriverSyn as boxedFloatDependency;
BoxedTypesSyn.DoubleValue canDependOn BoxedTypesSyn.DriverSyn as boxedDoubleDependency;
BoxedTypesSyn.CharValue canDependOn BoxedTypesSyn.DriverSyn as boxedCharDependency;
// --- inherited attributes not supported ---
//// native types, inherited
//send NativeTypesInh.IntValue;
//send NativeTypesInh.ShortValue;
//send NativeTypesInh.LongValue;
//send NativeTypesInh.FloatValue;
//send NativeTypesInh.DoubleValue;
//send NativeTypesInh.CharValue;
//send NativeTypesInh.StringValue;
//
//// boxed types, inherited
//send BoxedTypesInh.IntValue;
//send BoxedTypesInh.ShortValue;
//send BoxedTypesInh.LongValue;
//send BoxedTypesInh.FloatValue;
//send BoxedTypesInh.DoubleValue;
//send BoxedTypesInh.CharValue;
aspect Computation {
// native types, synthesized
syn int NativeTypesSyn.getIntValue() = Integer.parseInt(getDriverSyn());
syn short NativeTypesSyn.getShortValue() = Short.parseShort(getDriverSyn());
syn long NativeTypesSyn.getLongValue() = Long.parseLong(getDriverSyn());
syn float NativeTypesSyn.getFloatValue() = Float.parseFloat(getDriverSyn());
syn double NativeTypesSyn.getDoubleValue() = Double.parseDouble(getDriverSyn());
syn char NativeTypesSyn.getCharValue() = getDriverSyn().charAt(0);
syn String NativeTypesSyn.getStringValue() = new String(getDriverSyn());
// boxed types, synthesized
syn Integer BoxedTypesSyn.getIntValue() = Integer.valueOf(getDriverSyn());
syn Short BoxedTypesSyn.getShortValue() = Short.valueOf(getDriverSyn());
syn Long BoxedTypesSyn.getLongValue() = Long.valueOf(getDriverSyn());
syn Float BoxedTypesSyn.getFloatValue() = Float.valueOf(getDriverSyn());
syn Double BoxedTypesSyn.getDoubleValue() = Double.valueOf(getDriverSyn());
syn Character BoxedTypesSyn.getCharValue() = getDriverSyn().charAt(0);
// --- inherited attributes not supported ---
// // native types, inherited
// inh int NativeTypesInh.getIntValue();
// eq A.getNativeTypesInh().getIntValue() = Integer.parseInt(getDriverInh());
// inh short NativeTypesInh.getShortValue();
// eq A.getNativeTypesInh().getShortValue() = Short.parseShort(getDriverInh());
// inh long NativeTypesInh.getLongValue();
// eq A.getNativeTypesInh().getLongValue() = Long.parseLong(getDriverInh());
// inh float NativeTypesInh.getFloatValue();
// eq A.getNativeTypesInh().getFloatValue() = Float.parseFloat(getDriverInh());
// inh double NativeTypesInh.getDoubleValue();
// eq A.getNativeTypesInh().getDoubleValue() = Double.parseDouble(getDriverInh());
// inh char NativeTypesInh.getCharValue();
// eq A.getNativeTypesInh().getCharValue() = getDriverInh().charAt(0);
// inh String NativeTypesInh.getStringValue();
// eq A.getNativeTypesInh().getStringValue() = new String(getDriverInh());
//
// // boxed types, inherited
// inh Integer BoxedTypesInh.getIntValue();
// eq A.getBoxedTypesInh().getIntValue() = Integer.valueOf(getDriverInh());
// inh Short BoxedTypesInh.getShortValue();
// eq A.getBoxedTypesInh().getShortValue() = Short.valueOf(getDriverInh());
// inh Long BoxedTypesInh.getLongValue();
// eq A.getBoxedTypesInh().getLongValue() = Long.valueOf(getDriverInh());
// inh Float BoxedTypesInh.getFloatValue();
// eq A.getBoxedTypesInh().getFloatValue() = Float.valueOf(getDriverInh());
// inh Double BoxedTypesInh.getDoubleValue();
// eq A.getBoxedTypesInh().getDoubleValue() = Double.valueOf(getDriverInh());
// inh Character BoxedTypesInh.getCharValue();
// eq A.getBoxedTypesInh().getCharValue() = getDriverInh().charAt(0);
}
A ::= NativeTypesSyn* BoxedTypesSyn* <DriverInh:String>;
// native types, synthesized
NativeTypesSyn ::= <DriverSyn:String> /<IntValue:int>/ /<ShortValue:short>/ /<LongValue:long>/ /<FloatValue:float>/ /<DoubleValue:double>/ /<CharValue:char>/ /<StringValue:String>/ ;
// boxed types, synthesized
BoxedTypesSyn ::= <DriverSyn:String> /<IntValue:Integer>/ /<ShortValue:Short>/ /<LongValue:Long>/ /<FloatValue:Float>/ /<DoubleValue:Double>/ /<CharValue:Character>/ ;
// --- inherited attributes not supported ---
//// native types, inherited
//NativeTypesInh ::= /<IntValue:int>/ /<ShortValue:short>/ /<LongValue:long>/ /<FloatValue:float>/ /<DoubleValue:double>/ /<CharValue:char>/ /<StringValue:String>/ ;
//// boxed types, inherited
//BoxedTypesInh ::= /<IntValue:Integer>/ /<ShortValue:Short>/ /<LongValue:Long>/ /<FloatValue:Float>/ /<DoubleValue:Double>/ /<CharValue:Character>/ ;
// --- 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 ;
// 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;
:}
A ::= B C D ;
// read definitions
B ::= /<ErrorNTA:String>/ <ErrorTypeOfFirstMapping:String> <ErrorTypeOfLastMapping:String> <DoubledValue:int> <ErrorTypeMismatch:String> ;
// write definitions
C ::= <ErrorNotNTA:String> /<ErrorTypeOfFirstMapping:String>/ /<ErrorTypeOfLastMapping1:String>/ /<ErrorTypeOfLastMapping2:List<String>>/ /<ErrorTypeMismatch:String>/ /<DoubledValue:int>/ ;
// dependency definitions
D ::= <SourceNonExistingTarget>
/<TargetNonExistingSource>/
<SourceNoWriteDef> /<TargetNoWriteDef>/
<SourceSameAsListNode> /<TargetSameAsListNode>/
<SourceDoubledValue> /<TargetDoubledValue>/
MyList:D* ;
Ideas for errors:
- Read-Update
- the token must be resolvable within the parent type
- the Token must not be a TokenNTA (i.e., check for `!Token.getNTA()`)
- type of first mapping must be `byte[]`
- type of last mapping must be type of the Token
- types of mappings must match (modulo inheritance)
- Write-Update
- the token must be resolvable within the parent type
- Token must be a TokenNTA (i.e., check for `Token.getNTA()`)
- type of first mapping must be type of Token
- type of last mapping must be `byte[]`
- types of mappings must match (modulo inheritance)
- no more than one write mapping for each TokenComponent
- for all type checks, there are three cases regarding the two types to check against:
1) both are nonterminal types, check with grammar
2) both are known classes, check with `Class.forName()` and subclass-checking-methods
3) otherwise issue warning, that types could not be matched
- dependency-definition
- There **must be** a write update definition for the target token
- Otherwise there are missing update and write methods used in the virtual setter
- Both, source and target must be resolvable within the parent type
- The name of a dependency definition must not be equal to a list-node on the source
- There must not be two dependency definitions with the same name
# Example
Idea: Use the motivating example from our paper as a test case, including one read, one write update definition
/* Version 2020-07-15 */
// --- update definitions ---
receive Link.CurrentPosition using ParseRobotState, RobotStateToIntPosition ;
send RobotArm.AppropriateSpeed using CreateSpeedMessage, SerializeRobotConfig ;
// --- dependency definitions ---
RobotArm.AppropriateSpeed canDependOn Link.CurrentPosition as dependency1 ;
// --- mapping definitions ---
ParseRobotState maps byte[] bytes to robot.RobotStateOuterClass.RobotState {:
TestCounter.INSTANCE.numberParseLinkState += 1;
return robot.RobotStateOuterClass.RobotState.parseFrom(bytes);
:}
SerializeRobotConfig maps config.Config.RobotConfig rc to byte[] {:
TestCounter.INSTANCE.numberSerializeRobotConfig += 1;
return rc.toByteArray();
:}
RobotStateToIntPosition maps robot.RobotStateOuterClass.RobotState rs to IntPosition {:
TestCounter.INSTANCE.numberLinkStateToIntPosition += 1;
robot.RobotStateOuterClass.RobotState.Position p = rs.getPosition();
return IntPosition.of((int) (Math.round(p.getX() * 10)), (int) (Math.round(p.getY() * 10)), (int) (Math.round(p.getZ() * 10)));
:}
CreateSpeedMessage maps double speed to config.Config.RobotConfig {:
TestCounter.INSTANCE.numberCreateSpeedMessage += 1;
return config.Config.RobotConfig.newBuilder()
.setSpeed(speed)
.build();
:}
aspect GrammarTypes {
public class TestCounter {
public static TestCounter INSTANCE = new TestCounter();
public int numberParseLinkState = 0;
public int numberSerializeRobotConfig = 0;
public int numberLinkStateToIntPosition = 0;
public int numberCreateSpeedMessage = 0;
public int numberInSafetyZone = 0;
public static void reset() {
TestCounter.INSTANCE = new TestCounter();
}
}
public class IntPosition {
private final int x, y, z;
private IntPosition(int x, int y, int z) {
this.x = x;
this.y = y;
this.z = z;
}
public static IntPosition of(int x, int y, int z) {
return new IntPosition(x, y, z);
}
public int getX() {
return x;
}
public int getY() {
return y;
}
public int getZ() {
return z;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
IntPosition that = (IntPosition) o;
return x == that.x &&
y == that.y &&
z == that.z;
}
@Override
public int hashCode() {
return java.util.Objects.hash(x, y, z);
}
@Override
public String toString() {
return "(" + x + ", " + y + ", " + z + ")";
}
}
inh Model RobotArm.model();
eq Model.getRobotArm().model() = this;
inh RobotArm Link.containingRobotArm();
eq RobotArm.getLink().containingRobotArm() = this;
eq RobotArm.getEndEffector().containingRobotArm() = this;
syn boolean RobotArm.isInSafetyZone() {
TestCounter.INSTANCE.numberInSafetyZone += 1;
for (Link link : getLinkList()) {
if (model().getZoneModel().isInSafetyZone(link.getCurrentPosition())) {
return true;
}
}
return model().getZoneModel().isInSafetyZone(getEndEffector().getCurrentPosition());
}
cache ZoneModel.isInSafetyZone(IntPosition pos);
syn boolean ZoneModel.isInSafetyZone(IntPosition pos) {
for (Zone sz : getSafetyZoneList()) {
for (Coordinate coordinate : sz.getCoordinateList()) {
if (coordinate.getPosition().equals(pos)) {
return true;
}
}
}
return false;
}
syn double RobotArm.speedLow() = 0.4d;
syn double RobotArm.speedHigh() = 1.0d;
syn double RobotArm.getAppropriateSpeed() {
return isInSafetyZone() ? speedLow() : speedHigh();
}
}
Model ::= RobotArm ZoneModel ;
ZoneModel ::= SafetyZone:Zone* ;
Zone ::= Coordinate* ;
RobotArm ::= Link* EndEffector /<AppropriateSpeed:double>/ ;
Link ::= <Name:String> <CurrentPosition:IntPosition> ;
EndEffector : Link;
Coordinate ::= <Position:IntPosition> ;
{
"joints": [
{"name": "Joint1", "topic": "robot/arm/joint1"},
{"name": "Joint2", "topic": "robot/arm/joint2"},
{"name": "EndEffector", "topic": "-", "isEndEffector": true}
],
"robotConfigTopic": "robot/config",
"dataConfigTopic": "-"
}
# Read one - Write two
Idea: Define Read-Update for one terminal, add dependencies to two other terminals, which each have Write-Update defined. Test, whether code gets generated correctly and that write is trigger for each of the two terminals upon read.
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment