<commit_before><commit_msg>Add basic unit tests for /endpoints<commit_after>import base64
import hashlib
import os
import tempfile
import unittest

from argparse import Namespace
from tabpy_server.app.app import TabPyApp
from tabpy_server.handlers.endpoints_handler import EndpointsHandler
from tornado.testing import AsyncHTTPTestCase
from unittest.mock import patch


class TestEndpointsHandlerWithAuth(AsyncHTTPTestCase):
    @classmethod
    def setUpClass(cls):
        cls.patcher = patch(
            'tabpy_server.app.TabPyApp._parse_cli_arguments',
            return_value=Namespace(
                config=None))
        cls.patcher.start()

        prefix = '__TestEndpointsHandlerWithAuth_'
        # create password file
        cls.pwd_file = tempfile.NamedTemporaryFile(
            mode='w+t', prefix=prefix, suffix='.txt', delete=False)
        cls.pwd_file.write('username {}'.format(
            hashlib.sha3_256('password'.encode('utf-8')).hexdigest()))
        cls.pwd_file.close()

        # create state.ini dir and file
        cls.state_dir = tempfile.mkdtemp(prefix=prefix)
        cls.state_file = open(os.path.join(cls.state_dir, 'state.ini'), 'w+')
        cls.state_file.write('[Service Info]\n'
                             'Name = TabPy Serve\n'
                             'Description = \n'
                             'Creation Time = 0\n'
                             'Access-Control-Allow-Origin = \n'
                             'Access-Control-Allow-Headers = \n'
                             'Access-Control-Allow-Methods = \n'
                             '\n'
                             '[Query Objects Service Versions]\n'
                             '\n'
                             '[Query Objects Docstrings]\n'
                             '\n'
                             '[Meta]\n'
                             'Revision Number = 1\n')
        cls.state_file.close()

        # create config file
        cls.config_file = tempfile.NamedTemporaryFile(
            mode='w+t', prefix=prefix, suffix='.conf', delete=False)
        cls.config_file.write(
                '[TabPy]\n'
                'TABPY_PWD_FILE = {}\n'
                'TABPY_STATE_PATH = {}'.format(
                    cls.pwd_file.name,
                    cls.state_dir))
        cls.config_file.close()


    @classmethod
    def tearDownClass(cls):
        cls.patcher.stop()
        os.remove(cls.pwd_file.name)
        os.remove(cls.state_file.name)
        os.remove(cls.config_file.name)
        os.rmdir(cls.state_dir)


    def get_app(self):
        self.app = TabPyApp(self.config_file.name)
        return self.app._create_tornado_web_app()


    def test_no_creds_required_auth_fails(self):
        response = self.fetch('/endpoints')
        self.assertEqual(401, response.code)


    def test_invalid_creds_fails(self):
        response = self.fetch(
            '/endpoints',
            method = 'GET',
            headers = {
                'Authorization': 'Basic {}'.\
                format(
                    base64.b64encode('user:wrong_password'.encode('utf-8')).\
                    decode('utf-8'))
            })
        self.assertEqual(401, response.code)


    def test_valid_creds_pass(self):
        response = self.fetch(
            '/endpoints',
            method = 'GET',
            headers = {
                'Authorization': 'Basic {}'.\
                format(
                    base64.b64encode('username:password'.encode('utf-8')).\
                    decode('utf-8'))
            })
        self.assertEqual(200, response.code)
{'fraction_non_alphanumeric': 0.11061824230662601, 'fraction_numerical': 0.008317161075686166, 'mean_word_length': 1.60882140274765, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '821343', 'n_tokens_mistral': 1040, 'n_tokens_neox': 991, 'n_words': 171}