1# Copyright (C) 2014 The Android Open Source Project
2#
3# Licensed under the Apache License, Version 2.0 (the "License");
4# you may not use this file except in compliance with the License.
5# You may obtain a copy of the License at
6#
7#   http://www.apache.org/licenses/LICENSE-2.0
8#
9# Unless required by applicable law or agreed to in writing, software
10# distributed under the License is distributed on an "AS IS" BASIS,
11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12# See the License for the specific language governing permissions and
13# limitations under the License.
14
15from common.immutables import ImmutableDict
16from file_format.c1visualizer.parser import parse_c1_visualizer_stream
17from file_format.checker.parser import parse_checker_stream, parse_checker_statement
18from file_format.checker.struct import CheckerFile, TestCase, TestStatement
19from match.file import match_test_case, MatchFailedException, BadStructureException
20from match.line import match_lines
21
22import io
23import unittest
24
25CheckerException = SystemExit
26
27
28class MatchLines_Test(unittest.TestCase):
29
30  def create_test_statement(self, checker_string):
31    checker_file = CheckerFile("<checker-file>")
32    test_case = TestCase(checker_file, "TestMethod TestPass", 0)
33    return parse_checker_statement(test_case, checker_string, TestStatement.Variant.IN_ORDER, 0)
34
35  def try_match(self, checker_string, c1_string, var_state={}):
36    return match_lines(self.create_test_statement(checker_string),
37                       c1_string,
38                       ImmutableDict(var_state))
39
40  def assertMatches(self, checker_string, c1_string, var_state={}):
41    self.assertIsNotNone(self.try_match(checker_string, c1_string, var_state))
42
43  def assertDoesNotMatch(self, checker_string, c1_string, var_state={}):
44    self.assertIsNone(self.try_match(checker_string, c1_string, var_state))
45
46  def test_TextAndWhitespace(self):
47    self.assertMatches("foo", "foo")
48    self.assertMatches("foo", "  foo  ")
49    self.assertMatches("foo", "foo bar")
50    self.assertDoesNotMatch("foo", "XfooX")
51    self.assertDoesNotMatch("foo", "zoo")
52
53    self.assertMatches("foo bar", "foo   bar")
54    self.assertMatches("foo bar", "abc foo bar def")
55    self.assertMatches("foo bar", "foo foo bar bar")
56
57    self.assertMatches("foo bar", "foo X bar")
58    self.assertDoesNotMatch("foo bar", "foo Xbar")
59
60  def test_Pattern(self):
61    self.assertMatches("foo{{A|B}}bar", "fooAbar")
62    self.assertMatches("foo{{A|B}}bar", "fooBbar")
63    self.assertDoesNotMatch("foo{{A|B}}bar", "fooCbar")
64
65  def test_VariableReference(self):
66    self.assertMatches("foo<<X>>bar", "foobar", {"X": ""})
67    self.assertMatches("foo<<X>>bar", "fooAbar", {"X": "A"})
68    self.assertMatches("foo<<X>>bar", "fooBbar", {"X": "B"})
69    self.assertDoesNotMatch("foo<<X>>bar", "foobar", {"X": "A"})
70    self.assertDoesNotMatch("foo<<X>>bar", "foo bar", {"X": "A"})
71    with self.assertRaises(CheckerException):
72      self.try_match("foo<<X>>bar", "foobar", {})
73
74  def test_VariableDefinition(self):
75    self.assertMatches("foo<<X:A|B>>bar", "fooAbar")
76    self.assertMatches("foo<<X:A|B>>bar", "fooBbar")
77    self.assertDoesNotMatch("foo<<X:A|B>>bar", "fooCbar")
78
79    env = self.try_match("foo<<X:A.*B>>bar", "fooABbar", {})
80    self.assertEqual(env, {"X": "AB"})
81    env = self.try_match("foo<<X:A.*B>>bar", "fooAxxBbar", {})
82    self.assertEqual(env, {"X": "AxxB"})
83
84    self.assertMatches("foo<<X:A|B>>bar<<X>>baz", "fooAbarAbaz")
85    self.assertMatches("foo<<X:A|B>>bar<<X>>baz", "fooBbarBbaz")
86    self.assertDoesNotMatch("foo<<X:A|B>>bar<<X>>baz", "fooAbarBbaz")
87
88  def test_NoVariableRedefinition(self):
89    with self.assertRaises(CheckerException):
90      self.try_match("<<X:...>><<X>><<X:...>><<X>>", "foofoobarbar")
91
92  def test_EnvNotChangedOnPartialMatch(self):
93    env = {"Y": "foo"}
94    self.assertDoesNotMatch("<<X:A>>bar", "Abaz", env)
95    self.assertFalse("X" in env.keys())
96
97  def test_VariableContentEscaped(self):
98    self.assertMatches("<<X:..>>foo<<X>>", ".*foo.*")
99    self.assertDoesNotMatch("<<X:..>>foo<<X>>", ".*fooAAAA")
100
101
102class MatchFiles_Test(unittest.TestCase):
103
104  def assertMatches(self, checker_string, c1_string, isa=None, instruction_set_features=None):
105    checker_string = \
106      """
107        /// CHECK-START: MyMethod MyPass
108      """ + checker_string
109    meta_data = ""
110    if isa:
111      meta_data += "isa:" + isa
112
113    if instruction_set_features:
114      if meta_data:
115        meta_data += " "
116
117      joined_features = ",".join(
118        name if present else "-" + name for name, present in instruction_set_features.items())
119      meta_data += "isa_features:" + joined_features
120
121    meta_data_string = ""
122    if meta_data:
123      meta_data_string = \
124        """
125          begin_compilation
126            name "%s"
127            method "%s"
128            date 1234
129          end_compilation
130        """ % (meta_data, meta_data)
131    c1_string = meta_data_string + \
132               """
133                 begin_compilation
134                   name "MyMethod"
135                   method "MyMethod"
136                   date 1234
137                 end_compilation
138                 begin_cfg
139                   name "MyPass"
140               """ + c1_string + \
141               """
142                 end_cfg
143               """
144    checker_file = parse_checker_stream("<test-file>", "CHECK", io.StringIO(checker_string))
145    c1_file = parse_c1_visualizer_stream("<c1-file>", io.StringIO(c1_string))
146    assert len(checker_file.test_cases) == 1
147    assert len(c1_file.passes) == 1
148    match_test_case(checker_file.test_cases[0], c1_file.passes[0], c1_file.instruction_set_features)
149
150  def assertDoesNotMatch(self, checker_string, c1_string, isa=None, instruction_set_features=None):
151    with self.assertRaises(MatchFailedException):
152      self.assertMatches(checker_string, c1_string, isa, instruction_set_features)
153
154  def assertBadStructure(self, checker_string, c1_string):
155    with self.assertRaises(BadStructureException):
156      self.assertMatches(checker_string, c1_string)
157
158  def test_Text(self):
159    self.assertMatches("/// CHECK: foo bar", "foo bar")
160    self.assertDoesNotMatch("/// CHECK: foo bar", "abc def")
161
162  def test_Pattern(self):
163    self.assertMatches("/// CHECK: abc {{de.}}", "abc de#")
164    self.assertDoesNotMatch("/// CHECK: abc {{de.}}", "abc d#f")
165
166  def test_Variables(self):
167    self.assertMatches(
168      """
169        /// CHECK: foo<<X:.>>bar
170        /// CHECK: abc<<X>>def
171      """,
172      """
173        foo0bar
174        abc0def
175      """)
176    self.assertMatches(
177      """
178        /// CHECK: foo<<X:([0-9]+)>>bar
179        /// CHECK: abc<<X>>def
180        /// CHECK: ### <<X>> ###
181      """,
182      """
183        foo1234bar
184        abc1234def
185        ### 1234 ###
186      """)
187    self.assertDoesNotMatch(
188      """
189        /// CHECK: foo<<X:([0-9]+)>>bar
190        /// CHECK: abc<<X>>def
191      """,
192      """
193        foo1234bar
194        abc1235def
195      """)
196
197  def test_WholeWordMustMatch(self):
198    self.assertMatches("/// CHECK: b{{.}}r", "abc bar def")
199    self.assertDoesNotMatch("/// CHECK: b{{.}}r", "abc Xbar def")
200    self.assertDoesNotMatch("/// CHECK: b{{.}}r", "abc barX def")
201    self.assertDoesNotMatch("/// CHECK: b{{.}}r", "abc b r def")
202
203  def test_InOrderStatements(self):
204    self.assertMatches(
205      """
206        /// CHECK: foo
207        /// CHECK: bar
208      """,
209      """
210        foo
211        bar
212      """)
213    self.assertDoesNotMatch(
214      """
215        /// CHECK: foo
216        /// CHECK: bar
217      """,
218      """
219        bar
220        foo
221      """)
222
223  def test_NextLineStatements(self):
224    self.assertMatches(
225      """
226        /// CHECK:      foo
227        /// CHECK-NEXT: bar
228        /// CHECK-NEXT: abc
229        /// CHECK:      def
230      """,
231      """
232        foo
233        bar
234        abc
235        def
236      """)
237    self.assertMatches(
238      """
239        /// CHECK:      foo
240        /// CHECK-NEXT: bar
241        /// CHECK:      def
242      """,
243      """
244        foo
245        bar
246        abc
247        def
248      """)
249    self.assertDoesNotMatch(
250      """
251        /// CHECK:      foo
252        /// CHECK-NEXT: bar
253      """,
254      """
255        foo
256        abc
257        bar
258      """)
259
260    self.assertDoesNotMatch(
261      """
262        /// CHECK:      foo
263        /// CHECK-NEXT: bar
264      """,
265      """
266        bar
267        foo
268        abc
269      """)
270
271  def test_DagStatements(self):
272    self.assertMatches(
273      """
274        /// CHECK-DAG: foo
275        /// CHECK-DAG: bar
276      """,
277      """
278        foo
279        bar
280      """)
281    self.assertMatches(
282      """
283        /// CHECK-DAG: foo
284        /// CHECK-DAG: bar
285      """,
286      """
287        bar
288        foo
289      """)
290
291  def test_DagStatementsScope(self):
292    self.assertMatches(
293      """
294        /// CHECK:     foo
295        /// CHECK-DAG: abc
296        /// CHECK-DAG: def
297        /// CHECK:     bar
298      """,
299      """
300        foo
301        def
302        abc
303        bar
304      """)
305    self.assertDoesNotMatch(
306      """
307        /// CHECK:     foo
308        /// CHECK-DAG: abc
309        /// CHECK-DAG: def
310        /// CHECK:     bar
311      """,
312      """
313        foo
314        abc
315        bar
316        def
317      """)
318    self.assertDoesNotMatch(
319      """
320        /// CHECK:     foo
321        /// CHECK-DAG: abc
322        /// CHECK-DAG: def
323        /// CHECK:     bar
324      """,
325      """
326        foo
327        def
328        bar
329        abc
330      """)
331
332  def test_NotStatements(self):
333    self.assertMatches(
334      """
335        /// CHECK-NOT: foo
336      """,
337      """
338        abc
339        def
340      """)
341    self.assertDoesNotMatch(
342      """
343        /// CHECK-NOT: foo
344      """,
345      """
346        abc foo
347        def
348      """)
349    self.assertDoesNotMatch(
350      """
351        /// CHECK-NOT: foo
352        /// CHECK-NOT: bar
353      """,
354      """
355        abc
356        def bar
357      """)
358
359  def test_NotStatementsScope(self):
360    self.assertMatches(
361      """
362        /// CHECK:     abc
363        /// CHECK-NOT: foo
364        /// CHECK:     def
365      """,
366      """
367        abc
368        def
369      """)
370    self.assertMatches(
371      """
372        /// CHECK:     abc
373        /// CHECK-NOT: foo
374        /// CHECK:     def
375      """,
376      """
377        abc
378        def
379        foo
380      """)
381    self.assertDoesNotMatch(
382      """
383        /// CHECK:     abc
384        /// CHECK-NOT: foo
385        /// CHECK:     def
386      """,
387      """
388        abc
389        foo
390        def
391      """)
392    self.assertDoesNotMatch(
393      """
394        /// CHECK-NOT:  foo
395        /// CHECK-EVAL: 1 + 1 == 2
396        /// CHECK:      bar
397      """,
398      """
399        foo
400        abc
401        bar
402      """)
403    self.assertMatches(
404      """
405        /// CHECK-DAG:  bar
406        /// CHECK-DAG:  abc
407        /// CHECK-NOT:  foo
408      """,
409      """
410        foo
411        abc
412        bar
413      """)
414    self.assertDoesNotMatch(
415      """
416        /// CHECK-DAG:  abc
417        /// CHECK-DAG:  foo
418        /// CHECK-NOT:  bar
419      """,
420      """
421        foo
422        abc
423        bar
424      """)
425
426  def test_LineOnlyMatchesOnce(self):
427    self.assertMatches(
428      """
429        /// CHECK-DAG: foo
430        /// CHECK-DAG: foo
431      """,
432      """
433        foo
434        abc
435        foo
436      """)
437    self.assertDoesNotMatch(
438      """
439        /// CHECK-DAG: foo
440        /// CHECK-DAG: foo
441      """,
442      """
443        foo
444        abc
445        bar
446      """)
447
448  def test_EvalStatements(self):
449    self.assertMatches("/// CHECK-EVAL: True", "foo")
450    self.assertDoesNotMatch("/// CHECK-EVAL: False", "foo")
451
452    self.assertMatches("/// CHECK-EVAL: 1 + 2 == 3", "foo")
453    self.assertDoesNotMatch("/// CHECK-EVAL: 1 + 2 == 4", "foo")
454
455    twoVarTestCase = """
456                       /// CHECK-DAG: <<X:\d+>> <<Y:\d+>>
457                       /// CHECK-EVAL: <<X>> > <<Y>>
458                     """
459    self.assertMatches(twoVarTestCase, "42 41")
460    self.assertDoesNotMatch(twoVarTestCase, "42 43")
461
462  def test_MisplacedNext(self):
463    self.assertBadStructure(
464      """
465        /// CHECK-DAG:  foo
466        /// CHECK-NEXT: bar
467      """,
468      """
469      foo
470      bar
471      """)
472    self.assertBadStructure(
473      """
474        /// CHECK-NOT:  foo
475        /// CHECK-NEXT: bar
476      """,
477      """
478      foo
479      bar
480      """)
481    self.assertBadStructure(
482      """
483        /// CHECK-EVAL: True
484        /// CHECK-NEXT: bar
485      """,
486      """
487      foo
488      bar
489      """)
490    self.assertBadStructure(
491      """
492        /// CHECK-NEXT: bar
493      """,
494      """
495      foo
496      bar
497      """)
498
499  def test_EnvVariableEval(self):
500    self.assertMatches(
501      """
502        /// CHECK-IF: os.environ.get('MARTY_MCFLY') != '89mph!'
503        /// CHECK-FI:
504      """,
505      """
506      foo
507      """
508    )
509    self.assertMatches(
510      """
511        /// CHECK-EVAL: os.environ.get('MARTY_MCFLY') != '89mph!'
512      """,
513      """
514      foo
515      """
516    )
517
518  def test_IfStatements(self):
519    self.assertMatches(
520      """
521        /// CHECK: foo1
522        /// CHECK-IF: True
523        ///   CHECK-NEXT: foo2
524        /// CHECK-FI:
525        /// CHECK-NEXT: foo3
526        /// CHECK-NEXT: bar
527      """,
528      """
529      foo1
530      foo2
531      foo3
532      bar
533      """)
534    self.assertMatches(
535      """
536        /// CHECK: foo1
537        /// CHECK-IF: False
538        ///   CHECK-NEXT:    foo2
539        /// CHECK-FI:
540        /// CHECK-NEXT:    bar
541      """,
542      """
543      foo1
544      bar
545      """)
546    self.assertMatches(
547      """
548        /// CHECK: foo1
549        /// CHECK-IF: True
550        ///   CHECK-DAG:    foo2
551        /// CHECK-FI:
552        /// CHECK-DAG:    bar
553        /// CHECK: foo3
554      """,
555      """
556      foo1
557      bar
558      foo2
559      foo3
560      """)
561    self.assertDoesNotMatch(
562      """
563        /// CHECK: foo1
564        /// CHECK-IF: False
565        ///   CHECK-NEXT: foo2
566        /// CHECK-FI:
567        /// CHECK-NEXT: foo3
568      """,
569      """
570      foo1
571      foo2
572      foo3
573      """)
574
575  def test_IfElseStatements(self):
576    self.assertMatches(
577      """
578        /// CHECK: foo1
579        /// CHECK-IF: True
580        ///   CHECK-NEXT:    foo2
581        /// CHECK-ELSE:
582        ///   CHECK-NEXT:    foo3
583        /// CHECK-FI:
584        /// CHECK-NEXT:    bar
585      """,
586      """
587      foo1
588      foo2
589      bar
590      """)
591    self.assertMatches(
592      """
593        /// CHECK: foo1
594        /// CHECK-IF: False
595        ///   CHECK-NEXT:    foo2
596        /// CHECK-ELSE:
597        ///   CHECK-NEXT:    foo3
598        /// CHECK-FI:
599        /// CHECK-NEXT:    bar
600      """,
601      """
602      foo1
603      foo3
604      bar
605      """)
606    self.assertMatches(
607      """
608        /// CHECK: foo1
609        /// CHECK-IF: False
610        ///   CHECK-NEXT:    foo2
611        /// CHECK-ELSE:
612        ///   CHECK-DAG:    bar
613        /// CHECK-FI:
614        /// CHECK-DAG:    foo3
615        /// CHECK: foo4
616      """,
617      """
618      foo1
619      foo3
620      bar
621      foo4
622      """)
623    self.assertDoesNotMatch(
624      """
625        /// CHECK: foo1
626        /// CHECK-IF: False
627        ///   CHECK-NEXT:    foo2
628        /// CHECK-ELSE:
629        ///   CHECK-NEXT:    foo3
630        /// CHECK-FI:
631        /// CHECK-NEXT:    bar
632      """,
633      """
634      foo1
635      foo2
636      bar
637      """)
638
639  def test_IfElifElseStatements(self):
640    self.assertMatches(
641      """
642        /// CHECK: foo1
643        /// CHECK-IF: True
644        ///   CHECK-NEXT:    foo2
645        /// CHECK-ELIF: True
646        ///   CHECK-NEXT:    foo3
647        /// CHECK-ELIF: True
648        ///   CHECK-NEXT:    foo4
649        /// CHECK-FI:
650        /// CHECK-NEXT:    bar
651      """,
652      """
653      foo1
654      foo2
655      bar
656      """)
657    self.assertMatches(
658      """
659        /// CHECK: foo1
660        /// CHECK-IF: False
661        ///   CHECK-NEXT:    foo2
662        /// CHECK-ELIF: False
663        ///   CHECK-NEXT:    foo3
664        /// CHECK-ELIF: True
665        ///   CHECK-NEXT:    foo4
666        /// CHECK-FI:
667        /// CHECK-NEXT:    bar
668      """,
669      """
670      foo1
671      foo4
672      bar
673      """)
674    self.assertMatches(
675      """
676        /// CHECK: foo1
677        /// CHECK-IF: False
678        ///   CHECK-NEXT:    foo2
679        /// CHECK-ELIF: True
680        ///   CHECK-NEXT:    foo3
681        /// CHECK-ELIF: True
682        ///   CHECK-NEXT:    foo4
683        /// CHECK-FI:
684        /// CHECK-NEXT:    bar
685      """,
686      """
687      foo1
688      foo3
689      bar
690      """)
691    self.assertMatches(
692      """
693        /// CHECK: foo1
694        /// CHECK-IF: False
695        ///   CHECK-NEXT:    foo2
696        /// CHECK-ELIF: False
697        ///   CHECK-NEXT:    foo3
698        /// CHECK-ELIF: False
699        ///   CHECK-NEXT:    foo4
700        /// CHECK-FI:
701        /// CHECK-NEXT:    bar
702      """,
703      """
704      foo1
705      bar
706      """)
707    self.assertDoesNotMatch(
708      """
709        /// CHECK: foo1
710        /// CHECK-IF: False
711        ///   CHECK-NEXT:    foo2
712        /// CHECK-ELIF: True
713        ///   CHECK-NEXT:    foo3
714        /// CHECK-ELSE:
715        ///   CHECK-NEXT:    foo4
716        /// CHECK-FI:
717        /// CHECK-NEXT:    bar
718      """,
719      """
720      foo1
721      foo2
722      bar
723      """)
724
725  def test_NestedBranching(self):
726    self.assertMatches(
727      """
728        /// CHECK: foo1
729        /// CHECK-IF: True
730        ///   CHECK-IF: True
731        ///     CHECK-NEXT:    foo2
732        ///   CHECK-ELSE:
733        ///     CHECK-NEXT:    foo3
734        ///   CHECK-FI:
735        /// CHECK-ELSE:
736        ///   CHECK-IF: True
737        ///     CHECK-NEXT:    foo4
738        ///   CHECK-ELSE:
739        ///     CHECK-NEXT:    foo5
740        ///   CHECK-FI:
741        /// CHECK-FI:
742        /// CHECK-NEXT: foo6
743      """,
744      """
745      foo1
746      foo2
747      foo6
748      """)
749    self.assertMatches(
750      """
751        /// CHECK-IF: True
752        ///   CHECK-IF: False
753        ///     CHECK:    foo1
754        ///   CHECK-ELSE:
755        ///     CHECK:    foo2
756        ///   CHECK-FI:
757        /// CHECK-ELSE:
758        ///   CHECK-IF: True
759        ///     CHECK:    foo3
760        ///   CHECK-ELSE:
761        ///     CHECK:    foo4
762        ///   CHECK-FI:
763        /// CHECK-FI:
764      """,
765      """
766      foo2
767      """)
768    self.assertMatches(
769      """
770        /// CHECK-IF: False
771        ///   CHECK-IF: True
772        ///     CHECK:    foo1
773        ///   CHECK-ELSE:
774        ///     CHECK:    foo2
775        ///   CHECK-FI:
776        /// CHECK-ELSE:
777        ///   CHECK-IF: False
778        ///     CHECK:    foo3
779        ///   CHECK-ELSE:
780        ///     CHECK-IF: False
781        ///       CHECK:    foo4
782        ///     CHECK-ELSE:
783        ///       CHECK: foo5
784        ///     CHECK-FI:
785        ///   CHECK-FI:
786        /// CHECK-FI:
787      """,
788      """
789      foo5
790      """)
791    self.assertDoesNotMatch(
792      """
793        /// CHECK: foo1
794        /// CHECK-IF: True
795        ///   CHECK-IF: False
796        ///     CHECK-NEXT:    foo2
797        ///   CHECK-ELSE:
798        ///     CHECK-NEXT:    foo3
799        ///   CHECK-FI:
800        /// CHECK-NEXT: foo6
801      """,
802      """
803      foo1
804      foo2
805      foo6
806      """)
807
808  def test_VariablesInBranches(self):
809    self.assertMatches(
810      """
811        /// CHECK-IF: True
812        ///   CHECK: foo<<VarA:\d+>>
813        /// CHECK-FI:
814        /// CHECK-EVAL: <<VarA>> == 12
815      """,
816      """
817      foo12
818      """)
819    self.assertDoesNotMatch(
820      """
821        /// CHECK-IF: True
822        ///   CHECK: foo<<VarA:\d+>>
823        /// CHECK-FI:
824        /// CHECK-EVAL: <<VarA>> == 99
825      """,
826      """
827      foo12
828      """)
829    self.assertMatches(
830      """
831        /// CHECK-IF: True
832        ///   CHECK: foo<<VarA:\d+>>
833        ///   CHECK-IF: <<VarA>> == 12
834        ///     CHECK: bar<<VarB:M|N>>
835        ///   CHECK-FI:
836        /// CHECK-FI:
837        /// CHECK-EVAL: "<<VarB>>" == "M"
838      """,
839      """
840      foo12
841      barM
842      """)
843    self.assertMatches(
844      """
845        /// CHECK-IF: False
846        ///   CHECK: foo<<VarA:\d+>>
847        /// CHECK-ELIF: True
848        ///   CHECK: foo<<VarA:M|N>>
849        /// CHECK-FI:
850        /// CHECK-EVAL: "<<VarA>>" == "M"
851      """,
852      """
853      fooM
854      """)
855    self.assertMatches(
856      """
857        /// CHECK-IF: False
858        ///   CHECK: foo<<VarA:A|B>>
859        /// CHECK-ELIF: False
860        ///   CHECK: foo<<VarA:A|B>>
861        /// CHECK-ELSE:
862        ///   CHECK-IF: False
863        ///     CHECK: foo<<VarA:A|B>>
864        ///   CHECK-ELSE:
865        ///     CHECK: foo<<VarA:M|N>>
866        ///   CHECK-FI:
867        /// CHECK-FI:
868        /// CHECK-EVAL: "<<VarA>>" == "N"
869      """,
870      """
871      fooN
872      """)
873
874  def test_MalformedBranching(self):
875    self.assertBadStructure(
876      """
877        /// CHECK-IF: True
878        /// CHECK: foo
879      """,
880      """
881      foo
882      """)
883    self.assertBadStructure(
884      """
885        /// CHECK-ELSE:
886        /// CHECK: foo
887      """,
888      """
889      foo
890      """)
891    self.assertBadStructure(
892      """
893        /// CHECK-IF: True
894        /// CHECK: foo
895        /// CHECK-ELSE:
896      """,
897      """
898      foo
899      """)
900    self.assertBadStructure(
901      """
902        /// CHECK-IF: True
903        ///   CHECK: foo
904        /// CHECK-ELIF:
905        ///   CHECK: foo
906        ///   CHECK-IF: True
907        ///     CHECK: foo
908        /// CHECK-FI:
909      """,
910      """
911      foo
912      """)
913    self.assertBadStructure(
914      """
915        /// CHECK-IF: True
916        ///   CHECK: foo
917        /// CHECK-ELSE:
918        ///   CHECK: foo
919        /// CHECK-ELIF:
920        ///   CHECK: foo
921        /// CHECK-FI:
922      """,
923      """
924      foo
925      """)
926    self.assertBadStructure(
927      """
928        /// CHECK-IF: True
929        ///   CHECK: foo
930        /// CHECK-ELSE:
931        ///   CHECK: foo
932        /// CHECK-ELSE:
933        ///   CHECK: foo
934        /// CHECK-FI:
935      """,
936      """
937      foo
938      """)
939
940  def test_hasIsaFeature(self):
941    no_isa = None
942    self.assertMatches(
943      """
944        /// CHECK-EVAL: hasIsaFeature('feature1') and not hasIsaFeature('feature2')
945      """,
946      """
947      foo
948      """,
949      no_isa,
950      ImmutableDict({"feature1": True})
951    )
952    self.assertDoesNotMatch(
953      """
954        /// CHECK-EVAL: not hasIsaFeature('feature1')
955      """,
956      """
957      foo
958      """,
959      no_isa,
960      ImmutableDict({"feature1": True})
961    )
962    self.assertMatches(
963      """
964        /// CHECK-IF: hasIsaFeature('feature2')
965        ///   CHECK: bar1
966        /// CHECK-ELSE:
967        ///   CHECK: bar2
968        /// CHECK-FI:
969      """,
970      """
971      foo
972      bar1
973      """,
974      no_isa,
975      ImmutableDict({"feature1": False, "feature2": True})
976    )
977    self.assertMatches(
978      """
979        /// CHECK-EVAL: hasIsaFeature('feature1') and not hasIsaFeature('feature2')
980      """,
981      """
982      foo
983      """,
984      "some_isa",
985      ImmutableDict({"feature1": True})
986    )
987    self.assertDoesNotMatch(
988      """
989        /// CHECK-EVAL: not hasIsaFeature('feature1')
990      """,
991      """
992      foo
993      """,
994      "some_isa",
995      ImmutableDict({"feature1": True})
996    )
997    self.assertMatches(
998      """
999        /// CHECK-IF: hasIsaFeature('feature2')
1000        ///   CHECK: bar1
1001        /// CHECK-ELSE:
1002        ///   CHECK: bar2
1003        /// CHECK-FI:
1004      """,
1005      """
1006      foo
1007      bar1
1008      """,
1009      "some_isa",
1010      ImmutableDict({"feature1": False, "feature2": True})
1011    )
1012