def run_test_file(template_wasm_config, test_file_path, output_dir, cmd_args):
    global args
    test_name = os.path.basename(test_file_path)
    k_steps = get_steps_as_kseq(test_file_path, output_dir)
    final_config = None

    if cmd_args.log_level == 'none' or cmd_args.log_level == 'per-file':
        # Flatten the list of k_steps, just run them all in one go.
        k_steps = [('full', [y for (_, x) in k_steps for y in x])]

    (symbolic_config, init_subst) = pyk.splitConfigFrom(template_wasm_config)

    for i in range(len(k_steps)):
        step_name, curr_step = k_steps[i]
        if args.verbose:
            print('Executing step %s' % step_name)
        init_subst['K_CELL'] = KSequence(curr_step)

        init_config = pyk.substitute(symbolic_config, init_subst)

        input_json = config_to_kast_term(init_config)
        krun_args = ['--term', '--debug']

        # Run: generate a new JSON as a temporary file, then read that as the new wasm state.
        if cmd_args.log_level != 'none':
            log_intermediate_state("%s_%d_%s.pre" % (test_name, i, step_name),
                                   init_config, output_dir)
        (rc, new_wasm_config,
         err) = pyk.krunJSONLegacy(WASM_definition_llvm_no_coverage_dir,
                                   input_json,
                                   krunArgs=krun_args,
                                   teeOutput=True)
        if rc != 0:
            print('output:\n%s' % new_wasm_config, file=sys.stderr)
            print(
                pyk.prettyPrintKast(new_wasm_config,
                                    WASM_symbols_llvm_no_coverage))
            raise Exception("Received error while running: " + err)

        final_config = new_wasm_config

        if cmd_args.log_level != 'none':
            log_intermediate_state("%s_%d_%s" % (test_name, i, step_name),
                                   new_wasm_config, output_dir)

        # Check if the k cell is empty
        (symbolic_config, init_subst) = pyk.splitConfigFrom(new_wasm_config)
        k_cell = init_subst['K_CELL']
        assert k_cell['node'] == 'KSequence' and k_cell[
            'arity'] == 0, "k cell not empty, contains a sequence of %d items.\nSee %s" % (
                k_cell['arity'], output_dir)

    return final_config
예제 #2
0
def extractTrace(config):
    (_, subst) = pyk.splitConfigFrom(config)
    pEvents = subst['PROCESSED_EVENTS_CELL']
    log_events = flattenList(pEvents)
    return [
        makeSolidityCall(e, succeeds) for event in log_events
        for (e, succeeds) in extractCallEvents(event)
    ]
예제 #3
0
def detect_violations(config):
    (_, configSubst) = pyk.splitConfigFrom(config)
    properties = configSubst['PROPERTIES_CELL']
    violations = []
    for (prop, value) in flattenMap(properties):
        if pyk.isKApply(value) and value['label'] == 'Violated(_)_KMCD-PROPS_ViolationFSM_ViolationFSM':
            violations.append(prop['token'])
    return violations
예제 #4
0
def extractAsserts(config):
    (_, subst) = pyk.splitConfigFrom(config)
    snapshots = subst['KMCD_SNAPSHOTS_CELL']
    [preState, postState] = flattenList(snapshots)
    stateDelta = pyk.pushDownRewrites(pyk.KRewrite(preState, postState))
    (_, subst) = pyk.splitConfigFrom(stateDelta)
    asserts = []
    for cell in subst.keys():
        if pyk.isKRewrite(subst[cell]):
            contract = cell.split('_')[0]
            contract = contract[0] + contract[1:].lower()
            field = cell.split('_')[1].lower()
            if contract == 'Vat' and field == 'line':
                field = 'Line'
            rhs = subst[cell]['rhs']
            asserts.extend(buildAsserts(contract, field, rhs))
    stateDelta = noRewriteToDots(stateDelta)
    stateDelta = pyk.collapseDots(stateDelta)
    return (printMCD(stateDelta), asserts)
예제 #5
0
def extractTrace(config):
    (_, subst) = pyk.splitConfigFrom(config)
    pEvents = subst['PROCESSED_EVENTS_CELL']
    log_events = flattenList(pEvents)
    call_events = []
    last_event = None
    for event in log_events:
        if pyk.isKApply(event) and event[
                'label'] == 'Measure(_,_,_,_,_,_,_,_,_,_,_)_KMCD-PROPS_Measure_Rat_Map_Rat_Rat_Rat_Rat_Rat_Rat_Map_Rat_Map':
            if last_event is not None:
                call_events.extend(extractCallEvent(last_event))
        last_event = event
    return call_events
예제 #6
0
def detect_violations(config):
    (_, configSubst) = pyk.splitConfigFrom(config)
    properties = configSubst['PROPERTIES_CELL']
    violations = []

    def _gatherViolations(fsmMap):
        if pyk.isKApply(fsmMap) and fsmMap['label'] == '_|->_':
            if fsmMap['args'][1] == pyk.KConstant(
                    'Violated_KMCD-PROPS_ViolationFSM'):
                violations.append(fsmMap['args'][0]['token'])
        return fsmMap

    pyk.traverseTopDown(properties, _gatherViolations)
    return violations
