Skip to content

Commit 9160f3f

Browse files
aykevldeadprogram
authored andcommitted
main: use shared code for both run and test subcommands
This means that we don't need duplicate code to pass parameters to wasmtime and that the following actually produces verbose output (it didn't before this commit): tinygo test -v -target=cortex-m-qemu math
1 parent 69d7ed5 commit 9160f3f

File tree

2 files changed

+70
-93
lines changed

2 files changed

+70
-93
lines changed

main.go

Lines changed: 67 additions & 92 deletions
Original file line numberDiff line numberDiff line change
@@ -200,8 +200,26 @@ func Test(pkgName string, stdout, stderr io.Writer, options *compileopts.Options
200200
return false, err
201201
}
202202

203+
// Pass test flags to the test binary.
204+
var flags []string
205+
if testVerbose {
206+
flags = append(flags, "-test.v")
207+
}
208+
if testShort {
209+
flags = append(flags, "-test.short")
210+
}
211+
if testRunRegexp != "" {
212+
flags = append(flags, "-test.run="+testRunRegexp)
213+
}
214+
if testBenchRegexp != "" {
215+
flags = append(flags, "-test.bench="+testBenchRegexp)
216+
}
217+
if testBenchTime != "" {
218+
flags = append(flags, "-test.benchtime="+testBenchTime)
219+
}
220+
203221
passed := false
204-
err = builder.Build(pkgName, outpath, config, func(result builder.BuildResult) error {
222+
err = buildAndRun(pkgName, config, os.Stdout, flags, nil, 0, func(cmd *exec.Cmd, result builder.BuildResult) error {
205223
if testCompileOnly || outpath != "" {
206224
// Write test binary to the specified file name.
207225
if outpath == "" {
@@ -217,27 +235,53 @@ func Test(pkgName string, stdout, stderr io.Writer, options *compileopts.Options
217235
return nil
218236
}
219237

238+
// Tests are always run in the package directory.
239+
cmd.Dir = result.MainDir
240+
241+
// Wasmtime needs a few extra flags to work.
242+
emulator := config.Emulator()
243+
if len(emulator) != 0 && emulator[0] == "wasmtime" {
244+
// Add directories to the module root, but skip the current working
245+
// directory which is already added by buildAndRun.
246+
dirs := dirsToModuleRoot(result.MainDir, result.ModuleRoot)
247+
var args []string
248+
for _, d := range dirs[1:] {
249+
args = append(args, "--dir="+d)
250+
}
251+
252+
// create a new temp directory just for this run, announce it to os.TempDir() via TMPDIR
253+
tmpdir, err := ioutil.TempDir("", "tinygotmp")
254+
if err != nil {
255+
return fmt.Errorf("failed to create temporary directory: %w", err)
256+
}
257+
args = append(args, "--dir="+tmpdir, "--env=TMPDIR="+tmpdir)
258+
// TODO: add option to not delete temp dir for debugging?
259+
defer os.RemoveAll(tmpdir)
260+
261+
// Insert new argments at the front of the command line argments.
262+
args = append(args, cmd.Args[1:]...)
263+
cmd.Args = append(cmd.Args[:1:1], args...)
264+
}
265+
220266
// Run the test.
221-
config.Options.Semaphore <- struct{}{}
222-
defer func() {
223-
<-config.Options.Semaphore
224-
}()
225267
start := time.Now()
226-
var err error
227-
passed, err = runPackageTest(config, stdout, stderr, result, testVerbose, testShort, testRunRegexp, testBenchRegexp, testBenchTime)
228-
if err != nil {
229-
return err
230-
}
268+
err = cmd.Run()
231269
duration := time.Since(start)
232270

233271
// Print the result.
234272
importPath := strings.TrimSuffix(result.ImportPath, ".test")
273+
passed = err == nil
235274
if passed {
236275
fmt.Fprintf(stdout, "ok \t%s\t%.3fs\n", importPath, duration.Seconds())
237276
} else {
238277
fmt.Fprintf(stdout, "FAIL\t%s\t%.3fs\n", importPath, duration.Seconds())
239278
}
240-
return nil
279+
if _, ok := err.(*exec.ExitError); ok {
280+
// Binary exited with a non-zero exit code, which means the test
281+
// failed.
282+
return nil
283+
}
284+
return err
241285
})
242286
if err, ok := err.(loader.NoTestFilesError); ok {
243287
fmt.Fprintf(stdout, "? \t%s\t[no test files]\n", err.ImportPath)
@@ -260,81 +304,6 @@ func dirsToModuleRoot(maindir, modroot string) []string {
260304
return dirs
261305
}
262306

263-
// runPackageTest runs a test binary that was previously built. The return
264-
// values are whether the test passed and any errors encountered while trying to
265-
// run the binary.
266-
func runPackageTest(config *compileopts.Config, stdout, stderr io.Writer, result builder.BuildResult, testVerbose, testShort bool, testRunRegexp string, testBenchRegexp string, testBenchTime string) (bool, error) {
267-
var cmd *exec.Cmd
268-
emulator := config.Emulator()
269-
if len(emulator) == 0 {
270-
// Run directly.
271-
var flags []string
272-
if testVerbose {
273-
flags = append(flags, "-test.v")
274-
}
275-
if testShort {
276-
flags = append(flags, "-test.short")
277-
}
278-
if testRunRegexp != "" {
279-
flags = append(flags, "-test.run="+testRunRegexp)
280-
}
281-
if testBenchRegexp != "" {
282-
flags = append(flags, "-test.bench="+testBenchRegexp)
283-
}
284-
if testBenchTime != "" {
285-
flags = append(flags, "-test.benchtime="+testBenchTime)
286-
}
287-
cmd = executeCommand(config.Options, result.Binary, flags...)
288-
} else {
289-
// Run in an emulator.
290-
args := append(emulator[1:], result.Binary)
291-
if emulator[0] == "wasmtime" {
292-
// create a new temp directory just for this run, announce it to os.TempDir() via TMPDIR
293-
tmpdir, err := ioutil.TempDir("", "tinygotmp")
294-
if err != nil {
295-
return false, &commandError{"failed to create temporary directory", "tinygotmp", err}
296-
}
297-
args = append(args, "--dir="+tmpdir, "--env=TMPDIR="+tmpdir)
298-
// TODO: add option to not delete temp dir for debugging?
299-
defer os.RemoveAll(tmpdir)
300-
301-
// allow reading from directories up to module root
302-
for _, d := range dirsToModuleRoot(result.MainDir, result.ModuleRoot) {
303-
args = append(args, "--dir="+d)
304-
}
305-
306-
// mark end of wasmtime arguments and start of program ones: --
307-
args = append(args, "--")
308-
if testVerbose {
309-
args = append(args, "-test.v")
310-
}
311-
if testShort {
312-
args = append(args, "-test.short")
313-
}
314-
if testRunRegexp != "" {
315-
args = append(args, "-test.run="+testRunRegexp)
316-
}
317-
if testBenchRegexp != "" {
318-
args = append(args, "-test.bench="+testBenchRegexp)
319-
}
320-
}
321-
cmd = executeCommand(config.Options, emulator[0], args...)
322-
}
323-
cmd.Dir = result.MainDir
324-
cmd.Stdout = stdout
325-
cmd.Stderr = stderr
326-
err := cmd.Run()
327-
if err != nil {
328-
if _, ok := err.(*exec.ExitError); ok {
329-
// Binary exited with a non-zero exit code, which means the test
330-
// failed.
331-
return false, nil
332-
}
333-
return false, &commandError{"failed to run compiled binary", result.Binary, err}
334-
}
335-
return true, nil
336-
}
337-
338307
// Flash builds and flashes the built binary to the given serial port.
339308
func Flash(pkgName, port string, options *compileopts.Options) error {
340309
config, err := builder.NewConfig(options)
@@ -715,14 +684,16 @@ func Run(pkgName string, options *compileopts.Options, cmdArgs []string) error {
715684
return err
716685
}
717686

718-
return buildAndRun(pkgName, config, os.Stdout, cmdArgs, nil, 0)
687+
return buildAndRun(pkgName, config, os.Stdout, cmdArgs, nil, 0, func(cmd *exec.Cmd, result builder.BuildResult) error {
688+
return cmd.Run()
689+
})
719690
}
720691

721692
// buildAndRun builds and runs the given program, writing output to stdout and
722693
// errors to os.Stderr. It takes care of emulators (qemu, wasmtime, etc) and
723694
// passes command line arguments and evironment variables in a way appropriate
724695
// for the given emulator.
725-
func buildAndRun(pkgName string, config *compileopts.Config, stdout io.Writer, cmdArgs, environmentVars []string, timeout time.Duration) error {
696+
func buildAndRun(pkgName string, config *compileopts.Config, stdout io.Writer, cmdArgs, environmentVars []string, timeout time.Duration, run func(cmd *exec.Cmd, result builder.BuildResult) error) error {
726697
// make sure any special vars in the emulator definition are rewritten
727698
emulator := config.Emulator()
728699

@@ -764,7 +735,11 @@ func buildAndRun(pkgName string, config *compileopts.Config, stdout io.Writer, c
764735
for _, v := range environmentVars {
765736
args = append(args, "--env", v)
766737
}
767-
args = append(args, cmdArgs...)
738+
if len(cmdArgs) != 0 {
739+
// mark end of wasmtime arguments and start of program ones: --
740+
args = append(args, "--")
741+
args = append(args, cmdArgs...)
742+
}
768743
} else {
769744
// Pass environment variables and command line parameters as usual.
770745
// This also works on qemu-aarch64 etc.
@@ -821,11 +796,11 @@ func buildAndRun(pkgName string, config *compileopts.Config, stdout io.Writer, c
821796
if config.Options.PrintCommands != nil {
822797
config.Options.PrintCommands(cmd.Path, cmd.Args...)
823798
}
824-
err := cmd.Run()
799+
err := run(cmd, result)
825800
if err != nil {
826-
if cerr := ctx.Err(); cerr == context.DeadlineExceeded {
801+
if ctx != nil && ctx.Err() == context.DeadlineExceeded {
827802
stdout.Write([]byte(fmt.Sprintf("--- timeout of %s exceeded, terminating...\n", timeout)))
828-
err = cerr
803+
err = ctx.Err()
829804
}
830805
return &commandError{"failed to run compiled binary", result.Binary, err}
831806
}

main_test.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -332,7 +332,9 @@ func runTestWithConfig(name string, t *testing.T, options compileopts.Options, c
332332

333333
// Build the test binary.
334334
stdout := &bytes.Buffer{}
335-
err = buildAndRun("./"+path, config, stdout, cmdArgs, environmentVars, time.Minute)
335+
err = buildAndRun("./"+path, config, stdout, cmdArgs, environmentVars, time.Minute, func(cmd *exec.Cmd, result builder.BuildResult) error {
336+
return cmd.Run()
337+
})
336338
if err != nil {
337339
printCompilerError(t.Log, err)
338340
t.Fail()

0 commit comments

Comments
 (0)