mirror of https://github.com/google/pebble
				
				
				
			
		
			
				
	
	
		
			334 lines
		
	
	
		
			14 KiB
		
	
	
	
		
			Python
		
	
	
	
			
		
		
	
	
			334 lines
		
	
	
		
			14 KiB
		
	
	
	
		
			Python
		
	
	
	
# FIXME: PBL-17362 Script should be build type (FW or SDK) agnostic (waf & PEP8 compliant)
 | 
						|
import bitmapgen
 | 
						|
import png2pblpng
 | 
						|
import os
 | 
						|
import re
 | 
						|
import sh
 | 
						|
import sys
 | 
						|
import waflib
 | 
						|
from waftools.pebble_test import clar
 | 
						|
 | 
						|
def remove_old_coverage_files(bld):
 | 
						|
    # Remove old .gcda files:
 | 
						|
    old_coverage_files = bld.path.get_bld().ant_glob('**/*.gcda lcov.info', remove=False)
 | 
						|
    for old_file in old_coverage_files:
 | 
						|
        os.remove(old_file.abspath())
 | 
						|
 | 
						|
def update_lcov(bld):
 | 
						|
    """ Update lcov-related files based on the results of `./waf test`"""
 | 
						|
    print "Generating code coverage information using lcov..."
 | 
						|
    lcov_version_cmd = ['lcov', '--version']
 | 
						|
    # Send stdout of checking for lcov to /dev/null to hide it; stderr will still be visible
 | 
						|
    with open(os.devnull, 'w') as devnull_fp:
 | 
						|
        ret = bld.exec_command(lcov_version_cmd, stdout=devnull_fp)
 | 
						|
    if ret != 0:
 | 
						|
        bld.fatal("Error running `lcov`. Is it installed?")
 | 
						|
    tests_path = bld.path.get_bld().abspath()
 | 
						|
    lcov_info_out_file = os.path.join(tests_path, 'lcov.info')
 | 
						|
    try:
 | 
						|
        platform_specific_lcov_args = []
 | 
						|
        if sys.platform.startswith('linux'):
 | 
						|
            platform_specific_lcov_args.extend(['--gcov-tool', 'llvm-cov'])
 | 
						|
        cmd = ['lcov', '--capture', '--directory', tests_path, '--output-file', lcov_info_out_file]
 | 
						|
        cmd += platform_specific_lcov_args
 | 
						|
        bld.cmd_and_log(cmd, quiet=waflib.Context.BOTH)
 | 
						|
        # remove unit-tests directory itself from lcov report
 | 
						|
        cmd = ['lcov', '--remove', lcov_info_out_file, 'tests/**', '-o', lcov_info_out_file]
 | 
						|
        cmd += platform_specific_lcov_args
 | 
						|
        bld.cmd_and_log(cmd, quiet=waflib.Context.BOTH)
 | 
						|
    except waflib.Errors.WafError as e:
 | 
						|
        print e.stdout, '\n', e.stderr
 | 
						|
        bld.fatal("Error running `lcov`")
 | 
						|
    if bld.options.coverage:
 | 
						|
        lcov_html_directory = os.path.join(tests_path, 'lcov-html')
 | 
						|
        genhtml_cmd = ['genhtml', lcov_info_out_file, '--output-directory', lcov_html_directory]
 | 
						|
        try:
 | 
						|
            bld.cmd_and_log(genhtml_cmd, quiet=waflib.Context.BOTH)
 | 
						|
        except waflib.Errors.WafError as e:
 | 
						|
            print e.stdout, '\n', e.stderr
 | 
						|
            bld.fatal("Error running `genhtml`")
 | 
						|
        index_html = os.path.join(lcov_html_directory, 'index.html')
 | 
						|
        print "Updated coverage report at %s" % index_html
 | 
						|
 | 
						|