예제 #7
0
def get_coverage_data(term, cell_name, filter_func, collect_data_func):

    # TODO: Use traverseBottomUp.
    def filter_term(filter_func, term):
        res = []
        if filter_func(term):
            res.append(term)
        if 'args' in term:
            for arg in term['args']:
                res.extend(filter_term(filter_func, arg))
        return res

    cells = pyk.splitConfigFrom(term)[1]
    cov_cell = cells[cell_name]
    cov_data = filter_term(filter_func, cov_cell)
    result = [collect_data_func(entry) for entry in cov_data]
    return result
예제 #8
0
def get_init_config(init_term):
    kast_json = {'format': 'KAST', 'version': 1, 'term': init_term}
    (_, init_config, _) = krun(kast_json, *randomSeedArgs())
    return pyk.splitConfigFrom(init_config)
예제 #9
0
def noRewriteToDots(config):
    (cfg, subst) = pyk.splitConfigFrom(config)
    for cell in subst.keys():
        if not pyk.isKRewrite(subst[cell]):
            subst[cell] = pyk.ktokenDots
    return pyk.substitute(cfg, subst)
예제 #10
0
def get_init_config(init_term, debug = False):
    init_config = kmcdJSON(init_term, backend = 'llvm', debug = debug, kastArgs = [ '--sort', 'EthereumSimulation' ])
    return pyk.splitConfigFrom(init_config)
예제 #11
0
def get_init_config():
    init_term = { 'format': 'KAST', 'version': 1, 'term': KConstant('.List{"___WASM_Stmts_Stmt_Stmts"}_Stmts') }
    (_, simple_config, _) = krun(init_term)
    return pyk.splitConfigFrom(simple_config)
예제 #12
0
def insertDots(k):
    (config, subst) = pyk.splitConfigFrom(k)
    if pyk.isKSequence(subst['INSTRS_CELL']) and pyk.isKVariable(subst['INSTRS_CELL']['items'][-1]) and subst['INSTRS_CELL']['items'][-1]['name'].startswith('DotVar'):
        subst['INSTRS_CELL'] = KApply('#dotsRight', [KSequence(subst['INSTRS_CELL']['items'][0:-1])])
    return pyk.substitute(config, subst)
def get_init_config(backend):
    init_term = {'format': 'KAST', 'version': 1, 'term': KConstant('noop')}
    (_, simple_config, _) = krunJson(init_term, backend)
    return pyk.splitConfigFrom(simple_config)
def run_tests():
    global args
    testArgs = argparse.ArgumentParser(description='')
    testArgs.add_argument('files', metavar='N', type=str, nargs='+', help='')
    testArgs.add_argument('--coverage',
                          action='store_true',
                          help='Display test coverage data.')
    testArgs.add_argument('--log-level',
                          choices=['none', 'per-file', 'per-step'],
                          default='per-file')
    testArgs.add_argument('--verbose', action='store_true', help='')
    args = testArgs.parse_args()
    tests = args.files

    per_test_coverage = []

    template_wasm_config = pyk.readKastTerm('src/elrond-runtime.loaded.json')
    cells = pyk.splitConfigFrom(template_wasm_config)[1]
    assert cells['K_CELL']['arity'] == 0

    coverage = cov.Coverage()
    for test in tests:
        if args.verbose:
            print("Running test %s" % test)
        tmpdir = tempfile.mkdtemp(prefix="mandos_")
        if args.verbose:
            print("Intermediate test outputs stored in:\n%s" % tmpdir)

        initial_name = "0000_initial_config"
        with open('%s/%s' % (tmpdir, initial_name), 'w') as f:
            f.write(json.dumps(config_to_kast_term(template_wasm_config)))

        result_wasm_config = run_test_file(template_wasm_config, test, tmpdir,
                                           args)

        if args.coverage:
            end_config = result_wasm_config  #pyk.readKastTerm(os.path.join(tmpdir, test_name))

            collect_data_func = lambda entry: (int(entry['args'][0]['token']),
                                               int(entry['args'][1]['token']))

            func_cov_filter_func = lambda term: 'label' in term and term[
                'label'] == 'fcd'
            func_cov = cov.get_coverage_data(end_config, 'COVEREDFUNCS_CELL',
                                             func_cov_filter_func,
                                             collect_data_func)

            block_cov_filter_func = lambda term: 'label' in term and term[
                'label'] == 'blockUid'
            block_cov = cov.get_coverage_data(end_config, 'COVEREDBLOCK_CELL',
                                              block_cov_filter_func,
                                              collect_data_func)

            mods = cov.get_module_filename_map(result_wasm_config)

            cov_data = {
                'func_cov': func_cov,
                'block_cov': block_cov,
                'idx2file': mods
            }

            coverage.add_coverage(cov_data, unnamed='import')

        if args.verbose:
            print('See %s' % tmpdir)
            print()

    if args.coverage:
        text_modules = cov.insert_coverage_on_text_module(
            coverage, imports_mod_name='import')
        for module in text_modules:
            for line in module.splitlines():
                print(line.decode('utf8'))