pd_alg_main_test.cpp
Go to the documentation of this file.
1 /** @file pd_alg_cc_test.cpp Unit Tests */
2 
3 
4 /* Pushdown plugin for FAU Discrete Event Systems Library (libfaudes)
5 
6  Copyright (C) 2013 Stefan Jacobi, Sven Schneider, Anne-Kathrin Hess
7 
8 */
9 #include "pd_alg_main_test.h"
10 
11 namespace faudes {
12 
13 /* *****************
14  * TestTransientStates
15  * *****************/
17  std::string name = "Transient States";
18  TestStart(name);
19 
21 
22  StateSet states = Transient(g1);
23 
24  try{
25  //expected states are s2 and s3
26  if(!states.Exists(g1.StateIndex("s2")) || !states.Exists(g1.StateIndex("s3"))){
27  std::stringstream errstr;
28  errstr << "States " << g1.StateIndex("s2") << " and " << g1.StateIndex("s3") << " were expected but were not fount in the state set" << std::endl;
29  throw Exception(name, errstr.str(), 1003);
30  }
31  }
32  catch (Exception e){
33  }
34 
35  TestEnd(name);
36 }
37 
38 /* *****************
39  * TestTransientStatesEmpty
40  * *****************/
42  std::string name = "Transient States Empty";
43  TestStart(name);
44 
46 
47  StateSet states = Transient(g1);
48 
49  try{
50  //no states are expected
51  if(!states.Empty()){
52  std::stringstream errstr;
53  errstr << "State set was expected to be empty, but had size " << states.Size() << std::endl;
54  throw Exception(name, errstr.str(), 1003);
55  }
56  }
57  catch (Exception e){
58  }
59 
60  TestEnd(name);
61 }
62 
63 /* *****************
64  * TestRnceRemoveEars
65  * *****************/
67  std::string name = "Rnce Remove Ears";
68  TestStart(name);
69 
70  System s = TestSystem2();
72 
73  PushdownGenerator g2 = Rnce(g1,s);
74 
75  try{
76  //states s31 and s41 must be removed from the generator
77  if(g2.ExistsState("s31") || g2.ExistsState("s41")){
78  std::stringstream errstr;
79  errstr << "States s31 and s41 were expected to be deleted, but at least one of them was found in the state set" << std::endl;
80  throw Exception(name, errstr.str(), 1003);
81  }
82  //only 6 states must be left in the generator
83  if(g2.States().Size() != 6){
84  std::stringstream errstr;
85  errstr << "6 states were expected in the generator, but " << g2.States().Size() << " were found" << std::endl;
86  throw Exception(name, errstr.str(), 1003);
87  }
88  }
89  catch (Exception e){
90  }
91 
92  TestEnd(name);
93 }
94 
95 /* *****************
96  * TestIntersectEventsAll
97  * *****************/
99 
100  std::string name = "Intersect Events All";
101  TestStart(name);
102 
103  System s;
105 
106  //build two event sets to test every configuration of (un)controllable
107  //and (un)observable at least once
108  s.InsEvent("a"); g1.InsEvent("a");
109  s.InsControllableEvent("b"); s.ClrObservable("b"); g1.InsControllableEvent("b"); g1.ClrObservable("b");
112  s.InsEvent("e"); g1.InsUnobservableEvent("e");
113  s.InsEvent("f"); g1.InsControllableEvent("f"); g1.ClrObservable("f");
114  s.InsEvent("g"); g1.InsControllableEvent("g");
118 
120  IntersectEvents(s, g1, g2);
121 
122  try{
123  //resulting size of events has to be 4 (containing a, b, c and d)
124  if(g2.Alphabet().Size() != 4){
125  std::stringstream errstr;
126  errstr << "size of event set is " << g2.Alphabet().Size() << " (";
127  EventSet::Iterator evit;
128  for(evit = g2.AlphabetBegin(); evit != g2.AlphabetEnd(); evit++){
129  if(evit == g2.AlphabetBegin()){
130  errstr << g2.EventName(*evit);
131  }
132  else{
133  errstr << ", " << g2.EventName(*evit);
134  }
135  }
136  errstr << "), but 4 (a, b, c, d) was expected" << std::endl;
137  throw Exception(name, errstr.str(), 1003);
138  }
139  //a must be observable and must not be controllable
140  if(!(!g2.Controllable("a") && g2.Observable("a"))){
141  std::stringstream errstr;
142  errstr << "event a must not be controllable and must be observable, but controllable: " << g2.Controllable("a") << " and observable: " << g2.Observable("a")<< std::endl;
143  throw Exception(name, errstr.str(), 1003);
144  }
145  //b must not be observable and must be controllable
146  if(!(g2.Controllable("b") && !g2.Observable("b"))){
147  std::stringstream errstr;
148  errstr << "event b must be controllable and must not be observable, but controllable: " << g2.Controllable("b") << " and observable: " << g2.Observable("b")<< std::endl;
149  throw Exception(name, errstr.str(), 1003);
150  }
151  //c must be observable and must be controllable
152  if(!(g2.Controllable("c") && g2.Observable("c"))){
153  std::stringstream errstr;
154  errstr << "event c must be controllable and must be observable, but controllable: " << g2.Controllable("c") << " and observable: " << g2.Observable("c")<< std::endl;
155  throw Exception(name, errstr.str(), 1003);
156  }
157  //d must not be observable and must not be controllable
158  if(!(!g2.Controllable("d") && !g2.Observable("d"))){
159  std::stringstream errstr;
160  errstr << "event d must not be controllable and must not be observable, but controllable: " << g2.Controllable("d") << " and observable: " << g2.Observable("d")<< std::endl;
161  throw Exception(name, errstr.str(), 1003);
162  }
163  }
164  catch(Exception e){
165  }
166 
167  TestEnd(name);
168 }
169 
170 /* *****************
171  * TestTimesStates
172  * *****************/
174 
175  std::string name = "Times States";
176  TestStart(name);
177 
178  System s = TestSystem1();
180 
181  //create expected merge states
182  std::set< std::vector<Idx> > expectedMergeStateSet;
183  std::vector<Idx> expectedMergeStates;
184  StateSet::Iterator sit, g1it, g2it;
185  for(sit = s.StatesBegin(); sit != s.StatesEnd(); sit++){
186  for(g1it = g1.StatesBegin(); g1it != g1.StatesEnd(); g1it++){
187  expectedMergeStates.clear();
188  expectedMergeStates.push_back(*sit);
189  expectedMergeStates.push_back(*g1it);
190  expectedMergeStateSet.insert(expectedMergeStates);
191  }
192  }
193 
194  PushdownGenerator g2 = Times(s,g1);
195 
196  try{
197  //the number of states in g2 must be g2States = sStates*g1States
198  if(g2.States().Size() != s.States().Size() * g1.States().Size()){
199  std::stringstream errstr;
200  errstr << "number of states incorrect, was " << g2.States().Size() << ", but " << s.States().Size() * g1.States().Size() << " was expected" << std::endl;
201  throw Exception(name, errstr.str(), 1003);
202  }
203 
204  //all elements of the cartesian product of state indices g1States x sStates
205  //must appear uniquely in the merge states attribute
206  std::set<std::vector<Idx> >::const_iterator emsit;
207  for(g2it = g2.StatesBegin(); g2it != g2.StatesEnd(); g2it++){
208 
209  //check if the merge attribute is of type MergeStates
210  const MergeStates* ms = dynamic_cast<const MergeStates*> (g2.StateAttribute(*g2it).Merge());
211  if(ms == NULL){
212  std::stringstream errstr;
213  errstr << "MergeStateAnnotation in state " << *g2it << " not set." << std::endl;
214  throw Exception(name, errstr.str(), 1003);
215  }
216 
217  emsit = expectedMergeStateSet.find(ms->States());
218  //check if the contained state indices match the expected indices
219  if(emsit == expectedMergeStateSet.end()){
220  std::stringstream errstr;
221  errstr << "mergeStates attribute of state " << *g2it << " was (";
222  std::vector<Idx>::const_iterator vit;
223  for(vit = ms->States().begin(); vit != ms->States().end(); vit++){
224  if(vit == ms->States().begin()){
225  errstr << *vit;
226  }
227  else{
228  errstr << ", " << *vit;
229  }
230  }
231  errstr << "), but was not expected. it may have already occured or not been expected at all" << std::endl;
232  throw Exception(name, errstr.str(), 1003);
233  }
234  //if indices match, delete the expected element because it is only expected once
235  expectedMergeStateSet.erase(ms->States());
236  }
237  }
238  catch(Exception e){
239  }
240 
241  TestEnd(name);
242 }
243 
244 /* *****************
245  * TestTimesStackSymbols
246  * *****************/
248  std::string name = "Times Stack Symbols";
249  TestStart(name);
250 
251  System s = TestSystem1();
253 
254  PushdownGenerator g2 = Times(s,g1);
255 
256  try{
257  StackSymbolSet::Iterator g1ssit, g2ssit;
258  //ever stack symbol in g1 must be in g2
259  for(g1ssit = g1.StackSymbolsBegin(); g1ssit != g1.StackSymbolsEnd(); g1ssit++){
260  g2ssit = g2.StackSymbols().Find(g1.StackSymbolName(*g1ssit));
261  if(g2ssit == g2.StackSymbols().End()){
262  std::stringstream errstr;
263  errstr << "stack symbol " << g1.StackSymbolName(*g1ssit) << " was expected but not found" << std::endl;
264  throw Exception(name, errstr.str(), 1003);
265  }
266  }
267 
268  //the number of stack symbols in g2 must be the number of stack symbols in g1
269  if(g2.StackSymbols().Size() != g1.StackSymbols().Size()){
270  std::stringstream errstr;
271  errstr << "number of stack symbols incorrect, was " << g2.StackSymbols().Size() << ", but " << g1.StackSymbols().Size() << " was expected" << std::endl;
272  throw Exception(name, errstr.str(), 1003);
273  }
274 
275  //the stack bottoms must match
276  if(g2.StackSymbolObj(g2.StackBottom()) != g1.StackSymbolObj(g1.StackBottom())){
277  std::stringstream errstr;
278  errstr << "stack bottom symbol incorrect, was " << g2.StackSymbolName(g2.StackBottom()) << ", but " << g1.StackSymbolName(g1.StackBottom()) << " was expected" << std::endl;
279  throw Exception(name, errstr.str(), 1003);
280  }
281  }
282  catch(Exception e){
283  }
284 
285  TestEnd(name);
286 }
287 
288 /* *****************
289  * TestTimesTransitions
290  * *****************/
292  std::string name = "Times Transitions";
293  TestStart(name);
294 
295  System s = TestSystem1();
297 
298  TransSet::Iterator g1Transit;
299  //determine number of expected lambda-read transitions in resulting generator
300  uint expectedLambdaReads = 0;
301  for(g1Transit = g1.TransRelBegin(); g1Transit != g1.TransRelEnd(); g1Transit++){
302  if(g1.EventName(g1Transit->Ev).compare(FAUDES_PD_LAMBDA) == 0){
303  expectedLambdaReads += s.States().Size() * g1.PopPush(*g1Transit).size();
304  }
305  }
306 
307  TransSet::Iterator sTransit;
308  //determine number of expected transtitions (without lambda read)
309  uint expectedTransitions = 0;
310  for(g1Transit = g1.TransRelBegin(); g1Transit != g1.TransRelEnd(); g1Transit++){
311  for(sTransit = s.TransRelBegin(); sTransit != s.TransRelEnd(); sTransit++){
312  if(g1.EventName(g1Transit->Ev).compare(s.EventName(sTransit->Ev)) == 0){
313  expectedTransitions += g1.PopPush(*g1Transit).size();
314  }
315  }
316  }
317 
318  PushdownGenerator g2 = Times(s,g1);
319 
320  try{
321  TransSet::Iterator g2Transit;
322  //for every lambda-read transition in g1 there must be a lambda read transition
323  //for every state in s
324  uint lambdaReads = 0;
325  for(g2Transit = g2.TransRelBegin(); g2Transit != g2.TransRelEnd(); g2Transit++){
326  if(g2.EventName(g2Transit->Ev).compare(FAUDES_PD_LAMBDA) == 0){
327  lambdaReads += g2.PopPush(*g2Transit).size();
328  }
329  }
330  if(lambdaReads != expectedLambdaReads){
331  std::stringstream errstr;
332  errstr << "number of lambda read transition was " << lambdaReads << ", but " << expectedLambdaReads << " was expected" << std::endl;
333  throw Exception(name, errstr.str(), 1003);
334  }
335 
336  //the total number of transitions should be
337  //expectedLambdaReads + expectedTransitions
338  if(lambdaReads + expectedTransitions != g2.TransRel().Size()){
339  std::stringstream errstr;
340  errstr << "total number of transitions was " << g2.TransRel().Size() << ", but " << expectedLambdaReads + expectedTransitions << " was expected" << std::endl;
341  throw Exception(name, errstr.str(), 1003);
342  }
343  }
344  catch(Exception e){
345  }
346 
347  TestEnd(name);
348 }
349 
350 /* *****************
351  * TestSplitStackSymbols
352  * *****************/
354  std::string name = "Split Stack Symbols";
355  TestStart(name);
356 
358 
359  PushdownGenerator g2 = Split(g1);
360 
361  try{
362  //the stack bottom symbol must not be changed
363  if(g2.StackSymbolObj(g2.StackBottom()) != g1.StackSymbolObj(g1.StackBottom())){
364  std::stringstream errstr;
365  errstr << "stack bottom symbol was " << g2.StackSymbolName(g2.StackBottom()) << ", but " << g1.StackSymbolName(g1.StackBottom()) << " was expected" << std::endl;
366  throw Exception(name, errstr.str(), 1003);
367  }
368 
369  StackSymbolSet::Iterator ssit;
370  //all stack symbols of the old generator must found in the new generator
371  for(ssit = g1.StackSymbolsBegin(); ssit != g1.StackSymbolsEnd(); ssit++){
372  if(g2.StackSymbols().Exists(g1.StackSymbolName(*ssit)) == 0){
373  std::stringstream errstr;
374  errstr << "stack symbol " << g1.StackSymbolName(*ssit) << " was expected in the stack symbol set but not found" << std::endl;
375  throw Exception(name, errstr.str(), 1003);
376  }
377  }
378  }
379  catch(Exception e){
380  }
381 
382  TestEnd(name);
383 }
384 
385 /* *****************
386  * TestSplitStates
387  * *****************/
389  std::string name = "Split States";
390  TestStart(name);
391 
393 
394  //set of split state attributes that are expected
395  std::set<std::pair<Idx,Idx> > splitStateSet;
396  StateSet::Iterator stateit;
397  StackSymbolSet::Iterator ssit;
398  for(stateit = g1.StatesBegin(); stateit != g1.StatesEnd(); stateit++){
399 
400  //insert expected head
401  splitStateSet.insert(std::make_pair(*stateit, 0));
402  for(ssit = g1.StackSymbolsBegin(); ssit != g1.StackSymbolsEnd(); ssit++){
403 
404  if(!g1.IsStackSymbolLambda(*ssit)){
405  splitStateSet.insert(std::make_pair(*stateit, *ssit));
406  }
407  }
408  }
409 
410  PushdownGenerator g2 = Split(g1);
411 
412  try{
413 
414  for(stateit = g2.StatesBegin(); stateit != g2.StatesEnd(); stateit++){
415 
416  const MergeStateSplit* mss = dynamic_cast<const MergeStateSplit*>(g2.StateAttribute(*stateit).Merge());
417 
418  //test if MergeStateSplit was set
419  if(mss == NULL){
420  std::stringstream errstr;
421  errstr << "MergeStateSplit attribute not set for state " << *stateit << std::endl;
422  throw Exception(name, errstr.str(), 1003);
423  }
424 
425  //test if state was expected
426  if(splitStateSet.erase(std::make_pair(mss->State(), mss->Symbol())) == 0){
427  std::stringstream errstr;
428  if(!mss->IsHead()){
429  errstr << "Ear state with merge attribute (state: " << mss->State() << ", stack symbol: " << g2.StackSymbolName(mss->Symbol()) << ") found, but was not expected." << std::endl;
430  }
431 
432  else{
433  errstr << "Head state with merge attribute (state: " << mss->State() << ") found, but was not expected." << std::endl;
434  }
435  throw Exception(name, errstr.str(), 1003);
436  }
437  }
438 
439  //test if any expected states are left
440  if(splitStateSet.size() != 0){
441  std::stringstream errstr;
442  errstr << splitStateSet.size() << " states are missing from the generator: \n";
443 
444  std::set<std::pair<Idx,Idx> >::iterator it;
445  for(it = splitStateSet.begin(); it != splitStateSet.end(); it++){
446  if(it->second != 0){
447  errstr << "ear state with merge attribute (state: " << it->first << ", stack symbol: " << g2.StackSymbolName(it->second) << ")\n";
448  }
449  else{
450  errstr << "head state with merge attribute (state: " << it->first << ")\n";
451  }
452  }
453  errstr << std::endl;
454  throw Exception(name, errstr.str(), 1003);
455  }
456  }
457  catch(Exception e){
458  }
459 
460  TestEnd(name);
461 }
462 
463 /* *****************
464  * TestSplitTransitionsHeadToEar
465  * *****************/
467  std::string name = "Split Transitions Head To Ear";
468  TestStart(name);
469 
471 
472  PushdownGenerator g2 = Split(g1);
473 
474  try{
475  StateSet::Iterator stateit;
476  TransSet::Iterator transit;
477  PopPushSet::const_iterator ppit;
478  //look at all states
479  for(stateit = g2.StatesBegin(); stateit != g2.StatesEnd(); stateit++){
480 
481  const MergeStateSplit* mss1 = dynamic_cast<const MergeStateSplit*>(g2.StateAttribute(*stateit).Merge());
482 
483  //if the current state is a head
484  if(mss1->IsHead()){
485 
486  //look at all transitions starting here
487  for(transit = g2.TransRelBegin(*stateit); transit != g2.TransRelEnd(*stateit); transit++){
488  for(ppit = g2.PopPushBegin(*transit); ppit != g2.PopPushEnd(*transit); ppit++){
489 
490  const MergeStateSplit* mss2 = dynamic_cast<const MergeStateSplit*>(g2.StateAttribute(transit->X2).Merge());
491 
492  //the end state of the transition must be an ear (i. e. not a head)
493  if(mss2->IsHead()){
494  std::stringstream errstr;
495  errstr << "Transition from head to head found (from " << *stateit << " to " << transit->X2 << ") found, but from head to ear was expected." << std::endl;
496  throw Exception(name, errstr.str(), 1003);
497  }
498 
499  //pop and push size must be one
500  if(ppit->first.size() != 1 || ppit->second.size() != 1){
501  std::stringstream errstr;
502  errstr << "Pop size was " << ppit->first.size() << " and push size was " << ppit->second.size() << " at transition from head state " << transit->X1 << " to ear state " << transit->X2 << ", but size 1 was expected for both." << std::endl;
503  throw Exception(name, errstr.str(), 1003);
504  }
505 
506  //the ear's associated stack symbol must be popped and pushed
507  if(mss2->Symbol() != ppit->first.front() || mss2->Symbol() != ppit->second.front()){
508  std::stringstream errstr;
509  errstr << "Transition from head state " << transit->X1 << " to ear state " << transit->X2 << "has pop stack symbol idx" << ppit->first.front() << " and push stack symbol idx" << ppit->second.front() << ", but expected was the stack symbol idx" << mss2->Symbol() << ", because it is associated with the ear." << std::endl;
510  throw Exception(name, errstr.str(), 1003);
511  }
512  }
513  }
514  }
515  }
516  }
517  catch(Exception e){
518  }
519 
520  TestEnd(name);
521 }
522 
523 /* *****************
524  * TestSplitTransitionsEarToHead
525  * *****************/
527  std::string name = "Split Transitions Ear To Head";
528  TestStart(name);
529 
531 
532  PushdownGenerator g2 = Split(g1);
533 
534  try{
535  StateSet::Iterator stateit;
536  TransSet::Iterator transit;
537  PopPushSet::const_iterator ppit;
538  //look at all states
539  for(stateit = g2.StatesBegin(); stateit != g2.StatesEnd(); stateit++){
540 
541  const MergeStateSplit* mss1 = dynamic_cast<const MergeStateSplit*>(g2.StateAttribute(*stateit).Merge());
542 
543  //if the current state is an ear
544  if(!mss1->IsHead()){
545 
546  //look at all transitions starting here
547  for(transit = g2.TransRelBegin(*stateit); transit != g2.TransRelEnd(*stateit); transit++){
548  for(ppit = g2.PopPushBegin(*transit); ppit != g2.PopPushEnd(*transit); ppit++){
549 
550  const MergeStateSplit* mss2 = dynamic_cast<const MergeStateSplit*>(g2.StateAttribute(transit->X2).Merge());
551 
552  //the end state of the transition must be a head
553  if(!mss2->IsHead()){
554  std::stringstream errstr;
555  errstr << "Transition from ear to ear found (from " << *stateit << " to " << transit->X2 << ") found, but from ear to head was expected." << std::endl;
556  throw Exception(name, errstr.str(), 1003);
557  }
558 
559  //pop size must be one
560  if(ppit->first.size() != 1){
561  std::stringstream errstr;
562  errstr << "Pop size was " << ppit->first.size() << " but size 1 was expected." << std::endl;
563  throw Exception(name, errstr.str(), 1003);
564  }
565 
566  //the ear's associated stack symbol must be popped
567  if(mss1->Symbol() != ppit->first.front()){
568  std::stringstream errstr;
569  errstr << "Transition from ear state " << transit->X1 << " to head state " << transit->X2 << "has pop stack symbol idx " << ppit->first.front() << ", but " << mss1->Symbol() << " was expected, because it is associated with the ear." << std::endl;
570  throw Exception(name, errstr.str(), 1003);
571  }
572  }
573  }
574  }
575  }
576  }
577  catch(Exception e){
578  }
579 
580  TestEnd(name);
581 }
582 
583 /* *****************
584  * TestAcAccessible
585  * *****************/
587  std::string name = "Ac Accessible";
588  TestStart(name);
589 
591 
592  PushdownGenerator rPd;
593  PushdownAccessible(pd,rPd);
594 
595  try{
596 
597  //states s1, s2 and s4 must remain
598  if(!rPd.ExistsState("s1")){
599  std::stringstream errstr;
600  errstr << "State s1 was expected to exist, but did not." << std::endl;
601  throw Exception(name, errstr.str(), 1003);
602  }
603  if(!rPd.ExistsState("s2")){
604  std::stringstream errstr;
605  errstr << "State s2 was expected to exist, but did not." << std::endl;
606  throw Exception(name, errstr.str(), 1003);
607  }
608  if(!rPd.ExistsState("s4")){
609  std::stringstream errstr;
610  errstr << "State s4 was expected to exist, but did not." << std::endl;
611  throw Exception(name, errstr.str(), 1003);
612  }
613 
614  //there must be 3 states remaining
615  if(rPd.Size() != 3){
616  std::stringstream errstr;
617  errstr << "Number of remaining states was expected to be 3, but was "<< rPd.Size() << "." << std::endl;
618  throw Exception(name, errstr.str(), 1003);
619  }
620 
621  //there must be 2 transitions remaining
622  if(rPd.TransRelSize() != 2){
623  std::stringstream errstr;
624  errstr << "Number of remaining transitions was expected to be 2, but was "<< rPd.TransRelSize() << "." << std::endl;
625  throw Exception(name, errstr.str(), 1003);
626  }
627  }
628  catch(Exception e){
629  }
630 
631  TestEnd(name);
632 }
633 
634 /* *****************
635  * TestTransient
636  * *****************/
638 
641 }
642 
643 /* *****************
644  * TestRnce
645  * *****************/
646 void TestRnce(){
647 
649 }
650 
651 /* *****************
652  * TestTimes
653  * *****************/
654 void TestTimes(){
655 
657  TestTimesStates();
660 }
661 
662 /* *****************
663  * TestIntersectEvents
664  * *****************/
667 }
668 
669 /* *****************
670  * TestSplit
671  * *****************/
672 void TestSplit(){
674  TestSplitStates();
677 }
678 
679 /* *****************
680  * TestAc
681  * *****************/
682 void TestAc(){
684 }
685 } // namespace faudes
686 

libFAUDES 2.28c --- 2016.09.30 --- c++ api documentaion by doxygen