Esempio n. 1
0
def test_credentials(cred_json, conf_json):
    """
    Tests if credentials in "cred.json" are valid.
    """
    perform_once(__name__ + '.test_credentials')

    from http.client import HTTPSConnection
    from json import loads

    # Checks Client ID and secret ID presence
    client_id = cred_json['client_id']
    client_secret = cred_json['client_secret']
    assert client_id
    assert client_secret

    # Check OAuth credential validity
    def get_oauth_token():
        """Get OAuth token"""
        connection = HTTPSConnection(conf_json['licensing']['url'].split(
            '//', 1)[1])
        connection.request(
            "POST", "/o/token/",
            "client_id=%s&client_secret=%s&grant_type=client_credentials" %
            (client_id, client_secret), {
                'Content-type': 'application/x-www-form-urlencoded',
                'Accept': 'application/json'
            })
        return connection.getresponse()

    for i in range(3):
        response = get_oauth_token()
        status = response.status
        if status == 401 or status < 300:
            break

    if not (200 <= response.status < 300):
        pytest.fail(response.read().decode())
    assert loads(response.read()).get('access_token')
def test_abi_compliance(tmpdir, accelize_drm):
    """
    Test the ABI/API compliance of the lib_name.
    """
    perform_once(__name__ + '.test_abi_compliance')

    if not accelize_drm.pytest_build_environment:
        pytest.skip('This test is only performed on build environment.')
    elif not accelize_drm.pytest_build_type == 'debug':
        pytest.xfail('This test need libraries compiled in debug mode.')

    # Initialize test
    from concurrent.futures import ThreadPoolExecutor, as_completed
    build_futures = []
    dump_futures = []
    latest_futures = []
    tools_futures = []
    latest_dumps = {}
    reports = {}

    with ThreadPoolExecutor() as executor:

        def dumps_library(lib_version, lib_path, futures):
            """
            Dumps a version asynchronously.

            Args:
                lib_version (str): version.
                lib_path (str): Library directory.
                futures (list): Future list.
            """
            include = os.path.join(lib_path, 'include')
            for lib_name in LIB_NAMES:
                futures.append(
                    executor.submit(
                        dump_abi,
                        str(
                            tmpdir.join('%s_%s.abidump' %
                                        (lib_name, lib_version))),
                        os.path.join(lib_path, '%s.so' % lib_name), include,
                        lib_version, lib_name))

        # Get references versions
        abi_version = accelize_drm.get_api_version().major
        versions = executor.submit(get_reference_versions, tmpdir, abi_version)

        # Build reference versions
        versions = versions.result()
        if not versions:
            pytest.skip('No previous versions with ABI version %s' %
                        abi_version)

        print('CHECKING ABI/API AGAINST VERSIONS:', ', '.join(versions))
        for version, path in versions.items():
            build_futures.append(executor.submit(make_tag, version, path))

        # Waits for tools build completion
        for future in as_completed(tools_futures):
            future.result()

        # Dump latest version ABI and API
        dumps_library('latest', '.', latest_futures)

        # Dumps reference versions ABI and API
        for future in as_completed(build_futures):
            version, path = future.result()
            dumps_library(version, path, dump_futures)

        # Waits for latest version dump completion
        for future in as_completed(latest_futures):
            _, dump_file, name = future.result()
            latest_dumps[name] = dump_file

        # Compare latest ABI / API dumps with reference versions
        for future in as_completed(dump_futures):
            version, dump_file, name = future.result()

            reports[' '.join((name, version))] = executor.submit(
                checks_abi_compliance,
                old_dump=dump_file,
                new_dump=latest_dumps[name],
                name=name,
                report_path=str(tmpdir.join('%s%s.html' % (name, version))))

    # Analyses reports
    abi_broken = False
    for title, future in reports.items():
        report = future.result()
        if ('Total binary compatibility problems: 0' not in report
                or 'Total source compatibility problems: 0,' not in report):
            abi_broken = True
            print('Comparison against %s:\n%s\n' % (title, report))

    assert not abi_broken
