Esempio n. 1
0
def get_standard_metrics(capture, actions):
    analysis_props = _get_analysis_props(capture.metadata['captureDevice'])

    metrics = {}
    metrics['uniqueframes'] = videocapture.get_num_unique_frames(
        capture, threshold=analysis_props['animation_threshold'])
    metrics['fps'] = videocapture.get_fps(
        capture, threshold=analysis_props['animation_threshold'])
    metrics['checkerboard'] = videocapture.get_checkerboarding_area_duration(capture)
    if actions:
        # get the delta between the first non-sleep action being fired and
        # there being a visible change
        first_non_sleep_action = None
        for action in actions:
            if action['type'] != 'sleep':
                first_non_sleep_action = action
                break
        if first_non_sleep_action:
            framediffs = videocapture.get_framediff_sums(capture)
            for (i, framediff) in enumerate(framediffs):
                t = i/float(capture.fps)
                if first_non_sleep_action['start'] < t and \
                        framediff >= analysis_props['input_threshold']:
                    metrics['timetoresponse'] = (t - first_non_sleep_action['start'])
                    return metrics

    return metrics
Esempio n. 2
0
def get_standard_metrics(capture, actions):
    analysis_props = _get_analysis_props(capture.metadata["captureDevice"])

    metrics = {}
    if "unique_frames" in analysis_props["valid_measures"]:
        metrics["uniqueframes"] = videocapture.get_num_unique_frames(
            capture, threshold=analysis_props["animation_threshold"]
        )
    if "fps" in analysis_props["valid_measures"]:
        metrics["fps"] = videocapture.get_fps(capture, threshold=analysis_props["animation_threshold"])
    if "checkerboard" in analysis_props["valid_measures"]:
        metrics["checkerboard"] = videocapture.get_checkerboarding_area_duration(capture)
    if "overallentropy" in analysis_props["valid_measures"]:
        metrics["overallentropy"] = videocapture.get_overall_entropy(
            capture, edge_detection=analysis_props["edge_detection"]
        )

    if actions:
        # get the delta between the first non-sleep action being fired and
        # there being a visible change
        first_non_sleep_action = None
        for action in actions:
            if action["type"] != "sleep":
                first_non_sleep_action = action
                break
        if first_non_sleep_action:
            framediffs = videocapture.get_framediff_sums(capture)
            for (i, framediff) in enumerate(framediffs):
                t = i / float(capture.fps)
                if first_non_sleep_action["start"] < t and framediff >= analysis_props["input_threshold"]:
                    metrics["timetoresponse"] = t - first_non_sleep_action["start"]
                    return metrics

    return metrics
Esempio n. 3
0
 def GET(self, name):
     capture = videocapture.Capture(os.path.join(CAPTURE_DIR, name))
     percents = videocapture.get_checkerboarding_percents(capture)
     area_duration = videocapture.get_checkerboarding_area_duration(capture)
     return { "areaDuration": area_duration,
              "numCheckerboards": len(filter(lambda f: f > 0.0, percents)),
              "numFrames": capture.num_frames }
Esempio n. 4
0
def get_standard_metrics(capture, actions):
    analysis_props = _get_analysis_props(capture.metadata['captureDevice'])

    metrics = {}
    metrics['uniqueframes'] = videocapture.get_num_unique_frames(
        capture, threshold=analysis_props['animation_threshold'])
    metrics['fps'] = videocapture.get_fps(
        capture, threshold=analysis_props['animation_threshold'])
    metrics['checkerboard'] = videocapture.get_checkerboarding_area_duration(
        capture)
    if actions:
        # get the delta between the first non-sleep action being fired and
        # there being a visible change
        first_non_sleep_action = None
        for action in actions:
            if action['type'] != 'sleep':
                first_non_sleep_action = action
                break
        if first_non_sleep_action:
            framediffs = videocapture.get_framediff_sums(capture)
            for (i, framediff) in enumerate(framediffs):
                t = i / float(capture.fps)
                if first_non_sleep_action['start'] < t and \
                        framediff >= analysis_props['input_threshold']:
                    metrics['timetoresponse'] = (
                        t - first_non_sleep_action['start'])
                    return metrics

    return metrics
