def setUp(self):
     self._disk_1 = Disk(1)
     self._disk_2 = Disk(2)
     self._disk_3 = Disk(3)
     self._disk_4 = Disk(4)
     self._peg_b = self._create_peg_b()
     self._peg_c = self._create_peg_c()
     self._game = Game()
#!/usr/bin/env python3

import sys

from tower_of_hanoi import Game

def print_peg(peg):
    print('{0}: {1}'.format(peg.name(), ' - '.join([str(disk.size()) for disk in peg.disks()])))

def print_pegs(pegs):
    print('==========')
    for peg in sorted(pegs, key=lambda peg: peg.name()):
        print_peg(peg)

if len(sys.argv) != 2:
    print('Usage: {0} <disk_count>'.format(sys.argv[0]))
    sys,exit(1)

disk_count = int(sys.argv[1])
assert disk_count > 0

game = Game()
peg_a = game.create_peg('A', disk_count)
peg_b = game.create_peg('B')
peg_c = game.create_peg('C')

print_pegs([peg_a, peg_b, peg_c]) # display initial state
game.move(disk_count, peg_a, peg_c, peg_b, print_pegs)
class GameTestCase(unittest.TestCase):
    def _create_peg_a(self, disks):
        return Peg('a', disks)

    def _create_peg_b(self, disks=[]):
        return Peg('b', disks)

    def _create_peg_c(self, disks=[]):
        return Peg('c', disks)

    def setUp(self):
        self._disk_1 = Disk(1)
        self._disk_2 = Disk(2)
        self._disk_3 = Disk(3)
        self._disk_4 = Disk(4)
        self._peg_b = self._create_peg_b()
        self._peg_c = self._create_peg_c()
        self._game = Game()

    def test__create_peg__returns_peg_with_specified_name(self):
        name = 'name'

        peg = self._game.create_peg(name)

        self.assertEqual(name, peg.name())

    def test__create_peg__when_disk_count_is_0__returns_empty_peg(self):
        peg = self._game.create_peg('name', 0)

        self.assertEqual([], peg.disks())

    def test__create_peg__when_disk_count_is_1__returns_peg_with_1_disk(self):
        peg = self._game.create_peg('name', 1)

        self.assertEqual([self._disk_1], peg.disks())

    def test__create_peg__when_disk_count_is_3__returns_peg_with_3_disks_in_ascending_order_from_top(self):
        peg = self._game.create_peg('name', 3)

        self.assertEqual([self._disk_3, self._disk_2, self._disk_1], peg.disks())

    def test__move__when_disk_count_is_1__invokes_callback_after_each_move(self):
        move_spy = mock.Mock()
        peg_a = self._create_peg_a([self._disk_1])

        self._game.move(1, peg_a, self._peg_c, self._peg_b, move_spy)

        expected_move_spy_call_args_list = [
            mock.call([
                self._create_peg_a([]),
                self._create_peg_c([self._disk_1]),
                self._create_peg_b([])
            ])
        ]
        self.assertEqual(expected_move_spy_call_args_list, move_spy.call_args_list)

    def test__move__when_disk_count_is_1__moves_disks_from_peg_a_to_peg_c(self):
        peg_a = self._create_peg_a([self._disk_1])

        new_peg_a, new_peg_c, new_peg_b = self._game.move(1, peg_a, self._peg_c, self._peg_b)

        self.assertEqual(self._create_peg_a([]), new_peg_a)
        self.assertEqual(self._create_peg_b([]), new_peg_b)
        self.assertEqual(self._create_peg_c([self._disk_1]), new_peg_c)

    def test__move__when_disk_count_is_2__invokes_callback_after_each_move(self):
        move_spy = mock.Mock()
        peg_a = self._create_peg_a([self._disk_2, self._disk_1])

        self._game.move(2, peg_a, self._peg_c, self._peg_b, move_spy)

        expected_move_spy_call_args_list = [
            mock.call([
                self._create_peg_a([self._disk_2]),
                self._create_peg_b([self._disk_1]),
                self._create_peg_c([])
            ]),
            mock.call([
                self._create_peg_a([]),
                self._create_peg_c([self._disk_2]),
                self._create_peg_b([self._disk_1])
            ]),
            mock.call([
                self._create_peg_b([]),
                self._create_peg_c([self._disk_2, self._disk_1]),
                self._create_peg_a([])
            ])
        ]
        self.assertSequenceEqual(expected_move_spy_call_args_list, move_spy.call_args_list)

    def test__move__when_disk_count_is_2__moves_disks_from_peg_a_to_peg_c(self):
        peg_a = self._create_peg_a([self._disk_2, self._disk_1])

        new_peg_a, new_peg_c, new_peg_b = self._game.move(2, peg_a, self._peg_c, self._peg_b)

        self.assertEqual(self._create_peg_a([]), new_peg_a)
        self.assertEqual(self._create_peg_b([]), new_peg_b)
        self.assertEqual(self._create_peg_c([self._disk_2, self._disk_1]), new_peg_c)

    def test__move__when_disk_count_is_3__moves_disks_from_peg_a_to_peg_c(self):
        peg_a = self._create_peg_a([self._disk_3, self._disk_2, self._disk_1])

        new_peg_a, new_peg_c, new_peg_b = self._game.move(3, peg_a, self._peg_c, self._peg_b)

        self.assertEqual(self._create_peg_a([]), new_peg_a)
        self.assertEqual(self._create_peg_b([]), new_peg_b)
        self.assertEqual(self._create_peg_c([self._disk_3, self._disk_2, self._disk_1]), new_peg_c)

    def test__move__when_disk_count_is_4__moves_disks_from_peg_a_to_peg_c(self):
        peg_a = self._create_peg_a([self._disk_4, self._disk_3, self._disk_2, self._disk_1])

        new_peg_a, new_peg_c, new_peg_b = self._game.move(4, peg_a, self._peg_c, self._peg_b)

        self.assertEqual(self._create_peg_a([]), new_peg_a)
        self.assertEqual(self._create_peg_b([]), new_peg_b)
        self.assertEqual(self._create_peg_c([self._disk_4, self._disk_3, self._disk_2, self._disk_1]), new_peg_c)

    def test__move__when_disk_count_exceeds_source_peg_disk_count__raises_exception(self):
        peg_a = self._create_peg_a([self._disk_1])

        with self.assertRaises(Exception):
            self._game.move(2, peg_a, self._peg_c, self._peg_b)