def convert_png_to_pbi(task):
 | 
						|
    src_png = task.inputs[0].srcpath()
 | 
						|
    dest_pbi = task.outputs[0].srcpath()
 | 
						|
    bitdepth = None
 | 
						|
 | 
						|
    if any(word in dest_pbi for word in ['.8bit.', '~snowy', '~spalding', '~cutts', '~robert']):
 | 
						|
        img_fmt = 'color_raw'
 | 
						|
    elif any(word in dest_pbi for word in ['.1bit.', '~tintin']):
 | 
						|
        img_fmt = 'bw'
 | 
						|
    else:
 | 
						|
        img_fmt = 'color'  # raw and palettized color images
 | 
						|
        bit_suffix = re.search('(\d)bitpalette\.png', dest_pbi)
 | 
						|
        if bit_suffix:
 | 
						|
            bitdepth = int(bit_suffix.group(1))
 | 
						|
 | 
						|
    pb = bitmapgen.PebbleBitmap(src_png, bitmap_format=img_fmt, crop=False, bitdepth=bitdepth)
 | 
						|
    pb.convert_to_pbi_file(dest_pbi)
 | 
						|
 | 
						|
def convert_png_to_pblpng(task):
 | 
						|
    src_png = task.inputs[0].srcpath()
 | 
						|
    dest_png = task.outputs[0].srcpath()
 | 
						|
 | 
						|
    # we need to be able to skip the png generator for specific test pngs flagged 'raw'
 | 
						|
    # and copy over the original file
 | 
						|
    if dest_png.endswith('.raw.png'):
 | 
						|
        task.exec_command('cp -f {0} {1}'.format(task.inputs[0].abspath(), task.outputs[0].abspath()))
 | 
						|
    else:
 | 
						|
        palette_name = 'pebble64'
 | 
						|
        bitdepth = None
 | 
						|
        bit_suffix = re.search('(\d)bit(palette)?\.png', dest_png)
 | 
						|
 | 
						|
        if bit_suffix:
 | 
						|
            bitdepth = int(bit_suffix.group(1))
 | 
						|
        elif any(word in dest_png for word in ['~snowy', '~spalding', '~cutts', '~robert']):
 | 
						|
            bitdepth = 8
 | 
						|
        elif any(word in dest_png for word in ['~tintin']):
 | 
						|
            bitdepth = 1
 | 
						|
            palette_name = 'pebble2'
 | 
						|
 | 
						|
        png2pblpng.convert_png_to_pebble_png(src_png, dest_png,
 | 
						|
                                             palette_name=palette_name, bitdepth=bitdepth)
 | 
						|
 | 
						|
# Creates a job for each PNG in the test_images directory.
 | 
						|
# Each of these PNGs will be converted into a PBI in the build directory.
 | 
						|
# Also exports TEST_IMAGES_PATH to point to the location of the PBIs.
 | 
						|
def generate_test_pbis(ctx):
 | 
						|
 | 
						|
    test_image_pbis = []
 | 
						|
 | 
						|
    bitmapgen_path = ctx.path.find_node('../tools/bitmapgen.py').abspath()
 | 
						|
 | 
						|
    for png_file in ctx.path.find_node('test_images').ant_glob("*.png"):
 | 
						|
        dest_pbi = png_file.get_bld().change_ext('.pbi')
 | 
						|
 | 
						|
        # if the image contains Xbit in the name, then generate both 1bit and 8bit PBI images
 | 
						|
        if ".Xbit." in str(dest_pbi):
 | 
						|
            dest_pbi = png_file.get_bld().change_ext('.1bit.pbi', '.Xbit.png')
 | 
						|
            ctx(name='png_to_pbi', rule=convert_png_to_pbi, source=png_file, target=dest_pbi,
 | 
						|
                bmp_script=bitmapgen_path)
 | 
						|
            test_image_pbis.append(dest_pbi)
 | 
						|
 | 
						|
            dest_pbi = png_file.get_bld().change_ext('.8bit.pbi', '.Xbit.png')
 | 
						|
            ctx(name='png_to_pbi', rule=convert_png_to_pbi, source=png_file, target=dest_pbi,
 | 
						|
                bmp_script=bitmapgen_path)
 | 
						|
            test_image_pbis.append(dest_pbi)
 | 
						|
        else:
 | 
						|
            ctx(name='png_to_pbi', rule=convert_png_to_pbi, source=png_file, target=dest_pbi,
 | 
						|
                bmp_script=bitmapgen_path)
 | 
						|
            test_image_pbis.append(dest_pbi)
 | 
						|
 | 
						|
    return test_image_pbis
 | 
						|
 | 
						|
# Creates a job for select PNG in the test_images directory.
 | 
						|
# Each of these PNGs will be converted into a Pebble PNG8 in the build directory.
 | 
						|