Esempio n. 3
0
def test_systemd(conf_json, cred_json, tmpdir):
    """Test Accelize DRM systemd service"""
    perform_once(__name__ + '.test_systemd')

    from os import environ
    from socket import socket, AF_UNIX, SOCK_DGRAM
    from threading import Thread
    from time import sleep, time
    import accelize_drm._systemd as systemd
    from accelize_drm._systemd import AccelizeDrmService

    # Set FPGA slot
    fpga_slot_id = 1

    # Set configuration files
    conf_env_var = 'ACCELIZE_DRM_CONF_%s' % fpga_slot_id
    cred_env_var = 'ACCELIZE_DRM_CRED_%s' % fpga_slot_id
    conf_file_path = conf_json.path
    cred_file_path = cred_json.path
    environ[conf_env_var] = conf_file_path
    environ[cred_env_var] = cred_file_path
    default_conf_file_path = AccelizeDrmService.DEFAULT_CONF_FILE_PATH
    default_cred_file_path = AccelizeDrmService.DEFAULT_CRED_FILE_PATH

    # Set FPGA driver to use in configuration
    driver_env_var = 'ACCELIZE_DRM_DRIVER_%s' % fpga_slot_id
    fpga_driver_name = 'driver_name'
    environ[driver_env_var] = fpga_driver_name

    # Mock systemd notify socket
    socket_file = tmpdir.join('sd_notify')
    socket_address = environ['NOTIFY_SOCKET'] = str(socket_file)
    socket_received = []
    socket_stop = False

    class SdNotifySocketThread(Thread):
        """A thread running a UDP socket server"""
        def run(self):
            """Create a connection"""
            with socket(AF_UNIX, SOCK_DGRAM) as sock:
                sock.bind(socket_address)
                sock.setblocking(False)
                t0 = time()
                while True:
                    # Stop loop
                    if socket_stop:
                        break

                    # Timeout to stop test if something is wrong
                    elif time() - t0 > 20:
                        raise TimeoutError()

                    # Wait until error
                    try:
                        socket_received.append(sock.recv(4096))
                    except OSError:
                        continue

    # Mock driver and DRM library

    class Driver:
        """Mocked accelize_drm.fpga_drivers Driver"""
        def __init__(self, **kwargs):
            assert kwargs['fpga_slot_id'] == int(fpga_slot_id), \
                "Driver: Slot ID"
            assert 'drm_ctrl_base_addr' in kwargs, "Driver: Base address"

        read_register_callback = None
        write_register_callback = None

    def _get_driver(name):
        """Mocked accelize_drm.fpga_drivers.get_driver"""
        assert name == fpga_driver_name, 'Get driver: Driver name'
        return Driver

    class DrmManager:
        """Mocked accelize_drm.fpga_drivers Driver"""
        def __init__(self, **kwargs):
            assert kwargs['conf_file_path'] == conf_file_path, \
                'DRM manager: conf.json'
            assert kwargs['cred_file_path'] == cred_file_path, \
                'DRM manager: cred.json'
            assert 'read_register' in kwargs, 'DRM manager: read_register'
            assert 'write_register' in kwargs, 'DRM manager: write_register'

        @staticmethod
        def activate():
            """Do nothing"""

        @staticmethod
        def deactivate():
            """Do nothing"""

        @staticmethod
        def set(*_, **__):
            """Do nothing"""

    systemd_get_driver = systemd._get_driver
    systemd._get_driver = _get_driver
    systemd_drm_manager = systemd._DrmManager
    systemd._DrmManager = DrmManager

    # Tests
    try:
        sd_notify_thread = SdNotifySocketThread()
        try:
            sd_notify_thread.start()

            # Test: Start and stop service
            with AccelizeDrmService() as service:
                # Checks some parameters
                assert service._sd_notify_address == socket_address
                assert list(service._fpga_slots) == [fpga_slot_id]
                assert service._fpga_slots[fpga_slot_id][
                    'conf_file_path'] == conf_json.path
                assert service._fpga_slots[fpga_slot_id][
                    'cred_file_path'] == cred_json.path
                assert service._fpga_slots[fpga_slot_id][
                    'fpga_driver_name'] == fpga_driver_name

            # Test: systemd notification
            sleep(0.1)
            assert socket_received[0].startswith(b'READY=1\nSTATUS=')
            assert socket_received[-1].startswith(b"STOPPING=1")

            # Test: Bad path and error handling
            environ[conf_env_var] = str(tmpdir.join('not_exists'))

            with pytest.raises(KeyboardInterrupt):
                AccelizeDrmService()

            sleep(0.1)
            assert socket_received[-1].startswith(b"STATUS=Error")

        finally:
            socket_stop = True
            sd_notify_thread.join()
            del environ['NOTIFY_SOCKET']
            environ[conf_env_var] = conf_json.path
            socket_file.remove()

        # Test: Socket address starting by @
        fake_address = tmpdir.join('sd_notify_not_exists')
        environ['NOTIFY_SOCKET'] = '@%s' % fake_address
        try:
            assert AccelizeDrmService._get_sd_notify_socket() == \
                   '\0%s' % fake_address
        finally:
            del environ['NOTIFY_SOCKET']

        # Test: Broken socket should not break service
        AccelizeDrmService()

        # Test: Default values
        for key in (conf_env_var, cred_env_var, driver_env_var):
            del environ[key]
        fpga_slot_id = AccelizeDrmService.DEFAULT_FPGA_SLOT_ID
        fpga_driver_name = AccelizeDrmService.DEFAULT_FPGA_DRIVER_NAME
        AccelizeDrmService.DEFAULT_CONF_FILE_PATH = conf_file_path
        AccelizeDrmService.DEFAULT_CRED_FILE_PATH = cred_file_path

        with AccelizeDrmService() as service:
            # Checks some parameters
            assert list(service._fpga_slots) == [fpga_slot_id]
            assert service._fpga_slots[fpga_slot_id] == {}

    except KeyboardInterrupt:
        pytest.fail('Service stopped by "KeyboardInterrupt"')

    finally:
        systemd._get_driver = systemd_get_driver
        systemd._DrmManager = systemd_drm_manager
        AccelizeDrmService.DEFAULT_CONF_FILE_PATH = default_conf_file_path
        AccelizeDrmService.DEFAULT_CRED_FILE_PATH = default_cred_file_path