Esempio n. 5
0
 def GET(self, name):
     capture = videocapture.Capture(os.path.join(CAPTURE_DIR, name))
     percents = videocapture.get_checkerboarding_percents(capture)
     area_duration = videocapture.get_checkerboarding_area_duration(capture)
     return {
         "areaDuration": area_duration,
         "numCheckerboards": len(filter(lambda f: f > 0.0, percents)),
         "numFrames": capture.num_frames
     }
Esempio n. 6
0
def runtest(dm, product, appname, appinfo, testinfo, capture_name,
            outputdir, datafile, data, enable_profiling=False,
            dmtype="adb", host=None, port=None, devicetype="android"):
    capture_file = os.path.join(CAPTURE_DIR,
                                "%s-%s-%s-%s.zip" % (testinfo['key'],
                                                     appname,
                                                     appinfo.get('date'),
                                                     int(time.time())))
    if enable_profiling:
        profile_path = os.path.join('profiles', 'sps-profile-%s.zip' % time.time())
        profile_file = os.path.join(outputdir, profile_path)

    test_completed = False
    for i in range(3):
        print "Running test (try %s of 3)" % (i+1)

        # Kill any existing instances of the processes before starting
        dm.killProcess(appname)

        args = [ "runtest.py", "--name", capture_name, "--capture-file",
                 capture_file ]
        if dmtype:
            args.extend(["-m", dmtype])
        if devicetype:
            args.extend(["-d", devicetype])
        if host:
            args.extend(["--host", host])
        if port:
            args.extend(["--port", port])
        if enable_profiling:
            args.extend(["--profile-file", profile_file])
        if appname:
            args.extend(["--app-name", appname])
        retval = subprocess.call(args + [ testinfo['key'] ])
        if retval == 0:
            test_completed = True
            break
        else:
            print "Test failed, retrying..."

    if not test_completed:
        raise Exception("Failed to run test %s for %s (after 3 tries). "
                        "Aborting." % (testinfo['key'], product['name']))

    capture = videocapture.Capture(capture_file)

    # video file
    video_path = os.path.join('videos', 'video-%s.webm' % time.time())
    video_file = os.path.join(outputdir, video_path)
    open(video_file, 'w').write(capture.get_video().read())

    # need to initialize dict for product if not there already
    if not data['testdata'].get(product['name']):
        data['testdata'][product['name']] = {}

    # app date
    appdate = appinfo.get('date')

    if not data['testdata'][product['name']].get(appdate):
        data['testdata'][product['name']][appdate] = []

    datapoint = { 'uuid': uuid.uuid1().hex,
                  'video': video_path,
                  'appdate': appinfo.get('date'),
                  'buildid': appinfo.get('buildid'),
                  'revision': appinfo.get('revision') }

    if testinfo['type'] == 'startup':
        datapoint['timetostableframe'] = videocapture.get_stable_frame_time(capture)
    else:
        # standard test metrics
        datapoint['uniqueframes'] = videocapture.get_num_unique_frames(capture)
        datapoint['fps'] = videocapture.get_fps(capture)
        datapoint['checkerboard'] = videocapture.get_checkerboarding_area_duration(capture)

    if enable_profiling:
        datapoint['profile'] = profile_path

    data['testdata'][product['name']][appdate].append(datapoint)

    # Write the data to disk immediately (so we don't lose it if we fail later)
    datafile_dir = os.path.dirname(datafile)
    if not os.path.exists(datafile_dir):
        os.mkdir(datafile_dir)
    with open(datafile, 'w') as f:
        f.write(json.dumps(data))
