2013-11-20 07:56:10 -07:00
|
|
|
package godoc
|
|
|
|
|
|
|
|
import (
|
|
|
|
"bytes"
|
2013-11-22 11:58:59 -07:00
|
|
|
"go/build"
|
|
|
|
"io/ioutil"
|
|
|
|
"os"
|
|
|
|
"path/filepath"
|
2013-11-20 07:56:10 -07:00
|
|
|
"reflect"
|
|
|
|
"regexp"
|
2013-11-26 11:28:43 -07:00
|
|
|
"runtime"
|
2013-11-20 07:56:10 -07:00
|
|
|
"testing"
|
|
|
|
"text/template"
|
|
|
|
|
|
|
|
"code.google.com/p/go.tools/godoc/vfs"
|
|
|
|
"code.google.com/p/go.tools/godoc/vfs/mapfs"
|
|
|
|
)
|
|
|
|
|
2013-11-22 11:58:59 -07:00
|
|
|
// setupGoroot creates temporary directory to act as GOROOT when running tests
|
|
|
|
// that depend upon the build package. It updates build.Default to point to the
|
|
|
|
// new GOROOT.
|
|
|
|
// It returns a function that can be called to reset build.Default and remove
|
|
|
|
// the temporary directory.
|
|
|
|
func setupGoroot(t *testing.T) (cleanup func()) {
|
|
|
|
var stdLib = map[string]string{
|
|
|
|
"src/pkg/fmt/fmt.go": `// Package fmt implements formatted I/O.
|
|
|
|
package fmt
|
|
|
|
|
|
|
|
type Stringer interface {
|
|
|
|
String() string
|
|
|
|
}
|
|
|
|
`,
|
|
|
|
}
|
|
|
|
goroot, err := ioutil.TempDir("", "cmdline_test")
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
origContext := build.Default
|
|
|
|
build.Default = build.Context{
|
|
|
|
GOROOT: goroot,
|
|
|
|
Compiler: "gc",
|
|
|
|
}
|
|
|
|
for relname, contents := range stdLib {
|
|
|
|
name := filepath.Join(goroot, relname)
|
|
|
|
if err := os.MkdirAll(filepath.Dir(name), 0770); err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
if err := ioutil.WriteFile(name, []byte(contents), 0770); err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return func() {
|
|
|
|
if err := os.RemoveAll(goroot); err != nil {
|
|
|
|
t.Log(err)
|
|
|
|
}
|
|
|
|
build.Default = origContext
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-11-20 07:56:10 -07:00
|
|
|
func TestPaths(t *testing.T) {
|
2013-11-22 11:58:59 -07:00
|
|
|
cleanup := setupGoroot(t)
|
|
|
|
defer cleanup()
|
|
|
|
|
2013-11-20 07:56:10 -07:00
|
|
|
pres := &Presentation{
|
|
|
|
pkgHandler: handlerServer{
|
|
|
|
fsRoot: "/fsroot",
|
|
|
|
},
|
|
|
|
}
|
|
|
|
fs := make(vfs.NameSpace)
|
|
|
|
|
2013-11-26 11:28:43 -07:00
|
|
|
absPath := "/foo/fmt"
|
|
|
|
if runtime.GOOS == "windows" {
|
|
|
|
absPath = `c:\foo\fmt`
|
|
|
|
}
|
|
|
|
|
2013-11-20 07:56:10 -07:00
|
|
|
for _, tc := range []struct {
|
|
|
|
desc string
|
|
|
|
path string
|
|
|
|
expAbs string
|
|
|
|
expRel string
|
|
|
|
}{
|
|
|
|
{
|
|
|
|
"Absolute path",
|
2013-11-26 11:28:43 -07:00
|
|
|
absPath,
|
2013-11-20 07:56:10 -07:00
|
|
|
"/target",
|
|
|
|
"/target",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"Local import",
|
|
|
|
"../foo/fmt",
|
|
|
|
"/target",
|
|
|
|
"/target",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"Import",
|
|
|
|
"fmt",
|
|
|
|
"/target",
|
|
|
|
"fmt",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"Default",
|
|
|
|
"unknownpkg",
|
|
|
|
"/fsroot/unknownpkg",
|
|
|
|
"unknownpkg",
|
|
|
|
},
|
|
|
|
} {
|
|
|
|
abs, rel := paths(fs, pres, tc.path)
|
|
|
|
if abs != tc.expAbs || rel != tc.expRel {
|
|
|
|
t.Errorf("%s: paths(%q) = %s,%s; want %s,%s", tc.desc, tc.path, abs, rel, tc.expAbs, tc.expRel)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestMakeRx(t *testing.T) {
|
|
|
|
for _, tc := range []struct {
|
|
|
|
desc string
|
|
|
|
names []string
|
|
|
|
exp string
|
|
|
|
}{
|
|
|
|
{
|
|
|
|
desc: "empty string",
|
|
|
|
names: []string{""},
|
|
|
|
exp: `^$`,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
desc: "simple text",
|
|
|
|
names: []string{"a"},
|
|
|
|
exp: `^a$`,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
desc: "two words",
|
|
|
|
names: []string{"foo", "bar"},
|
|
|
|
exp: `^foo$|^bar$`,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
desc: "word & non-trivial",
|
|
|
|
names: []string{"foo", `ab?c`},
|
|
|
|
exp: `^foo$|ab?c`,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
desc: "bad regexp",
|
|
|
|
names: []string{`(."`},
|
|
|
|
exp: `(."`,
|
|
|
|
},
|
|
|
|
} {
|
|
|
|
expRE, expErr := regexp.Compile(tc.exp)
|
|
|
|
if re, err := makeRx(tc.names); !reflect.DeepEqual(err, expErr) && !reflect.DeepEqual(re, expRE) {
|
|
|
|
t.Errorf("%s: makeRx(%v) = %q,%q; want %q,%q", tc.desc, tc.names, re, err, expRE, expErr)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestCommandLine(t *testing.T) {
|
2013-11-22 11:58:59 -07:00
|
|
|
cleanup := setupGoroot(t)
|
|
|
|
defer cleanup()
|
2013-11-20 07:56:10 -07:00
|
|
|
mfs := mapfs.New(map[string]string{
|
|
|
|
"src/pkg/bar/bar.go": `// Package bar is an example.
|
|
|
|
package bar
|
2014-01-30 04:28:19 -07:00
|
|
|
`,
|
|
|
|
"src/pkg/foo/foo.go": `// Package foo.
|
|
|
|
package foo
|
|
|
|
|
|
|
|
// First function is first.
|
|
|
|
func First() {
|
|
|
|
}
|
|
|
|
|
|
|
|
// Second function is second.
|
|
|
|
func Second() {
|
|
|
|
}
|
2013-11-20 07:56:10 -07:00
|
|
|
`,
|
|
|
|
"src/cmd/go/doc.go": `// The go command
|
|
|
|
package main
|
|
|
|
`,
|
|
|
|
"src/cmd/gofmt/doc.go": `// The gofmt command
|
|
|
|
package main
|
|
|
|
`,
|
|
|
|
})
|
|
|
|
fs := make(vfs.NameSpace)
|
|
|
|
fs.Bind("/", mfs, "/", vfs.BindReplace)
|
|
|
|
c := NewCorpus(fs)
|
|
|
|
p := &Presentation{Corpus: c}
|
|
|
|
p.cmdHandler = handlerServer{p, c, "/cmd/", "/src/cmd"}
|
|
|
|
p.pkgHandler = handlerServer{p, c, "/pkg/", "/src/pkg"}
|
|
|
|
p.initFuncMap()
|
2014-01-30 13:32:23 -07:00
|
|
|
p.PackageText = template.Must(template.New("PackageText").Funcs(p.FuncMap()).Parse(`{{$info := .}}{{$filtered := .IsFiltered}}{{if $filtered}}{{range .PAst}}{{range .Decls}}{{node $info .}}{{end}}{{end}}{{else}}{{with .PAst}}{{range $filename, $ast := .}}{{$filename}}:
|
|
|
|
{{node $ $ast}}{{end}}{{end}}{{end}}{{with .PDoc}}{{if $.IsMain}}COMMAND {{.Doc}}{{else}}PACKAGE {{.Doc}}{{end}}{{with .Funcs}}
|
2014-01-30 04:28:19 -07:00
|
|
|
{{range .}}{{node $ .Decl}}
|
|
|
|
{{comment_text .Doc " " "\t"}}{{end}}{{end}}{{end}}`))
|
2013-11-20 07:56:10 -07:00
|
|
|
|
|
|
|
for _, tc := range []struct {
|
|
|
|
desc string
|
|
|
|
args []string
|
|
|
|
exp string
|
|
|
|
err bool
|
|
|
|
}{
|
|
|
|
{
|
|
|
|
desc: "standard package",
|
2013-11-22 11:58:59 -07:00
|
|
|
args: []string{"fmt"},
|
|
|
|
exp: "PACKAGE Package fmt implements formatted I/O.\n",
|
2013-11-20 07:56:10 -07:00
|
|
|
},
|
|
|
|
{
|
|
|
|
desc: "package",
|
|
|
|
args: []string{"bar"},
|
|
|
|
exp: "PACKAGE Package bar is an example.\n",
|
|
|
|
},
|
2014-01-30 04:28:19 -07:00
|
|
|
{
|
|
|
|
desc: "package w. filter",
|
|
|
|
args: []string{"foo", "First"},
|
|
|
|
exp: "PACKAGE \nfunc First()\n First function is first.\n",
|
|
|
|
},
|
2013-11-20 07:56:10 -07:00
|
|
|
{
|
|
|
|
desc: "source mode",
|
|
|
|
args: []string{"src/bar"},
|
2014-01-30 04:28:19 -07:00
|
|
|
exp: "bar/bar.go:\n// Package bar is an example.\npackage bar\n",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
desc: "source mode w. filter",
|
|
|
|
args: []string{"src/foo", "Second"},
|
|
|
|
exp: "// Second function is second.\nfunc Second() {\n}",
|
2013-11-20 07:56:10 -07:00
|
|
|
},
|
|
|
|
{
|
|
|
|
desc: "command",
|
|
|
|
args: []string{"go"},
|
|
|
|
exp: "COMMAND The go command\n",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
desc: "forced command",
|
|
|
|
args: []string{"cmd/gofmt"},
|
|
|
|
exp: "COMMAND The gofmt command\n",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
desc: "bad arg",
|
|
|
|
args: []string{"doesnotexist"},
|
|
|
|
err: true,
|
|
|
|
},
|
|
|
|
} {
|
|
|
|
w := new(bytes.Buffer)
|
|
|
|
err := CommandLine(w, fs, p, tc.args)
|
|
|
|
if got, want := w.String(), tc.exp; got != want || tc.err == (err == nil) {
|
|
|
|
t.Errorf("%s: CommandLine(%v) = %q,%v; want %q,%v",
|
|
|
|
tc.desc, tc.args, got, err, want, tc.err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|