1
0
mirror of https://github.com/SAP/jenkins-library.git synced 2024-12-14 11:03:09 +02:00
sap-jenkins-library/pkg/codeql/github_repo_upload_test.go
Daria Kuznetsova 439a7ad82e
fix(codeqlExecuteScan): init empty GitHub repo before mirroring code (#4714)
* added initializing empty repo

* updated go.mod

* updated go.mod

* updated go.sum

* updated go.mod

* updated go.mod

* updated go.mod

---------

Co-authored-by: sumeet patil <sumeet.patil@sap.com>
2023-12-21 11:20:44 +03:00

428 lines
10 KiB
Go

package codeql
import (
"archive/zip"
"fmt"
"io"
"os"
"path"
"path/filepath"
"strings"
"testing"
"github.com/go-git/go-git/v5"
"github.com/go-git/go-git/v5/plumbing"
"github.com/go-git/go-git/v5/plumbing/object"
"github.com/stretchr/testify/assert"
"gopkg.in/yaml.v2"
"k8s.io/utils/strings/slices"
)
const (
notExists = "not-exists"
exists = "exists"
refsHeads = "refs/heads/"
)
type gitMock struct {
ref string
url string
}
func newGitMock(ref, url string) *gitMock {
return &gitMock{ref: ref, url: url}
}
func (g *gitMock) listRemote() ([]reference, error) {
if g.url == notExists {
return nil, fmt.Errorf("repository not found")
}
list := []*referenceMock{
{
name: refsHeads + "ref1",
},
{
name: refsHeads + "ref2",
},
{
name: refsHeads + "ref3",
},
{
name: refsHeads + exists,
},
}
var convertedList []reference
for _, ref := range list {
convertedList = append(convertedList, ref)
}
return convertedList, nil
}
func (g *gitMock) cloneRepo(dir string, opts *git.CloneOptions) (*git.Repository, error) {
if opts.Auth == nil {
return nil, fmt.Errorf("error")
}
if opts.URL == notExists {
return nil, fmt.Errorf("error")
}
return &git.Repository{}, nil
}
func (g *gitMock) switchOrphan(branch string, repo *git.Repository) error {
return nil
}
func (g *gitMock) initRepo(dir string) (*git.Repository, error) {
return &git.Repository{}, nil
}
type referenceMock struct {
name string
}
func (r *referenceMock) Name() plumbing.ReferenceName {
return plumbing.ReferenceName(r.name)
}
type repoMock struct{}
func (r *repoMock) Worktree() (*git.Worktree, error) {
return &git.Worktree{}, nil
}
func (r *repoMock) CommitObject(commit plumbing.Hash) (*object.Commit, error) {
return &object.Commit{Hash: commit}, nil
}
func (r *repoMock) Push(opts *git.PushOptions) error {
if opts.Auth == nil {
return fmt.Errorf("error")
}
return nil
}
type worktreeMock struct{}
func (t *worktreeMock) RemoveGlob(pattern string) error {
return nil
}
func (t *worktreeMock) Clean(opts *git.CleanOptions) error {
return nil
}
func (t *worktreeMock) AddWithOptions(opts *git.AddOptions) error {
return nil
}
func (t *worktreeMock) Commit(msg string, opts *git.CommitOptions) (plumbing.Hash, error) {
if opts.Author == nil {
return plumbing.Hash{}, fmt.Errorf("error")
}
return plumbing.Hash{}, nil
}
func TestDoesRefExist(t *testing.T) {
t.Parallel()
t.Run("Invalid repository", func(t *testing.T) {
ghUploader := newGitMock(refsHeads+notExists, notExists)
_, _, err := doesRefExist(ghUploader, refsHeads+notExists)
assert.Error(t, err)
})
t.Run("Ref exists", func(t *testing.T) {
ghUploader := newGitMock(refsHeads+exists, exists)
ok, _, err := doesRefExist(ghUploader, refsHeads+exists)
assert.NoError(t, err)
assert.True(t, ok)
})
t.Run("Ref doesn't exist", func(t *testing.T) {
ghUploader := newGitMock(refsHeads+notExists, exists)
ok, _, err := doesRefExist(ghUploader, refsHeads+notExists)
assert.NoError(t, err)
assert.False(t, ok)
})
}
func TestClone(t *testing.T) {
t.Parallel()
t.Run("Created new branch", func(t *testing.T) {
ghUploader := newGitMock(refsHeads+notExists, exists)
repo, err := clone(ghUploader, ghUploader.url, "", ghUploader.ref, "", false, false)
assert.NoError(t, err)
assert.NotNil(t, repo)
})
t.Run("Target branch exists", func(t *testing.T) {
ghUploader := newGitMock(refsHeads+exists, exists)
repo, err := clone(ghUploader, ghUploader.url, "", ghUploader.ref, "", false, true)
assert.NoError(t, err)
assert.NotNil(t, repo)
})
t.Run("Repo was empty", func(t *testing.T) {
ghUploader := newGitMock(refsHeads+exists, exists)
repo, err := clone(ghUploader, ghUploader.url, "", ghUploader.ref, "", true, false)
assert.NoError(t, err)
assert.NotNil(t, repo)
})
}
func TestClean(t *testing.T) {
t.Parallel()
t.Run("Success", func(t *testing.T) {
tree := &worktreeMock{}
err := cleanDir(tree)
assert.NoError(t, err)
})
}
func TestAdd(t *testing.T) {
t.Run("Success", func(t *testing.T) {
tree := &worktreeMock{}
err := add(tree)
assert.NoError(t, err)
})
}
func TestCommit(t *testing.T) {
t.Run("Success", func(t *testing.T) {
tree := &worktreeMock{}
repo := &repoMock{}
c, err := commit(repo, tree, "", "")
assert.NoError(t, err)
assert.NotNil(t, c)
})
}
func TestPush(t *testing.T) {
t.Run("Success", func(t *testing.T) {
repo := &repoMock{}
err := push(repo, "")
assert.NoError(t, err)
})
}
func TestUnzip(t *testing.T) {
t.Parallel()
t.Run("Success", func(t *testing.T) {
targetDir, err := os.MkdirTemp("", "tmp_target")
if err != nil {
panic(err)
}
defer os.RemoveAll(targetDir)
sourceDir, err := os.MkdirTemp("", "tmp_source")
if err != nil {
panic(err)
}
defer os.RemoveAll(sourceDir)
zipPath := filepath.Join(sourceDir, "src.zip")
srcFilenames := []string{
filepath.Join(sourceDir, "file1"),
filepath.Join(sourceDir, "file2"),
filepath.Join(sourceDir, "codeqlDB"),
filepath.Join(sourceDir, "subfolder1", "file1"),
filepath.Join(sourceDir, "subfolder1", "file2"),
filepath.Join(sourceDir, "subfolder2", "file1"),
}
err = createZIP(zipPath, srcFilenames)
if err != nil {
panic(err)
}
assert.NoError(t, unzip(zipPath, targetDir, sourceDir, "codeqlDB"))
targetFilenames := []string{
filepath.Join(targetDir, "file1"),
filepath.Join(targetDir, "file2"),
filepath.Join(targetDir, "subfolder1", "file1"),
filepath.Join(targetDir, "subfolder1", "file2"),
filepath.Join(targetDir, "subfolder2", "file1"),
}
checkExistedFiles(t, targetDir, targetFilenames)
})
t.Run("Empty zip", func(t *testing.T) {
targetDir, err := os.MkdirTemp("", "tmp_target")
if err != nil {
panic(err)
}
defer os.RemoveAll(targetDir)
sourceDir, err := os.MkdirTemp("", "tmp_source")
if err != nil {
panic(err)
}
defer os.RemoveAll(sourceDir)
zipPath := filepath.Join(sourceDir, "src.zip")
filenames := []string{}
err = createZIP(zipPath, filenames)
if err != nil {
panic(err)
}
assert.NoError(t, unzip(zipPath, targetDir, sourceDir, "codeqlDB"))
checkExistedFiles(t, targetDir, filenames)
})
t.Run("zip not found", func(t *testing.T) {
targetDir, err := os.MkdirTemp("", "tmp_target")
if err != nil {
panic(err)
}
defer os.RemoveAll(targetDir)
sourceDir, err := os.MkdirTemp("", "tmp_source")
if err != nil {
panic(err)
}
defer os.RemoveAll(sourceDir)
zipPath := filepath.Join(sourceDir, "src.zip")
assert.Error(t, unzip(zipPath, targetDir, sourceDir, "codeqlDB"))
})
t.Run("extra files in zip", func(t *testing.T) {
targetDir, err := os.MkdirTemp("", "tmp_target")
if err != nil {
panic(err)
}
defer os.RemoveAll(targetDir)
sourceDir, err := os.MkdirTemp("", "tmp_source")
if err != nil {
panic(err)
}
defer os.RemoveAll(sourceDir)
zipPath := filepath.Join(sourceDir, "src.zip")
srcFilenames := []string{
filepath.Join(sourceDir, "file1"),
filepath.Join(sourceDir, "file2"),
filepath.Join(sourceDir, "subfolder1", "file1"),
filepath.Join(sourceDir, "subfolder1", "file2"),
filepath.Join(sourceDir, "subfolder2", "file1"),
filepath.Join(targetDir, "extrafile1"),
filepath.Join(targetDir, "extrafile2"),
filepath.Join(targetDir, "subfolder1", "extrafile1"),
}
err = createZIP(zipPath, srcFilenames)
if err != nil {
panic(err)
}
assert.NoError(t, unzip(zipPath, targetDir, sourceDir, "codeqlDB"))
targetFilenames := []string{
filepath.Join(targetDir, "file1"),
filepath.Join(targetDir, "file2"),
filepath.Join(targetDir, "subfolder1", "file1"),
filepath.Join(targetDir, "subfolder1", "file2"),
filepath.Join(targetDir, "subfolder2", "file1"),
}
checkExistedFiles(t, targetDir, targetFilenames)
})
}
func TestGetSourceLocationPrefix(t *testing.T) {
t.Parallel()
t.Run("Success", func(t *testing.T) {
filename := "test-file.yml"
location := "/some/location"
err := createFile(filename, location, false)
assert.NoError(t, err)
defer os.Remove(filename)
srcLocationPrefix, err := getSourceLocationPrefix(filename)
assert.NoError(t, err)
assert.Equal(t, location, srcLocationPrefix)
})
t.Run("No file found", func(t *testing.T) {
filename := "test-file-2.yml"
_, err := getSourceLocationPrefix(filename)
assert.Error(t, err)
})
t.Run("Empty file", func(t *testing.T) {
filename := "test-file-3.yml"
err := createFile(filename, "", true)
assert.NoError(t, err)
defer os.Remove(filename)
srcLocationPrefix, err := getSourceLocationPrefix(filename)
assert.NoError(t, err)
assert.Empty(t, srcLocationPrefix)
})
}
func checkExistedFiles(t *testing.T, dir string, filenames []string) {
counter := 0
err := filepath.Walk(dir, func(path string, info os.FileInfo, err error) error {
if err != nil {
return err
}
if path == dir || info.IsDir() {
return nil
}
assert.True(t, slices.Contains(filenames, path))
counter++
return nil
})
assert.NoError(t, err)
assert.Equal(t, len(filenames), counter)
}
func createZIP(zipPath string, filenames []string) error {
archive, err := os.Create(zipPath)
if err != nil {
return err
}
defer archive.Close()
zipWriter := zip.NewWriter(archive)
defer zipWriter.Close()
for _, filename := range filenames {
writer, err := zipWriter.Create(filename)
if err != nil {
return err
}
reader := strings.NewReader("test content\n")
if _, err := io.Copy(writer, reader); err != nil {
return err
}
}
return nil
}
func createFile(fileName, location string, isEmpty bool) error {
err := ensureBaseDir(fileName)
if err != nil {
return err
}
f, err := os.OpenFile(fileName, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, os.ModePerm)
if err != nil {
return err
}
defer f.Close()
if isEmpty {
return nil
}
type codeqlDatabase struct {
SourceLocation string `yaml:"sourceLocationPrefix"`
OtherInfo string `yaml:"otherInfo"`
}
db := codeqlDatabase{SourceLocation: location, OtherInfo: "test"}
data, err := yaml.Marshal(db)
if err != nil {
return err
}
_, err = f.Write(data)
return err
}
func ensureBaseDir(fpath string) error {
baseDir := path.Dir(fpath)
info, err := os.Stat(baseDir)
if err == nil && info.IsDir() {
return nil
}
return os.MkdirAll(baseDir, 0755)
}