class SIPAuthServeOffNominalSubscriberTestCase(unittest.TestCase):
    """Testing the components.SIPAuthServe class.

  Applying off-nominal uses of the 'subscribers' command and 'sipauthserve'
  target.
  """
    def setUp(self):
        self.sipauthserve_connection = SIPAuthServe()
        # mock a zmq socket with a simple recv return value
        self.sipauthserve_connection.socket = mock.Mock()
        self.sipauthserve_connection.socket.recv.return_value = json.dumps({
            'code':
            200,
            'data':
            'sample',
            'dirty':
            0
        })

    def test_get_nonexistent_subscribers(self):
        """Requesting a nonexistent subscriber returns an empty array."""
        self.sipauthserve_connection.socket.recv.return_value = json.dumps({
            'code':
            404,
            'data':
            'not found'
        })
        response = self.sipauthserve_connection.get_subscribers(
            imsi='non-existent')
        self.assertEqual([], response)

    def test_delete_subscriber_when_sqlite_unavailable(self):
        """Invalid request when sqlite is unavailble."""
        self.sipauthserve_connection.socket.recv.return_value = json.dumps({
            'code':
            503,
            'data': {
                'sip_buddies': 'something bad',
                'dialdata_table': 'this could be ok'
            }
        })
        with self.assertRaises(InvalidRequestError):
            self.sipauthserve_connection.delete_subscriber(310150123456789)
class SIPAuthServeNominalSubscriberTestCase(unittest.TestCase):
    """Testing the components.SIPAuthServe class.

  Applying nominal uses of the 'subscribers' command and 'sipauthserve' target.
  """
    def setUp(self):
        self.sipauthserve_connection = SIPAuthServe()
        # mock a zmq socket with a simple recv return value
        self.sipauthserve_connection.socket = mock.Mock()
        self.sipauthserve_connection.socket.recv.return_value = json.dumps({
            'code':
            204,
            'data': [{
                'exten': '5551234',
                'name': 'sample'
            }],
            'dirty':
            0
        })

    def test_get_all_subscribers(self):
        """Should send a message over zmq and get a response."""
        # Using 'side_effect' to mock multiple return values from the socket.  This
        # method makes quite a few requests.
        self.sipauthserve_connection.socket.recv.side_effect = [
            json.dumps({
                'code':
                200,
                'data': [{
                    'name': 'subscriber_a',
                    'exten': '5551234',
                    'ipaddr': '127.0.0.1',
                    'port': '5555'
                }, {
                    'name': 'subscriber_b',
                    'exten': '5559876',
                    'ipaddr': '127.0.0.1',
                    'port': '5555'
                }]
            }),
            json.dumps({
                'code': 200,
                'data': [{
                    'exten': '5551234'
                }]
            }),
            json.dumps({
                'code': 200,
                'data': [{
                    'account_balance': '3000'
                }]
            }),
            json.dumps({
                'code': 200,
                'data': [{
                    'callerid': '5551234'
                }]
            }),
            # Return values for a second mocked subscriber.
            json.dumps({
                'code': 200,
                'data': [{
                    'exten': '5559876'
                }]
            }),
            json.dumps({
                'code': 200,
                'data': [{
                    'account_balance': '100000'
                }]
            }),
            json.dumps({
                'code': 200,
                'data': [{
                    'callerid': '5559876'
                }]
            }),
        ]
        response = self.sipauthserve_connection.get_subscribers()
        self.assertTrue(self.sipauthserve_connection.socket.send.called)
        self.assertTrue(self.sipauthserve_connection.socket.recv.called)
        self.assertEqual(2, len(response))
        self.assertEqual('subscriber_a', response[0]['name'])
        self.assertEqual('100000', response[1]['account_balance'])

    def test_get_a_subscriber(self):
        """Requesting a subscriber should send a zmq message and get a response."""
        self.sipauthserve_connection.socket.recv.side_effect = [
            json.dumps({
                'code':
                200,
                'data': [{
                    'name': 'subscriber_a',
                    'exten': '5551234',
                    'ipaddr': '127.0.0.1',
                    'port': '5555'
                }]
            }),
            json.dumps({
                'code': 200,
                'data': [{
                    'exten': '5551234'
                }]
            }),
            json.dumps({
                'code': 200,
                'data': [{
                    'account_balance': '3000'
                }]
            }),
            json.dumps({
                'code': 200,
                'data': [{
                    'callerid': '5551234'
                }]
            }),
        ]
        response = self.sipauthserve_connection.get_subscribers(
            imsi='IMSI000000')
        self.assertTrue(self.sipauthserve_connection.socket.send.called)
        self.assertTrue(self.sipauthserve_connection.socket.recv.called)
        self.assertEqual(1, len(response))
        self.assertEqual('subscriber_a', response[0]['name'])
        self.assertEqual('3000', response[0]['account_balance'])

    def test_create_subscriber_with_ki(self):
        """Creating a subscriber should send a zmq message and get a response."""
        self.sipauthserve_connection.socket.recv.side_effect = [
            # First, get_subs should reply with 'not found' since this sub is new.
            json.dumps({'code': 404}),
            # The actual create sub message should succeed.
            json.dumps({'code': 200}),
            # The add_number request triggers a number lookup (should fail) and then
            # an actual "dialdata_table create" message which should succeed.
            json.dumps({'code': 404}),
            json.dumps({'code': 200}),
            # Then the OpenBTS ipaddr and port updates should succeed.
            json.dumps({'code': 200}),
            json.dumps({'code': 200}),
        ]
        self.sipauthserve_connection.create_subscriber(310150123456789,
                                                       123456789,
                                                       '127.0.0.1',
                                                       '1234',
                                                       ki='abc')

    def test_create_subscriber_sans_ki(self):
        """Creating a subscriber without a specficied ki uses zmq."""
        self.sipauthserve_connection.socket.recv.side_effect = [
            # First, get_subs should reply with 'not found' since this sub is new.
            json.dumps({'code': 404}),
            # The actual create sub message should succeed.
            json.dumps({'code': 200}),
            # The add_number request triggers a number lookup (should fail) and then
            # an actual "dialdata_table create" message which should succeed.
            json.dumps({'code': 404}),
            json.dumps({'code': 200}),
            # Then the OpenBTS ipaddr and port updates should succeed.
            json.dumps({'code': 200}),
            json.dumps({'code': 200}),
        ]
        self.sipauthserve_connection.create_subscriber(310150123456789,
                                                       123456789, '127.0.0.1',
                                                       '1234')

    def test_delete_subscriber_by_imsi(self):
        """Deleting a subscriber by IMSI should use zmq."""
        response = self.sipauthserve_connection.delete_subscriber(
            310150123456789)
        self.assertTrue(self.sipauthserve_connection.socket.send.called)
        expected_message = json.dumps({
            'command': 'subscribers',
            'action': 'delete',
            'match': {
                'imsi': '310150123456789'
            }
        })
        self.assertEqual(self.sipauthserve_connection.socket.send.call_args[0],
                         (expected_message, ))
        self.assertTrue(self.sipauthserve_connection.socket.recv.called)
        self.assertEqual(response.code, SuccessCode.NoContent)