def generate_test_pngs(ctx):
 | 
						|
 | 
						|
    test_image_pngs = []
 | 
						|
 | 
						|
    pblpng_resources_list = []
 | 
						|
    pblpng_resources_list.extend(
 | 
						|
        ctx.path.find_node('test_images').ant_glob("test_png__*.png"))
 | 
						|
 | 
						|
    for png_file in pblpng_resources_list:
 | 
						|
        dest_png = png_file.get_bld()
 | 
						|
 | 
						|
        ctx(name='png_to_pblpng', rule=convert_png_to_pblpng, source=png_file, target=dest_png)
 | 
						|
        test_image_pngs.append(dest_png)
 | 
						|
 | 
						|
    return test_image_pngs
 | 
						|
 | 
						|
def copy_test_pngs_to_build_dir(ctx):
 | 
						|
    test_image_pngs = []
 | 
						|
 | 
						|
    # copy over test specific files such as png, apng
 | 
						|
    copy_resources_list = []
 | 
						|
    copy_resources_list.extend(
 | 
						|
        ctx.path.find_node('test_images').ant_glob("test_bitblt_circular__*.png"))
 | 
						|
    copy_resources_list.extend(
 | 
						|
        ctx.path.find_node('test_images').ant_glob("test_gbitmap_sequence__*.apng"))
 | 
						|
    copy_resources_list.extend(
 | 
						|
        ctx.path.find_node('test_images').ant_glob("test_kino_reel__*.apng"))
 | 
						|
    copy_resources_list.extend(
 | 
						|
        ctx.path.find_node('test_images').ant_glob("test_graphics_draw_text_flow__*.png"))
 | 
						|
    for copy_file in copy_resources_list:
 | 
						|
        dest_file = copy_file.get_bld()
 | 
						|
        ctx(name='copy_png', rule='cp -f ${SRC} ${TGT}', source=copy_file, target=dest_file)
 | 
						|
        test_image_pngs.append(dest_file)
 | 
						|
 | 
						|
    return test_image_pngs
 | 
						|
 | 
						|
 | 
						|
def copy_pdc_files_to_build_dir(ctx):
 | 
						|
    test_image_pdc_files = []
 | 
						|
    copy_resources_list = ctx.path.find_node('test_images').ant_glob("*.pdc")
 | 
						|
    for copy_file in copy_resources_list:
 | 
						|
        dest_file = copy_file.get_bld()
 | 
						|
        ctx(name='copy_pdc', rule='cp -f ${SRC} ${TGT}', source=copy_file, target=dest_file)
 | 
						|
        test_image_pdc_files.append(dest_file)
 | 
						|
 | 
						|
    return test_image_pdc_files
 | 
						|
 | 
						|
 | 
						|
def copy_pfo_files_to_build_dir(ctx):
 | 
						|
    test_image_pfo_files = []
 | 
						|
    copy_resources_list = ctx.path.find_node('test_images').ant_glob("*.pfo")
 | 
						|
    for copy_file in copy_resources_list:
 | 
						|
        dest_file = copy_file.get_bld()
 | 
						|
        ctx(name='copy_pfo', rule='cp -f ${SRC} ${TGT}', source=copy_file, target=dest_file)
 | 
						|
        test_image_pfo_files.append(dest_file)
 | 
						|
 | 
						|
    return test_image_pfo_files
 | 
						|
 | 
						|
 | 
						|
