/* Copyright (c) Edgeless Systems GmbH SPDX-License-Identifier: AGPL-3.0-only */ package bazelfiles import ( "testing" "github.com/bazelbuild/buildtools/build" "github.com/bazelbuild/buildtools/edit" "github.com/spf13/afero" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "go.uber.org/goleak" ) func TestMain(m *testing.M) { goleak.VerifyTestMain(m, goleak.IgnoreAnyFunction("github.com/bazelbuild/rules_go/go/tools/bzltestutil.RegisterTimeoutHandler.func1")) } func TestFindFiles(t *testing.T) { testCases := map[string]struct { files []string wantFiles []BazelFile wantErr bool }{ "no WORKSPACE file": { files: []string{}, wantFiles: []BazelFile{}, wantErr: true, }, "only WORKSPACE file": { files: []string{"WORKSPACE"}, wantFiles: []BazelFile{ { RelPath: "WORKSPACE", AbsPath: "/WORKSPACE", Type: BazelFileTypeWorkspace, }, }, }, "only WORKSPACE.bazel file": { files: []string{"WORKSPACE.bazel"}, wantFiles: []BazelFile{ { RelPath: "WORKSPACE.bazel", AbsPath: "/WORKSPACE.bazel", Type: BazelFileTypeWorkspace, }, }, }, "both WORKSPACE and WORKSPACE.bazel files": { files: []string{"WORKSPACE", "WORKSPACE.bazel"}, wantFiles: []BazelFile{ { RelPath: "WORKSPACE.bazel", AbsPath: "/WORKSPACE.bazel", Type: BazelFileTypeWorkspace, }, }, }, "only .bzl file": { files: []string{"foo.bzl"}, wantErr: true, }, "all kinds": { files: []string{"WORKSPACE", "WORKSPACE.bazel", "foo.bzl", "bar.bzl", "unused.txt", "folder/baz.bzl"}, wantFiles: []BazelFile{ { RelPath: "WORKSPACE.bazel", AbsPath: "/WORKSPACE.bazel", Type: BazelFileTypeWorkspace, }, { RelPath: "foo.bzl", AbsPath: "/foo.bzl", Type: BazelFileTypeBzl, }, { RelPath: "bar.bzl", AbsPath: "/bar.bzl", Type: BazelFileTypeBzl, }, { RelPath: "folder/baz.bzl", AbsPath: "/folder/baz.bzl", Type: BazelFileTypeBzl, }, }, }, } for name, tc := range testCases { t.Run(name, func(t *testing.T) { assert := assert.New(t) require := require.New(t) fs := afero.NewMemMapFs() for _, file := range tc.files { _, err := fs.Create(file) assert.NoError(err) } helper := Helper{ fs: fs, workspaceRoot: "/", } gotFiles, err := helper.FindFiles() if tc.wantErr { assert.Error(err) return } require.NoError(err) assert.ElementsMatch(tc.wantFiles, gotFiles) }) } } func TestLoadFile(t *testing.T) { testCases := map[string]struct { file BazelFile contents string wantErr bool }{ "file does not exist": { file: BazelFile{ RelPath: "foo.bzl", AbsPath: "/foo.bzl", Type: BazelFileTypeBzl, }, wantErr: true, }, "file has unknown type": { file: BazelFile{ RelPath: "foo.txt", AbsPath: "/foo.txt", Type: BazelFileType(999), }, contents: "foo", wantErr: true, }, "file is a bzl file": { file: BazelFile{ RelPath: "foo.bzl", AbsPath: "/foo.bzl", Type: BazelFileTypeBzl, }, contents: "load(\"bar.bzl\", \"bar\")", }, "file is a workspace file": { file: BazelFile{ RelPath: "WORKSPACE", AbsPath: "/WORKSPACE", Type: BazelFileTypeWorkspace, }, contents: "workspace(name = \"foo\")", }, } for name, tc := range testCases { t.Run(name, func(t *testing.T) { assert := assert.New(t) require := require.New(t) fs := afero.NewMemMapFs() if tc.contents != "" { err := afero.WriteFile(fs, tc.file.RelPath, []byte(tc.contents), 0o644) require.NoError(err) } helper := Helper{ fs: fs, workspaceRoot: "/", } _, err := helper.LoadFile(tc.file) if tc.wantErr { assert.Error(err) return } require.NoError(err) }) } } func TestReadWriteFile(t *testing.T) { assert := assert.New(t) require := require.New(t) fs := afero.NewMemMapFs() err := afero.WriteFile(fs, "a.bzl", []byte("load(\"bar.bzl\", \"bar\")\n"), 0o644) require.NoError(err) helper := Helper{ fs: fs, workspaceRoot: "/", } bf, err := helper.LoadFile(BazelFile{ RelPath: "a.bzl", AbsPath: "/a.bzl", Type: BazelFileTypeBzl, }) require.NoError(err) err = helper.WriteFile(BazelFile{ RelPath: "b.bzl", AbsPath: "/b.bzl", Type: BazelFileTypeBzl, }, bf) require.NoError(err) _, err = fs.Stat("b.bzl") assert.NoError(err) contents, err := afero.ReadFile(fs, "b.bzl") assert.NoError(err) assert.Equal("load(\"bar.bzl\", \"bar\")\n", string(contents)) } func TestDiff(t *testing.T) { assert := assert.New(t) require := require.New(t) fs := afero.NewMemMapFs() err := afero.WriteFile(fs, "WORKSPACE.bazel", []byte(""), 0o644) require.NoError(err) helper := Helper{ fs: fs, workspaceRoot: "/", } fileRef := BazelFile{ RelPath: "WORKSPACE.bazel", AbsPath: "/WORKSPACE.bazel", Type: BazelFileTypeWorkspace, } bf, err := helper.LoadFile(fileRef) require.NoError(err) diff, err := helper.Diff(fileRef, bf) require.NoError(err) assert.Empty(diff) bf.Stmt = edit.InsertAtEnd( bf.Stmt, &build.CallExpr{ X: &build.Ident{Name: "workspace"}, List: []build.Expr{ &build.AssignExpr{ LHS: &build.Ident{Name: "name"}, Op: "=", RHS: &build.StringExpr{Value: "foo"}, }, }, }, ) diff, err = helper.Diff(fileRef, bf) require.NoError(err) assert.Equal("--- a/WORKSPACE.bazel\n+++ b/WORKSPACE.bazel\n@@ -1 +1 @@\n+workspace(name = \"foo\")\n", diff) err = helper.WriteFile(fileRef, bf) require.NoError(err) contents, err := afero.ReadFile(fs, "WORKSPACE.bazel") assert.NoError(err) assert.Equal("workspace(name = \"foo\")\n", string(contents)) diff, err = helper.Diff(fileRef, bf) require.NoError(err) assert.Empty(diff) }