Ejemplo n.º 1
0
 def initialize(self):
     self.config = DefaultConfig()
     self.config.UnitTests.templates = getWMBASE() + '/src/templates/WMCore/WebTools'
     self.config.Webtools.section_('server')
     self.config.Webtools.server.socket_timeout = 1
     self.urlbase = self.config.getServerUrl()
     self.cache_path = tempfile.mkdtemp()
Ejemplo n.º 2
0
 def initialize(self):
     self.config = DefaultConfig('WMCore.HTTPFrontEnd.WMBS.WMBSRESTModel')
     dbUrl = os.environ.get("DATABASE", None)
     self.config.setDBUrl(dbUrl)
     # mysql example
     #self.config.setDBUrl('mysql://[email protected]:3306/TestDB')
     #self.config.setDBSocket('/var/lib/mysql/mysql.sock')
     self.schemaModules = ["WMCore.WMBS", "WMCore.ResourceControl"]
Ejemplo n.º 3
0
    def initialize(self):
        self.config = DefaultConfig('CRABRESTModelMock')
        self.config.Webtools.environment = 'development'
        self.config.Webtools.error_log_level = logging.ERROR
        self.config.Webtools.access_log_level = logging.ERROR
        self.config.Webtools.port = 8518
        self.config.Webtools.host = '127.0.0.1'
        self.config.UnitTests.object = 'CRABRESTModelMock'
        #self.config.UnitTests.views.active.rest.logLevel = 'DEBUG'

        self.urlbase = self.config.getServerUrl()
Ejemplo n.º 4
0
    def initialize(self):
        self.config = DefaultConfig('WMCore_t.WebTools_t.DummyNestedModel')
        do_debug = True

        self.config.Webtools.environment = 'development'
        if do_debug:
            self.config.Webtools.error_log_level = logging.DEBUG
            self.config.Webtools.access_log_level = logging.DEBUG
        else:
            self.config.Webtools.error_log_level = logging.WARNING
            self.config.Webtools.access_log_level = logging.WARNING

        self.urlbase = self.config.getServerUrl()
Ejemplo n.º 5
0
class testRepeatCalls(RESTBaseUnitTest):
    def initialize(self):
        self.config = DefaultConfig()
        self.config.UnitTests.templates = getWMBASE() + '/src/templates/WMCore/WebTools'
        self.config.Webtools.section_('server')
        self.config.Webtools.server.socket_timeout = 1
        self.urlbase = self.config.getServerUrl()
        self.cache_path = tempfile.mkdtemp()

    def tearDown(self):
        shutil.rmtree(self.cache_path, ignore_errors = True)
        self.rt.stop()

    def test10Calls(self):
        fail_count = 0
        req = Requests.Requests(self.urlbase, {'req_cache_path': self.cache_path})

        for i in range(0, 5):
            time.sleep(i)
            print 'test %s starting at %s' % (i, time.time())
            try:
                result = req.get('/', incoming_headers={'Cache-Control':'no-cache'})
                self.assertEqual(False, result[3])
                self.assertEqual(200, result[1])
            except HTTPException, he:
                print 'test %s raised a %s error' % (i, he.status)
                fail_count += 1
            except Exception, e:
                print 'test %s raised an unexpected exception of type %s' % (i, type(e))
                print e
                fail_count += 1
Ejemplo n.º 6
0
class FakeRESTServer(RESTBaseUnitTest):
    """
    Loads a the CRABRESTModelMock REST interface which emulates the CRABRESTModel class.
    When testing a command which requires an interaction with the server wi will contact
    this class.
    """

    def initialize(self):
        self.config = DefaultConfig('CRABRESTModelMock')
        self.config.Webtools.environment = 'development'
        self.config.Webtools.error_log_level = logging.ERROR
        self.config.Webtools.access_log_level = logging.ERROR
        self.config.Webtools.port = 8518
        self.config.Webtools.host = '127.0.0.1'
        self.config.UnitTests.object = 'CRABRESTModelMock'
        #self.config.UnitTests.views.active.rest.logLevel = 'DEBUG'

        self.urlbase = self.config.getServerUrl()


    def setUp(self):
        """
        _setUp_
        """
        RESTBaseUnitTest.setUp(self)


    def tearDown(self):
        RESTBaseUnitTest.tearDown(self)
Ejemplo n.º 7
0
class NestedModelTest(RESTBaseUnitTest):
    def initialize(self):
        self.config = DefaultConfig('WMCore_t.WebTools_t.DummyNestedModel')
        do_debug = True

        self.config.Webtools.environment = 'development'
        if do_debug:
            self.config.Webtools.error_log_level = logging.DEBUG
            self.config.Webtools.access_log_level = logging.DEBUG
        else:
            self.config.Webtools.error_log_level = logging.WARNING
            self.config.Webtools.access_log_level = logging.WARNING

        self.urlbase = self.config.getServerUrl()

    def testOuterFooPass(self):
        verb = 'GET'
        url = self.urlbase + 'foo'
        output = {'code': 200, 'data': '"foo"'}
        expireTime = 3600
        methodTest(verb, url, output=output, expireTime=expireTime)

        url = self.urlbase + 'foo/test'
        output = {'code': 200, 'data': '"foo test"'}
        methodTest(verb, url, output=output, expireTime=expireTime)

        url = self.urlbase + 'foo'
        request_input = {'message': 'test'}
        output = {'code': 200, 'data': '"foo test"'}
        methodTest(verb,
                   url,
                   request_input=request_input,
                   output=output,
                   expireTime=expireTime)

    def testInnerPingPass(self):
        verb = 'GET'
        url = self.urlbase + 'foo/ping'
        output = {'code': 200, 'data': '"ping"'}
        expireTime = 3600

        methodTest(verb, url, output=output, expireTime=expireTime)

    def testOuterFooError(self):
        verb = 'GET'
        url = self.urlbase + 'foo/123/567'
        output = {'code': 400}
        methodTest(verb, url, output=output)

    # This test is flipping back and forth in Jenkins. Perhaps due to port 8888 not being available.
    # Disabling for now
    @attr("integration")
    def testInnerPingError(self):
        verb = 'GET'
        url = self.urlbase + 'foo/123/ping'
        output = {'code': 400}
        methodTest(verb, url, output=output)

        url = self.urlbase + 'foo/ping/123'
        methodTest(verb, url, output=output)
Ejemplo n.º 8
0
class testRepeatCalls(RESTBaseUnitTest):
    def initialize(self):
        self.config = DefaultConfig()
        self.config.UnitTests.templates = getWMBASE(
        ) + '/src/templates/WMCore/WebTools'
        self.config.Webtools.section_('server')
        self.config.Webtools.server.socket_timeout = 1
        self.urlbase = self.config.getServerUrl()
        self.cache_path = tempfile.mkdtemp()

    def tearDown(self):
        shutil.rmtree(self.cache_path, ignore_errors=True)
        self.rt.stop()

    def test10Calls(self):
        fail_count = 0
        req = Requests.Requests(self.urlbase,
                                {'req_cache_path': self.cache_path})

        for i in range(0, 5):
            time.sleep(i)
            print 'test %s starting at %s' % (i, time.time())
            try:
                result = req.get(
                    '/', incoming_headers={'Cache-Control': 'no-cache'})
                self.assertEqual(False, result[3])
                self.assertEqual(200, result[1])
            except HTTPException, he:
                print 'test %s raised a %s error' % (i, he.status)
                fail_count += 1
            except Exception, e:
                print 'test %s raised an unexpected exception of type %s' % (
                    i, type(e))
                print e
                fail_count += 1
