def test_resultReceived_invalidPath(self): """ If a result is received that was computed using arguments that don't correspond to a valid path in the garden, don't send the input on. """ store = InMemoryStore() store.put(Data('joe', 'money', '1', 'xxxx', 'lots')) garden = Garden() garden.addPath('happiness', '1', [ ('cake', '1'), ]) receiver = FakeReceiver([IResult]) f = InvalidResultFilter(garden, store) ISource(f).subscribe(receiver) r = f.resultReceived(Result('joe', 'happiness', '1', 'bbbb', 'yes', [ ('money', '1', 'xxxx', sha1('lots').hexdigest()), ])) self.assertEqual(receiver.receive.call_count, 0, "Should not " "send the result on, because money doesn't produce " "happiness in this garden. Only cake does that") self.assertTrue(r.called)
def test_dataReceived(self): """ Should store the data, then call doPossibleWork for all destinations for which the received data is an input. """ garden = Garden() garden.addPath('cake', '1', [ ('eggs', '1'), ('flour', '1'), ]) garden.addPath('german pancake', '1', [ ('eggs', '1'), ('flour', '1'), ]) w = WorkMaker(garden, None) w.doPossibleWork = create_autospec(w.doPossibleWork, side_effect=(lambda *x: defer.succeed(['hey']))) r = w.dataReceived(Data('Frog', 'flour', '1', 'bbbb', 'flour value')) w.doPossibleWork.assert_has_calls([ call('Frog', 'cake', '1'), call('Frog', 'german pancake', '1'), ]) self.assertTrue(r.called) return r
def test_resultReceived_hashcheck(self): """ When a result is received, it is only accepted if the inputs on which it is based are still valid. """ store = InMemoryStore() store.put(Data('joe', 'cake', '1', 'xxxx', 'chocolate')) garden = Garden() garden.addPath('happiness', '1', [ ('cake', '1'), ]) receiver = FakeReceiver([IResult]) f = InvalidResultFilter(garden, store) ISource(f).subscribe(receiver) # receive a result not based on the correct input value r = f.resultReceived(Result('joe', 'happiness', '1', 'bbbb', 'yes', [ ('cake', '1', 'xxxx', sha1('vanilla').hexdigest()), ])) self.assertEqual(receiver.receive.call_count, 0, "Should not " "have passed the result on") self.assertTrue(r.called) # receive a valid result (based on the current input value) result = Result('joe', 'happiness', '1', 'bbbb', 'yes', [ ('cake', '1', 'xxxx', sha1('chocolate').hexdigest()), ]) r = f.resultReceived(result) receiver.receive.assert_called_once_with(result) self.assertTrue(self.successResultOf(r))
def test_addPath_oneStepAwayCycle(self): """ It's illegal to add a destination that depends on something that depends on the first. """ g = Garden() g.addPath('chicken', 'v1', [ ('egg', 'v1'), ]) self.assertRaises(CycleError, g.addPath, 'egg', 'v1', [ ('chicken', 'v1'), ])
def test_addPath(self): """ You can add paths to a Garden. """ g = Garden() g.addPath('foo', 'v1', [ ('bar', 'a'), ('cow', 'b'), ]) self.assertEqual(list(g.pathsRequiring('bar', 'a')), [('foo', 'v1')]) self.assertEqual(list(g.pathsRequiring('cow', 'b')), [('foo', 'v1')]) self.assertEqual(list(g.inputsFor('foo', 'v1')), [ [('bar', 'a'), ('cow', 'b')] ])
def test_addPath_distantCycle(self): """ It's illegal to create a cycle, even if the paths are far removed. """ g = Garden() g.addPath('a', 'v1', [ ('b', 'v1'), ]) g.addPath('b', 'v1', [ ('c', 'v1'), ]) self.assertRaises(CycleError, g.addPath, 'c', 'v1', [ ('a', 'v1'), ])
def test_dataReceived_errorFetchingData(self): """ If there's an error getting data for computing, the whole call should fail """ store = InMemoryStore() store.get = create_autospec(store.get, side_effect=lambda *a: defer.fail(Exception('foo'))) garden = Garden() garden.addPath('cake', '1', [ ('eggs', '1'), ]) w = WorkMaker(garden, store) r = w.dataReceived(Data('Jim', 'eggs', '1', 'xxxx', 'value')) self.assertFailure(r, Exception) return r.addErrback(lambda x:None)
def mkCakeSetup(self): store = InMemoryStore() store = InMemoryStore() garden = Garden() garden.addPath('cake', '1', [ ('eggs', '1'), ('flour', '1'), ]) garden.addPath('cake', '1', [ ('eggs', '1'), ('flour', 'new'), ]) receiver = FakeReceiver([IWork]) w = WorkMaker(garden, store) ISource(w).subscribe(receiver) return store, garden, w, receiver
def test_dataReceived_errorReceiving(self): """ If the work_receiver errsback on receiving any of the pieces of work, the whole dataReceived call should also errback. """ store = InMemoryStore() store.put(Data('Jim', 'eggs', '1', 'xxxx', 'value')) garden = Garden() garden.addPath('cake', '1', [ ('eggs', '1'), ]) garden.addPath('cake', '2', [ ('eggs', '1'), ]) receiver = FakeReceiver([IWork], lambda x: defer.fail(Exception('foo'))) w = WorkMaker(garden, store) ISource(w).subscribe(receiver) r = w.dataReceived(Data('Jim', 'eggs', '1', 'xxxx', 'value')) self.assertFailure(r, Exception)
def test_addPath_addCycleInMiddle(self): """ Adding a path in the middle that will cause a Cycle should be detected """ # a --> b --> c --> d --> a # add b --> c last g = Garden() g.addPath('d', 'v1', [ ('c', 'v1'), ]) g.addPath('b', 'v1', [ ('a', 'v1'), ]) g.addPath('a', 'v1', [ ('d', 'v1'), ]) self.assertRaises(CycleError, g.addPath, 'c', 'v1', [ ('b', 'v1'), ])