예제 #1
0
def calculate_section_sizes(builddir):
    '''
    Return the sizes of the main sections.
    '''
    section_sizes = {'bss': 0, 'text': 0, 'data': 0, 'rodata': 0}

    mapfile = utils.join(builddir, 'linker.map')
    libdir = utils.join(builddir, 'libs')

    if not (utils.exists(mapfile) and utils.exists(libdir)):
        return section_sizes

    # Get the names of the object files that the static
    # libraries (libjerry-core.a, ...) have.
    objlist = read_objects_from_libs(libdir, _LIBLIST)

    raw_data = lumpy.load_map_data(mapfile)
    sections = lumpy.parse_to_sections(raw_data)
    # Extract .rodata section from the .text section.
    lumpy.hoist_section(sections, '.text', '.rodata')

    for section in sections:
        section_name = section['name'][1:]
        # Skip sections that are not relevant.
        if section_name not in section_sizes.keys():
            continue

        for entry in section['contents']:
            if any(obj in entry['path'] for obj in objlist):
                section_sizes[section_name] += entry['size']

    return section_sizes
예제 #2
0
    def run(self):
        '''
        Main method to run IoT.js or JerryScript tests.
        '''
        if self.env.options.no_test:
            return

        reporter.report_configuration(self.env)

        for testset, tests in read_testsets(self.env).items():
            self.run_testset(testset, tests)

        if self.env.options.coverage:
            device = self.env.options.device
            app_name = self.env.options.app

            if device in ['artik053', 'artik530', 'rpi2'
                          ] and app_name == 'iotjs':
                iotjs = self.env.modules.iotjs
                commit_info = utils.last_commit_info(iotjs['src'])
                result_name = 'cov-%s-%s.json' % (commit_info['commit'],
                                                  commit_info['date'])
                result_dir = utils.join(paths.RESULT_PATH,
                                        '%s/%s/' % (app_name, device))
                result_path = utils.join(result_dir, result_name)

            self.coverage_info = testrunner_utils.parse_coverage_info(
                self.env, result_path)

            reporter.report_coverage(self.coverage_info)

        reporter.report_final(self.results)
예제 #3
0
    def _build_iotjs(self, profile, extra_flags):
        '''
        Build IoT.js for Tizen target.
        '''
        iotjs = self.env['modules']['iotjs']

        profiles = {
            'minimal': 'profiles/minimal.profile',
            'target': 'test/profiles/tizen.profile'
        }

        build_flags = [
            '--clean', '--no-parallel-build', '--no-init-submodule',
            '--target-arch=noarch', '--target-os=tizen', '--target-board=rpi3',
            '--profile=%s' % profiles[profile],
            '--buildtype=%s' % self.env['info']['buildtype']
        ] + extra_flags

        iotjs_build_options = ' '.join(build_flags)
        # Note: these values should be defined for GBS, because
        #       it will compile the IoT.js itself.
        utils.define_environment('IOTJS_BUILD_OPTION', iotjs_build_options)

        args = ['--clean']

        if self.env['info']['buildtype'] == 'debug':
            args.append('--debug')

        utils.execute(iotjs['src'], 'config/tizen/gbsbuild.sh', args)

        tizen_build_dir = utils.join(paths.GBS_IOTJS_PATH, 'build')
        iotjs_build_dir = utils.join(iotjs['src'], 'build')
        # Copy the GBS created binaries to the iotjs build folder.
        # Note: GBS compiles iotjs in the GBS folder.
        utils.copy(tizen_build_dir, iotjs_build_dir)
예제 #4
0
    def _copy_build_files(self, target_module, builddir):
        '''
        Copy the created binaries, libs, linker map to the build folder.
        '''
        application = self.env['modules']['app']

        linker_map = utils.join(builddir, 'linker.map')
        lib_folder = utils.join(builddir, 'libs')

        utils.copy(application['paths']['libdir'], lib_folder)
        utils.copy(target_module['paths']['linker-map'], linker_map)
        utils.copy(target_module['paths']['image'], builddir)
예제 #5
0
    def create_result(self):
        '''
        Create a final JSON result file from the build and test information.
        '''
        result = {'bin': {}, 'date': {}, 'tests': {}, 'submodules': {}}

        labels = {
            'profiles/minimal-profile-build':
            'minimal-profile',
            'profiles/target-es5.1-profile-build':
            'target-es5_1-profile',
            'profiles/target-es2015subset-profile-build':
            'target-es2015subset-profile'
        }

        for job_id, build_path in self.results.iteritems():
            # Append the binary information.
            if 'test-build' in job_id:
                filename = utils.join(build_path, 'testresults.json')
                # Do not save the testresults if there is no available data.
                if not utils.exists(filename):
                    continue

                result.update(utils.read_json_file(filename))

            else:
                filename = utils.join(build_path, 'build.json')
                # Do not save build info if there is no available data.
                if not utils.exists(filename):
                    continue

                bin_data = utils.read_json_file(filename)
                # Translate job_id to database schema name.
                label = labels[job_id]

                result['bin'][label] = bin_data['bin']
                result['submodules'] = bin_data['submodules']
                result['date'] = bin_data['last-commit-date']

        filepath = utils.join(paths.RESULT_PATH, self.options.app,
                              self.options.device)
        filename = utils.join(filepath, utils.current_date() + '.json')
        # Save the content info a result file.
        utils.write_json_file(filename, result)

        console.log()
        console.log('The results are written into:', console.TERMINAL_BLUE)
        console.log('  {json_file}'.format(json_file=filename))
        console.log()

        return result
예제 #6
0
def read_test_files(env):
    '''
    Read all the tests from the given folder and create a
    dictionary similar to the IoT.js testsets.json file.
    '''
    testsets = {}
    # Read all the tests from the application.
    app = env.modules.app
    testpath = app.paths.tests

    for root, _, files in os.walk(testpath):
        # The name of the testset is always the folder name.
        testset = utils.relpath(root, utils.abspath(utils.join(testpath,
                                                               '..')))

        # Create a new testset entry if it doesn't exist.
        if testset not in testsets:
            testsets[testset] = []

        for filename in files:
            test = {'name': filename}

            if 'fail' in testset:
                test['expected-failure'] = True

            testsets[testset].append(test)

    return testsets
예제 #7
0
def parse_coverage_info(env, coverage_output):
    '''
    Parse and create coverage information
    '''
    coverage_info = {}

    iotjs = env.modules.iotjs
    js_folder = iotjs.paths['js-sources']

    # Store line information from the JS sources.
    for js_file in os.listdir(js_folder):
        filename, _ = os.path.splitext(js_file)

        coverage_info[filename] = {}
        coverage_info[filename]['lines'] = []
        coverage_info[filename]['coverage'] = [0, 0]

        js_file_path = utils.join(js_folder, js_file)

        with open(js_file_path, "r") as js_source:
            lines = js_source.readlines()

            for line in lines:
                # '0' indicates that the line has not been reached yet.
                coverage_info[filename]['lines'].append([line, '0'])

    with open(coverage_output, 'r') as cov_p:
        raw_data = json.load(cov_p)

        ignore_list = ['run_pass', 'run_fail', 'node', 'tools']

        for js_name in raw_data:
            # Skip empty key value.
            if not js_name:
                continue

            # Ignore test and tool files.
            if any(ignored_name in js_name for ignored_name in ignore_list):
                continue

            filename, _ = os.path.splitext(js_name)
            if filename not in coverage_info:
                continue

            # Iterate reached js files.
            for line_number, line_value in raw_data[js_name].iteritems():
                if line_value:
                    # Increase covered lines.
                    coverage_info[filename]['coverage'][0] += 1
                    # '2' indicates that the line has been covered.
                    coverage_info[filename]['lines'][int(line_number) -
                                                     1][1] = '2'
                else:
                    # '1' indicates that the line has not been covered.
                    coverage_info[filename]['lines'][int(line_number) -
                                                     1][1] = '1'

                coverage_info[filename]['coverage'][1] += 1

    return coverage_info
예제 #8
0
def create_build_info(env):
    '''
    Write binary size and commit information into a file.
    '''
    app_name = env['info']['app']
    build_path = env['paths']['build']

    # Binary size information.
    minimal_builddir = env['paths']['build-minimal']
    target_builddir = env['paths']['build-target']

    bin_sizes = {
        'minimal-profile': calculate_section_sizes(minimal_builddir),
        'target-profile': calculate_section_sizes(target_builddir)
    }

    # Git commit information from the projects.
    submodules = {}

    for name, module in env['modules'].iteritems():
        # Don't duplicate the application information.
        if name == 'app':
            continue

        submodules[name] = utils.last_commit_info(module['src'])

    # Merge the collected values into a result object.
    build_info = {
        'build-date': utils.current_date('%Y-%m-%dT%H.%M.%SZ'),
        'last-commit-date': submodules[app_name]['date'],
        'bin': bin_sizes,
        'submodules': submodules
    }

    utils.write_json_file(utils.join(build_path, 'build.json'), build_info)
예제 #9
0
    def save(self):
        '''
        Save the current testresults into JSON format.
        '''
        if self.env['info']['no_test']:
            return

        build_file = self.env['paths']['build-json']
        build_info = utils.read_json_file(build_file)

        # Add the build information.
        test_info = {
            'date': build_info['last-commit-date'],
            'bin': build_info['bin'],
            'submodules': build_info['submodules']
        }

        # Specify a date named results file.
        result_dir = self.env['paths']['result']
        filename = utils.join(result_dir, build_info['build-date'])

        if self.env['info']['coverage']:
            # Add the coverage information.
            test_info['coverage_info'] = self.coverage_info
            filename += '_coverage'
        else:
            # Add the test results.
            test_info['tests'] = self.results

        # Save the results into the date named file.
        utils.write_json_file(filename + '.json', test_info)

        # Publish the results if necessary.
        testrunner_utils.upload_data_to_firebase(self.env, test_info)
예제 #10
0
def read_testsets(env):
    '''
    Read all the tests into dictionary.
    '''
    testset = utils.join(env.modules.app.paths.tests, 'testsets.json')

    if utils.exists(testset):
        return utils.read_json_file(testset)

    return testrunner_utils.read_test_files(env)
예제 #11
0
    def initialize(self):
        '''
        Flash the device.
        '''
        if self.env['info']['no_flash']:
            return

        target_app = self.env['modules']['app']
        build_path = self.env['paths']['build']

        test_src = target_app['paths']['tests']
        test_dst = utils.join(build_path, 'tests')

        # 1. Copy all the necessary files.
        # Copy applicaiton RPM package file.
        rpm_package_path = self.env['paths']['tizen-rpm-package']
        utils.copy(rpm_package_path, build_path)

        # Copy all the tests into the build folder.
        utils.copy(test_src, test_dst)

        utils.copy(paths.FREYA_TESTER, build_path)

        if not self.env['info']['no_memstat']:
            utils.copy(paths.FREYA_CONFIG, build_path)

            # Resolve the iotjs-dirname macro in the Freya configuration file.
            basename = utils.basename(paths.GBS_IOTJS_PATH)
            sed_flags = [
                '-i',
                's/%%{iotjs-dirname}/%s/g' % basename, 'iotjs-freya.config'
            ]
            utils.execute(build_path, 'sed', sed_flags)

        # 2. Deploy the build folder to the device.
        self.login()
        self.channel.exec_command('mount -o remount,rw /')

        shell_flags = 'ssh -p %s' % self.port
        rsync_flags = [
            '--rsh', shell_flags, '--recursive', '--compress', '--delete'
        ]
        # Note: slash character is required after the path.
        # In this case `rsync` copies the whole folder, not
        # the subcontents to the destination.
        src = self.env['paths']['build'] + '/'
        dst = '%s@%s:%s' % (self.user, self.ip, self.workdir)

        utils.execute('.', 'rsync', rsync_flags + [src, dst])

        # 3. Install rpm package
        template = 'rpm -ivh --force --nodeps %s/%s-1.0.0-0.armv7l.rpm'
        self.channel.exec_command(template % (self.workdir, self.app))

        self.logout()
예제 #12
0
    def _build_freya(self):
        '''
        Cross-compile Valgrind and its Freya tool.
        '''
        build_dir = utils.join(self.env['paths']['build'], 'valgrind_freya')
        valgrind_files = [
            'vg-in-place', 'coregrind/valgrind', '.in_place/freya-arm-linux',
            '.in_place/vgpreload_core-arm-linux.so',
            '.in_place/vgpreload_freya-arm-linux.so'
        ]

        # Check if a Freya build already exists, if yes, skip the build.
        if utils.exist_files(build_dir, valgrind_files):
            return

        freya = self.env['modules']['freya']

        utils.define_environment('LD', 'arm-linux-gnueabihf-ld')
        utils.define_environment('AR', 'arm-linux-gnueabihf-ar')
        utils.define_environment('CC', 'arm-linux-gnueabihf-gcc')
        utils.define_environment('CPP', 'arm-linux-gnueabihf-cpp')
        utils.define_environment('CXX', 'arm-linux-gnueabihf-g++')

        configure_options = ['--host=armv7-linux-gnueabihf']

        utils.execute(freya['src'], './autogen.sh')
        utils.execute(freya['src'], './configure', configure_options)
        utils.execute(freya['src'], 'make', ['clean'])
        utils.execute(freya['src'], 'make', ['TOOLS=freya'])

        utils.unset_environment('LD')
        utils.unset_environment('AR')
        utils.unset_environment('CC')
        utils.unset_environment('CPP')
        utils.unset_environment('CXX')

        # Copy necessary files into the output directory.
        for valgrind_file in valgrind_files:
            src = utils.join(freya['src'], valgrind_file)
            dst = utils.join(build_dir, valgrind_file)

            utils.copy(src, dst)
예제 #13
0
def run_coverage_script(env):
    '''
    Start the client script.
    '''
    # Add latency because the start up of the debug server needs time.
    time.sleep(2)

    address = env.options.debugger
    iotjs = env.modules.iotjs
    coverage_client = iotjs.paths['coverage-client']
    device = env.options.device
    app_name = env.options.app

    commit_info = utils.last_commit_info(iotjs['src'])
    result_name = 'cov-%s-%s.json' % (commit_info['commit'],
                                      commit_info['date'])
    result_dir = utils.join(paths.RESULT_PATH, '%s/%s/' % (app_name, device))
    result_path = utils.join(result_dir, result_name)

    utils.mkdir(result_dir)
    utils.execute(paths.PROJECT_ROOT, 'python',
                  [coverage_client, '--coverage-output', result_path, address])
예제 #14
0
    def _read_skiplist(self):
        '''
        Read the local skiplists.
        '''
        skiplists = {
            'iotjs': 'iotjs-skiplist.json',
            'jerryscript': 'jerryscript-skiplist.json'
        }

        skipfile = utils.join(paths.TESTRUNNER_PATH, skiplists[self.app])
        skiplist = utils.read_json_file(skipfile)

        return skiplist[self.device_type]
예제 #15
0
def run_coverage_script(env):
    '''
    Start the client script.
    '''
    # Add latency because the start up of the debug server needs time.
    time.sleep(2)

    address = env['info']['coverage']
    iotjs = env['modules']['iotjs']
    coverage_client = iotjs['paths']['coverage-client']
    device = env['info']['device']
    app_name = env['info']['app']

    commit_info = utils.last_commit_info(iotjs['src'])
    result_name = 'cov-%s-%s.json' % (commit_info['commit'], commit_info['date'])
    result_dir = utils.join(paths.RESULT_PATH, '%s/%s/' % (app_name, device))
    result_path = utils.join(result_dir, result_name)

    utils.mkdir(result_dir)
    utils.execute(paths.PROJECT_ROOT, coverage_client, ['--non-interactive',
                                                        '--coverage-output=%s' % result_path,
                                                        address])
예제 #16
0
def create_testing_environment(user_options, job_options):
    '''
    Load the resource infromation that all modules define.
    '''
    resources = encode_as_objdict(utils.read_json_file(paths.RESOURCES_JSON))
    # Merge the two options.
    # Modify the user options with the options for the current job.
    options = namespace_as_dict(user_options)
    options.update(job_options)
    # Create an object from the dictionary.
    options = encode_as_objdict(options)

    # Get the dependencies of the current device.
    deps = resources.targets[options.device]
    # Update the deps list with user selected project.
    deps.insert(0, options.app)

    # Get the required module information. Drop all the
    # modules that are not required by the target.
    modules = encode_as_objdict(
        {name: resources.modules[name]
         for name in deps})

    # Update the path of the target application if custom
    # iotjs or jerryscript is used.
    if options.app_path:
        modules[options.app].src = options.app_path

    if options.testsuite:
        modules[options.app].paths.tests = options.testsuite

    # Add an 'app' named module that is just a reference
    # to the user defined target application.
    modules.app = modules[options.app]
    modules.app.name = options.app

    # Set the current build directory to the paths.
    resources.paths.builddir = utils.join(resources.paths.build, options.id)

    # Modify the no-build options according to the no-profile-build option.
    no_profile_build = options.no_profile_build and 'profile' in options.id
    options.no_build = options.no_build or no_profile_build

    environment = encode_as_objdict({
        'options': options,
        'modules': modules,
        'paths': resources.paths
    })

    # Resolve the symbolic values in the resources.json file.
    return encode_as_objdict(symbol_resolver.resolve(environment, environment))
예제 #17
0
    def _read_test_descriptor(self):
        '''
        Read the local skiplists.
        '''
        descriptors = {
            'iotjs': 'iotjs-test-descriptor.json',
            'jerryscript': 'jerryscript-test-descriptor.json'
        }

        descriptor_file = utils.join(paths.SKIPLIST_PATH,
                                     descriptors[self.app])
        descriptor_info = utils.read_json_file(descriptor_file)

        return descriptor_info[self.device_type]
예제 #18
0
def generate_romfs(src, dst):
    '''
    Create a romfs_img from the source directory that is
    converted to a header (byte array) file. Finally, add
    a `const` modifier to the byte array to be the data
    in the Read Only Memory.
    '''
    romfs_img = utils.join(os.curdir, 'romfs_img')

    utils.execute(os.curdir, 'genromfs', ['-f', romfs_img, '-d', src])
    utils.execute(os.curdir, 'xxd', ['-i', 'romfs_img', dst])
    utils.execute(os.curdir, 'sed',
                  ['-i', 's/unsigned/const\ unsigned/g', dst])

    os.remove(romfs_img)
예제 #19
0
def genromfs(**params):
    '''
    Create a romfs_img from the source directory that is
    converted to a header (byte array) file. Finally, add
    a `const` modifier to the byte array to be the data
    in the Read Only Memory.
    '''
    src = params['args'][0]
    dst = params['args'][1]

    romfs_img = utils.join(params['cwd'], 'romfs_img')

    utils.execute(params['cwd'], 'genromfs', ['-f', romfs_img, '-d', src])
    utils.execute(params['cwd'], 'xxd', ['-i', 'romfs_img', dst])
    utils.execute(params['cwd'], 'sed',
                  ['-i', 's/unsigned/const\ unsigned/g', dst])

    utils.remove_file(romfs_img)
예제 #20
0
    def read_modules(self):
        '''
        Collect buildable modules and their build instructions.
        '''
        modules = {}

        for name in self.env.modules:
            filename = utils.join(paths.BUILDER_MODULES_PATH,
                                  '%s.build.config' % name)
            # Skip modules that don't have configuration file (e.g. nuttx-apps).
            if not utils.exists(filename):
                continue

            build_info = utils.read_config_file(filename, self.env)
            # Check if the project is alredy built.
            if self.should_build(build_info):
                modules[name] = build_info[self.device]

        return modules
예제 #21
0
    def initialize(self):
        '''
        Flash the device.
        '''
        if self.env['info']['no_flash']:
            return

        # 1. Copy all the necessary files.
        target_app = self.env['modules']['app']
        build_path = self.env['paths']['build']

        test_src = target_app['paths']['tests']
        test_dst = utils.join(build_path, 'tests')

        # Copy all the tests into the build folder.
        utils.copy(test_src, test_dst)

        utils.copy(paths.FREYA_TESTER, build_path)

        if not self.env['info']['no_memstat']:
            # Copy Freya memory measurement files.
            utils.copy(paths.FREYA_CONFIG, build_path)

            # Resolve the iotjs-dirname macro in the Freya configuration file.
            basename = utils.basename(target_app['src'])
            sed_flags = [
                '-i',
                's/%%{iotjs-dirname}/%s/g' % basename, 'iotjs-freya.config'
            ]
            utils.execute(build_path, 'sed', sed_flags)

        # 2. Deploy the build folder to the device.
        shell_flags = 'ssh -p %s' % self.port
        rsync_flags = [
            '--rsh', shell_flags, '--recursive', '--compress', '--delete'
        ]
        # Note: slash character is required after the path.
        # In this case `rsync` copies the whole folder, not
        # the subcontents to the destination.
        src = self.env['paths']['build'] + '/'
        dst = '%s@%s:%s' % (self.user, self.ip, self.workdir)

        utils.execute('.', 'rsync', rsync_flags + [src, dst])
예제 #22
0
    def save(self):
        '''
        Save the current testresults into JSON format.
        '''
        if self.env.options.no_test:
            return

        results = {}
        # Specify a date named results file.
        filename = utils.join(self.env.paths.builddir, 'testresults.json')

        if self.env.options.coverage:
            results['coverage_info'] = self.coverage_info
            filename += '_coverage'

        else:
            results['tests'] = self.results

        # Save the results into the date named file.
        utils.write_json_file(filename, results)
예제 #23
0
def create_build_info(env):
    '''
    Write binary size and commit information into a file.
    '''
    submodules = {}

    for name, module in env.modules.iteritems():
        # Don't duplicate the application information.
        if name == 'app':
            continue

        submodules[name] = utils.last_commit_info(module['src'])

    # Merge the collected values into a result object.
    build_info = {
        'build-date': utils.current_date('%Y-%m-%dT%H.%M.%SZ'),
        'last-commit-date': submodules[env.options.app]['date'],
        'bin': calculate_section_sizes(env.paths.builddir),
        'submodules': submodules
    }

    utils.write_json_file(utils.join(env.paths.builddir, 'build.json'), build_info)