def convert_test_pdcs(ctx):
 | 
						|
    test_image_pdc_files = []
 | 
						|
 | 
						|
    resources_list = ctx.path.find_node('test_images').ant_glob("*.svg")
 | 
						|
    resources_list.extend(ctx.path.find_node('test_images').ant_glob("*", src=False, dir=True))
 | 
						|
    import sys
 | 
						|
    sys.path.insert(0, ctx.path.parent.abspath())
 | 
						|
 | 
						|
    from tools.generate_pdcs import pdc_gen
 | 
						|
    def convert_svg_image(task):
 | 
						|
        pdc_gen.create_pdc_from_path(
 | 
						|
                    task.inputs[0].abspath(),
 | 
						|
                    task.outputs[0].abspath(),
 | 
						|
                    viewbox_size=(0, 0),
 | 
						|
                    verbose=False,
 | 
						|
                    duration=0,
 | 
						|
                    play_count=0)
 | 
						|
 | 
						|
    def convert_svg_sequence(task):
 | 
						|
        dir_name = os.path.dirname(task.inputs[0].abspath())
 | 
						|
        pdc_gen.create_pdc_from_path(
 | 
						|
                    dir_name,
 | 
						|
                    task.outputs[0].abspath(),
 | 
						|
                    viewbox_size=(0, 0),
 | 
						|
                    verbose=False,
 | 
						|
                    duration=33,
 | 
						|
                    play_count=1)
 | 
						|
 | 
						|
    for input_node in resources_list:
 | 
						|
        output_pdc = input_node.get_bld().change_ext('.pdc')
 | 
						|
 | 
						|
        test_image_pdc_files.append(output_pdc)
 | 
						|
        if os.path.isdir(input_node.abspath()):
 | 
						|
            conversion_rule = convert_svg_sequence
 | 
						|
            source_files = input_node.ant_glob("*.svg")
 | 
						|
        else:
 | 
						|
            conversion_rule = convert_svg_image
 | 
						|
            source_files = [input_node]
 | 
						|
 | 
						|
        ctx(rule=conversion_rule,
 | 
						|
            source=source_files,
 | 
						|
            target=output_pdc)
 | 
						|
 | 
						|
    return test_image_pdc_files
 | 
						|
 | 
						|
 | 
						|
def convert_pdc_to_pbi(ctx):
 | 
						|
    bitmapgen_path = ctx.path.find_node('../tools/bitmapgen.py').abspath()
 | 
						|
 | 
						|
    test_pdc_pbis = []
 | 
						|
 | 
						|
    pdc_files = ctx.path.find_node('test_images').ant_glob("test_pdc__*.pdc")
 | 
						|
    pdc2png = ctx.path.get_bld().parent.make_node('pdc2png')
 | 
						|
 | 
						|
    for pdc in pdc_files:
 | 
						|
        dest_pdc = pdc.get_bld().change_ext('.pdc.pdc')
 | 
						|
        src_png = dest_pdc.change_ext('.png')
 | 
						|
        dest_pbi = dest_pdc.change_ext('.pbi')
 | 
						|
        ctx(rule='cp ${SRC} ${TGT}', source=pdc, target=dest_pdc)
 | 
						|
        ctx(rule='${SRC[0].abspath()} ${SRC[1].abspath()}', source=[pdc2png, dest_pdc], target=src_png)
 | 
						|
        ctx(rule=convert_png_to_pbi, source=src_png, target=dest_pbi, bmp_script=bitmapgen_path)
 | 
						|
        test_pdc_pbis.append(dest_pbi)
 | 
						|
 | 
						|
    return test_pdc_pbis
 | 
						|
 | 
						|
def options(opt):
 | 
						|
    gr = opt.add_option_group('test options')
 | 
						|
    gr.add_option('-D', '--debug_test', action='store_true',
 | 
						|
        help='Execute tests within GDB. Use alongside -M.')
 | 
						|
    gr.add_option('-M', '--match', dest='regex', default=None, action='store',
 | 
						|
        help='Run regex match tests. Example: ./waf test -M "test.*resource.*"')
 | 
						|
    gr.add_option('-L', '--list_tests', dest='list_tests', action='store_true',
 | 
						|
        help='List all test names. Usually used in conjunction with -M. Example: '
 | 
						|
             './waf test -M test_animation -L')
 | 
						|
    gr.add_option('-T', '--test_name', dest='test_name', default=None, action='store',
 | 
						|
        help='Run only the given test name. Usually used in conjunction with -M. Example: '
 | 
						|
             './waf test -M test_animation -T unschedule')
 | 
						|
    gr.add_option('-C', '--coverage', dest='coverage', action='store_true', help='Generate gcov test coverage data and use lcov to generate HTML report')
 | 
						|
    gr.add_option('--show_output', action='store_true', help='show test output')
 | 
						|
    gr.add_option('--no_run', action='store_true', help='Do not run the tests, just build them')
 | 
						|
    gr.add_option('--no_images', action='store_true', help='skip generation of test images, '
 | 
						|
                  'which are only required for some tests and can slow down build times')
 | 
						|
 | 
						|
