blob: 588f09a6c8c2526e5eeff41ef9e75c1ac792183e [file]
package analysis
import (
"go/ast"
"go/types"
"testing"
"github.com/gopherjs/gopherjs/internal/srctesting"
)
// See: https://github.com/gopherjs/gopherjs/issues/955.
func TestBlockingFunctionLiteral(t *testing.T) {
src := `
package test
func blocking() {
c := make(chan bool)
<-c
}
func indirectlyBlocking() {
func() { blocking() }()
}
func directlyBlocking() {
func() {
c := make(chan bool)
<-c
}()
}
func notBlocking() {
func() { println() } ()
}
`
f := srctesting.New(t)
file := f.Parse("test.go", src)
typesInfo, typesPkg := f.Check("pkg/test", file)
pkgInfo := AnalyzePkg([]*ast.File{file}, f.FileSet, typesInfo, typesPkg, func(f *types.Func) bool {
panic("isBlocking() should be never called for imported functions in this test.")
})
assertBlocking(t, file, pkgInfo, "blocking")
assertBlocking(t, file, pkgInfo, "indirectlyBlocking")
assertBlocking(t, file, pkgInfo, "directlyBlocking")
assertNotBlocking(t, file, pkgInfo, "notBlocking")
}
func assertBlocking(t *testing.T, file *ast.File, pkgInfo *Info, funcName string) {
typesFunc := getTypesFunc(t, file, pkgInfo, funcName)
if !pkgInfo.IsBlocking(typesFunc) {
t.Errorf("Got: %q is not blocking. Want: %q is blocking.", typesFunc, typesFunc)
}
}
func assertNotBlocking(t *testing.T, file *ast.File, pkgInfo *Info, funcName string) {
typesFunc := getTypesFunc(t, file, pkgInfo, funcName)
if pkgInfo.IsBlocking(typesFunc) {
t.Errorf("Got: %q is blocking. Want: %q is not blocking.", typesFunc, typesFunc)
}
}
func getTypesFunc(t *testing.T, file *ast.File, pkgInfo *Info, funcName string) *types.Func {
obj := file.Scope.Lookup(funcName)
if obj == nil {
t.Fatalf("Declaration of %q is not found in the AST.", funcName)
}
decl, ok := obj.Decl.(*ast.FuncDecl)
if !ok {
t.Fatalf("Got: %q is %v. Want: a function declaration.", funcName, obj.Kind)
}
blockingType, ok := pkgInfo.Defs[decl.Name]
if !ok {
t.Fatalf("No type information is found for %v.", decl.Name)
}
return blockingType.(*types.Func)
}