Esempio n. 7
0
        datapoint.update({ 'baseline': True })

    if testinfo['type'] == 'startup' or testinfo['type'] == 'webstartup' or \
            testinfo['defaultMeasure'] == 'timetostableframe':
        datapoint['timetostableframe'] = videocapture.get_stable_frame_time(capture)
    else:
        # standard test metrics
        threshold = 0
        if capture_device == "pointgrey":
            # even with median filtering, pointgrey captures tend to have a
            # bunch of visual noise -- try to compensate for this by setting
            # a higher threshold for frames to be considered different
            threshold = 2000
        datapoint['uniqueframes'] = videocapture.get_num_unique_frames(capture, threshold=threshold)
        datapoint['fps'] = videocapture.get_fps(capture, threshold=threshold)
        datapoint['checkerboard'] = videocapture.get_checkerboarding_area_duration(capture)

    if enable_profiling:
        datapoint['profile'] = profile_path

    if log_http_requests:
        datapoint['httpLog'] = request_log_path

    data['testdata'][productname][appdate].append(datapoint)

    # Write the data to disk immediately (so we don't lose it if we fail later)
    datafile_dir = os.path.dirname(datafile)
    if not os.path.exists(datafile_dir):
        os.mkdir(datafile_dir)
    with open(datafile, 'w') as f:
        f.write(json.dumps(data))
Esempio n. 8
0
def run_test(device, outputdir, outputfile, test, url_params, num_runs,
             startup_test, no_capture, get_internal_checkerboard_stats,
             apk=None, appname = None, appdate = None, enable_profiling=False,
             extra_prefs="{}", dmtype="adb", devicetype="android", host=None,
             port=None):
    if apk:
        appinfo = eideticker.get_fennec_appinfo(apk)
        appname = appinfo['appname']
        print "Installing %s (version: %s, revision %s)" % (appinfo['appname'],
                                                            appinfo['version'],
                                                            appinfo['revision'])
        device.updateApp(apk)
    else:
        appinfo = None

    captures = []

    for i in range(num_runs):
        # Kill any existing instances of the processes
        device.killProcess(appname)

        # Now run the test
        curtime = int(time.time())
        capture_file = os.path.join(CAPTURE_DIR,
                                    "metric-test-%s-%s.zip" % (appname,
                                                               curtime))
        if enable_profiling:
            profile_file = os.path.join(PROFILE_DIR,
                                        "profile-%s-%s.zip" % (appname, curtime))

        args = ["runtest.py", "--url-params", url_params,
                "--extra-prefs", extra_prefs, appname, test]
        if get_internal_checkerboard_stats:
            checkerboard_logfile = tempfile.NamedTemporaryFile()
            args.extend(["--checkerboard-log-file", checkerboard_logfile.name])
        if startup_test:
            args.extend(["--startup-test"])
        if no_capture:
            args.extend(["--no-capture"])
        else:
            args.extend(["--capture-file", capture_file])
        if enable_profiling:
            args.extend(["--profile-file", profile_file])
        if dmtype:
            args.extend(["-m", dmtype])
        if devicetype:
            args.extend(["-d", devicetype])
        if host:
            args.extend(["--host", host])
        if port:
            args.extend(["--port", port])
        print args
        retval = subprocess.call(args)
        if retval != 0:
            raise Exception("Failed to run test %s for %s" % (test, appname))

        capture_result = {}
        if not no_capture:
            capture_result['file'] = capture_file

            capture = videocapture.Capture(capture_file)

            if startup_test:
                capture_result['stableframe'] = videocapture.get_stable_frame(capture)
            else:
                capture_result['uniqueframes'] = videocapture.get_num_unique_frames(capture)
                capture_result['fps'] = videocapture.get_fps(capture)
                capture_result['checkerboard'] = videocapture.get_checkerboarding_area_duration(capture)
            if outputdir:
                video_path = os.path.join('videos', 'video-%s.webm' % time.time())
                video_file = os.path.join(outputdir, video_path)
                open(video_file, 'w').write(capture.get_video().read())
                capture_result['video'] = video_path

        if enable_profiling:
            capture_result['profile'] = profile_file

        if get_internal_checkerboard_stats:
            internal_checkerboard_totals = parse_checkerboard_log(checkerboard_logfile.name)
            capture_result['internalcheckerboard'] = internal_checkerboard_totals

        captures.append(capture_result)

    appkey = appname
    if appdate:
        appkey = appdate.isoformat()
    else:
        appkey = appname

    if appinfo and appinfo.get('revision'):
        display_key = "%s (%s)" % (appkey, appinfo['revision'])
    else:
        display_key = appkey
    print "=== Results for %s ===" % display_key

    if not no_capture:
        if startup_test:
            print "  First stable frames:"
            print "  %s" % map(lambda c: c['stableframe'], captures)
            print
        else:
            print "  Number of unique frames:"
            print "  %s" % map(lambda c: c['uniqueframes'], captures)
            print

            print "  Average number of unique frames per second:"
            print "  %s" % map(lambda c: c['fps'], captures)
            print

            print "  Checkerboard area/duration (sum of percents NOT percentage):"
            print "  %s" % map(lambda c: c['checkerboard'], captures)
            print

        print "  Capture files:"
        print "  Capture files: %s" % map(lambda c: c['file'], captures)
        print

    if enable_profiling:
        print "  Profile files:"
        print "  Profile files: %s" % map(lambda c: c['profile'], captures)
        print

    if get_internal_checkerboard_stats:
        print "  Internal Checkerboard Stats (sum of percents, not percentage):"
        print "  %s" % map(lambda c: c['internalcheckerboard'], captures)
        print

    if outputfile:
        resultdict = { 'title': test, 'data': {} }
        if os.path.isfile(outputfile):
            resultdict.update(json.loads(open(outputfile).read()))

        if not resultdict['data'].get(appkey):
            resultdict['data'][appkey] = []
        resultdict['data'][appkey].extend(captures)

        with open(outputfile, 'w') as f:
            f.write(json.dumps(resultdict))