Ejemplo n.º 9
0
 def initialize(self):
     self.config = DefaultConfig('PyCurlRESTModel')
     self.config.Webtools.environment = 'development'
     self.config.Webtools.error_log_level = logging.ERROR
     self.config.Webtools.access_log_level = logging.ERROR
     self.config.Webtools.port = 8888
     self.config.Webtools.host = '127.0.0.1'
     self.config.UnitTests.object = 'PyCurlRESTModel'
Ejemplo n.º 10
0
 def initialize(self):
     self.config = DefaultConfig('WMCore_t.Services_t.PyCurlRESTModel')
     self.config.Webtools.environment = 'development'
     self.config.Webtools.error_log_level = logging.ERROR
     self.config.Webtools.access_log_level = logging.ERROR
     self.config.Webtools.port = 8888
     self.config.Webtools.host = '127.0.0.1'
     self.config.UnitTests.object = 'WMCore_t.Services_t.PyCurlRESTModel'
     self.requestHandler = Requests('http://127.0.0.1:8888/unittests/rest/')
Ejemplo n.º 11
0
 def initialize(self):
     self.config = DefaultConfig(
             'WMCore.HTTPFrontEnd.WMBS.WMBSRESTModel')
     dbUrl = os.environ.get("DATABASE", None)
     self.config.setDBUrl(dbUrl)
     # mysql example
     #self.config.setDBUrl('mysql://[email protected]:3306/TestDB')
     #self.config.setDBSocket('/var/lib/mysql/mysql.sock')
     self.schemaModules = ["WMCore.WMBS", "WMCore.ResourceControl", "BossAir"]
Ejemplo n.º 12
0
class NestedModelTest(RESTBaseUnitTest):
    def initialize(self):
        self.config = DefaultConfig('WMCore_t.WebTools_t.DummyNestedModel')
        do_debug = True

        self.config.Webtools.environment = 'development'
        if do_debug:
            self.config.Webtools.error_log_level = logging.DEBUG
            self.config.Webtools.access_log_level = logging.DEBUG
        else:
            self.config.Webtools.error_log_level = logging.WARNING
            self.config.Webtools.access_log_level = logging.WARNING

        self.urlbase = self.config.getServerUrl()

    def testOuterFooPass(self):
        verb = 'GET'
        url = self.urlbase + 'foo'
        output = {'code': 200, 'data': '"foo"'}
        expireTime = 3600
        methodTest(verb, url, output=output, expireTime=expireTime)

        url = self.urlbase + 'foo/test'
        output = {'code': 200, 'data': '"foo test"'}
        methodTest(verb, url, output=output, expireTime=expireTime)

        url = self.urlbase + 'foo'
        request_input = {'message': 'test'}
        output = {'code': 200, 'data': '"foo test"'}
        methodTest(verb,
                   url,
                   request_input=request_input,
                   output=output,
                   expireTime=expireTime)

    def testInnerPingPass(self):
        verb = 'GET'
        url = self.urlbase + 'foo/ping'
        output = {'code': 200, 'data': '"ping"'}
        expireTime = 3600

        methodTest(verb, url, output=output, expireTime=expireTime)

    def testOuterFooError(self):
        verb = 'GET'
        url = self.urlbase + 'foo/123/567'
        output = {'code': 400}
        methodTest(verb, url, output=output)

    def testInnerPingError(self):
        verb = 'GET'
        url = self.urlbase + 'foo/123/ping'
        output = {'code': 400}
        methodTest(verb, url, output=output)

        url = self.urlbase + 'foo/ping/123'
        methodTest(verb, url, output=output)
Ejemplo n.º 13
0
class NestedModelTest(RESTBaseUnitTest):

    def initialize(self):
        self.config = DefaultConfig('WMCore_t.WebTools_t.DummyNestedModel')
        do_debug = True

        self.config.Webtools.environment = 'development'
        if do_debug:
            self.config.Webtools.error_log_level = logging.DEBUG
            self.config.Webtools.access_log_level = logging.DEBUG
        else:
            self.config.Webtools.error_log_level = logging.WARNING
            self.config.Webtools.access_log_level = logging.WARNING

        self.urlbase = self.config.getServerUrl()

    def testOuterFooPass(self):
        verb ='GET'
        url = self.urlbase + 'foo'
        output={'code':200, 'data':'"foo"'}
        expireTime =3600
        methodTest(verb, url, output=output, expireTime=expireTime)

        url = self.urlbase + 'foo/test'
        output={'code':200, 'data':'"foo test"'}
        methodTest(verb, url, output=output, expireTime=expireTime)

        url = self.urlbase + 'foo'
        request_input = {'message': 'test'}
        output={'code':200, 'data':'"foo test"'}
        methodTest(verb, url, request_input=request_input, output=output, expireTime=expireTime)

    def testInnerPingPass(self):
        verb ='GET'
        url = self.urlbase + 'foo/ping'
        output={'code':200, 'data':'"ping"'}
        expireTime =3600

        methodTest(verb, url, output=output, expireTime=expireTime)

    def testOuterFooError(self):
        verb ='GET'
        url = self.urlbase + 'foo/123/567'
        output={'code':400}
        methodTest(verb, url, output=output)

    def testInnerPingError(self):
        verb ='GET'
        url = self.urlbase + 'foo/123/ping'
        output={'code':400}
        methodTest(verb, url, output=output)

        url = self.urlbase + 'foo/ping/123'
        methodTest(verb, url, output=output)
Ejemplo n.º 14
0
    def initialize(self):
        self.config = DefaultConfig('WMCore_t.WebTools_t.DummyRESTModel')
        self.do_debug = False
        self.do_production = False

        if self.do_production:
            self.config.Webtools.environment = 'production'
            self.config.SecurityModule.dangerously_insecure = False
            # not real keyfile but for the test.
            # file will be deleted automaticall when garbage collected.
            self.tempFile = NamedTemporaryFile()
            self.config.SecurityModule.key_file = self.tempFile.name
            self.config.SecurityModule.section_("default")
            self.config.SecurityModule.default.role = ""
            self.config.SecurityModule.default.group = ""
            self.config.SecurityModule.default.site = ""

        if not self.do_debug:
            self.config.Webtools.error_log_level = logging.WARNING
            self.config.Webtools.access_log_level = logging.WARNING

        self.urlbase = self.config.getServerUrl()
Ejemplo n.º 15
0
class WorkQueueTest(RESTBaseUnitTest):
    """
    Test WorkQueue Service client
    It will start WorkQueue RESTService
    Server DB sets from environment variable.
    Client DB sets from environment variable.

    This checks whether DS call makes without error and return the results.
    Not the correctness of functions. That will be tested in different module.
    """
    def initialize(self):
        self.config = DefaultConfig(
                'WMCore.HTTPFrontEnd.WMBS.WMBSRESTModel')
        dbUrl = os.environ.get("DATABASE", None)
        self.config.setDBUrl(dbUrl)
        # mysql example
        #self.config.setDBUrl('mysql://[email protected]:3306/TestDB')
        #self.config.setDBSocket('/var/lib/mysql/mysql.sock')
        self.schemaModules = ["WMCore.WMBS", "WMCore.ResourceControl", "BossAir"]

    def setUp(self):
        """
        setUP global values
        """
        RESTBaseUnitTest.setUp(self)
        self.params = {}
        self.params['endpoint'] = self.config.getServerUrl()

    def tearDown(self):
        RESTBaseUnitTest.tearDown(self)

    def testWorkQueueService(self):

        # test getWork

        wmbsApi = WMBS(self.params)
        self.assertEqual(wmbsApi.getResourceInfo(), [])
        self.assertEqual(wmbsApi.getResourceInfo(tableFormat = False), {})
