go/packages: add a timeout for TestLoadImportsC

This will help debug golang/go#34621 by threading a context that's
canceled when the test times out. This will kill a go command that's
running when the test times out (the go command is already run
using CommandContext with the config's context).

Updates golang/go#34621

Change-Id: Iad373fd41d34395e817e6de50dd9e5842b2ef623
Reviewed-on: https://go-review.googlesource.com/c/tools/+/204200
Run-TryBot: Michael Matloob <matloob@golang.org>
Reviewed-by: Bryan C. Mills <bcmills@google.com>
diff --git a/go/packages/packages_test.go b/go/packages/packages_test.go
index 63818a5..b30e72e 100644
--- a/go/packages/packages_test.go
+++ b/go/packages/packages_test.go
@@ -6,7 +6,9 @@
 
 import (
 	"bytes"
+	"context"
 	"encoding/json"
+	"flag"
 	"fmt"
 	"go/ast"
 	constantpkg "go/constant"
@@ -21,14 +23,32 @@
 	"sort"
 	"strings"
 	"testing"
+	"time"
 
 	"golang.org/x/tools/go/packages"
 	"golang.org/x/tools/go/packages/packagestest"
 	"golang.org/x/tools/internal/testenv"
 )
 
+// testCtx is canceled when the test binary is about to time out.
+//
+// If https://golang.org/issue/28135 is accepted, uses of this variable in test
+// functions should be replaced by t.Context().
+var testCtx = context.Background()
+
 func TestMain(m *testing.M) {
 	testenv.ExitIfSmallMachine()
+
+	timeoutFlag := flag.Lookup("test.timeout")
+	if timeoutFlag != nil {
+		if d := timeoutFlag.Value.(flag.Getter).Get().(time.Duration); d != 0 {
+			aBitShorter := d * 95 / 100
+			var cancel context.CancelFunc
+			testCtx, cancel = context.WithTimeout(testCtx, aBitShorter)
+			defer cancel()
+		}
+	}
+
 	os.Exit(m.Run())
 }
 
diff --git a/go/packages/packagescgo_test.go b/go/packages/packagescgo_test.go
index 563e4bd..9858ba8 100644
--- a/go/packages/packagescgo_test.go
+++ b/go/packages/packagescgo_test.go
@@ -32,8 +32,9 @@
 	testenv.NeedsGoPackages(t)
 
 	cfg := &packages.Config{
-		Mode:  packages.LoadImports,
-		Tests: true,
+		Context: testCtx,
+		Mode:    packages.LoadImports,
+		Tests:   true,
 	}
 	initial, err := packages.Load(cfg, "syscall", "net")
 	if err != nil {