@@ -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.
339308func 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 }
0 commit comments