github.com/gopherjs/gopherjs@v1.19.0-beta1.0.20240506212314-27071a8796e4/compiler/analysis/info_test.go (about)

     1  package analysis
     2  
     3  import (
     4  	"go/ast"
     5  	"go/types"
     6  	"testing"
     7  
     8  	"github.com/gopherjs/gopherjs/internal/srctesting"
     9  )
    10  
    11  // See: https://github.com/gopherjs/gopherjs/issues/955.
    12  func TestBlockingFunctionLiteral(t *testing.T) {
    13  	src := `
    14  package test
    15  
    16  func blocking() {
    17  	c := make(chan bool)
    18  	<-c
    19  }
    20  
    21  func indirectlyBlocking() {
    22  	func() { blocking() }()
    23  }
    24  
    25  func directlyBlocking() {
    26  	func() {
    27  		c := make(chan bool)
    28  		<-c
    29  	}()
    30  }
    31  
    32  func notBlocking() {
    33  	func() { println() } ()
    34  }
    35  `
    36  	f := srctesting.New(t)
    37  	file := f.Parse("test.go", src)
    38  	typesInfo, typesPkg := f.Check("pkg/test", file)
    39  
    40  	pkgInfo := AnalyzePkg([]*ast.File{file}, f.FileSet, typesInfo, typesPkg, func(f *types.Func) bool {
    41  		panic("isBlocking() should be never called for imported functions in this test.")
    42  	})
    43  
    44  	assertBlocking(t, file, pkgInfo, "blocking")
    45  	assertBlocking(t, file, pkgInfo, "indirectlyBlocking")
    46  	assertBlocking(t, file, pkgInfo, "directlyBlocking")
    47  	assertNotBlocking(t, file, pkgInfo, "notBlocking")
    48  }
    49  
    50  func assertBlocking(t *testing.T, file *ast.File, pkgInfo *Info, funcName string) {
    51  	typesFunc := getTypesFunc(t, file, pkgInfo, funcName)
    52  	if !pkgInfo.IsBlocking(typesFunc) {
    53  		t.Errorf("Got: %q is not blocking. Want: %q is blocking.", typesFunc, typesFunc)
    54  	}
    55  }
    56  
    57  func assertNotBlocking(t *testing.T, file *ast.File, pkgInfo *Info, funcName string) {
    58  	typesFunc := getTypesFunc(t, file, pkgInfo, funcName)
    59  	if pkgInfo.IsBlocking(typesFunc) {
    60  		t.Errorf("Got: %q is blocking. Want: %q is not blocking.", typesFunc, typesFunc)
    61  	}
    62  }
    63  
    64  func getTypesFunc(t *testing.T, file *ast.File, pkgInfo *Info, funcName string) *types.Func {
    65  	obj := file.Scope.Lookup(funcName)
    66  	if obj == nil {
    67  		t.Fatalf("Declaration of %q is not found in the AST.", funcName)
    68  	}
    69  	decl, ok := obj.Decl.(*ast.FuncDecl)
    70  	if !ok {
    71  		t.Fatalf("Got: %q is %v. Want: a function declaration.", funcName, obj.Kind)
    72  	}
    73  	blockingType, ok := pkgInfo.Defs[decl.Name]
    74  	if !ok {
    75  		t.Fatalf("No type information is found for %v.", decl.Name)
    76  	}
    77  	return blockingType.(*types.Func)
    78  }