6     """Something asserted to be true during the test. 
    8     A given condition may be used as a precondition or a 
   12         """Called with a key and a state.  True if the condition is met.""" 
   16     """The affect an action will perform.""" 
   19         """Called with a key and a state. 
   21         The effect modifies the state as appropriate.""" 
   24     """Actions are the operations that will be permuted into test cases. 
   26     Each action has a collection of preconditions and postconditions 
   27     that will be evaluated for checking input and output state for the 
   30     Action.preconditions is the collection of conditions that must all 
   31     be true upon input to the action.  If any condition is not true, 
   32     the effect is not executed and the action state is considered 
   35     Action.effect is the callable that is expected to alter the state 
   36     to satisfy the postconditions of the action. 
   38     Action.postconditions is the collection of conditions that must 
   39     all be true after the effect of the action completes. 
   49         """The name of this action (default derived from class name)""" 
   50         n = self.__class__.__name__
 
   51         return n[0].lower() + n[1:]
 
   54     """The driver "performs" the test.""" 
   57         """Initialize and return the state for a test.""" 
   61         """Invoked with the sequence of tests before any are run.""" 
   64         """Invoked with the sequence of actions in a single test 
   65         before it is performed.""" 
   68         """Invoked when before starting an action.""" 
   71         """Invoked after the action is performed.""" 
   74         """Invoked at the end of a sequence of tests.""" 
   77         """Invoked with the sequence of tests after all of them are run.""" 
   79 def runTest(actions, driver, duplicates=3, length=4):
 
   80     """Run a test with the given collection of actions and driver. 
   82     The optional argument `duplicates' specifies how many times a 
   83     given action may be duplicated in a sequence. 
   85     The optional argument `length` specifies how long each test 
   89     instances = itertools.chain(*itertools.repeat([a() 
for a 
in actions],
 
   91     tests = set(itertools.permutations(instances, length))
 
   92     driver.preSuite(tests)
 
   93     for seq 
in sorted(tests):
 
   94         state = driver.newState()
 
   95         driver.startSequence(seq)
 
   98             haserror = 
not all(p(state) 
for p 
in a.preconditions)
 
  102                     haserror = 
not all(p(state) 
for p 
in a.postconditions)
 
  105             driver.endAction(a, state, haserror)
 
  106         driver.endSequence(seq, state)
 
  107     driver.postSuite(tests)
 
  109 def findActions(classes):
 
  110     """Helper function to extract action subclasses from a collection 
  114     for __t 
in (t 
for t 
in classes 
if isinstance(type, 
type(t))):
 
  115         if Action 
in __t.__mro__ 
and __t != Action 
and __t.enabled: