def _MakeHistoryEvaluator(history_items): parse_ctx = test_lib.InitParseContext() parse_ctx.Init_Trail(parse_lib.Trail()) debug_f = util.DebugFile(sys.stdout) readline = _MockReadlineHistory(history_items) return history.Evaluator(readline, parse_ctx, debug_f)
def testCompletesAliases(self): # I put some aliases in this file. with open('testdata/completion/osh-unit.bash') as f: code_str = f.read() aliases = {} parse_ctx = test_lib.InitParseContext(aliases=aliases) parse_ctx.Init_Trail(parse_lib.Trail()) comp_lookup = completion.Lookup() cmd_ev = test_lib.EvalCode(code_str, parse_ctx, comp_lookup=comp_lookup, aliases=aliases) r = _MakeRootCompleter(parse_ctx=parse_ctx, comp_lookup=comp_lookup) # The original command m = list(r.Matches(MockApi('ls '))) self.assertEqual(['ls one ', 'ls two '], sorted(m)) # Alias for the command m = list(r.Matches(MockApi('ll '))) self.assertEqual(['ll one ', 'll two '], sorted(m)) # DOUBLE alias expansion goes back to original m = list(r.Matches(MockApi('ll_classify '))) self.assertEqual(['ll_classify one ', 'll_classify two '], sorted(m)) # Trailing space m = list(r.Matches(MockApi('ll_trailing '))) self.assertEqual(['ll_trailing one ', 'll_trailing two '], sorted(m)) # It should NOT clobber completio registered for aliases m = list(r.Matches(MockApi('ll_own_completion '))) self.assertEqual( ['ll_own_completion own ', 'll_own_completion words '], sorted(m))
def _MakeRootCompleter(parse_ctx=None, comp_lookup=None): compopt_state = completion.OptionState() comp_ui_state = comp_ui.State() comp_lookup = comp_lookup or completion.Lookup() mem = state.Mem('', [], None, []) parse_opts, exec_opts, mutable_opts = state.MakeOpts(mem, None) mem.exec_opts = exec_opts state.InitMem(mem, {}, '0.1') mutable_opts.Init() if not parse_ctx: parse_ctx = test_lib.InitParseContext(parse_opts=parse_opts) parse_ctx.Init_Trail(parse_lib.Trail()) parse_ctx.Init_OnePassParse(True) if 1: # enable for details debug_f = util.DebugFile(sys.stdout) else: debug_f = util.NullDebugFile() ev = test_lib.InitWordEvaluator(exec_opts=exec_opts) return completion.RootCompleter(ev, mem, comp_lookup, compopt_state, comp_ui_state, parse_ctx, debug_f)
def testRunsUserDefinedFunctions(self): # This is here because it's hard to test readline with the spec tests. with open('testdata/completion/osh-unit.bash') as f: code_str = f.read() parse_ctx = test_lib.InitParseContext() parse_ctx.Init_Trail(parse_lib.Trail()) comp_lookup = completion.Lookup() cmd_ev = test_lib.EvalCode(code_str, parse_ctx, comp_lookup=comp_lookup) r = _MakeRootCompleter(comp_lookup=comp_lookup) # By default, we get a space on the end. m = list(r.Matches(MockApi('mywords t'))) self.assertEqual(['mywords three ', 'mywords two '], sorted(m)) # No space m = list(r.Matches(MockApi('mywords_nospace t'))) self.assertEqual( ['mywords_nospace three', 'mywords_nospace two'], sorted(m)) # next 3 fail on darwin if not IS_DARWIN: # Filtered out two and bin m = list(r.Matches(MockApi('flagX '))) self.assertEqual(['flagX one ', 'flagX three '], sorted(m)) # Filter out everything EXCEPT two and bin m = list(r.Matches(MockApi('flagX_bang '))) self.assertEqual(['flagX_bang bin ', 'flagX_bang two '], sorted(m)) # -X with -P m = list(r.Matches(MockApi('flagX_prefix '))) self.assertEqual(['flagX_prefix __one ', 'flagX_prefix __three '], sorted(m)) # -P with plusdirs m = list(r.Matches(MockApi('prefix_plusdirs b'))) self.assertEqual( [ 'prefix_plusdirs __bin ', 'prefix_plusdirs benchmarks/', 'prefix_plusdirs bin/', 'prefix_plusdirs build/' ], sorted(m)) if not IS_DARWIN: # -X with plusdirs. We're filtering out bin/, and then it's added back by # plusdirs. The filter doesn't kill it. m = list(r.Matches(MockApi('flagX_plusdirs b'))) self.assertEqual( [ 'flagX_plusdirs benchmarks/', 'flagX_plusdirs bin/', 'flagX_plusdirs build/' ], sorted(m)) # -P with dirnames. -P is NOT respected. m = list(r.Matches(MockApi('prefix_dirnames b'))) self.assertEqual( [ 'prefix_dirnames benchmarks/', 'prefix_dirnames bin/', 'prefix_dirnames build/' ], sorted(m))
def ParseAndEval(code_str): arena = test_lib.MakeArena('<arith_parse_test.py>') parse_ctx = test_lib.InitParseContext(arena=arena) w_parser = test_lib.InitWordParser(code_str, arena=arena) # This is weird but works w_parser._Next(lex_mode_e.Arith) # Calling private method anode = w_parser.a_parser.Parse() print('node:', anode) mem = state.Mem('', [], arena, []) parse_opts, exec_opts, mutable_opts = state.MakeOpts(mem, None) mem.exec_opts = exec_opts state.InitMem(mem, {}, '0.1') splitter = split.SplitContext(mem) errfmt = ui.ErrorFormatter(arena) word_ev = word_eval.CompletionWordEvaluator(mem, exec_opts, mutable_opts, splitter, errfmt) arith_ev = sh_expr_eval.ArithEvaluator(mem, exec_opts, parse_ctx, arena) arith_ev.word_ev = word_ev return arith_ev.EvalToInt(anode)
def testNoInfiniteLoop(self): # This was ONE place where we got an infinite loop. with open('testdata/completion/return-124.bash') as f: code_str = f.read() parse_ctx = test_lib.InitParseContext() parse_ctx.Init_Trail(parse_lib.Trail()) comp_lookup = completion.Lookup() cmd_ev = test_lib.EvalCode(code_str, parse_ctx, comp_lookup=comp_lookup) r = _MakeRootCompleter(parse_ctx=parse_ctx, comp_lookup=comp_lookup) m = list(r.Matches(MockApi('bad '))) self.assertEqual([], sorted(m)) # Error: spec not changed m = list(r.Matches(MockApi('both '))) self.assertEqual([], sorted(m)) # Redefines completions m = list(r.Matches(MockApi('both2 '))) self.assertEqual(['both2 b1 ', 'both2 b2 '], sorted(m))
def setUp(self): arena = test_lib.MakeArena('<ui_test.py>') mem = state.Mem('', [], arena, []) parse_ctx = test_lib.InitParseContext() self.p = prompt.Evaluator('osh', parse_ctx, mem) # note: this has a separate 'mem' object self.p.word_ev = test_lib.InitWordEvaluator()
def setUp(self): """Done on every test.""" self.arena = alloc.Arena() self.arena.PushSource(source.Unused('')) loader = pyutil.GetResourceLoader() oil_grammar = meta.LoadOilGrammar(loader) self.parse_ctx = test_lib.InitParseContext(arena=self.arena, oil_grammar=oil_grammar) self.parse_ctx.Init_OnePassParse(True)
def _Detect(test, word_str, expected): # TODO: This function could be moved to test_lib. log('-' * 80) w = word_parse_test._assertReadWord(test, word_str) actual = word_.DetectShAssignment(w) left_token, close_token, part_offset = actual expected_left, expected_close, expected_part_offset = expected print(left_token, close_token, part_offset) print() if expected_left is None: test.assertEqual(None, left_token) else: test.assertEqual(expected_left, left_token.id) if expected_close is None: test.assertEqual(None, close_token) else: test.assertEqual(expected_left, left_token.id) test.assertEqual(expected_part_offset, part_offset) parse_ctx = test_lib.InitParseContext() if left_token and left_token.id in (Id.Lit_VarLike, Id.Lit_ArrayLhsOpen): more_env = [] preparsed = (left_token, close_token, part_offset, w) try: cmd_parse._AppendMoreEnv([preparsed], more_env) except Exception as e: log('Error: %s', e) else: log('more_env: %s', more_env) try: assign_pair = cmd_parse._MakeAssignPair(parse_ctx, preparsed) except Exception as e: log('Error: %s', e) else: log('assign_pair: %s', assign_pair)
def testMatchesOracle(self): for i, case in enumerate(bash_oracle.CASES): # generated data flags = case.get('_init_completion_flags') if flags is None: continue # This was input code_str = case['code'] assert code_str.endswith('\t') log('') log('--- Case %d: %r with flags %s', i, code_str, flags) log('') #print(case) oracle_comp_words = case['COMP_WORDS'] oracle_comp_cword = case['COMP_CWORD'] oracle_comp_line = case['COMP_LINE'] oracle_comp_point = case['COMP_POINT'] # Init completion data oracle_words = case['words'] oracle_cur = case['cur'] oracle_prev = case['prev'] oracle_cword = case['cword'] oracle_split = case['split'] # # First test some invariants on the oracle's data. # self.assertEqual(code_str[:-1], oracle_comp_line) # weird invariant that always holds. So isn't COMP_CWORD useless? self.assertEqual(int(oracle_comp_cword), len(oracle_comp_words)-1) # Another weird invariant. Note this is from the bash ORACLE, not from # our mocks. self.assertEqual(int(oracle_comp_point), len(code_str) - 1) # # Now run a piece of code that compares OSH's actual data against the # oracle. # init_code = _INIT_TEMPLATE % { 'flags': ' '.join(flags), 'command': oracle_comp_words[0] } arena = test_lib.MakeArena('<InitCompletionTest>') parse_ctx = test_lib.InitParseContext(arena=arena) mem = state.Mem('', [], arena, []) parse_opts, exec_opts, mutable_opts = state.MakeOpts(mem, None) mem.exec_opts = exec_opts mutable_opts.Init() # # Allow our code to access oracle data # state.SetGlobalArray(mem, 'ORACLE_COMP_WORDS', oracle_comp_words) state.SetGlobalString(mem, 'ORACLE_COMP_CWORD', oracle_comp_cword) state.SetGlobalString(mem, 'ORACLE_COMP_LINE', oracle_comp_line) state.SetGlobalString(mem, 'ORACLE_COMP_POINT', oracle_comp_point) state.SetGlobalArray(mem, 'ORACLE_words', oracle_words) state.SetGlobalString(mem, 'ORACLE_cur', oracle_cur) state.SetGlobalString(mem, 'ORACLE_prev', oracle_prev) state.SetGlobalString(mem, 'ORACLE_cword', oracle_cword) state.SetGlobalString(mem, 'ORACLE_split', oracle_split) comp_lookup = completion.Lookup() cmd_ev = test_lib.EvalCode(init_code, parse_ctx, comp_lookup=comp_lookup, mem=mem) r = _MakeRootCompleter(comp_lookup=comp_lookup) comp = MockApi(code_str[:-1]) m = list(r.Matches(comp)) log('matches = %s', m) # Unterminated quote in case 5. Nothing to complete. # TODO: use a label if i == 5: continue # Our test shell script records what passed in an array. val = mem.GetValue('PASSED') self.assertEqual(value_e.MaybeStrArray, val.tag, "[case %d] Expected array, got %s" % (i, val)) actually_passed = val.strs should_pass = [ 'COMP_WORDS', 'COMP_CWORD', 'COMP_LINE', 'COMP_POINT', # old API 'words', 'cur', 'prev', 'cword', 'split' # new API ] if i == 4: should_pass.remove('COMP_WORDS') should_pass.remove('COMP_CWORD') should_pass.remove('cword') should_pass.remove('words') # double quotes aren't the same for t in should_pass: self.assert_( t in actually_passed, "%r was expected to pass (case %d)" % (t, i)) log('Ran %d cases', len(bash_oracle.CASES))