def test_register_twice_different_instance(self): '''Register a good username and password twice, from different instances. If a user tries to register a username that is already taken, show them a meaningful error.''' c = clientlib.Client() with self.fresh_servers(): result = c.register(username="******", password="******", email="*****@*****.**") self.assertTrue(result) c = clientlib.Client() with self.assertRaises(clientlib.RegistrationError) as cm: c.register(username="******", password="******", email="*****@*****.**") self.assertIn('User already exists.', cm.exception.message)
def test_scriptserver(self): '''Client can see the ScriptServer updating objects.''' with self.fresh_servers(): c = clientlib.Client(username=settings.DEFAULT_USERNAME, password=settings.DEFAULT_PASSWORD) character = c.create_character('Graxnor') # Override the character's zone: zone = 'playerinstance-AdventureDungeon-%s' % character c.characters[character].zone = zone c.set_online(character) print c.get_objects() linnea = self.get_linnea(c.objects) # Wait a bit for Linnea to wander about. time.sleep(0.1) c.get_objects() updated_linnea = self.get_linnea(c.objects) self.assertTrue(updated_linnea) self.assertNotEqual(linnea, updated_linnea) self.assertNotEqual(linnea['last_modified'], updated_linnea['last_modified']) # Any of the three x, y and z values should not match. matches = any([linnea['loc_%s'%attr] != updated_linnea['loc_%s'%attr] for attr in ('x', 'y', 'z')]) self.assertTrue(matches)
def test_register(self): '''Register with a good username and password.''' c = clientlib.Client() with self.fresh_servers(): result = c.register(username="******", password="******", email="*****@*****.**") self.assertTrue(result) self.assertEqual(c.last_user, "gooduser")
def test_get_zone_url_no_args(self): '''Client can get the url for the last character's zone.''' with self.fresh_servers(): c = clientlib.Client(username=settings.DEFAULT_USERNAME, password=settings.DEFAULT_PASSWORD) self.character = c.create_character('Graxnor') zoneurl = c.get_zone_url() self.assertIn('http', zoneurl)
def test_authenticate_bad(self): '''Authenticating with bad credentials after init does not succeed.''' with self.fresh_servers(): c = clientlib.Client() result = c.authenticate(username='******', password='******') self.assertFalse(result) self.assertFalse(c.cookies)
def test_authenticate_after_auth(self): '''Authenticating after initting Client with auth should work.''' with self.fresh_servers(): c = clientlib.Client(username=settings.DEFAULT_USERNAME, password=settings.DEFAULT_PASSWORD) result = c.authenticate(username=settings.DEFAULT_USERNAME, password=settings.DEFAULT_PASSWORD) self.assertTrue(result) self.assertTrue(c.cookies['user'])
def test_get_objects(self): '''Client can get the objects in our character's zone.''' with self.fresh_servers(): c = clientlib.Client(username=settings.DEFAULT_USERNAME, password=settings.DEFAULT_PASSWORD) self.character = c.create_character('Graxnor') print c.get_objects() self.assertTrue(c.objects) print c.objects
def test_characters(self): '''After authenticating, Client has a dictionary of characters.''' with self.fresh_servers(): c = clientlib.Client(username=settings.DEFAULT_USERNAME, password=settings.DEFAULT_PASSWORD) self.character = c.create_character('Graxnor') self.assertTrue(c.characters) self.assertIn(self.character, c.characters) self.assertTrue(c.characters[self.character])
def test_bad_ping(self): '''Pinging a bogus authserver should return False.''' oldserver = settings.AUTHSERVER clientlib.settings.AUTHSERVER = "http://127.0.0.1:53000" c = clientlib.Client() result = c.ping() self.assertFalse(result) clientlib.settings.AUTHSERVER = oldserver
def test_move_character(self): '''Client can move a character.''' with self.fresh_servers(): c = clientlib.Client(username=settings.DEFAULT_USERNAME, password=settings.DEFAULT_PASSWORD) character = c.create_character('Graxnor') c.set_character_status(character, 'online') result = c.move_character(character, 100, 100, 100) self.assertTrue(result)
def test_set_character_status(self): '''Client can update its objects.''' with self.fresh_servers(): c = clientlib.Client(username=settings.DEFAULT_USERNAME, password=settings.DEFAULT_PASSWORD) self.character = c.create_character('Graxnor') c.get_objects() result = c.set_character_status(self.character, 'online') self.assertTrue(result) self.assertTrue(c.characters[self.character].online)
def test_get_objects_verbose(self): '''Client can get the objects in our character's zone, when we give it.''' with self.fresh_servers(): c = clientlib.Client(username=settings.DEFAULT_USERNAME, password=settings.DEFAULT_PASSWORD) self.character = c.create_character('Graxnor') zoneid = c.get_zone(self.character) zoneurl = c.get_zone_url(zoneid) c.get_objects(zoneurl) self.assertTrue(c.objects)
def test_authenticate(self): '''Authenticating after initting Client should work.''' c = clientlib.Client() with self.fresh_servers(): result = c.authenticate(username=settings.DEFAULT_USERNAME, password=settings.DEFAULT_PASSWORD) self.character = c.create_character('Graxnor') self.assertTrue(result) self.assertTrue(c.cookies['user']) self.assertTrue(c.characters)
def test_move_character_bump(self): '''Client can try to move a character, but fail due to physics.''' with self.fresh_servers(): c = clientlib.Client(username=settings.DEFAULT_USERNAME, password=settings.DEFAULT_PASSWORD) character = c.create_character('Graxnor') c.set_character_status(character, 'online') result = c.move_character(character) self.assertFalse(result)
def test_get_zone_cacheing(self): '''Client can get the zone for our character from the cache.''' with self.fresh_servers(): c = clientlib.Client(username=settings.DEFAULT_USERNAME, password=settings.DEFAULT_PASSWORD) self.character = c.create_character('Graxnor') self.assertTrue(c.get_zone(self.character)) expected = "Expected Zone" c.characters[self.character].zone = expected result = c.get_zone(self.character) self.assertEqual(result, expected)
def test_create(self): '''Create a character. Not only must the create_character function return the character name the server created, but also update the client's characters dict.''' with self.fresh_servers(): c = clientlib.Client(username=settings.DEFAULT_USERNAME, password=settings.DEFAULT_PASSWORD) expected = "Cuddlepums" result = c.create_character(character_name=expected) self.assertEqual(result, expected) self.assertIn(expected, c.characters)
def test_get_objects_update(self): '''Client can update its objects.''' with self.fresh_servers(): c = clientlib.Client(username=settings.DEFAULT_USERNAME, password=settings.DEFAULT_PASSWORD) self.character = c.create_character('Graxnor') self.assertEqual(len(c.objects), 0) orig_objs = c.get_objects() result = c.get_objects() self.assertEqual(len(c.objects), 11) self.assertEqual(len(result), 0, 'When updating that quickly, there should be no updated objects. {}'.format(str(result)))
def test_get_zone_url_with_cache(self): '''Client can get the url for our character's zone from the cache''' with self.fresh_servers(): c = clientlib.Client(username=settings.DEFAULT_USERNAME, password=settings.DEFAULT_PASSWORD) self.character = c.create_character('Graxnor') zoneid = c.get_zone(self.character) c.get_zone_url(zoneid) expected = "Expected Zone Id" c.zones[zoneid] = expected result = c.get_zone_url(zoneid) self.assertEqual(result, expected)
def test_register_twice(self): '''Register with a good username and password, twice! If a user tries to register twice, with the same info, their request should be squelched and all continues as if nothing went awry. (If the user re-instantiates the client, show errors as normal.) ''' c = clientlib.Client() with self.fresh_servers(): first_result = c.register(username="******", password="******", email="*****@*****.**") self.assertTrue(first_result) self.assertEqual(c.last_user, "gooduser") second_result = c.register(username="******", password="******", email="*****@*****.**") self.assertTrue(second_result)
def test_get_messages(self): with self.fresh_servers(): c = clientlib.Client(username=settings.DEFAULT_USERNAME, password=settings.DEFAULT_PASSWORD) character = c.create_character('Graxnor') # Override the character's zone: zone = 'playerinstance-AdventureDungeon-%s' % character c.characters[character].zone = zone c.set_online(character) c.get_objects() # Poke Linnea to make her talk linnea = self.get_linnea(c.objects) c.activate(linnea['id']) c.get_messages() self.assertTrue(c.messages)
def test_activation(self): '''Client can activate an object.''' with self.fresh_servers(): c = clientlib.Client(username=settings.DEFAULT_USERNAME, password=settings.DEFAULT_PASSWORD) character = c.create_character('Graxnor') print "testing using ", character # Override the character's zone: zone = 'playerinstance-AdventureDungeon-%s' % character c.characters[character].zone = zone c.set_online(character) c.get_objects() linnea = self.get_linnea(c.objects) self.assertTrue(linnea) self.assertTrue(c.activate(linnea['id']))
class InteractiveClient(Cmd): client = clientlib.Client() quiet = False debug = True prompt = " > " def precmd(self, line): self.do_update() return line def postcmd(self, stop, line): self.do_update() return stop def format_prompt(self, username='', character='', zone=''): if not username: username = self.client.last_user if not character: character = self.client.last_character if not zone: # We want the actual name of the zone instead of the url. for zoneid, zone in self.client.zones.iteritems(): if zone == self.client.last_zone: # The instance type and instance owner are implied, # So we only want the actual zone name. zone = zoneid.split('-')[1] break zone = '@{0}'.format(zone) if zone else '' prompt_string = " {username}:{character}{zone} ({num_objs})> " self.prompt = prompt_string.format(username=username, character=(character or "No Character Selected"), zone=zone, num_objs=len(self.client.objects)) return self.prompt def logged_in(self): if not self.client.last_character: return False else: return True @options([make_option('-u', '--username', type="string", help="The name of the user you want to register."), make_option('-p', '--password', type="string", help="The password for the user."), make_option('-e', '--email', type="string", default=None, help="The email for the user."), ]) def do_register(self, args, opts=None): '''Register a username and password combination so you can log in. You only need to do this once per user you want to create. Calling this more than once with the same arguments will generate an error at worst, and be ignored at best.''' if not opts: username, password, email = args.split(" ") else: username = opts.username password = opts.password email = opts.email try: result = self.client.register(username, password, email) except clientlib.RegistrationError as exc: self.perror("Error: Registration failed: {0}" .format(exc.message)) return if result: self.pfeedback(result) @options([make_option('-u', '--username', type="string", default=settings.DEFAULT_USERNAME, help="The user you want to log in as."), make_option('-p', '--password', type="string", default=settings.DEFAULT_PASSWORD, help="The password for the user."), ]) def do_login(self, args, opts=None): '''Log in as a given user.''' if not opts: username, password = args.split(' ') else: username = opts.username password = opts.password return self.login(username, password) def login(self, username, password, charnum=None): # Sometimes the authserver may not be up. if not self.client.ping(): self.perror("Error: Authentication server is not online.") return # Let's see if the username and password are right: result = self.client.authenticate(username, password) if not result: self.perror("Authentication failed.") return else: self.pfeedback("Authentication successful. You are now logged in as {0}." .format(repr(username))) character = None if charnum: character = self.client.characters[list(self.client.characters)[int(charnum-1)]].name else: if self.client.characters: if len(self.client.characters) == 1: character = self.client.characters.keys()[0] else: character = self.select(self.client.characters, 'Select a Character: ') if character: self.client.last_character = character self.client.set_character_status(character) self.client.get_objects() else: self.pfeedback("No characters found.") character_name = raw_input("New character's name: ").strip() self.do_create_character(character_name) self.login(username, password, charnum) self.format_prompt() @options([make_option('-n', '--name', type="string", default="Graxnor", help="The name of the character you want to create.."), ]) def do_create_character(self, args, opts=None): if not opts: (name,) = args.split(' ') else: name = opts.name try: result = self.client.create_character(name) except (clientlib.ClientError, clientlib.UnexpectedHTTPStatus) as exc: self.perror("Error: Character creation failed: {0}".format(exc.message)) return return result def do_update(self, args=None): '''Update all the things that can be updated. This includes objects only at the moment.''' if not self.logged_in(): return self.client.get_objects() self.client.get_messages() for msg in self.format_messages(): self.pfeedback(msg) def format_messages(self): for msgid, message in self.client.messages.iteritems(): if not message.get('read'): message['read'] = True timestamp = datetime.fromtimestamp(message.get('last_modified', {}).get('$date', 0)/1000) yield "[{timestamp:%X}] "\ "<{sender}>: "\ "{body}".format(sender=message.get('sender'), body=message.get('body'), timestamp=timestamp) def do_map(self, args): '''Renders a map of the zone your character is currently in. By default this is ascii, but you can also ask it to render to an image.''' if not self.logged_in(): return # Get bounds (maxx, maxy, minx, miny) of all objects in the zone maxx = 0 maxy = 0 minx = 0 miny = 0 goodobjs = [] for objid, obj in self.client.objects.iteritems(): try: objloc = obj['loc'] except KeyError: # Some objects have no location, so skip em. continue try: if 'hidden' in obj['states']: # Skip hidden objects. continue except KeyError: # Stuff without states are A-OK pass maxx = max(maxx, objloc['x']) maxy = max(maxy, objloc['y']) minx = min(minx, objloc['x']) miny = min(miny, objloc['y']) goodobjs.append(obj) xlen, ylen = maxx-minx, maxy-miny deltax = maxx-minx deltay = maxy-miny if not args: # Default is fullscreen import os rows, columns = os.popen('stty size', 'r').read().split() mapsizex = int(rows)-2 mapsizey = int(columns)-1 else: # Otherwise use whatever args are passed. mapsizex, mapsizey = [int(n) for n in args.split()] import numpy # Build out the default array. maparray = numpy.array([['.']*mapsizey]*mapsizex) # This places the objects in the array based on their relative position. names = {} for obj in goodobjs: # Stupid rounding here, but good enough. x = int(((obj['loc']['x']-minx)/deltax)*mapsizex) y = int(((obj['loc']['y']-miny)/deltay)*mapsizey) try: name = names[obj['resource']] except KeyError: name = obj['resource'][0] names[obj['resource']] = name maparray[x-1, y-1] = name # Make a string because printing manually is dumb. mapstring = '\n'.join([''.join([y for y in x]) for x in maparray]) self.poutput(mapstring) def clean_dict(self, dirty): '''Clean up ugly values and drop private keys.''' newobj = {} for k, v in dirty.iteritems(): if type(v) == float: v = float("%.4f" % v) if type(v) == dict: v = self.clean_dict(v) if not k.startswith("_"): newobj[k] = v return newobj def format_object(self, objdata): '''Pretty-print an object from the client.''' newobj = {u'id': objdata['_id']['$oid']} newobj.update(self.clean_dict(objdata)) for k, v in objdata.iteritems(): # Prettify the last modified timestamp if k == "last_modified": v = datetime.fromtimestamp(v[r'$date']/1000.0)\ .strftime(settings.DATETIME_FORMAT) newobj[k] = v return pformat(newobj) def get_match(self, objname): '''Get a matching object from the client for a given id or name. It matches based on exact matches, starts with or contains, in that order.''' objname = objname.lower() # Try exact match first: try: obj = self.client.objects[objname] return obj except KeyError: # Couldn't find the exact match. pass # Try startswith match next: for objid, obj in self.client.objects.iteritems(): if objid.lower().startswith(objname) or obj['name'].lower().startswith(objname): return obj # Try contains match next: for objid, obj in self.client.objects.iteritems(): if objname in objid.lower() or objname in obj['name'].lower(): return obj # Couldn't find anything. return False def do_detail(self, args): '''Pass in the name or id of the object you want to look at.''' objname = args if objname: obj = self.get_match(objname) if obj: self.poutput(self.format_object(obj)) else: self.perror("Could not find anything resembling {0}.".format(objname))
def test_get_zone(self): '''Client can get the zone for our character.''' with self.fresh_servers(): c = clientlib.Client(username=settings.DEFAULT_USERNAME, password=settings.DEFAULT_PASSWORD) self.character = c.create_character('Graxnor') self.assertTrue(c.get_zone(self.character))
def test___init___autoauth_bad(self): '''Initting the Client with a bad user/pass combo will raise an exception. ''' with self.assertRaises(clientlib.AuthenticationError): clientlib.Client(username="******", password="******")
def test___init___autoauth(self): '''Init the Client with a known good user/pass combo.''' with self.fresh_servers(): c = clientlib.Client(username=settings.DEFAULT_USERNAME, password=settings.DEFAULT_PASSWORD) self.assertTrue(c.cookies) self.assertTrue(c.cookies['user'])
def test___init__(self): '''Init the Client with no args.''' c = clientlib.Client() self.assertTrue(c)
def test_ping(self): '''Pinging the authserver should work.''' with self.fresh_servers(): c = clientlib.Client() result = c.ping() self.assertTrue(result)