родитель
							
								
									a3d1f1a514
								
							
						
					
					
						коммит
						208e1719ad
					
				
					 9 изменённых файлов: 288 добавлений и 13 удалений
				
			
		
							
								
								
									
										4
									
								
								Makefile
									
										
									
									
									
								
							
							
						
						
									
										4
									
								
								Makefile
									
										
									
									
									
								
							| 
						 | 
					@ -38,6 +38,7 @@ fmt:
 | 
				
			||||||
fmt-check:
 | 
					fmt-check:
 | 
				
			||||||
	@unformatted=$$(gofmt -l $(FMT_PATHS)); [ -z "$$unformatted" ] && exit 0; echo "Unformatted:"; for fn in $$unformatted; do echo "  $$fn"; done; exit 1
 | 
						@unformatted=$$(gofmt -l $(FMT_PATHS)); [ -z "$$unformatted" ] && exit 0; echo "Unformatted:"; for fn in $$unformatted; do echo "  $$fn"; done; exit 1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
gen-device: gen-device-avr gen-device-nrf gen-device-sam gen-device-stm32
 | 
					gen-device: gen-device-avr gen-device-nrf gen-device-sam gen-device-stm32
 | 
				
			||||||
 | 
					
 | 
				
			||||||
gen-device-avr:
 | 
					gen-device-avr:
 | 
				
			||||||
| 
						 | 
					@ -85,6 +86,9 @@ build/tinygo:
 | 
				
			||||||
test:
 | 
					test:
 | 
				
			||||||
	CGO_CPPFLAGS="$(CGO_CPPFLAGS)" CGO_CXXFLAGS="$(CGO_CXXFLAGS)" CGO_LDFLAGS="$(CGO_LDFLAGS)" go test -v -tags byollvm .
 | 
						CGO_CPPFLAGS="$(CGO_CPPFLAGS)" CGO_CXXFLAGS="$(CGO_CXXFLAGS)" CGO_LDFLAGS="$(CGO_LDFLAGS)" go test -v -tags byollvm .
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					tinygo-test:
 | 
				
			||||||
 | 
						cd tests/tinygotest && tinygo test
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.PHONY: smoketest smoketest-no-avr
 | 
					.PHONY: smoketest smoketest-no-avr
 | 
				
			||||||
