def setUp(self): self.lh = logging.NullHandler() logging.getLogger(driver.LOGGER_NAME).addHandler(self.lh) self.game = Minesweeper()
class MinesweeperTest(unittest.TestCase): def setUp(self): self.lh = logging.NullHandler() logging.getLogger(driver.LOGGER_NAME).addHandler(self.lh) self.game = Minesweeper() def test_new_game(self): self.assertIsNone(self.game.size()) self.assertIsNone(self.game.bombs()) self.assertIsNone(self.game.flags()) self.assertFalse(self.game.is_win()) self.assertFalse(self.game.is_lose()) self.assertTrue(self.game.saved()) self.assertEqual(0, self.game.get_time()) self.game.new_game((5, 6), 8) self.assertEqual((5, 6), self.game.size()) self.assertEqual(8, self.game.bombs()) self.assertEqual(0, self.game.flags()) self.assertFalse(self.game.is_win()) self.assertFalse(self.game.is_lose()) self.assertTrue(self.game.saved()) self.assertEqual(0, self.game.get_time()) def test_handlers(self): counter = {event_type: 0 for event_type in EventTypes} def handle(event): counter[event] += 1 handlers = {} for evt_type in EventTypes: handlers[evt_type] = (lambda e=evt_type: lambda *args: handle(e))() self.game.add_event_handler(evt_type, handlers[evt_type]) def remove_handler(event): self.game.remove_event_handler(event, handlers[event]) with patch_field_generator(Field((2, 1), {(0, 0)})): self.game.new_game((2, 1), 1) with self.subTest('changed handler'): self.assertEqual(0, counter[EventTypes.CELL_CHANGED]) self.game.invert_flag((0, 0)) self.assertEqual(1, counter[EventTypes.CELL_CHANGED]) remove_handler(EventTypes.CELL_CHANGED) self.game.invert_flag((0, 0)) self.assertEqual(1, counter[EventTypes.CELL_CHANGED]) with self.subTest('win handler'): self.game.again() self.assertEqual(0, counter[EventTypes.PLAYER_WIN]) self.game.open_cell((1, 0)) self.game.invert_flag((0, 0)) self.assertEqual(1, counter[EventTypes.PLAYER_WIN]) self.game.again() remove_handler(EventTypes.PLAYER_WIN) self.game.open_cell((1, 0)) self.game.invert_flag((0, 0)) self.assertEqual(1, counter[EventTypes.PLAYER_WIN]) with self.subTest('lose handler'): self.game.again() self.assertEqual(0, counter[EventTypes.PLAYER_LOSE]) self.game.open_cell((0, 0)) self.assertEqual(1, counter[EventTypes.PLAYER_LOSE]) self.game.again() remove_handler(EventTypes.PLAYER_LOSE) self.game.open_cell((0, 0)) self.assertEqual(1, counter[EventTypes.PLAYER_LOSE]) with self.subTest('new_game handler'): counter[EventTypes.NEW_GAME] = 0 self.game.again() self.assertEqual(1, counter[EventTypes.NEW_GAME]) remove_handler(EventTypes.NEW_GAME) self.game.again() self.assertEqual(1, counter[EventTypes.NEW_GAME]) with self.subTest('end_change handler'): counter[EventTypes.END_CHANGE] = 0 self.game.again() self.assertEqual(1, counter[EventTypes.END_CHANGE]) self.game.invert_flag((0, 0)) self.assertEqual(2, counter[EventTypes.END_CHANGE]) self.game.invert_flag((0, 0)) self.assertEqual(3, counter[EventTypes.END_CHANGE]) self.game.open_cell((1, 0)) self.assertEqual(4, counter[EventTypes.END_CHANGE]) self.game.undo() self.assertEqual(5, counter[EventTypes.END_CHANGE]) self.game.redo() self.assertEqual(6, counter[EventTypes.END_CHANGE]) remove_handler(EventTypes.END_CHANGE) self.game.undo() self.assertEqual(6, counter[EventTypes.END_CHANGE]) def test_handler_decorator(self): callargs = [] @self.game.event_handler(EventTypes.NEW_GAME) def handler(*args): callargs.append(args) self.game.new_game((5, 5), 10) self.assertListEqual([((5, 5), 10)], callargs) def test_open_cell(self): callargs = [] self.game.add_event_handler(EventTypes.CELL_CHANGED, lambda *args: callargs.append(args)) self.game.open_cell((0, 0)) self.assertListEqual([], callargs) with patch_field_generator(Field((4, 3), {(0, 0), (2, 0)})): self.game.new_game((4, 3), 2) self.game.open_cell((3, 2)) self.assertEqual(8, len(callargs)) self.assertSetEqual( {e[0] for e in callargs if e[1] == CellState.OPENED}, {(x, y) for x in (0, 1, 2, 3) for y in (1, 2)}) self.game.again() callargs = [] self.game.open_cell(('3', '2')) self.assertEqual(8, len(callargs)) self.assertFalse(self.game.is_win()) self.game.open_cell((3, 2)) self.assertEqual(8, len(callargs)) def test_autocomplete(self): callargs = [] self.game.add_event_handler(EventTypes.CELL_CHANGED, lambda *args: callargs.append(args)) with patch_field_generator(Field((3, 3), {(0, 0), (2, 0)})): self.game.new_game((3, 3), 2) self.game.open_cell((1, 2)) self.game.open_cell((1, 0)) self.assertFalse(self.game.is_win()) self.game.again() self.game.open_cell((1, 2)) self.game.open_cell((1, 0), True) self.assertTrue(self.game.is_win()) self.assertSetEqual({(0, 0), (2, 0)}, {e[0] for e in callargs if e[1] == CellState.FLAG}) self.game.again() self.game.invert_flag((1, 0)) self.game.open_cell((1, 2), True) self.assertFalse(self.game.is_win()) def test_neighbors(self): self.assertIsNone(self.game.get_neighbors((0, 0))) with patch_field_generator(Field((3, 3), {(0, 0), (2, 0)})): self.game.new_game((3, 3), 2) self.game.open_cell((2, 2)) self.assertListEqual( [1, 2, 1], [self.game.get_neighbors((x, 1)) for x in (0, 1, 2)]) self.assertListEqual( [1, 2, 1], [self.game.get_neighbors((x, '1')) for x in (0, 1, 2)]) self.assertListEqual( [0, 0, 0], [self.game.get_neighbors((x, 2)) for x in (0, 1, 2)]) def test_state(self): self.assertIsNone(self.game.get_state()) with patch_field_generator(Field((2, 2), {(0, 0)})): self.game.new_game((2, 2), 1) callargs = [] self.game.add_event_handler(EventTypes.CELL_CHANGED, lambda *args: callargs.append(args)) self.game.open_cell((1, 1)) state = self.game.get_state() self.assertEqual(CellState.OPENED, state.get_state((1, 1))) self.assertEqual(1, len(callargs)) state.open_cell((1, 0)) self.assertEqual(1, len(callargs)) state.set_flag((0, 0)) self.assertEqual(0, self.game.flags()) def test_time(self): with self.subTest('flags'): self.game.new_game((3, 3), 2) self.assertEqual(0, self.game.get_time()) time.sleep(0.1) self.assertEqual(0, self.game.get_time()) self.game.invert_flag((0, 0)) time.sleep(0.1) self.assertGreaterEqual(self.game.get_time(), 10) with self.subTest('open'): with patch_field_generator(Field((3, 3), {(0, 0), (2, 0)})): self.game.new_game((3, 3), 2) self.assertEqual(0, self.game.get_time()) self.game.open_cell((2, 2)) time.sleep(0.2) self.assertGreaterEqual(self.game.get_time(), 20) with self.subTest('load'): self.game.again() self.game.open_cell((2, 2)) time.sleep(0.15) try: with tempfile.NamedTemporaryFile(delete=False) as f: name = f.name self.game.save_game(name) self.game.new_game((10, 10), 10) self.game.load_game(name) self.assertGreaterEqual(self.game.get_time(), 15) time.sleep(0.1) self.assertGreaterEqual(self.game.get_time(), 25) finally: if os.path.exists(name): os.remove(name) def test_flags(self): callargs = [] self.game.add_event_handler(EventTypes.CELL_CHANGED, lambda *args: callargs.append(args)) self.game.invert_flag((0, 0)) self.assertListEqual([], callargs) with patch_field_generator(Field((4, 3), {(0, 0), (2, 0)})): self.game.new_game((4, 3), 2) self.game.invert_flag((0, 2)) self.assertListEqual([((0, 2), CellState.FLAG)], callargs) self.game.open_cell((3, 2)) self.assertEqual(8, len(callargs)) self.game.invert_flag(('0', '2')) self.assertEqual(((0, 2), CellState.UNKNOWN), callargs[-1]) self.game.invert_flag((0, 0)) self.assertFalse(self.game.is_lose()) self.game.open_cell((0, 0)) self.assertFalse(self.game.is_lose()) def test_new_game_handler(self): callargs = [] self.game.add_event_handler(EventTypes.NEW_GAME, lambda *args: callargs.append(args)) self.game.new_game((4, 3), 2) self.assertEqual(((4, 3), 2), callargs[0]) self.game.new_game((8, 8), 10) self.assertEqual(((8, 8), 10), callargs[1]) self.game.again() self.assertEqual(((8, 8), 10), callargs[2]) self.game.new_game((5, 4), 7) self.assertEqual(((5, 4), 7), callargs[3]) self.game.again() self.assertEqual(((5, 4), 7), callargs[4]) self.game.again() self.assertEqual(((5, 4), 7), callargs[5]) def test_again(self): with patch_field_generator(Field((2, 2), {(0, 0)})): self.game.new_game((2, 2), 1) self.game.invert_flag((0, 0)) self.assertEqual(1, self.game.flags()) self.game.again() self.assertEqual(0, self.game.flags()) for coords in ((0, 1), (1, 0), (1, 1)): self.game.open_cell(coords) self.assertFalse(self.game.is_win()) self.game.invert_flag((0, 0)) self.assertTrue(self.game.is_win()) self.game.again() self.assertFalse(self.game.is_win()) self.assertFalse(self.game.is_lose()) self.game.open_cell((0, 0)) self.assertTrue(self.game.is_lose()) self.game.again() self.assertFalse(self.game.is_lose()) def test_win(self): field = Field((3, 3), {(0, 0), (2, 0)}) with patch_field_generator(field): self.game.new_game((3, 3), 2) callargs = [] self.game.add_event_handler(EventTypes.PLAYER_WIN, lambda *args: callargs.append(args)) self.game.open_cell((1, 2)) self.assertFalse(self.game.is_win()) self.assertListEqual([], callargs) self.game.open_cell((1, 0)) self.assertFalse(self.game.is_win()) self.assertListEqual([], callargs) self.game.invert_flag((0, 0)) self.game.invert_flag((2, 0)) self.assertTrue(self.game.is_win()) self.assertTrue(self.game.saved()) self.assertListEqual([(field, )], callargs) def test_lose(self): field = Field((3, 3), {(0, 0), (2, 0)}) with patch_field_generator(field): self.game.new_game((3, 3), 2) callargs = [] self.game.add_event_handler(EventTypes.PLAYER_LOSE, lambda *args: callargs.append(args)) self.game.open_cell((1, 2)) self.assertFalse(self.game.is_lose()) self.assertListEqual([], callargs) self.game.open_cell((0, 0)) self.assertTrue(self.game.is_lose()) self.assertTrue(self.game.saved()) self.assertListEqual([(field, (0, 0))], callargs) def test_undo_redo(self): with patch_field_generator(Field((4, 3), {(0, 0), (3, 1)})): self.game.new_game((4, 3), 2) callargs = [] self.game.add_event_handler(EventTypes.CELL_CHANGED, lambda *args: callargs.append(args)) self.assertFalse(self.game.can_undo()) self.assertFalse(self.game.can_redo()) self.game.undo() self.game.redo() self.assertListEqual([], callargs) with self.subTest('flags'): self.game.invert_flag((0, 0)) self.assertTrue(self.game.can_undo()) self.assertEqual(1, self.game.flags()) self.game.undo() self.assertFalse(self.game.can_undo()) self.assertTrue(self.game.can_redo()) self.assertEqual(0, self.game.flags()) self.game.invert_flag((0, 0)) self.assertFalse(self.game.can_redo()) self.assertEqual(1, self.game.flags()) self.game.undo() self.assertEqual(0, self.game.flags()) self.game.redo() self.assertEqual(1, self.game.flags()) self.assertEqual(5, len(callargs)) with self.subTest('again'): self.assertTrue(self.game.can_undo() or self.game.can_redo()) self.game.again() self.assertFalse(self.game.can_undo() or self.game.can_redo()) with self.subTest('wrong_flags'): self.game.open_cell((2, 2)) self.game.invert_flag((2, 2)) self.game.undo() self.assertFalse(self.game.can_undo()) with self.subTest('open'): self.game.again() callargs = [] self.game.open_cell((2, 0)) self.game.open_cell((0, 2)) self.game.open_cell((1, 0)) self.assertTrue(self.game.can_undo()) self.game.undo() self.assertEqual(CellState.UNKNOWN, callargs[-1][1]) self.assertEqual(CellState.OPENED, callargs[-2][1]) self.assertTrue(self.game.can_undo()) self.game.undo() self.assertListEqual([CellState.UNKNOWN] * 6, [x[1] for x in callargs[-6:]]) self.game.redo() self.assertListEqual([CellState.OPENED] * 6, [x[1] for x in callargs[-6:]]) self.assertTrue(self.game.can_redo()) self.game.open_cell((1, 2)) with patch_field_generator(Field((2, 1), {(0, 0)})): self.game.new_game((2, 1), 1) with self.subTest('lose'): self.game.open_cell((1, 0)) self.assertFalse(self.game.is_lose()) self.game.open_cell((0, 0)) self.assertTrue(self.game.is_lose()) self.assertFalse(self.game.can_undo() or self.game.can_redo()) with self.subTest('win'): self.game.again() self.game.open_cell((1, 0)) self.assertFalse(self.game.is_win()) self.game.invert_flag((0, 0)) self.assertTrue(self.game.is_win()) self.assertFalse(self.game.can_undo() or self.game.can_redo()) @unittest.skipIf(sys.platform.startswith('win'), 'Windows not supported') def test_load_bad(self): with tempfile.NamedTemporaryFile(delete=False) as f: name = f.name f.write(b'BAD DATA') old_mode = stat.S_IMODE(os.stat(name).st_mode) try: with self.assertRaises(driver.LoadError): self.game.load_game(name) self.game.new_game((4, 4), 3) self.game.save_game(name) self.assertTrue(os.path.exists(name)) os.chmod(name, 0) with self.assertRaises(driver.LoadError): self.game.load_game(name) self.game.new_game((4, 4), 3) self.game.invert_flag((0, 0)) os.remove(name) self.assertFalse(os.path.exists(name)) with self.assertRaises(driver.LoadError): self.game.load_game(name) self.assertTrue(1, self.game.flags()) finally: if os.path.exists(name): os.chmod(name, old_mode) os.remove(name) def test_save_bad(self): with tempfile.NamedTemporaryFile(delete=False) as f: name = f.name old_mode = stat.S_IMODE(os.stat(name).st_mode) try: with self.assertRaises(driver.SaveError): self.game.save_game(name) self.game.new_game((4, 4), 3) os.chmod(name, 0) with self.assertRaises(driver.SaveError): self.game.save_game(name) finally: if os.path.exists(name): os.chmod(name, old_mode) os.remove(name) def test_save_load(self): with tempfile.NamedTemporaryFile(delete=False) as f: name = f.name try: with patch_field_generator(Field((4, 3), {(0, 0), (3, 1)})): self.game.new_game((4, 3), 2) self.game.open_cell((0, 2)) self.game.invert_flag((0, 0)) self.game.invert_flag((1, 0)) time.sleep(0.3) self.game.undo() self.assertFalse(self.game.saved()) self.game.save_game(name) self.assertTrue(self.game.saved()) self.game.new_game((5, 5), 10) callargs = [] for evt_type in (EventTypes.NEW_GAME, EventTypes.CELL_CHANGED): self.game.add_event_handler( evt_type, lambda *args: callargs.append(args)) self.game.load_game(name) self.assertEqual(((4, 3), 2), callargs[0]) self.assertSetEqual( {(0, 0)}, {x[0] for x in callargs if x[1] == CellState.FLAG}) self.assertSetEqual( {(x, y) for x in (0, 1, 2) for y in (1, 2)}, {x[0] for x in callargs if x[1] == CellState.OPENED}) self.assertSetEqual( {(1, 0), (2, 0), (3, 0), (3, 1), (3, 2)}, {x[0] for x in callargs if x[1] == CellState.UNKNOWN}) self.assertGreaterEqual(self.game.get_time(), 30) self.assertTrue(self.game.can_undo()) finally: if os.path.exists(name): os.remove(name) def tearDown(self): logging.getLogger(driver.LOGGER_NAME).removeHandler(self.lh)
class MinesweeperTest(unittest.TestCase): def setUp(self): self.lh = logging.NullHandler() logging.getLogger(driver.LOGGER_NAME).addHandler(self.lh) self.game = Minesweeper() def test_new_game(self): self.assertIsNone(self.game.size()) self.assertIsNone(self.game.bombs()) self.assertIsNone(self.game.flags()) self.assertFalse(self.game.is_win()) self.assertFalse(self.game.is_lose()) self.assertTrue(self.game.saved()) self.assertEqual(0, self.game.get_time()) self.game.new_game((5, 6), 8) self.assertEqual((5, 6), self.game.size()) self.assertEqual(8, self.game.bombs()) self.assertEqual(0, self.game.flags()) self.assertFalse(self.game.is_win()) self.assertFalse(self.game.is_lose()) self.assertTrue(self.game.saved()) self.assertEqual(0, self.game.get_time()) def test_handlers(self): counter = {event_type: 0 for event_type in EventTypes} def handle(event): counter[event] += 1 handlers = {} for evt_type in EventTypes: handlers[evt_type] = (lambda e=evt_type: lambda *args: handle(e))() self.game.add_event_handler(evt_type, handlers[evt_type]) def remove_handler(event): self.game.remove_event_handler(event, handlers[event]) with patch_field_generator(Field((2, 1), {(0, 0)})): self.game.new_game((2, 1), 1) with self.subTest('changed handler'): self.assertEqual(0, counter[EventTypes.CELL_CHANGED]) self.game.invert_flag((0, 0)) self.assertEqual(1, counter[EventTypes.CELL_CHANGED]) remove_handler(EventTypes.CELL_CHANGED) self.game.invert_flag((0, 0)) self.assertEqual(1, counter[EventTypes.CELL_CHANGED]) with self.subTest('win handler'): self.game.again() self.assertEqual(0, counter[EventTypes.PLAYER_WIN]) self.game.open_cell((1, 0)) self.game.invert_flag((0, 0)) self.assertEqual(1, counter[EventTypes.PLAYER_WIN]) self.game.again() remove_handler(EventTypes.PLAYER_WIN) self.game.open_cell((1, 0)) self.game.invert_flag((0, 0)) self.assertEqual(1, counter[EventTypes.PLAYER_WIN]) with self.subTest('lose handler'): self.game.again() self.assertEqual(0, counter[EventTypes.PLAYER_LOSE]) self.game.open_cell((0, 0)) self.assertEqual(1, counter[EventTypes.PLAYER_LOSE]) self.game.again() remove_handler(EventTypes.PLAYER_LOSE) self.game.open_cell((0, 0)) self.assertEqual(1, counter[EventTypes.PLAYER_LOSE]) with self.subTest('new_game handler'): counter[EventTypes.NEW_GAME] = 0 self.game.again() self.assertEqual(1, counter[EventTypes.NEW_GAME]) remove_handler(EventTypes.NEW_GAME) self.game.again() self.assertEqual(1, counter[EventTypes.NEW_GAME]) with self.subTest('end_change handler'): counter[EventTypes.END_CHANGE] = 0 self.game.again() self.assertEqual(1, counter[EventTypes.END_CHANGE]) self.game.invert_flag((0, 0)) self.assertEqual(2, counter[EventTypes.END_CHANGE]) self.game.invert_flag((0, 0)) self.assertEqual(3, counter[EventTypes.END_CHANGE]) self.game.open_cell((1, 0)) self.assertEqual(4, counter[EventTypes.END_CHANGE]) self.game.undo() self.assertEqual(5, counter[EventTypes.END_CHANGE]) self.game.redo() self.assertEqual(6, counter[EventTypes.END_CHANGE]) remove_handler(EventTypes.END_CHANGE) self.game.undo() self.assertEqual(6, counter[EventTypes.END_CHANGE]) def test_handler_decorator(self): callargs = [] @self.game.event_handler(EventTypes.NEW_GAME) def handler(*args): callargs.append(args) self.game.new_game((5, 5), 10) self.assertListEqual([((5, 5), 10)], callargs) def test_open_cell(self): callargs = [] self.game.add_event_handler(EventTypes.CELL_CHANGED, lambda *args: callargs.append(args)) self.game.open_cell((0, 0)) self.assertListEqual([], callargs) with patch_field_generator(Field((4, 3), {(0, 0), (2, 0)})): self.game.new_game((4, 3), 2) self.game.open_cell((3, 2)) self.assertEqual(8, len(callargs)) self.assertSetEqual( {e[0] for e in callargs if e[1] == CellState.OPENED}, {(x, y) for x in (0, 1, 2, 3) for y in (1, 2)}) self.game.again() callargs = [] self.game.open_cell(('3', '2')) self.assertEqual(8, len(callargs)) self.assertFalse(self.game.is_win()) self.game.open_cell((3, 2)) self.assertEqual(8, len(callargs)) def test_autocomplete(self): callargs = [] self.game.add_event_handler(EventTypes.CELL_CHANGED, lambda *args: callargs.append(args)) with patch_field_generator(Field((3, 3), {(0, 0), (2, 0)})): self.game.new_game((3, 3), 2) self.game.open_cell((1, 2)) self.game.open_cell((1, 0)) self.assertFalse(self.game.is_win()) self.game.again() self.game.open_cell((1, 2)) self.game.open_cell((1, 0), True) self.assertTrue(self.game.is_win()) self.assertSetEqual({(0, 0), (2, 0)}, {e[0] for e in callargs if e[1] == CellState.FLAG}) self.game.again() self.game.invert_flag((1, 0)) self.game.open_cell((1, 2), True) self.assertFalse(self.game.is_win()) def test_neighbors(self): self.assertIsNone(self.game.get_neighbors((0, 0))) with patch_field_generator(Field((3, 3), {(0, 0), (2, 0)})): self.game.new_game((3, 3), 2) self.game.open_cell((2, 2)) self.assertListEqual( [1, 2, 1], [self.game.get_neighbors((x, 1)) for x in (0, 1, 2)]) self.assertListEqual( [1, 2, 1], [self.game.get_neighbors((x, '1')) for x in (0, 1, 2)]) self.assertListEqual( [0, 0, 0], [self.game.get_neighbors((x, 2)) for x in (0, 1, 2)]) def test_state(self): self.assertIsNone(self.game.get_state()) with patch_field_generator(Field((2, 2), {(0, 0)})): self.game.new_game((2, 2), 1) callargs = [] self.game.add_event_handler(EventTypes.CELL_CHANGED, lambda *args: callargs.append(args)) self.game.open_cell((1, 1)) state = self.game.get_state() self.assertEqual(CellState.OPENED, state.get_state((1, 1))) self.assertEqual(1, len(callargs)) state.open_cell((1, 0)) self.assertEqual(1, len(callargs)) state.set_flag((0, 0)) self.assertEqual(0, self.game.flags()) def test_time(self): with self.subTest('flags'): self.game.new_game((3, 3), 2) self.assertEqual(0, self.game.get_time()) time.sleep(0.1) self.assertEqual(0, self.game.get_time()) self.game.invert_flag((0, 0)) time.sleep(0.1) self.assertGreaterEqual(self.game.get_time(), 10) with self.subTest('open'): with patch_field_generator(Field((3, 3), {(0, 0), (2, 0)})): self.game.new_game((3, 3), 2) self.assertEqual(0, self.game.get_time()) self.game.open_cell((2, 2)) time.sleep(0.2) self.assertGreaterEqual(self.game.get_time(), 20) with self.subTest('load'): self.game.again() self.game.open_cell((2, 2)) time.sleep(0.15) try: with tempfile.NamedTemporaryFile(delete=False) as f: name = f.name self.game.save_game(name) self.game.new_game((10, 10), 10) self.game.load_game(name) self.assertGreaterEqual(self.game.get_time(), 15) time.sleep(0.1) self.assertGreaterEqual(self.game.get_time(), 25) finally: if os.path.exists(name): os.remove(name) def test_flags(self): callargs = [] self.game.add_event_handler(EventTypes.CELL_CHANGED, lambda *args: callargs.append(args)) self.game.invert_flag((0, 0)) self.assertListEqual([], callargs) with patch_field_generator(Field((4, 3), {(0, 0), (2, 0)})): self.game.new_game((4, 3), 2) self.game.invert_flag((0, 2)) self.assertListEqual([((0, 2), CellState.FLAG)], callargs) self.game.open_cell((3, 2)) self.assertEqual(8, len(callargs)) self.game.invert_flag(('0', '2')) self.assertEqual(((0, 2), CellState.UNKNOWN), callargs[-1]) self.game.invert_flag((0, 0)) self.assertFalse(self.game.is_lose()) self.game.open_cell((0, 0)) self.assertFalse(self.game.is_lose()) def test_new_game_handler(self): callargs = [] self.game.add_event_handler(EventTypes.NEW_GAME, lambda *args: callargs.append(args)) self.game.new_game((4, 3), 2) self.assertEqual(((4, 3), 2), callargs[0]) self.game.new_game((8, 8), 10) self.assertEqual(((8, 8), 10), callargs[1]) self.game.again() self.assertEqual(((8, 8), 10), callargs[2]) self.game.new_game((5, 4), 7) self.assertEqual(((5, 4), 7), callargs[3]) self.game.again() self.assertEqual(((5, 4), 7), callargs[4]) self.game.again() self.assertEqual(((5, 4), 7), callargs[5]) def test_again(self): with patch_field_generator(Field((2, 2), {(0, 0)})): self.game.new_game((2, 2), 1) self.game.invert_flag((0, 0)) self.assertEqual(1, self.game.flags()) self.game.again() self.assertEqual(0, self.game.flags()) for coords in ((0, 1), (1, 0), (1, 1)): self.game.open_cell(coords) self.assertFalse(self.game.is_win()) self.game.invert_flag((0, 0)) self.assertTrue(self.game.is_win()) self.game.again() self.assertFalse(self.game.is_win()) self.assertFalse(self.game.is_lose()) self.game.open_cell((0, 0)) self.assertTrue(self.game.is_lose()) self.game.again() self.assertFalse(self.game.is_lose()) def test_win(self): field = Field((3, 3), {(0, 0), (2, 0)}) with patch_field_generator(field): self.game.new_game((3, 3), 2) callargs = [] self.game.add_event_handler(EventTypes.PLAYER_WIN, lambda *args: callargs.append(args)) self.game.open_cell((1, 2)) self.assertFalse(self.game.is_win()) self.assertListEqual([], callargs) self.game.open_cell((1, 0)) self.assertFalse(self.game.is_win()) self.assertListEqual([], callargs) self.game.invert_flag((0, 0)) self.game.invert_flag((2, 0)) self.assertTrue(self.game.is_win()) self.assertTrue(self.game.saved()) self.assertListEqual([(field,)], callargs) def test_lose(self): field = Field((3, 3), {(0, 0), (2, 0)}) with patch_field_generator(field): self.game.new_game((3, 3), 2) callargs = [] self.game.add_event_handler(EventTypes.PLAYER_LOSE, lambda *args: callargs.append(args)) self.game.open_cell((1, 2)) self.assertFalse(self.game.is_lose()) self.assertListEqual([], callargs) self.game.open_cell((0, 0)) self.assertTrue(self.game.is_lose()) self.assertTrue(self.game.saved()) self.assertListEqual([(field, (0, 0))], callargs) def test_undo_redo(self): with patch_field_generator(Field((4, 3), {(0, 0), (3, 1)})): self.game.new_game((4, 3), 2) callargs = [] self.game.add_event_handler(EventTypes.CELL_CHANGED, lambda *args: callargs.append(args)) self.assertFalse(self.game.can_undo()) self.assertFalse(self.game.can_redo()) self.game.undo() self.game.redo() self.assertListEqual([], callargs) with self.subTest('flags'): self.game.invert_flag((0, 0)) self.assertTrue(self.game.can_undo()) self.assertEqual(1, self.game.flags()) self.game.undo() self.assertFalse(self.game.can_undo()) self.assertTrue(self.game.can_redo()) self.assertEqual(0, self.game.flags()) self.game.invert_flag((0, 0)) self.assertFalse(self.game.can_redo()) self.assertEqual(1, self.game.flags()) self.game.undo() self.assertEqual(0, self.game.flags()) self.game.redo() self.assertEqual(1, self.game.flags()) self.assertEqual(5, len(callargs)) with self.subTest('again'): self.assertTrue(self.game.can_undo() or self.game.can_redo()) self.game.again() self.assertFalse(self.game.can_undo() or self.game.can_redo()) with self.subTest('wrong_flags'): self.game.open_cell((2, 2)) self.game.invert_flag((2, 2)) self.game.undo() self.assertFalse(self.game.can_undo()) with self.subTest('open'): self.game.again() callargs = [] self.game.open_cell((2, 0)) self.game.open_cell((0, 2)) self.game.open_cell((1, 0)) self.assertTrue(self.game.can_undo()) self.game.undo() self.assertEqual(CellState.UNKNOWN, callargs[-1][1]) self.assertEqual(CellState.OPENED, callargs[-2][1]) self.assertTrue(self.game.can_undo()) self.game.undo() self.assertListEqual([CellState.UNKNOWN]*6, [x[1] for x in callargs[-6:]]) self.game.redo() self.assertListEqual([CellState.OPENED]*6, [x[1] for x in callargs[-6:]]) self.assertTrue(self.game.can_redo()) self.game.open_cell((1, 2)) with patch_field_generator(Field((2, 1), {(0, 0)})): self.game.new_game((2, 1), 1) with self.subTest('lose'): self.game.open_cell((1, 0)) self.assertFalse(self.game.is_lose()) self.game.open_cell((0, 0)) self.assertTrue(self.game.is_lose()) self.assertFalse(self.game.can_undo() or self.game.can_redo()) with self.subTest('win'): self.game.again() self.game.open_cell((1, 0)) self.assertFalse(self.game.is_win()) self.game.invert_flag((0, 0)) self.assertTrue(self.game.is_win()) self.assertFalse(self.game.can_undo() or self.game.can_redo()) @unittest.skipIf(sys.platform.startswith('win'), 'Windows not supported') def test_load_bad(self): with tempfile.NamedTemporaryFile(delete=False) as f: name = f.name f.write(b'BAD DATA') old_mode = stat.S_IMODE(os.stat(name).st_mode) try: with self.assertRaises(driver.LoadError): self.game.load_game(name) self.game.new_game((4, 4), 3) self.game.save_game(name) self.assertTrue(os.path.exists(name)) os.chmod(name, 0) with self.assertRaises(driver.LoadError): self.game.load_game(name) self.game.new_game((4, 4), 3) self.game.invert_flag((0, 0)) os.remove(name) self.assertFalse(os.path.exists(name)) with self.assertRaises(driver.LoadError): self.game.load_game(name) self.assertTrue(1, self.game.flags()) finally: if os.path.exists(name): os.chmod(name, old_mode) os.remove(name) def test_save_bad(self): with tempfile.NamedTemporaryFile(delete=False) as f: name = f.name old_mode = stat.S_IMODE(os.stat(name).st_mode) try: with self.assertRaises(driver.SaveError): self.game.save_game(name) self.game.new_game((4, 4), 3) os.chmod(name, 0) with self.assertRaises(driver.SaveError): self.game.save_game(name) finally: if os.path.exists(name): os.chmod(name, old_mode) os.remove(name) def test_save_load(self): with tempfile.NamedTemporaryFile(delete=False) as f: name = f.name try: with patch_field_generator(Field((4, 3), {(0, 0), (3, 1)})): self.game.new_game((4, 3), 2) self.game.open_cell((0, 2)) self.game.invert_flag((0, 0)) self.game.invert_flag((1, 0)) time.sleep(0.3) self.game.undo() self.assertFalse(self.game.saved()) self.game.save_game(name) self.assertTrue(self.game.saved()) self.game.new_game((5, 5), 10) callargs = [] for evt_type in (EventTypes.NEW_GAME, EventTypes.CELL_CHANGED): self.game.add_event_handler( evt_type, lambda *args: callargs.append(args)) self.game.load_game(name) self.assertEqual(((4, 3), 2), callargs[0]) self.assertSetEqual( {(0, 0)}, {x[0] for x in callargs if x[1] == CellState.FLAG}) self.assertSetEqual( {(x, y) for x in (0, 1, 2) for y in (1, 2)}, {x[0] for x in callargs if x[1] == CellState.OPENED}) self.assertSetEqual( {(1, 0), (2, 0), (3, 0), (3, 1), (3, 2)}, {x[0] for x in callargs if x[1] == CellState.UNKNOWN}) self.assertGreaterEqual(self.game.get_time(), 30) self.assertTrue(self.game.can_undo()) finally: if os.path.exists(name): os.remove(name) def tearDown(self): logging.getLogger(driver.LOGGER_NAME).removeHandler(self.lh)