1//
2//  CommonTreeTest.m
3//  ANTLR
4//
5//  Created by Ian Michell on 26/05/2010.
6//  Copyright 2010 Ian Michell. All rights reserved.
7//
8
9#import <ANTLR/BaseTree.h>
10#import "CommonTreeTest.h"
11#import <ANTLR/ANTLRStringStream.h>
12#import <ANTLR/CommonTree.h>
13#import <ANTLR/CommonToken.h>
14#import <ANTLR/ANTLRError.h>
15#import <ANTLR/RuntimeException.h>
16
17@implementation CommonTreeTest
18
19-(void) test01InitAndRelease
20{
21	CommonTree *tree = [CommonTree newTree];
22	STAssertNotNil(tree, @"Tree was nil");
23	// FIXME: It doesn't do anything else, perhaps initWithTree should set something somewhere, java says no though...
24    return;
25}
26
27-(void) test02InitWithTree
28{
29	CommonTree *tree = [CommonTree newTree];
30	STAssertNotNil(tree, @"Tree was nil");
31    if (tree != nil)
32        STAssertEquals(tree.type, (NSInteger)TokenTypeInvalid, @"Tree should have an invalid token type, because it has no token");
33    // [tree release];
34    return;
35}
36
37-(void) test03WithToken
38{
39	ANTLRStringStream *stream = [ANTLRStringStream newANTLRStringStream:@"this||is||a||double||piped||separated||csv"];
40	CommonToken *token = [CommonToken newToken:stream Type:555 Channel:TokenChannelDefault Start:4 Stop:5];
41	token.line = 1;
42	token.charPositionInLine = 4;
43	CommonTree *tree = [CommonTree newTreeWithToken:token];
44	STAssertNotNil(tree, @"Tree was nil");
45    if (tree != nil)
46        STAssertNotNil(tree.token, @"Tree with token was nil");
47    if (tree != nil && tree.token != nil) {
48        STAssertEquals((NSUInteger) tree.token.line, (NSUInteger)1, [NSString stringWithFormat:@"Tree should be at line 1, but was at %d", tree.token.line] );
49        STAssertEquals((NSUInteger) tree.token.charPositionInLine, (NSUInteger)4, [NSString stringWithFormat:@"Char position should be 1, but was at %d", tree.token.charPositionInLine]);
50        STAssertNotNil(((CommonToken *)tree.token).text, @"Tree with token with text was nil");
51    }
52    if (tree != nil && tree.token != nil && tree.token.text != nil)
53        STAssertTrue([tree.token.text isEqualToString:@"||"], @"Text was not ||");
54	//[tree release];
55    return;
56}
57
58-(void) test04InvalidTreeNode
59{
60	CommonTree *tree = [CommonTree newTreeWithToken:[CommonToken invalidToken]];
61	STAssertNotNil(tree, @"Tree was nil");
62	STAssertEquals(tree.token.type, (NSInteger)TokenTypeInvalid, @"Tree Token type was not TokenTypeInvalid");
63	//[tree release];
64    return;
65}
66
67-(void) test05InitWithCommonTreeNode
68{
69	ANTLRStringStream *stream = [ANTLRStringStream newANTLRStringStream:@"this||is||a||double||piped||separated||csv"];
70	CommonToken *token = [CommonToken newToken:stream Type:555 Channel:TokenChannelDefault Start:4 Stop:5];
71	CommonTree *tree = [CommonTree newTreeWithToken:token];
72	STAssertNotNil(tree, @"Tree was nil");
73	STAssertNotNil(tree.token, @"Tree token was nil");
74	CommonTree *newTree = [CommonTree newTreeWithTree:tree];
75	STAssertNotNil(newTree, @"New tree was nil");
76	STAssertNotNil(newTree.token, @"New tree token was nil");
77	STAssertEquals(newTree.token, tree.token, @"Tokens did not match");
78	STAssertEquals(newTree.startIndex, tree.startIndex, @"Token start index did not match %d:%d", newTree.startIndex, tree.startIndex);
79	STAssertEquals(newTree.stopIndex, tree.stopIndex, @"Token stop index did not match %d:%d", newTree.stopIndex, tree.stopIndex);
80	//[stream release];
81	//[tree release];
82	//[newTree release];
83	//[token release];
84    return;
85}
86
87-(void) test06CopyTree
88{
89	ANTLRStringStream *stream = [ANTLRStringStream newANTLRStringStream:@"this||is||a||double||piped||separated||csv"];
90	CommonToken *token = [CommonToken newToken:stream Type:555 Channel:TokenChannelDefault Start:4 Stop:5];
91	CommonTree *tree = [CommonTree newTreeWithToken:token];
92	STAssertNotNil(tree, @"Tree was nil");
93	CommonTree *newTree = (CommonTree *)[tree copyWithZone:nil];
94	STAssertTrue([newTree isKindOfClass:[CommonTree class]], @"Copied tree was not an CommonTree");
95	STAssertNotNil(newTree, @"New tree was nil");
96	// STAssertEquals(newTree.token, tree.token, @"Tokens did not match");
97	STAssertEquals(newTree.stopIndex, tree.stopIndex, @"Token stop index did not match");
98	STAssertEquals(newTree.startIndex, tree.startIndex, @"Token start index did not match");
99	//[stream release];
100	//[tree release];
101	//[newTree release];
102	// [token release];
103    return;
104}
105
106-(void) test07Description
107{
108    NSString *aString;
109	CommonTree *errorTree = [CommonTree invalidNode];
110	STAssertNotNil(errorTree, @"Error tree node is nil");
111    if (errorTree != nil) {
112        aString = [errorTree description];
113        STAssertNotNil( aString, @"errorTree description returned nil");
114        if (aString != nil)
115            STAssertTrue([aString isEqualToString:@"<errornode>"], @"Not a valid error node description %@", aString);
116    }
117	//[errorTree release];
118
119	CommonTree *tree = [CommonTree newTreeWithTokenType:TokenTypeUP];
120	STAssertNotNil(tree, @"Tree is nil");
121    if (tree != nil)
122        STAssertNil([tree description], @"Tree description was not nil, was: %@", [tree description]);
123	//[tree release];
124
125	tree = [CommonTree newTree];
126	STAssertNotNil(tree, @"Tree is nil");
127    if (tree != nil) {
128        aString = [tree description];
129        STAssertNotNil(aString, @"tree description returned nil");
130        if (aString != nil)
131            STAssertTrue([aString isEqualToString:@"nil"], @"Tree description was not empty", [tree description]);
132    }
133	//[tree release];
134
135	ANTLRStringStream *stream = [ANTLRStringStream newANTLRStringStream:@"this||is||a||double||piped||separated||csv"];
136	CommonToken *token = [CommonToken newToken:stream Type:555 Channel:TokenChannelDefault Start:4 Stop:5];
137	tree = [CommonTree newTreeWithToken:token];
138	STAssertNotNil(tree, @"Tree node is nil");
139    aString = [tree description];
140    STAssertNotNil(aString, @"tree description returned nil");
141    if (aString != nil)
142        STAssertTrue([aString isEqualToString:@"||"], @"description was not || was instead %@", [tree description]);
143	//[tree release];
144    return;
145}
146
147-(void) test08Text
148{
149	ANTLRStringStream *stream = [ANTLRStringStream newANTLRStringStream:@"this||is||a||double||piped||separated||csv"];
150	CommonToken *token = [CommonToken newToken:stream Type:555 Channel:TokenChannelDefault Start:4 Stop:5];
151	CommonTree *tree = [CommonTree newTreeWithToken:token];
152	STAssertNotNil(tree, @"Tree was nil");
153	STAssertTrue([tree.token.text isEqualToString:@"||"], @"Tree text was not valid, should have been || was %@", tree.token.text);
154	//[tree release];
155
156	// test nil (for line coverage)
157	tree = [CommonTree newTree];
158	STAssertNotNil(tree, @"Tree was nil");
159	STAssertNil(tree.token.text, @"Tree text was not nil: %@", tree.token.text);
160    return;
161}
162
163-(void) test09AddChild
164{
165	// Create a new tree
166	CommonTree *parent = [CommonTree newTreeWithTokenType:555];
167    parent.token.line = 1;
168	parent.token.charPositionInLine = 1;
169
170	// Child tree
171	ANTLRStringStream *stream = [ANTLRStringStream newANTLRStringStream:@"this||is||a||double||piped||separated||csv"];
172	CommonToken *token = [CommonToken newToken:stream Type:555 Channel:TokenChannelDefault Start:4 Stop:5];
173	token.line = 1;
174	token.charPositionInLine = 4;
175	CommonTree *tree = [CommonTree newTreeWithToken:token];
176
177	// Add a child to the parent tree
178	[parent addChild:tree];
179
180
181	STAssertNotNil(parent, @"parent was nil");
182    if (parent != nil)
183        STAssertNotNil(parent.token, @"parent was nil");
184	STAssertEquals((NSInteger)parent.token.line, (NSInteger)1, @"Tree should be at line 1 but is %d", parent.token.line);
185	STAssertEquals((NSInteger)parent.token.charPositionInLine, (NSInteger)1, @"Char position should be 1 but is %d", parent.token.charPositionInLine);
186
187	STAssertEquals((NSInteger)[parent getChildCount], (NSInteger)1, @"There should be 1 child but there were %d", [parent getChildCount]);
188	STAssertEquals((NSInteger)[[parent getChild:0] getChildIndex], (NSInteger)0, @"Child index should be 0 was : %d", [[parent getChild:0] getChildIndex]);
189	STAssertEquals([[parent getChild:0] getParent], parent, @"Parent not set for child");
190
191	//[parent release];
192    return;
193}
194
195-(void) test10AddChildren
196{
197	// Create a new tree
198	CommonTree *parent = [CommonTree newTree];
199
200	// Child tree
201	ANTLRStringStream *stream = [ANTLRStringStream newANTLRStringStream:@"this||is||a||double||piped||separated||csv"];
202	CommonToken *token = [CommonToken newToken:stream Type:555 Channel:TokenChannelDefault Start:4 Stop:5];
203	token.line = 1;
204	token.charPositionInLine = 4;
205	CommonTree *tree = [CommonTree newTreeWithToken:token];
206
207	// Add a child to the parent tree
208	[parent addChild: tree];
209
210	CommonTree *newParent = [CommonTree newTree];
211	[newParent addChildren:parent.children];
212
213	STAssertEquals([newParent getChild:0], [parent getChild:0], @"Children did not match");
214    return;
215}
216
217-(void) test11AddSelfAsChild
218{
219	CommonTree *parent = [CommonTree newTree];
220	@try
221	{
222		[parent addChild:parent];
223	}
224	@catch (NSException *e)
225	{
226		STAssertTrue([[e name] isEqualToString:@"IllegalArgumentException"], @"Got wrong kind of exception! %@", [e name]);
227		//[parent release];
228		return;
229	}
230	STFail(@"Did not get an exception when adding an empty child!");
231    return;
232}
233
234-(void) test12AddEmptyChildWithNoChildren
235{
236	CommonTree *emptyChild = [CommonTree newTree];
237	CommonTree *parent = [CommonTree newTree];
238	[parent addChild:emptyChild];
239	STAssertEquals((NSInteger)[parent getChildCount], (NSInteger)0, @"There were supposed to be no children!");
240	//[parent release];
241	//[emptyChild release];
242    return;
243}
244
245-(void) test13AddEmptyChildWithChildren
246{
247	// Create a new tree
248	CommonTree *parent = [CommonTree newTree];
249
250	// Child tree
251	ANTLRStringStream *stream = [ANTLRStringStream newANTLRStringStream:@"this||is||a||double||piped||separated||csv"];
252	CommonToken *token = [CommonToken newToken:stream Type:555 Channel:TokenChannelDefault Start:4 Stop:5];
253	token.line = 1;
254	token.charPositionInLine = 4;
255	CommonTree *tree = [CommonTree newTreeWithToken:token];
256
257	// Add a child to the parent tree
258	[parent addChild: tree];
259
260	CommonTree *newParent = [CommonTree newTree];
261	[newParent addChild:parent];
262
263	STAssertEquals((NSInteger)[newParent getChildCount], (NSInteger)1, @"Parent should only have 1 child: %d", [newParent getChildCount]);
264	STAssertEquals([newParent getChild:0], tree, @"Child was not the correct object.");
265	//[parent release];
266	//[newParent release];
267	//[tree release];
268    return;
269}
270
271-(void) test14ChildAtIndex
272{
273	// Create a new tree
274	CommonTree *parent = [CommonTree newTree];
275
276	// Child tree
277	ANTLRStringStream *stream = [ANTLRStringStream newANTLRStringStream:@"this||is||a||double||piped||separated||csv"];
278	CommonToken *token = [CommonToken newToken:stream Type:555 Channel:TokenChannelDefault Start:4 Stop:5];
279	CommonTree *tree = [CommonTree newTreeWithToken:token];
280
281	// Add a child to the parent tree
282	[parent addChild: tree];
283
284	STAssertEquals((NSInteger)[parent getChildCount], (NSInteger)1, @"There were either no children or more than 1: %d", [parent getChildCount]);
285
286	CommonTree *child = [parent getChild:0];
287	STAssertNotNil(child, @"Child at index 0 should not be nil");
288	STAssertEquals(child, tree, @"Child and Original tree were not the same");
289	//[parent release];
290    return;
291}
292
293-(void) test15SetChildAtIndex
294{
295	CommonTree *parent = [CommonTree newTree];
296
297	// Child tree
298	ANTLRStringStream *stream = [ANTLRStringStream newANTLRStringStream:@"this||is||a||double||piped||separated||csv"];
299	CommonToken *token = [CommonToken newToken:stream Type:555 Channel:TokenChannelDefault Start:4 Stop:5];
300	CommonTree *tree = [CommonTree newTreeWithToken:token];
301
302
303	tree = [CommonTree newTreeWithTokenType:TokenTypeUP];
304	tree.token.text = @"<UP>";
305	[parent addChild:tree];
306
307	STAssertTrue([parent getChild:0] == tree, @"Trees don't match");
308	[parent setChild:0 With:tree];
309
310	CommonTree *child = [parent getChild:0];
311	STAssertTrue([parent getChildCount] == 1, @"There were either no children or more than 1: %d", [parent getChildCount]);
312	STAssertNotNil(child, @"Child at index 0 should not be nil");
313	STAssertEquals(child, tree, @"Child and Original tree were not the same");
314	//[parent release];
315    return;
316}
317
318-(void) test16GetAncestor
319{
320	CommonTree *parent = [CommonTree newTreeWithTokenType:TokenTypeUP];
321	parent.token.text = @"<UP>";
322
323	CommonTree *down = [CommonTree newTreeWithTokenType:TokenTypeDOWN];
324	down.token.text = @"<DOWN>";
325
326	[parent addChild:down];
327
328	// Child tree
329	ANTLRStringStream *stream = [ANTLRStringStream newANTLRStringStream:@"this||is||a||double||piped||separated||csv"];
330	CommonToken *token = [CommonToken newToken:stream Type:555 Channel:TokenChannelDefault Start:4 Stop:5];
331	CommonTree *tree = [CommonTree newTreeWithToken:token];
332
333	[down addChild:tree];
334	STAssertTrue([tree hasAncestor:TokenTypeUP], @"Should have an ancestor of type TokenTypeUP");
335
336	CommonTree *ancestor = [tree getAncestor:TokenTypeUP];
337	STAssertNotNil(ancestor, @"Ancestor should not be nil");
338	STAssertEquals(ancestor, parent, @"Acenstors do not match");
339	//[parent release];
340    return;
341}
342
343-(void) test17FirstChildWithType
344{
345	// Create a new tree
346	CommonTree *parent = [CommonTree newTree];
347
348	CommonTree *up = [CommonTree newTreeWithTokenType:TokenTypeUP];
349	CommonTree *down = [CommonTree newTreeWithTokenType:TokenTypeDOWN];
350
351	[parent addChild:up];
352	[parent addChild:down];
353
354	CommonTree *found = (CommonTree *)[parent getFirstChildWithType:TokenTypeDOWN];
355	STAssertNotNil(found, @"Child with type DOWN should not be nil");
356    if (found != nil) {
357        STAssertNotNil(found.token, @"Child token with type DOWN should not be nil");
358        if (found.token != nil)
359            STAssertEquals((NSInteger)found.token.type, (NSInteger)TokenTypeDOWN, @"Token type was not correct, should be down!");
360    }
361	found = (CommonTree *)[parent getFirstChildWithType:TokenTypeUP];
362	STAssertNotNil(found, @"Child with type UP should not be nil");
363    if (found != nil) {
364        STAssertNotNil(found.token, @"Child token with type UP should not be nil");
365        if (found.token != nil)
366            STAssertEquals((NSInteger)found.token.type, (NSInteger)TokenTypeUP, @"Token type was not correct, should be up!");
367    }
368	//[parent release];
369    return;
370}
371
372-(void) test18SanityCheckParentAndChildIndexesForParentTree
373{
374	// Child tree
375	ANTLRStringStream *stream = [ANTLRStringStream newANTLRStringStream:@"this||is||a||double||piped||separated||csv"];
376	CommonToken *token = [CommonToken newToken:stream Type:555 Channel:TokenChannelDefault Start:4 Stop:5];
377	CommonTree *tree = [CommonTree newTreeWithToken:token];
378
379	CommonTree *parent = [CommonTree newTreeWithTokenType:555];
380	STAssertNotNil(tree, @"tree should not be nil");
381	@try
382	{
383		[tree sanityCheckParentAndChildIndexes];
384	}
385	@catch (NSException * e)
386	{
387		STFail(@"Exception was thrown and this is not what's right...");
388	}
389
390	BOOL passed = NO;
391	@try
392	{
393		[tree sanityCheckParentAndChildIndexes:parent At:0];
394	}
395	@catch (NSException * e)
396	{
397		STAssertTrue([[e name] isEqualToString:@"IllegalStateException"], @"Exception was not an IllegalStateException but was %@", [e name]);
398		passed = YES;
399	}
400	if (!passed)
401	{
402		STFail(@"An exception should have been thrown");
403	}
404
405	STAssertNotNil(parent, @"parent should not be nil");
406	[parent addChild:tree];
407	@try
408	{
409		[tree sanityCheckParentAndChildIndexes:parent At:0];
410	}
411	@catch (NSException * e)
412	{
413		STFail(@"No exception should have been thrown!");
414	}
415    return;
416}
417
418-(void) test19DeleteChild
419{
420	// Child tree
421	ANTLRStringStream *stream = [ANTLRStringStream newANTLRStringStream:@"this||is||a||double||piped||separated||csv"];
422	CommonToken *token = [CommonToken newToken:stream Type:555 Channel:TokenChannelDefault Start:4 Stop:5];
423	CommonTree *tree = [CommonTree newTreeWithToken:token];
424
425	CommonTree *parent = [CommonTree newTree];
426	[parent addChild:tree];
427
428	CommonTree *deletedChild = [parent deleteChild:0];
429	STAssertEquals(deletedChild, tree, @"Children do not match!");
430	STAssertEquals((NSInteger)[parent getChildCount], (NSInteger)0, @"Child count should be zero!");
431    return;
432}
433
434-(void) test20TreeDescriptions
435{
436	// Child tree
437	ANTLRStringStream *stream = [ANTLRStringStream newANTLRStringStream:@"this||is||a||double||piped||separated||csv"];
438	CommonToken *token = [CommonToken newToken:stream Type:555 Channel:TokenChannelDefault Start:4 Stop:5];
439	CommonTree *tree = [CommonTree newTreeWithToken:token];
440
441	// Description for tree
442	NSString *treeDesc = [tree treeDescription];
443    STAssertNotNil(treeDesc, @"Tree description should not be nil");
444    STAssertTrue([treeDesc isEqualToString:@"||"], @"Tree description was not || but rather %@", treeDesc);
445
446	CommonTree *parent = [CommonTree newTree];
447	STAssertTrue([[parent treeDescription] isEqualToString:@"nil"], @"Tree description was not nil was %@", [parent treeDescription]);
448	[parent addChild:tree];
449	treeDesc = [parent treeDescription];
450	STAssertTrue([treeDesc isEqualToString:@"||"], @"Tree description was not || but was: %@", treeDesc);
451
452	// Test non empty parent
453	CommonTree *down = [CommonTree newTreeWithTokenType:TokenTypeDOWN];
454	down.token.text = @"<DOWN>";
455
456	[tree addChild:down];
457	treeDesc = [parent treeDescription];
458	STAssertTrue([treeDesc isEqualToString:@"(|| <DOWN>)"], @"Tree description was wrong expected (|| <DOWN>) but got: %@", treeDesc);
459    return;
460}
461
462-(void) test21ReplaceChildrenAtIndexWithNoChildren
463{
464	CommonTree *parent = [CommonTree newTree];
465	CommonTree *parent2 = [CommonTree newTree];
466	CommonTree *child = [CommonTree newTreeWithTokenType:TokenTypeDOWN];
467	child.token.text = @"<DOWN>";
468	[parent2 addChild:child];
469	@try
470	{
471		[parent replaceChildrenFrom:1 To:2 With:parent2];
472	}
473	@catch (NSException *ex)
474	{
475		STAssertTrue([[ex name] isEqualToString:@"IllegalArgumentException"], @"Expected an illegal argument exception... Got instead: %@", [ex name]);
476		return;
477	}
478	STFail(@"Exception was not thrown when I tried to replace a child on a parent with no children");
479    return;
480}
481
482-(void) test22ReplaceChildrenAtIndex
483{
484	CommonTree *parent1 = [CommonTree newTree];
485	CommonTree *child1 = [CommonTree newTreeWithTokenType:TokenTypeUP];
486	[parent1 addChild:child1];
487	CommonTree *parent2 = [CommonTree newTree];
488	CommonTree *child2 = [CommonTree newTreeWithTokenType:TokenTypeDOWN];
489	child2.token.text = @"<DOWN>";
490	[parent2 addChild:child2];
491
492	[parent2 replaceChildrenFrom:0 To:0 With:parent1];
493
494	STAssertEquals([parent2 getChild:0], child1, @"Child for parent 2 should have been from parent 1");
495    return;
496}
497
498-(void) test23ReplaceChildrenAtIndexWithChild
499{
500	CommonTree *replacement = [CommonTree newTreeWithTokenType:TokenTypeUP];
501	replacement.token.text = @"<UP>";
502	CommonTree *parent = [CommonTree newTree];
503	CommonTree *child = [CommonTree newTreeWithTokenType:TokenTypeDOWN];
504	child.token.text = @"<DOWN>";
505	[parent addChild:child];
506
507	[parent replaceChildrenFrom:0 To:0 With:replacement];
508
509	STAssertTrue([parent getChild:0] == replacement, @"Children do not match");
510    return;
511}
512
513-(void) test24ReplacechildrenAtIndexWithLessChildren
514{
515	CommonTree *parent1 = [CommonTree newTree];
516	CommonTree *child1 = [CommonTree newTreeWithTokenType:TokenTypeUP];
517	[parent1 addChild:child1];
518
519	CommonTree *parent2 = [CommonTree newTree];
520
521	CommonTree *child2 = [CommonTree newTreeWithTokenType:TokenTypeEOF];
522	[parent2 addChild:child2];
523
524	CommonTree *child3 = [CommonTree newTreeWithTokenType:TokenTypeDOWN];
525	child2.token.text = @"<DOWN>";
526	[parent2 addChild:child3];
527
528	[parent2 replaceChildrenFrom:0 To:1 With:parent1];
529	STAssertEquals((NSInteger)[parent2 getChildCount], (NSInteger)1, @"Should have one child but has %d", [parent2 getChildCount]);
530	STAssertEquals([parent2 getChild:0], child1, @"Child for parent 2 should have been from parent 1");
531    return;
532}
533
534-(void) test25ReplacechildrenAtIndexWithMoreChildren
535{
536	CommonTree *parent1 = [CommonTree newTree];
537	CommonTree *child1 = [CommonTree newTreeWithTokenType:TokenTypeUP];
538	[parent1 addChild:child1];
539	CommonTree *child2 = [CommonTree newTreeWithTokenType:TokenTypeEOF];
540	[parent1 addChild:child2];
541
542	CommonTree *parent2 = [CommonTree newTree];
543
544	CommonTree *child3 = [CommonTree newTreeWithTokenType:TokenTypeDOWN];
545	child2.token.text = @"<DOWN>";
546	[parent2 addChild:child3];
547
548	[parent2 replaceChildrenFrom:0 To:0 With:parent1];
549	STAssertEquals((NSInteger)[parent2 getChildCount], (NSInteger)2, @"Should have one child but has %d", [parent2 getChildCount]);
550	STAssertEquals([parent2 getChild:0], child1, @"Child for parent 2 should have been from parent 1");
551	STAssertEquals([parent2 getChild:1], child2, @"An extra child (child2) should be in the children collection");
552    return;
553}
554
555@end
556