blob: d5e60e55ac39d8f2e8ffd8f0b512fd390834e483 [file] [log] [blame]
// Copyright 2015 The Vanadium 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 main
import (
"bytes"
"fmt"
"io"
"os"
"path/filepath"
"regexp"
"testing"
"v.io/jiri/gitutil"
"v.io/jiri/jiritest"
"v.io/jiri/project"
"v.io/jiri/tool"
)
func TestCopyright(t *testing.T) {
fake, cleanup := jiritest.NewFakeJiriRoot(t)
defer cleanup()
var errOut bytes.Buffer
fake.X.Context = tool.NewContext(tool.ContextOpts{
Stderr: io.MultiWriter(os.Stderr, &errOut),
})
// Load assets.
assets, err := loadAssets(fake.X, filepath.Join("..", "tooldata", "data"))
if err != nil {
t.Fatalf("%v", err)
}
if err := fake.CreateRemoteProject("test"); err != nil {
t.Fatalf("%v", err)
}
if err := fake.AddProject(project.Project{
Name: "test",
Path: "test",
Remote: fake.Projects["test"],
}); err != nil {
t.Fatalf("%v", err)
}
if err := fake.UpdateUniverse(false); err != nil {
t.Fatalf("%v", err)
}
allFiles := map[string]string{}
for file, data := range assets.MatchFiles {
allFiles[file] = data
}
for file, data := range assets.MatchPrefixFiles {
allFiles[file] = data
}
// Write out test licensing files and sample source code files to a
// project and verify that the project checks out.
projectPath := filepath.Join(fake.X.Root, "test")
project := project.Project{Path: projectPath}
s := fake.X.NewSeq()
for _, lang := range languages {
file := "test" + lang.FileExtension
if err := s.WriteFile(filepath.Join(projectPath, file), nil, os.FileMode(0600)).Done(); err != nil {
t.Fatalf("%v", err)
}
missing, err := checkFile(fake.X, filepath.Join(project.Path, file), assets, true)
if err != nil {
t.Fatalf("%v", err)
}
if got, want := missing, false; got != want {
t.Errorf("got %v, want %v", got, want)
}
if err := gitutil.New(fake.X.NewSeq(), gitutil.RootDirOpt(projectPath)).CommitFile(file, "adding "+file); err != nil {
t.Fatalf("%v", err)
}
}
for file, data := range allFiles {
if err := s.WriteFile(filepath.Join(projectPath, file), []byte(data), os.FileMode(0600)).Done(); err != nil {
t.Fatalf("%v", err)
}
if err := gitutil.New(fake.X.NewSeq(), gitutil.RootDirOpt(projectPath)).CommitFile(file, "adding "+file); err != nil {
t.Fatalf("%v", err)
}
}
missing, err := checkProject(fake.X, project, assets, false)
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
if got, want := missing, false; got != want {
t.Errorf("got %v, want %v", got, want)
}
if got, want := errOut.String(), ""; got != want {
t.Fatalf("unexpected error message: got %q, want %q", got, want)
}
// Check that missing licensing files are reported correctly.
for file, _ := range allFiles {
errOut.Reset()
missing, err := checkProject(fake.X, project, assets, true)
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
if got, want := missing, false; got != want {
t.Errorf("got %v, want %v", got, want)
}
path := filepath.Join(projectPath, file)
if err := gitutil.New(fake.X.NewSeq(), gitutil.RootDirOpt(projectPath)).Remove(file); err != nil {
t.Fatalf("%v", err)
}
missing, err = checkProject(fake.X, project, assets, false)
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
if got, want := missing, true; got != want {
t.Errorf("got %v, want %v", got, want)
}
if got, want := errOut.String(), fmt.Sprintf("%v is missing\n", path); got != want {
t.Fatalf("unexpected error message: got %q, want %q", got, want)
}
}
// Check that out-of-date licensing files are reported correctly.
for file, _ := range allFiles {
errOut.Reset()
missing, err := checkProject(fake.X, project, assets, true)
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
if got, want := missing, false; got != want {
t.Errorf("got %v, want %v", got, want)
}
path := filepath.Join(projectPath, file)
if err := s.WriteFile(path, []byte("garbage"), os.FileMode(0600)).Done(); err != nil {
t.Fatalf("%v", err)
}
missing, err = checkProject(fake.X, project, assets, false)
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
if got, want := missing, true; got != want {
t.Errorf("got %v, want %v", got, want)
}
if got, want := errOut.String(), fmt.Sprintf("%v is not up-to-date\n", path); got != want {
t.Fatalf("unexpected error message: got %q, want %q", got, want)
}
}
// Check that source code files without the copyright header are
// reported correctly.
for _, lang := range languages {
errOut.Reset()
missing, err := checkProject(fake.X, project, assets, true)
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
if got, want := missing, false; got != want {
t.Errorf("got %v, want %v", got, want)
}
path := filepath.Join(projectPath, "test"+lang.FileExtension)
if err := s.WriteFile(path, []byte("garbage"), os.FileMode(0600)).Done(); err != nil {
t.Fatalf("%v", err)
}
missing, err = checkProject(fake.X, project, assets, false)
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
if got, want := missing, true; got != want {
t.Errorf("got %v, want %v", got, want)
}
if got, want := errOut.String(), fmt.Sprintf("%v copyright is missing\n", path); got != want {
t.Fatalf("unexpected error message: got %q, want %q", got, want)
}
}
// Check that missing licensing files are fixed up correctly.
for file, _ := range allFiles {
errOut.Reset()
missing, err := checkProject(fake.X, project, assets, true)
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
if got, want := missing, false; got != want {
t.Errorf("got %v, want %v", got, want)
}
path := filepath.Join(projectPath, file)
if err := s.RemoveAll(path).Done(); err != nil {
t.Fatalf("%v", err)
}
missing, err = checkProject(fake.X, project, assets, true)
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
if got, want := missing, false; got != want {
t.Errorf("got %v, want %v", got, want)
}
missing, err = checkProject(fake.X, project, assets, false)
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
if got, want := missing, false; got != want {
t.Errorf("got %v, want %v", got, want)
}
if got, want := errOut.String(), ""; got != want {
t.Fatalf("unexpected error message: got %q, want %q", got, want)
}
}
// Check that out-of-date licensing files are fixed up correctly.
for file, _ := range allFiles {
errOut.Reset()
missing, err := checkProject(fake.X, project, assets, true)
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
if got, want := missing, false; got != want {
t.Errorf("got %v, want %v", got, want)
}
path := filepath.Join(projectPath, file)
if err := s.WriteFile(path, []byte("garbage"), os.FileMode(0600)).Done(); err != nil {
t.Fatalf("%v", err)
}
missing, err = checkProject(fake.X, project, assets, true)
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
if got, want := missing, false; got != want {
t.Errorf("got %v, want %v", got, want)
}
missing, err = checkProject(fake.X, project, assets, false)
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
if got, want := missing, false; got != want {
t.Errorf("got %v, want %v", got, want)
}
if got, want := errOut.String(), ""; got != want {
t.Fatalf("unexpected error message: got %q, want %q", got, want)
}
}
// Check that source code files missing the copyright header are
// fixed up correctly.
for _, lang := range languages {
errOut.Reset()
missing, err := checkProject(fake.X, project, assets, true)
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
if got, want := missing, false; got != want {
t.Errorf("got %v, want %v", got, want)
}
path := filepath.Join(projectPath, "test"+lang.FileExtension)
if err := s.WriteFile(path, []byte("garbage"), os.FileMode(0600)).Done(); err != nil {
t.Fatalf("%v", err)
}
missing, err = checkProject(fake.X, project, assets, true)
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
if got, want := missing, false; got != want {
t.Errorf("got %v, want %v", got, want)
}
missing, err = checkProject(fake.X, project, assets, false)
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
if got, want := missing, false; got != want {
t.Errorf("got %v, want %v", got, want)
}
if got, want := errOut.String(), ""; got != want {
t.Fatalf("unexpected error message: got %q, want %q", got, want)
}
}
// Check that third-party files are skipped when checking for copyright
// headers.
errOut.Reset()
missing, err = checkProject(fake.X, project, assets, true)
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
if got, want := missing, false; got != want {
t.Errorf("got %v, want %v", got, want)
}
path := filepath.Join(projectPath, "third_party")
gpath := filepath.Join(path, "test.go")
if err := s.MkdirAll(path, 0700).
WriteFile(gpath, []byte("garbage"), os.FileMode(0600)).Done(); err != nil {
t.Fatalf("%v", err)
}
// Since this file is in a subdir, we must run "git add" to have git track it.
// Without this, the test passes regardless of the subdir name.
if err := gitutil.New(fake.X.NewSeq(), gitutil.RootDirOpt(projectPath)).Add(path); err != nil {
t.Fatalf("%v", err)
}
missing, err = checkProject(fake.X, project, assets, false)
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
if got, want := missing, false; got != want {
t.Errorf("got %v, want %v", got, want)
}
if errOut.Len() != 0 {
t.Fatalf("unexpected error message: %q", errOut.String())
}
// Test .jiriignore functionality.
errOut.Reset()
// Add .jiriignore file.
ignoreFile := filepath.Join(projectPath, jiriIgnore)
publicDir := filepath.Join(projectPath, "public")
filename := filepath.Join(publicDir, "fancy.js")
if err := s.
WriteFile(ignoreFile, []byte("public/fancy.js"), os.FileMode(0600)).
MkdirAll(publicDir, 0700).
WriteFile(filename, []byte("garbage"), os.FileMode(0600)).Done(); err != nil {
t.Fatalf("%v", err)
}
// Since the copyright check only applies to tracked files, we must run "git
// add" to have git track it. Without this, the test passes regardless of the
// subdir name.
if err := gitutil.New(fake.X.NewSeq(), gitutil.RootDirOpt(projectPath)).Add(filename); err != nil {
t.Fatalf("%v", err)
}
missing, err = checkProject(fake.X, project, assets, false)
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
if got, want := missing, false; got != want {
t.Errorf("got %v, want %v", got, want)
}
if errOut.Len() != 0 {
t.Fatalf("unexpected error message: %q", errOut.String())
}
}
func TestCopyrightIsIgnored(t *testing.T) {
lines := []string{
"public/bundle.*",
"build/",
"dist/min.js",
}
expressions := []*regexp.Regexp{}
for _, line := range lines {
expression, err := regexp.Compile(line)
if err != nil {
t.Fatalf("unexpected regexp.Compile(%v) failed: %v", line, err)
}
expressions = append(expressions, expression)
}
shouldIgnore := []string{
"public/bundle.js",
"public/bundle.css",
"dist/min.js",
"build/bar",
}
for _, path := range shouldIgnore {
if ignore, _ := isIgnored(path, expressions); !ignore {
t.Errorf("isIgnored(%s, expressions) == %v, should be %v", path, ignore, true)
}
}
shouldNotIgnore := []string{"foo", "bar"}
for _, path := range shouldNotIgnore {
if ignore, _ := isIgnored(path, expressions); ignore {
t.Errorf("isIgnored(%s, expressions) == %v, should be %v", path, ignore, false)
}
}
}