1 /*******************************************************************************
2 * Copyright (c) 2013 Etienne Bergeron
4 * All rights reserved. This program and the accompanying materials are
5 * made available under the terms of the Eclipse Public License v1.0 which
6 * accompanies this distribution, and is available at
7 * http://www.eclipse.org/legal/epl-v10.html
10 * Etienne Bergeron - Initial API and implementation
11 *******************************************************************************/
13 package org
.eclipse
.linuxtools
.ctf
.parser
.tests
;
15 import static org
.junit
.Assert
.assertEquals
;
16 import static org
.junit
.Assert
.fail
;
18 import org
.antlr
.runtime
.ANTLRStringStream
;
19 import org
.antlr
.runtime
.CharStream
;
20 import org
.antlr
.runtime
.CommonTokenStream
;
21 import org
.antlr
.runtime
.RecognitionException
;
22 import org
.antlr
.runtime
.tree
.CommonTree
;
23 import org
.eclipse
.linuxtools
.ctf
.parser
.CTFLexer
;
24 import org
.eclipse
.linuxtools
.ctf
.parser
.CTFParser
;
25 import org
.junit
.Ignore
;
26 import org
.junit
.Test
;
29 * This test validates the CTF-Parser implementation.
31 * The goal of these tests is to validate syntactic rules and not the
32 * CTF semantic. Each test parses a string with a given rule of the
33 * compiled parser and validates the resulting tree by using match rules.
35 * @author Etienne Bergeron
37 public class CtfParserTest
{
39 // ------------------------------------------------------------------------
41 // ------------------------------------------------------------------------
43 private CTFParser parser
;
45 // ------------------------------------------------------------------------
46 // Matches - Helper class and functions to match a parsed tree.
47 // ------------------------------------------------------------------------
49 private class TreeMatcher
{
54 TreeMatcher(int type
, String text
, TreeMatcher child
[]) {
60 void matches(CommonTree tree
) {
64 if (tree
.getType() != fType
) {
65 fail("Type mismatch!" +
66 " expected:" + fType
+
67 " actual:" + tree
.getType());
71 if (tree
.getText().compareTo(fText
) != 0) {
72 fail("Text mismatch!" +
73 " expected:" + fText
+
74 " actual:" + tree
.getText());
79 int size
= fChild
.length
;
80 if (tree
.getChildren() == null) {
82 fail("Invalid children!"
83 + "Expect: " + size
+ "child");
86 if (tree
.getChildren().size() != size
) {
87 fail("Invalid number of childs!"
89 + " actual:" + tree
.getChildren().size());
92 for (int i
= 0; i
< size
; ++i
) {
93 fChild
[i
].matches((CommonTree
) tree
.getChild(i
));
100 void Matches(TreeMatcher matcher
, CommonTree tree
) {
102 fail("Parsing failed!");
104 matcher
.matches(tree
);
108 return new TreeMatcher(-1, null, null);
111 TreeMatcher
Node(int type
, TreeMatcher
... child
) {
112 return new TreeMatcher(type
, null, child
);
115 TreeMatcher
Node(int type
, String text
, TreeMatcher
... child
) {
116 return new TreeMatcher(type
, text
, child
);
119 TreeMatcher
List(TreeMatcher
... child
) {
120 return new TreeMatcher(0, null, child
);
123 // ------------------------------------------------------------------------
125 // ------------------------------------------------------------------------
127 private void setInput(String content
) {
128 CharStream cs
= new ANTLRStringStream(content
);
129 CTFLexer lexer
= new CTFLexer(cs
);
130 CommonTokenStream tokens
= new CommonTokenStream(lexer
);
131 parser
= new CTFParser(tokens
, false);
134 private CommonTree
primaryExpression(String content
) {
137 return (CommonTree
) parser
.primaryExpression().getTree();
138 } catch (RecognitionException e
) {
143 private CommonTree
unaryExpression(String content
) {
146 return (CommonTree
) parser
.unaryExpression().getTree();
147 } catch (RecognitionException e
) {
152 private CommonTree
declaration(String content
) {
155 return (CommonTree
) parser
.declaration().getTree();
156 } catch (RecognitionException e
) {
161 // ------------------------------------------------------------------------
163 // ------------------------------------------------------------------------
167 * Validate that parsing of an empty expression is invalid.
170 public void testPrimaryExpression() {
171 CommonTree tree_empty
= primaryExpression("");
172 assertEquals(null, tree_empty
);
176 * Validate parsing of literals through a primary expression
179 public void testIntegerLiteralPrimaryExpression() {
180 Matches(Node(CTFParser
.UNARY_EXPRESSION_DEC
,
181 Node(CTFParser
.DECIMAL_LITERAL
, "123")),
182 primaryExpression("123"));
184 Matches(Node(CTFParser
.UNARY_EXPRESSION_HEX
,
185 Node(CTFParser
.HEX_LITERAL
, "0x123")),
186 primaryExpression("0x123"));
188 Matches(Node(CTFParser
.UNARY_EXPRESSION_OCT
,
189 Node(CTFParser
.OCTAL_LITERAL
, "0123")),
190 primaryExpression("0123"));
192 Matches(Node(CTFParser
.UNARY_EXPRESSION_DEC
,
193 Node(CTFParser
.DECIMAL_LITERAL
, "123"),
194 Node(CTFParser
.SIGN
, "-")),
195 primaryExpression("-123"));
197 Matches(Node(CTFParser
.UNARY_EXPRESSION_DEC
,
198 Node(CTFParser
.DECIMAL_LITERAL
, "123"),
199 Node(CTFParser
.SIGN
, "-")),
200 primaryExpression(" - 123"));
202 Matches(Node(CTFParser
.UNARY_EXPRESSION_DEC
,
203 Node(CTFParser
.DECIMAL_LITERAL
, "123"),
204 Node(CTFParser
.SIGN
, "-"),
205 Node(CTFParser
.SIGN
, "-"),
206 Node(CTFParser
.SIGN
, "+")),
207 primaryExpression(" - - + 123"));
209 Matches(Node(CTFParser
.UNARY_EXPRESSION_HEX
,
210 Node(CTFParser
.HEX_LITERAL
, "0x123"),
211 Node(CTFParser
.SIGN
, "+"),
212 Node(CTFParser
.SIGN
, "-")),
213 primaryExpression("+ - 0x123"));
215 Matches(Node(CTFParser
.UNARY_EXPRESSION_OCT
,
216 Node(CTFParser
.OCTAL_LITERAL
, "0123"),
217 Node(CTFParser
.SIGN
, "+"),
218 Node(CTFParser
.SIGN
, "-")),
219 primaryExpression("+ - 0123"));
223 * Validate parsing of a character literals through a primary expression
226 public void testCharacterLiteralPrimaryExpression() {
227 Matches(Node(CTFParser
.CHARACTER_LITERAL
, "'a'"),
228 primaryExpression("'a'"));
230 Matches(Node(CTFParser
.CHARACTER_LITERAL
, "'\\n'"),
231 primaryExpression("'\\n'"));
235 * Validate parsing of a string literals through a primary expression
238 public void testStringLiteralPrimaryExpression() {
239 Matches(Node(CTFParser
.UNARY_EXPRESSION_STRING_QUOTES
,
240 Node(CTFParser
.STRING_LITERAL
, "\"aaa\"")),
241 primaryExpression("\"aaa\""));
243 Matches(Node(CTFParser
.UNARY_EXPRESSION_STRING_QUOTES
,
244 Node(CTFParser
.STRING_LITERAL
, "L\"aaa\"")),
245 primaryExpression("L\"aaa\""));
247 Matches(Node(CTFParser
.UNARY_EXPRESSION_STRING_QUOTES
,
248 Node(CTFParser
.STRING_LITERAL
, "\"aaa\\n\"")),
249 primaryExpression("\"aaa\\n\""));
253 * Validate parsing of keywords through a primary expression
256 public void testKeywordPrimaryExpression() {
257 Matches(Node(CTFParser
.UNARY_EXPRESSION_STRING
,
258 Node(CTFParser
.SIGNEDTOK
, "signed")),
259 primaryExpression("signed"));
260 Matches(Node(CTFParser
.UNARY_EXPRESSION_STRING
,
261 Node(CTFParser
.ALIGNTOK
, "align")),
262 primaryExpression("align"));
266 * Validate parsing of identifiers through a primary expression
269 public void testIdentifierPrimaryExpression() {
270 Matches(Node(CTFParser
.UNARY_EXPRESSION_STRING
,
271 Node(CTFParser
.IDENTIFIER
, "x")),
272 primaryExpression("x"));
273 Matches(Node(CTFParser
.UNARY_EXPRESSION_STRING
,
274 Node(CTFParser
.IDENTIFIER
, "_123")),
275 primaryExpression("_123"));
279 * Validate that parsing of an empty unary expression is invalid.
282 public void testUnaryExpression() {
283 CommonTree tree_empty
= unaryExpression("");
284 assertEquals(null, tree_empty
);
288 * Validate parsing primary expression through an unary expression
291 public void testSimpleUnaryExpression() {
292 Matches(Node(CTFParser
.UNARY_EXPRESSION_DEC
,
293 Node(CTFParser
.DECIMAL_LITERAL
, "123")),
294 unaryExpression("123"));
296 Matches(Node(CTFParser
.UNARY_EXPRESSION_STRING
,
297 Node(CTFParser
.IDENTIFIER
, "x")),
298 unaryExpression("x"));
302 * Validate parsing array through an unary expression
305 public void testArrayUnaryExpression() {
306 Matches(List(Node(CTFParser
.UNARY_EXPRESSION_STRING
,
307 Node(CTFParser
.IDENTIFIER
, "x")),
308 Node(CTFParser
.OPENBRAC
),
309 Node(CTFParser
.UNARY_EXPRESSION_DEC
,
310 Node(CTFParser
.DECIMAL_LITERAL
, "1"))),
311 unaryExpression("x[1]"));
313 Matches(List(Node(CTFParser
.UNARY_EXPRESSION_STRING
,
314 Node(CTFParser
.IDENTIFIER
, "x")),
315 Node(CTFParser
.OPENBRAC
),
316 Node(CTFParser
.UNARY_EXPRESSION_STRING
,
317 Node(CTFParser
.IDENTIFIER
, "n"))),
318 unaryExpression("x[n]"));
320 Matches(List(Node(CTFParser
.UNARY_EXPRESSION_STRING
,
321 Node(CTFParser
.IDENTIFIER
, "x")),
322 Node(CTFParser
.OPENBRAC
),
323 Node(CTFParser
.UNARY_EXPRESSION_STRING
,
324 Node(CTFParser
.IDENTIFIER
, "n")),
325 Node(CTFParser
.OPENBRAC
),
326 Node(CTFParser
.UNARY_EXPRESSION_DEC
,
327 Node(CTFParser
.DECIMAL_LITERAL
, "1"))),
328 unaryExpression("x[n][1]"));
330 Matches(List(Node(CTFParser
.UNARY_EXPRESSION_STRING
,
331 Node(CTFParser
.IDENTIFIER
, "x")),
332 Node(CTFParser
.OPENBRAC
),
333 Node(CTFParser
.UNARY_EXPRESSION_STRING
,
334 Node(CTFParser
.IDENTIFIER
, "n")),
335 Node(CTFParser
.OPENBRAC
),
336 Node(CTFParser
.UNARY_EXPRESSION_DEC
,
337 Node(CTFParser
.DECIMAL_LITERAL
, "1"),
338 Node(CTFParser
.SIGN
, "+"))),
339 unaryExpression("x[n][+1]"));
343 * Validate parsing array with keywords through an unary expression
346 public void testSpecialArrayUnaryExpression() {
347 // Added for CTF-v1.8
348 Matches(List(Node(CTFParser
.TRACE
),
349 Node(CTFParser
.OPENBRAC
),
350 Node(CTFParser
.UNARY_EXPRESSION_STRING
,
351 Node(CTFParser
.IDENTIFIER
, "n"))),
352 unaryExpression("trace[n]"));
354 Matches(List(Node(CTFParser
.CLOCK
),
355 Node(CTFParser
.OPENBRAC
),
356 Node(CTFParser
.UNARY_EXPRESSION_STRING
,
357 Node(CTFParser
.IDENTIFIER
, "n")),
358 Node(CTFParser
.OPENBRAC
),
359 Node(CTFParser
.UNARY_EXPRESSION_DEC
,
360 Node(CTFParser
.DECIMAL_LITERAL
, "1"))),
361 unaryExpression("clock[n][1]"));
365 * Validate parsing member expression through an unary expression
368 public void testMemberUnaryExpression() {
369 Matches(List(Node(CTFParser
.UNARY_EXPRESSION_STRING
,
370 Node(CTFParser
.IDENTIFIER
, "x")),
372 Node(CTFParser
.UNARY_EXPRESSION_STRING
,
373 Node(CTFParser
.IDENTIFIER
, "y")))),
374 unaryExpression("x.y"));
376 Matches(List(Node(CTFParser
.UNARY_EXPRESSION_STRING
,
377 Node(CTFParser
.IDENTIFIER
, "x")),
379 Node(CTFParser
.UNARY_EXPRESSION_STRING
,
380 Node(CTFParser
.IDENTIFIER
, "y"))),
382 Node(CTFParser
.UNARY_EXPRESSION_STRING
,
383 Node(CTFParser
.IDENTIFIER
, "z")))),
384 unaryExpression("x.y.z"));
388 * Validate parsing pointer expression through an unary expression
391 public void testPointerUnaryExpression() {
392 Matches(List(Node(CTFParser
.UNARY_EXPRESSION_STRING
,
393 Node(CTFParser
.IDENTIFIER
, "x")),
394 Node(CTFParser
.ARROW
,
395 Node(CTFParser
.UNARY_EXPRESSION_STRING
,
396 Node(CTFParser
.IDENTIFIER
, "y")))),
397 unaryExpression("x->y"));
399 Matches(List(Node(CTFParser
.UNARY_EXPRESSION_STRING
,
400 Node(CTFParser
.IDENTIFIER
, "x")),
401 Node(CTFParser
.ARROW
,
402 Node(CTFParser
.UNARY_EXPRESSION_STRING
,
403 Node(CTFParser
.IDENTIFIER
, "y"))),
404 Node(CTFParser
.ARROW
,
405 Node(CTFParser
.UNARY_EXPRESSION_STRING
,
406 Node(CTFParser
.IDENTIFIER
, "z")))),
407 unaryExpression("x->y->z"));
411 * Validate complex expressions through an unary expression
414 public void testMixedUnaryExpression() {
415 Matches(List(Node(CTFParser
.UNARY_EXPRESSION_STRING
,
416 Node(CTFParser
.IDENTIFIER
, "x")),
417 Node(CTFParser
.OPENBRAC
),
418 Node(CTFParser
.UNARY_EXPRESSION_DEC
,
419 Node(CTFParser
.DECIMAL_LITERAL
, "2")),
420 Node(CTFParser
.ARROW
,
421 Node(CTFParser
.UNARY_EXPRESSION_STRING
,
422 Node(CTFParser
.IDENTIFIER
, "y"))),
424 Node(CTFParser
.UNARY_EXPRESSION_STRING
,
425 Node(CTFParser
.IDENTIFIER
, "z"))),
426 Node(CTFParser
.OPENBRAC
),
427 Node(CTFParser
.UNARY_EXPRESSION_DEC
,
428 Node(CTFParser
.DECIMAL_LITERAL
, "1"))),
429 unaryExpression("x[2]->y.z[1]"));
433 * Validate that parsing of an empty declaration is invalid.
436 public void testDeclaration() {
437 CommonTree tree_empty
= declaration("");
438 assertEquals(null, tree_empty
);
442 * Validate parsing of integer declaration
445 public void testIntegerTypeAliasDeclaration() {
446 // TODO: replace the "all" match with a better tree matcher.
448 declaration("typealias integer { } := int;"));
450 declaration("typealias integer { signed=true; } := int;"));
454 * Validate parsing of floating declaration
457 public void testFloatingTypeAliasDeclaration() {
458 // TODO: replace the "all" match with a better tree matcher.
460 declaration("typealias floating_point { } := float;"));
462 declaration("typealias floating_point { align = 32; } := float;"));
466 * Validate parsing of typedef declaration
468 @Ignore("This need a fix to the grammar to support a dummy initial scope. ")
470 public void testTypedefDeclaration() {
471 // TODO: replace the "all" match with a better tree matcher.
473 declaration("typedef dummy int;"));
475 declaration("typedef integer { } int;"));
479 * Validate parsing of an enum declaration
482 public void testEnumDeclaration() {
483 Matches(Node(CTFParser
.DECLARATION
,
484 Node(CTFParser
.TYPE_SPECIFIER_LIST
,
486 Node(CTFParser
.ENUM_NAME
,
487 Node(CTFParser
.IDENTIFIER
, "name")),
488 Node(CTFParser
.ENUM_BODY
,
489 Node(CTFParser
.ENUM_ENUMERATOR
,
490 Node(CTFParser
.UNARY_EXPRESSION_STRING
,
491 Node(CTFParser
.IDENTIFIER
, "A"))))))),
492 declaration("enum name { A };"));
494 Matches(Node(CTFParser
.DECLARATION
,
495 Node(CTFParser
.TYPE_SPECIFIER_LIST
,
497 Node(CTFParser
.ENUM_NAME
, All()),
498 Node(CTFParser
.ENUM_CONTAINER_TYPE
,
499 Node(CTFParser
.TYPE_SPECIFIER_LIST
,
500 Node(CTFParser
.INTTOK
))),
501 Node(CTFParser
.ENUM_BODY
, All())))),
502 declaration("enum name : int { A };"));
504 Matches(Node(CTFParser
.DECLARATION
,
505 Node(CTFParser
.TYPE_SPECIFIER_LIST
,
507 Node(CTFParser
.ENUM_BODY
, All())))),
508 declaration("enum { A };"));
510 Matches(Node(CTFParser
.DECLARATION
,
511 Node(CTFParser
.TYPE_SPECIFIER_LIST
,
513 Node(CTFParser
.ENUM_CONTAINER_TYPE
,
514 Node(CTFParser
.TYPE_SPECIFIER_LIST
,
515 Node(CTFParser
.INTTOK
))),
516 Node(CTFParser
.ENUM_BODY
, All())))),
517 declaration("enum : int { A };"));
521 * Validate parsing of an enumerator
523 @Ignore("The grammar needs to be fixed.")
525 public void testDeclaratorOfEnumDeclaration() {
526 /* TODO: This test crash the parser. */
528 declaration("enum { };"));
530 Matches(Node(CTFParser
.DECLARATION
,
531 Node(CTFParser
.TYPE_SPECIFIER_LIST
,
533 Node(CTFParser
.ENUM_BODY
,
534 Node(CTFParser
.ENUM_ENUMERATOR
,
535 Node(CTFParser
.UNARY_EXPRESSION_STRING
,
536 Node(CTFParser
.IDENTIFIER
, "A"))),
537 Node(CTFParser
.ENUM_ENUMERATOR
,
538 Node(CTFParser
.UNARY_EXPRESSION_STRING
,
539 Node(CTFParser
.IDENTIFIER
, "B")),
540 Node(CTFParser
.ENUM_VALUE
,
541 Node(CTFParser
.UNARY_EXPRESSION_DEC
,
542 Node(CTFParser
.DECIMAL_LITERAL
, "2")))),
543 Node(CTFParser
.ENUM_ENUMERATOR
,
544 Node(CTFParser
.UNARY_EXPRESSION_STRING
,
545 Node(CTFParser
.IDENTIFIER
, "C")),
546 Node(CTFParser
.ENUM_VALUE_RANGE
,
547 Node(CTFParser
.UNARY_EXPRESSION_DEC
,
548 Node(CTFParser
.DECIMAL_LITERAL
, "3")),
549 Node(CTFParser
.UNARY_EXPRESSION_DEC
,
550 Node(CTFParser
.DECIMAL_LITERAL
, "5")))))))),
551 declaration("enum { A, B=2, C=3...5 };"));
553 Matches(Node(CTFParser
.DECLARATION
,
554 Node(CTFParser
.TYPE_SPECIFIER_LIST
,
556 Node(CTFParser
.ENUM_BODY
,
557 Node(CTFParser
.ENUM_ENUMERATOR
,
558 Node(CTFParser
.UNARY_EXPRESSION_STRING_QUOTES
,
559 Node(CTFParser
.STRING_LITERAL
, "\"A\""))),
560 Node(CTFParser
.ENUM_ENUMERATOR
,
561 Node(CTFParser
.UNARY_EXPRESSION_STRING_QUOTES
,
562 Node(CTFParser
.STRING_LITERAL
, "\"B\"")),
564 declaration("enum { \"A\", \"B\"=2 };"));
568 * Validate parsing of empty declaration
570 @Ignore("The grammar need to be fixed to support empty ctf-body.")
572 public void testEmptyDeclaration() {
573 /* TODO: An exception is throw when building an common tree without
574 * assignments in the ctf-body.
577 declaration("env { };"));
579 declaration("trace { };"));
581 declaration("stream { };"));
583 declaration("event { };"));
587 * Validate parsing of an environment declaration
590 public void testEnvDeclaration() {
591 Matches(Node(CTFParser
.ENV
,
592 Node(CTFParser
.CTF_EXPRESSION_VAL
,
593 Node(CTFParser
.CTF_LEFT
,
594 Node(CTFParser
.UNARY_EXPRESSION_STRING
,
595 Node(CTFParser
.IDENTIFIER
, "pid"))),
596 Node(CTFParser
.CTF_RIGHT
,
597 Node(CTFParser
.UNARY_EXPRESSION_STRING
,
598 Node(CTFParser
.IDENTIFIER
, "value"))))),
599 declaration("env { pid = value; };"));
601 Matches(Node(CTFParser
.ENV
,
602 Node(CTFParser
.CTF_EXPRESSION_VAL
, All(), All()),
603 Node(CTFParser
.CTF_EXPRESSION_VAL
, All(), All()),
604 Node(CTFParser
.CTF_EXPRESSION_VAL
, All(), All())),
605 declaration("env { pid = value; proc_name = \"name\"; x = y;};"));
609 * Validate parsing of a trace declaration
611 @Ignore("The grammar need to be fixed.")
613 public void testTraceDeclaration() {
614 Matches(Node(CTFParser
.TRACE
,
615 Node(CTFParser
.CTF_EXPRESSION_VAL
,
616 Node(CTFParser
.CTF_LEFT
,
617 Node(CTFParser
.UNARY_EXPRESSION_STRING
,
618 Node(CTFParser
.IDENTIFIER
, "major"))),
619 Node(CTFParser
.CTF_RIGHT
,
620 Node(CTFParser
.UNARY_EXPRESSION_DEC
,
621 Node(CTFParser
.DECIMAL_LITERAL
, "1"))))),
622 declaration("trace { major = 1; };"));
624 Matches(Node(CTFParser
.TRACE
,
625 Node(CTFParser
.CTF_EXPRESSION_TYPE
,
626 Node(CTFParser
.CTF_LEFT
,
627 Node(CTFParser
.UNARY_EXPRESSION_STRING
,
628 Node(CTFParser
.IDENTIFIER
, "packet")),
630 Node(CTFParser
.UNARY_EXPRESSION_STRING
,
631 Node(CTFParser
.IDENTIFIER
, "header")))),
632 Node(CTFParser
.CTF_RIGHT
,
633 Node(CTFParser
.TYPE_SPECIFIER_LIST
,
634 Node(CTFParser
.STRUCT
,
635 Node(CTFParser
.STRUCT_NAME
,
636 Node(CTFParser
.IDENTIFIER
, "dummy"))))))),
637 declaration("trace { packet.header := struct dummy; };"));
639 /* TODO: This test crash the parser. */
640 Matches(Node(CTFParser
.TRACE
,
642 declaration("trace { typedef x y; };"));
644 Matches(Node(CTFParser
.TRACE
,
645 Node(CTFParser
.CTF_EXPRESSION_VAL
, All(), All()),
646 Node(CTFParser
.CTF_EXPRESSION_VAL
, All(), All()),
647 Node(CTFParser
.CTF_EXPRESSION_TYPE
, All(), All())),
648 declaration("trace { major = 1; minor = 1;"
649 + "packet.header := struct dummy; };"));