Skip to content

Commit d773b4c

Browse files
authored
cmd/testscript: make -work actually work (#125)
Turns out that we were only printing the cmd/testscript created work directory for an argument. We also need to print (and preserve) the working directory that is created by testscript itself when running the script. Combine this with a bit of light refactoring to improve readability.
1 parent 6a414f0 commit d773b4c

File tree

2 files changed

+92
-58
lines changed

2 files changed

+92
-58
lines changed

cmd/testscript/main.go

Lines changed: 89 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,13 @@ func mainerr() (retErr error) {
9999
return fmt.Errorf("cannot use -u when reading from stdin")
100100
}
101101

102+
tr := testRunner{
103+
update: *fUpdate,
104+
verbose: *fVerbose,
105+
env: envVars.vals,
106+
testWork: *fWork,
107+
}
108+
102109
dirNames := make(map[string]int)
103110
for _, filename := range files {
104111
// TODO make running files concurrent by default? If we do, note we'll need to do
@@ -118,70 +125,35 @@ func mainerr() (retErr error) {
118125
if err := os.Mkdir(runDir, 0777); err != nil {
119126
return fmt.Errorf("failed to create a run directory within %v for %v: %v", td, renderFilename(filename), err)
120127
}
121-
if err := run(runDir, filename, *fUpdate, *fVerbose, envVars.vals); err != nil {
128+
if err := tr.run(runDir, filename); err != nil {
122129
return err
123130
}
124131
}
125132

126133
return nil
127134
}
128135

129-
var (
130-
failedRun = errors.New("failed run")
131-
skipRun = errors.New("skip")
132-
)
136+
type testRunner struct {
137+
// update denotes that the source testscript archive filename should be
138+
// updated in the case of any cmp failures.
139+
update bool
133140

134-
type runner struct {
141+
// verbose indicates the running of the script should be noisy.
135142
verbose bool
136-
}
137-
138-
func (r runner) Skip(is ...interface{}) {
139-
panic(skipRun)
140-
}
141-
142-
func (r runner) Fatal(is ...interface{}) {
143-
r.Log(is...)
144-
r.FailNow()
145-
}
146-
147-
func (r runner) Parallel() {
148-
// No-op for now; we are currently only running a single script in a
149-
// testscript instance.
150-
}
151-
152-
func (r runner) Log(is ...interface{}) {
153-
fmt.Print(is...)
154-
}
155-
156-
func (r runner) FailNow() {
157-
panic(failedRun)
158-
}
159143

160-
func (r runner) Run(n string, f func(t testscript.T)) {
161-
// For now we we don't top/tail the run of a subtest. We are currently only
162-
// running a single script in a testscript instance, which means that we
163-
// will only have a single subtest.
164-
f(r)
165-
}
144+
// env is the environment that should be set on top of the base
145+
// testscript-defined minimal environment.
146+
env []string
166147

167-
func (r runner) Verbose() bool {
168-
return r.verbose
169-
}
170-
171-
// renderFilename renders filename in error messages, taking into account
172-
// the filename could be the special "-" (stdin)
173-
func renderFilename(filename string) string {
174-
if filename == "-" {
175-
return "<stdin>"
176-
}
177-
return filename
148+
// testWork indicates whether or not temporary working directory trees
149+
// should be left behind. Corresponds exactly to the
150+
// testscript.Params.TestWork field.
151+
testWork bool
178152
}
179153

180-
// run runs the testscript archive in filename within the temporary runDir.
181-
// verbose causes the output to be verbose (akin to go test -v) and update
182-
// sets the UpdateScripts parameter passed to testscript.Run such that any
183-
// updates to the archive get written back to filename
184-
func run(runDir, filename string, update bool, verbose bool, envVars []string) error {
154+
// run runs the testscript archive located at the path filename, within the
155+
// working directory runDir. filename could be "-" in the case of stdin
156+
func (tr *testRunner) run(runDir, filename string) error {
185157
var ar *txtar.Archive
186158
var err error
187159

@@ -231,7 +203,7 @@ func run(runDir, filename string, update bool, verbose bool, envVars []string) e
231203

232204
p := testscript.Params{
233205
Dir: runDir,
234-
UpdateScripts: update,
206+
UpdateScripts: tr.update,
235207
}
236208

237209
if _, err := exec.LookPath("go"); err == nil {
@@ -252,6 +224,13 @@ func run(runDir, filename string, update bool, verbose bool, envVars []string) e
252224
}
253225
}
254226

227+
if tr.testWork {
228+
addSetup(func(env *testscript.Env) error {
229+
fmt.Fprintf(os.Stderr, "temporary work directory for %s: %s\n", renderFilename(filename), env.WorkDir)
230+
return nil
231+
})
232+
}
233+
255234
if len(gomodProxy.Files) > 0 {
256235
srv, err := goproxytest.NewServer(mods, "")
257236
if err != nil {
@@ -270,9 +249,9 @@ func run(runDir, filename string, update bool, verbose bool, envVars []string) e
270249
})
271250
}
272251

273-
if len(envVars) > 0 {
252+
if len(tr.env) > 0 {
274253
addSetup(func(env *testscript.Env) error {
275-
for _, v := range envVars {
254+
for _, v := range tr.env {
276255
varName := v
277256
if i := strings.Index(v, "="); i >= 0 {
278257
varName = v[:i]
@@ -291,8 +270,8 @@ func run(runDir, filename string, update bool, verbose bool, envVars []string) e
291270
})
292271
}
293272

294-
r := runner{
295-
verbose: verbose,
273+
r := runT{
274+
verbose: tr.verbose,
296275
}
297276

298277
func() {
@@ -312,7 +291,7 @@ func run(runDir, filename string, update bool, verbose bool, envVars []string) e
312291
return fmt.Errorf("error running %v in %v\n", renderFilename(filename), runDir)
313292
}
314293

315-
if update && filename != "-" {
294+
if tr.update && filename != "-" {
316295
// Parse the (potentially) updated scriptFile as an archive, then merge
317296
// with the original archive, retaining order. Then write the archive
318297
// back to the source file
@@ -336,4 +315,57 @@ func run(runDir, filename string, update bool, verbose bool, envVars []string) e
336315
}
337316

338317
return nil
318+
319+
}
320+
321+
var (
322+
failedRun = errors.New("failed run")
323+
skipRun = errors.New("skip")
324+
)
325+
326+
// renderFilename renders filename in error messages, taking into account
327+
// the filename could be the special "-" (stdin)
328+
func renderFilename(filename string) string {
329+
if filename == "-" {
330+
return "<stdin>"
331+
}
332+
return filename
333+
}
334+
335+
// runT implements testscript.T and is used in the call to testscript.Run
336+
type runT struct {
337+
verbose bool
338+
}
339+
340+
func (r runT) Skip(is ...interface{}) {
341+
panic(skipRun)
342+
}
343+
344+
func (r runT) Fatal(is ...interface{}) {
345+
r.Log(is...)
346+
r.FailNow()
347+
}
348+
349+
func (r runT) Parallel() {
350+
// No-op for now; we are currently only running a single script in a
351+
// testscript instance.
352+
}
353+
354+
func (r runT) Log(is ...interface{}) {
355+
fmt.Print(is...)
356+
}
357+
358+
func (r runT) FailNow() {
359+
panic(failedRun)
360+
}
361+
362+
func (r runT) Run(n string, f func(t testscript.T)) {
363+
// For now we we don't top/tail the run of a subtest. We are currently only
364+
// running a single script in a testscript instance, which means that we
365+
// will only have a single subtest.
366+
f(r)
367+
}
368+
369+
func (r runT) Verbose() bool {
370+
return r.verbose
339371
}

cmd/testscript/testdata/work.txt

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,9 @@
99
unquote file.txt dir/file.txt
1010

1111
testscript -v -work file.txt dir/file.txt
12-
stderr '\Qtemporary work directory: '$WORK'\E[/\\]tmp[/\\]'
12+
stderr '^temporary work directory: \Q'$WORK'\E[/\\]tmp[/\\]'
13+
stderr '^temporary work directory for file.txt: \Q'$WORK'\E[/\\]tmp[/\\]'
14+
stderr '^temporary work directory for dir[/\\]file.txt: \Q'$WORK'\E[/\\]tmp[/\\]'
1315
expandone $WORK/tmp/testscript*/file.txt/script.txt
1416
expandone $WORK/tmp/testscript*/file.txt1/script.txt
1517

0 commit comments

Comments
 (0)