xref: /aosp_15_r20/art/tools/checker/match/test.py (revision 795d594fd825385562da6b089ea9b2033f3abf5a)
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,
105                    isa=None,
106                    instruction_set_features=None,
107                    read_barrier_type="none"):
108    checker_string = \
109      """
110        /// CHECK-START: MyMethod MyPass
111      """ + checker_string
112    meta_data = ""
113    if isa:
114      meta_data += "isa:" + isa
115
116    if instruction_set_features:
117      if meta_data:
118        meta_data += " "
119
120      joined_features = ",".join(
121        name if present else "-" + name for name, present in instruction_set_features.items())
122      meta_data += "isa_features:" + joined_features
123
124    if meta_data:
125      meta_data += " "
126    meta_data += f"read_barrier_type:{read_barrier_type}"
127
128    meta_data_string = ""
129    if meta_data:
130      meta_data_string = \
131        """
132          begin_compilation
133            name "%s"
134            method "%s"
135            date 1234
136          end_compilation
137        """ % (meta_data, meta_data)
138    c1_string = meta_data_string + \
139               """
140                 begin_compilation
141                   name "MyMethod"
142                   method "MyMethod"
143                   date 1234
144                 end_compilation
145                 begin_cfg
146                   name "MyPass"
147               """ + c1_string + \
148               """
149                 end_cfg
150               """
151    checker_file = parse_checker_stream("<test-file>", "CHECK", io.StringIO(checker_string))
152    c1_file = parse_c1_visualizer_stream("<c1-file>", io.StringIO(c1_string))
153    assert len(checker_file.test_cases) == 1
154    assert len(c1_file.passes) == 1
155    match_test_case(checker_file.test_cases[0],
156                    c1_file.passes[0],
157                    c1_file.instruction_set_features,
158                    c1_file.read_barrier_type)
159
160  def assertDoesNotMatch(self, checker_string, c1_string,
161                         isa=None,
162                         instruction_set_features=None,
163                         read_barrier_type="none"):
164    with self.assertRaises(MatchFailedException):
165      self.assertMatches(checker_string, c1_string, isa, instruction_set_features, read_barrier_type)
166
167  def assertBadStructure(self, checker_string, c1_string):
168    with self.assertRaises(BadStructureException):
169      self.assertMatches(checker_string, c1_string)
170
171  def test_Text(self):
172    self.assertMatches("/// CHECK: foo bar", "foo bar")
173    self.assertDoesNotMatch("/// CHECK: foo bar", "abc def")
174
175  def test_Pattern(self):
176    self.assertMatches("/// CHECK: abc {{de.}}", "abc de#")
177    self.assertDoesNotMatch("/// CHECK: abc {{de.}}", "abc d#f")
178
179  def test_Variables(self):
180    self.assertMatches(
181      """
182        /// CHECK: foo<<X:.>>bar
183        /// CHECK: abc<<X>>def
184      """,
185      """
186        foo0bar
187        abc0def
188      """)
189    self.assertMatches(
190      """
191        /// CHECK: foo<<X:([0-9]+)>>bar
192        /// CHECK: abc<<X>>def
193        /// CHECK: ### <<X>> ###
194      """,
195      """
196        foo1234bar
197        abc1234def
198        ### 1234 ###
199      """)
200    self.assertDoesNotMatch(
201      """
202        /// CHECK: foo<<X:([0-9]+)>>bar
203        /// CHECK: abc<<X>>def
204      """,
205      """
206        foo1234bar
207        abc1235def
208      """)
209
210  def test_WholeWordMustMatch(self):
211    self.assertMatches("/// CHECK: b{{.}}r", "abc bar def")
212    self.assertDoesNotMatch("/// CHECK: b{{.}}r", "abc Xbar def")
213    self.assertDoesNotMatch("/// CHECK: b{{.}}r", "abc barX def")
214    self.assertDoesNotMatch("/// CHECK: b{{.}}r", "abc b r def")
215
216  def test_InOrderStatements(self):
217    self.assertMatches(
218      """
219        /// CHECK: foo
220        /// CHECK: bar
221      """,
222      """
223        foo
224        bar
225      """)
226    self.assertDoesNotMatch(
227      """
228        /// CHECK: foo
229        /// CHECK: bar
230      """,
231      """
232        bar
233        foo
234      """)
235
236  def test_NextLineStatements(self):
237    self.assertMatches(
238      """
239        /// CHECK:      foo
240        /// CHECK-NEXT: bar
241        /// CHECK-NEXT: abc
242        /// CHECK:      def
243      """,
244      """
245        foo
246        bar
247        abc
248        def
249      """)
250    self.assertMatches(
251      """
252        /// CHECK:      foo
253        /// CHECK-NEXT: bar
254        /// CHECK:      def
255      """,
256      """
257        foo
258        bar
259        abc
260        def
261      """)
262    self.assertDoesNotMatch(
263      """
264        /// CHECK:      foo
265        /// CHECK-NEXT: bar
266      """,
267      """
268        foo
269        abc
270        bar
271      """)
272
273    self.assertDoesNotMatch(
274      """
275        /// CHECK:      foo
276        /// CHECK-NEXT: bar
277      """,
278      """
279        bar
280        foo
281        abc
282      """)
283
284  def test_DagStatements(self):
285    self.assertMatches(
286      """
287        /// CHECK-DAG: foo
288        /// CHECK-DAG: bar
289      """,
290      """
291        foo
292        bar
293      """)
294    self.assertMatches(
295      """
296        /// CHECK-DAG: foo
297        /// CHECK-DAG: bar
298      """,
299      """
300        bar
301        foo
302      """)
303
304  def test_DagStatementsScope(self):
305    self.assertMatches(
306      """
307        /// CHECK:     foo
308        /// CHECK-DAG: abc
309        /// CHECK-DAG: def
310        /// CHECK:     bar
311      """,
312      """
313        foo
314        def
315        abc
316        bar
317      """)
318    self.assertDoesNotMatch(
319      """
320        /// CHECK:     foo
321        /// CHECK-DAG: abc
322        /// CHECK-DAG: def
323        /// CHECK:     bar
324      """,
325      """
326        foo
327        abc
328        bar
329        def
330      """)
331    self.assertDoesNotMatch(
332      """
333        /// CHECK:     foo
334        /// CHECK-DAG: abc
335        /// CHECK-DAG: def
336        /// CHECK:     bar
337      """,
338      """
339        foo
340        def
341        bar
342        abc
343      """)
344
345  def test_NotStatements(self):
346    self.assertMatches(
347      """
348        /// CHECK-NOT: foo
349      """,
350      """
351        abc
352        def
353      """)
354    self.assertDoesNotMatch(
355      """
356        /// CHECK-NOT: foo
357      """,
358      """
359        abc foo
360        def
361      """)
362    self.assertDoesNotMatch(
363      """
364        /// CHECK-NOT: foo
365        /// CHECK-NOT: bar
366      """,
367      """
368        abc
369        def bar
370      """)
371
372  def test_NotStatementsScope(self):
373    self.assertMatches(
374      """
375        /// CHECK:     abc
376        /// CHECK-NOT: foo
377        /// CHECK:     def
378      """,
379      """
380        abc
381        def
382      """)
383    self.assertMatches(
384      """
385        /// CHECK:     abc
386        /// CHECK-NOT: foo
387        /// CHECK:     def
388      """,
389      """
390        abc
391        def
392        foo
393      """)
394    self.assertDoesNotMatch(
395      """
396        /// CHECK:     abc
397        /// CHECK-NOT: foo
398        /// CHECK:     def
399      """,
400      """
401        abc
402        foo
403        def
404      """)
405    self.assertDoesNotMatch(
406      """
407        /// CHECK-NOT:  foo
408        /// CHECK-EVAL: 1 + 1 == 2
409        /// CHECK:      bar
410      """,
411      """
412        foo
413        abc
414        bar
415      """)
416    self.assertMatches(
417      """
418        /// CHECK-DAG:  bar
419        /// CHECK-DAG:  abc
420        /// CHECK-NOT:  foo
421      """,
422      """
423        foo
424        abc
425        bar
426      """)
427    self.assertDoesNotMatch(
428      """
429        /// CHECK-DAG:  abc
430        /// CHECK-DAG:  foo
431        /// CHECK-NOT:  bar
432      """,
433      """
434        foo
435        abc
436        bar
437      """)
438
439  def test_LineOnlyMatchesOnce(self):
440    self.assertMatches(
441      """
442        /// CHECK-DAG: foo
443        /// CHECK-DAG: foo
444      """,
445      """
446        foo
447        abc
448        foo
449      """)
450    self.assertDoesNotMatch(
451      """
452        /// CHECK-DAG: foo
453        /// CHECK-DAG: foo
454      """,
455      """
456        foo
457        abc
458        bar
459      """)
460
461  def test_EvalStatements(self):
462    self.assertMatches("/// CHECK-EVAL: True", "foo")
463    self.assertDoesNotMatch("/// CHECK-EVAL: False", "foo")
464
465    self.assertMatches("/// CHECK-EVAL: 1 + 2 == 3", "foo")
466    self.assertDoesNotMatch("/// CHECK-EVAL: 1 + 2 == 4", "foo")
467
468    twoVarTestCase = """
469                       /// CHECK-DAG: <<X:\d+>> <<Y:\d+>>
470                       /// CHECK-EVAL: <<X>> > <<Y>>
471                     """
472    self.assertMatches(twoVarTestCase, "42 41")
473    self.assertDoesNotMatch(twoVarTestCase, "42 43")
474
475  def test_MisplacedNext(self):
476    self.assertBadStructure(
477      """
478        /// CHECK-DAG:  foo
479        /// CHECK-NEXT: bar
480      """,
481      """
482      foo
483      bar
484      """)
485    self.assertBadStructure(
486      """
487        /// CHECK-NOT:  foo
488        /// CHECK-NEXT: bar
489      """,
490      """
491      foo
492      bar
493      """)
494    self.assertBadStructure(
495      """
496        /// CHECK-EVAL: True
497        /// CHECK-NEXT: bar
498      """,
499      """
500      foo
501      bar
502      """)
503    self.assertBadStructure(
504      """
505        /// CHECK-NEXT: bar
506      """,
507      """
508      foo
509      bar
510      """)
511
512  def test_EnvVariableEval(self):
513    self.assertMatches(
514      """
515        /// CHECK-IF: os.environ.get('MARTY_MCFLY') != '89mph!'
516        /// CHECK-FI:
517      """,
518      """
519      foo
520      """
521    )
522    self.assertMatches(
523      """
524        /// CHECK-EVAL: os.environ.get('MARTY_MCFLY') != '89mph!'
525      """,
526      """
527      foo
528      """
529    )
530
531  def test_IfStatements(self):
532    self.assertMatches(
533      """
534        /// CHECK: foo1
535        /// CHECK-IF: True
536        ///   CHECK-NEXT: foo2
537        /// CHECK-FI:
538        /// CHECK-NEXT: foo3
539        /// CHECK-NEXT: bar
540      """,
541      """
542      foo1
543      foo2
544      foo3
545      bar
546      """)
547    self.assertMatches(
548      """
549        /// CHECK: foo1
550        /// CHECK-IF: False
551        ///   CHECK-NEXT:    foo2
552        /// CHECK-FI:
553        /// CHECK-NEXT:    bar
554      """,
555      """
556      foo1
557      bar
558      """)
559    self.assertMatches(
560      """
561        /// CHECK: foo1
562        /// CHECK-IF: True
563        ///   CHECK-DAG:    foo2
564        /// CHECK-FI:
565        /// CHECK-DAG:    bar
566        /// CHECK: foo3
567      """,
568      """
569      foo1
570      bar
571      foo2
572      foo3
573      """)
574    self.assertDoesNotMatch(
575      """
576        /// CHECK: foo1
577        /// CHECK-IF: False
578        ///   CHECK-NEXT: foo2
579        /// CHECK-FI:
580        /// CHECK-NEXT: foo3
581      """,
582      """
583      foo1
584      foo2
585      foo3
586      """)
587
588  def test_IfElseStatements(self):
589    self.assertMatches(
590      """
591        /// CHECK: foo1
592        /// CHECK-IF: True
593        ///   CHECK-NEXT:    foo2
594        /// CHECK-ELSE:
595        ///   CHECK-NEXT:    foo3
596        /// CHECK-FI:
597        /// CHECK-NEXT:    bar
598      """,
599      """
600      foo1
601      foo2
602      bar
603      """)
604    self.assertMatches(
605      """
606        /// CHECK: foo1
607        /// CHECK-IF: False
608        ///   CHECK-NEXT:    foo2
609        /// CHECK-ELSE:
610        ///   CHECK-NEXT:    foo3
611        /// CHECK-FI:
612        /// CHECK-NEXT:    bar
613      """,
614      """
615      foo1
616      foo3
617      bar
618      """)
619    self.assertMatches(
620      """
621        /// CHECK: foo1
622        /// CHECK-IF: False
623        ///   CHECK-NEXT:    foo2
624        /// CHECK-ELSE:
625        ///   CHECK-DAG:    bar
626        /// CHECK-FI:
627        /// CHECK-DAG:    foo3
628        /// CHECK: foo4
629      """,
630      """
631      foo1
632      foo3
633      bar
634      foo4
635      """)
636    self.assertDoesNotMatch(
637      """
638        /// CHECK: foo1
639        /// CHECK-IF: False
640        ///   CHECK-NEXT:    foo2
641        /// CHECK-ELSE:
642        ///   CHECK-NEXT:    foo3
643        /// CHECK-FI:
644        /// CHECK-NEXT:    bar
645      """,
646      """
647      foo1
648      foo2
649      bar
650      """)
651
652  def test_IfElifElseStatements(self):
653    self.assertMatches(
654      """
655        /// CHECK: foo1
656        /// CHECK-IF: True
657        ///   CHECK-NEXT:    foo2
658        /// CHECK-ELIF: True
659        ///   CHECK-NEXT:    foo3
660        /// CHECK-ELIF: True
661        ///   CHECK-NEXT:    foo4
662        /// CHECK-FI:
663        /// CHECK-NEXT:    bar
664      """,
665      """
666      foo1
667      foo2
668      bar
669      """)
670    self.assertMatches(
671      """
672        /// CHECK: foo1
673        /// CHECK-IF: False
674        ///   CHECK-NEXT:    foo2
675        /// CHECK-ELIF: False
676        ///   CHECK-NEXT:    foo3
677        /// CHECK-ELIF: True
678        ///   CHECK-NEXT:    foo4
679        /// CHECK-FI:
680        /// CHECK-NEXT:    bar
681      """,
682      """
683      foo1
684      foo4
685      bar
686      """)
687    self.assertMatches(
688      """
689        /// CHECK: foo1
690        /// CHECK-IF: False
691        ///   CHECK-NEXT:    foo2
692        /// CHECK-ELIF: True
693        ///   CHECK-NEXT:    foo3
694        /// CHECK-ELIF: True
695        ///   CHECK-NEXT:    foo4
696        /// CHECK-FI:
697        /// CHECK-NEXT:    bar
698      """,
699      """
700      foo1
701      foo3
702      bar
703      """)
704    self.assertMatches(
705      """
706        /// CHECK: foo1
707        /// CHECK-IF: False
708        ///   CHECK-NEXT:    foo2
709        /// CHECK-ELIF: False
710        ///   CHECK-NEXT:    foo3
711        /// CHECK-ELIF: False
712        ///   CHECK-NEXT:    foo4
713        /// CHECK-FI:
714        /// CHECK-NEXT:    bar
715      """,
716      """
717      foo1
718      bar
719      """)
720    self.assertDoesNotMatch(
721      """
722        /// CHECK: foo1
723        /// CHECK-IF: False
724        ///   CHECK-NEXT:    foo2
725        /// CHECK-ELIF: True
726        ///   CHECK-NEXT:    foo3
727        /// CHECK-ELSE:
728        ///   CHECK-NEXT:    foo4
729        /// CHECK-FI:
730        /// CHECK-NEXT:    bar
731      """,
732      """
733      foo1
734      foo2
735      bar
736      """)
737
738  def test_NestedBranching(self):
739    self.assertMatches(
740      """
741        /// CHECK: foo1
742        /// CHECK-IF: True
743        ///   CHECK-IF: True
744        ///     CHECK-NEXT:    foo2
745        ///   CHECK-ELSE:
746        ///     CHECK-NEXT:    foo3
747        ///   CHECK-FI:
748        /// CHECK-ELSE:
749        ///   CHECK-IF: True
750        ///     CHECK-NEXT:    foo4
751        ///   CHECK-ELSE:
752        ///     CHECK-NEXT:    foo5
753        ///   CHECK-FI:
754        /// CHECK-FI:
755        /// CHECK-NEXT: foo6
756      """,
757      """
758      foo1
759      foo2
760      foo6
761      """)
762    self.assertMatches(
763      """
764        /// CHECK-IF: True
765        ///   CHECK-IF: False
766        ///     CHECK:    foo1
767        ///   CHECK-ELSE:
768        ///     CHECK:    foo2
769        ///   CHECK-FI:
770        /// CHECK-ELSE:
771        ///   CHECK-IF: True
772        ///     CHECK:    foo3
773        ///   CHECK-ELSE:
774        ///     CHECK:    foo4
775        ///   CHECK-FI:
776        /// CHECK-FI:
777      """,
778      """
779      foo2
780      """)
781    self.assertMatches(
782      """
783        /// CHECK-IF: False
784        ///   CHECK-IF: True
785        ///     CHECK:    foo1
786        ///   CHECK-ELSE:
787        ///     CHECK:    foo2
788        ///   CHECK-FI:
789        /// CHECK-ELSE:
790        ///   CHECK-IF: False
791        ///     CHECK:    foo3
792        ///   CHECK-ELSE:
793        ///     CHECK-IF: False
794        ///       CHECK:    foo4
795        ///     CHECK-ELSE:
796        ///       CHECK: foo5
797        ///     CHECK-FI:
798        ///   CHECK-FI:
799        /// CHECK-FI:
800      """,
801      """
802      foo5
803      """)
804    self.assertDoesNotMatch(
805      """
806        /// CHECK: foo1
807        /// CHECK-IF: True
808        ///   CHECK-IF: False
809        ///     CHECK-NEXT:    foo2
810        ///   CHECK-ELSE:
811        ///     CHECK-NEXT:    foo3
812        ///   CHECK-FI:
813        /// CHECK-NEXT: foo6
814      """,
815      """
816      foo1
817      foo2
818      foo6
819      """)
820
821  def test_VariablesInBranches(self):
822    self.assertMatches(
823      """
824        /// CHECK-IF: True
825        ///   CHECK: foo<<VarA:\d+>>
826        /// CHECK-FI:
827        /// CHECK-EVAL: <<VarA>> == 12
828      """,
829      """
830      foo12
831      """)
832    self.assertDoesNotMatch(
833      """
834        /// CHECK-IF: True
835        ///   CHECK: foo<<VarA:\d+>>
836        /// CHECK-FI:
837        /// CHECK-EVAL: <<VarA>> == 99
838      """,
839      """
840      foo12
841      """)
842    self.assertMatches(
843      """
844        /// CHECK-IF: True
845        ///   CHECK: foo<<VarA:\d+>>
846        ///   CHECK-IF: <<VarA>> == 12
847        ///     CHECK: bar<<VarB:M|N>>
848        ///   CHECK-FI:
849        /// CHECK-FI:
850        /// CHECK-EVAL: "<<VarB>>" == "M"
851      """,
852      """
853      foo12
854      barM
855      """)
856    self.assertMatches(
857      """
858        /// CHECK-IF: False
859        ///   CHECK: foo<<VarA:\d+>>
860        /// CHECK-ELIF: True
861        ///   CHECK: foo<<VarA:M|N>>
862        /// CHECK-FI:
863        /// CHECK-EVAL: "<<VarA>>" == "M"
864      """,
865      """
866      fooM
867      """)
868    self.assertMatches(
869      """
870        /// CHECK-IF: False
871        ///   CHECK: foo<<VarA:A|B>>
872        /// CHECK-ELIF: False
873        ///   CHECK: foo<<VarA:A|B>>
874        /// CHECK-ELSE:
875        ///   CHECK-IF: False
876        ///     CHECK: foo<<VarA:A|B>>
877        ///   CHECK-ELSE:
878        ///     CHECK: foo<<VarA:M|N>>
879        ///   CHECK-FI:
880        /// CHECK-FI:
881        /// CHECK-EVAL: "<<VarA>>" == "N"
882      """,
883      """
884      fooN
885      """)
886
887  def test_MalformedBranching(self):
888    self.assertBadStructure(
889      """
890        /// CHECK-IF: True
891        /// CHECK: foo
892      """,
893      """
894      foo
895      """)
896    self.assertBadStructure(
897      """
898        /// CHECK-ELSE:
899        /// CHECK: foo
900      """,
901      """
902      foo
903      """)
904    self.assertBadStructure(
905      """
906        /// CHECK-IF: True
907        /// CHECK: foo
908        /// CHECK-ELSE:
909      """,
910      """
911      foo
912      """)
913    self.assertBadStructure(
914      """
915        /// CHECK-IF: True
916        ///   CHECK: foo
917        /// CHECK-ELIF:
918        ///   CHECK: foo
919        ///   CHECK-IF: True
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-ELIF:
933        ///   CHECK: foo
934        /// CHECK-FI:
935      """,
936      """
937      foo
938      """)
939    self.assertBadStructure(
940      """
941        /// CHECK-IF: True
942        ///   CHECK: foo
943        /// CHECK-ELSE:
944        ///   CHECK: foo
945        /// CHECK-ELSE:
946        ///   CHECK: foo
947        /// CHECK-FI:
948      """,
949      """
950      foo
951      """)
952
953  def test_hasIsaFeature(self):
954    no_isa = None
955    self.assertMatches(
956      """
957        /// CHECK-EVAL: hasIsaFeature('feature1') and not hasIsaFeature('feature2')
958      """,
959      """
960      foo
961      """,
962      no_isa,
963      ImmutableDict({"feature1": True})
964    )
965    self.assertDoesNotMatch(
966      """
967        /// CHECK-EVAL: not hasIsaFeature('feature1')
968      """,
969      """
970      foo
971      """,
972      no_isa,
973      ImmutableDict({"feature1": True})
974    )
975    self.assertMatches(
976      """
977        /// CHECK-IF: hasIsaFeature('feature2')
978        ///   CHECK: bar1
979        /// CHECK-ELSE:
980        ///   CHECK: bar2
981        /// CHECK-FI:
982      """,
983      """
984      foo
985      bar1
986      """,
987      no_isa,
988      ImmutableDict({"feature1": False, "feature2": True})
989    )
990    self.assertMatches(
991      """
992        /// CHECK-EVAL: hasIsaFeature('feature1') and not hasIsaFeature('feature2')
993      """,
994      """
995      foo
996      """,
997      "some_isa",
998      ImmutableDict({"feature1": True})
999    )
1000    self.assertDoesNotMatch(
1001      """
1002        /// CHECK-EVAL: not hasIsaFeature('feature1')
1003      """,
1004      """
1005      foo
1006      """,
1007      "some_isa",
1008      ImmutableDict({"feature1": True})
1009    )
1010    self.assertMatches(
1011      """
1012        /// CHECK-IF: hasIsaFeature('feature2')
1013        ///   CHECK: bar1
1014        /// CHECK-ELSE:
1015        ///   CHECK: bar2
1016        /// CHECK-FI:
1017      """,
1018      """
1019      foo
1020      bar1
1021      """,
1022      "some_isa",
1023      ImmutableDict({"feature1": False, "feature2": True})
1024    )
1025
1026  def test_readBarrierType(self):
1027    # CheckEval assertions with no read barrier
1028    self.assertMatches(
1029        """
1030          /// CHECK-EVAL: readBarrierType('none')
1031        """,
1032        """
1033        foo
1034        """,
1035        None,
1036        read_barrier_type="none"
1037    )
1038    self.assertDoesNotMatch(
1039        """
1040          /// CHECK-EVAL: readBarrierType('none')
1041        """,
1042        """
1043        foo
1044        """,
1045        None,
1046        read_barrier_type="baker"
1047    )
1048    self.assertDoesNotMatch(
1049        """
1050          /// CHECK-EVAL: readBarrierType('none')
1051        """,
1052        """
1053        foo
1054        """,
1055        None,
1056        read_barrier_type="tablelookup"
1057    )
1058
1059    # CheckEval assertions with "baker" read barrier
1060    self.assertMatches(
1061        """
1062          /// CHECK-EVAL: readBarrierType('baker')
1063        """,
1064        """
1065        foo
1066        """,
1067        None,
1068        read_barrier_type="baker"
1069    )
1070    self.assertDoesNotMatch(
1071        """
1072          /// CHECK-EVAL: readBarrierType('baker')
1073        """,
1074        """
1075        foo
1076        """,
1077        None,
1078        read_barrier_type="none"
1079    )
1080    self.assertDoesNotMatch(
1081        """
1082          /// CHECK-EVAL: readBarrierType('baker')
1083        """,
1084        """
1085        foo
1086        """,
1087        None,
1088        read_barrier_type="tablelookup"
1089    )
1090
1091    # CheckEval assertions with "tablelookup" read barrier
1092    self.assertMatches(
1093        """
1094          /// CHECK-EVAL: readBarrierType('tablelookup')
1095        """,
1096        """
1097        foo
1098        """,
1099        None,
1100        read_barrier_type="tablelookup"
1101    )
1102    self.assertDoesNotMatch(
1103        """
1104          /// CHECK-EVAL: readBarrierType('tablelookup')
1105        """,
1106        """
1107        foo
1108        """,
1109        None,
1110        read_barrier_type="none"
1111    )
1112    self.assertDoesNotMatch(
1113        """
1114          /// CHECK-EVAL: readBarrierType('tablelookup')
1115        """,
1116        """
1117        foo
1118        """,
1119        None,
1120        read_barrier_type="baker"
1121    )
1122
1123    # CheckIf assertions with no read barrier
1124    self.assertMatches(
1125      """
1126        /// CHECK-IF: readBarrierType('none')
1127        ///   CHECK: bar1
1128        /// CHECK-ELSE:
1129        ///   CHECK: bar2
1130        /// CHECK-FI:
1131      """,
1132      """
1133      foo
1134      bar1
1135      """,
1136      None,
1137      read_barrier_type="none"
1138    )
1139    self.assertMatches(
1140      """
1141        /// CHECK-IF: not readBarrierType('none')
1142        ///   CHECK: bar1
1143        /// CHECK-ELSE:
1144        ///   CHECK: bar2
1145        /// CHECK-FI:
1146      """,
1147      """
1148      foo
1149      bar2
1150      """,
1151      None,
1152      read_barrier_type="none"
1153    )
1154
1155    # CheckIf assertions with 'baker' read barrier
1156    self.assertMatches(
1157        """
1158        /// CHECK-IF: readBarrierType('baker')
1159        ///   CHECK: bar1
1160        /// CHECK-ELSE:
1161        ///   CHECK: bar2
1162        /// CHECK-FI:
1163        """,
1164        """
1165        foo
1166        bar1
1167        """,
1168        None,
1169        read_barrier_type="baker"
1170    )
1171    self.assertMatches(
1172        """
1173        /// CHECK-IF: not readBarrierType('baker')
1174        ///   CHECK: bar1
1175        /// CHECK-ELSE:
1176        ///   CHECK: bar2
1177        /// CHECK-FI:
1178        """,
1179        """
1180        foo
1181        bar2
1182        """,
1183        None,
1184        read_barrier_type="baker"
1185    )
1186
1187    # CheckIf assertions with 'tablelookup' read barrier
1188    self.assertMatches(
1189        """
1190        /// CHECK-IF: readBarrierType('tablelookup')
1191        ///   CHECK: bar1
1192        /// CHECK-ELSE:
1193        ///   CHECK: bar2
1194        /// CHECK-FI:
1195        """,
1196        """
1197        foo
1198        bar1
1199        """,
1200        None,
1201        read_barrier_type="tablelookup"
1202    )
1203    self.assertMatches(
1204        """
1205        /// CHECK-IF: not readBarrierType('tablelookup')
1206        ///   CHECK: bar1
1207        /// CHECK-ELSE:
1208        ///   CHECK: bar2
1209        /// CHECK-FI:
1210        """,
1211        """
1212        foo
1213        bar2
1214        """,
1215        None,
1216        read_barrier_type="tablelookup"
1217    )
1218