def build(bld):
 | 
						|
    if bld.options.debug_test:
 | 
						|
        if not bld.options.regex:
 | 
						|
            bld.fatal('When using --debug_test, you must also use --match to'
 | 
						|
                      ' specify the test file to debug')
 | 
						|
        bld.env.append_value('DEFINES', 'UNITTEST_DEBUG')
 | 
						|
 | 
						|
    bld.env.CFLAGS.append('-I' + bld.path.abspath() + '/../src/fw/util/time')
 | 
						|
    bld.env.CFLAGS.append('-I' + bld.path.abspath() + '/../src/include')
 | 
						|
 | 
						|
    # clang on Linux errors on true == true or false == false compile-time assertions
 | 
						|
    bld.env.CFLAGS.append('-Wno-tautological-compare')
 | 
						|
 | 
						|
    # time_t is defined in sys/types in newlib, and time.h on recent Linux
 | 
						|
    # so just force the defined type for testing time
 | 
						|
    bld.env.CFLAGS.append('-Dtime_t=__SYSCALL_SLONG_TYPE')
 | 
						|
 | 
						|
    # Many tests operate on a set of test images and require tools to process these
 | 
						|
    # images and therefore need extra defines. Set up our environment first before running any
 | 
						|
    # tests.
 | 
						|
    test_images_dest_dir = bld.path.find_node('test_images').get_bld()
 | 
						|
 | 
						|
    # Set up the fail directory, and make it. This is used to output data from the tests for
 | 
						|
    # comparison with the expected results.
 | 
						|
    fail_dir = test_images_dest_dir.parent.make_node('failed')
 | 
						|
    fail_path = fail_dir.abspath().strip()
 | 
						|
    sh.rm('-rf', fail_path)
 | 
						|
    fail_dir.mkdir()
 | 
						|
 | 
						|
    def convert_to_emscripten_fs_path_if_needed(node):
 | 
						|
        real_fs_abspath = node.abspath()
 | 
						|
        if bld.variant != 'test_rocky_emx':
 | 
						|
            return real_fs_abspath
 | 
						|
        # When transpiling unittests with Emscripten, the host machine's
 | 
						|
        # filesystem is mounted at /node_fs, so we need to translate paths.
 | 
						|
        return '/node_fs' + real_fs_abspath
 | 
						|
 | 
						|
    bld.env.test_image_defines = [
 | 
						|
        'TEST_IMAGES_PATH="%s"' % convert_to_emscripten_fs_path_if_needed(test_images_dest_dir),
 | 
						|
        'TEST_OUTPUT_PATH="%s"' % convert_to_emscripten_fs_path_if_needed(fail_dir),
 | 
						|
        'PBI2PNG_EXE="%s"' % bld.path.find_node('../tools/pbi2png.py').abspath()]
 | 
						|
 | 
						|
    # Add test_pbis or test_pngs to runtime_deps for tests that require them
 | 
						|
    if not bld.options.no_images:
 | 
						|
        bld.env.test_pbis = generate_test_pbis(bld)
 | 
						|
        bld.env.test_pngs = copy_test_pngs_to_build_dir(bld)
 | 
						|
        bld.env.test_pngs.extend(generate_test_pngs(bld))
 | 
						|
        bld.env.test_pfos = copy_pfo_files_to_build_dir(bld)
 | 
						|
        # Includes reference pdc and pbi generated from ref png
 | 
						|
        bld.env.test_pdcs = bld.env.test_pbis + convert_test_pdcs(bld) + copy_pdc_files_to_build_dir(bld)
 | 
						|
        bld.env.pdcs2png_test_files = bld.env.test_pbis + convert_pdc_to_pbi(bld)
 | 
						|
 | 
						|
    if bld.options.coverage:
 | 
						|
        bld.env.append_value('CFLAGS', '-fprofile-arcs')
 | 
						|
        bld.env.append_value('CFLAGS', '-ftest-coverage')
 | 
						|
        bld.env.append_value('LINKFLAGS', '--coverage')
 | 
						|
    test_wscript_dirs = [os.path.dirname(f.abspath()) for f in bld.path.ant_glob('**/wscript')]
 | 
						|
    for dir in test_wscript_dirs:
 | 
						|
        bld.recurse(dir)
 | 
						|
    if bld.options.coverage:
 | 
						|
        bld.add_pre_fun(remove_old_coverage_files)
 | 
						|
        bld.add_post_fun(update_lcov)
 | 
						|
 | 
						|
 | 
						|
# vim:filetype=python
 |