Esempio n. 4
0
def test_abi_compliance(tmpdir, accelize_drm):
    """
    Test the ABI/API compliance of the lib_name.
    """
    if not accelize_drm.pytest_build_environment:
        pytest.skip('This test is only performed on build environment.')
    elif not accelize_drm.pytest_build_type == 'debug':
        pytest.xfail('This test needs libraries compiled in debug mode.')
    elif not check_dump_abi():
        pytest.xfail(
            'This test cannot be performed because ABI-Dumper app is not usable.'
        )

    perform_once(__name__ + '.test_abi_compliance')

    # Initialize test
    from concurrent.futures import ThreadPoolExecutor, as_completed
    build_tag_futures = []
    dump_tag_futures = []
    dump_current_futures = []
    current_dumps = {}
    reports = {}

    with ThreadPoolExecutor() as executor:

        def dumps_library(lib_version, lib_path, futures):
            """
            Dumps a version asynchronously.
            Args:
                lib_version (str): version.
                lib_path (str): Library directory.
                futures (list): Future list.
            """
            include = join(lib_path, 'include')
            for lib_name in LIB_NAMES:
                futures.append(
                    executor.submit(
                        dump_abi,
                        str(
                            tmpdir.join('%s_%s.abidump' %
                                        (lib_name, lib_version))),
                        join(lib_path, '%s.so' % lib_name), include,
                        lib_version, lib_name))

        # Get reference versions
        abi_version = accelize_drm.get_api_version().major
        versions = executor.submit(get_reference_versions, tmpdir, abi_version)

        # Build reference versions
        versions = versions.result()
        if not versions:
            pytest.skip('No previous versions with ABI version %s' %
                        abi_version)

        print('CHECKING ABI/API AGAINST VERSIONS:', ', '.join(versions))
        # Close each tag with the same major version
        for version, path in versions.items():
            build_tag_futures.append(
                executor.submit(build_tag_version, version, path))

        # Dump current version ABI and API
        dumps_library('current', '.', dump_current_futures)

        # Dumps reference versions ABI and API
        for future in as_completed(build_tag_futures):
            version, path = future.result()
            dumps_library(version, path, dump_tag_futures)

        # Waits for current version dump completion
        for future in as_completed(dump_current_futures):
            _, dump_file, name = future.result()
            current_dumps[name] = dump_file

        # Compare current ABI / API dumps with reference versions
        for future in as_completed(dump_tag_futures):
            version, dump_file, name = future.result()
            report_file = join(accelize_drm.pytest_artifacts_dir,
                               '%s%s.html' % (name, version))
            reports[' '.join(
                (name,
                 version))] = (report_file,
                               executor.submit(checks_abi_compliance,
                                               old_dump=dump_file,
                                               new_dump=current_dumps[name],
                                               name=name,
                                               report_path=report_file))

    # Analyses reports
    abi_broken = False
    for title, (report_file, future) in reports.items():
        stdout = future.result()
        if ('Total binary compatibility problems: 0' not in stdout
                or 'Total source compatibility problems: 0,' not in stdout):
            print('Comparison against %s shows issues:\n%s\n' %
                  (title, stdout))
            abi_broken = True
        else:
            print('Comparison against %s shows no issue:\n%s\n' %
                  (title, stdout))

    assert not abi_broken