Ejemplo n.º 16
0
    def initialize(self):
        self.config = DefaultConfig('WMCore_t.WebTools_t.DummyRESTModel')
        self.do_debug = False
        self.do_production = False

        if self.do_production:
            self.config.Webtools.environment = 'production'
            self.config.SecurityModule.dangerously_insecure = False
            # not real keyfile but for the test.
            # file will be deleted automaticall when garbage collected.
            self.tempFile = NamedTemporaryFile()
            self.config.SecurityModule.key_file = self.tempFile.name
            self.config.SecurityModule.section_("default")
            self.config.SecurityModule.default.role = ""
            self.config.SecurityModule.default.group = ""
            self.config.SecurityModule.default.site = ""

        if not self.do_debug:
            self.config.Webtools.error_log_level = logging.WARNING
            self.config.Webtools.access_log_level = logging.WARNING

        self.urlbase = self.config.getServerUrl()
Ejemplo n.º 17
0
class RESTTest(RESTBaseUnitTest):
    def initialize(self):
        self.config = DefaultConfig('WMCore_t.WebTools_t.DummyRESTModel')
        self.do_debug = False
        self.do_production = False

        if self.do_production:
            self.config.Webtools.environment = 'production'
            self.config.SecurityModule.dangerously_insecure = False
            # not real keyfile but for the test.
            # file will be deleted automaticall when garbage collected.
            self.tempFile = NamedTemporaryFile()
            self.config.SecurityModule.key_file = self.tempFile.name
            self.config.SecurityModule.section_("default")
            self.config.SecurityModule.default.role = ""
            self.config.SecurityModule.default.group = ""
            self.config.SecurityModule.default.site = ""

        if not self.do_debug:
            self.config.Webtools.error_log_level = logging.WARNING
            self.config.Webtools.access_log_level = logging.WARNING

        self.urlbase = self.config.getServerUrl()

    def testUnsupportedFormat(self):
        # test not accepted type should return 406 error
        url = self.urlbase + 'ping'
        methodTest('GET', url, accept='text/das', output={'code':406})

    def testGoodEcho(self):
        verb ='POST'
        url = self.urlbase + 'echo'
        input_data={'message': 'unit test'}
        output={'code':200, 'type':'text/json',
              'data':'{"message": "unit test"}'}

        methodTest(verb, url, input_data, output=output)

    def testBadEchoWithPosArg(self):
        "Echo takes one argument (message), with the positional argument it should fail"
        verb ='POST'
        url = self.urlbase + 'echo/stuff'
        input_data={'message': 'unit test'}
        output={'code':400, 'type':'text/json'}
        methodTest(verb, url, input_data, output=output)

    def testBadMethodEcho(self):
        """
        The echo method isn't supported by GET, so should raise a 405
        """
        verb ='GET'
        url = self.urlbase + 'echo'
        input={'data': 'unit test'}
        output={'code':405, 'type':'text/json'}

        methodTest(verb, url, input, output=output)

    def testBadVerbEcho(self):
        "echo is only available to GET and POST, so should raise a 501"
        url = self.urlbase + 'echo'
        input={'data': 'unit test'}
        output={'code':501, 'type':'text/json'}

        for verb in ['DELETE']:
          methodTest(verb, url, input, output=output)

    def testPing(self):
        verb ='GET'
        url = self.urlbase + 'ping'
        output={'code':200, 'type':'text/json', 'data':'"ping"'}
        expireTime =3600

        methodTest(verb, url, output=output, expireTime=expireTime)

    def testBadPing(self):
        verb ='GET'

        url = self.urlbase + 'wrong'
        output={'code':404}
        methodTest(verb, url, output=output)

        url = self.urlbase + 'echo'
        output={'code':405}
        methodTest(verb, url, output=output)


        url = self.urlbase + 'ping/wrong'
        output={'code':400}
        methodTest(verb, url, output=output)

    def testException(self):
        """
        list takes a single integer argument, querying with a string
        """
        url = self.urlbase + 'list?int=a'
        self.assertRaises(urllib2.HTTPError, urllib2.urlopen, url)
        # urllib2,urlopen raise the error but not urllib.urlopen
        url = self.urlbase + 'list1?int=a'
        expected_data = {"exception": 400, "type": "HTTPError", "message": "Invalid input"}
        urllib_data = urllib.urlopen(url)
        if self.do_production:
            #production mode returns 403 error
            self.assertEquals(urllib_data.getcode(), 403)
        else:
            response_data = urllib_data.read()
            response_data = json.loads(response_data)
            self.assertEquals(response_data['type'], expected_data['type'])
            self.assertEquals(response_data['message'], expected_data['message'])
            self.assertEquals(urllib_data.getcode(), 400)

    def testList(self):
        verb ='GET'
        url = self.urlbase + 'list/'
        request_input = {'input_int':123, 'input_str':'abc'}
        output={'code':200, 'type':'text/json'}
        result = json.loads(methodTest(verb, url, request_input=request_input, output=output)[0])
        for i in result.keys():
            self.assertEqual(result[i], request_input[i], '%s does not match response' % i)


    def testA(self):
        for t in ['GET', 'POST', 'PUT', 'DELETE', 'UPDATE']:
            response = makeRequest(url=self.urlbase + '/', values={'value':1234})
            assert response[1] == 200, 'Got a return code != 200 (got %s)' % response[1]

    def testSanitisePass(self):
        """
        Emulate how CherryPy passes arguments to a method, check that the data
        returned is correct.

        No server setup required
        """
        drm = DummyRESTModel(self.config.getModelConfig())

        def func(*args, **kwargs):
           sanitised_input = drm._sanitise_input(args, kwargs, "list")
           return drm.list(**sanitised_input)

        # 2 positional args (e.g. url/arg1/arg2)
        result = func(123, 'abc')
        assert result == {'input_int':123, 'input_str':'abc'},\
                                'list with 2 positional args failed: %s' % result
        # 2 query string args (e.g. url?int=arg1&str=arg2)
        result = func(input_int=123, input_str='abc')
        assert result == {'input_int':123, 'input_str':'abc'},\
                               'list with 2 query string args failed: %s' % result

        # 1 positional, 1 keyword  (e.g. url/arg1/?str=arg2)
        result = func(123, input_str='abc')
        assert result == {'input_int':123, 'input_str':'abc'},\
               'list with 1 positional, 1 keyword failed: %s' % result

    def testSanitisePassHTTP(self):
        """
        Same as testSanitisePass but do it over http and check the returned http
        codes.
        """
        # 2 positional args (e.g. url/arg1/arg2)
        url = self.urlbase + 'list/123/abc'
        response = makeRequest(url=url)
        assert response[1] == 200, \
             'list with 2 positional args failed: ' +\
             '. Got a return code != 200 (got %s)' % response[1] +\
             '. Returned data: %s' % response[0]
              # 2 query string args (e.g. url?int=arg1&str=arg2)
        url = self.urlbase + 'list/'
        response = makeRequest(url=url, values={'input_int':'123', 'input_str':'abc'})
        assert response[1] == 200, \
                 'list with 2 query string args failed: ' +\
                 '. Got a return code != 200 (got %s)' % response[1] +\
                 '. Returned data: %s' % response[0]

        # 1 positional, 1 keyword  (e.g. url/arg1/?str=arg2)
        url = self.urlbase + 'list/123/'
        response = makeRequest(url=url,
                                     values={'input_str':'abc'})
        assert response[1] == 200, \
                 'list with 1 positional, 1 keyword failed: ' +\
                 '. Got a return code != 200 (got %s)' % response[1] +\
                 '. Returned data: %s' % response[0]

    def testSanitiseAssertFail(self):
        """
        No server set up required, the purpose of the test is just
        demonstrating how validation is used.
        """
        drm = DummyRESTModel(self.config.getModelConfig())

        def func(*args, **kwargs):
            sanitised_input = drm._sanitise_input(args, kwargs, "list")
            return drm.list(**sanitised_input)

        # Wrong type for input args
        self.assertRaises(HTTPError, func, 123, 123)
        self.assertRaises(HTTPError, func, 'abc', 'abc')
        self.assertRaises(HTTPError, func, input_str = 'abc', input_int = 123, other='dfe')
        self.assertRaises(HTTPError, func, str = 123, int ='abc')
        self.assertRaises(HTTPError, func, str =' abc', int = 'abc')
        self.assertRaises(HTTPError, func, 'abc', 123)
        self.assertRaises(HTTPError, func, 'abc', 'abc')
        self.assertRaises(HTTPError, func, str = 123, int = 'abc')
        self.assertRaises(HTTPError, func, str =123, int = 123)
        self.assertRaises(HTTPError, func, str = 'abc', int ='abc')

        # Incorrect values for input args
        self.assertRaises(HTTPError, func, 1234, 'abc')
        self.assertRaises(HTTPError, func, 123, 'abcd')

        # Empty input data, when data is required
        self.assertRaises(HTTPError, func)

    def testSanitiseFailHTTP(self):
        """
        Same as testSanitisePass but do it over http and check the returned http
        codes.
        """
        # 2 positional args (e.g. url/arg1/arg2)
        url = self.urlbase + 'list/123/'
        response = makeRequest(url=url, accept='text/json')
        assert response[1] == 400, \
                 'list with 2 positional args failed: ' +\
                 '. Got a return code != 400 (got %s)' % response[1] +\
                 '. Returned data: %s' % response[0]

        self.assertEqual(response[2], 'text/json', 'type is not text/json : %s' % type)
        # 2 query string args (e.g. url?int=arg1&str=arg2)
        url = self.urlbase + 'list'
        response = makeRequest(url=url, values={'int':'abc', 'str':'abc'})
        assert response[1] == 400, \
                 'list with 2 query string args failed: ' +\
                 '. Got a return code != 400 (got %s)' % response[1] +\
                 '. Returned data: %s' % response[0]

        # 1 positional, 1 keyword  (e.g. url/arg1/?str=arg2)
        url = self.urlbase + 'list/abc'
        response = makeRequest(url=url, values={'str':'abc'})
        assert response[1] == 400, \
                 'list with 1 positional, 1 keyword failed: ' +\
                 '. Got a return code != 400 (got %s)' % response[1] +\
                 '. Returned data: %s' % response[0]

    # don't need server set up
    def testDAOBased(self):
        drm = DummyRESTModel(self.config.getModelConfig())

        result = drm.methods['GET']['data1']['call']()
        self.assertEqual( result ,  123, 'Error default value is set to 123 but returns %s' % result )

        result =  drm.methods['GET']['data2']['call'](456)
        self.assertEqual( result['num'] ,  456 )

        result =  drm.methods['GET']['data2']['call'](num = 456)
        self.assertEqual( result['num'] ,  456 )

        result =  drm.methods['GET']['data3']['call'](num = 456, thing="TEST")
        self.assertEqual( result['num'] == 456 and result['thing'] ,  "TEST" )

    def testDAOBasedHTTP(self):
        """
        Same as testSanitisePass but do it over http and check the returned http
        codes.
        """
        # 2 positional args (e.g. url/arg1/arg2)
        url = self.urlbase + 'data1/'
        response = makeRequest(url=url)
        assert response[1] == 200, \
                 'dao without args failed: ' +\
                 '. Got a return code != 200 (got %s)' % response[1] +\
                 '. Returned data: %s' % response[0]
        self.assertEqual( response[0] ,  '123', response[0])

        # 2 query string args (e.g. url?int=arg1&str=arg2)
        url = self.urlbase + 'data2'
        response = makeRequest(url=url, values={'num':456})

        assert response[1] == 200, \
                 'dao with 1 args failed: ' +\
                 '. Got a return code != 200 (got %s)' % response[1] +\
                 '. Returned data: %s' % response[0]
        #Warning quotation type matters
        #Should use encoded and decoded format
        self.assertEqual( response[0] ,  "{'num': '456'}", "should be {'num': '456'} but got %s" % response[0]          )

        # 1 positional, 1 keyword  (e.g. url/arg1/?str=arg2)
        url = self.urlbase + 'data3/123'
        response = makeRequest(url=url, values={'thing':'abc'})

        assert response[1] == 200, \
                 'dao with 1 positional, 1 keyword failed: ' +\
                 '. Got a return code != 200 (got %s)' % response[1] +\
                 '. Returned data: %s' % response[0]
        #Warning quotation type and order matters
        #Should use encoded and decoded format
        self.assertEqual( response[0] ,  "{'thing': 'abc', 'num': '123'}", "should be {'thing': 'abc', 'num': '123'} but got %s" % response[0] )

    def testListTypeArgs(self):
        # 2 positional args (e.g. url/arg1/arg2)
        url = self.urlbase + 'listTypeArgs?aList=1'
        response = makeRequest(url=url)
        assert response[1] == 200 and response[0] == "[1]", \
                 'list args failed: ' +\
                 '. Got a return code != 200 (got %s)' % response[1] +\
                 '. Returned data: %s' % response[0]


        # 2 values with the same keywords (e.g. url/arg1/arg2)
        url = self.urlbase + 'listTypeArgs?aList=1&aList=2'
        response = makeRequest(url=url)
        assert response[1] == 200 and response[0] == "[1, 2]", \
                 'list args failed: ' +\
                 '. Got a return code != 200 (got %s)' % response[1] +\
                 '. Returned data: %s' % response[0]

    @cherrypySetup(secureConfig)
    @attr("integration")    
    def testAuthentication(self):
        verb ='PUT'
        url = self.urlbase + 'list1'
        urllib_data = urllib.urlopen(url)
        self.assertEquals(urllib_data.getcode(), 403)

        # pass proper role
        output={'code':200}
        methodTest(verb, url, output=output,
                   secure=True, secureParam={'key': secureKey,
                                             'role': DUMMY_ROLE,
                                             'group': DUMMY_GROUP,
                                             'site': DUMMY_SITE})
