How to implement the type validation test for my grammar [message #1796405] |
Fri, 12 October 2018 13:08 |
kozhaev Vladimir Messages: 108 Registered: July 2009 |
Senior Member |
|
|
Hi, all.
I have written the test for my grammar(please, see it below) and the method
Quote:@Test def void stringConstant() { "'foo'".assertStringType }
Fails with the following error
Quote:java.lang.NullPointerException
at org.blockchain.rell.tests.ExpressionsTypeProviderTest.assertType(ExpressionsTypeProviderTest.java:78)
at org.blockchain.rell.tests.ExpressionsTypeProviderTest.assertStringType(ExpressionsTypeProviderTest.java:58)
at org.blockchain.rell.tests.ExpressionsTypeProviderTest.stringConstant(ExpressionsTypeProviderTest.java:39)
I understand why it's happened - because of strings what we have tested are not valid with my grammar. But how to test part of the grammar. In the ANTLR I can check only one rule. But how to do something like it with XText?
Regards,
Vladimir
My grammar
grammar org.blockchain.rell.Rell with org.eclipse.xtext.common.Terminals
generate rell "http://www.blockchain.org/rell/Rell"
Model:
entities+=TheClass*
operations+=Operation*;
TheClass:
'class' name=ID ('extends' superType=[TheClass])? '{'
attributes+=Attribute*
'}';
Operation:
"operation" name=ID "(" parameters=RelAttrubutesList? ")" "{" statements+=Statement* "}";
Statement:
(Relational | Variable) ';';
Variable:
declaration=VariableDeclaration '=' expression=Expression;
Relational:
Update | Delete | Create;
Update:
'update' entity=ID '(' expressions=ExpressionsModel? ')' '{' variableList+=VariableInit
(',' variableList+=VariableInit*)? '}';
Delete:
'delete' entity=ID '(' expressions=ExpressionsModel? ')';
Create:
'create' entity=ID '(' expressions=ExpressionsModel? ')';
ExpressionsModel:
elements+=ConditionElements (',' elements+=ConditionElements*)?;
ConditionElements:
compareName=ID ('==' | '!=' | '>' | '<' | '>=' | '<=') expr=Expression;
VariableInit:
name=ID '=' expression=Expression;
Expression:
Or;
Or returns Expression:
And ({Or.left=current} "or" right=And)*;
And returns Expression:
Equality ({And.left=current} "and" right=Equality)*;
Equality returns Expression:
Comparison ({Equality.left=current} op=("==" | "!=")
right=Comparison)*;
Comparison returns Expression:
PlusOrMinus ({Comparison.left=current} op=(">=" | "<=" | ">" | "<")
right=PlusOrMinus)*;
PlusOrMinus returns Expression:
MulOrDiv (({Plus.left=current} '+' | {Minus.left=current} '-')
right=MulOrDiv)*;
Atomic returns Expression:
{IntConstant} value=INT |
{StringConstant} value=STRING |
{BoolConstant} value=('true' | 'false') |
{VariableRef} variable=[VariableDeclaration];
MulOrDiv returns Expression:
Primary ({MulOrDiv.left=current} op=('*' | '/')
right=Primary)*;
Primary returns Expression:
'(' Expression ')' |
{Not} "not" expression=Primary |
Atomic;
RelAttrubutesList:
value+=VariableDeclaration (',' value+=VariableDeclaration)*;
Attribute:
modificator=Prefix? variable=VariableDeclaration ';';
VariableDeclaration:
name=ID ':' type=TypeReference;
TypeReference:
primitive=PrimitiveType | entity=EntityType;
PrimitiveType:
Text | Integer | Json | ByteArray;
EntityType:
entity=[TheClass];
Json:
'json';
Integer:
'integer' | 'timestamp';
Text:
'text' | 'tuid' | 'name';
ByteArray:
'byte_array' | 'signer' | 'guid' | 'pubkey';
Prefix:
'key' | 'index';
My test
grammar org.blockchain.rell.Rell with org.eclipse.xtext.common.Terminals
generate rell "http://www.blockchain.org/rell/Rell"
Model:
entities+=TheClass*
operations+=Operation*;
TheClass:
'class' name=ID ('extends' superType=[TheClass])? '{'
attributes+=Attribute*
'}';
Operation:
"operation" name=ID "(" parameters=RelAttrubutesList? ")" "{" statements+=Statement* "}";
Statement:
(Relational | Variable) ';';
Variable:
declaration=VariableDeclaration '=' expression=Expression;
Relational:
Update | Delete | Create;
Update:
'update' entity=ID '(' expressions=ExpressionsModel? ')' '{' variableList+=VariableInit
(',' variableList+=VariableInit*)? '}';
Delete:
'delete' entity=ID '(' expressions=ExpressionsModel? ')';
Create:
'create' entity=ID '(' expressions=ExpressionsModel? ')';
ExpressionsModel:
elements+=ConditionElements (',' elements+=ConditionElements*)?;
ConditionElements:
compareName=ID ('==' | '!=' | '>' | '<' | '>=' | '<=') expr=Expression;
VariableInit:
name=ID '=' expression=Expression;
Expression:
Or;
Or returns Expression:
And ({Or.left=current} "or" right=And)*;
And returns Expression:
Equality ({And.left=current} "and" right=Equality)*;
Equality returns Expression:
Comparison ({Equality.left=current} op=("==" | "!=")
right=Comparison)*;
Comparison returns Expression:
PlusOrMinus ({Comparison.left=current} op=(">=" | "<=" | ">" | "<")
right=PlusOrMinus)*;
PlusOrMinus returns Expression:
MulOrDiv (({Plus.left=current} '+' | {Minus.left=current} '-')
right=MulOrDiv)*;
Atomic returns Expression:
{IntConstant} value=INT |
{StringConstant} value=STRING |
{BoolConstant} value=('true' | 'false') |
{VariableRef} variable=[VariableDeclaration];
MulOrDiv returns Expression:
Primary ({MulOrDiv.left=current} op=('*' | '/')
right=Primary)*;
Primary returns Expression:
'(' Expression ')' |
{Not} "not" expression=Primary |
Atomic;
RelAttrubutesList:
value+=VariableDeclaration (',' value+=VariableDeclaration)*;
Attribute:
modificator=Prefix? variable=VariableDeclaration ';';
VariableDeclaration:
name=ID ':' type=TypeReference;
TypeReference:
primitive=PrimitiveType | entity=EntityType;
PrimitiveType:
Text | Integer | Json | ByteArray;
EntityType:
entity=[TheClass];
Json:
'json';
Integer:
'integer' | 'timestamp';
Text:
'text' | 'tuid' | 'name';
ByteArray:
'byte_array' | 'signer' | 'guid' | 'pubkey';
Prefix:
'key' | 'index';
|
|
|
|
|
Re: How to implement the type validation test for my grammar [message #1796416 is a reply to message #1796412] |
Fri, 12 October 2018 14:36 |
|
here is a simple example for a unit test
import com.google.inject.Inject
import org.eclipse.xtext.testing.InjectWith
import org.eclipse.xtext.testing.extensions.InjectionExtension
import org.eclipse.xtext.testing.util.ParseHelper
import org.junit.jupiter.api.Assertions
import org.junit.jupiter.api.Test
import org.junit.jupiter.api.^extension.ExtendWith
import org.xtext.example.mydsl2.myDsl.Model
import org.eclipse.xtext.testing.validation.ValidationTestHelper
import org.xtext.example.mydsl2.myDsl.MyDslPackage
import org.xtext.example.mydsl2.validation.MyDslValidator
@ExtendWith(InjectionExtension)
@InjectWith(MyDslInjectorProvider)
class MyDslParsingTest {
@Inject
ParseHelper<Model> parseHelper
@Inject extension ValidationTestHelper
@Test
def void loadModel() {
val result = parseHelper.parse('''
Hello Xtext!
''')
Assertions.assertNotNull(result)
val errors = result.eResource.errors
Assertions.assertTrue(errors.isEmpty, '''Unexpected errors: «errors.join(", ")»''')
val result2 = parseHelper.parse('''
Hello xtext!
''')
Assertions.assertNotNull(result2)
val errors2 = result2.eResource.errors
Assertions.assertTrue(errors2.isEmpty, '''Unexpected errors: «errors2.join(", ")»''')
result2.assertWarning(MyDslPackage.Literals.GREETING, MyDslValidator.INVALID_NAME, "Name should start with a capital")
}
}
Twitter : @chrdietrich
Blog : https://www.dietrich-it.de
|
|
|
|
|
|
|
|
|
|
|
Re: How to implement the type validation test for my grammar [message #1796635 is a reply to message #1796610] |
Tue, 16 October 2018 18:05 |
|
test that shows your problem
import com.google.inject.Inject
import com.google.inject.Provider
import org.eclipse.emf.common.util.URI
import org.eclipse.emf.ecore.resource.ResourceSet
import org.eclipse.xtext.testing.InjectWith
import org.eclipse.xtext.testing.XtextRunner
import org.eclipse.xtext.util.StringInputStream
import org.junit.Assert
import org.junit.Test
import org.junit.runner.RunWith
@RunWith(XtextRunner)
@InjectWith(MyDslInjectorProvider)
class MyDslParsingTest {
@Inject
Provider<ResourceSet> rsp
@Test
def void loadModel() {
val input = '''1'''
var rs = rsp.get()
var r = rs.createResource(URI.createURI("test.mydsl2"));
r.load(new StringInputStream(input.toString()),null)
r.getErrors // test if empty
var errors = r.errors
Assert.assertTrue('''Unexpected errors: «errors.join(", ")»''', errors.isEmpty)
var model = r.getContents.get(0)
}
}
test that shows solution (1)
import com.google.inject.Inject
import com.google.inject.Provider
import org.eclipse.emf.common.util.URI
import org.eclipse.emf.ecore.resource.ResourceSet
import org.eclipse.xtext.testing.InjectWith
import org.eclipse.xtext.testing.XtextRunner
import org.eclipse.xtext.util.StringInputStream
import org.junit.Assert
import org.junit.Test
import org.junit.runner.RunWith
@RunWith(XtextRunner)
@InjectWith(MyDslInjectorProvider)
class MyDslParsingTest {
@Inject
Provider<ResourceSet> rsp
@Test
def void loadModel() {
val input = '''1'''
val completeInput = '''operation myOp() {
x : integer = «input»;
}'''
var rs = rsp.get()
var r = rs.createResource(URI.createURI("test.mydsl2"));
r.load(new StringInputStream(completeInput.toString()),null)
r.getErrors // test if empty
var errors = r.errors
Assert.assertTrue('''Unexpected errors: «errors.join(", ")»''', errors.isEmpty)
var model = r.getContents.get(0)
}
}
test that shows solution (2)
import com.google.inject.Inject
import com.google.inject.Provider
import org.eclipse.emf.common.util.URI
import org.eclipse.emf.ecore.resource.ResourceSet
import org.eclipse.xtext.testing.InjectWith
import org.eclipse.xtext.testing.XtextRunner
import org.eclipse.xtext.util.StringInputStream
import org.junit.Assert
import org.junit.Test
import org.junit.runner.RunWith
import org.eclipse.xtext.resource.XtextResource
import org.xtext.example.mydsl2.services.MyDslGrammarAccess
@RunWith(XtextRunner)
@InjectWith(MyDslInjectorProvider)
class MyDslParsingTest {
@Inject
Provider<ResourceSet> rsp
@Inject
MyDslGrammarAccess ga;
@Test
def void loadModel() {
val input = '''1'''
var rs = rsp.get()
var r = rs.createResource(URI.createURI("test.mydsl2"));
(r as XtextResource).entryPoint = ga.expressionRule
r.load(new StringInputStream(input.toString()),null)
r.getErrors // test if empty
var errors = r.errors
Assert.assertTrue('''Unexpected errors: «errors.join(", ")»''', errors.isEmpty)
var model = r.getContents.get(0)
}
}
Twitter : @chrdietrich
Blog : https://www.dietrich-it.de
|
|
|
Powered by
FUDForum. Page generated in 0.03822 seconds