main (test): add tests to tinygo test
				
					
				
			Этот коммит содержится в:
		
							родитель
							
								
									21b89ef327
								
							
						
					
					
						коммит
						d86dd642b3
					
				
					 6 изменённых файлов: 234 добавлений и 46 удалений
				
			
		
							
								
								
									
										238
									
								
								main_test.go
									
										
									
									
									
								
							
							
						
						
									
										238
									
								
								main_test.go
									
										
									
									
									
								
							|  | @ -9,12 +9,14 @@ import ( | ||||||
| 	"errors" | 	"errors" | ||||||
| 	"flag" | 	"flag" | ||||||
| 	"fmt" | 	"fmt" | ||||||
|  | 	"io" | ||||||
| 	"io/ioutil" | 	"io/ioutil" | ||||||
| 	"os" | 	"os" | ||||||
| 	"os/exec" | 	"os/exec" | ||||||
| 	"path/filepath" | 	"path/filepath" | ||||||
| 	"runtime" | 	"runtime" | ||||||
| 	"strings" | 	"strings" | ||||||
|  | 	"sync" | ||||||
| 	"testing" | 	"testing" | ||||||
| 	"time" | 	"time" | ||||||
| 
 | 
 | ||||||
|  | @ -27,7 +29,11 @@ const TESTDATA = "testdata" | ||||||
| 
 | 
 | ||||||
| var testTarget = flag.String("target", "", "override test target") | var testTarget = flag.String("target", "", "override test target") | ||||||
| 
 | 
 | ||||||
| func TestCompiler(t *testing.T) { | var sema = make(chan struct{}, runtime.NumCPU()) | ||||||
|  | 
 | ||||||
|  | func TestBuild(t *testing.T) { | ||||||
|  | 	t.Parallel() | ||||||
|  | 
 | ||||||
| 	tests := []string{ | 	tests := []string{ | ||||||
| 		"alias.go", | 		"alias.go", | ||||||
| 		"atomic.go", | 		"atomic.go", | ||||||
|  | @ -62,8 +68,6 @@ func TestCompiler(t *testing.T) { | ||||||
| 		tests = append(tests, "go1.17.go") | 		tests = append(tests, "go1.17.go") | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	sema := make(chan struct{}, runtime.NumCPU()) |  | ||||||
| 
 |  | ||||||
| 	if *testTarget != "" { | 	if *testTarget != "" { | ||||||
| 		// This makes it possible to run one specific test (instead of all), | 		// This makes it possible to run one specific test (instead of all), | ||||||
| 		// which is especially useful to quickly check whether some changes | 		// which is especially useful to quickly check whether some changes | ||||||
|  | @ -84,41 +88,29 @@ func TestCompiler(t *testing.T) { | ||||||
| 		// Test with few optimizations enabled (no inlining, etc). | 		// Test with few optimizations enabled (no inlining, etc). | ||||||
| 		t.Run("opt=1", func(t *testing.T) { | 		t.Run("opt=1", func(t *testing.T) { | ||||||
| 			t.Parallel() | 			t.Parallel() | ||||||
| 			runTestWithConfig("stdlib.go", t, compileopts.Options{ | 			opts := optionsFromTarget("", sema) | ||||||
| 				GOOS:      goenv.Get("GOOS"), | 			opts.Opt = "1" | ||||||
| 				GOARCH:    goenv.Get("GOARCH"), | 			runTestWithConfig("stdlib.go", t, opts, nil, nil) | ||||||
| 				GOARM:     goenv.Get("GOARM"), |  | ||||||
| 				Opt:       "1", |  | ||||||
| 				Semaphore: sema, |  | ||||||
| 			}, nil, nil) |  | ||||||
| 		}) | 		}) | ||||||
| 
 | 
 | ||||||
| 		// Test with only the bare minimum of optimizations enabled. | 		// Test with only the bare minimum of optimizations enabled. | ||||||
| 		// TODO: fix this for stdlib.go, which currently fails. | 		// TODO: fix this for stdlib.go, which currently fails. | ||||||
| 		t.Run("opt=0", func(t *testing.T) { | 		t.Run("opt=0", func(t *testing.T) { | ||||||
| 			t.Parallel() | 			t.Parallel() | ||||||
| 			runTestWithConfig("print.go", t, compileopts.Options{ | 			opts := optionsFromTarget("", sema) | ||||||
| 				GOOS:      goenv.Get("GOOS"), | 			opts.Opt = "0" | ||||||
| 				GOARCH:    goenv.Get("GOARCH"), | 			runTestWithConfig("print.go", t, opts, nil, nil) | ||||||
| 				GOARM:     goenv.Get("GOARM"), |  | ||||||
| 				Opt:       "0", |  | ||||||
| 				Semaphore: sema, |  | ||||||
| 			}, nil, nil) |  | ||||||
| 		}) | 		}) | ||||||
| 
 | 
 | ||||||
| 		t.Run("ldflags", func(t *testing.T) { | 		t.Run("ldflags", func(t *testing.T) { | ||||||
| 			t.Parallel() | 			t.Parallel() | ||||||
| 			runTestWithConfig("ldflags.go", t, compileopts.Options{ | 			opts := optionsFromTarget("", sema) | ||||||
| 				GOOS:   goenv.Get("GOOS"), | 			opts.GlobalValues = map[string]map[string]string{ | ||||||
| 				GOARCH: goenv.Get("GOARCH"), |  | ||||||
| 				GOARM:  goenv.Get("GOARM"), |  | ||||||
| 				GlobalValues: map[string]map[string]string{ |  | ||||||
| 				"main": { | 				"main": { | ||||||
| 					"someGlobal": "foobar", | 					"someGlobal": "foobar", | ||||||
| 				}, | 				}, | ||||||
| 				}, | 			} | ||||||
| 				Semaphore: sema, | 			runTestWithConfig("ldflags.go", t, opts, nil, nil) | ||||||
| 			}, nil, nil) |  | ||||||
| 		}) | 		}) | ||||||
| 	}) | 	}) | ||||||
| 
 | 
 | ||||||
|  | @ -211,22 +203,12 @@ func TestCompiler(t *testing.T) { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func runPlatTests(options compileopts.Options, tests []string, t *testing.T) { | func runPlatTests(options compileopts.Options, tests []string, t *testing.T) { | ||||||
| 	// Check if the emulator is installed. | 	emuCheck(t, options) | ||||||
|  | 
 | ||||||
| 	spec, err := compileopts.LoadTarget(&options) | 	spec, err := compileopts.LoadTarget(&options) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		t.Fatal("failed to load target spec:", err) | 		t.Fatal("failed to load target spec:", err) | ||||||
| 	} | 	} | ||||||
| 	if len(spec.Emulator) != 0 { |  | ||||||
| 		_, err := exec.LookPath(spec.Emulator[0]) |  | ||||||
| 		if err != nil { |  | ||||||
| 			if errors.Is(err, exec.ErrNotFound) { |  | ||||||
| 				t.Skipf("emulator not installed: %q", spec.Emulator[0]) |  | ||||||
| 			} |  | ||||||
| 
 |  | ||||||
| 			t.Errorf("searching for emulator: %v", err) |  | ||||||
| 			return |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
| 
 | 
 | ||||||
| 	for _, name := range tests { | 	for _, name := range tests { | ||||||
| 		name := name // redefine to avoid race condition | 		name := name // redefine to avoid race condition | ||||||
|  | @ -263,6 +245,25 @@ func runPlatTests(options compileopts.Options, tests []string, t *testing.T) { | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | func emuCheck(t *testing.T, options compileopts.Options) { | ||||||
|  | 	// Check if the emulator is installed. | ||||||
|  | 	spec, err := compileopts.LoadTarget(&options) | ||||||
|  | 	if err != nil { | ||||||
|  | 		t.Fatal("failed to load target spec:", err) | ||||||
|  | 	} | ||||||
|  | 	if len(spec.Emulator) != 0 { | ||||||
|  | 		_, err := exec.LookPath(spec.Emulator[0]) | ||||||
|  | 		if err != nil { | ||||||
|  | 			if errors.Is(err, exec.ErrNotFound) { | ||||||
|  | 				t.Skipf("emulator not installed: %q", spec.Emulator[0]) | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
|  | 			t.Errorf("searching for emulator: %v", err) | ||||||
|  | 			return | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
| func optionsFromTarget(target string, sema chan struct{}) compileopts.Options { | func optionsFromTarget(target string, sema chan struct{}) compileopts.Options { | ||||||
| 	return compileopts.Options{ | 	return compileopts.Options{ | ||||||
| 		// GOOS/GOARCH are only used if target == "" | 		// GOOS/GOARCH are only used if target == "" | ||||||
|  | @ -271,6 +272,9 @@ func optionsFromTarget(target string, sema chan struct{}) compileopts.Options { | ||||||
| 		GOARM:     goenv.Get("GOARM"), | 		GOARM:     goenv.Get("GOARM"), | ||||||
| 		Target:    target, | 		Target:    target, | ||||||
| 		Semaphore: sema, | 		Semaphore: sema, | ||||||
|  | 		Debug:     true, | ||||||
|  | 		VerifyIR:  true, | ||||||
|  | 		Opt:       "z", | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -283,6 +287,9 @@ func optionsFromOSARCH(osarch string, sema chan struct{}) compileopts.Options { | ||||||
| 		GOOS:      parts[0], | 		GOOS:      parts[0], | ||||||
| 		GOARCH:    parts[1], | 		GOARCH:    parts[1], | ||||||
| 		Semaphore: sema, | 		Semaphore: sema, | ||||||
|  | 		Debug:     true, | ||||||
|  | 		VerifyIR:  true, | ||||||
|  | 		Opt:       "z", | ||||||
| 	} | 	} | ||||||
| 	if options.GOARCH == "arm" { | 	if options.GOARCH == "arm" { | ||||||
| 		options.GOARM = parts[2] | 		options.GOARM = parts[2] | ||||||
|  | @ -295,13 +302,6 @@ func runTest(name string, options compileopts.Options, t *testing.T, cmdArgs, en | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func runTestWithConfig(name string, t *testing.T, options compileopts.Options, cmdArgs, environmentVars []string) { | func runTestWithConfig(name string, t *testing.T, options compileopts.Options, cmdArgs, environmentVars []string) { | ||||||
| 	// Set default config. |  | ||||||
| 	options.Debug = true |  | ||||||
| 	options.VerifyIR = true |  | ||||||
| 	if options.Opt == "" { |  | ||||||
| 		options.Opt = "z" |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	// Get the expected output for this test. | 	// Get the expected output for this test. | ||||||
| 	// Note: not using filepath.Join as it strips the path separator at the end | 	// Note: not using filepath.Join as it strips the path separator at the end | ||||||
| 	// of the path. | 	// of the path. | ||||||
|  | @ -466,6 +466,156 @@ func runTestWithConfig(name string, t *testing.T, options compileopts.Options, c | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | func TestTest(t *testing.T) { | ||||||
|  | 	t.Parallel() | ||||||
|  | 
 | ||||||
|  | 	type targ struct { | ||||||
|  | 		name string | ||||||
|  | 		opts compileopts.Options | ||||||
|  | 	} | ||||||
|  | 	targs := []targ{ | ||||||
|  | 		// Host | ||||||
|  | 		{"Host", optionsFromTarget("", sema)}, | ||||||
|  | 	} | ||||||
|  | 	if !testing.Short() { | ||||||
|  | 		if runtime.GOOS == "linux" { | ||||||
|  | 			targs = append(targs, | ||||||
|  | 				// Linux | ||||||
|  | 				targ{"X86Linux", optionsFromOSARCH("linux/386", sema)}, | ||||||
|  | 				targ{"ARMLinux", optionsFromOSARCH("linux/arm/6", sema)}, | ||||||
|  | 				targ{"ARM64Linux", optionsFromOSARCH("linux/arm64", sema)}, | ||||||
|  | 			) | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		targs = append(targs, | ||||||
|  | 			// QEMU microcontrollers | ||||||
|  | 			targ{"EmulatedCortexM3", optionsFromTarget("cortex-m-qemu", sema)}, | ||||||
|  | 			targ{"EmulatedRISCV", optionsFromTarget("riscv-qemu", sema)}, | ||||||
|  | 
 | ||||||
|  | 			// Node/Wasmtime | ||||||
|  | 			targ{"WASM", optionsFromTarget("wasm", sema)}, | ||||||
|  | 			targ{"WASI", optionsFromTarget("wasi", sema)}, | ||||||
|  | 		) | ||||||
|  | 	} | ||||||
|  | 	for _, targ := range targs { | ||||||
|  | 		targ := targ | ||||||
|  | 		t.Run(targ.name, func(t *testing.T) { | ||||||
|  | 			t.Parallel() | ||||||
|  | 
 | ||||||
|  | 			emuCheck(t, targ.opts) | ||||||
|  | 
 | ||||||
|  | 			t.Run("Pass", func(t *testing.T) { | ||||||
|  | 				t.Parallel() | ||||||
|  | 
 | ||||||
|  | 				// Test a package which builds and passes normally. | ||||||
|  | 
 | ||||||
|  | 				var wg sync.WaitGroup | ||||||
|  | 				defer wg.Wait() | ||||||
|  | 
 | ||||||
|  | 				out := ioLogger(t, &wg) | ||||||
|  | 				defer out.Close() | ||||||
|  | 
 | ||||||
|  | 				opts := targ.opts | ||||||
|  | 				passed, err := Test("github.com/tinygo-org/tinygo/tests/testing/pass", out, out, &opts, false, false, false, "", "") | ||||||
|  | 				if err != nil { | ||||||
|  | 					t.Errorf("test error: %v", err) | ||||||
|  | 				} | ||||||
|  | 				if !passed { | ||||||
|  | 					t.Error("test failed") | ||||||
|  | 				} | ||||||
|  | 			}) | ||||||
|  | 
 | ||||||
|  | 			t.Run("Fail", func(t *testing.T) { | ||||||
|  | 				t.Parallel() | ||||||
|  | 
 | ||||||
|  | 				// Test a package which builds fine but fails. | ||||||
|  | 
 | ||||||
|  | 				var wg sync.WaitGroup | ||||||
|  | 				defer wg.Wait() | ||||||
|  | 
 | ||||||
|  | 				out := ioLogger(t, &wg) | ||||||
|  | 				defer out.Close() | ||||||
|  | 
 | ||||||
|  | 				opts := targ.opts | ||||||
|  | 				passed, err := Test("github.com/tinygo-org/tinygo/tests/testing/fail", out, out, &opts, false, false, false, "", "") | ||||||
|  | 				if err != nil { | ||||||
|  | 					t.Errorf("test error: %v", err) | ||||||
|  | 				} | ||||||
|  | 				if passed { | ||||||
|  | 					t.Error("test passed") | ||||||
|  | 				} | ||||||
|  | 			}) | ||||||
|  | 
 | ||||||
|  | 			if targ.name != "Host" { | ||||||
|  | 				// Emulated tests are somewhat slow, and these do not need to be run across every platform. | ||||||
|  | 				return | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
|  | 			t.Run("Nothing", func(t *testing.T) { | ||||||
|  | 				t.Parallel() | ||||||
|  | 
 | ||||||
|  | 				// Test a package with no test files. | ||||||
|  | 
 | ||||||
|  | 				var wg sync.WaitGroup | ||||||
|  | 				defer wg.Wait() | ||||||
|  | 
 | ||||||
|  | 				out := ioLogger(t, &wg) | ||||||
|  | 				defer out.Close() | ||||||
|  | 
 | ||||||
|  | 				var output bytes.Buffer | ||||||
|  | 				opts := targ.opts | ||||||
|  | 				passed, err := Test("github.com/tinygo-org/tinygo/tests/testing/nothing", io.MultiWriter(&output, out), out, &opts, false, false, false, "", "") | ||||||
|  | 				if err != nil { | ||||||
|  | 					t.Errorf("test error: %v", err) | ||||||
|  | 				} | ||||||
|  | 				if !passed { | ||||||
|  | 					t.Error("test failed") | ||||||
|  | 				} | ||||||
|  | 				if !strings.Contains(output.String(), "[no test files]") { | ||||||
|  | 					t.Error("missing [no test files] in output") | ||||||
|  | 				} | ||||||
|  | 			}) | ||||||
|  | 
 | ||||||
|  | 			t.Run("BuildErr", func(t *testing.T) { | ||||||
|  | 				t.Parallel() | ||||||
|  | 
 | ||||||
|  | 				// Test a package which fails to build. | ||||||
|  | 
 | ||||||
|  | 				var wg sync.WaitGroup | ||||||
|  | 				defer wg.Wait() | ||||||
|  | 
 | ||||||
|  | 				out := ioLogger(t, &wg) | ||||||
|  | 				defer out.Close() | ||||||
|  | 
 | ||||||
|  | 				opts := targ.opts | ||||||
|  | 				passed, err := Test("github.com/tinygo-org/tinygo/tests/testing/builderr", out, out, &opts, false, false, false, "", "") | ||||||
|  | 				if err == nil { | ||||||
|  | 					t.Error("test did not error") | ||||||
|  | 				} | ||||||
|  | 				if passed { | ||||||
|  | 					t.Error("test passed") | ||||||
|  | 				} | ||||||
|  | 			}) | ||||||
|  | 		}) | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func ioLogger(t *testing.T, wg *sync.WaitGroup) io.WriteCloser { | ||||||
|  | 	r, w := io.Pipe() | ||||||
|  | 	wg.Add(1) | ||||||
|  | 	go func() { | ||||||
|  | 		defer wg.Done() | ||||||
|  | 		defer r.Close() | ||||||
|  | 
 | ||||||
|  | 		scanner := bufio.NewScanner(r) | ||||||
|  | 		for scanner.Scan() { | ||||||
|  | 			t.Log(scanner.Text()) | ||||||
|  | 		} | ||||||
|  | 	}() | ||||||
|  | 
 | ||||||
|  | 	return w | ||||||
|  | } | ||||||
|  | 
 | ||||||
| // This TestMain is necessary because TinyGo may also be invoked to run certain | // This TestMain is necessary because TinyGo may also be invoked to run certain | ||||||
| // LLVM tools in a separate process. Not capturing these invocations would lead | // LLVM tools in a separate process. Not capturing these invocations would lead | ||||||
| // to recursive tests. | // to recursive tests. | ||||||
|  |  | ||||||
							
								
								
									
										10
									
								
								tests/testing/builderr/builderr.go
									
										
									
									
									
										Обычный файл
									
								
							
							
						
						
									
										10
									
								
								tests/testing/builderr/builderr.go
									
										
									
									
									
										Обычный файл
									
								
							|  | @ -0,0 +1,10 @@ | ||||||
|  | package builderr | ||||||
|  | 
 | ||||||
|  | import _ "unsafe" | ||||||
|  | 
 | ||||||
|  | //go:linkname x notARealFunction | ||||||
|  | func x() | ||||||
|  | 
 | ||||||
|  | func Thing() { | ||||||
|  | 	x() | ||||||
|  | } | ||||||
							
								
								
									
										11
									
								
								tests/testing/builderr/builderr_test.go
									
										
									
									
									
										Обычный файл
									
								
							
							
						
						
									
										11
									
								
								tests/testing/builderr/builderr_test.go
									
										
									
									
									
										Обычный файл
									
								
							|  | @ -0,0 +1,11 @@ | ||||||
|  | package builderr_test | ||||||
|  | 
 | ||||||
|  | import ( | ||||||
|  | 	"testing" | ||||||
|  | 
 | ||||||
|  | 	"github.com/tinygo-org/tinygo/tests/testing/builderr" | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | func TestThing(t *testing.T) { | ||||||
|  | 	builderr.Thing() | ||||||
|  | } | ||||||
							
								
								
									
										7
									
								
								tests/testing/fail/fail_test.go
									
										
									
									
									
										Обычный файл
									
								
							
							
						
						
									
										7
									
								
								tests/testing/fail/fail_test.go
									
										
									
									
									
										Обычный файл
									
								
							|  | @ -0,0 +1,7 @@ | ||||||
|  | package fail_test | ||||||
|  | 
 | ||||||
|  | import "testing" | ||||||
|  | 
 | ||||||
|  | func TestFail(t *testing.T) { | ||||||
|  | 	t.Error("fail") | ||||||
|  | } | ||||||
							
								
								
									
										3
									
								
								tests/testing/nothing/nothing.go
									
										
									
									
									
										Обычный файл
									
								
							
							
						
						
									
										3
									
								
								tests/testing/nothing/nothing.go
									
										
									
									
									
										Обычный файл
									
								
							|  | @ -0,0 +1,3 @@ | ||||||
|  | package nothing | ||||||
|  | 
 | ||||||
|  | // This package has no tests. | ||||||
							
								
								
									
										7
									
								
								tests/testing/pass/pass_test.go
									
										
									
									
									
										Обычный файл
									
								
							
							
						
						
									
										7
									
								
								tests/testing/pass/pass_test.go
									
										
									
									
									
										Обычный файл
									
								
							|  | @ -0,0 +1,7 @@ | ||||||
|  | package pass_test | ||||||
|  | 
 | ||||||
|  | import "testing" | ||||||
|  | 
 | ||||||
|  | func TestPass(t *testing.T) { | ||||||
|  | 	// This test passes. | ||||||
|  | } | ||||||
		Загрузка…
	
	Создание таблицы
		
		Сослаться в новой задаче
	
	 Nia Waldvogel
						Nia Waldvogel