Esempio n. 5
0
def test_changelog_and_version(accelize_drm):
    """
    Checks if Version match with Git tag and if changelog is up to date.
    """
    perform_once(__name__ + '.test_changelog_and_version')

    from os.path import join
    from subprocess import run, PIPE
    from re import fullmatch

    if not accelize_drm.pytest_build_environment:
        pytest.skip("Can only be checked in build environment")

    # Ensure tags are pulled
    try:
        run(['git', 'fetch', '--tags', '--force'],
            stderr=PIPE,
            stdout=PIPE,
            universal_newlines=True)
    except FileNotFoundError:
        fail = (pytest.fail
                if accelize_drm.pytest_build_type == 'debug' else pytest.xfail)
        fail('Git is required for this test.')

    # Get head tag if any
    result = run(
        ['git', 'describe', '--abbrev=0', '--exact-match', '--tags', 'HEAD'],
        stderr=PIPE,
        stdout=PIPE,
        universal_newlines=True)

    if result.returncode:
        pytest.skip("Can only be checked on tagged git head")

    tag = result.stdout.strip()
    version = tag.lstrip('v')

    # Checks tag format using library version
    lib_ver = accelize_drm.get_api_version()
    assert tag == 'v%s' % (lib_ver.version.split('+')[0])

    # Check tag format match semantic versioning

    if not fullmatch(
            r'^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)'
            r'(-(0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)'
            r'(\.(0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*)?'
            r'(\+[0-9a-zA-Z-]+(\.[0-9a-zA-Z-]+)*)?$', version):
        pytest.fail('"%s" does not match semantic versioning format.' %
                    version)

    # Check if changelog is up-to-date (Not for prereleases)
    if not lib_ver.prerelease:
        changelog_path = join(accelize_drm.pytest_build_source_dir,
                              'CHANGELOG')
        with open(changelog_path, 'rt') as changelog:
            last_change = changelog.readline().strip()

        assert fullmatch(
            r"\* [a-zA-Z]{3} [a-zA-Z]{3} [0-9]{2} [0-9]{4} Accelize " + tag,
            last_change)

    # Check prerelease format:
    # Alpha: "1.0.0-alpha.1"
    # Beta: "1.0.0-beta.1"
    # Release candidate: "1.0.0-rc.1"
    else:
        assert fullmatch(r"(alpha|beta|rc)\.[0-9]+", lib_ver.prerelease)