def accept(f): if getattr(f, RULE_MARKER, None) or getattr(f, INITIALIZE_RULE_MARKER, None): raise InvalidDefinition( "A function cannot be used for both a rule and an invariant.", Settings.default, ) existing_invariant = getattr(f, INVARIANT_MARKER, None) if existing_invariant is not None: raise InvalidDefinition( "A function cannot be used for two distinct invariants.", Settings.default, ) preconditions = getattr(f, PRECONDITIONS_MARKER, ()) invar = Invariant( function=f, preconditions=preconditions, check_during_init=check_during_init, ) @proxies(f) def invariant_wrapper(*args, **kwargs): return f(*args, **kwargs) setattr(invariant_wrapper, INVARIANT_MARKER, invar) return invariant_wrapper
def accept(f): if getattr(f, INVARIANT_MARKER, None): raise InvalidDefinition( "A function cannot be used for both a rule and an invariant.", Settings.default, ) existing_rule = getattr(f, RULE_MARKER, None) existing_initialize_rule = getattr(f, INITIALIZE_RULE_MARKER, None) if existing_rule is not None or existing_initialize_rule is not None: raise InvalidDefinition( "A function cannot be used for two distinct rules. ", Settings.default) preconditions = getattr(f, PRECONDITIONS_MARKER, ()) rule = Rule( targets=converted_targets, arguments=kwargs, function=f, preconditions=preconditions, ) @proxies(f) def rule_wrapper(*args, **kwargs): return f(*args, **kwargs) setattr(rule_wrapper, RULE_MARKER, rule) return rule_wrapper
def accept(f): existing_rule = getattr(f, RULE_MARKER, None) existing_initialize_rule = getattr(f, INITIALIZE_RULE_MARKER, None) if existing_rule is not None or existing_initialize_rule is not None: raise InvalidDefinition( "A function cannot be used for two distinct rules. ", Settings.default) precondition = getattr(f, PRECONDITION_MARKER, None) if precondition: raise InvalidDefinition( "An initialization rule cannot have a precondition. ", Settings.default) rule = Rule( targets=converted_targets, arguments=kwargs, function=f, precondition=precondition, ) @proxies(f) def rule_wrapper(*args, **kwargs): return f(*args, **kwargs) setattr(rule_wrapper, INITIALIZE_RULE_MARKER, rule) return rule_wrapper
def steps(self): # Pick initialize rules first if self._initialize_rules_to_run: return one_of([ tuples(just(rule), fixed_dictionaries(rule.arguments)) for rule in self._initialize_rules_to_run ]) # All initialize rules has been run once, go with the regular rules strategies = [] for rule in self.rules(): converted_arguments = {} valid = True if rule.precondition and not rule.precondition(self): continue for k, v in sorted(rule.arguments.items()): if isinstance(v, Bundle): bundle = self.bundle(v.name) if not bundle: valid = False break v = BundleReferenceStrategy(v.name) converted_arguments[k] = v if valid: strategies.append( tuples(just(rule), fixed_dictionaries(converted_arguments))) if not strategies: raise InvalidDefinition(u'No progress can be made from state %r' % (self, )) return one_of(strategies)
def decorator(f): @proxies(f) def precondition_wrapper(*args, **kwargs): return f(*args, **kwargs) existing_initialize_rule = getattr(f, INITIALIZE_RULE_MARKER, None) if existing_initialize_rule is not None: raise InvalidDefinition( "An initialization rule cannot have a precondition. ", Settings.default) rule = getattr(f, RULE_MARKER, None) invariant = getattr(f, INVARIANT_MARKER, None) if rule is not None: assert invariant is None new_rule = attr.evolve(rule, preconditions=rule.preconditions + (precond, )) setattr(precondition_wrapper, RULE_MARKER, new_rule) elif invariant is not None: assert rule is None new_invariant = attr.evolve(invariant, preconditions=invariant.preconditions + (precond, )) setattr(precondition_wrapper, INVARIANT_MARKER, new_invariant) else: setattr( precondition_wrapper, PRECONDITIONS_MARKER, getattr(f, PRECONDITIONS_MARKER, ()) + (precond, ), ) return precondition_wrapper
def steps(self): strategies = [] for rule in self.rules(): converted_arguments = {} valid = True if rule.precondition and not rule.precondition(self): continue for k, v in sorted(rule.arguments.items()): if isinstance(v, Bundle): bundle = self.bundle(v.name) if not bundle: valid = False break converted_arguments[k] = v if valid: strategies.append(TupleStrategy(( just(rule), FixedKeysDictStrategy(converted_arguments) ), tuple)) if not strategies: raise InvalidDefinition( u'No progress can be made from state %r' % (self,) ) for name, bundle in self.bundles.items(): if len(bundle) > 1: strategies.append( builds( ShuffleBundle, just(name), lists(integers(0, len(bundle) - 1)))) return one_of(strategies)
def decorator(f): @proxies(f) def precondition_wrapper(*args, **kwargs): return f(*args, **kwargs) existing_initialize_rule = getattr(f, INITIALIZE_RULE_MARKER, None) if existing_initialize_rule is not None: raise InvalidDefinition( "An initialization rule cannot have a precondition. ", Settings.default) rule = getattr(f, RULE_MARKER, None) if rule is None: setattr(precondition_wrapper, PRECONDITION_MARKER, precond) else: new_rule = Rule( targets=rule.targets, arguments=rule.arguments, function=rule.function, precondition=precond, ) setattr(precondition_wrapper, RULE_MARKER, new_rule) invariant = getattr(f, INVARIANT_MARKER, None) if invariant is not None: new_invariant = Invariant(function=invariant.function, precondition=precond) setattr(precondition_wrapper, INVARIANT_MARKER, new_invariant) return precondition_wrapper
def steps(self): strategies = [] for rule in self.rules(): converted_arguments = {} valid = True if rule.precondition is not None and not rule.precondition(self): continue for k, v in sorted(rule.arguments.items()): if isinstance(v, Bundle): bundle = self.bundle(v.name) if not bundle: valid = False break else: v = sampled_from(bundle) converted_arguments[k] = v if valid: strategies.append( TupleStrategy((just(rule), FixedKeysDictStrategy(converted_arguments)), tuple)) if not strategies: raise InvalidDefinition(u'No progress can be made from state %r' % (self, )) return one_of(*strategies)
def __init__(self): if not self.rules(): raise InvalidDefinition(u'Type %s defines no rules' % (type(self).__name__, )) self.bundles = {} self.name_counter = 1 self.names_to_values = {}
def do_draw(self, data): try: rule = data.draw(st.sampled_from(self.rules).filter(self.is_valid)) except HypothesisException: # FailedHealthCheck or UnsatisfiedAssumption depending on user settings. msg = u"No progress can be made from state %r" % (self.machine, ) quiet_raise(InvalidDefinition(msg)) return (rule, data.draw(rule.arguments_strategy))
def __init__(self): if not self.rules(): raise InvalidDefinition(u'Type %s defines no rules' % (type(self).__name__, )) self.bundles = {} # type: Dict[Text, list] self.name_counter = 1 self.names_to_values = {} # type: Dict[Text, Any] self.__stream = CUnicodeIO() self.__printer = RepresentationPrinter(self.__stream)
def __init__(self): if not self.rules(): raise InvalidDefinition("Type %s defines no rules" % (type(self).__name__,)) self.bundles = {} # type: Dict[str, list] self.name_counter = 1 self.names_to_values = {} # type: Dict[str, Any] self.__stream = StringIO() self.__printer = RepresentationPrinter(self.__stream) self._initialize_rules_to_run = copy(self.initialize_rules()) self._rules_strategy = RuleStrategy(self)
def accept(f): existing_invariant = getattr(f, INVARIANT_MARKER, None) if existing_invariant is not None: raise InvalidDefinition( "A function cannot be used for two distinct invariants.", Settings.default, ) precondition = getattr(f, PRECONDITION_MARKER, None) rule = Invariant(function=f, precondition=precondition) @proxies(f) def invariant_wrapper(*args, **kwargs): return f(*args, **kwargs) setattr(invariant_wrapper, INVARIANT_MARKER, rule) return invariant_wrapper
def accept(f): existing_rule = getattr(f, RULE_MARKER, None) if existing_rule is not None: raise InvalidDefinition( 'A function cannot be used for two distinct rules. ', Settings.default, ) precondition = getattr(f, PRECONDITION_MARKER, None) rule = Rule(targets=tuple(converted_targets), arguments=kwargs, function=f, precondition=precondition) @proxies(f) def rule_wrapper(*args, **kwargs): return f(*args, **kwargs) setattr(rule_wrapper, RULE_MARKER, rule) return rule_wrapper
def do_draw(self, data): if not any(self.is_valid(rule) for rule in self.rules): msg = "No progress can be made from state %r" % (self.machine, ) raise InvalidDefinition(msg) from None feature_flags = data.draw(self.enabled_rules_strategy) # Note: The order of the filters here is actually quite important, # because checking is_enabled makes choices, so increases the size of # the choice sequence. This means that if we are in a case where many # rules are invalid we will make a lot more choices if we ask if they # are enabled before we ask if they are valid, so our test cases will # be artificially large. rule = data.draw( st.sampled_from(self.rules).filter(self.is_valid).filter( lambda r: feature_flags.is_enabled(r.function.__name__))) return (rule, data.draw(rule.arguments_strategy))
def do_draw(self, data): # This strategy is slightly strange in its implementation. # We don't want the interpretation of the rule we draw to change based # on whether other rules satisfy their preconditions or have data in # their bundles. Therefore the index into the rule list needs to stay # stable. BUT we don't want to draw invalid rules. So what we do is we # draw an index. We *could* just loop until it's valid, but if most # rules are invalid then that could result in a very long loop. # So what we do is the following: # # 1. We first draw a rule unconditionally, and check if it's valid. # If it is, great. Nothing more to do, that's our rule. # 2. If it is invalid, we now calculate the list of valid rules and # draw from that list (if there are none, that's an error in the # definition of the machine and we complain to the user about it). # 3. Once we've drawn a valid rule, we write that back to the byte # stream. As a result, when shrinking runs the shrinker can delete # the initial failed draw + the draw that lead to us finding an # index into valid_rules, leaving just the written value of i. # When this is run, it will look as we got lucky and just happened # to pick a valid rule. # # Easy, right? n = len(self.rules) i = cu.integer_range(data, 0, n - 1) u, v = data.blocks[-1] block_length = v - u rule = self.rules[i] if not self.is_valid(rule): valid_rules = [ j for j, r in enumerate(self.rules) if self.is_valid(r) ] if not valid_rules: raise InvalidDefinition( u'No progress can be made from state %r' % (self.machine, )) i = valid_rules[cu.integer_range(data, 0, len(valid_rules) - 1)] data.write(int_to_bytes(i, block_length)) rule = self.rules[i] return (rule, data.draw(rule.arguments_strategy))
def steps(self): strategies = [] for rule in self.rules(): converted_arguments = {} valid = True for k, v in rule.arguments.items(): if isinstance(v, Bundle): bundle = self.bundle(v.name) if not bundle: valid = False break else: v = SimpleSampledFromStrategy(bundle) converted_arguments[k] = v if valid: strategies.append( TupleStrategy((JustStrategy(rule), FixedKeysDictStrategy(converted_arguments)), tuple)) if not strategies: raise InvalidDefinition('No progress can be made from state %r' % (self, )) return one_of_strategies(strategies)
def do_draw(self, data): if not any(self.is_valid(rule) for rule in self.rules): msg = u"No progress can be made from state %r" % (self.machine,) quiet_raise(InvalidDefinition(msg)) rule = data.draw(st.sampled_from(self.rules).filter(self.is_valid)) return (rule, data.draw(rule.arguments_strategy))