1
2
3
4
5 package pipeline
6
7 import (
8 "bufio"
9 "bytes"
10 "encoding/json"
11 "flag"
12 "fmt"
13 "go/build"
14 "os"
15 "os/exec"
16 "path"
17 "path/filepath"
18 "reflect"
19 "runtime"
20 "strings"
21 "testing"
22
23 "golang.org/x/text/language"
24 )
25
26 var genFiles = flag.Bool("gen", false, "generate output files instead of comparing")
27
28
29 var setHelper = func(t *testing.T) {}
30
31 func TestFullCycle(t *testing.T) {
32 if runtime.GOOS == "android" {
33 t.Skip("cannot load outside packages on android")
34 }
35 if b := os.Getenv("GO_BUILDER_NAME"); b == "plan9-arm" {
36 t.Skipf("skipping: test frequently times out on %s", b)
37 }
38 if _, err := exec.LookPath("go"); err != nil {
39 t.Skipf("skipping because 'go' command is unavailable: %v", err)
40 }
41
42 GOPATH, err := os.MkdirTemp("", "pipeline_test")
43 if err != nil {
44 t.Fatal(err)
45 }
46 defer os.RemoveAll(GOPATH)
47 testdata := filepath.Join(GOPATH, "src", "testdata")
48
49
50 copyTestdata(t, testdata)
51 initTestdataModule(t, testdata)
52
53
54
55 defer func(prev string) { build.Default.GOPATH = prev }(build.Default.GOPATH)
56 build.Default.GOPATH = GOPATH + string(filepath.ListSeparator) + build.Default.GOPATH
57 if wd := reflect.ValueOf(&build.Default).Elem().FieldByName("WorkingDir"); wd.IsValid() {
58 defer func(prev string) { wd.SetString(prev) }(wd.String())
59 wd.SetString(testdata)
60 }
61
62
63
64
65 wd, _ := os.Getwd()
66 defer os.Chdir(wd)
67
68 dirs, err := os.ReadDir(testdata)
69 if err != nil {
70 t.Fatal(err)
71 }
72 for _, f := range dirs {
73 if !f.IsDir() {
74 continue
75 }
76 t.Run(f.Name(), func(t *testing.T) {
77 chk := func(t *testing.T, err error) {
78 setHelper(t)
79 if err != nil {
80 t.Fatal(err)
81 }
82 }
83 dir := filepath.Join(testdata, f.Name())
84 pkgPath := "testdata/" + f.Name()
85 config := Config{
86 SourceLanguage: language.AmericanEnglish,
87 Packages: []string{pkgPath},
88 Dir: filepath.Join(dir, "locales"),
89 GenFile: "catalog_gen.go",
90 GenPackage: pkgPath,
91 }
92
93 os.Chdir(dir)
94
95
96 s, err := Extract(&config)
97 chk(t, err)
98 chk(t, s.Import())
99 chk(t, s.Merge())
100
101
102
103
104 chk(t, s.Export())
105 chk(t, s.Generate())
106
107 os.Chdir(wd)
108
109 writeJSON(t, filepath.Join(dir, "extracted.gotext.json"), s.Extracted)
110 checkOutput(t, dir, f.Name())
111 })
112 }
113 }
114
115 func copyTestdata(t *testing.T, dst string) {
116 err := filepath.Walk("testdata", func(p string, f os.FileInfo, err error) error {
117 if p == "testdata" || strings.HasSuffix(p, ".want") {
118 return nil
119 }
120
121 rel := strings.TrimPrefix(p, "testdata"+string(filepath.Separator))
122 if f.IsDir() {
123 return os.MkdirAll(filepath.Join(dst, rel), 0755)
124 }
125
126 data, err := os.ReadFile(p)
127 if err != nil {
128 return err
129 }
130 return os.WriteFile(filepath.Join(dst, rel), data, 0644)
131 })
132 if err != nil {
133 t.Fatal(err)
134 }
135 }
136
137 func initTestdataModule(t *testing.T, dst string) {
138 xTextDir, err := filepath.Abs("../..")
139 if err != nil {
140 t.Fatal(err)
141 }
142
143 goMod := fmt.Sprintf(`module testdata
144
145 replace golang.org/x/text => %s
146 `, xTextDir)
147 if err := os.WriteFile(filepath.Join(dst, "go.mod"), []byte(goMod), 0644); err != nil {
148 t.Fatal(err)
149 }
150
151
152
153 data, err := os.ReadFile(filepath.Join(xTextDir, "go.sum"))
154 if err != nil {
155 t.Fatal(err)
156 }
157 if err := os.WriteFile(filepath.Join(dst, "go.sum"), data, 0644); err != nil {
158 t.Fatal(err)
159 }
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175 getCmd := exec.Command("go", "get", "-d", "./...")
176 getCmd.Dir = dst
177 getCmd.Env = append(os.Environ(), "PWD="+dst, "GOPROXY=off", "GOCACHE=off")
178 if out, err := getCmd.CombinedOutput(); err != nil {
179 t.Logf("%s", out)
180 t.Fatal(err)
181 }
182 }
183
184 func checkOutput(t *testing.T, gen string, testdataDir string) {
185 err := filepath.Walk(gen, func(gotFile string, f os.FileInfo, err error) error {
186 if f.IsDir() {
187 return nil
188 }
189 rel := strings.TrimPrefix(gotFile, gen+string(filepath.Separator))
190
191 wantFile := filepath.Join("testdata", testdataDir, rel+".want")
192 if _, err := os.Stat(wantFile); os.IsNotExist(err) {
193 return nil
194 }
195
196 got, err := os.ReadFile(gotFile)
197 if err != nil {
198 t.Errorf("failed to read %q", gotFile)
199 return nil
200 }
201 if *genFiles {
202 if err := os.WriteFile(wantFile, got, 0644); err != nil {
203 t.Fatal(err)
204 }
205 }
206 want, err := os.ReadFile(wantFile)
207 if err != nil {
208 t.Errorf("failed to read %q", wantFile)
209 } else {
210 scanGot := bufio.NewScanner(bytes.NewReader(got))
211 scanWant := bufio.NewScanner(bytes.NewReader(want))
212 line := 0
213 clean := func(s string) string {
214 if i := strings.LastIndex(s, "//"); i != -1 {
215 s = s[:i]
216 }
217 return path.Clean(filepath.ToSlash(s))
218 }
219 for scanGot.Scan() && scanWant.Scan() {
220 got := clean(scanGot.Text())
221 want := clean(scanWant.Text())
222 if got != want {
223 t.Errorf("file %q differs from .want file at line %d:\n\t%s\n\t%s", gotFile, line, got, want)
224 break
225 }
226 line++
227 }
228 if scanGot.Scan() || scanWant.Scan() {
229 t.Errorf("file %q differs from .want file at line %d.", gotFile, line)
230 }
231 }
232 return nil
233 })
234 if err != nil {
235 t.Fatal(err)
236 }
237 }
238
239 func writeJSON(t *testing.T, path string, x interface{}) {
240 data, err := json.MarshalIndent(x, "", " ")
241 if err != nil {
242 t.Fatal(err)
243 }
244 if err := os.WriteFile(path, data, 0644); err != nil {
245 t.Fatal(err)
246 }
247 }
248
View as plain text