Ejemplo n.º 18
0
class RESTFormatTest(RESTBaseUnitTest):

    def initialize(self):
        self.config = DefaultConfig('WMCore_t.WebTools_t.DummyRESTModel')
        do_debug = False

        self.config.Webtools.environment = 'development'
        if do_debug:
            self.config.Webtools.error_log_level = logging.DEBUG
            self.config.Webtools.access_log_level = logging.DEBUG
        else:
            self.config.Webtools.error_log_level = logging.WARNING
            self.config.Webtools.access_log_level = logging.WARNING

        self.urlbase = self.config.getServerUrl()

    def testUnsupportedFormat(self):
        # test not accepted type should return 406 error
        url = self.urlbase +'list1/'
        methodTest('GET', url, accept='text/das', output={'code':406})

    def testSupportedFormat(self):
        rf = RESTFormatter(config=self.config.Webtools)
        url = self.urlbase +'list1/'

        for textType in rf.supporttypes.keys():
            # test accepted type should return 200 error
            methodTest('GET', url, accept=textType, output={'code':200})

    # This test is flipping back and forth in Jenkins. Perhaps due to port 8888 not being available.
    # Disabling for now
    @attr("integration")
    def testEncodedInput(self):
        textType = 'text/plain'

        url = self.urlbase + 'list3?a=a%&b=b'
        data = json.dumps({'a': 'a%', 'b': 'b'})
        methodTest('GET', url, accept=textType,
                         output={'code':200, 'data':data})

        request_input={'a':'%', 'b':'b'}

        #methodTest encoded input with urlencode
        url = self.urlbase +'list3'
        data = json.dumps({'a': '%', 'b': 'b'})
        methodTest('GET', url, accept=textType, request_input=request_input,
                 output={'code':200, 'data':data})

    def testReturnFormat(self):
        return_type = 'application/json'

        url = self.urlbase +'list3?a=a%&b=b'
        methodTest('GET', url, accept=return_type,
                         output={'code':200, 'data':'{"a": "a%", "b": "b"}'})

        url = self.urlbase + 'list?input_int=a&input_str=a'
        expected_data = '''{"exception": 400, "message": "Invalid input: Input data failed validation.", "type": "HTTPError"}'''
        methodTest('GET', url, accept=return_type,
                         output={'code':400, 'data':expected_data})

    def testNoArgMethods(self):
        """
        list1 takes no arguments, it should raise an error if called with one. Require json output.
        """
        return_type = 'application/json'
        url = self.urlbase + 'list1?int=a'
        expected_data = """{"exception": 400, "message": "Invalid input: Arguments added where none allowed", "type": "HTTPError"}"""
        methodTest('GET', url, accept=return_type, output={'code':400, 'data':expected_data})

    def testGenerator(self):
        rf = RESTFormatter(config=self.config.Webtools)
        url = self.urlbase +'gen'
        # gen method from DummyRESTModel will return this generator
        gen = ({'idx':i} for i in range(10))
        # the WMCore should convert it into list regardless of accept type
        data = rf.json(gen)
        methodTest('GET', url, accept='application/json',
                         output={'code':200, 'data':data})
        methodTest('GET', url, accept='*/*',
                         output={'code':200, 'data':data})
