self_test.go raw

   1  // Copyright 2013 The Go Authors. All rights reserved.
   2  // Use of this source code is governed by a BSD-style
   3  // license that can be found in the LICENSE file.
   4  
   5  package types_test
   6  
   7  import (
   8  	"go/ast"
   9  	"go/parser"
  10  	"go/token"
  11  	"internal/testenv"
  12  	"path"
  13  	"path/filepath"
  14  	"testing"
  15  	"time"
  16  
  17  	. "go/types"
  18  )
  19  
  20  func TestSelf(t *testing.T) {
  21  	testenv.MustHaveGoBuild(t) // The Go command is needed for the importer to determine the locations of stdlib .a files.
  22  
  23  	fset := token.NewFileSet()
  24  	files, err := pkgFiles(fset, ".")
  25  	if err != nil {
  26  		t.Fatal(err)
  27  	}
  28  
  29  	conf := Config{Importer: defaultImporter(fset)}
  30  	_, err = conf.Check("go/types", fset, files, nil)
  31  	if err != nil {
  32  		t.Fatal(err)
  33  	}
  34  }
  35  
  36  func BenchmarkCheck(b *testing.B) {
  37  	testenv.MustHaveGoBuild(b) // The Go command is needed for the importer to determine the locations of stdlib .a files.
  38  
  39  	for _, p := range []string{
  40  		"net/http",
  41  		"go/parser",
  42  		"go/constant",
  43  		"runtime",
  44  		filepath.Join("go", "internal", "gcimporter"),
  45  	} {
  46  		b.Run(path.Base(p), func(b *testing.B) {
  47  			path := filepath.Join("..", "..", p)
  48  			for _, ignoreFuncBodies := range []bool{false, true} {
  49  				name := "funcbodies"
  50  				if ignoreFuncBodies {
  51  					name = "nofuncbodies"
  52  				}
  53  				b.Run(name, func(b *testing.B) {
  54  					b.Run("info", func(b *testing.B) {
  55  						runbench(b, path, ignoreFuncBodies, true)
  56  					})
  57  					b.Run("noinfo", func(b *testing.B) {
  58  						runbench(b, path, ignoreFuncBodies, false)
  59  					})
  60  				})
  61  			}
  62  		})
  63  	}
  64  }
  65  
  66  func runbench(b *testing.B, path string, ignoreFuncBodies, writeInfo bool) {
  67  	fset := token.NewFileSet()
  68  	files, err := pkgFiles(fset, path)
  69  	if err != nil {
  70  		b.Fatal(err)
  71  	}
  72  	// determine line count
  73  	lines := 0
  74  	fset.Iterate(func(f *token.File) bool {
  75  		lines += f.LineCount()
  76  		return true
  77  	})
  78  
  79  	b.ResetTimer()
  80  	start := time.Now()
  81  	for i := 0; i < b.N; i++ {
  82  		conf := Config{
  83  			IgnoreFuncBodies: ignoreFuncBodies,
  84  			Importer:         defaultImporter(fset),
  85  		}
  86  		var info *Info
  87  		if writeInfo {
  88  			info = &Info{
  89  				Types:      make(map[ast.Expr]TypeAndValue),
  90  				Defs:       make(map[*ast.Ident]Object),
  91  				Uses:       make(map[*ast.Ident]Object),
  92  				Implicits:  make(map[ast.Node]Object),
  93  				Selections: make(map[*ast.SelectorExpr]*Selection),
  94  				Scopes:     make(map[ast.Node]*Scope),
  95  			}
  96  		}
  97  		if _, err := conf.Check(path, fset, files, info); err != nil {
  98  			b.Fatal(err)
  99  		}
 100  	}
 101  	b.StopTimer()
 102  	b.ReportMetric(float64(lines)*float64(b.N)/time.Since(start).Seconds(), "lines/s")
 103  }
 104  
 105  func pkgFiles(fset *token.FileSet, path string) ([]*ast.File, error) {
 106  	filenames, err := pkgFilenames(path, true) // from stdlib_test.go
 107  	if err != nil {
 108  		return nil, err
 109  	}
 110  
 111  	var files []*ast.File
 112  	for _, filename := range filenames {
 113  		file, err := parser.ParseFile(fset, filename, nil, 0)
 114  		if err != nil {
 115  			return nil, err
 116  		}
 117  		files = append(files, file)
 118  	}
 119  
 120  	return files, nil
 121  }
 122