def __get__(self, obj, type=None): if obj is None: return self else: try: result = obj.__dict__[self.name] # This is a gross hack, but it preserves the old behaviour that # you can change the storage directory and it will be reflected # in the default database. if self.name == "database" and result is not_set: from hypothesis.database import ExampleDatabase result = ExampleDatabase(not_set) return result except KeyError: raise AttributeError(self.name)
def test_will_find_a_failure_from_the_database(): db = ExampleDatabase() class Rejected(Exception): pass @given(Foo, settings=Settings(max_examples=10, database=db)) def nope(x): print(x) raise Rejected() try: with pytest.raises(Rejected): nope() # pragma: no branch finally: db.close()
def test_terminates_shrinks(n): db = ExampleDatabase(':memory:') runner = ConjectureRunner(slow_shrinker(), settings=settings( max_examples=5000, max_iterations=10000, max_shrinks=n, database=db, timeout=unlimited, ), random=Random(0), database_key=b'key') runner.run() assert runner.last_data.status == Status.INTERESTING assert runner.shrinks == n in_db = set(v for vs in db.data.values() for v in vs) assert len(in_db) == n + 1
def database(self): """An ExampleDatabase instance to use for storage of examples. May be None. If this was explicitly set at Settings instantiation then that value will be used (even if it was None). If not and the database_file setting is not None this will be lazily loaded as an SQLite backed ExampleDatabase using that file the first time this property is accessed. """ if self._database is not_set and self.database_file is not None: from hypothesis.database import ExampleDatabase from hypothesis.database.backend import SQLiteBackend self._database = databases.get(self.database_file) or ( ExampleDatabase(backend=SQLiteBackend(self.database_file))) databases[self.database_file] = self._database return self._database
def __init__(self, parent=None, **kwargs): # type: (settings, **Any) -> None if (kwargs.get("database", not_set) is not_set and kwargs.get("database_file", not_set) is not not_set): if kwargs["database_file"] is None: kwargs["database"] = None else: from hypothesis.database import ExampleDatabase kwargs["database"] = ExampleDatabase(kwargs["database_file"]) if not kwargs.get("perform_health_check", True): kwargs["suppress_health_check"] = HealthCheck.all() if kwargs.get("max_shrinks") == 0: kwargs["phases"] = tuple( p for p in _validate_phases(kwargs.get("phases")) if p != Phase.shrink) self._construction_complete = False deprecations = [] defaults = parent or settings.default if defaults is not None: for setting in all_settings.values(): if kwargs.get(setting.name, not_set) is not_set: kwargs[setting.name] = getattr(defaults, setting.name) else: if kwargs[setting.name] != setting.future_default: if setting.deprecation_message is not None: deprecations.append(setting) if setting.validator: kwargs[setting.name] = setting.validator( kwargs[setting.name]) for name, value in kwargs.items(): if name not in all_settings: raise InvalidArgument( "Invalid argument: %r is not a valid setting" % (name, )) setattr(self, name, value) self.storage = threading.local() self._construction_complete = True for d in deprecations: note_deprecation( d.deprecation_message, since=d.deprecated_since, verbosity=self.verbosity, )
def database(self): """An ExampleDatabase instance to use for storage of examples. May be None. If this was explicitly set at settings instantiation then that value will be used (even if it was None). If not and the database_file setting is not None this will be lazily loaded as an ExampleDatabase, using that file the first time that this property is accessed on a particular thread. """ if self._database is not_set and self.database_file is not None: from hypothesis.database import ExampleDatabase if self.database_file not in _db_cache: _db_cache[self.database_file] = (ExampleDatabase( self.database_file)) return _db_cache[self.database_file] if self._database is not_set: self._database = None return self._database
def test_verifier_deduplicates_on_coming_out_of_the_database(): db = ExampleDatabase() storage = db.storage_for((frozenset({int}), )) db.backend.save(storage.key, '[1, 2, 3]') db.backend.save(storage.key, '[3, 2, 1]') counter = Counter() calls = [] good = frozenset({1, 2, 3}) def count_and_object(x): counter[x] += 1 if not calls: calls.append(x) return x == good verifier = Verifier(settings=hs.Settings(database=db)) verifier.falsify(count_and_object, frozenset({int})) assert calls[0] == good assert counter[good] == 1
def test_stops_after_max_iterations_when_reading(): key = b'key' max_iterations = 1 db = ExampleDatabase(':memory:') for i in range(10): db.save(key, hbytes([i])) seen = [] def f(data): seen.append(data.draw_bytes(1)) data.mark_invalid() runner = ConjectureRunner(f, settings=settings( max_examples=1, max_iterations=max_iterations, database=db, ), database_key=key) runner.run() assert len(seen) == max_iterations
def test_storage_does_not_return_things_not_matching_strategy(): table = StrategyTable() strategy = JustStrategy(PickyStrategyLazyFormat()) strategy.could_have_produced = lambda *args: False table.define_specification_for(PickyStrategyLazyFormat, lambda s, d: strategy) converters = ConverterTable(strategy_table=table) converters.define_specification_for( PickyStrategyLazyFormat, lambda s, d: JustConverter(PickyStrategyLazyFormat())) database = ExampleDatabase( converters=converters, backend=SQLiteBackend(), ) stor = database.storage_for(PickyStrategyLazyFormat) database.backend.save(stor.key, 'null') assert list(database.backend.fetch(stor.key)) != [] assert list(stor.fetch()) == [] assert list(database.backend.fetch(stor.key)) == []
def test_saves_data_while_shrinking(): key = b'hi there' n = 5 db = ExampleDatabase(':memory:') assert list(db.fetch(key)) == [] seen = set() def f(data): x = data.draw_bytes(512) if sum(x) >= 5000 and len(seen) < n: seen.add(hbytes(x)) if hbytes(x) in seen: data.mark_interesting() runner = TestRunner(f, settings=settings(database=db), database_key=key) runner.run() assert runner.last_data.status == Status.INTERESTING assert len(seen) == n in_db = set(db.fetch(key)) assert in_db.issubset(seen) assert in_db == seen
def test_stops_after_max_iterations_when_generating(): key = b'key' value = b'rubber baby buggy bumpers' max_iterations = 100 db = ExampleDatabase(':memory:') db.save(key, value) seen = [] def f(data): seen.append(data.draw_bytes(len(value))) data.mark_invalid() runner = ConjectureRunner(f, settings=settings( max_examples=1, max_iterations=max_iterations, database=db, ), database_key=key) runner.run() assert len(seen) == max_iterations assert value in seen
def test_stability(): @given( st.lists(st.text(max_size=1), unique=True, min_size=5), st.choices(), ) @settings(database=ExampleDatabase()) def test_choose_and_then_fail(ls, choice): for _ in hrange(100): choice(ls) assert False with capture_out() as o: with raises(AssertionError): test_choose_and_then_fail() out1 = o.getvalue() with capture_out() as o: with raises(AssertionError): test_choose_and_then_fail() out2 = o.getvalue() assert out1 == out2 assert 'Choice #100:' in out1
def test_can_handle_more_than_max_examples_values_in_db(): """This is checking that if we store a large number of examples in the DB and then subsequently reduce max_examples below that count, we a) don't error (which is how this bug was found) and b) stop at max_examples rather than continuing onwards.""" db = ExampleDatabase() try: settings = hs.settings(database=db, max_examples=10) seen = [] first = [True] for _ in range(10): first[0] = True @given(integers()) @settings def test_seen(x): if x not in seen: if first[0]: first[0] = False seen.append(x) assert x in seen try: test_seen() except AssertionError: pass assert len(seen) >= 2 seen = [] @given(integers()) @hs.settings(max_examples=1, database=db) def test_seen(x): seen.append(x) test_seen() assert len(seen) == 1 finally: db.close()
def test_garbage_collects_the_database(): key = b'hi there' n = 200 db = ExampleDatabase(':memory:') local_settings = settings(database=db, max_shrinks=n, timeout=unlimited) runner = ConjectureRunner(slow_shrinker(), settings=local_settings, database_key=key) runner.run() assert runner.last_data.status == Status.INTERESTING def in_db(): return set(v for vs in db.data.values() for v in vs) assert len(in_db()) == n + 1 runner = ConjectureRunner(lambda data: None, settings=local_settings, database_key=key) runner.run() assert 0 < len(in_db()) < n
def test_garbage_collects_the_database(): key = b'hi there' n = 200 db = ExampleDatabase(':memory:') assert list(db.fetch(key)) == [] seen = set() go = True counter = [0] def f(data): """This function is designed to shrink very badly. So we only occasionally mark things as interesting, and require a certain amount of complexity to do so. """ x = hbytes(data.draw_bytes(512)) if not go: return if counter[0] % 10 == 0 and len(seen) < n and sum(x) > 1000: seen.add(x) counter[0] += 1 if x in seen: data.mark_interesting() local_settings = settings(database=db, max_shrinks=2 * n, timeout=unlimited) runner = ConjectureRunner(f, settings=local_settings, database_key=key) runner.run() assert runner.last_data.status == Status.INTERESTING assert len(seen) == n assert set(db.fetch(key)) == seen go = False runner = ConjectureRunner(f, settings=local_settings, database_key=key) runner.run() assert 0 < len(set(db.fetch(key))) < n
def test_flatmap_retrieve_from_db(): constant_float_lists = floats(0, 1).flatmap(lambda x: lists(just(x))) track = [] db = ExampleDatabase() @given(constant_float_lists, settings=Settings(database=db)) def record_and_test_size(xs): track.append(xs) assert sum(xs) < 1 with pytest.raises(AssertionError): record_and_test_size() assert track example = track[-1] track = [] with pytest.raises(AssertionError): record_and_test_size() assert track[0] == example
def __init__(self, parent=None, **kwargs): # type: (settings, **Any) -> None if ( kwargs.get('database', not_set) is not_set and kwargs.get('database_file', not_set) is not not_set ): if kwargs['database_file'] is None: kwargs['database'] = None else: from hypothesis.database import ExampleDatabase kwargs['database'] = ExampleDatabase(kwargs['database_file']) if not kwargs.get('perform_health_check', True): kwargs['suppress_health_check'] = HealthCheck.all() self._construction_complete = False deprecations = [] defaults = parent or settings.default if defaults is not None: for setting in all_settings.values(): if kwargs.get(setting.name, not_set) is not_set: kwargs[setting.name] = getattr(defaults, setting.name) else: if kwargs[setting.name] != setting.future_default: if setting.deprecation_message is not None: deprecations.append(setting) if setting.validator: kwargs[setting.name] = setting.validator( kwargs[setting.name]) for name, value in kwargs.items(): if name not in all_settings: raise InvalidArgument( 'Invalid argument: %r is not a valid setting' % (name,)) setattr(self, name, value) self.storage = threading.local() self._construction_complete = True for d in deprecations: note_deprecation(d.deprecation_message, self)