Ejemplo n.º 19
0
class testRepeatCalls(RESTBaseUnitTest):
    def initialize(self):
        self.config = DefaultConfig()
        self.config.UnitTests.templates = getWMBASE() + '/src/templates/WMCore/WebTools'
        self.config.Webtools.section_('server')
        self.config.Webtools.server.socket_timeout = 1
        self.urlbase = self.config.getServerUrl()
        self.cache_path = tempfile.mkdtemp()

    def tearDown(self):
        shutil.rmtree(self.cache_path, ignore_errors = True)
        self.rt.stop()

    def test10Calls(self):
        fail_count = 0
        req = Requests.Requests(self.urlbase, {'req_cache_path': self.cache_path})

        for i in range(0, 5):
            time.sleep(i)
            print('test %s starting at %s' % (i, time.time()))
            try:
                result = req.get('/', incoming_headers={'Cache-Control':'no-cache'})
                self.assertEqual(False, result[3])
                self.assertEqual(200, result[1])
            except HTTPException as he:
                print('test %s raised a %s error' % (i, he.status))
                fail_count += 1
            except Exception as e:
                print('test %s raised an unexpected exception of type %s' % (i, type(e)))
                print(e)
                fail_count += 1
        if fail_count > 0:
            raise Exception('Test did not pass!')

    def test10Calls_with_pycurl(self):
        fail_count = 0
        idict = {'req_cache_path': self.cache_path, 'pycurl':1}
        req = Requests.Requests(self.urlbase, idict)

        for i in range(0, 5):
            time.sleep(i)
            print('test %s starting at %s' % (i, time.time()))
            try:
                result = req.get('/', incoming_headers={'Cache-Control':'no-cache'}, decode=False)
                self.assertEqual(False, result[3])
                self.assertEqual(200, result[1])
            except HTTPException as he:
                print('test %s raised a %s error' % (i, he.status))
                fail_count += 1
            except Exception as e:
                print('test %s raised an unexpected exception of type %s' % (i, type(e)))
                print(e)
                fail_count += 1
        if fail_count > 0:
            raise Exception('Test did not pass!')

    def testRecoveryFromConnRefused(self):
        """Connections succeed after server down"""
        import socket
        self.rt.stop()
        req = Requests.Requests(self.urlbase, {'req_cache_path': self.cache_path})
        headers = {'Cache-Control':'no-cache'}
        self.assertRaises(socket.error, req.get, '/', incoming_headers=headers)

        # now restart server and hope we can connect
        self.rt.start(blocking=False)
        result = req.get('/', incoming_headers=headers)
        self.assertEqual(result[3], False)
        self.assertEqual(result[1], 200)

    def testRecoveryFromConnRefused_with_pycurl(self):
        """Connections succeed after server down"""
        import pycurl
        self.rt.stop()
        idict = {'req_cache_path': self.cache_path, 'pycurl':1}
        req = Requests.Requests(self.urlbase, idict)
        headers = {'Cache-Control':'no-cache'}
        self.assertRaises(pycurl.error, req.get, '/', incoming_headers=headers, decode=False)

        # now restart server and hope we can connect
        self.rt.start(blocking=False)
        result = req.get('/', incoming_headers=headers, decode=False)
        self.assertEqual(result[3], False)
        self.assertEqual(result[1], 200)
Ejemplo n.º 20
0
class RESTFormatTest(RESTBaseUnitTest):

    def initialize(self):
        self.config = DefaultConfig('WMCore_t.WebTools_t.DummyRESTModel')
        do_debug = False

        self.config.Webtools.environment = 'development'
        if do_debug:
            self.config.Webtools.error_log_level = logging.DEBUG
            self.config.Webtools.access_log_level = logging.DEBUG
        else:
            self.config.Webtools.error_log_level = logging.WARNING
            self.config.Webtools.access_log_level = logging.WARNING

        self.urlbase = self.config.getServerUrl()

    def testUnsupportedFormat(self):
        # test not accepted type should return 406 error
        url = self.urlbase +'list1/'
        methodTest('GET', url, accept='text/das', output={'code':406})

    def testSupportedFormat(self):
        rf = RESTFormatter(config=self.config.Webtools)
        url = self.urlbase +'list1/'

        for textType in rf.supporttypes.keys():
            # test accepted type should return 200 error
            methodTest('GET', url, accept=textType, output={'code':200})

    # This test is flipping back and forth in Jenkins. Perhaps due to port 8888 not being available.
    # Disabling for now
    @attr("integration")
    def testEncodedInput(self):
        textType = 'text/plain'

        url = self.urlbase + 'list3?a=a%&b=b'
        data = json.dumps({'a': 'a%', 'b': 'b'})
        methodTest('GET', url, accept=textType,
                         output={'code':200, 'data':data})

        request_input={'a':'%', 'b':'b'}

        #methodTest encoded input with urlencode
        url = self.urlbase +'list3'
        data = json.dumps({'a': '%', 'b': 'b'})
        methodTest('GET', url, accept=textType, request_input=request_input,
                 output={'code':200, 'data':data})

    def testReturnFormat(self):
        return_type = 'application/json'

        url = self.urlbase +'list3?a=a%&b=b'
        methodTest('GET', url, accept=return_type,
                         output={'code':200, 'data':'{"a": "a%", "b": "b"}'})

        url = self.urlbase + 'list?input_int=a&input_str=a'
        expected_data_py2 = '{"exception": 400, "message": "Invalid input: Input data failed validation.", "type": "HTTPError"}'
        expected_data_py3 = '{"exception": 400, "type": "HTTPError", "message": "Invalid input: Input data failed validation."}'
        expected_data = expected_data_py3 if PY3 else expected_data_py2
        methodTest('GET', url, accept=return_type,
                         output={'code':400, 'data':expected_data})

    def testNoArgMethods(self):
        """
        list1 takes no arguments, it should raise an error if called with one. Require json output.
        """
        return_type = 'application/json'
        url = self.urlbase + 'list1?int=a'
        expected_data_py2 = '{"exception": 400, "message": "Invalid input: Arguments added where none allowed", "type": "HTTPError"}'
        expected_data_py3 = '{"exception": 400, "type": "HTTPError", "message": "Invalid input: Arguments added where none allowed"}'
        expected_data = expected_data_py3 if PY3 else expected_data_py2
        methodTest('GET', url, accept=return_type, output={'code':400, 'data':expected_data})

    def testGenerator(self):
        rf = RESTFormatter(config=self.config.Webtools)
        url = self.urlbase +'gen'
        # gen method from DummyRESTModel will return this generator
        gen = ({'idx':i} for i in range(10))
        # the WMCore should convert it into list regardless of accept type
        data = rf.json(gen)
        methodTest('GET', url, accept='application/json',
                         output={'code':200, 'data':data})
        methodTest('GET', url, accept='*/*',
                         output={'code':200, 'data':data})
