-
Notifications
You must be signed in to change notification settings - Fork 63
/
test_avatar_runner.py
145 lines (115 loc) · 6.63 KB
/
test_avatar_runner.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
from unittest import TestCase
import mock
from avatar_runner import AvatarRunner
from user_exceptions import InvalidActionException
NORTH = {'x': 0, 'y': 1}
SOUTH = {'x': 0, 'y': -1}
EAST = {'x': 1, 'y': 0}
WEST = {'x': -1, 'y': 0}
class TestAvatarRunner(TestCase):
def test_runner_does_not_crash_on_code_errors(self):
class Avatar(object):
def handle_turn(self, world_map, avatar_state):
assert False
runner = AvatarRunner(avatar=Avatar(), auto_update=False)
action = runner.process_avatar_turn(world_map={}, avatar_state={}, src_code='')['action']
self.assertEqual(action, {'action_type': 'wait'})
def test_runner_updates_code_on_change(self):
avatar1 = '''class Avatar(object):
def handle_turn(self, world_map, avatar_state):
from simulation.action import MoveAction
from simulation.direction import EAST
return MoveAction(EAST)
'''
avatar2 = '''class Avatar(object):
def handle_turn(self, world_map, avatar_state):
from simulation.action import MoveAction
from simulation.direction import WEST
return MoveAction(WEST)
'''
runner = AvatarRunner()
response = runner.process_avatar_turn(world_map={}, avatar_state={}, src_code=avatar1)
self.assertEqual(response['action'], {'action_type': 'move', 'options': {'direction': EAST}})
response = runner.process_avatar_turn(world_map={}, avatar_state={}, src_code=avatar2)
self.assertEqual(response['action'], {'action_type': 'move', 'options': {'direction': WEST}})
def test_runner_can_maintain_state(self):
""" This test ensures that if the code is the same, we do not recreate the avatar object in the runner.
We check this by making sure that self.x is being updated and its value retained. """
avatar = '''class Avatar(object):
def __init__(self):
from simulation.action import MoveAction
from simulation.direction import NORTH, SOUTH, EAST, WEST
self.moves = [MoveAction(NORTH), MoveAction(EAST), MoveAction(SOUTH), MoveAction(WEST)]
self.x = 0
def handle_turn(self, world_map, avatar_state):
move = self.moves[self.x]
self.x += 1
return move
'''
runner = AvatarRunner()
directions = [NORTH, EAST, SOUTH, WEST]
for direction in directions:
response = runner.process_avatar_turn(world_map={}, avatar_state={}, src_code=avatar)
self.assertEqual(response['action'], {'action_type': 'move', 'options': {'direction': direction}})
def test_update_code_flag_simple(self):
avatar1 = '''class Avatar(object):
def handle_turn(self, world_map, avatar_state):
from simulation.action import MoveAction
from simulation.direction import NORTH
return MoveAction(NORTH)
'''
avatar2 = '''class Avatar(object):
def handle_turn(self, world_map, avatar_state):
from simulation.action import MoveAction
from simulation.direction import SOUTH
return MoveAction(SOUTH)
'''
runner = AvatarRunner()
response = runner.process_avatar_turn(world_map={}, avatar_state={}, src_code=avatar1)
self.assertTrue(response['avatar_updated'])
response = runner.process_avatar_turn(world_map={}, avatar_state={}, src_code=avatar1)
self.assertFalse(response['avatar_updated'])
response = runner.process_avatar_turn(world_map={}, avatar_state={}, src_code=avatar2)
self.assertTrue(response['avatar_updated'])
response = runner.process_avatar_turn(world_map={}, avatar_state={}, src_code=avatar2)
self.assertFalse(response['avatar_updated'])
def test_update_code_flag_with_syntax_errors(self):
avatar = '''class Avatar(object:
pass
'''
runner = AvatarRunner()
response = runner.process_avatar_turn(world_map={}, avatar_state={}, src_code=avatar)
self.assertTrue(response['avatar_updated'])
response = runner.process_avatar_turn(world_map={}, avatar_state={}, src_code=avatar)
self.assertFalse(response['avatar_updated'])
def test_invalid_action_exception(self):
avatar = '''class Avatar(object):
def handle_turn(self, world_map, avatar_state):
from simulation.action import MoveAction
from simulation.direction import NORTH
'''
runner = AvatarRunner()
runner._update_avatar(src_code=avatar)
with self.assertRaises(InvalidActionException):
runner.decide_action(world_map={}, avatar_state={})
def test_runtime_error_contains_only_user_traceback(self):
avatar = '''class Avatar(object):
def handle_turn(self, world_map, avatar_state):
from simulation.action import MoveAction
from simulation.direction import NORTH
1 + 'foo'
return MoveAction(NORTH)
'''
runner = AvatarRunner()
response = runner.process_avatar_turn(world_map={}, avatar_state={}, src_code=avatar)
self.assertFalse(response['log'].__contains__('/usr/src/app/'))
def test_syntax_error_contains_only_user_traceback(self):
avatar = '''class Avatar(object):
def handle_turn(self, world_map, avatar_state):
from simulation.action import MoveAction
from simulation.direction import NORTH
return MoveAction(NORTH))))
'''
runner = AvatarRunner()
response = runner.process_avatar_turn(world_map={}, avatar_state={}, src_code=avatar)
self.assertFalse(response['log'].__contains__('/usr/src/app/'))