# -*- coding: utf-8 -*-

import hashlib

import nose
from nose.tools.trivial import eq_

from cmonkey import (
    CookieClient,
    SignatureClient,
    SignatureBuilder,
    IntegrationClient,
)

try:
    import mock
except ImportError:
    from unittest import mock


class Test_SignatureBuilder(object):

    APIKEY = '<KEY>'
    SECRETKEY = '<KEY>'

    def test_build(self):
        params = {
            'command': 'listUsers',
            'keyword': 'ad',
        }
        builder = SignatureBuilder(self.APIKEY, self.SECRETKEY)
        signature = builder.build(params)
        eq_(signature, b'QEq3xbEHhBmSfFw4RwVzkWyQYWc=')

    def test_contains_slash(self):
        params = {
            'command': 'createZone',
            'dns1': '203.0.113.1',
            'internaldns1': '198.51.100.1',
            'name': 'sample-zone',
            'networktype': 'Advanced',
            'guestcidraddress': '192.0.2.0/24',
        }
        builder = SignatureBuilder(self.APIKEY, self.SECRETKEY)
        signature = builder.build(params)
        eq_(signature, b'4+XLXpBJuqKH/BVg2WNYRcPFjTY=')


class Test_CookieClient(object):

    def test_request(self):
        endpoint = 'http://localhost:8080/client/api'
        username = 'admin'
        password = 'password'
        client = CookieClient(endpoint, username, password, async_block=False)
        # モックアウト
        sessionkey = 'hogehoge'
        client.login = mock.MagicMock(return_value=sessionkey)
        response = mock.Mock()
        response.status_code = 200
        response.headers = {}
        response.json = lambda: {}
        client.request = mock.Mock(return_value=response)
        # 実行
        params = {
            'account': 'admin',
            'response': 'json',
        }
        client.listUsers(**params)
        # 検証
        calls = [
            mock.call(username, password, False)
        ]
        client.login.assert_has_calls(calls)
        params['command'] = 'listUsers'
        params['sessionkey'] = sessionkey
        calls = [
            mock.call('GET', params, None, None)
        ]
        client.request.assert_has_calls(calls)

    def test_login_digest(self):
        self._test_login(digest=True)

    def test_login_no_digest(self):
        self._test_login(digest=False)

    def _test_login(self, digest):
        endpoint = 'http://localhost:8080/client/api'
        username = 'admin'
        password = 'password'
        client = CookieClient(endpoint, username, password, digest=digest)
        # モックアウト
        response_mock = mock.Mock()
        response_mock.status_code = 200
        response_mock.json = lambda: {
            'loginresponse': {
                'sessionkey': 'hoge',
            },
        }
        client.request = mock.MagicMock(return_value=response_mock)
        # 実行
        client.login(username, password, digest)
        # 検証
        params = {
            'response': 'json',
        }
        headers = {
            'Content-Type': 'application/x-www-form-urlencoded',
        }
        password = self._md5(password) if digest else password
        data = {
            'command': 'login',
            'username': username,
            'password': password,
            'domain': '/',
        }
        calls = [
            mock.call('POST', params, headers, data)
        ]
        client.request.assert_has_calls(calls)

    def _md5(self, s):
        m = hashlib.md5()
        m.update(s.encode())
        return m.hexdigest()


class Test_IntegrationClient(object):

    def test_request(self):
        endpoint = 'http://localhost:8080/client/api'
        client = IntegrationClient(endpoint, async_block=False)
        # モックアウト
        response = mock.Mock()
        response.status_code = 200
        response.headers = {}
        response.json = lambda: {}
        client.request = mock.Mock(return_value=response)
        # 実行
        params = {
            'account': 'admin',
            'response': 'json',
        }
        client.listUsers(**params)
        # 検証
        params['command'] = 'listUsers'
        calls = [
            mock.call('GET', params, None, None)
        ]
        client.request.assert_has_calls(calls)

    def test_async_block(self):
        endpoint = 'http://localhost:8080/client/api'
        client = IntegrationClient(endpoint, async_block=True)
        # モックアウト
        r1 = mock.Mock()
        r1.status_code = 200
        r1.headers = {}
        r1.json = lambda: {
            'addvpnuserresponse': {
                'jobid': 1,
            }
        }
        r2 = mock.Mock()
        r2.status_code = 200
        r2.headers = {}
        r2.json = lambda: {
            'queryasyncjobresultresponse': {
                'jobstatus': 0,
            }
        }
        r3 = mock.Mock()
        r3.status_code = 200
        r3.headers = {}
        r3.json = lambda: {
            'queryasyncjobresultresponse': {
                'jobstatus': 1,
            }
        }
        client.request = mock.Mock(side_effect=[r1, r2, r3])
        # 実行
        params = {
            'username': 'foo',
            'password': '<PASSWORD>',
            'response': 'json',
        }
        client.addVpnUser(**params)
        # 検証
        params['command'] = 'addVpnUser'
        async_params = {
            'command': 'queryAsyncJobResult',
            'jobid': 1,
            'response': 'json',
        }
        calls = [
            mock.call('GET', params, None, None),
            mock.call('GET', async_params, None, None),
            mock.call('GET', async_params, None, None),
        ]
        client.request.assert_has_calls(calls)