Ejemplo n.º 21
0
class RESTFormatTest(RESTBaseUnitTest):

    def initialize(self):
        self.config = DefaultConfig('WMCore_t.WebTools_t.DummyRESTModel')
        do_debug = False

        self.config.Webtools.environment = 'development'
        if do_debug:
            self.config.Webtools.error_log_level = logging.DEBUG
            self.config.Webtools.access_log_level = logging.DEBUG
        else:
            self.config.Webtools.error_log_level = logging.WARNING
            self.config.Webtools.access_log_level = logging.WARNING

        self.urlbase = self.config.getServerUrl()

    def testUnsupportedFormat(self):
        # test not accepted type should return 406 error
        url = self.urlbase +'list1/'
        methodTest('GET', url, accept='text/das', output={'code':406})

    def testSupportedFormat(self):
        rf = RESTFormatter(config=self.config.Webtools)
        url = self.urlbase +'list1/'

        for type in rf.supporttypes.keys():
            # test accepted type should return 200 error
            methodTest('GET', url, accept=type, output={'code':200})

    def testEncodedInput(self):
        type = 'text/plain'

        url = self.urlbase + 'list3?a=a%&b=b'
        methodTest('GET', url, accept=type,
                         output={'code':200, 'data':"{'a': 'a%', 'b': 'b'}"})

        request_input={'a':'%', 'b':'b'}

        #methodTest encoded input with urlencode
        url = self.urlbase +'list3'
        methodTest('GET', url, accept=type, request_input=request_input,
                 output={'code':200, 'data':"{'a': '%', 'b': 'b'}"})

    def testReturnFormat(self):
        return_type = 'application/json'

        url = self.urlbase +'list3?a=a%&b=b'
        methodTest('GET', url, accept=return_type,
                         output={'code':200, 'data':'{"a": "a%", "b": "b"}'})

        url = self.urlbase + 'list?input_int=a&input_str=a'
        expected_data = '''{"exception": 400, "message": "Invalid input: Input data failed validation.", "type": "HTTPError"}'''
        methodTest('GET', url, accept=return_type,
                         output={'code':400, 'data':expected_data})

    def testNoArgMethods(self):
        """
        list1 takes no arguments, it should raise an error if called with one. Require json output.
        """
        return_type = 'application/json'
        url = self.urlbase + 'list1?int=a'
        expected_data = """{"exception": 400, "message": "Invalid input: Arguments added where none allowed", "type": "HTTPError"}"""
        methodTest('GET', url, accept=return_type, output={'code':400, 'data':expected_data})
Ejemplo n.º 22
0
class RESTFormatTest(RESTBaseUnitTest):

    def initialize(self):
        self.config = DefaultConfig('WMCore_t.WebTools_t.DummyRESTModel')
        do_debug = False

        self.config.Webtools.environment = 'development'
        if do_debug:
            self.config.Webtools.error_log_level = logging.DEBUG
            self.config.Webtools.access_log_level = logging.DEBUG
        else:
            self.config.Webtools.error_log_level = logging.WARNING
            self.config.Webtools.access_log_level = logging.WARNING

        self.urlbase = self.config.getServerUrl()

    def testUnsupportedFormat(self):
        # test not accepted type should return 406 error
        url = self.urlbase +'list1/'
        methodTest('GET', url, accept='text/das', output={'code':406})

    def testSupportedFormat(self):
        rf = RESTFormatter(config=self.config.Webtools)
        url = self.urlbase +'list1/'

        for type in rf.supporttypes.keys():
            # test accepted type should return 200 error
            methodTest('GET', url, accept=type, output={'code':200})

    def testEncodedInput(self):
        type = 'text/plain'

        url = self.urlbase + 'list3?a=a%&b=b'
        methodTest('GET', url, accept=type,
                         output={'code':200, 'data':"{'a': 'a%', 'b': 'b'}"})

        request_input={'a':'%', 'b':'b'}

        #methodTest encoded input with urlencode
        url = self.urlbase +'list3'
        methodTest('GET', url, accept=type, request_input=request_input,
                 output={'code':200, 'data':"{'a': '%', 'b': 'b'}"})

    def testReturnFormat(self):
        return_type = 'application/json'

        url = self.urlbase +'list3?a=a%&b=b'
        methodTest('GET', url, accept=return_type,
                         output={'code':200, 'data':'{"a": "a%", "b": "b"}'})

        url = self.urlbase + 'list?input_int=a&input_str=a'
        expected_data = '''{"exception": 400, "message": "Invalid input", "type": "HTTPError"}'''
        methodTest('GET', url, accept=return_type,
                         output={'code':400, 'data':expected_data})

    def testNoArgMethods(self):
        """
        list1 takes no arguments, it should raise an error if called with one. Require json output.
        """
        return_type = 'application/json'
        url = self.urlbase + 'list1?int=a'
        expected_data = """{"exception": 400, "message": "Invalid input", "type": "HTTPError"}"""
        methodTest('GET', url, accept=return_type, output={'code':400, 'data':expected_data})
Ejemplo n.º 23
0
    def specific_404_exception(self):
        """
        Raise an HTTP Error, this will be preserved and propagated to the client
        """
        raise HTTPError(404, 'I threw a 404')

    def not_serialisable(self):
        """
        Raise an exception in the formatter (complex numbers aren't json serialisable
        by default), this is caught and turned into a 500 Server Error by the RESTAPI
        """
        return complex(1, 2)


test_config = DefaultConfig('WMCore_t.WebTools_t.REST_Exceptions_t')
test_config.Webtools.access_log_level = logging.WARNING
test_config.Webtools.error_log_level = logging.WARNING

from WMQuality.WebTools.RESTBaseUnitTest import RESTBaseUnitTest


# Disabling tests because the decorator doesn't work right
class RESTTestFAIL():
    def setUp(self):
        self.config = test_config
        self.dasFlag = False
        self.urlbase = self.config.getServerUrl()

    def tearDown(self):
        self.dasFlag = None
