mirror of
https://github.com/aquasecurity/trivy.git
synced 2025-12-05 20:40:16 -08:00
test: replace embedded Git repository with dynamically created repository (#6824)
Signed-off-by: knqyf263 <knqyf263@gmail.com>
This commit is contained in:
132
internal/gittest/server.go
Normal file
132
internal/gittest/server.go
Normal 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
36
internal/testutil/fs.go
Normal 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)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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{
|
||||
|
||||
1
pkg/fanal/artifact/repo/testdata/test-repo/anothertest.txt
vendored
Normal file
1
pkg/fanal/artifact/repo/testdata/test-repo/anothertest.txt
vendored
Normal file
@@ -0,0 +1 @@
|
||||
this is another text file.
|
||||
1
pkg/fanal/artifact/repo/testdata/test-repo/test.txt
vendored
Normal file
1
pkg/fanal/artifact/repo/testdata/test-repo/test.txt
vendored
Normal file
@@ -0,0 +1 @@
|
||||
this is a text file.
|
||||
@@ -1 +0,0 @@
|
||||
ref: refs/heads/master
|
||||
@@ -1,6 +0,0 @@
|
||||
[core]
|
||||
repositoryformatversion = 0
|
||||
filemode = true
|
||||
bare = true
|
||||
ignorecase = true
|
||||
precomposeunicode = true
|
||||
@@ -1,2 +0,0 @@
|
||||
x<01><>Aj<41>0s<>+<2B><08><><EFBFBD>X˲<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>h1\<5C><><EFBFBD>~<7E>un<75>[<5B><>
|
||||
\4[<5B><11><><06>f<EFBFBD><66><EFBFBD><EFBFBD><1C><08><05><>'<27><>}<7D>:<3A>*?
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -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>
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -1 +0,0 @@
|
||||
0d8bf3f07c3970b3e38c2cfb1c619cb86fae76d2
|
||||
@@ -1 +0,0 @@
|
||||
d7937c5f0ce7f2054e4e3be65ab3cd0f9462dc1b
|
||||
@@ -1 +0,0 @@
|
||||
c906fc4a94762f8a2c77c718947143d16e4e9ec7
|
||||
@@ -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",
|
||||
|
||||
1
pkg/plugin/testdata/test_plugin.git/HEAD
vendored
1
pkg/plugin/testdata/test_plugin.git/HEAD
vendored
@@ -1 +0,0 @@
|
||||
ref: refs/heads/main
|
||||
8
pkg/plugin/testdata/test_plugin.git/config
vendored
8
pkg/plugin/testdata/test_plugin.git/config
vendored
@@ -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
|
||||
@@ -1 +0,0 @@
|
||||
Unnamed repository; edit this file 'description' to name the repository.
|
||||
@@ -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]
|
||||
# *~
|
||||
Binary file not shown.
@@ -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
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -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
|
||||
Reference in New Issue
Block a user