smoketest: smoketest-no-avr
 | 
					smoketest: smoketest-no-avr
 | 
				
			||||||
	tinygo build -size short -o test.elf -target=arduino             examples/blinky1
 | 
						tinygo build -size short -o test.elf -target=arduino             examples/blinky1
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -48,6 +48,12 @@ type Config struct {
 | 
				
			||||||
	TINYGOROOT    string   // GOROOT for TinyGo
 | 
						TINYGOROOT    string   // GOROOT for TinyGo
 | 
				
			||||||
	GOPATH        string   // GOPATH, like `go env GOPATH`
 | 
						GOPATH        string   // GOPATH, like `go env GOPATH`
 | 
				
			||||||
	BuildTags     []string // build tags for TinyGo (empty means {Config.GOOS/Config.GOARCH})
 | 
						BuildTags     []string // build tags for TinyGo (empty means {Config.GOOS/Config.GOARCH})
 | 
				
			||||||
 | 
						TestConfig    TestConfig
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type TestConfig struct {
 | 
				
			||||||
 | 
						CompileTestBinary bool
 | 
				
			||||||
 | 
						// TODO: Filter the test functions to run, include verbose flag, etc
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type Compiler struct {
 | 
					type Compiler struct {
 | 
				
			||||||
| 
						 | 
					@ -214,7 +220,7 @@ func (c *Compiler) Compile(mainPath string) []error {
 | 
				
			||||||
				path = path[len(tinygoPath+"/src/"):]
 | 
									path = path[len(tinygoPath+"/src/"):]
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			switch path {
 | 
								switch path {
 | 
				
			||||||
			case "machine", "os", "reflect", "runtime", "runtime/volatile", "sync":
 | 
								case "machine", "os", "reflect", "runtime", "runtime/volatile", "sync", "testing":
 | 
				
			||||||
				return path
 | 
									return path
 | 
				
			||||||
			default:
 | 
								default:
 | 
				
			||||||
				if strings.HasPrefix(path, "device/") || strings.HasPrefix(path, "examples/") {
 | 
									if strings.HasPrefix(path, "device/") || strings.HasPrefix(path, "examples/") {
 | 
				
			||||||
| 
						 | 
					@ -241,6 +247,7 @@ func (c *Compiler) Compile(mainPath string) []error {
 | 
				
			||||||
		CFlags:       c.CFlags,
 | 
							CFlags:       c.CFlags,
 | 
				
			||||||
		ClangHeaders: c.ClangHeaders,
 | 
							ClangHeaders: c.ClangHeaders,
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if strings.HasSuffix(mainPath, ".go") {
 | 
						if strings.HasSuffix(mainPath, ".go") {
 | 
				
			||||||
		_, err = lprogram.ImportFile(mainPath)
 | 
							_, err = lprogram.ImportFile(mainPath)
 | 
				
			||||||
		if err != nil {
 | 
							if err != nil {
 | 
				
			||||||
| 
						 | 
					@ -252,12 +259,13 @@ func (c *Compiler) Compile(mainPath string) []error {
 | 
				
			||||||
			return []error{err}
 | 
								return []error{err}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	_, err = lprogram.Import("runtime", "")
 | 
						_, err = lprogram.Import("runtime", "")
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return []error{err}
 | 
							return []error{err}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	err = lprogram.Parse()
 | 
						err = lprogram.Parse(c.TestConfig.CompileTestBinary)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return []error{err}
 | 
							return []error{err}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										137
									
								
								loader/loader.go
									
										
									
									
									
								
							
							
						
						
									
										137
									
								
								loader/loader.go
									
										
									
									
									
								
							| 
						 | 
					@ -1,6 +1,7 @@
 | 
				
			||||||
package loader
 | 
					package loader
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
 | 
						"bytes"
 | 
				
			||||||
	"errors"
 | 
						"errors"
 | 
				
			||||||
	"go/ast"
 | 
						"go/ast"
 | 
				
			||||||
	"go/build"
 | 
						"go/build"
 | 
				
			||||||
| 
						 | 
					@ -10,12 +11,15 @@ import (
 | 
				
			||||||
	"os"
 | 
						"os"
 | 
				
			||||||
	"path/filepath"
 | 
						"path/filepath"
 | 
				
			||||||
	"sort"
 | 
						"sort"
 | 
				
			||||||
 | 
						"strings"
 | 
				
			||||||
 | 
						"text/template"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"github.com/tinygo-org/tinygo/cgo"
 | 
						"github.com/tinygo-org/tinygo/cgo"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Program holds all packages and some metadata about the program as a whole.
 | 
					// Program holds all packages and some metadata about the program as a whole.
 | 
				
			||||||
type Program struct {
 | 
					type Program struct {
 | 
				
			||||||
 | 
						mainPkg      string
 | 
				
			||||||
	Build        *build.Context
 | 
						Build        *build.Context
 | 
				
			||||||
	OverlayBuild *build.Context
 | 
						OverlayBuild *build.Context
 | 
				
			||||||
	OverlayPath  func(path string) string
 | 
						OverlayPath  func(path string) string
 | 
				
			||||||
| 
						 | 
					@ -64,6 +68,11 @@ func (p *Program) Import(path, srcDir string) (*Package, error) {
 | 
				
			||||||
	p.sorted = nil // invalidate the sorted order of packages
 | 
						p.sorted = nil // invalidate the sorted order of packages
 | 
				
			||||||
	pkg := p.newPackage(buildPkg)
 | 
						pkg := p.newPackage(buildPkg)
 | 
				
			||||||
	p.Packages[buildPkg.ImportPath] = pkg
 | 
						p.Packages[buildPkg.ImportPath] = pkg
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if p.mainPkg == "" {
 | 
				
			||||||
 | 
							p.mainPkg = buildPkg.ImportPath
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return pkg, nil
 | 
						return pkg, nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -93,6 +102,11 @@ func (p *Program) ImportFile(path string) (*Package, error) {
 | 
				
			||||||
	p.sorted = nil // invalidate the sorted order of packages
 | 
						p.sorted = nil // invalidate the sorted order of packages
 | 
				
			||||||
	pkg := p.newPackage(buildPkg)
 | 
						pkg := p.newPackage(buildPkg)
 | 
				
			||||||
	p.Packages[buildPkg.ImportPath] = pkg
 | 
						p.Packages[buildPkg.ImportPath] = pkg
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if p.mainPkg == "" {
 | 
				
			||||||
 | 
							p.mainPkg = buildPkg.ImportPath
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return pkg, nil
 | 
						return pkg, nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -171,10 +185,12 @@ func (p *Program) sort() {
 | 
				
			||||||
// The returned error may be an Errors error, which contains a list of errors.
 | 
					// The returned error may be an Errors error, which contains a list of errors.
 | 
				
			||||||
//
 | 
					//
 | 
				
			||||||
// Idempotent.
 | 
					// Idempotent.
 | 
				
			||||||
func (p *Program) Parse() error {
 | 
					func (p *Program) Parse(compileTestBinary bool) error {
 | 
				
			||||||
 | 
						includeTests := compileTestBinary
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Load all imports
 | 
						// Load all imports
 | 
				
			||||||
	for _, pkg := range p.Sorted() {
 | 
						for _, pkg := range p.Sorted() {
 | 
				
			||||||
		err := pkg.importRecursively()
 | 
							err := pkg.importRecursively(includeTests)
 | 
				
			||||||
		if err != nil {
 | 
							if err != nil {
 | 
				
			||||||
			if err, ok := err.(*ImportCycleError); ok {
 | 
								if err, ok := err.(*ImportCycleError); ok {
 | 
				
			||||||
				if pkg.ImportPath != err.Packages[0] {
 | 
									if pkg.ImportPath != err.Packages[0] {
 | 
				
			||||||
| 
						 | 
					@ -187,7 +203,14 @@ func (p *Program) Parse() error {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Parse all packages.
 | 
						// Parse all packages.
 | 
				
			||||||
	for _, pkg := range p.Sorted() {
 | 
						for _, pkg := range p.Sorted() {
 | 
				
			||||||
		err := pkg.Parse()
 | 
							err := pkg.Parse(includeTests)
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								return err
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if compileTestBinary {
 | 
				
			||||||
 | 
							err := p.SwapTestMain()
 | 
				
			||||||
		if err != nil {
 | 
							if err != nil {
 | 
				
			||||||
			return err
 | 
								return err
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
| 
						 | 
					@ -204,6 +227,83 @@ func (p *Program) Parse() error {
 | 
				
			||||||
	return nil
 | 
						return nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (p *Program) SwapTestMain() error {
 | 
				
			||||||
 | 
						var tests []string
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						isTestFunc := func(f *ast.FuncDecl) bool {
 | 
				
			||||||
 | 
							// TODO: improve signature check
 | 
				
			||||||
 | 
							if strings.HasPrefix(f.Name.Name, "Test") && f.Name.Name != "TestMain" {
 | 
				
			||||||
 | 
								return true
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							return false
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						mainPkg := p.Packages[p.mainPkg]
 | 
				
			||||||
 | 
						for _, f := range mainPkg.Files {
 | 
				
			||||||
 | 
							for i, d := range f.Decls {
 | 
				
			||||||
 | 
								switch v := d.(type) {
 | 
				
			||||||
 | 
								case *ast.FuncDecl:
 | 
				
			||||||
 | 
									if isTestFunc(v) {
 | 
				
			||||||
 | 
										tests = append(tests, v.Name.Name)
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									if v.Name.Name == "main" {
 | 
				
			||||||
 | 
										// Remove main
 | 
				
			||||||
 | 
										if len(f.Decls) == 1 {
 | 
				
			||||||
 | 
											f.Decls = make([]ast.Decl, 0)
 | 
				
			||||||
 | 
										} else {
 | 
				
			||||||
 | 
											f.Decls[i] = f.Decls[len(f.Decls)-1]
 | 
				
			||||||
 | 
											f.Decls = f.Decls[:len(f.Decls)-1]
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// TODO: Check if they defined a TestMain and call it instead of testing.TestMain
 | 
				
			||||||
 | 
						const mainBody = `package main
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"testing"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func main () {
 | 
				
			||||||
 | 
						m := &testing.M{
 | 
				
			||||||
 | 
							Tests: []testing.TestToCall{
 | 
				
			||||||
 | 
					{{range .TestFunctions}}
 | 
				
			||||||
 | 
								{Name: "{{.}}", Func: {{.}}},
 | 
				
			||||||
 | 
					{{end}}
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						testing.TestMain(m)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					`
 | 
				
			||||||
 | 
						tmpl := template.Must(template.New("testmain").Parse(mainBody))
 | 
				
			||||||
 | 
						b := bytes.Buffer{}
 | 
				
			||||||
 | 
						tmplData := struct {
 | 
				
			||||||
 | 
							TestFunctions []string
 | 
				
			||||||
 | 
						}{
 | 
				
			||||||
 | 
							TestFunctions: tests,
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						err := tmpl.Execute(&b, tmplData)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						path := filepath.Join(p.mainPkg, "$testmain.go")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if p.fset == nil {
 | 
				
			||||||
 | 
							p.fset = token.NewFileSet()
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						newMain, err := parser.ParseFile(p.fset, path, b.Bytes(), parser.AllErrors)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						mainPkg.Files = append(mainPkg.Files, newMain)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// parseFile is a wrapper around parser.ParseFile.
 | 
					// parseFile is a wrapper around parser.ParseFile.
 | 
				
			||||||
func (p *Program) parseFile(path string, mode parser.Mode) (*ast.File, error) {
 | 
					func (p *Program) parseFile(path string, mode parser.Mode) (*ast.File, error) {
 | 
				
			||||||
	if p.fset == nil {
 | 
						if p.fset == nil {
 | 
				
			||||||
| 
						 | 
					@ -228,7 +328,7 @@ func (p *Program) parseFile(path string, mode parser.Mode) (*ast.File, error) {
 | 
				
			||||||
// Parse parses and typechecks this package.
 | 
					// Parse parses and typechecks this package.
 | 
				
			||||||
//
 | 
					//
 | 
				
			||||||
// Idempotent.
 | 
					// Idempotent.
 | 
				
			||||||
func (p *Package) Parse() error {
 | 
					func (p *Package) Parse(includeTests bool) error {
 | 
				
			||||||
	if len(p.Files) != 0 {
 | 
						if len(p.Files) != 0 {
 | 
				
			||||||
		return nil
 | 
							return nil
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					@ -242,7 +342,7 @@ func (p *Package) Parse() error {
 | 
				
			||||||
		return nil
 | 
							return nil
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	files, err := p.parseFiles()
 | 
						files, err := p.parseFiles(includeTests)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return err
 | 
							return err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					@ -281,11 +381,21 @@ func (p *Package) Check() error {
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// parseFiles parses the loaded list of files and returns this list.
 | 
					// parseFiles parses the loaded list of files and returns this list.
 | 
				
			||||||
func (p *Package) parseFiles() ([]*ast.File, error) {
 | 
					func (p *Package) parseFiles(includeTests bool) ([]*ast.File, error) {
 | 
				
			||||||
	// TODO: do this concurrently.
 | 
						// TODO: do this concurrently.
 | 
				
			||||||
	var files []*ast.File
 | 
						var files []*ast.File
 | 
				
			||||||
	var fileErrs []error
 | 
						var fileErrs []error
 | 
				
			||||||
	for _, file := range p.GoFiles {
 | 
					
 | 
				
			||||||
 | 
						var gofiles []string
 | 
				
			||||||
 | 
						if includeTests {
 | 
				
			||||||
 | 
							gofiles = make([]string, 0, len(p.GoFiles)+len(p.TestGoFiles))
 | 
				
			||||||
 | 
							gofiles = append(gofiles, p.GoFiles...)
 | 
				
			||||||
 | 
							gofiles = append(gofiles, p.TestGoFiles...)
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							gofiles = p.GoFiles
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for _, file := range gofiles {
 | 
				
			||||||
		f, err := p.parseFile(filepath.Join(p.Package.Dir, file), parser.ParseComments)
 | 
							f, err := p.parseFile(filepath.Join(p.Package.Dir, file), parser.ParseComments)
 | 
				
			||||||
		if err != nil {
 | 
							if err != nil {
 | 
				
			||||||
			fileErrs = append(fileErrs, err)
 | 
								fileErrs = append(fileErrs, err)
 | 
				
			||||||
| 
						 | 
					@ -320,6 +430,7 @@ func (p *Package) parseFiles() ([]*ast.File, error) {
 | 
				
			||||||
	if len(fileErrs) != 0 {
 | 
						if len(fileErrs) != 0 {
 | 
				
			||||||
		return nil, Errors{p, fileErrs}
 | 
							return nil, Errors{p, fileErrs}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return files, nil
 | 
						return files, nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -340,9 +451,15 @@ func (p *Package) Import(to string) (*types.Package, error) {
 | 
				
			||||||
// importRecursively() on the imported packages as well.
 | 
					// importRecursively() on the imported packages as well.
 | 
				
			||||||
//
 | 
					//
 | 
				
			||||||
// Idempotent.
 | 
					// Idempotent.
 | 
				
			||||||
func (p *Package) importRecursively() error {
 | 
					func (p *Package) importRecursively(includeTests bool) error {
 | 
				
			||||||
	p.Importing = true
 | 
						p.Importing = true
 | 
				
			||||||
	for _, to := range p.Package.Imports {
 | 
					
 | 
				
			||||||
 | 
						imports := p.Package.Imports
 | 
				
			||||||
 | 
						if includeTests {
 | 
				
			||||||
 | 
							imports = append(imports, p.Package.TestImports...)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for _, to := range imports {
 | 
				
			||||||
		if to == "C" {
 | 
							if to == "C" {
 | 
				
			||||||
			// Do CGo processing in a later stage.
 | 
								// Do CGo processing in a later stage.
 | 
				
			||||||
			continue
 | 
								continue
 | 
				
			||||||
| 
						 | 
					@ -360,7 +477,7 @@ func (p *Package) importRecursively() error {
 | 
				
			||||||
		if importedPkg.Importing {
 | 
							if importedPkg.Importing {
 | 
				
			||||||
			return &ImportCycleError{[]string{p.ImportPath, importedPkg.ImportPath}, p.ImportPos[to]}
 | 
								return &ImportCycleError{[]string{p.ImportPath, importedPkg.ImportPath}, p.ImportPos[to]}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		err = importedPkg.importRecursively()
 | 
							err = importedPkg.importRecursively(false)
 | 
				
			||||||
		if err != nil {
 | 
							if err != nil {
 | 
				
			||||||
			if err, ok := err.(*ImportCycleError); ok {
 | 
								if err, ok := err.(*ImportCycleError); ok {
 | 
				
			||||||
				err.Packages = append([]string{p.ImportPath}, err.Packages...)
 | 
									err.Packages = append([]string{p.ImportPath}, err.Packages...)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										33
									
								
								main.go
									
										
									
									
									
								
							
							
						
						
									
										33
									
								
								main.go
									
										
									
									
									
								
							| 
						 | 
					@ -54,6 +54,7 @@ type BuildConfig struct {
 | 
				
			||||||
	cFlags        []string
 | 
						cFlags        []string
 | 
				
			||||||
	ldFlags       []string
 | 
						ldFlags       []string
 | 
				
			||||||
	wasmAbi       string
 | 
						wasmAbi       string
 | 
				
			||||||
 | 
						testConfig    compiler.TestConfig
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Helper function for Compiler object.
 | 
					// Helper function for Compiler object.
 | 
				
			||||||
| 
						 | 
					@ -108,6 +109,7 @@ func Compile(pkgName, outpath string, spec *TargetSpec, config *BuildConfig, act
 | 
				
			||||||
		GOROOT:        goroot,
 | 
							GOROOT:        goroot,
 | 
				
			||||||
		GOPATH:        getGopath(),
 | 
							GOPATH:        getGopath(),
 | 
				
			||||||
		BuildTags:     tags,
 | 
							BuildTags:     tags,
 | 
				
			||||||
 | 
							TestConfig:    config.testConfig,
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	c, err := compiler.NewCompiler(pkgName, compilerConfig)
 | 
						c, err := compiler.NewCompiler(pkgName, compilerConfig)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
| 
						 | 
					@ -349,6 +351,30 @@ func Build(pkgName, outpath, target string, config *BuildConfig) error {
 | 
				
			||||||
	})
 | 
						})
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func Test(pkgName, target string, config *BuildConfig) error {
 | 
				
			||||||
 | 
						spec, err := LoadTarget(target)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						spec.BuildTags = append(spec.BuildTags, "test")
 | 
				
			||||||
 | 
						config.testConfig.CompileTestBinary = true
 | 
				
			||||||
 | 
						return Compile(pkgName, ".elf", spec, config, func(tmppath string) error {
 | 
				
			||||||
 | 
							cmd := exec.Command(tmppath)
 | 
				
			||||||
 | 
							cmd.Stdout = os.Stdout
 | 
				
			||||||
 | 
							cmd.Stderr = os.Stderr
 | 
				
			||||||
 | 
							err := cmd.Run()
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								// Propagate the exit code
 | 
				
			||||||
 | 
								if err, ok := err.(*exec.ExitError); ok {
 | 
				
			||||||
 | 
									os.Exit(err.ExitCode())
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								return &commandError{"failed to run compiled binary", tmppath, err}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							return nil
 | 
				
			||||||
 | 
						})
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func Flash(pkgName, target, port string, config *BuildConfig) error {
 | 
					func Flash(pkgName, target, port string, config *BuildConfig) error {
 | 
				
			||||||
	spec, err := LoadTarget(target)
 | 
						spec, err := LoadTarget(target)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
| 
						 | 
					@ -656,6 +682,13 @@ func main() {
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		err := Run(flag.Arg(0), *target, config)
 | 
							err := Run(flag.Arg(0), *target, config)
 | 
				
			||||||
		handleCompilerError(err)
 | 
							handleCompilerError(err)
 | 
				
			||||||
 | 
						case "test":
 | 
				
			||||||
 | 
							pkgRoot := "."
 | 
				
			||||||
 | 
							if flag.NArg() == 1 {
 | 
				
			||||||
 | 
								pkgRoot = flag.Arg(0)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							err := Test(pkgRoot, *target, config)
 | 
				
			||||||
 | 
							handleCompilerError(err)
 | 
				
			||||||
	case "clean":
 | 
						case "clean":
 | 
				
			||||||
		// remove cache directory
 | 
							// remove cache directory
 | 
				
			||||||
		dir := cacheDir()
 | 
							dir := cacheDir()
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -92,7 +92,7 @@ func (v Value) Pointer() uintptr {
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (v Value) IsValid() bool {
 | 
					func (v Value) IsValid() bool {
 | 
				
			||||||
	panic("unimplemented: (reflect.Value).IsValid()")
 | 
						return v.typecode != 0
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (v Value) CanInterface() bool {
 | 
					func (v Value) CanInterface() bool {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										6
									
								
								src/testing/doc.go
									
										
									
									
									
										Обычный файл
									
								
							
							
						
						
									
										6
									
								
								src/testing/doc.go
									
										
									
									
									
										Обычный файл
									
								
							| 
						 | 
					@ -0,0 +1,6 @@
 | 
				
			||||||
 | 
					package testing
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 This is a sad stub of the upstream testing package because it doesn't compile
 | 
				
			||||||
 | 
					 with tinygo right now.
 | 
				
			||||||
 | 
					*/
 | 
				
			||||||
							
								
								
									
										77
									
								
								src/testing/testing.go
									
										
									
									
									
										Обычный файл
									
								
							
							
						
						
									
										77
									
								
								src/testing/testing.go
									
										
									
									
									
										Обычный файл
									
								
							| 
						 | 
					@ -0,0 +1,77 @@
 | 
				
			||||||
 | 
					package testing
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"bytes"
 | 
				
			||||||
 | 
						"fmt"
 | 
				
			||||||
 | 
						"io"
 | 
				
			||||||
 | 
						"os"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// T is a test helper.
 | 
				
			||||||
 | 
					type T struct {
 | 
				
			||||||
 | 
						name   string
 | 
				
			||||||
 | 
						output io.Writer
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// flags the test as having failed when non-zero
 | 
				
			||||||
 | 
						failed int
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// TestToCall is a reference to a test that should be called during a test suite run.
 | 
				
			||||||
 | 
					type TestToCall struct {
 | 
				
			||||||
 | 
						// Name of the test to call.
 | 
				
			||||||
 | 
						Name string
 | 
				
			||||||
 | 
						// Function reference to the test.
 | 
				
			||||||
 | 
						Func func(*T)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// M is a test suite.
 | 
				
			||||||
 | 
					type M struct {
 | 
				
			||||||
 | 
						// tests is a list of the test names to execute
 | 
				
			||||||
 | 
						Tests []TestToCall
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Run the test suite.
 | 
				
			||||||
 | 
					func (m *M) Run() int {
 | 
				
			||||||
 | 
						failures := 0
 | 
				
			||||||
 | 
						for _, test := range m.Tests {
 | 
				
			||||||
 | 
							t := &T{
 | 
				
			||||||
 | 
								name:   test.Name,
 | 
				
			||||||
 | 
								output: &bytes.Buffer{},
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							fmt.Printf("=== RUN   %s\n", test.Name)
 | 
				
			||||||
 | 
							test.Func(t)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if t.failed == 0 {
 | 
				
			||||||
 | 
								fmt.Printf("--- PASS: %s\n", test.Name)
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
 | 
								fmt.Printf("--- FAIL: %s\n", test.Name)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							fmt.Println(t.output)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							failures += t.failed
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if failures > 0 {
 | 
				
			||||||
 | 
							fmt.Printf("exit status %d\n", failures)
 | 
				
			||||||
 | 
							fmt.Println("FAIL")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return failures
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TestMain(m *M) {
 | 
				
			||||||
 | 
						os.Exit(m.Run())
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Error is equivalent to Log followed by Fail
 | 
				
			||||||
 | 
					func (t *T) Error(args ...interface{}) {
 | 
				
			||||||
 | 
						// This doesn't print the same as in upstream go, but works good enough
 | 
				
			||||||
 | 
						// TODO: buffer test output like go does
 | 
				
			||||||
 | 
						fmt.Fprintf(t.output, "\t")
 | 
				
			||||||
 | 
						fmt.Fprintln(t.output, args...)
 | 
				
			||||||
 | 
						t.Fail()
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (t *T) Fail() {
 | 
				
			||||||
 | 
						t.failed = 1
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										14
									
								
								tests/tinygotest/main.go
									
										
									
									
									
										Обычный файл
									
								
							
							
						
						
									
										14
									
								
								tests/tinygotest/main.go
									
										
									
									
									
										Обычный файл
									
								
							| 
						 | 
					@ -0,0 +1,14 @@
 | 
				
			||||||
 | 
					package main
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"fmt"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func main() {
 | 
				
			||||||
 | 
						Thing()
 | 
				
			||||||
 | 
						fmt.Println("normal main")
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func Thing() {
 | 
				
			||||||
 | 
						fmt.Println("THING")
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										16
									
								
								tests/tinygotest/main_test.go
									
										
									
									
									
										Обычный файл
									
								
							
							
						
						
									
										16
									
								
								tests/tinygotest/main_test.go
									
										
									
									
									
										Обычный файл
									
								
							| 
						 | 
					@ -0,0 +1,16 @@
 | 
				
			||||||
 | 
					package main
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"testing" // This is the tinygo testing package
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TestFail1(t *testing.T) {
 | 
				
			||||||
 | 
						t.Error("TestFail1 failed because of stuff and things")
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TestFail2(t *testing.T) {
 | 
				
			||||||
 | 
						t.Error("TestFail2 failed for reasons")
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TestPass(t *testing.T) {
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
		Загрузка…
	
	Создание таблицы
		
		Сослаться в новой задаче