def runtest(dm,
            product,
            current_date,
            appname,
            appinfo,
            test,
            capture_name,
            outputdir,
            datafile,
            data,
            enable_profiling=False,
            dmtype="adb",
            host=None,
            port=None):
    capture_file = os.path.join(
        CAPTURE_DIR, "%s-%s-%s-%s.zip" %
        (test['name'], appname, appinfo.get('date'), int(time.time())))
    if enable_profiling:
        profile_package = os.path.join(
            CAPTURE_DIR, "profile-package-%s-%s-%s-%s.zip" %
            (test['name'], appname, appinfo.get('date'), int(time.time())))

    urlparams = test.get('urlparams', '')

    test_completed = False
    for i in range(3):
        print "Running test (try %s of 3)" % (i + 1)

        # Kill any existing instances of the processes before starting
        dm.killProcess(appname)

        args = [
            "runtest.py", "--url-params", urlparams, "--name", capture_name,
            "--capture-file", capture_file
        ]
        if test.get('startup_test'):
            args.append("--startup-test")
        if dmtype:
            args.extend(["-m", dmtype])
        if host:
            args.extend(["--host", host])
        if port:
            args.extend(["--port", port])
        if enable_profiling:
            args.extend(["--profile-file", profile_package])
        retval = subprocess.call(args + [appname, test['path']])
        if retval == 0:
            test_completed = True
            break
        else:
            print "Test failed, retrying..."

    if not test_completed:
        raise Exception("Failed to run test %s for %s (after 3 tries). "
                        "Aborting." % (test['name'], product['name']))

    capture = videocapture.Capture(capture_file)

    # video file
    video_path = os.path.join('videos', 'video-%s.webm' % time.time())
    video_file = os.path.join(outputdir, video_path)
    open(video_file, 'w').write(capture.get_video().read())

    # profile file
    if enable_profiling:
        profile_path = os.path.join('profiles',
                                    'sps-profile-%s.zip' % time.time())
        profile_file = os.path.join(outputdir, profile_path)
        symbolicated_profile_path = symbolicate_profile_package(
            profile_package, profile_path, profile_file)
        os.remove(profile_package)

    # need to initialize dict for product if not there already
    if not data[test['name']].get(product['name']):
        data[test['name']][product['name']] = {}

    if not data[test['name']][product['name']].get(current_date):
        data[test['name']][product['name']][current_date] = []

    datapoint = {
        'uuid': uuid.uuid1().hex,
        'video': video_path,
        'appdate': appinfo.get('date'),
        'buildid': appinfo.get('buildid'),
        'revision': appinfo.get('revision')
    }

    if test.get('startup_test'):
        datapoint['timetostableframe'] = videocapture.get_stable_frame_time(
            capture)
    else:
        # standard test metrics
        datapoint['uniqueframes'] = videocapture.get_num_unique_frames(capture)
        datapoint['fps'] = videocapture.get_fps(capture)
        datapoint[
            'checkerboard'] = videocapture.get_checkerboarding_area_duration(
                capture)

    if enable_profiling:
        datapoint['profile'] = symbolicated_profile_path

    data[test['name']][product['name']][current_date].append(datapoint)

    # Write the data to disk immediately (so we don't lose it if we fail later)
    with open(datafile, 'w') as f:
        f.write(json.dumps(data))
