add code for skipping test cases
authorJacob Lifshay <programmerjake@gmail.com>
Wed, 29 Jul 2020 00:23:02 +0000 (17:23 -0700)
committerJacob Lifshay <programmerjake@gmail.com>
Wed, 29 Jul 2020 00:23:02 +0000 (17:23 -0700)
src/soc/fu/spr/test/test_pipe_caller.py
src/soc/fu/test/common.py

index 47a9e6c131ef5cf072668f77a125c81cf78bcaa7..b3452ca8d6dbda9edc09075f5b5ca86cad7376bb 100644 (file)
@@ -13,7 +13,8 @@ from soc.config.endian import bigendian
 from soc.consts import MSR
 
 
-from soc.fu.test.common import (TestAccumulatorBase, TestCase, ALUHelpers)
+from soc.fu.test.common import (
+    TestAccumulatorBase, skip_case, TestCase, ALUHelpers)
 from soc.fu.spr.pipeline import SPRBasePipe
 from soc.fu.spr.pipe_data import SPRPipeSpec
 import random
@@ -83,7 +84,7 @@ class SPRTestCase(TestAccumulatorBase):
         initial_sprs = {'SRR0': 0x12345678, 'SRR1': 0x5678, 'LR': 0x1234,
                         'XER': 0xe00c0000}
         self.add_case(Program(lst, bigendian),
-                             initial_regs, initial_sprs)
+                      initial_regs, initial_sprs)
 
     def case_1_mtspr(self):
         lst = ["mtspr 26, 1",  # SRR0
@@ -98,7 +99,7 @@ class SPRTestCase(TestAccumulatorBase):
         initial_sprs = {'SRR0': 0x12345678, 'SRR1': 0x5678, 'LR': 0x1234,
                         'XER': 0x0}
         self.add_case(Program(lst, bigendian),
-                             initial_regs, initial_sprs)
+                      initial_regs, initial_sprs)
 
     def case_2_mtspr_mfspr(self):
         lst = ["mtspr 26, 1",  # SRR0
@@ -117,11 +118,11 @@ class SPRTestCase(TestAccumulatorBase):
         initial_sprs = {'SRR0': 0x12345678, 'SRR1': 0x5678, 'LR': 0x1234,
                         'XER': 0x0}
         self.add_case(Program(lst, bigendian),
-                             initial_regs, initial_sprs)
+                      initial_regs, initial_sprs)
 
     # TODO XXX whoops...
-    #@unittest.skip("spr does not have TRAP in it. has to be done another way")
-    def _skip_case_3_mtspr_priv(self):
+    @skip_case("spr does not have TRAP in it. has to be done another way")
+    def case_3_mtspr_priv(self):
         lst = ["mtspr 26, 1",  # SRR0
                "mtspr 27, 2",  # SRR1
                "mtspr 1, 3",  # XER
@@ -135,7 +136,7 @@ class SPRTestCase(TestAccumulatorBase):
                         'XER': 0x0}
         msr = 1 << MSR.PR
         self.add_case(Program(lst, bigendian),
-                             initial_regs, initial_sprs, initial_msr=msr)
+                      initial_regs, initial_sprs, initial_msr=msr)
 
     def case_ilang(self):
         pspec = SPRPipeSpec(id_wid=2)
index 6d6181d7ebf1cc5aa78f6d8dbe8ff5d72ae43fca..d1473b052a1e7567495f5087aa1a58937f07b192 100644 (file)
@@ -4,10 +4,73 @@ Bugreports:
 """
 
 import inspect
+import functools
+import types
 from soc.decoder.power_enums import XER_bits, CryIn, spr_dict
 from soc.regfile.util import fast_reg_to_spr  # HACK!
 from soc.regfile.regfiles import FastRegs
 
+
+class SkipCase(Exception):
+    """Raise this exception to skip a test case.
+
+    Usually you'd use one of the skip_case* decorators.
+
+    For use with TestAccumulatorBase
+    """
+
+
+def _id(obj):
+    """identity function"""
+    return obj
+
+
+def skip_case(reason):
+    """
+    Unconditionally skip a test case.
+
+    Use like:
+        @skip_case("my reason for skipping")
+        def case_abc(self):
+            ...
+    or:
+        @skip_case
+        def case_def(self):
+            ...
+
+    For use with TestAccumulatorBase
+    """
+    def decorator(item):
+        assert not isinstance(item, type), \
+            "can't use skip_case to decorate types"
+
+        @functools.wraps(item)
+        def wrapper(*args, **kwargs):
+            raise SkipCase(reason)
+        return wrapper
+    if isinstance(reason, types.FunctionType):
+        item = reason
+        reason = ""
+        return decorator(item)
+    return decorator
+
+
+def skip_case_if(condition, reason):
+    """
+    Conditionally skip a test case.
+
+    Use like:
+        @skip_case_if(should_i_skip(), "my reason for skipping")
+        def case_abc(self):
+            ...
+
+    For use with TestAccumulatorBase
+    """
+    if condition:
+        return skip_case(reason)
+    return _id
+
+
 class TestAccumulatorBase:
 
     def __init__(self):
@@ -17,14 +80,20 @@ class TestAccumulatorBase:
         # we need a different system
         for n, v in self.__class__.__dict__.items():
             if n.startswith("case_") and callable(v):
-                v(self)
+                try:
+                    v(self)
+                except SkipCase as e:
+                    # TODO(programmerjake): translate to final test sending
+                    # skip signal to unittest. for now, just print the skipped
+                    # reason and ignore
+                    print(f"SKIPPED({n}):", str(e))
 
     def add_case(self, prog, initial_regs=None, initial_sprs=None,
-                        initial_cr=0, initial_msr=0,
-                        initial_mem=None):
+                 initial_cr=0, initial_msr=0,
+                 initial_mem=None):
 
-        test_name = inspect.stack()[1][3] # name of caller of this function
-        tc = TestCase(prog, test_name, 
+        test_name = inspect.stack()[1][3]  # name of caller of this function
+        tc = TestCase(prog, test_name,
                       regs=initial_regs, sprs=initial_sprs, cr=initial_cr,
                       msr=initial_msr,
                       mem=initial_mem)