Ejemplo n.º 24
0
class RESTTest(RESTBaseUnitTest):
    def initialize(self):
        self.config = DefaultConfig('WMCore_t.WebTools_t.DummyRESTModel')
        self.do_debug = False
        self.do_production = False

        if self.do_production:
            self.config.Webtools.environment = 'production'
            self.config.SecurityModule.dangerously_insecure = False
            # not real keyfile but for the test.
            # file will be deleted automaticall when garbage collected.
            self.tempFile = NamedTemporaryFile()
            self.config.SecurityModule.key_file = self.tempFile.name
            self.config.SecurityModule.section_("default")
            self.config.SecurityModule.default.role = ""
            self.config.SecurityModule.default.group = ""
            self.config.SecurityModule.default.site = ""

        if not self.do_debug:
            self.config.Webtools.error_log_level = logging.WARNING
            self.config.Webtools.access_log_level = logging.WARNING

        self.urlbase = self.config.getServerUrl()

    def testGeneratorMethod(self):
        # test not accepted type should return 406 error
        url = self.urlbase + 'gen'
        output={'code':200}
        data, _ = methodTest('GET', url, accept='text/json', output=output)
        data = json.loads(data)
        self.assertEqual(type(data), list)
        self.assertEqual(type(data[0]), dict)

    def testUnsupportedFormat(self):
        # test not accepted type should return 406 error
        url = self.urlbase + 'ping'
        methodTest('GET', url, accept='text/das', output={'code':406})

    def testGoodEcho(self):
        verb ='POST'
        url = self.urlbase + 'echo'
        input_data={'message': 'unit test'}
        output={'code':200, 'type':'text/json',
              'data':'{"message": "unit test"}'}

        methodTest(verb, url, input_data, output=output)

    def testBadEchoWithPosArg(self):
        "Echo takes one argument (message), with the positional argument it should fail"
        verb ='POST'
        url = self.urlbase + 'echo/stuff'
        input_data={'message': 'unit test'}
        output={'code':400, 'type':'text/json'}
        methodTest(verb, url, input_data, output=output)

    def testBadMethodEcho(self):
        """
        The echo method isn't supported by GET, so should raise a 405
        """
        verb ='GET'
        url = self.urlbase + 'echo'
        input_data = {'data': 'unit test'}
        output = {'code':405, 'type':'text/json'}

        methodTest(verb, url, input_data, output=output)

    def testBadVerbEcho(self):
        "echo is only available to GET and POST, so should raise a 501"
        url = self.urlbase + 'echo'
        input_data = {'data': 'unit test'}
        output = {'code':501, 'type':'text/json'}

        for verb in ['DELETE']:
            methodTest(verb, url, input_data, output=output)

    def testPing(self):
        verb ='GET'
        url = self.urlbase + 'ping'
        output={'code':200, 'type':'text/json', 'data':'"ping"'}
        expireTime =3600

        methodTest(verb, url, output=output, expireTime=expireTime)

    def testBadPing(self):
        verb ='GET'

        url = self.urlbase + 'wrong'
        output={'code':404}
        methodTest(verb, url, output=output)

        url = self.urlbase + 'echo'
        output={'code':405}
        methodTest(verb, url, output=output)


        url = self.urlbase + 'ping/wrong'
        output={'code':400}
        methodTest(verb, url, output=output)

    def testException(self):
        """
        testException

        list takes a single integer argument, querying with a string
        """
        url = self.urlbase + 'list?int=a'
        self.assertRaises(urllib.error.HTTPError, urllib.request.urlopen, url)
        try:
            urllib.request.urlopen(url)
        except urllib.error.HTTPError as e:
            self.assertEqual(e.code, 400)
            self.assertEqual(e.reason, u'Bad Request')
            self.assertEqual(e.msg, u'Bad Request')
            exception_data = json.loads(e.read())
            self.assertEqual(exception_data['type'], 'HTTPError')
            self.assertEqual(exception_data['message'], 'Invalid input: Input arguments failed sanitation.')

        url = self.urlbase + 'list1?int=a'
        self.assertRaises(urllib.error.HTTPError, urllib.request.urlopen, url)
        try:
            urllib.request.urlopen(url)
        except urllib.error.HTTPError as e:
            self.assertEqual(e.code, 400)
            self.assertEqual(e.reason, u'Bad Request')
            self.assertEqual(e.msg, u'Bad Request')
            exception_data = json.loads(e.read())
            self.assertEqual(exception_data['type'], 'HTTPError')
            self.assertEqual(exception_data['message'], 'Invalid input: Arguments added where none allowed')

    def testList(self):
        verb ='GET'
        url = self.urlbase + 'list/'
        request_input = {'input_int':123, 'input_str':'abc'}
        output={'code':200, 'type':'text/json'}
        result = json.loads(methodTest(verb, url, request_input=request_input, output=output)[0])
        for i in result.keys():
            self.assertEqual(result[i], request_input[i], '%s does not match response' % i)

    def testA(self):
        # This test doesn't actually use the type, just the same thing 5 times.
        for t in ['GET', 'POST', 'PUT', 'DELETE', 'UPDATE']:
            response = makeRequest(url=self.urlbase + '/', values={'value':1234})
            assert response[1] == 200, 'Got a return code != 200 (got %s)' % response[1]

    def testSanitisePass(self):
        """
        Emulate how CherryPy passes arguments to a method, check that the data
        returned is correct.

        No server setup required
        """
        drm = DummyRESTModel(self.config.getModelConfig())

        def func(*args, **kwargs):
            sanitised_input = drm._sanitise_input(args, kwargs, "list")
            return drm.list(**sanitised_input)

        # 2 positional args (e.g. url/arg1/arg2)
        result = func(123, 'abc')
        assert result == {'input_int':123, 'input_str':'abc'},\
                                'list with 2 positional args failed: %s' % result
        # 2 query string args (e.g. url?int=arg1&str=arg2)
        result = func(input_int=123, input_str='abc')
        assert result == {'input_int':123, 'input_str':'abc'},\
                               'list with 2 query string args failed: %s' % result

        # 1 positional, 1 keyword  (e.g. url/arg1/?str=arg2)
        result = func(123, input_str='abc')
        assert result == {'input_int':123, 'input_str':'abc'},\
               'list with 1 positional, 1 keyword failed: %s' % result

    def testSanitisePassHTTP(self):
        """
        Same as testSanitisePass but do it over http and check the returned http
        codes.
        """
        # 2 positional args (e.g. url/arg1/arg2)
        url = self.urlbase + 'list/123/abc'
        response = makeRequest(url=url)
        assert response[1] == 200, \
             'list with 2 positional args failed: ' +\
             '. Got a return code != 200 (got %s)' % response[1] +\
             '. Returned data: %s' % response[0]
              # 2 query string args (e.g. url?int=arg1&str=arg2)
        url = self.urlbase + 'list/'
        response = makeRequest(url=url, values={'input_int':'123', 'input_str':'abc'})
        assert response[1] == 200, \
                 'list with 2 query string args failed: ' +\
                 '. Got a return code != 200 (got %s)' % response[1] +\
                 '. Returned data: %s' % response[0]

        # 1 positional, 1 keyword  (e.g. url/arg1/?str=arg2)
        url = self.urlbase + 'list/123/'
        response = makeRequest(url=url,
                                     values={'input_str':'abc'})
        assert response[1] == 200, \
                 'list with 1 positional, 1 keyword failed: ' +\
                 '. Got a return code != 200 (got %s)' % response[1] +\
                 '. Returned data: %s' % response[0]

    def testSanitiseAssertFail(self):
        """
        No server set up required, the purpose of the test is just
        demonstrating how validation is used.
        """
        drm = DummyRESTModel(self.config.getModelConfig())

        def func(*args, **kwargs):
            sanitised_input = drm._sanitise_input(args, kwargs, "list")
            return drm.list(**sanitised_input)

        # Wrong type for input args
        self.assertRaises(HTTPError, func, 123, 123)
        self.assertRaises(HTTPError, func, 'abc', 'abc')
        self.assertRaises(HTTPError, func, input_str = 'abc', input_int = 123, other='dfe')
        self.assertRaises(HTTPError, func, str = 123, int ='abc')
        self.assertRaises(HTTPError, func, str =' abc', int = 'abc')
        self.assertRaises(HTTPError, func, 'abc', 123)
        self.assertRaises(HTTPError, func, 'abc', 'abc')
        self.assertRaises(HTTPError, func, str = 123, int = 'abc')
        self.assertRaises(HTTPError, func, str =123, int = 123)
        self.assertRaises(HTTPError, func, str = 'abc', int ='abc')

        # Incorrect values for input args
        self.assertRaises(HTTPError, func, 1234, 'abc')
        self.assertRaises(HTTPError, func, 123, 'abcd')

        # Empty input data, when data is required
        self.assertRaises(HTTPError, func)

    def testSanitiseFailHTTP(self):
        """
        Same as testSanitisePass but do it over http and check the returned http
        codes.
        """
        # 2 positional args (e.g. url/arg1/arg2)
        url = self.urlbase + 'list/123/'
        response = makeRequest(url=url, accept='text/json')
        assert response[1] == 400, \
                 'list with 2 positional args failed: ' +\
                 '. Got a return code != 400 (got %s)' % response[1] +\
                 '. Returned data: %s' % response[0]

        self.assertEqual(response[2], 'text/json', 'type is not text/json : %s' % type)
        # 2 query string args (e.g. url?int=arg1&str=arg2)
        url = self.urlbase + 'list'
        response = makeRequest(url=url, values={'int':'abc', 'str':'abc'})
        assert response[1] == 400, \
                 'list with 2 query string args failed: ' +\
                 '. Got a return code != 400 (got %s)' % response[1] +\
                 '. Returned data: %s' % response[0]

        # 1 positional, 1 keyword  (e.g. url/arg1/?str=arg2)
        url = self.urlbase + 'list/abc'
        response = makeRequest(url=url, values={'str':'abc'})
        assert response[1] == 400, \
                 'list with 1 positional, 1 keyword failed: ' +\
                 '. Got a return code != 400 (got %s)' % response[1] +\
                 '. Returned data: %s' % response[0]

    # don't need server set up
    def testDAOBased(self):
        drm = DummyRESTModel(self.config.getModelConfig())

        result = drm.methods['GET']['data1']['call']()
        self.assertEqual( result ,  123, 'Error default value is set to 123 but returns %s' % result )

        result =  drm.methods['GET']['data2']['call'](456)
        self.assertEqual( result['num'] ,  456 )

        result =  drm.methods['GET']['data2']['call'](num = 456)
        self.assertEqual( result['num'] ,  456 )

        result =  drm.methods['GET']['data3']['call'](num = 456, thing="TEST")
        self.assertEqual( result['num'] == 456 and result['thing'] ,  "TEST" )

    # This test is flipping back and forth in Jenkins. Perhaps due to port 8888 not being available.
    # Disabling for now
    @attr("integration")
    def testDAOBasedHTTP(self):
        """
        Same as testSanitisePass but do it over http and check the returned http
        codes.
        """
        # 2 positional args (e.g. url/arg1/arg2)
        url = self.urlbase + 'data1/'
        response = makeRequest(url=url)
        assert response[1] == 200, \
                 'dao without args failed: ' +\
                 '. Got a return code != 200 (got %s)' % response[1] +\
                 '. Returned data: %s' % response[0]
        self.assertEqual( response[0] ,  '123', response[0])

        # 2 query string args (e.g. url?int=arg1&str=arg2)
        url = self.urlbase + 'data2'
        response = makeRequest(url=url, values={'num':456})

        assert response[1] == 200, \
                 'dao with 1 args failed: ' +\
                 '. Got a return code != 200 (got %s)' % response[1] +\
                 '. Returned data: %s' % response[0]
        #Warning quotation type matters
        #Should use encoded and decoded format
        self.assertEqual( response[0] ,  "{'num': '456'}", "should be {'num': '456'} but got %s" % response[0]          )

        # 1 positional, 1 keyword  (e.g. url/arg1/?str=arg2)
        url = self.urlbase + 'data3/123'
        response = makeRequest(url=url, values={'thing':'abc'})

        assert response[1] == 200, \
                 'dao with 1 positional, 1 keyword failed: ' +\
                 '. Got a return code != 200 (got %s)' % response[1] +\
                 '. Returned data: %s' % response[0]
        #Warning quotation type and order matters
        #Should use encoded and decoded format
        self.assertEqual( response[0] ,  "{'thing': 'abc', 'num': '123'}", "should be {'thing': 'abc', 'num': '123'} but got %s" % response[0] )

    def testListTypeArgs(self):
        # 2 positional args (e.g. url/arg1/arg2)
        url = self.urlbase + 'listTypeArgs?aList=1'
        response = makeRequest(url=url)
        assert response[1] == 200 and response[0] == b"[1]", \
                 'list args failed: ' +\
                 '. Got a return code != 200 (got %s)' % response[1] +\
                 '. Returned data: %s' % response[0]


        # 2 values with the same keywords (e.g. url/arg1/arg2)
        url = self.urlbase + 'listTypeArgs?aList=1&aList=2'
        response = makeRequest(url=url)
        assert response[1] == 200 and response[0] == b"[1, 2]", \
                 'list args failed: ' +\
                 '. Got a return code != 200 (got %s)' % response[1] +\
                 '. Returned data: %s' % response[0]

    @cherrypySetup(secureConfig)
    @attr("integration")
    def testAuthentication(self):
        verb ='PUT'
        url = self.urlbase + 'list1'
        urllib_data = urllib.request.urlopen(url)
        self.assertEqual(urllib_data.getcode(), 403)

        # pass proper role
        output={'code':200}
        methodTest(verb, url, output=output,
                   secure=True, secureParam={'key': secureKey,
                                             'role': DUMMY_ROLE,
                                             'group': DUMMY_GROUP,
                                             'site': DUMMY_SITE})