def run_test(device,
             outputdir,
             outputfile,
             test,
             url_params,
             num_runs,
             startup_test,
             no_capture,
             get_internal_checkerboard_stats,
             apk=None,
             appname=None,
             appdate=None,
             profile_file=None,
             dmtype="adb",
             host=None,
             port=None):
    if apk:
        appinfo = eideticker.get_fennec_appinfo(apk)
        appname = appinfo['appname']
        print "Installing %s (version: %s, revision %s)" % (
            appinfo['appname'], appinfo['version'], appinfo['revision'])
        device.updateApp(apk)
    else:
        appinfo = None

    captures = []

    for i in range(num_runs):
        # Kill any existing instances of the processes
        device.killProcess(appname)

        # Now run the test
        capture_file = os.path.join(
            CAPTURE_DIR, "metric-test-%s-%s.zip" % (appname, int(time.time())))
        args = ["runtest.py", "--url-params", url_params, appname, test]
        if get_internal_checkerboard_stats:
            checkerboard_logfile = tempfile.NamedTemporaryFile()
            args.extend(["--checkerboard-log-file", checkerboard_logfile.name])
        if startup_test:
            args.extend(["--startup-test"])
        if no_capture:
            args.extend(["--no-capture"])
        else:
            args.extend(["--capture-file", capture_file])
        if profile_file:
            args.extend(["--profile-file", profile_file])
        if dmtype:
            args.extend(["-m", dmtype])
        if host:
            args.extend(["--host", host])
        if port:
            args.extend(["--port", port])
        print args
        retval = subprocess.call(args)
        if retval != 0:
            raise Exception("Failed to run test %s for %s" % (test, appname))

        capture_result = {}
        if not no_capture:
            capture_result['file'] = capture_file

            capture = videocapture.Capture(capture_file)

            framediff_sums = videocapture.get_framediff_sums(capture)
            if startup_test:
                capture_result['stableframe'] = videocapture.get_stable_frame(
                    capture)
            else:
                capture_result[
                    'uniqueframes'] = videocapture.get_num_unique_frames(
                        capture)
                capture_result['fps'] = videocapture.get_fps(capture)
                capture_result[
                    'checkerboard'] = videocapture.get_checkerboarding_area_duration(
                        capture)
            if outputdir:
                video_path = os.path.join('videos',
                                          'video-%s.webm' % time.time())
                video_file = os.path.join(outputdir, video_path)
                open(video_file, 'w').write(capture.get_video().read())
                capture_result['video'] = video_path

        if get_internal_checkerboard_stats:
            internal_checkerboard_totals = parse_checkerboard_log(
                checkerboard_logfile.name)
            capture_result[
                'internalcheckerboard'] = internal_checkerboard_totals

        captures.append(capture_result)

    appkey = appname
    if appdate:
        appkey = appdate.isoformat()
    else:
        appkey = appname

    if appinfo and appinfo.get('revision'):
        display_key = "%s (%s)" % (appkey, appinfo['revision'])
    else:
        display_key = appkey
    print "=== Results for %s ===" % display_key

    if not no_capture:
        if startup_test:
            print "  First stable frames:"
            print "  %s" % map(lambda c: c['stableframe'], captures)
            print
        else:
            print "  Number of unique frames:"
            print "  %s" % map(lambda c: c['uniqueframes'], captures)
            print

            print "  Average number of unique frames per second:"
            print "  %s" % map(lambda c: c['fps'], captures)
            print

            print "  Checkerboard area/duration (sum of percents NOT percentage):"
            print "  %s" % map(lambda c: c['checkerboard'], captures)
            print

        print "  Capture files (for further reference):"
        print "  Capture files: %s" % map(lambda c: c['file'], captures)
        print

    if get_internal_checkerboard_stats:
        print "  Internal Checkerboard Stats (sum of percents, not percentage):"
        print "  %s" % map(lambda c: c['internalcheckerboard'], captures)
        print

    if outputfile:
        resultdict = {'title': test, 'data': {}}
        if os.path.isfile(outputfile):
            resultdict.update(json.loads(open(outputfile).read()))

        if not resultdict['data'].get(appkey):
            resultdict['data'][appkey] = []
        resultdict['data'][appkey].extend(captures)

        with open(outputfile, 'w') as f:
            f.write(json.dumps(resultdict))
