Пример #1
0
 def test_init_from_environ(self):
     """Test initializing the engine API using the values of environment
     variables.
     """
     # Set environment variable for database and engine base directory
     os.environ[config.ENV_DATABASE] = CONNECT
     os.environ[config.ENV_BASEDIR] = TMP_DIR
     os.environ[config.ENV_SERVICE_NAME] = 'Test service'
     # Create engine without any arguments
     api = EngineApi()
     # The temporary base directory should contain sub-folders for templates
     # and uploaded files. The directory also contains the database file
     tmpl_dir = os.path.join(TMP_DIR, config.TEMPLATE_DIR)
     self.assertTrue(os.path.isdir(tmpl_dir))
     upload_dir = os.path.join(TMP_DIR, config.UPLOAD_DIR)
     self.assertTrue(os.path.isdir(upload_dir))
     db_file = os.path.join(TMP_DIR, 'test.db')
     self.assertTrue(os.path.isfile(db_file))
     # Get the service descriptor
     service = api.service_descriptor()
     self.assertEqual(service[labels.NAME], 'Test service')
     self.assertEqual(service[labels.VERSION], api.version)
     links = hateoas.deserialize(service[labels.LINKS])
     self.assertEqual(len(links), 5)
     self.assertTrue(hateoas.SELF in links)
     self.assertTrue(hateoas.user(hateoas.LOGIN) in links)
     self.assertTrue(hateoas.user(hateoas.LOGOUT) in links)
     self.assertTrue(hateoas.user(hateoas.REGISTER) in links)
     self.assertTrue(hateoas.benchmark(hateoas.LIST) in links)
     # Make sure to close the database connesction
     api.close()
Пример #2
0
 def setUp(self):
     """Create empty directory."""
     if os.path.isdir(TMP_DIR):
         shutil.rmtree(TMP_DIR)
     os.mkdir(TMP_DIR)
     os.environ[config.ENV_DATABASE] = CONNECT
     DatabaseDriver.init_db()
     os.environ[config.ENV_BASEDIR] = os.path.join(TMP_DIR)
     self.engine = EngineApi()
Пример #3
0
class TestBenchmarkApi(TestCase):
    """Test API methods that access and list benchmarks and leaderboards."""
    def setUp(self):
        """Create empty directory."""
        if os.path.isdir(TMP_DIR):
            shutil.rmtree(TMP_DIR)
        os.mkdir(TMP_DIR)
        os.environ[config.ENV_DATABASE] = CONNECT
        os.environ[config.ENV_BASEDIR] = TMP_DIR
        DatabaseDriver.init_db()
        self.engine = EngineApi()

    def tearDown(self):
        """Remove temporary directory."""
        self.engine.close()
        if os.path.isdir(TMP_DIR):
            shutil.rmtree(TMP_DIR)

    def test_get_benchmark(self):
        """Test get benchmark handle."""
        repo = self.engine.benchmarks().repository
        benchmark = repo.add_benchmark(name='First competition',
                                       description='Some text',
                                       instructions='More text',
                                       src_dir=TEMPLATE_DIR)
        benchmark_id = benchmark.identifier
        response = self.engine.benchmarks().get_benchmark(benchmark_id)
        self.validate_benchmark(response,
                                is_handle=True,
                                has_description=True,
                                has_instructions=True)
        # Create benchmark without the optional description and instructions
        benchmark = repo.add_benchmark(name='Second competition',
                                       src_dir=TEMPLATE_DIR)
        benchmark_id = benchmark.identifier
        response = self.engine.benchmarks().get_benchmark(benchmark_id)
        self.validate_benchmark(response,
                                is_handle=True,
                                has_description=False,
                                has_instructions=False)
        # Get handle for invalid access token will raise error
        with self.assertRaises(err.UnauthenticatedAccessError):
            self.engine.benchmarks().get_benchmark(benchmark_id,
                                                   access_token='unknown')

    def test_list_benchmarks(self):
        """Test benchmark listing."""
        repo = self.engine.benchmarks().repository
        benchmark1 = repo.add_benchmark(name='First competition',
                                        description='Some text',
                                        instructions='More text',
                                        src_dir=TEMPLATE_DIR)
        benchmark2 = repo.add_benchmark(name='Second competition',
                                        src_dir=TEMPLATE_DIR)
        response = self.engine.benchmarks().list_benchmarks()
        self.assertEqual(len(response), 2)
        self.assertTrue(labels.BENCHMARKS in response)
        self.assertTrue(labels.LINKS in response)
        benchmarks = response[labels.BENCHMARKS]
        self.assertEqual(len(benchmarks), 2)
        names = set()
        for benchmark in benchmarks:
            names.add(benchmark[labels.NAME])
            self.validate_benchmark(
                benchmark,
                has_description=benchmark[labels.ID] == benchmark1.identifier,
                has_instructions=benchmark[labels.ID] == benchmark1.identifier)
        self.assertTrue('First competition' in names)
        self.assertTrue('Second competition' in names)
        links = hateoas.deserialize(response[labels.LINKS])
        self.assertEqual(len(links), 1)
        self.assertTrue(hateoas.SELF in links)
        # Get listing for invalid access token
        with self.assertRaises(err.UnauthenticatedAccessError):
            self.engine.benchmarks().list_benchmarks(access_token='unknown')

    def validate_benchmark(
            self,
            benchmark,
            is_handle=False,
            has_description=False,
            has_instructions=False,
            rels=[hateoas.SELF,
                  hateoas.benchmark(hateoas.LEADERBOARD)]):
        """Validate a given serialization of a benchmark descriptor."""
        elements = [labels.ID, labels.NAME, labels.LINKS]
        if has_description:
            elements.append(labels.DESCRIPTION)
        if has_instructions:
            elements.append(labels.INSTRUCTIONS)
        if is_handle:
            elements.append(labels.PARAMETERS)
        self.assertEqual(len(benchmark), len(elements))
        for key in elements:
            self.assertTrue(key in benchmark)
        links = hateoas.deserialize(benchmark[labels.LINKS])
        self.assertEqual(len(links), len(rels))
        for key in rels:
            self.assertTrue(key in links)
