blob: e037cda73aec4c554011d2a204178d6d1cbbf486 [file] [log] [blame]
// Copyright 2019 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 (
"context"
"errors"
"io/fs"
"testing"
"github.com/google/go-cmp/cmp"
"golang.org/x/pkgsite/internal"
"golang.org/x/pkgsite/internal/derrors"
"golang.org/x/pkgsite/internal/proxy/proxytest"
"golang.org/x/pkgsite/internal/stdlib"
"golang.org/x/pkgsite/internal/testenv"
)
func TestExtractReadme(t *testing.T) {
testenv.MustHaveExecPath(t, "git")
defer stdlib.WithTestData()()
ctx := context.Background()
for _, test := range []struct {
name, modulePath, pkgPath, version string
files map[string]string
want *internal.Readme
}{
{
name: "README at root and README in unit and README in _",
modulePath: stdlib.ModulePath,
pkgPath: "cmd/pprof",
version: "v1.12.5",
want: &internal.Readme{
Filepath: "cmd/pprof/README",
Contents: "This directory is the copy of Google's pprof shipped as part of the Go distribution.\n",
},
},
{
name: "directory start with _",
modulePath: "github.com/my/module",
pkgPath: "github.com/my/module/_foo",
version: "v1.0.0",
files: map[string]string{
"_foo/README.md": "README",
},
want: nil,
},
{
name: "prefer README.md",
modulePath: "github.com/my/module",
pkgPath: "github.com/my/module/foo",
version: "v1.0.0",
files: map[string]string{
"foo/README": "README",
"foo/README.md": "README",
},
want: &internal.Readme{
Filepath: "foo/README.md",
Contents: "README",
},
},
{
name: "prefer readme.markdown",
modulePath: "github.com/my/module",
pkgPath: "github.com/my/module/foo",
version: "v1.0.0",
files: map[string]string{
"foo/README.markdown": "README",
"foo/readme.rst": "README",
},
want: &internal.Readme{
Filepath: "foo/README.markdown",
Contents: "README",
},
},
{
name: "no readme",
modulePath: "emp.ty/module",
version: "v1.0.0",
files: map[string]string{},
},
{
name: "readme is a directory",
modulePath: "github.com/my/module",
version: "v1.0.0",
files: map[string]string{
"foo/README/bar": "README",
},
want: nil,
},
} {
t.Run(test.name, func(t *testing.T) {
var (
contentDir fs.FS
err error
)
if test.modulePath == stdlib.ModulePath {
contentDir, _, _, err = stdlib.ContentDir(ctx, test.version)
if err != nil {
t.Fatal(err)
}
} else {
proxyClient, teardownProxy := proxytest.SetupTestClient(t, []*proxytest.Module{
{ModulePath: test.modulePath, Files: test.files}})
defer teardownProxy()
reader, err := proxyClient.Zip(ctx, test.modulePath, "v1.0.0")
if err != nil {
t.Fatal(err)
}
contentDir, err = fs.Sub(reader, test.modulePath+"@v1.0.0")
if err != nil {
t.Fatal(err)
}
}
got, err := extractReadme(test.modulePath, test.pkgPath, test.version, contentDir)
if err != nil {
t.Fatal(err)
}
if diff := cmp.Diff(test.want, got); diff != "" {
t.Errorf("mismatch (-want +got):\n%s", diff)
}
})
}
}
func TestExtractReadmesError(t *testing.T) {
ctx := context.Background()
var (
modulePath = "github.com/my/module"
pkgPath = "github.com/my/module/foo"
version = "v1.0.0"
files = map[string]string{
"foo/README.md": string(make([]byte, MaxFileSize+100)),
}
)
var (
contentDir fs.FS
err error
)
proxyClient, teardownProxy := proxytest.SetupTestClient(t, []*proxytest.Module{
{ModulePath: modulePath, Files: files}})
defer teardownProxy()
reader, err := proxyClient.Zip(ctx, modulePath, "v1.0.0")
if err != nil {
t.Fatal(err)
}
contentDir, err = fs.Sub(reader, modulePath+"@v1.0.0")
if err != nil {
t.Fatal(err)
}
got, err := extractReadme(modulePath, pkgPath, version, contentDir)
if err == nil {
t.Fatalf("want error, got %v", cmp.Diff([]*internal.Readme{}, got))
}
if !errors.Is(err, derrors.ModuleTooLarge) {
t.Errorf("want ModuleTooLarge, got %v", err)
}
}
func TestIsReadme(t *testing.T) {
for _, test := range []struct {
name, file string
want bool
}{
{
name: "README in nested dir returns true",
file: "github.com/my/module@v1.0.0/README.md",
want: true,
},
{
name: "case insensitive",
file: "rEaDme",
want: true,
},
{
name: "random extension returns true",
file: "README.FOO",
want: true,
},
{
name: "{prefix}readme will return false",
file: "FOO_README",
want: false,
},
{
file: "README_FOO",
name: "readme{suffix} will return false",
want: false,
},
{
file: "README.FOO.FOO",
name: "README file with multiple extensions will return false",
want: false,
},
{
file: "readme.go",
name: ".go README file will return false",
want: false,
},
{
file: "readme.vendor",
name: ".vendor README file will return false",
want: false,
},
{
file: "",
name: "empty filename returns false",
want: false,
},
} {
{
t.Run(test.file, func(t *testing.T) {
if got := isReadme(test.file); got != test.want {
t.Errorf("isReadme(%q) = %t: %t", test.file, got, test.want)
}
})
}
}
}