Esempio n. 11
0
def runtest(dm, product, current_date, appinfo, test, capture_name, outputdir, datafile, data, gesture_file=None, appname=None, enable_profiling=False):
    test_completed = False
    capture_file = os.path.join(CAPTURE_DIR,
                            "%s-%s-%s-%s.zip" % (test['name'],
                                                 appname,
                                                 appinfo.get('date'),
                                                 int(time.time())))
    if product['name'] != 'b2g':
        urlparams = test.get('urlparams', '')

        call_args = ["runtest.py", "--url-params", urlparams,
                "--name", capture_name,
                "--capture-file", capture_file,
                appname, test['path']]
    else:
        call_args = ["runtest.py", "--b2g",
                "--name", capture_name,
                "--capture-file", capture_file]

        if not gesture_file:
            gesture_file = test.get('gesture_file', None)
        if gesture_file:
            call_args.extend(["--gesture-file", gesture_file])

    if enable_profiling:
        profile_package = os.path.join(CAPTURE_DIR,
                                       "profile-package-%s-%s-%s-%s.zip" % (test['name'],
                                                                            appname,
                                                                            appinfo.get('date'),
                                                                            int(time.time())))

        args.extend(["--profile-file", profile_package])

    call_args.append(test['path'])

    for i in range(3):
        print "Running test (try %s of 3)" % (i+1)

        retval = subprocess.call(call_args)
        if retval == 0:
            test_completed = True
            break
        else:
            print "Test failed, retrying..."

    if not test_completed:
        raise Exception("Failed to run test %s for %s (after 3 tries). "
                        "Aborting." % (test['name'], product['name']))


    capture = videocapture.Capture(capture_file)

    # video file
    video_path = os.path.join('videos', 'video-%s.webm' % time.time())
    video_file = os.path.join(outputdir, video_path)
    open(video_file, 'w').write(capture.get_video().read())

    #  profile file
    if enable_profiling:
        profile_path = os.path.join('profiles', 'sps-profile-%s.zip' % time.time())
        profile_file = os.path.join(outputdir, profile_path)
        symbolicated_profile_path = symbolicate_profile_package(profile_package, profile_path, profile_file)
        os.remove(profile_package)

    # frames-per-second / num unique frames
    num_unique_frames = videocapture.get_num_unique_frames(capture)
    fps = videocapture.get_fps(capture)

    # checkerboarding
    checkerboard = videocapture.get_checkerboarding_area_duration(capture)

    # need to initialize dict for product if not there already
    if not data[test['name']].get(product['name']):
        data[test['name']][product['name']] = {}

    if not data[test['name']][product['name']].get(current_date):
        data[test['name']][product['name']][current_date] = []
    datapoint = { 'fps': fps,
                  'uuid': uuid.uuid1().hex,
                  'checkerboard': checkerboard,
                  'uniqueframes': num_unique_frames,
                  'video': video_path,
                  'appdate': appinfo.get('date'),
                  'buildid': appinfo.get('buildid'),
                  'revision': appinfo.get('revision') }
    if enable_profiling:
        datapoint['profile'] = symbolicated_profile_path

    data[test['name']][product['name']][current_date].append(datapoint)

    # Write the data to disk immediately (so we don't lose it if we fail later)
    with open(datafile, 'w') as f:
        f.write(json.dumps(data))
