github.com/jmigpin/editor@v1.6.0/core/godebug/scripts_test.go (about) 1 package godebug 2 3 import ( 4 "bytes" 5 "context" 6 "fmt" 7 "go/parser" 8 "go/token" 9 "log" 10 "os" 11 "path/filepath" 12 "strings" 13 "sync" 14 "testing" 15 16 "github.com/jmigpin/editor/core/godebug/debug" 17 "github.com/jmigpin/editor/util/flagutil" 18 "github.com/jmigpin/editor/util/pathutil" 19 "github.com/jmigpin/editor/util/testutil" 20 "golang.org/x/tools/txtar" 21 ) 22 23 func TestScripts(t *testing.T) { 24 scr := testutil.NewScript(os.Args) 25 26 // uncomment to access work dir 27 //scr.Work = true 28 29 scr.ScriptsDir = "testdata" 30 scr.Cmds = []*testutil.ScriptCmd{ 31 &testutil.ScriptCmd{"godebugtester", godebugTester}, 32 } 33 scr.Run(t) 34 } 35 func godebugTester(t *testing.T, args []string) error { 36 log.SetFlags(0) 37 log.SetPrefix("godebugtester: ") 38 39 args = args[1:] 40 41 cmd := NewCmd() 42 43 dir, _ := os.Getwd() 44 cmd.Dir = dir 45 46 ctx := context.Background() 47 done, err := cmd.Start(ctx, args) 48 if err != nil { 49 return err 50 } 51 if done { // ex: "build", "-help" 52 return nil 53 } 54 55 wg := sync.WaitGroup{} 56 wg.Add(1) 57 go func() { 58 defer wg.Done() 59 // util func 60 add := func(s string) { 61 fmt.Printf("recv: %v\n", s) 62 } 63 for msg := range cmd.Messages() { 64 switch mt := msg.(type) { 65 case *debug.LineMsg: 66 add(StringifyItem(mt.Item)) 67 case []*debug.LineMsg: 68 for _, m := range mt { 69 add(StringifyItem(m.Item)) 70 } 71 default: 72 add(fmt.Sprintf("(%T)%v", msg, msg)) 73 } 74 } 75 }() 76 77 err = cmd.Wait() 78 wg.Wait() 79 return err 80 } 81 82 //---------- 83 //---------- 84 //---------- 85 86 func TestAnnotator(t *testing.T) { 87 testsFilename := "testdata/annotator/annotator_in_out.txt" 88 ar, err := txtar.ParseFile(testsFilename) 89 if err != nil { 90 t.Fatal() 91 } 92 93 // map files 94 m := map[string]txtar.File{} 95 for _, file := range ar.Files { 96 m[file.Name] = file 97 } 98 99 countLines := func(b []byte) int { 100 return bytes.Count(b, []byte("\n")) 101 } 102 103 line := countLines(ar.Comment) + 1 // start at line 1 104 nextLines := 0 105 for iar, file := range ar.Files { 106 line += nextLines 107 nextLines = countLines(file.Data) + 1 // add name line 108 109 // only start a test with a ".in" ext 110 if !strings.HasSuffix(file.Name, ".in") { 111 continue 112 } 113 // find ".out" 114 outName := pathutil.ReplaceExt(file.Name, ".out") 115 file2, ok := m[outName] 116 if !ok { 117 t.Logf("warning: missing *.out for %v", file.Name) 118 continue 119 } 120 121 name := filepath.Base(file.Name) 122 ok2 := t.Run(name, func(t2 *testing.T) { 123 if err := testAnnotator2(t2, name, file.Data, file2.Data, testsFilename, line, ar, iar+1); err != nil { 124 t2.Fatal(err) 125 } 126 }) 127 if !ok2 { 128 break // stop on first failed test 129 } 130 } 131 } 132 func testAnnotator2(t *testing.T, name string, in, out []byte, filename string, line int, ar *txtar.Archive, iarOut int) error { 133 t.Logf("name: %v\n", name) 134 135 fset := token.NewFileSet() 136 137 // parse input ast 138 mode := parser.ParseComments 139 astFile, err := parser.ParseFile(fset, "a.go", in, mode) 140 if err != nil { 141 return err 142 } 143 144 // annotate 145 ann := NewAnnotator(fset) 146 ann.simpleTestMode = true 147 ann.debugPkgName = "Σ" // expected by tests 148 ann.debugVarPrefix = "Σ" // expected by tests 149 150 _, _, _ = testutil.CollectLog(t, func() error { 151 // TODO: types and other? anntype? 152 ann.AnnotateAstFile(astFile) 153 return nil 154 }) 155 156 // output result to string for comparison 157 res := ann.sprintNode(astFile) 158 //_ := parseutil.TrimLineSpaces(res) // old way of comparing 159 160 fail := res != string(out) 161 162 overwrite := false 163 if !overwrite { 164 // use after flag "--": 165 // ex: go test -run=Annotator -- -overwriteoutput=TestAnnotator1.in 166 v, ok := flagutil.GetFlagString(os.Args, "owout") 167 overwrite = ok && v == name 168 } 169 if !overwrite { 170 v := flagutil.GetFlagBool(os.Args, "owoutFirstFail") 171 overwrite = v && fail 172 } 173 continueOnOverwrite := false 174 if !overwrite { 175 v := flagutil.GetFlagBool(os.Args, "owoutAllFail") 176 overwrite = v && fail 177 if overwrite { 178 continueOnOverwrite = true 179 } 180 } 181 if overwrite { 182 fmt.Printf("overwriting output for test: %v\n", name) 183 ar.Files[iarOut].Data = []byte(res) 184 b := txtar.Format(ar) 185 //fmt.Println(string(b)) // DEBUG 186 if err := os.WriteFile(filename, b, 0o644); err != nil { 187 return err 188 } 189 if continueOnOverwrite { 190 return nil 191 } 192 return fmt.Errorf("tests file overwriten") 193 } 194 195 if fail { 196 location := fmt.Sprintf("%s:%d", filename, line) 197 err := fmt.Errorf(""+ //"\n"+ 198 "%s\n"+ 199 "-- input --\n%s"+ // has ending newline (go fmt) 200 "-- result --\n%s"+ // has ending newline (go fmt) 201 "-- expected --\n%s", // has ending newline (go fmt) 202 location, in, res, out) 203 return err 204 } 205 return nil 206 }