def test_execute(self): """ Listing squares should return a list of all the things in the world which are squares. It should include their coordinates and number of each kind of thing inside them. """ world = World(MagicMock()) s1 = world.create('square')['id'] s2 = world.create('square')['id'] world.setAttr(s2, 'coordinates', (0, 1)) thing1 = world.create('thing')['id'] Move(thing1, s2).execute(world) output = ListSquares(thing1).execute(world) self.assertIn( { 'id': s1, 'kind': 'square', 'coordinates': None, 'contents': {}, }, output) self.assertIn( { 'id': s2, 'kind': 'square', 'coordinates': (0, 1), 'contents': { 'thing': 1, } }, output) self.assertEqual(len(output), 2)
def test_execute(self): """ Listing squares should return a list of all the things in the world which are squares. It should include their coordinates and number of each kind of thing inside them. """ world = World(MagicMock()) s1 = world.create('square')['id'] s2 = world.create('square')['id'] world.setAttr(s2, 'coordinates', (0, 1)) thing1 = world.create('thing')['id'] Move(thing1, s2).execute(world) output = ListSquares(thing1).execute(world) self.assertIn({ 'id': s1, 'kind': 'square', 'coordinates': None, 'contents': {}, }, output) self.assertIn({ 'id': s2, 'kind': 'square', 'coordinates': (0, 1), 'contents': { 'thing': 1, } }, output) self.assertEqual(len(output), 2)
def test_makeSecondTool(self): """ If you make a tool from a different piece of ore, your existing tool is unequipped and the lifesource it was made from is reverted to ore. """ world = World(MagicMock()) ore1 = world.create('ore') ore2 = world.create('ore') bot = world.create('bot') MakeTool(bot['id'], ore1['id'], 'knife').execute(world) MakeTool(bot['id'], ore2['id'], 'butterfly net').execute(world) self.assertEqual(bot['tool'], 'butterfly net', "Should equip the new tool") self.assertEqual(ore1['kind'], 'ore', "Should revert to ore") self.assertEqual(ore2['kind'], 'lifesource') # kill original world.setAttr(ore1['id'], 'hp', 0) self.assertEqual( bot['tool'], 'butterfly net', "should not change tool" " when the original ore dies") self.assertEqual(ore2['kind'], 'lifesource')
def test_execute(self): """ Locking something should increase the number of 'locks' on the thing. """ world = World(MagicMock()) thing = world.create('thing')['id'] box = world.create('box') AddLock(thing, box['id']).execute(world) self.assertEqual(box['locks'], 1)
def test_onlyOre(self): """ Only ore can be turned into tools. """ world = World(MagicMock()) ore = world.create('flower') bot = world.create('bot') self.assertRaises(NotAllowed, MakeTool(bot['id'], ore['id'], 'knife').execute, world)
def test_stayAbove0(self): """ You can't damage something below 0 by shooting. """ world = World(MagicMock()) thing = world.create('foo') target = world.create('foo') world.setAttr(target['id'], 'hp', 30) Shoot(thing['id'], target['id'], 500).execute(world) self.assertEqual(target['hp'], 0, "Should reduce the hitpoints to 0")
def test_execute(self): """ Shooting something should reduce its hitpoints by the given amount. """ world = World(MagicMock()) thing = world.create('foo') target = world.create('foo') world.setAttr(target['id'], 'hp', 30) Shoot(thing['id'], target['id'], 10).execute(world) self.assertEqual(target['hp'], 20, "Should reduce the hitpoints")
def test_invulnerable(self): """ You can't shoot something that is invulnerable. """ world = World(MagicMock()) thing = world.create('foo') target = world.create('foo') self.assertRaises(Invulnerable, Shoot(thing['id'], target['id'], 500).execute, world) world.setAttr(target['id'], 'hp', None) self.assertRaises(Invulnerable, Shoot(thing['id'], target['id'], 500).execute, world)
def test_onlyBotsCanExecute(self): """ Only bots can execute commands. """ world = World(MagicMock()) rules = StandardRules() bot = world.create('bot')['id'] rules.isAllowed(world, action.ListSquares(bot)) nonbot = world.create('foo')['id'] self.assertRaises(NotAllowed, rules.isAllowed, world, action.ListSquares(nonbot))
def test_execute(self): """ Repairing something should increas the number of hitpoints on that thing. """ world = World(MagicMock()) thing = world.create('foo') target = world.create('foo') world.setAttr(target['id'], 'hp', 30) Repair(thing['id'], target['id'], 10).execute(world) self.assertEqual(target['hp'], 40, "Should increase the hitpoints")
def test_emit_oneEventAtATime(self): """ Only one event should be emitted at a time. If an event emission causes another event to be emitted, it should be appended to a queue and be emitted after the current event is finished. """ world = World(MagicMock()) obj1 = world.create('foo')['id'] obj2 = world.create('foo')['id'] obj3 = world.create('foo')['id'] obj1_received = [] world.receiveFor(obj1, obj1_received.append) obj2_received = [] world.receiveFor(obj2, obj2_received.append) obj3_received = [] world.receiveFor(obj3, obj3_received.append) # obj1 will emit to # obj2 and obj3 world.subscribeTo(obj1, world.receiverFor(obj2)) world.subscribeTo(obj1, world.receiverFor(obj3)) # obj2 will emit to # obj1 and obj3 world.subscribeTo(obj2, world.receiverFor(obj1)) world.subscribeTo(obj2, world.receiverFor(obj3)) # 1_ # /|\ # / \ # |/_ _\| # 3 <---- 2 # obj2 will emit "obj2" every time he receives an event def noisy(_): world.emit('obj2', obj2) world.receiveFor(obj2, noisy) # If things are working properly, then obj3 will receive # the 'obj2' emissions AFTER it receives the event from obj1 world.emit('obj1', obj1) self.assertEqual(obj1_received, ['obj1', 'obj2'], "obj1 should receive obj1 from self, then obj2") self.assertEqual(obj2_received, ['obj1', 'obj2'], "obj2 should receive obj1, then obj2 from self") self.assertEqual(obj3_received, ['obj1', 'obj2'], "obj3 should receiver obj1 first, then obj2")
def test_execute_inRoom(self): """ If an object is already located in another container, then moving it should: - Unsubscribe from the location's events - Unsubscribe the location from the thing's events - Cause C{contents} to be updated. """ world = World(MagicMock()) thing = world.create('thing')['id'] room1 = world.create('room1')['id'] room2 = world.create('room2')['id'] move1 = Move(thing, room1) move1.execute(world) move2 = Move(thing, room2) move2.execute(world) room1_called = [] world.receiveFor(room1, room1_called.append) room2_called = [] world.receiveFor(room2, room2_called.append) thing_called = [] world.receiveFor(thing, thing_called.append) # emit from room1 world.emit('foo', room1) self.assertEqual(thing_called, [], "Thing should detach from previous " "room events") room1_called.pop() # emit from thing world.emit('bar', thing) self.assertEqual(thing_called, ['bar'], "Thing should see own events") self.assertEqual(room1_called, [], "Room1 should detach from thing" " events") # room1 contents room1_obj = world.get(room1) self.assertEqual(room1_obj['contents'], [], "Should remove from " "contents of room1") location = world.get(thing)['location'] self.assertEqual( location, room2, "Should update the " "location of the thing. This is mostly to confirm " "that the default moving behavior tested in the other " "test happened.")
def test_inLocation(self): """ Should list the things in my location """ world = World(MagicMock()) room = world.create('foo') thing = world.create('thing') other = world.create('thing') Move(thing['id'], room['id']).execute(world) Move(other['id'], room['id']).execute(world) r = Look(thing['id']).execute(world) self.assertEqual(set(r), set([thing['id'], other['id']]))
def test_destroy_disableSubscribers(self): """ When an object is destroyed, things subscribed to its events will no longer receive events. """ world = World(MagicMock()) thing = world.create('foo') received = [] world.receiveFor(thing['id'], received.append) emitted = [] world.subscribeTo(thing['id'], emitted.append) receiver = world.receiverFor(thing['id']) emitter = world.emitterFor(thing['id']) world.destroy(thing['id']) received.pop() emitted.pop() receiver('foo') self.assertEqual(received, []) self.assertEqual(emitted, []) emitter('foo') self.assertEqual(received, []) self.assertEqual(emitted, [])
def test_execute_energyRequired_command_fails(self): """ If there is energy required and the command fails to run, the energy should not be consumed. """ e = self.friendlyEngine() # require some energy e.engine.energyRequirement.return_value = 2 # make some energy world = World(MagicMock()) actor = world.create('thing') yield Charge(actor['id']).execute(world) yield Charge(actor['id']).execute(world) self.assertEqual(len(actor['energy']), 2) # do the action and consume the energy action = MagicMock() action.subject.return_value = actor['id'] # synchronous action.execute.side_effect = NotAllowed('foo') self.assertFailure(e.execute(world, action), NotAllowed) self.assertEqual(len(actor['energy']), 2, "Should not have consumed " "the energy") # asynchronous action.execute.side_effect = None action.execute.return_value = defer.fail(NotAllowed('foo')) self.assertFailure(e.execute(world, action), NotAllowed) self.assertEqual(len(actor['energy']), 2, "Should not have consumed " "the energy")
def test_share(self): """ Sharing energy should result in the energy being removed from the giver's energy pool and added to the receiver's energy pool. """ world = World(MagicMock()) giver = world.create('thing') receiver = world.create('thing') Charge(giver['id']).execute(world) ShareEnergy(giver['id'], receiver['id'], 1).execute(world) self.assertEqual(len(giver['energy']), 0, "Should deplete giver's energy") self.assertEqual(len(receiver['energy']), 1, "Should increase receiver's energy")
def test_emit_receiveOnce(self): """ Events should only be received by each object once. """ world = World(MagicMock()) obj1 = world.create('foo')['id'] obj2 = world.create('foo')['id'] obj1_received = [] world.receiveFor(obj1, obj1_received.append) obj2_received = [] world.receiveFor(obj2, obj2_received.append) # obj1 emits everything it receives world.receiveFor(obj1, world.emitterFor(obj1)) # obj2 emits everything it receives world.receiveFor(obj2, world.emitterFor(obj2)) # obj2 receives emissions from obj1 world.subscribeTo(obj1, world.receiverFor(obj2)) # obj1 receives emissions from obj2 world.subscribeTo(obj2, world.receiverFor(obj1)) # we have a nice loop set up. When this test fails, it is likely to # continue spinning forever. world.emit('echo', obj1) self.assertEqual(obj1_received, ['echo'], "Should have received the " "message once") self.assertEqual(obj2_received, ['echo'], "Should have received the " "message once")
def test_failIfNotOnBoard(self): """ The following actions require a bot to be on the board. """ world = World(MagicMock()) rules = StandardRules() bot = world.create('bot')['id'] actions = [ action.Charge(bot), action.ShareEnergy(bot, 'foo', 2), action.ConsumeEnergy(bot, 2), action.Shoot(bot, 'foo', 1), action.Repair(bot, 'foo', 1), action.MakeTool(bot, 'foo', 'foo'), action.OpenPortal(bot, 'foo', 'foo'), action.AddLock(bot, 'foo'), action.BreakLock(bot, 'foo'), action.LookAt(bot, 'foo'), ] for a in actions: try: rules.isAllowed(world, a) except NotAllowed: pass else: self.fail("You must be on a square to do %r" % (a, ))
def test_execute_energyRequired_succeed(self): """ If energy is required and the actor has enough energy, do the action. """ e = self.friendlyEngine() # require some energy e.engine.energyRequirement.return_value = 2 # make some energy world = World(MagicMock()) actor = world.create('thing') yield Charge(actor['id']).execute(world) yield Charge(actor['id']).execute(world) self.assertEqual(len(actor['energy']), 2) # do the action and consume the energy action = MagicMock() action.subject.return_value = actor['id'] action.execute.return_value = 'foo' ret = yield e.execute(world, action) self.assertEqual(ret, 'foo', "Should have executed the action") self.assertEqual(len(actor['energy']), 0, "Should have consumed " "the energy")
def test_portal_user_noMatch(self): """ It is NotAllowed to use a portal with a portal_user different than the thing trying to use the portal. """ world = World(MagicMock()) place = world.create('place') ore = world.create('ore') bot = world.create('bot') lander = world.create('lander') imposter = world.create('imposter') Move(ore['id'], place['id']).execute(world) OpenPortal(bot['id'], ore['id'], lander['id']).execute(world) self.assertRaises(NotAllowed, UsePortal(imposter['id'], ore['id']).execute, world)
def test_execute(self): """ Breaking a lock will reduce the number of locks on a thing. It can't be reduced below 0, though. """ world = World(MagicMock()) thing = world.create('thing')['id'] box = world.create('box') AddLock(thing, box['id']).execute(world) BreakLock(thing, box['id']).execute(world) self.assertEqual(box['locks'], 0) # make sure it doesn't go negative BreakLock(thing, box['id']).execute(world) self.assertEqual(box['locks'], 0, "It can't have a negative number " "of locks")
def test_create_uniqueId(self): """ The id of an object should be unique """ world = World(MagicMock()) o1 = world.create('foo') o2 = world.create('bar') self.assertNotEqual(o1['id'], o2['id'])
def test_get(self): """ You can get objects. """ world = World(MagicMock()) obj = world.create('foo') obj2 = world.get(obj['id']) self.assertEqual(obj, obj2)
def test_invalidLocation(self): """ It is an error to move to a non-entity. """ world = World(MagicMock()) thing = world.create('thing')['id'] self.assertRaises(NotAllowed, Move(thing, 4).execute, world)
def test_nowhere(self): """ If you are nowhere, return an empty list. """ world = World(MagicMock()) thing = world.create('thing') self.assertEqual(Look(thing['id']).execute(world), [])
def test_badPassword(self): auth = FileStoredPasswords(self.mktemp()) world = World(MagicMock(), auth=auth) thing = world.create('thing') yield CreateTeam(thing['id'], 'teamA', 'password').execute(world) self.assertFailure( JoinTeam(thing['id'], 'teamA', 'not password').execute(world), BadPassword)
def test_basic(self): """ Should return information about the object. """ world = World(MagicMock()) thing = world.create('thing') r = LookAt(thing['id'], thing['id']).execute(world) self.assertEqual(r, world.get(thing['id']))
def test_thingsInTheSameRoom(self): """ Things in the same location should see events emitted by each other. """ world = World(MagicMock()) room = world.create('a')['id'] thing1 = world.create('thing')['id'] thing2 = world.create('thing')['id'] Move(thing1, room).execute(world) Move(thing2, room).execute(world) c1 = [] world.receiveFor(thing1, c1.append) c2 = [] world.receiveFor(thing2, c2.append) world.emit('foo', thing1) self.assertEqual(c1, ['foo']) self.assertEqual(c2, ['foo'])
def test_sharedEnergy_destroyed(self): """ When shared energy is destroyed, it should be removed from the energy pool of whoever has it and still decrement the creator's created_energy amount. """ world = World(MagicMock()) giver = world.create('thing') receiver = world.create('thing') Charge(giver['id']).execute(world) ShareEnergy(giver['id'], receiver['id'], 1).execute(world) e = receiver['energy'][0] world.destroy(e) self.assertEqual(giver['created_energy'], 0, "Should decrement creator's created count") self.assertEqual(len(receiver['energy']), 0, "Should deplete receiver's energy")
def test_execute(self): """ Should set the team name if the password matches. """ auth = FileStoredPasswords(self.mktemp()) world = World(MagicMock(), auth=auth) thing = world.create('thing') yield CreateTeam(thing['id'], 'teamA', 'password').execute(world) yield JoinTeam(thing['id'], 'teamA', 'password').execute(world) self.assertEqual(thing['team'], 'teamA')
def test_execute(self): """ Moving to a new location should: - Cause C{location} to be updated - Cause C{contents} to be updated - Subscribe the thing to the location's events - Subscribe the location to the thing's events """ world = World(MagicMock()) thing = world.create('thing') room = world.create('room') move = Move(thing['id'], room['id']) move.execute(world) self.assertEqual(thing['location'], room['id'], "Should set location") self.assertEqual(room['contents'], [thing['id']], "Should set contents") room_called = [] world.receiveFor(room['id'], room_called.append) thing_called = [] world.receiveFor(thing['id'], thing_called.append) world.emit('foo', room['id']) self.assertEqual(room_called, ['foo'], "Room should receive room events") self.assertEqual(thing_called, ['foo'], "Thing should receive room events") room_called.pop() thing_called.pop() world.emit('foo', thing['id']) self.assertEqual(room_called, ['foo'], "Room should receive thing events") self.assertEqual(thing_called, ['foo'], "Thing should receive thing events")