def freePool(request, hosts, monkeypatch): monkeypatch.setattr(globallock, "assertLocked", lambda: True) _freePool = FreePool(hosts) for host in hosts.all(): monkeypatch.setattr(host, 'setDestroyCallback', lambda x: None, raising=False) _freePool.put(host) return _freePool
def setUp(self): self.addCleanup(globallock._lock.release) globallock._lock.acquire() self.currentTimer = None self.currentTimerTag = None timer.scheduleIn = self.scheduleTimerIn timer.cancelAllByTag = self.cancelAllTimersByTag requirements = dict(node0=dict(imageHint='alpha-bravo', imageLabel='tango-lima'), node1=dict(imageHint='charlie-delta', imageLabel='kilo-juliet'), node2=dict(imageHint='echo-foxtrot', imageLabel='zooloo-papa')) self.index = random.randint(1, sys.maxint) self.allocationInfo = 'This allocation has got swag.' allocated = dict((hostName, HostStateMachine(Host(hostName))) for hostName in requirements.keys()) self.originalAllocated = copy.copy(allocated) self.expectedStates = dict(allocatedButNotInaugurated=set(allocated.values()), inaugurated=set()) self.expectedDestroyed = set() self.expectedDetached = set() self.expectedReleased = set() self.wasAllocationDoneAtSomePoint = False self.broadcaster.reset_mock() self.hosts = Hosts() self.freepool = FreePool(self.hosts) for stateMachine in allocated.values(): self.hosts.add(stateMachine) self.tested = allocation.Allocation(self.index, requirements, self.allocationInfo, allocated, self.broadcaster, self.freepool, self.hosts)
def setUp(self): globallock._lock.acquire() self._hosts = Hosts() self.tested = FreePool(self._hosts)
class Test(unittest.TestCase): def setUp(self): globallock._lock.acquire() self._hosts = Hosts() self.tested = FreePool(self._hosts) def tearDown(self): globallock._lock.release() def test_OneHost(self): host = HostStateMachine('host1') self.tested.put(host) self.assertIn(host, self.tested.all()) self.tested.takeOut(host) self.assertNotIn(host, self.tested.all()) def test_DestroyCallback(self): host = HostStateMachine('host1') self._hosts.add(host) self.tested.put(host) host._destroyCallback(host) self.assertNotIn(host, self.tested.all()) def test_All(self): hosts = [HostStateMachine(str(i)) for i in xrange(10)] for host in hosts: self._hosts.add(host) for host in hosts: self.tested.put(host) actualAll = self.tested.all() self.assertEquals(set(actualAll), set(hosts))
class Test(unittest.TestCase): @classmethod def setUpClass(cls): cls.broadcaster = Publish() def setUp(self): self.addCleanup(globallock._lock.release) globallock._lock.acquire() self.currentTimer = None self.currentTimerTag = None timer.scheduleIn = self.scheduleTimerIn timer.cancelAllByTag = self.cancelAllTimersByTag requirements = dict(node0=dict(imageHint='alpha-bravo', imageLabel='tango-lima'), node1=dict(imageHint='charlie-delta', imageLabel='kilo-juliet'), node2=dict(imageHint='echo-foxtrot', imageLabel='zooloo-papa')) self.index = random.randint(1, sys.maxint) self.allocationInfo = 'This allocation has got swag.' allocated = dict((hostName, HostStateMachine(Host(hostName))) for hostName in requirements.keys()) self.originalAllocated = copy.copy(allocated) self.expectedStates = dict(allocatedButNotInaugurated=set(allocated.values()), inaugurated=set()) self.expectedDestroyed = set() self.expectedDetached = set() self.expectedReleased = set() self.wasAllocationDoneAtSomePoint = False self.broadcaster.reset_mock() self.hosts = Hosts() self.freepool = FreePool(self.hosts) for stateMachine in allocated.values(): self.hosts.add(stateMachine) self.tested = allocation.Allocation(self.index, requirements, self.allocationInfo, allocated, self.broadcaster, self.freepool, self.hosts) def test_Index(self): self.assertEquals(self.tested.index(), self.index) def test_AllocationInfo(self): self.assertEquals(self.allocationInfo, self.tested.allocationInfo()) def test_InauguratedWhenNotDoneRaisesAssertionError(self): self.assertRaises(AssertionError, self.tested.inaugurated) def test_InauguratedWhenDone(self): self.fakeInaugurationDoneForAll() expected = {stateMachine.hostImplementation().id(): stateMachine for stateMachine in self.expectedStates["inaugurated"]} self.assertEquals(expected, self.tested.inaugurated()) def test_Allocated(self): self.assertEquals(self.originalAllocated, self.tested.allocated()) def test_Free(self): self.tested.free() self.assertEquals(self.tested.dead(), "freed") self.validate() def test_CantFreeDeadAllocation(self): self.tested.free() self.assertEquals(self.tested.dead(), "freed") self.assertRaises(Exception, self.tested.free) self.validate() def test_Withdraw(self): self.tested.withdraw("Don't want this allocation anymore") self.assertEquals(self.tested.dead(), "withdrawn") self.validate() def test_HeartBeatWhenDeadDoesNothing(self): self.assertIsNotNone(self.currentTimer) self.tested.free() self.assertIsNone(self.currentTimer) self.tested.heartbeat() self.assertIsNone(self.currentTimer) self.validate() def test_NotDeadForAWhileIfNotDead(self): self.assertFalse(self.tested.deadForAWhile()) def test_NoCrashWhenGotMoreThanOneInaugurationDoneForSameMachine(self): self.fakeInaugurationDoneForAll() self.fakeInaugurationDoneForAll() self.fakeInaugurationDoneForAll() self.fakeInaugurationDoneForAll() self.fakeInaugurationDoneForAll() def test_DeadForAWhile(self): self.tested.free() executeCodeWhileAllocationIsDeadOfHeartbeatTimeout(self.tested, lambda: None) def test_NotDeadForAWhile(self): orig_time = time.time self.tested.free() timeInWhichAllocationIsDeadNotForAWhile = \ time.time() + self.tested._LIMBO_AFTER_DEATH_DURATION * 0.9 try: time.time = mock.Mock(return_value=timeInWhichAllocationIsDeadNotForAWhile) self.assertFalse(self.tested.deadForAWhile()) finally: time.time = orig_time def test_HeartBeatTimeout(self): self.currentTimer() self.assertEquals(self.tested.dead(), "heartbeat timeout") self.validate() def test_DieUponSelfDestructionOfMachine(self): self.destroyMachineByName('node0') self.assertIn("Unable to inaugurate ", self.tested.dead()) self.validate() def test_NoCrashIfStateMachineSelfDestructedWhileAllocationIsDead(self): machine = self.originalAllocated['node0'] destroyCallback = machine._destroyCallback stateChangeCallback = self.originalAllocated['node0']._destroyCallback self.tested.free() self.assertEquals(self.tested.dead(), "freed") self.validate() machine.setDestroyCallback(destroyCallback) self.destroyMachineByName('node0') machine.setDestroyCallback(None) self.freepool.takeOut(machine) # todo: fix the following (which is a bug); The state machine should unassign in case it deetroys # itself. machine.assign(stateChangeCallback, None, None) self.validate() def test_DetachHostBeforeInaugurated(self): machine = self.originalAllocated['node0'] self.detachHost(machine) self.validate() self.fakeInaugurationDoneForAll() self.validate() def test_DetachHostAfterInaugurated(self): machine = self.originalAllocated['node0'] self.fakeInaugurationDoneForAll() self.validate() self.detachHost(machine) self.validate() def test_CannotDetachHostAfterDestroyed(self): machine = self.originalAllocated['node0'] self.destroyMachineByName('node0') self.validate() self.assertRaises(Exception, self.tested.detachHost, machine) self.validate() def test_CannotDetachHostAfterInauguratedAndDestroyed(self): machine = self.originalAllocated['node0'] self.fakeInaugurationDoneForAll() self.assertIn(machine, self.tested.allocated().values()) self.destroyMachineByName('node0') self.validate() self.assertRaises(Exception, self.tested.detachHost, machine) self.validate() def test_CannotDetachUnAllocatedHost(self): machine = HostStateMachine("whatIsThisMachine") self.assertRaises(Exception, self.detachHost, machine) def test_DetachingLastHostKillsAllocation(self): for machine in self.originalAllocated.values(): self.detachHost(machine) self.validate() isDead = self.tested.dead() is not None self.assertTrue(isDead) def test_ReleaseHostBeforeInaugurated(self): machine = self.originalAllocated['node0'] self.releaseHost(machine) self.validate() self.fakeInaugurationDoneForAll() self.validate() def test_ReleaseHostAfterInaugurated(self): machine = self.originalAllocated['node0'] self.fakeInaugurationDoneForAll() self.validate() self.releaseHost(machine) self.validate() def test_CannotRelaseHostAfterDestroyed(self): machine = self.originalAllocated['node0'] self.destroyMachineByName('node0') self.validate() self.assertRaises(Exception, self.tested.releaseHost, machine) self.validate() def test_CannotReleaseHostAfterInauguratedAndDestroyed(self): machine = self.originalAllocated['node0'] self.fakeInaugurationDoneForAll() self.assertIn(machine, self.tested.allocated().values()) self.destroyMachineByName('node0') self.validate() self.assertRaises(Exception, self.tested.releaseHost, machine) self.validate() def test_CannotReleaseUnAllocatedHost(self): machine = HostStateMachine("whatIsThisMachine") self.assertRaises(Exception, self.releaseHost, machine) def test_ReleasingLastHostKillsAllocation(self): for machine in self.originalAllocated.values(): self.releaseHost(machine) self.validate() isDead = self.tested.dead() is not None self.assertTrue(isDead) def test_CannotReleaseDetachedHost(self): machine = self.originalAllocated['node0'] self.detachHost(machine) self.assertRaises(Exception, self.releaseHost, machine) def test_CannotDetachReleasedHost(self): machine = self.originalAllocated['node0'] self.releaseHost(machine) self.assertRaises(Exception, self.detachHost, machine) def test_AllocationCreationReported(self): self.validateBroadcastCalls() def test_AllocationDoneBroadcasted(self): self.fakeInaugurationDoneForAll() self.validateBroadcastCalls() def test_AllocationDeathBroadcasted(self): self.fakeInaugurationDoneForAll() self.tested.free() self.validateBroadcastCalls() def fakeInaugurationDoneForAll(self): self.wasAllocationDoneAtSomePoint = True collection = self.expectedStates["allocatedButNotInaugurated"] for stateMachine in self.originalAllocated.values(): stateMachine.fakeInaugurationDone() if stateMachine in collection: collection.remove(stateMachine) self.expectedStates["inaugurated"].add(stateMachine) def scheduleTimerIn(self, timeout, callback, tag): self.assertIs(self.currentTimer, None) self.assertIs(self.currentTimerTag, None) self.currentTimer = callback self.currentTimerTag = tag def cancelAllTimersByTag(self, tag): if self.currentTimerTag is not None: self.assertIsNot(self.currentTimer, None) self.assertIs(self.currentTimerTag, tag) self.currentTimer = None self.currentTimerTag = None def _validateFreePool(self): isDead = self.tested.dead() is not None expectedHostsInFreePool = set() if isDead: expectedHostsInFreePool = self.expectedStates["allocatedButNotInaugurated"].union( self.expectedStates["inaugurated"]).union(self.expectedReleased) else: expectedHostsInFreePool = self.expectedReleased expectedHostsInFreePool = [host for host in expectedHostsInFreePool if host not in self.expectedDestroyed] for stateMachine in expectedHostsInFreePool: self.assertIn(stateMachine, self.freepool.all()) expectedHostsNotInFreePool = [stateMachine for stateMachine in self.originalAllocated.values() if stateMachine not in expectedHostsInFreePool] for stateMachine in expectedHostsNotInFreePool: self.assertNotIn(stateMachine, self.freepool.all()) def _validateAllocated(self): actual = self.tested.allocated() expected = self.expectedStates["allocatedButNotInaugurated"] isDead = self.tested.dead() is not None if not isDead: expected = expected.union(self.expectedStates["inaugurated"]) expected = {stateMachine.hostImplementation().id(): stateMachine for stateMachine in expected} self.assertEquals(expected, actual) def _validateInaugurated(self): isDead = self.tested.dead() is not None if isDead: self.assertRaises(AssertionError, self.tested.inaugurated) else: if self.tested.done(): expected = {stateMachine.hostImplementation().id(): stateMachine for stateMachine in self.expectedStates["inaugurated"]} self.assertEquals(self.tested.inaugurated(), expected) else: self.assertRaises(AssertionError, self.tested.inaugurated) def validateBroadcastCalls(self): expectedMethodsNames = list() expectedMethodsNames.append("allocationCreated") if self.wasAllocationDoneAtSomePoint: expectedMethodsNames.append("allocationDone") deathReason = self.tested.dead() if deathReason is not None: expectedMethodsNames.append("allocationDied") expectedMethodsNames.append("cleanupAllocationPublishResources") actualCalls = \ [call for call in self.broadcaster.method_calls if call[0] != "allocationProviderMessage"] while expectedMethodsNames: expectedMethodName = expectedMethodsNames.pop(0) actualCall = actualCalls.pop(0) actualMethodName = actualCall[0] args = actualCall[1] kwargs = actualCall[2] if expectedMethodName == "allocationCreated": allocationID = kwargs["allocationID"] expectedAllocate = {name: self.originalAllocated[name].hostImplementation().id() for name in self.originalAllocated} elif expectedMethodName == "allocationDone": allocationID = args[0] elif expectedMethodName == "allocationDied": allocationID = args[0] reason = kwargs["reason"] self.assertEquals(self.tested.dead(), reason) elif expectedMethodName == "cleanupAllocationPublishResources": allocationID = args[0] else: self.assertTrue(False) self.assertEquals(allocationID, self.tested.index()) self.assertEquals(actualMethodName, expectedMethodName) self.assertFalse(actualCalls) def _validateDone(self): isDead = self.tested.dead() is not None if isDead: self.assertRaises(AssertionError, self.tested.done) else: allowedNotToBeInaugurated = self.expectedDetached expected = \ self.expectedStates["allocatedButNotInaugurated"].issubset(allowedNotToBeInaugurated) actual = self.tested.done() self.assertEquals(expected, actual) def _validateHosts(self): hosts = self.hosts.all() notExpected = self.expectedDestroyed.union(self.expectedDetached) for host in notExpected: self.assertNotIn(host, hosts) expected = [host for host in self.originalAllocated.values() if host not in notExpected] for host in expected: self.assertIn(host, hosts) def validateAllocationIsNotEmpty(self): self.assertTrue(self.tested.allocated()) def validate(self): self._validateAllocated() self._validateInaugurated() self._validateFreePool() self._validateHosts() self._validateDone() isDead = self.tested.dead() is not None if not isDead: self.validateAllocationIsNotEmpty() self.validateBroadcastCalls() def destroyMachineByName(self, name): stateMachine = self.originalAllocated[name] stateMachine.destroy() self.expectedDestroyed.add(stateMachine) def detachHost(self, machine): self.tested.detachHost(machine) self._removeFromCollections(machine) self.expectedDetached.add(machine) def releaseHost(self, machine): self.tested.releaseHost(machine) self._removeFromCollections(machine) self.expectedReleased.add(machine) def _removeFromCollections(self, machine): for collection in self.expectedStates.values(): if machine in collection: collection.remove(machine)