Skip to content

Commit

Permalink
Add new config tuple cache (renatahodovan#34)
Browse files Browse the repository at this point in the history
It uses a dictionary of tuples as the underlying data structure,
contrary to the classic config cache that uses a tree.
  • Loading branch information
akosthekiss authored Jul 14, 2023
1 parent fb51672 commit ef59596
Show file tree
Hide file tree
Showing 3 changed files with 54 additions and 10 deletions.
44 changes: 44 additions & 0 deletions picire/cache.py
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,50 @@ def _str(p):
return ''.join(s)


@CacheRegistry.register('config-tuple')
class ConfigTupleCache(OutcomeCache):
"""
This cache associates configurations (i.e., lists of elements) with their
test outcomes, using a dictionary of tuples as the underlying data
structure.
"""

def __init__(self, *, cache_fail=False, evict_after_fail=True):
"""
:param cache_fail: Add configurations with FAIL outcome to the cache.
:param evict_after_fail: When a configuration with a FAIL outcome is
added to the cache, evict all larger configurations.
"""
# NOTE: evict_after_fail=True should be safe as after a fail is found,
# reduction continues from there, generating only even smaller test
# cases, and larger tests are never re-tested again.
self._cache_fail = cache_fail
self._evict_after_fail = evict_after_fail
self._container = {}

def set_test_builder(self, test_builder):
pass

def add(self, config, result):
if result is Outcome.PASS or self._cache_fail:
self._container[tuple(config)] = result

if result is Outcome.FAIL and self._evict_after_fail:
length = len(config)
evicted = [c for c in self._container if len(c) > length]
for c in evicted:
del self._container[c]

def lookup(self, config):
return self._container.get(tuple(config), None)

def clear(self):
self._container = {}

def __str__(self):
return '{\n%s}' % ''.join(f'\t{c!r}: {r.name!r},\n' for c, r in sorted(self._container.items()))


@CacheRegistry.register('content')
class ContentCache(OutcomeCache):
"""
Expand Down
16 changes: 8 additions & 8 deletions tests/test_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -85,20 +85,20 @@ def _run_picire(self, interesting, config, expect, granularity, dd, split, subse
@pytest.mark.parametrize('split, subset_first, subset_iterator, complement_iterator, cache', [
(picire.splitter.BalancedSplit, True, picire.iterator.forward, picire.iterator.forward, picire.cache.NoCache),
(picire.splitter.ZellerSplit, True, picire.iterator.forward, picire.iterator.backward, picire.cache.ConfigCache),
(picire.splitter.BalancedSplit, False, picire.iterator.backward, picire.iterator.forward, picire.cache.NoCache),
(picire.splitter.ZellerSplit, False, picire.iterator.backward, picire.iterator.backward, picire.cache.ConfigCache),
(picire.splitter.BalancedSplit, True, picire.iterator.skip, picire.iterator.forward, picire.cache.NoCache),
(picire.splitter.ZellerSplit, True, picire.iterator.skip, picire.iterator.backward, picire.cache.ConfigCache),
(picire.splitter.BalancedSplit, False, picire.iterator.backward, picire.iterator.forward, picire.cache.ConfigTupleCache),
(picire.splitter.ZellerSplit, False, picire.iterator.backward, picire.iterator.backward, picire.cache.NoCache),
(picire.splitter.BalancedSplit, True, picire.iterator.skip, picire.iterator.forward, picire.cache.ConfigCache),
(picire.splitter.ZellerSplit, True, picire.iterator.skip, picire.iterator.backward, picire.cache.ConfigTupleCache),
])
def test_dd(self, interesting, config, expect, granularity, split, subset_first, subset_iterator, complement_iterator, cache):
self._run_picire(interesting, config, expect, granularity, picire.DD, split, subset_first, subset_iterator, complement_iterator, cache)

@pytest.mark.parametrize('split, subset_first, subset_iterator, complement_iterator, cache', [
(picire.splitter.ZellerSplit, False, picire.iterator.forward, picire.iterator.forward, picire.cache.ConfigCache),
(picire.splitter.BalancedSplit, False, picire.iterator.forward, picire.iterator.backward, picire.cache.NoCache),
(picire.splitter.ZellerSplit, True, picire.iterator.backward, picire.iterator.forward, picire.cache.ConfigCache),
(picire.splitter.BalancedSplit, True, picire.iterator.backward, picire.iterator.backward, picire.cache.NoCache),
(picire.splitter.ZellerSplit, False, picire.iterator.skip, picire.iterator.forward, picire.cache.ConfigCache),
(picire.splitter.BalancedSplit, False, picire.iterator.forward, picire.iterator.backward, picire.cache.ConfigTupleCache),
(picire.splitter.ZellerSplit, True, picire.iterator.backward, picire.iterator.forward, picire.cache.NoCache),
(picire.splitter.BalancedSplit, True, picire.iterator.backward, picire.iterator.backward, picire.cache.ConfigCache),
(picire.splitter.ZellerSplit, False, picire.iterator.skip, picire.iterator.forward, picire.cache.ConfigTupleCache),
(picire.splitter.BalancedSplit, False, picire.iterator.skip, picire.iterator.backward, picire.cache.NoCache),
])
def test_parallel(self, interesting, config, expect, granularity, split, subset_first, subset_iterator, complement_iterator, cache):
Expand Down
4 changes: 2 additions & 2 deletions tests/test_cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,15 +52,15 @@ def _run_picire(self, test, inp, exp, tmpdir, args):
('--split=balanced', '--subset-iterator=forward', '--complement-iterator=forward', '--cache=config'),
('--split=zeller', '--subset-iterator=forward', '--complement-iterator=backward', '--cache=content'),
('--split=balanced', '--complement-first', '--subset-iterator=backward', '--complement-iterator=forward', '--cache=content-hash'),
('--split=zeller', '--complement-first', '--subset-iterator=backward', '--complement-iterator=backward', '--cache=config', '--cache-fail', '--no-cache-evict-after-fail'),
('--split=zeller', '--complement-first', '--subset-iterator=backward', '--complement-iterator=backward', '--cache=config-tuple', '--cache-fail', '--no-cache-evict-after-fail'),
('--split=balanced', '--subset-iterator=skip', '--complement-iterator=forward', '--cache=content', '--cache-fail', '--no-cache-evict-after-fail'),
('--split=zeller', '--subset-iterator=skip', '--complement-iterator=backward', '--cache=content-hash', '--cache-fail', '--no-cache-evict-after-fail'),
])
def test_dd(self, test, inp, exp, tmpdir, args_atom, args):
self._run_picire(test, inp, exp, tmpdir, args_atom + args)

@pytest.mark.parametrize('args', [
('--split=zeller', '--complement-first', '--subset-iterator=forward', '--complement-iterator=forward', '--cache=config'),
('--split=zeller', '--complement-first', '--subset-iterator=forward', '--complement-iterator=forward', '--cache=config-tuple'),
('--split=balanced', '--complement-first', '--subset-iterator=forward', '--complement-iterator=backward', '--cache=content'),
('--split=zeller', '--subset-iterator=backward', '--complement-iterator=forward', '--cache=content-hash'),
('--split=balanced', '--subset-iterator=backward', '--complement-iterator=backward', '--cache=config', '--cache-fail', '--no-cache-evict-after-fail'),
Expand Down

0 comments on commit ef59596

Please sign in to comment.