Skip to content

Commit

Permalink
rework git-related tests so they don't download code
Browse files Browse the repository at this point in the history
  • Loading branch information
mkisielewski-arista committed Jan 8, 2025
1 parent 385c0d2 commit 4a3212b
Show file tree
Hide file tree
Showing 2 changed files with 91 additions and 193 deletions.
19 changes: 10 additions & 9 deletions impl/create_srpm_from_git.go
Original file line number Diff line number Diff line change
Expand Up @@ -72,25 +72,21 @@ func cloneGitRepo(pkg, srcURL, revision, targetDir string, executor executor.Exe
return cloneDir, nil
}

func generateArchiveFile(targetDir, clonedDir, revision, repo, pkg string, isPkgSubdirInRepo bool,
func generateArchiveFile(targetDir, clonedDir, revision, repo, pkg string, parentFolder string,
errPrefix util.ErrPrefix, executor executor.Executor) (string, error) {
// User should ensure the same fileName is specified in .spec file.
// We use Source0.tar.gz as the generated tarball path,
// since this can be extended to support multiple sources in future.
gitArchiveFile := "Source0.tar.gz"
gitArchiveFilePath := filepath.Join(targetDir, gitArchiveFile)
parentFolder, err := getRpmNameFromSpecFile(repo, pkg, isPkgSubdirInRepo, executor)
if err != nil {
return "", err
}

// Create the tarball from the specified commit/tag revision
archiveCmd := []string{"archive",
"--prefix", parentFolder + "/",
"-o", gitArchiveFilePath,
revision,
}
err = executor.ExecInDir(clonedDir, "git", archiveCmd...)
err := executor.ExecInDir(clonedDir, "git", archiveCmd...)
if err != nil {
return "", fmt.Errorf("%sgit archive of %s failed: %s %v", errPrefix, pkg, err, archiveCmd)
}
Expand All @@ -106,7 +102,12 @@ func archiveGitRepo(srcURL, targetDir, revision, repo, pkg string, isPkgSubdirIn
return "", "", fmt.Errorf("cloning git repo failed: %s", err)
}

gitArchiveFile, err := generateArchiveFile(targetDir, cloneDir, revision, repo, pkg, isPkgSubdirInRepo, errPrefix, executor)
// parent folder should be the same as the RPM name
parentFolder, err := getRpmNameFromSpecFile(repo, pkg, isPkgSubdirInRepo, executor)
if err != nil {
return "", "", fmt.Errorf("getting RPM name from the spec failed: %s", err)
}
gitArchiveFile, err := generateArchiveFile(targetDir, cloneDir, revision, repo, pkg, parentFolder, errPrefix, executor)
if err != nil {
return "", "", fmt.Errorf("generating git archive failed: %s", err)
}
Expand Down Expand Up @@ -204,13 +205,13 @@ func verifyGitSignature(pubKeyPath string, gitSpec gitSpec, errPrefix util.ErrPr
}
defer os.Unsetenv("GNUPGHOME")

if err := executor.ExecInDir("gpg", "--fingerprint"); err != nil {
if err := executor.Exec("gpg", "--fingerprint"); err != nil {
return fmt.Errorf("%sError '%s'creating keyring",
errPrefix, err)
}

// Import public key
if err := executor.ExecInDir("gpg", "--import", pubKeyPath); err != nil {
if err := executor.Exec("gpg", "--import", pubKeyPath); err != nil {
return fmt.Errorf("%sError '%s' importing public-key %s",
errPrefix, err, pubKeyPath)
}
Expand Down
265 changes: 81 additions & 184 deletions impl/create_srpm_from_git_test.go
Original file line number Diff line number Diff line change
@@ -1,224 +1,121 @@
// Copyright (c) 2023 Arista Networks, Inc. All rights reserved.
// Arista Networks, Inc. Confidential and Proprietary.

//go:build containerized

package impl

import (
"fmt"
"io"
"net/http"
"os"
"path/filepath"
"strings"
"os/exec"
"testing"

"code.arista.io/eos/tools/eext/executor"
"code.arista.io/eos/tools/eext/util"
"github.com/spf13/viper"
"github.com/stretchr/testify/require"
//"code.arista.io/eos/tools/eext/executor/mocked_executor"
)

type TestDataType struct {
gitSpec *gitSpec
expectedValue string
}

// We are currently using a tarball of the libpcap repo, and extracting it in a temp folder.
// This ensures that we mock 'cloneGitRepo' and steps after are tested.
// If we migrate to a remote repo, we can use this function to update the url.
func getSrcURL() string {
url := "https://artifactory.infra.corp.arista.io/artifactory/eext-sources/eext-testData/libpcap.tar"
return url
}

func downloadTarball(url, targetDir string) (string, error) {
tarBallFilePath := filepath.Join(targetDir, "libpcap.tar")
out, err := os.Create(tarBallFilePath)
if err != nil {
return "", fmt.Errorf("failed to create file: %s", err)
}
defer out.Close()

resp, err := http.Get(url)
if err != nil {
return "", fmt.Errorf("failed to download file: %s", err)
}
defer resp.Body.Close()

if resp.StatusCode != http.StatusOK {
return "", fmt.Errorf("server returned: %s", resp.Status)
}
_, err = io.Copy(out, resp.Body)
if err != nil {
return "", fmt.Errorf("failed to write to file: %s", err)
}

return tarBallFilePath, nil
}

// Gets the .tar file from test repo, and untars it into the required git repo.
func cloneRepoFromUrl(url, targetDir string) (string, error) {
tarBallFilePath, err := downloadTarball(url, targetDir)
if err != nil {
return "", fmt.Errorf("failed to download tarball from %s: %s", url, err)
}

err = util.RunSystemCmdInDir(targetDir, "tar", "-xvf", tarBallFilePath)
if err != nil {
return "", fmt.Errorf("failed to extract tarball %s: %s", tarBallFilePath, err)
}

clonedDir := filepath.Join(targetDir, "libpcap")
fmt.Println(clonedDir)

// suppress git error 128 (dubious ownership)
user, err := util.CheckOutput("whoami", []string{}...)
if err != nil {
return "", fmt.Errorf("failed to get current user %s", err)
}
suppressCmdArgs := []string{"chown", "-R", strings.TrimSpace(user), clonedDir}
err = util.RunSystemCmd("sudo", suppressCmdArgs...)
if err != nil {
return "", fmt.Errorf("failed to suppress git warning %s", err)
}

return clonedDir, nil
}

// A mock function for cloneGitRepo().
// Since we do not use remote git repo, this function downloads a tarball from a test repo,
// and expands it to be used as though we have cloned the repo from git.
func cloneGitDir() (string, error) {
srcURL := getSrcURL()
tempDir, err := os.MkdirTemp("", "upstream-git-test")
if err != nil {
return "", fmt.Errorf("failed to create temp dir: %s", err)
}

clonedDir, err := cloneRepoFromUrl(srcURL, tempDir)
if err != nil {
return "", fmt.Errorf("failed to clone repo dir from source %s at %s: %s", srcURL, tempDir, err)
}

return clonedDir, nil
}

func populateTestData(cloneDir string, revisionList, expectedList []string) []*TestDataType {
// Not used in any tests currently, since we mock cloneGitRepo.
// Will be usefull for testing gitSpec.typeOfGitRevisionFromRemote.
srcURL := getSrcURL()

var dataList []*TestDataType
for i, revision := range revisionList {
gitSpec := &gitSpec{
SrcUrl: srcURL,
Revision: revision,
ClonedDir: cloneDir,
}
dataType := &TestDataType{
gitSpec: gitSpec,
expectedValue: expectedList[i],
}
dataList = append(dataList, dataType)
}

return dataList
}

func populateTestDataForRevision(cloneDir string) []*TestDataType {
revisionList := []string{"libpcap-1.10.4", "95691eb", "59747a7e74506bd2fbf6cc668e1d66b68ac6eb6d"}
expectedList := []string{"TAG", "COMMIT", "COMMIT"}

testData := populateTestData(cloneDir, revisionList, expectedList)

// Required for testing typeOfGitRevisionFromRemote()
// Keep disabled until we start using remote test data.
/*for i, data := range testData {
if i%2 == 0 {
data.gitSpec.ClonedDir = ""
}
}*/

return testData
}

func populateTestDataForGitSignature(cloneDir string) []*TestDataType {
// Yet to verify commit signatures,
// since not many commits signed with public keys are available.
revisionList := []string{"libpcap-1.10.1"}
expectedList := []string{""}

return populateTestData(cloneDir, revisionList, expectedList)
}

func TestRpmNameFromSpecFile(t *testing.T) {
viper.Set("SrcDir", "testData/")
defer viper.Reset()
pkg := "libpcap"
repo := "upstream-git-repo-1"
expectedRpmName := "libpcap-1.10.1"

gotRpmName, err := getRpmNameFromSpecFile(repo, pkg, false)
if err != nil {
t.Fatal(err)
mex := executor.MockedExecutor{
Responses: []executor.Response{executor.NewResponse(0, "libpcap-1.10.1", nil)},
}

require.Equal(t, expectedRpmName, gotRpmName)
t.Log("Test rpmNameFromSpecFile PASSED")
}

func TestVerifyGitSignature(t *testing.T) {
cloneDir, err := cloneGitDir()
gotRpmName, err := getRpmNameFromSpecFile(repo, pkg, false, &mex)
if err != nil {
t.Fatal(err)
}
defer os.RemoveAll(cloneDir)

viper.Set("PkiPath", "../pki")
defer viper.Reset()
pubKeyPath := filepath.Join(getDetachedSigDir(), "tcpdump/tcpdumpPubKey.pem")
testData := populateTestDataForGitSignature(cloneDir)
for _, data := range testData {
gitSpec := data.gitSpec
if expectedRpmName != gotRpmName {
t.Fatalf("TestRpmNameFromSpecFile test failed. Expected: %s, Got %s",
expectedRpmName, gotRpmName)

err := verifyGitSignature(pubKeyPath, *gitSpec, "")
if err != nil {
t.Fatal(err)
}
}
t.Log("Test verifyGitRepoSignature PASSED")
t.Log("Test rpmNameFromSpecFile PASSED")
}

func TestGitArchive(t *testing.T) {
clonedDir, err := cloneGitDir()
if err != nil {
t.Fatal(err)
}
defer os.RemoveAll(clonedDir)

testWorkingDir, mkdirErr := os.MkdirTemp("", "upstream-git")
if mkdirErr != nil {
t.Fatal(mkdirErr)
}
defer os.RemoveAll(testWorkingDir)

viper.Set("SrcDir", "testData/")
defer viper.Reset()
clonedDir := "/tmp/fake-cloned-dir"
testWorkingDir := "/tmp/fake-working-dir"
pkg := "libpcap"
repo := "upstream-git-repo-1"
revision := "libpcap-1.10.1"

archiveFile, err := generateArchiveFile(testWorkingDir, clonedDir, revision, repo, pkg, false, "")
if err != nil {
t.Fatal(err)
parentFolder := "libpcap-1.10.1"
mex := executor.MockedExecutor{
Responses: []executor.Response{executor.NewResponse(0, "libpcap-1.10.1", nil)},
}

archivePath := filepath.Join(testWorkingDir, archiveFile)
err = util.CheckPath(archivePath, false, false)
_, err := generateArchiveFile(testWorkingDir, clonedDir, revision, repo, pkg, parentFolder, "", &mex)
if err != nil {
t.Fatal(err)
}
expectedCall := executor.NewRecordedCall("/tmp/fake-cloned-dir", "git",
[]string{"archive", "--prefix", "libpcap-1.10.1/", "-o", "/tmp/fake-working-dir/Source0.tar.gz", "libpcap-1.10.1"})
//expected := "In the directory '/tmp/fake-cloned-dir', would execute: git archive --prefix libpcap-1.10.1/ -o /tmp/fake-working-dir/Source0.tar.gz libpcap-1.10.1"
actual := mex.Calls[0]
if !mex.HasCall(expectedCall) {
t.Fatalf("generateArchiveFile executed an unexpected command.\nExpected:\n%s\nActual:\n%s", expectedCall, actual)
}

t.Log("Test gitArchive PASSED")
}

func TestVerifyGitSignatureRevIsTagPassing(t *testing.T) {
spec := gitSpec{
SrcUrl: "http://example.com",
Revision: "A-tag",
ClonedDir: "/tmp/verification-dir",
}
pubKeyPath := "/tmp/pubkey"
mex := executor.MockedExecutor{
Responses: []executor.Response{
executor.NewResponse(0, "", nil), // for gpg --fingerprint
executor.NewResponse(0, "", nil), // for gpg --import
executor.NewResponse(0, spec.Revision, nil), // for git show-ref
executor.NewResponse(0, "", nil), // for git verify-tag
},
}

verifyGitSignature(pubKeyPath, spec, util.ErrPrefix(""), &mex)
expectedCalls := []executor.RecordedCall{
executor.NewRecordedCall("", "gpg", []string{"--fingerprint"}),
executor.NewRecordedCall("", "gpg", []string{"--import", pubKeyPath}),
executor.NewRecordedCall(spec.ClonedDir, "git", []string{"show-ref", "--quiet", "--tags", spec.Revision}),
executor.NewRecordedCall(spec.ClonedDir, "git", []string{"verify-tag", "-v", spec.Revision}),
}
if !mex.HasExactCalls(expectedCalls) {
t.Fatalf("verifyGitSignature executed wrong commands.\nExpected:\n%v\nActual:\n%v", expectedCalls, mex.Calls)
}
}

func TestVerifyGitSignatureRevIsCommitPassing(t *testing.T) {
spec := gitSpec{
SrcUrl: "http://example.com",
Revision: "A-tag",
ClonedDir: "/tmp/verification-dir",
}
pubKeyPath := "/tmp/pubkey"
mex := executor.MockedExecutor{
Responses: []executor.Response{
executor.NewResponse(0, "", nil), // for gpg --fingerprint
executor.NewResponse(0, "", nil), // for gpg --import
executor.NewResponse(1, "", &exec.ExitError{}), // for git show-ref
executor.NewResponse(0, "", nil), // for git cat-file
executor.NewResponse(0, "", nil), // for git verify-commit
},
}

verifyGitSignature(pubKeyPath, spec, util.ErrPrefix(""), &mex)
expectedCalls := []executor.RecordedCall{
executor.NewRecordedCall("", "gpg", []string{"--fingerprint"}),
executor.NewRecordedCall("", "gpg", []string{"--import", pubKeyPath}),
executor.NewRecordedCall(spec.ClonedDir, "git", []string{"show-ref", "--quiet", "--tags", spec.Revision}),
executor.NewRecordedCall(spec.ClonedDir, "git", []string{"cat-file", "-e", spec.Revision}),
executor.NewRecordedCall(spec.ClonedDir, "git", []string{"verify-commit", "-v", spec.Revision}),
}
if !mex.HasExactCalls(expectedCalls) {
t.Fatalf("verifyGitSignature executed wrong commands.\nExpected:\n%v\nActual:\n%v", expectedCalls, mex.Calls)
}
}

0 comments on commit 4a3212b

Please sign in to comment.