class GameTestCase(unittest.TestCase):
    class _MoveSpy(mock.Mock):
        '''
        A test spy that can be passed as the `callback` parameter of the
        `Game.move` method.

        Because `Peg`s are mutable, we must copy the peg arguments during each
        call instead of storing them directly.  Otherwise, all calls will
        reflect the final state of the pegs.
        '''

        def _mock_call(self, *args, **kwargs):
            import copy
            args_copy = copy.deepcopy(args)
            kwargs_copy = copy.deepcopy(kwargs)
            return super()._mock_call(*args_copy, **kwargs_copy)

    def _create_peg_a(self, disks):
        return Peg('a', disks)

    def _create_peg_b(self, disks=[]):
        return Peg('b', disks)

    def _create_peg_c(self, disks=[]):
        return Peg('c', disks)

    def setUp(self):
        self._disk_1 = Disk(1)
        self._disk_2 = Disk(2)
        self._disk_3 = Disk(3)
        self._disk_4 = Disk(4)
        self._peg_b = self._create_peg_b()
        self._peg_c = self._create_peg_c()
        self._game = Game()

    def test__create_peg__returns_peg_with_specified_name(self):
        name = 'name'

        peg = self._game.create_peg(name)

        self.assertEqual(name, peg.name())

    def test__create_peg__when_disk_count_is_0__returns_empty_peg(self):
        peg = self._game.create_peg('name', 0)

        self.assertEqual([], peg.disks())

    def test__create_peg__when_disk_count_is_1__returns_peg_with_1_disk(self):
        peg = self._game.create_peg('name', 1)

        self.assertEqual([self._disk_1], peg.disks())

    def test__create_peg__when_disk_count_is_3__returns_peg_with_3_disks_in_ascending_order_from_top(self):
        peg = self._game.create_peg('name', 3)

        self.assertEqual([self._disk_3, self._disk_2, self._disk_1], peg.disks())

    def test__move__when_disk_count_is_1__invokes_callback_after_each_move(self):
        move_spy = GameTestCase._MoveSpy()
        peg_a = self._create_peg_a([self._disk_1])

        self._game.move(1, peg_a, self._peg_c, self._peg_b, move_spy)

        expected_move_spy_call_args_list = [
            mock.call([
                self._create_peg_a([]),
                self._create_peg_c([self._disk_1]),
                self._create_peg_b([])
            ])
        ]
        self.assertEqual(expected_move_spy_call_args_list, move_spy.call_args_list)

    def test__move__when_disk_count_is_1__moves_disks_from_peg_a_to_peg_c(self):
        peg_a = self._create_peg_a([self._disk_1])

        self._game.move(1, peg_a, self._peg_c, self._peg_b)

        self.assertEqual(self._create_peg_a([]), peg_a)
        self.assertEqual(self._create_peg_b([]), self._peg_b)
        self.assertEqual(self._create_peg_c([self._disk_1]), self._peg_c)

    def test__move__when_disk_count_is_2__invokes_callback_after_each_move(self):
        move_spy = GameTestCase._MoveSpy()
        peg_a = self._create_peg_a([self._disk_2, self._disk_1])

        self._game.move(2, peg_a, self._peg_c, self._peg_b, move_spy)

        expected_move_spy_call_args_list = [
            mock.call([
                self._create_peg_a([self._disk_2]),
                self._create_peg_b([self._disk_1]),
                self._create_peg_c([])
            ]),
            mock.call([
                self._create_peg_a([]),
                self._create_peg_c([self._disk_2]),
                self._create_peg_b([self._disk_1])
            ]),
            mock.call([
                self._create_peg_b([]),
                self._create_peg_c([self._disk_2, self._disk_1]),
                self._create_peg_a([])
            ])
        ]
        self.assertEqual(expected_move_spy_call_args_list, move_spy.call_args_list)

    def test__move__when_disk_count_is_2__moves_disks_from_peg_a_to_peg_c(self):
        peg_a = self._create_peg_a([self._disk_2, self._disk_1])

        self._game.move(2, peg_a, self._peg_c, self._peg_b)

        self.assertEqual(self._create_peg_a([]), peg_a)
        self.assertEqual(self._create_peg_b([]), self._peg_b)
        self.assertEqual(self._create_peg_c([self._disk_2, self._disk_1]), self._peg_c)

    def test__move__when_disk_count_is_3__moves_disks_from_peg_a_to_peg_c(self):
        peg_a = self._create_peg_a([self._disk_3, self._disk_2, self._disk_1])

        self._game.move(3, peg_a, self._peg_c, self._peg_b)

        self.assertEqual(self._create_peg_a([]), peg_a)
        self.assertEqual(self._create_peg_b([]), self._peg_b)
        self.assertEqual(self._create_peg_c([self._disk_3, self._disk_2, self._disk_1]), self._peg_c)

    def test__move__when_disk_count_is_4__moves_disks_from_peg_a_to_peg_c(self):
        peg_a = self._create_peg_a([self._disk_4, self._disk_3, self._disk_2, self._disk_1])

        self._game.move(4, peg_a, self._peg_c, self._peg_b)

        self.assertEqual(self._create_peg_a([]), peg_a)
        self.assertEqual(self._create_peg_b([]), self._peg_b)
        self.assertEqual(self._create_peg_c([self._disk_4, self._disk_3, self._disk_2, self._disk_1]), self._peg_c)

    def test__move__when_disk_count_exceeds_source_peg_disk_count__raises_exception(self):
        peg_a = self._create_peg_a([self._disk_1])

        with self.assertRaises(Exception):
            self._game.move(2, peg_a, self._peg_c, self._peg_b)