def testCompletesAliases(self): # I put some aliases in this file. with open('testdata/completion/osh-unit.bash') as f: code_str = f.read() trail = parse_lib.Trail() arena = alloc.SideArena('<completion_test.py>') parse_ctx = parse_lib.ParseContext(arena, {}, trail=trail) comp_lookup = completion.Lookup() ex = test_lib.EvalCode(code_str, parse_ctx, comp_lookup=comp_lookup) 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 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 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() trail = parse_lib.Trail() arena = test_lib.MakeArena('<completion_test.py>') parse_opts = parse_lib.OilParseOptions() parse_ctx = parse_lib.ParseContext(arena, parse_opts, {}, None, trail=trail) comp_lookup = completion.Lookup() ex = 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 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 main(argv): init_code = ' echo hi >&2 ' arena = test_lib.MakeArena('<InitCompletionTest>') parse_ctx = parse_lib.ParseContext(arena, {}) mem = state.Mem('', [], {}, arena) comp_lookup = completion.Lookup() ex = test_lib.EvalCode(init_code, parse_ctx, comp_lookup=comp_lookup, mem=mem) print('hi')
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() trail = parse_lib.Trail() arena = alloc.SideArena('<completion_test.py>') parse_ctx = parse_lib.ParseContext(arena, {}, trail=trail) comp_lookup = completion.Lookup() ex = 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(['three ', 'two '], sorted(m)) # No space m = list(r.Matches(MockApi('mywords_nospace t'))) self.assertEqual(['three', 'two'], sorted(m)) # Filtered out two and bin m = list(r.Matches(MockApi('flagX '))) self.assertEqual(['one ', 'three '], sorted(m)) # Filter out everything EXCEPT two and bin m = list(r.Matches(MockApi('flagX_bang '))) self.assertEqual(['bin ', 'two '], sorted(m)) # -X with -P m = list(r.Matches(MockApi('flagX_prefix '))) self.assertEqual(['__one ', '__three '], sorted(m)) # TODO: Fix these! # -P with plusdirs m = list(r.Matches(MockApi('prefix_plusdirs b'))) self.assertEqual(['__bin ', 'benchmarks/', 'bin/', 'build/'], sorted(m)) # -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(['benchmarks/', 'bin/', 'build/'], sorted(m)) # -P with dirnames. -P is NOT respected. m = list(r.Matches(MockApi('prefix_dirnames b'))) self.assertEqual(['benchmarks/', 'bin/', 'build/'], sorted(m))
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 = parse_lib.ParseContext(arena, {}) mem = state.Mem('', [], {}, arena) # # 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() ex = 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.GetVar('PASSED') self.assertEqual(value_e.StrArray, val.tag, "Expected array, got %s" % 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))