class Test_SignatureClient(object):

    APIKEY = '<KEY>'
    SECRETKEY = '<KEY>'
    SIGNATURE = b'jhoz5uOKJp8707r9MeMJjCOVLqM='

    def test_request(self):
        endpoint = 'http://localhost:8080/client/api'
        client = SignatureClient(
            endpoint,
            self.APIKEY,
            self.SECRETKEY,
            async_block=False,
        )
        # モックアウト
        response = mock.Mock()
        response.status_code = 200
        response.headers = {}
        response.json = lambda: {}
        client.request = mock.Mock(return_value=response)
        # 実行
        params = {
            'account': 'admin',
            'response': 'json',
        }
        client.listUsers(**params)
        # 検証
        params['command'] = 'listUsers'
        params['apikey'] = self.APIKEY
        params['signature'] = self.SIGNATURE
        calls = [
            mock.call('GET', params, None, None)
        ]
        client.request.assert_has_calls(calls)


if __name__ == "__main__":
    nose.main(argv=['nosetests', '-s', '-v'], defaultTest=__file__)

# -*- coding: utf-8 -*-

import hashlib

import nose
from nose.tools.trivial import eq_

from cmonkey import (
    CookieClient,
    SignatureClient,
    SignatureBuilder,
    IntegrationClient,
)

try:
    import mock
except ImportError:
    from unittest import mock


class Test_SignatureBuilder(object):

    APIKEY = '<KEY>'
    SECRETKEY = '<KEY>'

    def test_build(self):
        params = {
            'command': 'listUsers',
            'keyword': 'ad',
        }
        builder = SignatureBuilder(self.APIKEY, self.SECRETKEY)
        signature = builder.build(params)
        eq_(signature, b'QEq3xbEHhBmSfFw4RwVzkWyQYWc=')

    def test_contains_slash(self):
        params = {
            'command': 'createZone',
            'dns1': '203.0.113.1',
            'internaldns1': '198.51.100.1',
            'name': 'sample-zone',
            'networktype': 'Advanced',
            'guestcidraddress': '192.0.2.0/24',
        }
        builder = SignatureBuilder(self.APIKEY, self.SECRETKEY)
        signature = builder.build(params)
        eq_(signature, b'4+XLXpBJuqKH/BVg2WNYRcPFjTY=')


class Test_CookieClient(object):

    def test_request(self):
        endpoint = 'http://localhost:8080/client/api'
        username = 'admin'
        password = 'password'
        client = CookieClient(endpoint, username, password, async_block=False)
        # モックアウト
        sessionkey = 'hogehoge'
        client.login = mock.MagicMock(return_value=sessionkey)
        response = mock.Mock()
        response.status_code = 200
        response.headers = {}
        response.json = lambda: {}
        client.request = mock.Mock(return_value=response)
        # 実行
        params = {
            'account': 'admin',
            'response': 'json',
        }
        client.listUsers(**params)
        # 検証
        calls = [
            mock.call(username, password, False)
        ]
        client.login.assert_has_calls(calls)
        params['command'] = 'listUsers'
        params['sessionkey'] = sessionkey
        calls = [
            mock.call('GET', params, None, None)
        ]
        client.request.assert_has_calls(calls)

    def test_login_digest(self):
        self._test_login(digest=True)

    def test_login_no_digest(self):
        self._test_login(digest=False)

    def _test_login(self, digest):
        endpoint = 'http://localhost:8080/client/api'
        username = 'admin'
        password = 'password'
        client = CookieClient(endpoint, username, password, digest=digest)
        # モックアウト
        response_mock = mock.Mock()
        response_mock.status_code = 200
        response_mock.json = lambda: {
            'loginresponse': {
                'sessionkey': 'hoge',
            },
        }
        client.request = mock.MagicMock(return_value=response_mock)
        # 実行
        client.login(username, password, digest)
        # 検証
        params = {
            'response': 'json',
        }
        headers = {
            'Content-Type': 'application/x-www-form-urlencoded',
        }
        password = self._md5(password) if digest else password
        data = {
            'command': 'login',
            'username': username,
            'password': password,
            'domain': '/',
        }
        calls = [
            mock.call('POST', params, headers, data)
        ]
        client.request.assert_has_calls(calls)

    def _md5(self, s):
        m = hashlib.md5()
        m.update(s.encode())
        return m.hexdigest()