Esempio n. 12
0
def runtest(device_prefs, capture_device, outputdir, outputfile, testname, url_params, num_runs,
             startup_test, no_capture, get_internal_checkerboard_stats,
             apk=None, appname = None, appdate = None, enable_profiling=False,
             extra_prefs={}, extra_env_vars={}):
    device = None
    if apk:
        appinfo = eideticker.get_fennec_appinfo(apk)
        appname = appinfo['appname']
        print "Installing %s (version: %s, revision %s)" % (appinfo['appname'],
                                                            appinfo['version'],
                                                            appinfo['revision'])
        device = eideticker.getDevice(**device_prefs)
        device.updateApp(apk)
    else:
        appinfo = None

    captures = []

    for i in range(num_runs):
        # Kill any existing instances of the processes (for Android)
        if device:
            device.killProcess(appname)

        # Now run the test
        curtime = int(time.time())
        capture_file = os.path.join(CAPTURE_DIR,
                                    "metric-test-%s-%s.zip" % (appname,
                                                               curtime))
        if enable_profiling:
            profile_file = os.path.join(PROFILE_DIR,
                                        "profile-%s-%s.zip" % (appname, curtime))
        else:
            profile_file = None

        if get_internal_checkerboard_stats:
            checkerboard_log_file = tempfile.NamedTemporaryFile()
        else:
            checkerboard_log_file = None

        current_date = time.strftime("%Y-%m-%d")
        capture_name = "%s - %s (taken on %s)" % (testname, appname, current_date)

        eideticker.run_test(testname, capture_device,
                            appname, capture_name, device_prefs,
                            extra_prefs=extra_prefs,
                            extra_env_vars=extra_env_vars,
                            checkerboard_log_file=checkerboard_log_file,
                            profile_file=profile_file,
                            no_capture=no_capture,
                            capture_file=capture_file)

        capture_result = {}
        if not no_capture:
            capture_result['file'] = capture_file

            capture = videocapture.Capture(capture_file)

            if startup_test:
                capture_result['stableframe'] = videocapture.get_stable_frame(capture)
            else:
                capture_result['uniqueframes'] = videocapture.get_num_unique_frames(capture)
                capture_result['fps'] = videocapture.get_fps(capture)
                capture_result['checkerboard'] = videocapture.get_checkerboarding_area_duration(capture)
            if outputdir:
                video_path = os.path.join('videos', 'video-%s.webm' % time.time())
                video_file = os.path.join(outputdir, video_path)
                open(video_file, 'w').write(capture.get_video().read())
                capture_result['video'] = video_path

        if enable_profiling:
            capture_result['profile'] = profile_file

        if get_internal_checkerboard_stats:
            internal_checkerboard_totals = parse_checkerboard_log(checkerboard_log_file.name)
            capture_result['internalcheckerboard'] = internal_checkerboard_totals

        captures.append(capture_result)

    appkey = appname
    if appdate:
        appkey = appdate.isoformat()
    else:
        appkey = appname

    if appinfo and appinfo.get('revision'):
        display_key = "%s (%s)" % (appkey, appinfo['revision'])
    else:
        display_key = appkey
    print "=== Results for %s ===" % display_key

    if not no_capture:
        if startup_test:
            print "  First stable frames:"
            print "  %s" % map(lambda c: c['stableframe'], captures)
            print
        else:
            print "  Number of unique frames:"
            print "  %s" % map(lambda c: c['uniqueframes'], captures)
            print

            print "  Average number of unique frames per second:"
            print "  %s" % map(lambda c: c['fps'], captures)
            print

            print "  Checkerboard area/duration (sum of percents NOT percentage):"
            print "  %s" % map(lambda c: c['checkerboard'], captures)
            print

        print "  Capture files:"
        print "  Capture files: %s" % map(lambda c: c['file'], captures)
        print

    if enable_profiling:
        print "  Profile files:"
        print "  Profile files: %s" % map(lambda c: c['profile'], captures)
        print

    if get_internal_checkerboard_stats:
        print "  Internal Checkerboard Stats (sum of percents, not percentage):"
        print "  %s" % map(lambda c: c['internalcheckerboard'], captures)
        print

    if outputfile:
        resultdict = { 'title': testname, 'data': {} }
        if os.path.isfile(outputfile):
            resultdict.update(json.loads(open(outputfile).read()))

        if not resultdict['data'].get(appkey):
            resultdict['data'][appkey] = []
        resultdict['data'][appkey].extend(captures)

        with open(outputfile, 'w') as f:
            f.write(json.dumps(resultdict))