package pkgpath

import (
	"os"
	"os/exec"
	"path/filepath"
	"strings"
	"testing"
)

func TestPkgpathMain(t *testing.T) {
	pkg, ok := Main()
	if have, want := pkg, "code.justin.tv/common/golibs/pkgpath/_test"; have != want {
		t.Errorf("Main(); %q != %q", have, want)
	}
	if have, want := ok, true; have != want {
		t.Errorf("Main(); %t != %t", have, want)
	}
}

func TestByRunning(t *testing.T) {
	cmd := exec.Command("go", "run", "-a", "--", "./maintest/main.go")

	// Create environment for go run.
	for _, env := range os.Environ() {
		if strings.HasPrefix(env, "GO15VENDOREXPERIMENT=") {
			continue
		}
		if strings.HasPrefix(env, "GOPATH=") {
			continue
		}
		cmd.Env = append(cmd.Env, env)
	}
	cmd.Env = append(cmd.Env, "GO15VENDOREXPERIMENT=1")
	// Set GOPATH to contain the _vendor directory after the usual value.
	gopath := []string{os.Getenv("GOPATH")}
	if gopath[0] == "" {
		gopath = gopath[:0]
	}
	wd, _ := os.Getwd()
	gopath = append(gopath, filepath.Join(wd, "maintest/_vendor"))
	cmd.Env = append(cmd.Env, "GOPATH="+strings.Join(gopath, string(os.PathListSeparator)))

	out, err := cmd.CombinedOutput()
	if err != nil {
		t.Fatalf("go run maintest/main.go; err = %q, output = %q", err, out)
	}

	// We're looking for four separate behaviors here, represented by the four
	// lines of output below. The first is that a program should be able to
	// determine its own name, definited as the import path of its package
	// main. The second is that a package should be able to determine its own
	// import path, even when it is a main package. The third is that a non-
	// main pacakge should be able to determine its import path. Finally, a
	// package that appears under a "vendor" path (per the Go 1.5 vendor
	// experiment https://golang.org/s/go15vendor) should observe its import
	// path without the .../vendor/ prefix.
	if have, want := string(out), `
code.justin.tv/common/golibs/pkgpath/maintest
code.justin.tv/common/golibs/pkgpath/maintest
code.justin.tv/common/golibs/pkgpath/maintest/imported
imported2
`[1:]; have != want {
		t.Errorf("pkgpath.Main();\n%q\n!=\n%q\n", have, want)
	}
}

func TestPkgpathCaller(t *testing.T) {
	pkg, ok := Caller(0)
	if have, want := pkg, "code.justin.tv/common/golibs/pkgpath"; have != want {
		t.Errorf("Main(); %q != %q", have, want)
	}
	if have, want := ok, true; have != want {
		t.Errorf("Main(); %t != %t", have, want)
	}
}

func TestPkgpathCallerClosure(t *testing.T) {
	var pkg string
	var ok bool
	func() {
		pkg, ok = Caller(0)
	}()
	if have, want := pkg, "code.justin.tv/common/golibs/pkgpath"; have != want {
		t.Errorf("Main(); %q != %q", have, want)
	}
	if have, want := ok, true; have != want {
		t.Errorf("Main(); %t != %t", have, want)
	}
}

func TestFileImportPath(t *testing.T) {
	tests := []struct {
		file string
		path string
	}{
		{file: "/go/src/code.justin.tv/web/tmi/irc/irc.go",
			path: "code.justin.tv/web/tmi/irc"},
		{file: "/go/src/code.justin.tv/web/owl/Godeps/_workspace/src/github.com/kisielk/errcheck/main.go",
			path: "github.com/kisielk/errcheck"},
		{file: "code.justin.tv/common/chitin/_test/generated.go",
			path: "code.justin.tv/common/chitin/_test"},
		{file: "/tmp/runme.go",
			path: "main"},
	}

	for _, tt := range tests {
		if have, want := fileImportPath(tt.file), tt.path; have != want {
			t.Errorf("fileImportPath(%q); %q != %q", tt.file, have, want)
		}
	}
}
