def setUp(self):
     self.host = 'localhost'
     self.port = 8000
     self.test_client = FibonacciNumberCalculatorClient(self.host, self.port)
class ClientMethodTests(unittest.TestCase):

    def setUp(self):
        self.host = 'localhost'
        self.port = 8000
        self.test_client = FibonacciNumberCalculatorClient(self.host, self.port)


    @patch('builtins.input')
    def test_user_input_received(self, mock_input):
        mock_input.return_value = 'user input'
        self.test_client._receive_user_input()

        self.assertEqual('user input', self.test_client.user_input)
        self.assertEqual(1, mock_input.call_count)


    def test_user_input_is_empty_string(self):
        self.test_client.user_input = ''

        self.assertRaises(SystemExit, lambda: self.test_client._check_user_input())


    def test_user_input_is_not_an_integer(self):
        self.test_client.user_input = 'w3'

        self.assertRaises(SystemExit, lambda: self.test_client._check_user_input())


    def test_user_input_is_a_negative_integer(self):
        self.test_client.user_input = '-8'

        self.assertRaises(SystemExit, lambda: self.test_client._check_user_input())


    def test_fibonacci_input_is_set_after_user_input_checked(self):
        self.test_client.user_input = '8'
        self.test_client._check_user_input()

        self.assertEqual(8, self.test_client.fibonacci_input)


    def test_fibonacci_input_is_greater_than_max_unsigned_int(self):
        self.test_client.fibonacci_input = 4294967296
        self.test_client._pack_fibonacci_input()

        self.assertEqual(b'\x00\x00\x00\x00\x01\x00\x00\x00',
            self.test_client.packed_fibonacci_input)


    def test_fibonacci_input_is_equal_to_max_unsigned_int(self):
        self.test_client.fibonacci_input = 4294967295
        self.test_client._pack_fibonacci_input()

        self.assertEqual(b'\xff\xff\xff\xff',
            self.test_client.packed_fibonacci_input)


    def test_fibonacci_input_is_equal_to_zero(self):
        self.test_client.fibonacci_input = 0
        self.test_client._pack_fibonacci_input()

        self.assertEqual(b'\x00\x00\x00\x00',
            self.test_client.packed_fibonacci_input)


    def test_fibonacci_input_is_less_than_zero(self):
        self.test_client.fibonacci_input = -5
        
        self.assertRaises(SystemExit, lambda: self.test_client._pack_fibonacci_input())


    @patch.object(socket, 'socket')
    def test_socket_object_can_not_be_created(self, mock_socket):
        socket.socket.side_effect = socket.error

        self.assertRaises(SystemExit, lambda: self.test_client._send_to_and_receive_from_server())


    @patch.object(socket.socket, 'connect')
    def test_socket_can_not_connect_to_server(self, mock_connect):
        socket.socket.connect.side_effect = socket.error
        
        self.assertRaises(SystemExit, lambda: self.test_client._send_to_and_receive_from_server())


    @patch.object(socket.socket, 'connect')
    @patch.object(socket.socket, 'sendall')
    @patch.object(socket.socket, 'recv')
    def test_socket_can_receive_4_byte_object_from_server(self, mock_connect, mock_sendall, mock_recv):
        socket.socket.recv.return_value = b'\x00\x00\x00\x00'
        self.test_client.packed_fibonacci_input = b'test input'
        self.test_client._send_to_and_receive_from_server()
        
        self.assertEqual(b'\x00\x00\x00\x00', self.test_client.packed_fibonacci_output)


    @patch.object(socket.socket, 'connect')
    @patch.object(socket.socket, 'sendall')
    @patch.object(socket.socket, 'recv')
    def test_socket_can_receive_8_byte_object_from_server(self, mock_connect, mock_sendall, mock_recv):
        socket.socket.recv.return_value = b'\x00\x00\x00\x00\x01\x00\x00\x00'
        self.test_client.packed_fibonacci_input = b'test input'
        self.test_client._send_to_and_receive_from_server()
        
        self.assertEqual(b'\x00\x00\x00\x00\x01\x00\x00\x00', self.test_client.packed_fibonacci_output)


    def test_packed_fibonacci_output_is_greater_than_max_unsigned_int(self):
        self.test_client.packed_fibonacci_output = b'\x00\x00\x00\x00\x01\x00\x00\x00'
        self.test_client._unpack_fibonacci_output()

        self.assertEqual(4294967296, self.test_client.fibonacci_output)


    def test_packed_fibonacci_output_is_equal_to_max_unsigned_int(self):
        self.test_client.packed_fibonacci_output = b'\xff\xff\xff\xff'
        self.test_client._unpack_fibonacci_output()

        self.assertEqual(4294967295, self.test_client.fibonacci_output)


    def test_packed_fibonacci_output_is_equal_to_zero(self):
        self.test_client.packed_fibonacci_output = b'\x00\x00\x00\x00'
        self.test_client._unpack_fibonacci_output()

        self.assertEqual(0, self.test_client.fibonacci_output)