Пример #4
0
class TestUserApi(TestCase):
    """Test API methods that access and manipulate users."""
    def setUp(self):
        """Create empty directory."""
        if os.path.isdir(TMP_DIR):
            shutil.rmtree(TMP_DIR)
        os.mkdir(TMP_DIR)
        os.environ[config.ENV_DATABASE] = CONNECT
        DatabaseDriver.init_db()
        os.environ[config.ENV_BASEDIR] = os.path.join(TMP_DIR)
        self.engine = EngineApi()

    def tearDown(self):
        """Remove temporary directory."""
        self.engine.close()
        if os.path.isdir(TMP_DIR):
            shutil.rmtree(TMP_DIR)

    def test_login_user(self):
        """Test logging in and logging out."""
        users = self.engine.users()
        users.register(username='******', password='******')
        response = users.login(username='******', password='******')
        self.assertEqual(len(response), 2)
        self.assertTrue(labels.ACCESS_TOKEN in response)
        self.assertTrue(labels.LINKS in response)
        links = hateoas.deserialize(response[labels.LINKS])
        self.assertEqual(len(links), 2)
        self.assertTrue(hateoas.SERVICE in links)
        self.assertTrue(hateoas.user(hateoas.LOGOUT) in links)
        response = users.logout(response[labels.ACCESS_TOKEN])
        self.assertEqual(len(response), 2)
        self.assertTrue(labels.STATE in response)
        self.assertTrue(labels.LINKS in response)
        links = hateoas.deserialize(response[labels.LINKS])
        self.assertEqual(len(links), 1)
        self.assertTrue(hateoas.user(hateoas.LOGIN) in links)
        response = users.logout('unknown')
        self.assertEqual(len(response), 2)
        self.assertTrue(labels.STATE in response)
        self.assertTrue(labels.LINKS in response)
        links = hateoas.deserialize(response[labels.LINKS])
        self.assertEqual(len(links), 1)
        self.assertTrue(hateoas.user(hateoas.LOGIN) in links)

    def test_register_user(self):
        """Test new user registration via API."""
        users = self.engine.users()
        response = users.register(username='******', password='******')
        self.assertEqual(len(response), 3)
        self.assertTrue(labels.ID in response)
        self.assertTrue(labels.USERNAME in response)
        self.assertTrue(labels.LINKS in response)
        links = hateoas.deserialize(response[labels.LINKS])
        self.assertEqual(len(links), 2)
        self.assertTrue(hateoas.user(hateoas.LOGIN) in links)
        self.assertTrue(hateoas.user(hateoas.LOGOUT) in links)
        # Errors when registering users with existing or invalid user names
        with self.assertRaises(err.DuplicateUserError):
            users.register(username='******', password='******')
        with self.assertRaises(err.ConstraintViolationError):
            users.register(username='******' * 256, password='******')

    def test_whoami(self):
        """Test retrieving information for current user."""
        users = self.engine.users()
        users.register(username='******', password='******')
        response = users.login(username='******', password='******')
        response = users.whoami(response[labels.ACCESS_TOKEN])
        self.assertEqual(len(response), 3)
        self.assertTrue(labels.ID in response)
        self.assertTrue(labels.USERNAME in response)
        self.assertTrue(labels.LINKS in response)

    def test_whoarethey(self):
        """Test retrieving information for current user."""
        users = self.engine.users()
        response = users.register(username='******', password='******')
        user_id = response[labels.ID]
        response = users.whoarethey('myuser')
        self.assertEqual(len(response), 3)
        self.assertTrue(labels.ID in response)
        self.assertTrue(labels.USERNAME in response)
        self.assertTrue(labels.LINKS in response)
        self.assertEqual(response[labels.ID], user_id)
        self.assertEqual(response[labels.USERNAME], 'myuser')
