github.com/amarpal/go-tools@v0.0.0-20240422043104-40142f59f616/go/ir/irutil/load_test.go (about) 1 // Copyright 2015 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 irutil_test 6 7 import ( 8 "bytes" 9 "go/ast" 10 "go/importer" 11 "go/parser" 12 "go/token" 13 "go/types" 14 "os" 15 "strings" 16 "testing" 17 18 "github.com/amarpal/go-tools/go/ir/irutil" 19 20 "golang.org/x/tools/go/packages" 21 ) 22 23 const hello = `package main 24 25 import "fmt" 26 27 func main() { 28 fmt.Println("Hello, world") 29 } 30 ` 31 32 func TestBuildPackage(t *testing.T) { 33 // There is a more substantial test of BuildPackage and the 34 // IR program it builds in ../ir/builder_test.go. 35 36 fset := token.NewFileSet() 37 f, err := parser.ParseFile(fset, "hello.go", hello, parser.SkipObjectResolution) 38 if err != nil { 39 t.Fatal(err) 40 } 41 42 pkg := types.NewPackage("hello", "") 43 irpkg, _, err := irutil.BuildPackage(&types.Config{Importer: importer.Default()}, fset, pkg, []*ast.File{f}, 0) 44 if err != nil { 45 t.Fatal(err) 46 } 47 if pkg.Name() != "main" { 48 t.Errorf("pkg.Name() = %s, want main", pkg.Name()) 49 } 50 if irpkg.Func("main") == nil { 51 irpkg.WriteTo(os.Stderr) 52 t.Errorf("irpkg has no main function") 53 } 54 } 55 56 func TestPackages(t *testing.T) { 57 cfg := &packages.Config{Mode: packages.NeedName | packages.NeedFiles | packages.NeedCompiledGoFiles | packages.NeedImports | packages.NeedTypes | packages.NeedTypesSizes | packages.NeedSyntax | packages.NeedTypesInfo} 58 initial, err := packages.Load(cfg, "bytes") 59 if err != nil { 60 t.Fatal(err) 61 } 62 if packages.PrintErrors(initial) > 0 { 63 t.Fatal("there were errors") 64 } 65 66 prog, pkgs := irutil.Packages(initial, 0, nil) 67 bytesNewBuffer := pkgs[0].Func("NewBuffer") 68 bytesNewBuffer.Pkg.Build() 69 70 // We'll dump the IR of bytes.NewBuffer because it is small and stable. 71 out := new(bytes.Buffer) 72 bytesNewBuffer.WriteTo(out) 73 74 // For determinism, sanitize the location. 75 location := prog.Fset.Position(bytesNewBuffer.Pos()).String() 76 got := strings.Replace(out.String(), location, "$GOROOT/src/bytes/buffer.go:1", -1) 77 78 want := ` 79 # Name: bytes.NewBuffer 80 # Package: bytes 81 # Location: $GOROOT/src/bytes/buffer.go:1 82 func NewBuffer(buf []byte) *Buffer: 83 b0: # entry 84 t1 = Const <int> {0} 85 t2 = Const <readOp> {0} 86 t3 = Parameter <[]byte> {buf} 87 t4 = HeapAlloc <*Buffer> 88 t5 = CompositeValue <Buffer> [100] t3 t1 t2 89 Store {bytes.Buffer} t4 t5 90 Jump → b1 91 92 b1: ← b0 # exit 93 Return t4 94 95 `[1:] 96 if got != want { 97 t.Errorf("bytes.NewBuffer IR = <<%s>>, want <<%s>>", got, want) 98 } 99 } 100 101 func TestBuildPackage_MissingImport(t *testing.T) { 102 fset := token.NewFileSet() 103 f, err := parser.ParseFile(fset, "bad.go", `package bad; import "missing"`, parser.SkipObjectResolution) 104 if err != nil { 105 t.Fatal(err) 106 } 107 108 pkg := types.NewPackage("bad", "") 109 irpkg, _, err := irutil.BuildPackage(new(types.Config), fset, pkg, []*ast.File{f}, 0) 110 if err == nil || irpkg != nil { 111 t.Fatal("BuildPackage succeeded unexpectedly") 112 } 113 } 114 115 func TestIssue28106(t *testing.T) { 116 // In go1.10, go/packages loads all packages from source, not 117 // export data, but does not type check function bodies of 118 // imported packages. This test ensures that we do not attempt 119 // to run the IR builder on functions without type information. 120 cfg := &packages.Config{Mode: packages.NeedName | packages.NeedFiles | packages.NeedCompiledGoFiles | packages.NeedImports | packages.NeedTypes | packages.NeedTypesSizes | packages.NeedSyntax | packages.NeedTypesInfo} 121 pkgs, err := packages.Load(cfg, "runtime") 122 if err != nil { 123 t.Fatal(err) 124 } 125 prog, _ := irutil.Packages(pkgs, 0, nil) 126 prog.Build() // no crash 127 }