// Copyright 2015 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// Incomplete std lib sources on Android.

//go:build !android
// +build !android

package importgraph_test

import (
	"fmt"
	"go/build"
	"os"
	"sort"
	"strings"
	"testing"

	"golang.org/x/tools/internal/packagestest"
	"golang.org/x/tools/refactor/importgraph"

	_ "crypto/hmac" // just for test, below
)

const this = "golang.org/x/tools/refactor/importgraph"

func TestBuild(t *testing.T) {
	exported := packagestest.Export(t, packagestest.GOPATH, []packagestest.Module{
		{Name: "golang.org/x/tools/refactor/importgraph", Files: packagestest.MustCopyFileTree(".")}})
	defer exported.Cleanup()

	var gopath string
	for _, env := range exported.Config.Env {
		eq := strings.Index(env, "=")
		if eq == 0 {
			// We sometimes see keys with a single leading "=" in the environment on Windows.
			// TODO(#49886): What is the correct way to parse them in general?
			eq = strings.Index(env[1:], "=") + 1
		}
		if eq < 0 {
			t.Fatalf("invalid variable in exported.Config.Env: %q", env)
		}
		k := env[:eq]
		v := env[eq+1:]
		if k == "GOPATH" {
			gopath = v
		}

		if os.Getenv(k) == v {
			continue
		}
		defer func(prev string, prevOK bool) {
			if !prevOK {
				if err := os.Unsetenv(k); err != nil {
					t.Fatal(err)
				}
			} else {
				if err := os.Setenv(k, prev); err != nil {
					t.Fatal(err)
				}
			}
		}(os.LookupEnv(k))

		if err := os.Setenv(k, v); err != nil {
			t.Fatal(err)
		}
		t.Logf("%s=%s", k, v)
	}
	if gopath == "" {
		t.Fatal("Failed to fish GOPATH out of env: ", exported.Config.Env)
	}

	var buildContext = build.Default
	buildContext.GOPATH = gopath
	buildContext.Dir = exported.Config.Dir

	forward, reverse, errs := importgraph.Build(&buildContext)
	for path, err := range errs {
		t.Errorf("%s: %s", path, err)
	}
	if t.Failed() {
		return
	}

	// Log the complete graph before the errors, so that the errors are near the
	// end of the log (where we expect them to be).
	nodePrinted := map[string]bool{}
	printNode := func(direction string, from string) {
		key := fmt.Sprintf("%s[%q]", direction, from)
		if nodePrinted[key] {
			return
		}
		nodePrinted[key] = true

		var g importgraph.Graph
		switch direction {
		case "forward":
			g = forward
		case "reverse":
			g = reverse
		default:
			t.Helper()
			t.Fatalf("bad direction: %q", direction)
		}

		t.Log(key)
		var pkgs []string
		for pkg := range g[from] {
			pkgs = append(pkgs, pkg)
		}
		sort.Strings(pkgs)
		for _, pkg := range pkgs {
			t.Logf("\t%s", pkg)
		}
	}

	if testing.Verbose() {
		printNode("forward", this)
		printNode("reverse", this)
	}

	// Test direct edges.
	// We throw in crypto/hmac to prove that external test files
	// (such as this one) are inspected.
	for _, p := range []string{"go/build", "testing", "crypto/hmac"} {
		if !forward[this][p] {
			printNode("forward", this)
			t.Errorf("forward[%q][%q] not found", this, p)
		}
		if !reverse[p][this] {
			printNode("reverse", p)
			t.Errorf("reverse[%q][%q] not found", p, this)
		}
	}

	// Test non-existent direct edges
	for _, p := range []string{"errors", "reflect"} {
		if forward[this][p] {
			printNode("forward", this)
			t.Errorf("unexpected: forward[%q][%q] found", this, p)
		}
		if reverse[p][this] {
			printNode("reverse", p)
			t.Errorf("unexpected: reverse[%q][%q] found", p, this)
		}
	}

	// Test Search is reflexive.
	if !forward.Search(this)[this] {
		printNode("forward", this)
		t.Errorf("irreflexive: forward.Search(importgraph)[importgraph] not found")
	}
	if !reverse.Search(this)[this] {
		printNode("reverse", this)
		t.Errorf("irreflexive: reverse.Search(importgraph)[importgraph] not found")
	}

	// Test Search is transitive.  (There is no direct edge to these packages.)
	for _, p := range []string{"errors", "reflect", "unsafe"} {
		if !forward.Search(this)[p] {
			printNode("forward", this)
			t.Errorf("intransitive: forward.Search(importgraph)[%s] not found", p)
		}
		if !reverse.Search(p)[this] {
			printNode("reverse", p)
			t.Errorf("intransitive: reverse.Search(%s)[importgraph] not found", p)
		}
	}

	// Test strongly-connected components.  Because A's external
	// test package can depend on B, and vice versa, most of the
	// standard libraries are mutually dependent when their external
	// tests are considered.
	//
	// For any nodes x, y in the same SCC, y appears in the results
	// of both forward and reverse searches starting from x
	if !forward.Search("fmt")["io"] ||
		!forward.Search("io")["fmt"] ||
		!reverse.Search("fmt")["io"] ||
		!reverse.Search("io")["fmt"] {
		printNode("forward", "fmt")
		printNode("forward", "io")
		printNode("reverse", "fmt")
		printNode("reverse", "io")
		t.Errorf("fmt and io are not mutually reachable despite being in the same SCC")
	}
}