Пример #5
0
class TestTeamApi(TestCase):
    """Test API methods that access and manipulate teams."""
    def setUp(self):
        """Create empty directory."""
        if os.path.isdir(TMP_DIR):
            shutil.rmtree(TMP_DIR)
        os.mkdir(TMP_DIR)
        os.environ[config.ENV_DATABASE] = CONNECT
        os.environ[config.ENV_BASEDIR] = os.path.join(TMP_DIR, 'files')
        DatabaseDriver.init_db()
        self.engine = EngineApi()

    def tearDown(self):
        """Remove temporary directory."""
        self.engine.close()
        if os.path.isdir(TMP_DIR):
            shutil.rmtree(TMP_DIR)

    def test_create_team(self):
        """Test creating a new team."""
        users = self.engine.users()
        users.register(username='******', password='******')
        response = users.login(username='******', password='******')
        access_token = response[labels.ACCESS_TOKEN]
        teams = self.engine.teams()
        response = teams.create_team(access_token=access_token, name='My Team')
        self.assertEqual(len(response), 5)
        self.assertTrue(labels.ID in response)
        self.assertTrue(labels.NAME in response)
        self.assertTrue(labels.OWNER_ID in response)
        self.assertTrue(labels.MEMBER_COUNT in response)
        self.assertTrue(labels.LINKS in response)
        self.assertEqual(response[labels.MEMBER_COUNT], 1)
        links = hateoas.deserialize(response[labels.LINKS])
        self.assertEqual(len(links), 4)
        self.assertTrue(hateoas.SELF in links)
        self.assertTrue(hateoas.ADD in links)
        self.assertTrue(hateoas.DELETE in links)
        self.assertTrue(hateoas.UPLOAD in links)
        # Error when specifying unknonw user
        with self.assertRaises(err.UnknownUserError):
            teams.create_team(access_token=access_token,
                              name='No Team',
                              members=['myfriend'])
        response = users.register(username='******', password='******')
        user_id = response[labels.ID]
        response = teams.create_team(access_token=access_token,
                                     name='No Team',
                                     members=[user_id])
        self.assertEqual(response[labels.MEMBER_COUNT], 2)

    def test_delete_team(self):
        """Test deleting a team."""
        # Initialize database with two user, each being the owner of one team
        users = self.engine.users()
        users.register(username='******', password='******')
        users.register(username='******', password='******')
        token1 = users.login(username='******', password='******')[labels.ACCESS_TOKEN]
        token2 = users.login(username='******', password='******')[labels.ACCESS_TOKEN]
        teams = self.engine.teams()
        team1 = teams.create_team(access_token=token1, name='Team1')[labels.ID]
        team2 = teams.create_team(access_token=token2, name='Team2')[labels.ID]
        # Delete team 1 for user 1 returns SUCCESS
        response = self.engine.teams().delete_team(team_id=team1,
                                                   access_token=token1)
        self.assertEqual(response, {labels.STATE: 'SUCCESS'})
        # Deleting the same team again will raise unknown team error
        with self.assertRaises(err.UnknownTeamError):
            self.engine.teams().delete_team(team_id=team1, access_token=token1)
        # If user 1 attempts to delete team 2 an error is raised
        with self.assertRaises(err.UnauthorizedAccessError):
            self.engine.teams().delete_team(team_id=team2, access_token=token1)
        # The superuser (no access token) can delete team 2
        response = self.engine.teams().delete_team(team_id=team2)
        self.assertEqual(response, {labels.STATE: 'SUCCESS'})

    def test_team_get(self):
        """Test get team handle."""
        users = self.engine.users()
        users.register(username='******', password='******')[labels.ID]
        users.register(username='******', password='******')[labels.ID]
        token1 = users.login(username='******', password='******')[labels.ACCESS_TOKEN]
        token2 = users.login(username='******', password='******')[labels.ACCESS_TOKEN]
        teams = self.engine.teams()
        # User 1 and 2 are member of two teams.
        team_id = teams.create_team(access_token=token1,
                                    name='Team1')[labels.ID]
        response = teams.get_team(team_id=team_id, access_token=token1)
        self.assertEqual(len(response), 6)
        self.assertTrue(labels.ID in response)
        self.assertTrue(labels.NAME in response)
        self.assertTrue(labels.MEMBERS in response)
        self.assertTrue(labels.MEMBER_COUNT in response)
        self.assertTrue(labels.OWNER_ID in response)
        self.assertTrue(labels.LINKS in response)
        members = response[labels.MEMBERS]
        for user in members:
            self.assertEqual(len(user), 3)
            self.assertTrue(labels.ID in user)
            self.assertTrue(labels.USERNAME in user)
            self.assertTrue(labels.LINKS in user)
            links = hateoas.deserialize(user[labels.LINKS])
            self.assertEqual(len(links), 1)
            self.assertTrue(hateoas.DELETE in links)
        links = hateoas.deserialize(response[labels.LINKS])
        self.assertEqual(len(links), 4)
        self.assertTrue(hateoas.SELF in links)
        self.assertTrue(hateoas.ADD in links)
        self.assertTrue(hateoas.DELETE in links)
        self.assertTrue(hateoas.UPLOAD in links)
        team_id = teams.create_team(access_token=token2,
                                    name='Team2')[labels.ID]
        with self.assertRaises(err.UnauthorizedAccessError):
            teams.get_team(team_id=team_id, access_token=token1)
        teams.get_team(team_id=team_id)

    def test_list_teams(self):
        """Test getting team listings."""
        users = self.engine.users()
        u1 = users.register(username='******', password='******')[labels.ID]
        u2 = users.register(username='******', password='******')[labels.ID]
        token1 = users.login(username='******', password='******')[labels.ACCESS_TOKEN]
        token2 = users.login(username='******', password='******')[labels.ACCESS_TOKEN]
        teams = self.engine.teams()
        # User 1 and 2 are member of two teams.
        teams.create_team(access_token=token1, name='Team1')
        teams.create_team(access_token=token2, name='Team2', members=[u1])
        teams.create_team(access_token=token2, name='Team3')
        tlist = teams.list_teams(access_token=token1)
        self.assertEqual(len(tlist[labels.TEAMS]), 2)
        links = hateoas.deserialize(tlist[labels.LINKS])
        self.assertEqual(len(links), 2)
        self.assertTrue(hateoas.SELF in links)
        self.assertTrue(hateoas.CREATE in links)
        tlist = teams.list_teams(access_token=token2)
        self.assertEqual(len(tlist[labels.TEAMS]), 2)
        tlist = teams.list_teams()
        self.assertEqual(len(tlist[labels.TEAMS]), 3)

    def test_team_members(self):
        """Test adding and removing team members."""
        # Initialize database with three users and one team
        users = self.engine.users()
        u1 = users.register(username='******', password='******')[labels.ID]
        u2 = users.register(username='******', password='******')[labels.ID]
        u3 = users.register(username='******', password='******')[labels.ID]
        token1 = users.login(username='******', password='******')[labels.ACCESS_TOKEN]
        token2 = users.login(username='******', password='******')[labels.ACCESS_TOKEN]
        teams = self.engine.teams()
        team1 = teams.create_team(access_token=token1, name='Team1')[labels.ID]
        teams = self.engine.teams()
        # User 2 cannot add themselves as team member
        with self.assertRaises(err.UnauthorizedAccessError):
            teams.add_members(team_id=team1, members=[u2], access_token=token2)
        # User 1 can add user 2 as team member
        response = teams.add_members(team_id=team1,
                                     members=[u2],
                                     access_token=token1)
        self.assertTrue(len(response[labels.MEMBERS]), 2)
        # The superuser can also add team members
        response = teams.add_members(team_id=team1, members=[u3])
        self.assertTrue(len(response[labels.MEMBERS]), 3)
        # User 2 cannot remove user 3 as team member
        with self.assertRaises(err.UnauthorizedAccessError):
            teams.remove_member(team_id=team1,
                                member_id=u3,
                                access_token=token2)
        # User 2 can remove themselves as team member
        response = teams.remove_member(team_id=team1,
                                       member_id=u2,
                                       access_token=token2)
        self.assertTrue(len(response[labels.MEMBERS]), 2)
        # User 1 can remove user 3 as team member
        response = teams.remove_member(team_id=team1,
                                       member_id=u3,
                                       access_token=token1)
        self.assertTrue(len(response[labels.MEMBERS]), 1)
        # User 1 cannot remove themselves as team member
        with self.assertRaises(err.ConstraintViolationError):
            teams.remove_member(team_id=team1,
                                member_id=u1,
                                access_token=token1)

    def test_update_team_name(self):
        """Test updating the team name."""
        users = self.engine.users()
        users.register(username='******', password='******')[labels.ID]
        users.register(username='******', password='******')[labels.ID]
        token1 = users.login(username='******', password='******')[labels.ACCESS_TOKEN]
        token2 = users.login(username='******', password='******')[labels.ACCESS_TOKEN]
        teams = self.engine.teams()
        # Create first team and rename it
        team_id = teams.create_team(access_token=token1,
                                    name='Team1')[labels.ID]
        response = teams.update_team_name(team_id=team_id,
                                          name='My Team',
                                          access_token=token1)
        self.assertEqual(len(response), 5)
        self.assertEqual(response[labels.NAME], 'My Team')
        # Create second team and let user2 try to rename it
        team_id = teams.create_team(access_token=token1,
                                    name='Team1')[labels.ID]
        with self.assertRaises(err.UnauthorizedAccessError):
            teams.update_team_name(team_id=team_id,
                                   name='My Other Team',
                                   access_token=token2)

    def test_upload_files(self):
        """Test uploading and deleting files."""
        # Create two users and one team
        users = self.engine.users()
        users.register(username='******', password='******')[labels.ID]
        users.register(username='******', password='******')[labels.ID]
        token1 = users.login(username='******', password='******')[labels.ACCESS_TOKEN]
        token2 = users.login(username='******', password='******')[labels.ACCESS_TOKEN]
        teams = self.engine.teams()
        team_id = teams.create_team(access_token=token1,
                                    name='Team1')[labels.ID]
        # Upload file
        response = teams.upload_file(file=FakeStream(),
                                     file_name='file.txt',
                                     team_id=team_id,
                                     access_token=token1)
        self.assertEqual(len(response), 5)
        self.assertTrue(labels.ID in response)
        self.assertTrue(labels.NAME in response)
        self.assertTrue(labels.CREATED_AT in response)
        self.assertTrue(labels.FILESIZE in response)
        self.assertTrue(labels.LINKS in response)
        links = hateoas.deserialize(response[labels.LINKS])
        self.assertEqual(len(links), 2)
        self.assertTrue(hateoas.DELETE in links)
        self.assertTrue(hateoas.DOWNLOAD in links)
        # Error when uploading as a non-member
        with self.assertRaises(err.UnauthorizedAccessError):
            teams.upload_file(file=FakeStream(),
                              file_name='file.txt',
                              team_id=team_id,
                              access_token=token2)
        # Get handle for uploaded file
        file_id = response[labels.ID]
        fh = teams.get_file(team_id=team_id,
                            file_id=file_id,
                            access_token=token1)
        self.assertEqual(fh, response)
        # Error when getting file as a non-member
        with self.assertRaises(err.UnauthorizedAccessError):
            teams.get_file(team_id=team_id,
                           file_id=file_id,
                           access_token=token2)
        # Error when deleting file as non member
        with self.assertRaises(err.UnauthorizedAccessError):
            teams.delete_file(team_id=team_id,
                              file_id=file_id,
                              access_token=token2)
        # Delete file
        response = teams.delete_file(team_id=team_id,
                                     file_id=file_id,
                                     access_token=token1)
        self.assertEqual(response, {labels.STATE: 'SUCCESS'})
        # Error when accessing or deleting a non-existing file
        with self.assertRaises(err.UnknownFileError):
            teams.get_file(team_id=team_id,
                           file_id=file_id,
                           access_token=token1)
        with self.assertRaises(err.UnknownFileError):
            teams.delete_file(team_id=team_id,
                              file_id=file_id,
                              access_token=token1)