| // Copyright 2020 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. |
| |
| package fetch |
| |
| import ( |
| "net/http" |
| "strings" |
| |
| "golang.org/x/pkgsite/internal" |
| "golang.org/x/pkgsite/internal/derrors" |
| "golang.org/x/pkgsite/internal/godoc" |
| "golang.org/x/pkgsite/internal/proxy" |
| "golang.org/x/pkgsite/internal/source" |
| "golang.org/x/pkgsite/internal/stdlib" |
| "golang.org/x/pkgsite/internal/testing/testhelper" |
| ) |
| |
| type testModule struct { |
| mod *proxy.Module |
| fr *FetchResult |
| docStrings map[string][]string |
| } |
| |
| var moduleOnePackage = &testModule{ |
| mod: &proxy.Module{ |
| ModulePath: "github.com/basic", |
| Files: map[string]string{ |
| "README.md": "THIS IS A README", |
| "foo/foo.go": "// package foo exports a helpful constant.\npackage foo\nimport \"net/http\"\nconst OK = http.StatusOK", |
| "LICENSE": testhelper.BSD0License, |
| }, |
| }, |
| fr: &FetchResult{ |
| Module: &internal.Module{ |
| ModuleInfo: internal.ModuleInfo{ |
| ModulePath: "github.com/basic", |
| HasGoMod: false, |
| }, |
| Units: []*internal.Unit{ |
| { |
| UnitMeta: internal.UnitMeta{ |
| Path: "github.com/basic", |
| }, |
| Readme: &internal.Readme{ |
| Filepath: "README.md", |
| Contents: "THIS IS A README", |
| }, |
| }, |
| { |
| UnitMeta: internal.UnitMeta{ |
| Name: "foo", |
| Path: "github.com/basic/foo", |
| }, |
| Documentation: []*internal.Documentation{{ |
| Synopsis: "package foo exports a helpful constant.", |
| }}, |
| Imports: []string{"net/http"}, |
| }, |
| }, |
| }, |
| }, |
| } |
| |
| var moduleMultiPackage = &testModule{ |
| mod: &proxy.Module{ |
| ModulePath: "github.com/my/module", |
| Files: map[string]string{ |
| "go.mod": "module github.com/my/module\n\ngo 1.12", |
| "LICENSE": testhelper.BSD0License, |
| "README.md": "README FILE FOR TESTING.", |
| "bar/COPYING": testhelper.MITLicense, |
| "bar/README.md": "Another README FILE FOR TESTING.", |
| "bar/bar.go": ` |
| // package bar |
| package bar |
| |
| // Bar returns the string "bar". |
| func Bar() string { |
| return "bar" |
| }`, |
| "foo/LICENSE.md": testhelper.MITLicense, |
| "foo/foo.go": ` |
| // package foo |
| package foo |
| |
| import ( |
| "fmt" |
| |
| "github.com/my/module/bar" |
| ) |
| |
| // FooBar returns the string "foo bar". |
| func FooBar() string { |
| return fmt.Sprintf("foo %s", bar.Bar()) |
| }`, |
| }, |
| }, |
| fr: &FetchResult{ |
| Module: &internal.Module{ |
| ModuleInfo: internal.ModuleInfo{ |
| ModulePath: "github.com/my/module", |
| HasGoMod: true, |
| SourceInfo: source.NewGitHubInfo("https://github.com/my/module", "", "v1.0.0"), |
| }, |
| Units: []*internal.Unit{ |
| { |
| UnitMeta: internal.UnitMeta{ |
| Path: "github.com/my/module", |
| }, |
| Readme: &internal.Readme{ |
| Filepath: "README.md", |
| Contents: "README FILE FOR TESTING.", |
| }, |
| }, |
| { |
| UnitMeta: internal.UnitMeta{ |
| Name: "bar", |
| Path: "github.com/my/module/bar", |
| }, |
| Readme: &internal.Readme{ |
| Filepath: "bar/README.md", |
| Contents: "Another README FILE FOR TESTING.", |
| }, |
| Documentation: []*internal.Documentation{{ |
| Synopsis: "package bar", |
| }}, |
| }, |
| { |
| UnitMeta: internal.UnitMeta{ |
| Name: "foo", |
| Path: "github.com/my/module/foo", |
| }, |
| Documentation: []*internal.Documentation{{ |
| Synopsis: "package foo", |
| }}, |
| Imports: []string{"fmt", "github.com/my/module/bar"}, |
| }, |
| }, |
| }, |
| }, |
| docStrings: map[string][]string{ |
| "github.com/my/module/bar": {"Bar returns the string "bar"."}, |
| "github.com/my/module/foo": {"FooBar returns the string "foo bar"."}, |
| }, |
| } |
| |
| var moduleNoGoMod = &testModule{ |
| mod: &proxy.Module{ |
| ModulePath: "no.mod/module", |
| Files: map[string]string{ |
| "LICENSE": testhelper.BSD0License, |
| "p/p.go": ` |
| // Package p is inside a module where a go.mod |
| // file hasn't been explicitly added yet. |
| package p |
| |
| // Year is a year before go.mod files existed. |
| const Year = 2009`, |
| }, |
| }, |
| fr: &FetchResult{ |
| Module: &internal.Module{ |
| ModuleInfo: internal.ModuleInfo{ |
| ModulePath: "no.mod/module", |
| HasGoMod: false, |
| }, |
| Units: []*internal.Unit{ |
| { |
| UnitMeta: internal.UnitMeta{ |
| Path: "no.mod/module", |
| }, |
| }, |
| { |
| UnitMeta: internal.UnitMeta{ |
| Name: "p", |
| Path: "no.mod/module/p", |
| }, |
| Documentation: []*internal.Documentation{{ |
| Synopsis: "Package p is inside a module where a go.mod file hasn't been explicitly added yet.", |
| }}, |
| }, |
| }, |
| }, |
| }, |
| docStrings: map[string][]string{ |
| "no.mod/module/p": {"const Year = 2009"}, |
| }, |
| } |
| |
| var moduleEmpty = &testModule{ |
| mod: &proxy.Module{ |
| ModulePath: "emp.ty/module", |
| }, |
| fr: &FetchResult{Module: &internal.Module{}}, |
| } |
| |
| var moduleBadPackages = &testModule{ |
| mod: &proxy.Module{ |
| ModulePath: "bad.mod/module", |
| Files: map[string]string{ |
| "LICENSE": testhelper.BSD0License, |
| "good/good.go": ` |
| // Package good is inside a module that has bad packages. |
| package good |
| |
| // Good is whether this package is good. |
| const Good = true`, |
| |
| "illegalchar/p.go": ` |
| package p |
| |
| func init() { |
| var c00 uint8 = '\0'; // ERROR "oct|char" |
| var c01 uint8 = '\07'; // ERROR "oct|char" |
| var cx0 uint8 = '\x0'; // ERROR "hex|char" |
| var cx1 uint8 = '\x'; // ERROR "hex|char" |
| _, _, _, _ = c00, c01, cx0, cx1 |
| } |
| `, |
| "multiplepkgs/a.go": "package a", |
| "multiplepkgs/b.go": "package b", |
| }, |
| }, |
| fr: &FetchResult{ |
| Status: derrors.ToStatus(derrors.HasIncompletePackages), |
| Module: &internal.Module{ |
| ModuleInfo: internal.ModuleInfo{ |
| ModulePath: "bad.mod/module", |
| }, |
| Units: []*internal.Unit{ |
| { |
| UnitMeta: internal.UnitMeta{ |
| Path: "bad.mod/module", |
| }, |
| }, |
| { |
| UnitMeta: internal.UnitMeta{ |
| Name: "good", |
| Path: "bad.mod/module/good", |
| }, |
| Documentation: []*internal.Documentation{{ |
| Synopsis: "Package good is inside a module that has bad packages.", |
| }}, |
| }, |
| }, |
| }, |
| PackageVersionStates: []*internal.PackageVersionState{ |
| { |
| PackagePath: "bad.mod/module/good", |
| ModulePath: "bad.mod/module", |
| Version: "v1.0.0", |
| Status: 200, |
| }, |
| { |
| PackagePath: "bad.mod/module/illegalchar", |
| ModulePath: "bad.mod/module", |
| Version: "v1.0.0", |
| Status: 600, |
| }, |
| { |
| PackagePath: "bad.mod/module/multiplepkgs", |
| ModulePath: "bad.mod/module", |
| Version: "v1.0.0", |
| Status: 600, |
| }, |
| }, |
| }, |
| docStrings: map[string][]string{ |
| "bad.mod/module/good": {`const Good = <a href="/builtin#true">true</a>`}, |
| }, |
| } |
| |
| var moduleBuildConstraints = &testModule{ |
| mod: &proxy.Module{ |
| ModulePath: "build.constraints/module", |
| Files: map[string]string{ |
| "LICENSE": testhelper.BSD0License, |
| "cpu/cpu.go": ` |
| // Package cpu implements processor feature detection |
| // used by the Go standard library. |
| package cpu`, |
| "cpu/cpu_arm.go": "package cpu\n\nconst CacheLinePadSize = 1", |
| "cpu/cpu_arm64.go": "package cpu\n\nconst CacheLinePadSize = 2", |
| "cpu/cpu_x86.go": "// +build 386 amd64 amd64p32\n\npackage cpu\n\nconst CacheLinePadSize = 3", |
| "ignore/ignore.go": "// +build ignore\n\npackage ignore", |
| }, |
| }, |
| fr: &FetchResult{ |
| Status: derrors.ToStatus(derrors.HasIncompletePackages), |
| Module: &internal.Module{ |
| ModuleInfo: internal.ModuleInfo{ |
| ModulePath: "build.constraints/module", |
| HasGoMod: false, |
| }, |
| Units: []*internal.Unit{ |
| { |
| UnitMeta: internal.UnitMeta{ |
| Path: "build.constraints/module", |
| }, |
| }, |
| { |
| UnitMeta: internal.UnitMeta{ |
| Name: "cpu", |
| Path: "build.constraints/module/cpu", |
| }, |
| Documentation: []*internal.Documentation{{ |
| Synopsis: "Package cpu implements processor feature detection used by the Go standard library.", |
| }}, |
| }, |
| }, |
| }, |
| PackageVersionStates: []*internal.PackageVersionState{ |
| { |
| ModulePath: "build.constraints/module", |
| Version: "v1.0.0", |
| PackagePath: "build.constraints/module/cpu", |
| Status: http.StatusOK, |
| }, |
| { |
| ModulePath: "build.constraints/module", |
| Version: "v1.0.0", |
| PackagePath: "build.constraints/module/ignore", |
| Status: derrors.ToStatus(derrors.PackageBuildContextNotSupported), |
| }, |
| }, |
| }, |
| docStrings: map[string][]string{ |
| "build.constraints/module/cpu": {"const CacheLinePadSize = 3"}, |
| }, |
| } |
| |
| var moduleNonRedist = &testModule{ |
| mod: &proxy.Module{ |
| ModulePath: "nonredistributable.mod/module", |
| Files: map[string]string{ |
| "go.mod": "module nonredistributable.mod/module\n\ngo 1.13", |
| "LICENSE": testhelper.BSD0License, |
| "README.md": "README FILE FOR TESTING.", |
| "bar/baz/COPYING": testhelper.MITLicense, |
| "bar/baz/baz.go": ` |
| // package baz |
| package baz |
| |
| // Baz returns the string "baz". |
| func Baz() string { |
| return "baz" |
| } |
| `, |
| "bar/LICENSE": testhelper.MITLicense, |
| "bar/bar.go": ` |
| // package bar |
| package bar |
| |
| // Bar returns the string "bar". |
| func Bar() string { |
| return "bar" |
| }`, |
| "foo/README.md": "README FILE SHOW UP HERE BUT WILL BE REMOVED BEFORE DB INSERT", |
| "foo/LICENSE.md": testhelper.UnknownLicense, |
| "foo/foo.go": ` |
| // package foo |
| package foo |
| |
| import ( |
| "fmt" |
| |
| "github.com/my/module/bar" |
| ) |
| |
| // FooBar returns the string "foo bar". |
| func FooBar() string { |
| return fmt.Sprintf("foo %s", bar.Bar()) |
| }`, |
| }, |
| }, |
| fr: &FetchResult{ |
| Module: &internal.Module{ |
| ModuleInfo: internal.ModuleInfo{ |
| ModulePath: "nonredistributable.mod/module", |
| HasGoMod: true, |
| }, |
| Units: []*internal.Unit{ |
| { |
| UnitMeta: internal.UnitMeta{ |
| Path: "nonredistributable.mod/module", |
| }, |
| Readme: &internal.Readme{ |
| Filepath: "README.md", |
| Contents: "README FILE FOR TESTING.", |
| }, |
| }, |
| { |
| UnitMeta: internal.UnitMeta{ |
| Name: "bar", |
| Path: "nonredistributable.mod/module/bar", |
| }, |
| Documentation: []*internal.Documentation{{ |
| Synopsis: "package bar", |
| }}, |
| }, |
| { |
| UnitMeta: internal.UnitMeta{ |
| Name: "baz", |
| Path: "nonredistributable.mod/module/bar/baz", |
| }, |
| Documentation: []*internal.Documentation{{ |
| Synopsis: "package baz", |
| }}, |
| }, |
| { |
| UnitMeta: internal.UnitMeta{ |
| Name: "foo", |
| Path: "nonredistributable.mod/module/foo", |
| }, |
| Readme: &internal.Readme{ |
| Filepath: "foo/README.md", |
| Contents: "README FILE SHOW UP HERE BUT WILL BE REMOVED BEFORE DB INSERT", |
| }, |
| Documentation: []*internal.Documentation{{ |
| Synopsis: "package foo", |
| }}, |
| Imports: []string{"fmt", "github.com/my/module/bar"}, |
| }, |
| }, |
| }, |
| }, |
| docStrings: map[string][]string{ |
| "nonredistributable.mod/module/bar": {"Bar returns the string"}, |
| "nonredistributable.mod/module/bar/baz": {"Baz returns the string"}, |
| "nonredistributable.mod/module/foo": {"FooBar returns the string"}, |
| }, |
| } |
| |
| var moduleBadImportPath = &testModule{ |
| mod: &proxy.Module{ |
| ModulePath: "bad.import.path.com", |
| Files: map[string]string{ |
| "good/import/path/foo.go": "package foo", |
| "bad/import path/foo.go": "package foo", |
| }, |
| }, |
| fr: &FetchResult{ |
| Status: derrors.ToStatus(derrors.HasIncompletePackages), |
| Module: &internal.Module{ |
| ModuleInfo: internal.ModuleInfo{ |
| ModulePath: "bad.import.path.com", |
| }, |
| Units: []*internal.Unit{ |
| { |
| UnitMeta: internal.UnitMeta{ |
| Path: "bad.import.path.com", |
| }, |
| }, |
| { |
| UnitMeta: internal.UnitMeta{ |
| Path: "bad.import.path.com/good", |
| }, |
| }, |
| { |
| UnitMeta: internal.UnitMeta{ |
| Path: "bad.import.path.com/good/import", |
| }, |
| }, |
| { |
| UnitMeta: internal.UnitMeta{ |
| Name: "foo", |
| Path: "bad.import.path.com/good/import/path", |
| }, |
| Documentation: []*internal.Documentation{{}}, |
| }, |
| }, |
| }, |
| PackageVersionStates: []*internal.PackageVersionState{ |
| { |
| ModulePath: "bad.import.path.com", |
| PackagePath: "bad.import.path.com/bad/import path", |
| Version: "v1.0.0", |
| Status: derrors.ToStatus(derrors.PackageBadImportPath), |
| }, |
| { |
| ModulePath: "bad.import.path.com", |
| PackagePath: "bad.import.path.com/good/import/path", |
| Version: "v1.0.0", |
| Status: http.StatusOK, |
| }, |
| }, |
| }, |
| } |
| |
| var moduleDocTest = &testModule{ |
| mod: &proxy.Module{ |
| ModulePath: "doc.test", |
| Files: map[string]string{ |
| "LICENSE": testhelper.BSD0License, |
| "permalink/doc.go": ` |
| // Package permalink is for testing the heading |
| // permalink documentation rendering feature. |
| // |
| // This is a heading |
| // |
| // This is a paragraph. |
| // |
| // This is yet another |
| // paragraph. |
| // |
| package permalink`, |
| }, |
| }, |
| fr: &FetchResult{ |
| GoModPath: "doc.test", |
| Module: &internal.Module{ |
| ModuleInfo: internal.ModuleInfo{ |
| ModulePath: "doc.test", |
| HasGoMod: false, |
| }, |
| Units: []*internal.Unit{ |
| { |
| UnitMeta: internal.UnitMeta{ |
| Path: "doc.test", |
| }, |
| }, |
| { |
| UnitMeta: internal.UnitMeta{ |
| Name: "permalink", |
| Path: "doc.test/permalink", |
| }, |
| Documentation: []*internal.Documentation{{ |
| Synopsis: "Package permalink is for testing the heading permalink documentation rendering feature.", |
| }}, |
| }, |
| }, |
| }, |
| }, |
| docStrings: map[string][]string{ |
| "doc.test/permalink": { |
| "<h4 id=\"hdr-This_is_a_heading\">This is a heading <a", |
| "href=\"#hdr-This_is_a_heading\">¶</a></h4>", |
| }, |
| }, |
| } |
| |
| var moduleDocTooLarge = &testModule{ |
| mod: &proxy.Module{ |
| ModulePath: "bigdoc.test", |
| Files: map[string]string{ |
| "LICENSE": testhelper.BSD0License, |
| "doc.go": "// This documentation is big.\n" + |
| strings.Repeat("// Too big.\n", 100_000) + |
| "package bigdoc", |
| }, |
| }, |
| fr: &FetchResult{ |
| Status: derrors.ToStatus(derrors.HasIncompletePackages), |
| GoModPath: "bigdoc.test", |
| Module: &internal.Module{ |
| ModuleInfo: internal.ModuleInfo{ |
| ModulePath: "bigdoc.test", |
| HasGoMod: false, |
| }, |
| Units: []*internal.Unit{ |
| { |
| UnitMeta: internal.UnitMeta{ |
| Name: "bigdoc", |
| Path: "bigdoc.test", |
| }, |
| Documentation: []*internal.Documentation{{ |
| Synopsis: "This documentation is big.", |
| }}, |
| }, |
| }, |
| }, |
| PackageVersionStates: []*internal.PackageVersionState{ |
| { |
| PackagePath: "bigdoc.test", |
| ModulePath: "bigdoc.test", |
| Version: "v1.0.0", |
| Status: derrors.ToStatus(derrors.PackageDocumentationHTMLTooLarge), |
| }, |
| }, |
| }, |
| docStrings: map[string][]string{ |
| "bigdoc.test": {godoc.DocTooLargeReplacement}, |
| }, |
| } |
| |
| var moduleWasm = &testModule{ |
| mod: &proxy.Module{ |
| ModulePath: "github.com/my/module/js", |
| Files: map[string]string{ |
| |
| "README.md": "THIS IS A README", |
| "LICENSE": testhelper.BSD0License, |
| "js/js.go": ` |
| // +build js,wasm |
| |
| // Package js only works with wasm. |
| package js |
| type Value int`, |
| }, |
| }, |
| fr: &FetchResult{ |
| Module: &internal.Module{ |
| ModuleInfo: internal.ModuleInfo{ |
| ModulePath: "github.com/my/module/js", |
| SourceInfo: source.NewGitHubInfo("https://github.com/my/module", "js", "js/v1.0.0"), |
| }, |
| Units: []*internal.Unit{ |
| { |
| UnitMeta: internal.UnitMeta{ |
| Path: "github.com/my/module/js", |
| }, |
| Readme: &internal.Readme{ |
| Filepath: "README.md", |
| Contents: "THIS IS A README", |
| }, |
| }, |
| { |
| UnitMeta: internal.UnitMeta{ |
| Name: "js", |
| Path: "github.com/my/module/js/js", |
| }, |
| Documentation: []*internal.Documentation{{ |
| Synopsis: "Package js only works with wasm.", |
| GOOS: "js", |
| GOARCH: "wasm", |
| }}, |
| }, |
| }, |
| }, |
| }, |
| } |
| |
| var moduleAlternative = &testModule{ |
| mod: &proxy.Module{ |
| ModulePath: "github.com/my/module", |
| Files: map[string]string{"go.mod": "module canonical"}, |
| }, |
| fr: &FetchResult{ |
| GoModPath: "canonical", |
| }, |
| } |
| |
| var moduleStd = &testModule{ |
| mod: &proxy.Module{ |
| ModulePath: stdlib.ModulePath, |
| Version: "v1.12.5", |
| }, |
| fr: &FetchResult{ |
| Module: &internal.Module{ |
| ModuleInfo: internal.ModuleInfo{ |
| ModulePath: "std", |
| Version: "v1.12.5", |
| CommitTime: stdlib.TestCommitTime, |
| HasGoMod: true, |
| SourceInfo: source.NewStdlibInfo("v1.12.5"), |
| }, |
| Units: []*internal.Unit{ |
| { |
| UnitMeta: internal.UnitMeta{ |
| Path: "std", |
| |
| IsRedistributable: true, |
| }, |
| Readme: &internal.Readme{ |
| Filepath: "README.md", |
| Contents: "# The Go Programming Language\n", |
| }, |
| }, |
| { |
| UnitMeta: internal.UnitMeta{ |
| Name: "builtin", |
| Path: "builtin", |
| }, |
| Documentation: []*internal.Documentation{{ |
| Synopsis: "Package builtin provides documentation for Go's predeclared identifiers.", |
| }}, |
| }, |
| { |
| UnitMeta: internal.UnitMeta{ |
| Path: "cmd", |
| }, |
| }, |
| { |
| UnitMeta: internal.UnitMeta{ |
| Name: "main", |
| Path: "cmd/pprof", |
| }, |
| Readme: &internal.Readme{ |
| Filepath: "cmd/pprof/README", |
| Contents: "This directory is the copy of Google's pprof shipped as part of the Go distribution.\n", |
| }, |
| Documentation: []*internal.Documentation{{ |
| Synopsis: "Pprof interprets and displays profiles of Go programs.", |
| }}, |
| Imports: []string{ |
| "cmd/internal/objfile", |
| "crypto/tls", |
| "debug/dwarf", |
| "fmt", |
| "github.com/google/pprof/driver", |
| "github.com/google/pprof/profile", |
| "golang.org/x/crypto/ssh/terminal", |
| "io", |
| "io/ioutil", |
| "net/http", |
| "net/url", |
| "os", |
| "regexp", |
| "strconv", |
| "strings", |
| "sync", |
| "time", |
| }, |
| }, |
| { |
| UnitMeta: internal.UnitMeta{ |
| Name: "context", |
| Path: "context", |
| }, |
| Documentation: []*internal.Documentation{{ |
| Synopsis: "Package context defines the Context type, which carries deadlines, cancelation signals, and other request-scoped values across API boundaries and between processes.", |
| }}, |
| Imports: []string{"errors", "fmt", "reflect", "sync", "time"}, |
| }, |
| { |
| UnitMeta: internal.UnitMeta{ |
| Path: "encoding", |
| }, |
| }, |
| { |
| UnitMeta: internal.UnitMeta{ |
| Name: "json", |
| Path: "encoding/json", |
| }, |
| Documentation: []*internal.Documentation{{ |
| Synopsis: "Package json implements encoding and decoding of JSON as defined in RFC 7159.", |
| }}, |
| Imports: []string{ |
| "bytes", |
| "encoding", |
| "encoding/base64", |
| "errors", |
| "fmt", |
| "io", |
| "math", |
| "reflect", |
| "sort", |
| "strconv", |
| "strings", |
| "sync", |
| "unicode", |
| "unicode/utf16", |
| "unicode/utf8", |
| }, |
| }, |
| { |
| UnitMeta: internal.UnitMeta{ |
| Name: "errors", |
| Path: "errors", |
| }, |
| Documentation: []*internal.Documentation{{ |
| Synopsis: "Package errors implements functions to manipulate errors.", |
| }}, |
| }, |
| { |
| UnitMeta: internal.UnitMeta{ |
| Name: "flag", |
| Path: "flag", |
| }, |
| Imports: []string{"errors", "fmt", "io", "os", "reflect", "sort", "strconv", "strings", "time"}, |
| Documentation: []*internal.Documentation{{ |
| Synopsis: "Package flag implements command-line flag parsing.", |
| }}, |
| }, |
| }, |
| }, |
| }, |
| } |
| |
| var moduleMaster = &testModule{ |
| mod: &proxy.Module{ |
| ModulePath: "github.com/my/module", |
| Files: map[string]string{ |
| "foo/foo.go": "// package foo exports a helpful constant.\npackage foo\nconst Bar = 1", |
| }, |
| Version: "v0.0.0-20200706064627-355bc3f705ed", |
| }, |
| fr: &FetchResult{ |
| RequestedVersion: "master", |
| Module: &internal.Module{ |
| ModuleInfo: internal.ModuleInfo{ |
| ModulePath: "github.com/my/module", |
| Version: "v0.0.0-20200706064627-355bc3f705ed", |
| SourceInfo: source.NewGitHubInfo("https://github.com/my/module", "", "355bc3f705ed"), |
| }, |
| Units: []*internal.Unit{ |
| { |
| UnitMeta: internal.UnitMeta{ |
| Path: "github.com/my/module", |
| }, |
| }, |
| { |
| UnitMeta: internal.UnitMeta{ |
| Name: "foo", |
| Path: "github.com/my/module/foo", |
| }, |
| Documentation: []*internal.Documentation{{ |
| Synopsis: "package foo exports a helpful constant.", |
| }}, |
| }, |
| }, |
| }, |
| }, |
| } |
| |
| var moduleLatest = &testModule{ |
| mod: &proxy.Module{ |
| ModulePath: "github.com/my/module", |
| Files: map[string]string{ |
| "foo/foo.go": "// package foo exports a helpful constant.\npackage foo\nconst Bar = 1", |
| }, |
| Version: "v1.2.4", |
| }, |
| fr: &FetchResult{ |
| RequestedVersion: "latest", |
| Module: &internal.Module{ |
| ModuleInfo: internal.ModuleInfo{ |
| ModulePath: "github.com/my/module", |
| Version: "v1.2.4", |
| SourceInfo: source.NewGitHubInfo("https://github.com/my/module", "", "v1.2.4"), |
| }, |
| Units: []*internal.Unit{ |
| { |
| UnitMeta: internal.UnitMeta{ |
| Path: "github.com/my/module", |
| }, |
| }, |
| { |
| UnitMeta: internal.UnitMeta{ |
| Name: "foo", |
| Path: "github.com/my/module/foo", |
| }, |
| Documentation: []*internal.Documentation{{ |
| Synopsis: "package foo exports a helpful constant.", |
| }}, |
| }, |
| }, |
| }, |
| }, |
| } |
| |
| // moduleWithExamples returns a testModule that contains an example. |
| // It provides the common bits for the tests for package, function, |
| // type, and method examples below. |
| // |
| // The fetch result's documentation HTML is treated as a set |
| // of substrings that should appear in the generated documentation. |
| // The substrings are separated by a '~' character. |
| func moduleWithExamples(path, source, test string, docSubstrings ...string) *testModule { |
| return &testModule{ |
| mod: &proxy.Module{ |
| ModulePath: path, |
| Files: map[string]string{ |
| "LICENSE": testhelper.BSD0License, |
| "example/example.go": ` |
| // Package example contains examples. |
| package example |
| ` + source, |
| "example/example_test.go": ` |
| package example_test |
| ` + test, |
| }, |
| }, |
| fr: &FetchResult{ |
| GoModPath: path, |
| Module: &internal.Module{ |
| ModuleInfo: internal.ModuleInfo{ |
| ModulePath: path, |
| HasGoMod: false, |
| }, |
| Units: []*internal.Unit{ |
| { |
| UnitMeta: internal.UnitMeta{ |
| Path: path, |
| }, |
| }, |
| { |
| UnitMeta: internal.UnitMeta{ |
| Name: "example", |
| Path: path + "/example", |
| }, |
| Documentation: []*internal.Documentation{{ |
| Synopsis: "Package example contains examples.", |
| }}, |
| }, |
| }, |
| }, |
| }, |
| docStrings: map[string][]string{ |
| path + "/example": docSubstrings, |
| }, |
| } |
| } |
| |
| var modulePackageExample = moduleWithExamples("package.example", |
| ``, |
| `import "fmt" |
| |
| // Example for the package. |
| func Example() { |
| fmt.Println("hello") |
| // Output: hello |
| } |
| `, "Documentation-exampleButtonsContainer") |
| |
| var moduleFuncExample = moduleWithExamples("func.example", |
| `func F() {} |
| `, `import "func.example/example" |
| |
| // Example for the function. |
| func ExampleF() { |
| example.F() |
| } |
| `, "Documentation-exampleButtonsContainer") |
| |
| var moduleTypeExample = moduleWithExamples("type.example", |
| `type T struct{} |
| `, `import "type.example/example" |
| |
| // Example for the type. |
| func ExampleT() { |
| example.T{} |
| } |
| `, "Documentation-exampleButtonsContainer") |
| |
| var moduleMethodExample = moduleWithExamples("method.example", |
| `type T struct {} |
| |
| func (*T) M() {} |
| `, `import "method.example/example" |
| |
| // Example for the method. |
| func ExampleT_M() { |
| new(example.T).M() |
| } |
| `, "Documentation-exampleButtonsContainer") |