github.com/elves/elvish@v0.15.0/pkg/edit/highlight_test.go (about) 1 package edit 2 3 import ( 4 "io/ioutil" 5 "os" 6 "path/filepath" 7 "runtime" 8 "testing" 9 10 "github.com/elves/elvish/pkg/cli/term" 11 "github.com/elves/elvish/pkg/env" 12 "github.com/elves/elvish/pkg/eval" 13 "github.com/elves/elvish/pkg/eval/vars" 14 "github.com/elves/elvish/pkg/parse" 15 "github.com/elves/elvish/pkg/testutil" 16 "github.com/elves/elvish/pkg/tt" 17 ) 18 19 // High-level sanity test. 20 21 func TestHighlighter(t *testing.T) { 22 f := setup() 23 defer f.Cleanup() 24 25 feedInput(f.TTYCtrl, "put $true") 26 f.TestTTY(t, 27 "~> put $true", Styles, 28 " vvv $$$$$", term.DotHere, 29 ) 30 31 feedInput(f.TTYCtrl, "x") 32 f.TestTTY(t, 33 "~> put $truex", Styles, 34 " vvv ??????", term.DotHere, "\n", 35 "compilation error: 4-10 in [tty]: variable $truex not found", 36 ) 37 } 38 39 // Fine-grained tests against the highlighter. 40 41 func TestCheck(t *testing.T) { 42 ev := eval.NewEvaler() 43 ev.AddGlobal(eval.NsBuilder{"good": vars.FromInit(0)}.Ns()) 44 45 tt.Test(t, tt.Fn("check", check), tt.Table{ 46 tt.Args(ev, mustParse("")).Rets(noError), 47 tt.Args(ev, mustParse("echo $good")).Rets(noError), 48 // TODO: Check the range of the returned error 49 tt.Args(ev, mustParse("echo $bad")).Rets(anyError), 50 }) 51 } 52 53 type anyErrorMatcher struct{} 54 55 func (anyErrorMatcher) Match(ret tt.RetValue) bool { 56 err, _ := ret.(error) 57 return err != nil 58 } 59 60 var ( 61 noError = error(nil) 62 anyError anyErrorMatcher 63 ) 64 65 const colonInFilenameOk = runtime.GOOS != "windows" 66 67 func TestMakeHasCommand(t *testing.T) { 68 ev := eval.NewEvaler() 69 70 // Set up global functions and modules in the evaler. 71 goodFn := eval.NewGoFn("good", func() {}) 72 ev.AddGlobal(eval.NsBuilder{}. 73 AddFn("good", goodFn). 74 AddNs("a", 75 eval.NsBuilder{}. 76 AddFn("good", goodFn). 77 AddNs("b", eval.NsBuilder{}.AddFn("good", goodFn).Ns()). 78 Ns()). 79 Ns()) 80 81 // Set up environment. 82 testDir, cleanup := testutil.InTestDir() 83 defer cleanup() 84 oldPath := os.Getenv(env.PATH) 85 defer os.Setenv(env.PATH, oldPath) 86 if runtime.GOOS == "windows" { 87 oldPathExt := os.Getenv(env.PATHEXT) 88 defer os.Setenv(env.PATHEXT, oldPathExt) 89 os.Unsetenv(env.PATHEXT) // force default value 90 } 91 92 // Set up a directory in PATH. 93 os.Setenv(env.PATH, filepath.Join(testDir, "bin")) 94 mustMkdirAll("bin") 95 mustMkExecutable("bin/external") 96 mustMkExecutable("bin/@external") 97 if colonInFilenameOk { 98 mustMkExecutable("bin/ex:tern:al") 99 } 100 101 // Set up a directory not in PATH. 102 mustMkdirAll("a/b/c") 103 mustMkExecutable("a/b/c/executable") 104 105 tt.Test(t, tt.Fn("hasCommand", hasCommand), tt.Table{ 106 // Builtin special form 107 tt.Args(ev, "if").Rets(true), 108 109 // Builtin function 110 tt.Args(ev, "put").Rets(true), 111 // Explicit builtin: 112 tt.Args(ev, "builtin:put").Rets(true), 113 tt.Args(ev, "builtin:bad-builtin").Rets(false), 114 115 // User-defined function 116 tt.Args(ev, "good").Rets(true), 117 118 // Function in modules 119 tt.Args(ev, "a:good").Rets(true), 120 tt.Args(ev, "a:b:good").Rets(true), 121 tt.Args(ev, "a:bad").Rets(false), 122 tt.Args(ev, "a:b:bad").Rets(false), 123 124 // Non-searching directory and external 125 tt.Args(ev, "./a").Rets(true), 126 tt.Args(ev, "a/b").Rets(true), 127 tt.Args(ev, "a/b/c/executable").Rets(true), 128 tt.Args(ev, "./bad").Rets(false), 129 tt.Args(ev, "a/bad").Rets(false), 130 131 // External in PATH 132 tt.Args(ev, "external").Rets(true), 133 tt.Args(ev, "@external").Rets(true), 134 tt.Args(ev, "ex:tern:al").Rets(colonInFilenameOk), 135 // With explicit e: 136 tt.Args(ev, "e:external").Rets(true), 137 tt.Args(ev, "e:bad-external").Rets(false), 138 139 // Non-existent 140 tt.Args(ev, "bad").Rets(false), 141 tt.Args(ev, "a:").Rets(false), 142 }) 143 } 144 145 func mustParse(src string) parse.Tree { 146 tree, err := parse.Parse(parse.SourceForTest(src)) 147 if err != nil { 148 panic(err) 149 } 150 return tree 151 } 152 153 func mustMkdirAll(path string) { 154 err := os.MkdirAll(path, 0700) 155 if err != nil { 156 panic(err) 157 } 158 } 159 160 func mustMkExecutable(path string) { 161 if runtime.GOOS == "windows" { 162 path += ".exe" 163 } 164 err := ioutil.WriteFile(path, nil, 0700) 165 if err != nil { 166 panic(err) 167 } 168 }