Ejemplo n.º 25
0
import urllib.request, urllib.error
import json

from cherrypy import HTTPError
from nose.plugins.attrib import attr
from tempfile import NamedTemporaryFile

from WMCore_t.WebTools_t.DummyRESTModel import DummyRESTModel
from WMCore_t.WebTools_t.DummyRESTModel import (DUMMY_ROLE, DUMMY_GROUP, DUMMY_SITE)

from WMQuality.WebTools.RESTBaseUnitTest import RESTBaseUnitTest
from WMQuality.WebTools.RESTServerSetup import (DefaultConfig, cherrypySetup)
from WMQuality.WebTools.RESTClientAPI import (makeRequest, methodTest)


secureConfig = DefaultConfig('WMCore_t.WebTools_t.DummyRESTModel')
secureConfig.SecurityModule.dangerously_insecure = False
secureConfig.Webtools.environment = 'production'
tempFile = NamedTemporaryFile()
secureConfig.SecurityModule.key_file = tempFile.name
f = open(tempFile.name,"rb")
secureKey = f.read()
secureConfig.SecurityModule.section_("default")
secureConfig.SecurityModule.default.role = DUMMY_ROLE
secureConfig.SecurityModule.default.group = DUMMY_GROUP
secureConfig.SecurityModule.default.site = DUMMY_SITE

class RESTTest(RESTBaseUnitTest):
    def initialize(self):
        self.config = DefaultConfig('WMCore_t.WebTools_t.DummyRESTModel')
        self.do_debug = False