diff --git a/integration/test_hypothesis_happiness.py b/integration/test_hypothesis_happiness.py new file mode 100644 index 000000000..83c91ecdd --- /dev/null +++ b/integration/test_hypothesis_happiness.py @@ -0,0 +1,22 @@ +# -*- coding: utf-8 -*- + +from twisted.trial import unittest +from hypothesis import given +from hypothesis.strategies import text, sets +from allmydata.immutable import happiness_upload + + +class Happiness(unittest.TestCase): + + @given(sets(elements=text(min_size=1), min_size=4, max_size=4), sets(elements=text(min_size=1), min_size=4)) + def test_hypothesis_unhappy(self, peers, shares): + """ + similar to test_unhappy we test that the resulting happiness is always 4 since the size of peers is 4. + """ + # https://hypothesis.readthedocs.io/en/latest/data.html#hypothesis.strategies.sets + # hypothesis.strategies.sets(elements=None, min_size=None, average_size=None, max_size=None)[source] + readonly_peers = set() + peers_to_shares = {} + places = happiness_upload.share_placement(peers, readonly_peers, shares, peers_to_shares) + happiness = happiness_upload.calculate_happiness(places) + self.assertEqual(4, happiness) diff --git a/setup.py b/setup.py index f54a6daf9..86a19e82d 100644 --- a/setup.py +++ b/setup.py @@ -284,6 +284,7 @@ setup(name="tahoe-lafs", # also set in __init__.py "txi2p >= 0.3.2", # in case pip's resolver doesn't work "pytest", "pytest-twisted", + "hypothesis >= 3.6.1", ], "tor": [ "foolscap[tor] >= 0.12.5", diff --git a/src/allmydata/interfaces.py b/src/allmydata/interfaces.py index 171f63bcd..7ba5323cd 100644 --- a/src/allmydata/interfaces.py +++ b/src/allmydata/interfaces.py @@ -796,7 +796,7 @@ class IPeerSelector(Interface): I return whether the share assignments I'm currently using reflect a healthy file, based on my internal definitions. """ - + def needs_recomputation(): """ I return True if the share assignments I last returned may have diff --git a/src/allmydata/test/test_happiness.py b/src/allmydata/test/test_happiness.py index 4fc72ee00..3ebefc3a5 100644 --- a/src/allmydata/test/test_happiness.py +++ b/src/allmydata/test/test_happiness.py @@ -31,25 +31,21 @@ class Happiness(unittest.TestCase): def test_placement_simple(self): shares = {'share0', 'share1', 'share2'} - peers = { - 'peer0', - 'peer1', - } + peers = {'peer0', 'peer1'} readonly_peers = {'peer0'} peers_to_shares = { 'peer0': {'share2'}, 'peer1': [], } - places0 = happiness_upload.share_placement(peers, readonly_peers, shares, peers_to_shares) + places = happiness_upload.share_placement(peers, readonly_peers, shares, peers_to_shares) if False: - print("places0") - for k, v in places0.items(): + for k, v in places.items(): print(" {} -> {}".format(k, v)) self.assertEqual( - places0, + places, { 'share0': {'peer1'}, 'share1': {'peer1'}, @@ -86,7 +82,7 @@ class Happiness(unittest.TestCase): 'peerB': set(), } - places0 = happiness_upload.share_placement(peers, readonly_peers, shares, peers_to_shares) + places = happiness_upload.share_placement(peers, readonly_peers, shares, peers_to_shares) # share N maps to peer N # i.e. this says that share0 should be on peer0, share1 should @@ -95,10 +91,9 @@ class Happiness(unittest.TestCase): 'share{}'.format(i): {'peer{}'.format(i)} for i in range(10) } - self.assertEqual(expected, places0) + self.assertEqual(expected, places) def test_unhappy(self): - shares = { 'share1', 'share2', 'share3', 'share4', 'share5', } @@ -106,9 +101,7 @@ class Happiness(unittest.TestCase): 'peer1', 'peer2', 'peer3', 'peer4', } readonly_peers = set() - peers_to_shares = { - } - + peers_to_shares = {} places = happiness_upload.share_placement(peers, readonly_peers, shares, peers_to_shares) happiness = happiness_upload.calculate_happiness(places) self.assertEqual(4, happiness) diff --git a/src/allmydata/util/happinessutil.py b/src/allmydata/util/happinessutil.py index c5bc03330..3e49dd560 100644 --- a/src/allmydata/util/happinessutil.py +++ b/src/allmydata/util/happinessutil.py @@ -4,10 +4,7 @@ reporting it in messages """ from copy import deepcopy -from allmydata.immutable.happiness_upload import share_placement -from allmydata.immutable.happiness_upload import calculate_happiness from allmydata.immutable.happiness_upload import residual_network -from allmydata.immutable.happiness_upload import bfs from allmydata.immutable.happiness_upload import augmenting_path_for