class Test_IntegrationClient(object):

    def test_request(self):
        endpoint = 'http://localhost:8080/client/api'
        client = IntegrationClient(endpoint, async_block=False)
        # モックアウト
        response = mock.Mock()
        response.status_code = 200
        response.headers = {}
        response.json = lambda: {}
        client.request = mock.Mock(return_value=response)
        # 実行
        params = {
            'account': 'admin',
            'response': 'json',
        }
        client.listUsers(**params)
        # 検証
        params['command'] = 'listUsers'
        calls = [
            mock.call('GET', params, None, None)
        ]
        client.request.assert_has_calls(calls)

    def test_async_block(self):
        endpoint = 'http://localhost:8080/client/api'
        client = IntegrationClient(endpoint, async_block=True)
        # モックアウト
        r1 = mock.Mock()
        r1.status_code = 200
        r1.headers = {}
        r1.json = lambda: {
            'addvpnuserresponse': {
                'jobid': 1,
            }
        }
        r2 = mock.Mock()
        r2.status_code = 200
        r2.headers = {}
        r2.json = lambda: {
            'queryasyncjobresultresponse': {
                'jobstatus': 0,
            }
        }
        r3 = mock.Mock()
        r3.status_code = 200
        r3.headers = {}
        r3.json = lambda: {
            'queryasyncjobresultresponse': {
                'jobstatus': 1,
            }
        }
        client.request = mock.Mock(side_effect=[r1, r2, r3])
        # 実行
        params = {
            'username': 'foo',
            'password': '<PASSWORD>',
            'response': 'json',
        }
        client.addVpnUser(**params)
        # 検証
        params['command'] = 'addVpnUser'
        async_params = {
            'command': 'queryAsyncJobResult',
            'jobid': 1,
            'response': 'json',
        }
        calls = [
            mock.call('GET', params, None, None),
            mock.call('GET', async_params, None, None),
            mock.call('GET', async_params, None, None),
        ]
        client.request.assert_has_calls(calls)


class Test_SignatureClient(object):

    APIKEY = '<KEY>'
    SECRETKEY = '<KEY>'
    SIGNATURE = b'jhoz5uOKJp8707r9MeMJjCOVLqM='

    def test_request(self):
        endpoint = 'http://localhost:8080/client/api'
        client = SignatureClient(
            endpoint,
            self.APIKEY,
            self.SECRETKEY,
            async_block=False,
        )
        # モックアウト
        response = mock.Mock()
        response.status_code = 200
        response.headers = {}
        response.json = lambda: {}
        client.request = mock.Mock(return_value=response)
        # 実行
        params = {
            'account': 'admin',
            'response': 'json',
        }
        client.listUsers(**params)
        # 検証
        params['command'] = 'listUsers'
        params['apikey'] = self.APIKEY
        params['signature'] = self.SIGNATURE
        calls = [
            mock.call('GET', params, None, None)
        ]
        client.request.assert_has_calls(calls)


if __name__ == "__main__":
    nose.main(argv=['nosetests', '-s', '-v'], defaultTest=__file__)

# -*- coding: utf-8 -*- # モックアウト # 実行 # 検証 # モックアウト # 実行 # 検証 # モックアウト # 実行 # 検証 # モックアウト # 実行 # 検証 # モックアウト # 実行 # 検証