test: replace embedded Git repository with dynamically created repository (#6824)

Signed-off-by: knqyf263 <knqyf263@gmail.com>
This commit is contained in:
Teppei Fukuda
2024-06-03 11:34:28 +04:00
committed by GitHub
parent c24dfbab68
commit b7b8cdc9e9
36 changed files with 240 additions and 85 deletions

132
internal/gittest/server.go Normal file
View File

@@ -0,0 +1,132 @@
//go:build unix
package gittest
import (
"errors"
"net/http/httptest"
"path/filepath"
"testing"
"time"
"github.com/go-git/go-git/v5"
"github.com/go-git/go-git/v5/config"
"github.com/go-git/go-git/v5/plumbing"
"github.com/go-git/go-git/v5/plumbing/object"
"github.com/sosedoff/gitkit"
"github.com/stretchr/testify/require"
"github.com/aquasecurity/trivy/internal/testutil"
)
var signature = &object.Signature{
Name: "Test",
Email: "test@example.com",
When: time.Now(),
}
func NewServer(t *testing.T, repo, dir string) *httptest.Server {
wtDir := t.TempDir()
// git init
r, err := git.PlainInit(wtDir, false)
require.NoError(t, err)
wt, err := r.Worktree()
require.NoError(t, err)
testutil.CopyDir(t, dir, wtDir)
_, err = wt.Add(".")
require.NoError(t, err)
_, err = wt.Commit("initial commit", &git.CommitOptions{
Author: signature,
})
require.NoError(t, err)
// Create a bare repository
bareDir := t.TempDir()
gitDir := filepath.Join(bareDir, repo+".git")
_, err = git.PlainClone(gitDir, true, &git.CloneOptions{URL: wtDir})
require.NoError(t, err)
// Set up a git server
service := gitkit.New(gitkit.Config{Dir: bareDir})
err = service.Setup()
require.NoError(t, err)
return httptest.NewServer(service)
}
func Clone(t *testing.T, ts *httptest.Server, repo, worktree string) *git.Repository {
cloneOptions := git.CloneOptions{
URL: ts.URL + "/" + repo + ".git",
}
r, err := git.PlainClone(worktree, false, &cloneOptions)
require.NoError(t, err)
return r
}
func CommitAll(t *testing.T, r *git.Repository, msg string) {
w, err := r.Worktree()
require.NoError(t, err)
_, err = w.Add(".")
require.NoError(t, err)
_, err = w.Commit(msg, &git.CommitOptions{
Author: signature,
})
require.NoError(t, err)
}
func SetTag(t *testing.T, r *git.Repository, tag string) {
h, err := r.Head()
require.NoError(t, err)
t.Logf("git tag -a %s %s -m \"%s\"", tag, h.Hash(), tag)
_, err = r.CreateTag(tag, h.Hash(), &git.CreateTagOptions{
Tagger: signature,
Message: tag,
})
require.NoError(t, err)
}
func PushTags(t *testing.T, r *git.Repository) {
t.Log("git push --tags")
err := r.Push(&git.PushOptions{
RemoteName: "origin",
RefSpecs: []config.RefSpec{"refs/tags/*:refs/tags/*"},
})
if err != nil {
if errors.Is(err, git.NoErrAlreadyUpToDate) {
return
}
require.NoError(t, err)
}
}
func CreateRemoteBranch(t *testing.T, r *git.Repository, branchName string) {
wt, err := r.Worktree()
require.NoError(t, err)
ref := plumbing.NewBranchReferenceName(branchName)
err = wt.Checkout(&git.CheckoutOptions{
Branch: ref,
Create: true,
})
require.NoError(t, err)
defer func() {
require.NoError(t, wt.Checkout(&git.CheckoutOptions{}))
}()
err = r.Push(&git.PushOptions{
RemoteName: "origin",
RefSpecs: []config.RefSpec{config.RefSpec(ref + ":" + ref)},
})
require.NoError(t, err)
}

36
internal/testutil/fs.go Normal file
View File

@@ -0,0 +1,36 @@
package testutil
import (
"os"
"path/filepath"
"testing"
"github.com/stretchr/testify/require"
"github.com/aquasecurity/trivy/pkg/utils/fsutils"
)
// CopyDir copies the directory content from src to dst.
// It supports only simple cases for testing.
func CopyDir(t *testing.T, src, dst string) {
srcInfo, err := os.Stat(src)
require.NoError(t, err)
err = os.MkdirAll(dst, srcInfo.Mode())
require.NoError(t, err)
entries, err := os.ReadDir(src)
require.NoError(t, err)
for _, entry := range entries {
srcPath := filepath.Join(src, entry.Name())
dstPath := filepath.Join(dst, entry.Name())
if entry.IsDir() {
CopyDir(t, srcPath, dstPath)
} else {
_, err = fsutils.CopyFile(srcPath, dstPath)
require.NoError(t, err)
}
}
}

View File

@@ -7,10 +7,11 @@ import (
"net/http/httptest"
"testing"
"github.com/sosedoff/gitkit"
"github.com/go-git/go-git/v5"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/aquasecurity/trivy/internal/gittest"
"github.com/aquasecurity/trivy/pkg/fanal/artifact"
"github.com/aquasecurity/trivy/pkg/fanal/cache"
"github.com/aquasecurity/trivy/pkg/fanal/walker"
@@ -19,26 +20,29 @@ import (
_ "github.com/aquasecurity/trivy/pkg/fanal/analyzer/secret"
)
func setupGitServer() (*httptest.Server, error) {
service := gitkit.New(gitkit.Config{
Dir: "./testdata",
AutoCreate: false,
})
func setupGitRepository(t *testing.T, repo, dir string) (*httptest.Server, *git.Repository) {
gs := gittest.NewServer(t, repo, dir)
if err := service.Setup(); err != nil {
return nil, err
}
worktree := t.TempDir()
r := gittest.Clone(t, gs, repo, worktree)
ts := httptest.NewServer(service)
// Branch
gittest.CreateRemoteBranch(t, r, "valid-branch")
return ts, nil
// Tag
gittest.SetTag(t, r, "v1.0.0")
gittest.PushTags(t, r)
return gs, r
}
func TestNewArtifact(t *testing.T) {
ts, err := setupGitServer()
require.NoError(t, err)
ts, repo := setupGitRepository(t, "test-repo", "testdata/test-repo")
defer ts.Close()
head, err := repo.Head()
require.NoError(t, err)
type args struct {
target string
c cache.ArtifactCache
@@ -55,7 +59,7 @@ func TestNewArtifact(t *testing.T) {
{
name: "remote repo",
args: args{
target: ts.URL + "/test.git",
target: ts.URL + "/test-repo.git",
c: nil,
noProgress: false,
},
@@ -71,9 +75,9 @@ func TestNewArtifact(t *testing.T) {
assertion: assert.NoError,
},
{
name: "happy noProgress",
name: "no progress",
args: args{
target: ts.URL + "/test.git",
target: ts.URL + "/test-repo.git",
c: nil,
noProgress: true,
},
@@ -82,7 +86,7 @@ func TestNewArtifact(t *testing.T) {
{
name: "branch",
args: args{
target: ts.URL + "/test.git",
target: ts.URL + "/test-repo.git",
c: nil,
repoBranch: "valid-branch",
},
@@ -91,7 +95,7 @@ func TestNewArtifact(t *testing.T) {
{
name: "tag",
args: args{
target: ts.URL + "/test.git",
target: ts.URL + "/test-repo.git",
c: nil,
repoTag: "v1.0.0",
},
@@ -100,9 +104,9 @@ func TestNewArtifact(t *testing.T) {
{
name: "commit",
args: args{
target: ts.URL + "/test.git",
target: ts.URL + "/test-repo.git",
c: nil,
repoCommit: "6ac152fe2b87cb5e243414df71790a32912e778d",
repoCommit: head.String(),
},
assertion: assert.NoError,
},
@@ -131,7 +135,7 @@ func TestNewArtifact(t *testing.T) {
{
name: "invalid branch",
args: args{
target: ts.URL + "/test.git",
target: ts.URL + "/test-repo.git",
c: nil,
repoBranch: "invalid-branch",
},
@@ -142,7 +146,7 @@ func TestNewArtifact(t *testing.T) {
{
name: "invalid tag",
args: args{
target: ts.URL + "/test.git",
target: ts.URL + "/test-repo.git",
c: nil,
repoTag: "v1.0.9",
},
@@ -153,7 +157,7 @@ func TestNewArtifact(t *testing.T) {
{
name: "invalid commit",
args: args{
target: ts.URL + "/test.git",
target: ts.URL + "/test-repo.git",
c: nil,
repoCommit: "6ac152fe2b87cb5e243414df71790a32912e778e",
},
@@ -178,8 +182,7 @@ func TestNewArtifact(t *testing.T) {
}
func TestArtifact_Inspect(t *testing.T) {
ts, err := setupGitServer()
require.NoError(t, err)
ts, _ := setupGitRepository(t, "test-repo", "testdata/test-repo")
defer ts.Close()
tests := []struct {
@@ -190,9 +193,9 @@ func TestArtifact_Inspect(t *testing.T) {
}{
{
name: "happy path",
rawurl: ts.URL + "/test.git",
rawurl: ts.URL + "/test-repo.git",
want: artifact.Reference{
Name: ts.URL + "/test.git",
Name: ts.URL + "/test-repo.git",
Type: artifact.TypeRepository,
ID: "sha256:6a89d4fcd50f840a79da64523c255da80171acd3d286df2acc60056c778d9304",
BlobIDs: []string{

View File

@@ -0,0 +1 @@
this is another text file.

View File

@@ -0,0 +1 @@
this is a text file.

View File

@@ -1 +0,0 @@
ref: refs/heads/master

View File

@@ -1,6 +0,0 @@
[core]
repositoryformatversion = 0
filemode = true
bare = true
ignorecase = true
precomposeunicode = true

View File

@@ -1,2 +0,0 @@
x<01><>Aj<41>0s<>+<2B><08><><EFBFBD><58> <09><>`,<2C>"<22><>^<5E>c<EFBFBD><63>G<EFBFBD><47> Ї<><D087><EFBFBD><EFBFBD>{<7B>M<EFBFBD>G<EFBFBD><47><EFBFBD>xb<78><1C>$<24>nZӄ3<07>d<EFBFBD><64><EFBFBD>V<EFBFBD><56><12>ul|<7C>]!rv<72><17><>Ly <09>'<27>W<>Q<EFBFBD><51>>9/D<>j<EFBFBD>Ժ<1F>Yϥr<CFA5><72><EFBFBD>h߼1\<5C><><EFBFBD>~<7E>un<75>[<5B><>
\ 4[<5B><11><><06>f<EFBFBD><66><EFBFBD><EFBFBD><1C><08><05><>'<27><>}<7D>:<3A>*?

View File

@@ -1,3 +0,0 @@
x<01><>K<EFBFBD><4B>0Dg<44>S<EFBFBD>><10><>B<>r<><72><EFBFBD>5Xqp<71>$<24>mr<6D>@-<2D><><EFBFBD>Qym<79>
<18>~dc6.<2E>@<40><>&*<2A>&˔<>O<EFBFBD><<3C><>l
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><1B><05>8<EFBFBD><38><1D>.S<12>c<>:<3A><><EFBFBD>%<1D><><EFBFBD>9*<2A>e^7<><37><EFBFBD>4c<34><63>e<EFBFBD>/\<10><>ǧ<EFBFBD>׿<EFBFBD>u9<75><39>]@<1F>Х#o<07>i*<2A><>CF9<46><39><EFBFBD> =<08>o<EFBFBD>RV<><56><EFBFBD>R<EFBFBD>

View File

@@ -1 +0,0 @@
0d8bf3f07c3970b3e38c2cfb1c619cb86fae76d2

View File

@@ -1 +0,0 @@
d7937c5f0ce7f2054e4e3be65ab3cd0f9462dc1b

View File

@@ -1 +0,0 @@
c906fc4a94762f8a2c77c718947143d16e4e9ec7

View File

@@ -14,11 +14,12 @@ import (
"testing"
"time"
"github.com/go-git/go-git/v5"
"github.com/google/go-containerregistry/pkg/v1"
"github.com/sosedoff/gitkit" // Not work on Windows
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/aquasecurity/trivy/internal/gittest"
"github.com/aquasecurity/trivy/pkg/clock"
ftypes "github.com/aquasecurity/trivy/pkg/fanal/types"
"github.com/aquasecurity/trivy/pkg/log"
@@ -26,24 +27,43 @@ import (
"github.com/aquasecurity/trivy/pkg/utils/fsutils"
)
func setupGitServer() (*httptest.Server, error) {
service := gitkit.New(gitkit.Config{
Dir: "./testdata",
AutoCreate: false,
})
func setupGitRepository(t *testing.T, repo, dir string) *httptest.Server {
gs := gittest.NewServer(t, repo, dir)
if err := service.Setup(); err != nil {
return nil, err
}
worktree := t.TempDir()
r := gittest.Clone(t, gs, repo, worktree)
ts := httptest.NewServer(service)
// git tag
gittest.SetTag(t, r, "v0.2.0")
return ts, nil
// git commit
modifyManifest(t, worktree, "0.3.0")
gittest.CommitAll(t, r, "bump up to 0.3.0")
err := r.Push(&git.PushOptions{})
require.NoError(t, err)
// git tag
gittest.SetTag(t, r, "v0.3.0")
// git push --tags
gittest.PushTags(t, r)
return gs
}
func modifyManifest(t *testing.T, worktree, version string) {
manifestPath := filepath.Join(worktree, "plugin.yaml")
b, err := os.ReadFile(manifestPath)
require.NoError(t, err)
b = bytes.ReplaceAll(b, []byte("0.2.0"), []byte(version))
err = os.WriteFile(manifestPath, b, 0644)
require.NoError(t, err)
}
func TestManager_Install(t *testing.T) {
gs, err := setupGitServer()
require.NoError(t, err)
gs := setupGitRepository(t, "test_plugin", "testdata/test_plugin")
t.Cleanup(gs.Close)
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
@@ -76,8 +96,8 @@ func TestManager_Install(t *testing.T) {
},
},
}
wantPluginWithVersion := wantPlugin
wantPluginWithVersion.Version = "0.1.0"
wantPluginWithGit := wantPlugin
wantPluginWithGit.Version = "0.3.0"
wantLogs := `2021-08-25T12:20:30Z INFO Installing the plugin... src="%s"
2021-08-25T12:20:30Z INFO Plugin successfully installed name="test_plugin" version="%s"
@@ -109,16 +129,16 @@ func TestManager_Install(t *testing.T) {
{
name: "git",
pluginName: "git::" + gs.URL + "/test_plugin.git",
want: wantPlugin,
want: wantPluginWithGit,
wantFile: ".trivy/plugins/test_plugin/test.sh",
wantLogs: fmt.Sprintf(wantLogs, "git::"+gs.URL+"/test_plugin.git", "0.2.0"),
wantLogs: fmt.Sprintf(wantLogs, "git::"+gs.URL+"/test_plugin.git", "0.3.0"),
},
{
name: "with version",
pluginName: "git::" + gs.URL + "/test_plugin.git@v0.1.0",
want: wantPluginWithVersion,
pluginName: "git::" + gs.URL + "/test_plugin.git@v0.2.0",
want: wantPlugin,
wantFile: ".trivy/plugins/test_plugin/test.sh",
wantLogs: fmt.Sprintf(wantLogs, "git::"+gs.URL+"/test_plugin.git", "0.1.0"),
wantLogs: fmt.Sprintf(wantLogs, "git::"+gs.URL+"/test_plugin.git", "0.2.0"),
},
{
name: "via index",

View File

@@ -1 +0,0 @@
ref: refs/heads/main

View File

@@ -1,8 +0,0 @@
[core]
repositoryformatversion = 0
filemode = true
bare = true
ignorecase = true
precomposeunicode = true
[remote "origin"]
url = /Users/teppei/src/github.com/aquasecurity/trivy/pkg/plugin/testdata/test_plugin

View File

@@ -1 +0,0 @@
Unnamed repository; edit this file 'description' to name the repository.

View File

@@ -1,6 +0,0 @@
# git ls-files --others --exclude-from=.git/info/exclude
# Lines that start with '#' are comments.
# For a project mostly in C, the following would be a good set of
# exclude patterns (uncomment them if you want to use them):
# *.[oa]
# *~

View File

@@ -1,3 +0,0 @@
xM<><4D>
<EFBFBD>0 <0C><><EFBFBD>S<EFBFBD><53>[7a}ɺ<>
<EFBFBD>#iE<69>޵(<28><>s<EFBFBD><73><EFBFBD>,>-0<><30>!b C!)<29><><EFBFBD><EFBFBD><EFBFBD>A1<41>$<24>$~h<> <0B><><08> <16><><EFBFBD><1B><><EFBFBD>AI

View File

@@ -1,4 +0,0 @@
# pack-refs with: peeled fully-peeled sorted
d78abde66b1d35bdac65402f0e2cddf3a96cd377 refs/heads/main
929b4718db99b64a38b4e8c3ec8e673976821c08 refs/tags/v0.1.0
d78abde66b1d35bdac65402f0e2cddf3a96cd377 refs/tags/v0.2.0