mirror of
https://github.com/SAP/jenkins-library.git
synced 2025-01-16 05:16:08 +02:00
Enhance piperutils.Files and mock.FilesMock (#1664)
* Flesh out piperutils.Files and mock.FilesMock functionality * Avoid a lot of code-duplication via embedding
This commit is contained in:
parent
4e73a699c2
commit
f855658e06
@ -25,7 +25,7 @@ func TestMavenBuild(t *testing.T) {
|
||||
execMockRunner := mock.ExecMockRunner{}
|
||||
|
||||
mockedUtils := mock.FilesMock{}
|
||||
mockedUtils.Files = []string{"integration-tests/pom.xml"}
|
||||
mockedUtils.AddFile("integration-tests/pom.xml", []byte{})
|
||||
|
||||
config := mavenBuildOptions{}
|
||||
|
||||
|
@ -2,7 +2,6 @@ package cmd
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/bmatcuk/doublestar"
|
||||
"github.com/pkg/errors"
|
||||
"os"
|
||||
"path/filepath"
|
||||
@ -23,82 +22,44 @@ import (
|
||||
// nexusUploadUtils defines an interface for utility functionality used from external packages,
|
||||
// so it can be easily mocked for testing.
|
||||
type nexusUploadUtils interface {
|
||||
fileExists(path string) (bool, error)
|
||||
fileRead(path string) ([]byte, error)
|
||||
fileWrite(path string, content []byte, perm os.FileMode) error
|
||||
fileRemove(path string)
|
||||
dirExists(path string) (bool, error)
|
||||
usesMta() bool
|
||||
usesMaven() bool
|
||||
usesNpm() bool
|
||||
FileExists(path string) (bool, error)
|
||||
FileRead(path string) ([]byte, error)
|
||||
FileWrite(path string, content []byte, perm os.FileMode) error
|
||||
FileRemove(path string) error
|
||||
DirExists(path string) (bool, error)
|
||||
Glob(pattern string) (matches []string, err error)
|
||||
|
||||
UsesMta() bool
|
||||
UsesMaven() bool
|
||||
UsesNpm() bool
|
||||
|
||||
getEnvParameter(path, name string) string
|
||||
getExecRunner() execRunner
|
||||
evaluate(options *maven.EvaluateOptions, expression string) (string, error)
|
||||
glob(pattern string) (matches []string, err error)
|
||||
}
|
||||
|
||||
type utilsBundle struct {
|
||||
projectStructure piperutils.ProjectStructure
|
||||
fileUtils piperutils.Files
|
||||
execRunner *command.Command
|
||||
*piperutils.ProjectStructure
|
||||
*piperutils.Files
|
||||
execRunner *command.Command
|
||||
}
|
||||
|
||||
func newUtilsBundle() *utilsBundle {
|
||||
return &utilsBundle{
|
||||
projectStructure: piperutils.ProjectStructure{},
|
||||
fileUtils: piperutils.Files{},
|
||||
ProjectStructure: &piperutils.ProjectStructure{},
|
||||
Files: &piperutils.Files{},
|
||||
}
|
||||
}
|
||||
|
||||
func (u *utilsBundle) fileExists(path string) (bool, error) {
|
||||
return u.fileUtils.FileExists(path)
|
||||
}
|
||||
|
||||
func (u *utilsBundle) fileRead(path string) ([]byte, error) {
|
||||
return u.fileUtils.FileRead(path)
|
||||
}
|
||||
|
||||
func (u *utilsBundle) fileWrite(filePath string, content []byte, perm os.FileMode) error {
|
||||
func (u *utilsBundle) FileWrite(filePath string, content []byte, perm os.FileMode) error {
|
||||
parent := filepath.Dir(filePath)
|
||||
if parent != "" {
|
||||
err := u.fileUtils.MkdirAll(parent, 0775)
|
||||
err := u.Files.MkdirAll(parent, 0775)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return u.fileUtils.FileWrite(filePath, content, perm)
|
||||
}
|
||||
|
||||
func (u *utilsBundle) fileRemove(path string) {
|
||||
err := os.Remove(path)
|
||||
if err != nil {
|
||||
log.Entry().WithError(err).Warnf("Failed to remove file '%s'.", path)
|
||||
}
|
||||
}
|
||||
|
||||
func (u *utilsBundle) dirExists(path string) (bool, error) {
|
||||
info, err := os.Stat(path)
|
||||
|
||||
if os.IsNotExist(err) {
|
||||
return false, nil
|
||||
}
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
return info.IsDir(), nil
|
||||
}
|
||||
|
||||
func (u *utilsBundle) usesMta() bool {
|
||||
return u.projectStructure.UsesMta()
|
||||
}
|
||||
|
||||
func (u *utilsBundle) usesMaven() bool {
|
||||
return u.projectStructure.UsesMaven()
|
||||
}
|
||||
|
||||
func (u *utilsBundle) usesNpm() bool {
|
||||
return u.projectStructure.UsesNpm()
|
||||
return u.Files.FileWrite(filePath, content, perm)
|
||||
}
|
||||
|
||||
func (u *utilsBundle) getEnvParameter(path, name string) string {
|
||||
@ -118,10 +79,6 @@ func (u *utilsBundle) evaluate(options *maven.EvaluateOptions, expression string
|
||||
return maven.Evaluate(options, expression, u.getExecRunner())
|
||||
}
|
||||
|
||||
func (u *utilsBundle) glob(pattern string) (matches []string, err error) {
|
||||
return doublestar.Glob(pattern)
|
||||
}
|
||||
|
||||
func nexusUpload(options nexusUploadOptions, _ *telemetry.CustomData) {
|
||||
utils := newUtilsBundle()
|
||||
uploader := nexus.Upload{}
|
||||
@ -140,7 +97,7 @@ func runNexusUpload(utils nexusUploadUtils, uploader nexus.Uploader, options *ne
|
||||
return err
|
||||
}
|
||||
|
||||
if utils.usesNpm() && performNpmUpload {
|
||||
if utils.UsesNpm() && performNpmUpload {
|
||||
log.Entry().Info("NPM project structure detected")
|
||||
err = uploadNpmArtifacts(utils, uploader, options)
|
||||
} else {
|
||||
@ -151,10 +108,10 @@ func runNexusUpload(utils nexusUploadUtils, uploader nexus.Uploader, options *ne
|
||||
}
|
||||
|
||||
if performMavenUpload {
|
||||
if utils.usesMta() {
|
||||
if utils.UsesMta() {
|
||||
log.Entry().Info("MTA project structure detected")
|
||||
return uploadMTA(utils, uploader, options)
|
||||
} else if utils.usesMaven() {
|
||||
} else if utils.UsesMaven() {
|
||||
log.Entry().Info("Maven project structure detected")
|
||||
return uploadMaven(utils, uploader, options)
|
||||
}
|
||||
@ -184,7 +141,7 @@ func uploadMTA(utils nexusUploadUtils, uploader nexus.Uploader, options *nexusUp
|
||||
return fmt.Errorf("the 'groupId' parameter needs to be provided for MTA projects")
|
||||
}
|
||||
var mtaPath string
|
||||
exists, _ := utils.fileExists("mta.yaml")
|
||||
exists, _ := utils.FileExists("mta.yaml")
|
||||
if exists {
|
||||
mtaPath = "mta.yaml"
|
||||
// Give this file precedence, but it would be even better if
|
||||
@ -223,7 +180,7 @@ type mtaYaml struct {
|
||||
}
|
||||
|
||||
func getInfoFromMtaFile(utils nexusUploadUtils, filePath string) (*mtaYaml, error) {
|
||||
mtaYamlContent, err := utils.fileRead(filePath)
|
||||
mtaYamlContent, err := utils.FileRead(filePath)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("could not read from required project descriptor file '%s'",
|
||||
filePath)
|
||||
@ -273,7 +230,7 @@ func setupNexusCredentialsSettingsFile(utils nexusUploadUtils, options *nexusUpl
|
||||
return "", nil
|
||||
}
|
||||
|
||||
err := utils.fileWrite(settingsPath, []byte(nexusMavenSettings), os.ModePerm)
|
||||
err := utils.FileWrite(settingsPath, []byte(nexusMavenSettings), os.ModePerm)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("failed to write maven settings file to '%s': %w", settingsPath, err)
|
||||
}
|
||||
@ -322,7 +279,7 @@ func uploadArtifacts(utils nexusUploadUtils, uploader nexus.Uploader, options *n
|
||||
return fmt.Errorf("writing credential settings for maven failed: %w", err)
|
||||
}
|
||||
if settingsFile != "" {
|
||||
defer utils.fileRemove(settingsFile)
|
||||
defer func() { _ = utils.FileRemove(settingsFile) }()
|
||||
}
|
||||
|
||||
// iterate over the artifact descriptions, the first one is the main artifact, the following ones are
|
||||
@ -385,7 +342,7 @@ func uploadArtifactsBundle(d artifactDefines, generatePOM bool, mavenOptions mav
|
||||
}
|
||||
|
||||
func addArtifact(utils nexusUploadUtils, uploader nexus.Uploader, filePath, classifier, fileType string) error {
|
||||
exists, _ := utils.fileExists(filePath)
|
||||
exists, _ := utils.FileExists(filePath)
|
||||
if !exists {
|
||||
return fmt.Errorf("artifact file not found '%s'", filePath)
|
||||
}
|
||||
@ -400,7 +357,7 @@ func addArtifact(utils nexusUploadUtils, uploader nexus.Uploader, filePath, clas
|
||||
var errPomNotFound = errors.New("pom.xml not found")
|
||||
|
||||
func uploadMaven(utils nexusUploadUtils, uploader nexus.Uploader, options *nexusUploadOptions) error {
|
||||
pomFiles, _ := utils.glob("**/pom.xml")
|
||||
pomFiles, _ := utils.Glob("**/pom.xml")
|
||||
if len(pomFiles) == 0 {
|
||||
return errPomNotFound
|
||||
}
|
||||
@ -434,7 +391,7 @@ func uploadMavenArtifacts(utils nexusUploadUtils, uploader nexus.Uploader, optio
|
||||
}
|
||||
if packaging != "pom" {
|
||||
// Ignore this module if there is no 'target' folder
|
||||
hasTarget, _ := utils.dirExists(targetFolder)
|
||||
hasTarget, _ := utils.DirExists(targetFolder)
|
||||
if !hasTarget {
|
||||
log.Entry().Warnf("Ignoring module '%s' as it has no 'target' folder", pomPath)
|
||||
return nil
|
||||
@ -481,7 +438,7 @@ func addMavenTargetArtifacts(utils nexusUploadUtils, uploader nexus.Uploader, po
|
||||
|
||||
for _, fileType := range fileTypes {
|
||||
pattern := targetFolder + "/*." + fileType
|
||||
matches, _ := utils.glob(pattern)
|
||||
matches, _ := utils.Glob(pattern)
|
||||
if len(matches) == 0 && fileType == packaging {
|
||||
return fmt.Errorf("target artifact not found for packaging '%s'", packaging)
|
||||
}
|
||||
|
@ -5,85 +5,39 @@ import (
|
||||
"github.com/SAP/jenkins-library/pkg/maven"
|
||||
"github.com/SAP/jenkins-library/pkg/mock"
|
||||
"github.com/SAP/jenkins-library/pkg/nexus"
|
||||
"github.com/bmatcuk/doublestar"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"sort"
|
||||
"testing"
|
||||
)
|
||||
|
||||
type mockUtilsBundle struct {
|
||||
mta bool
|
||||
maven bool
|
||||
npm bool
|
||||
files map[string][]byte
|
||||
removedFiles map[string][]byte
|
||||
properties map[string]map[string]string
|
||||
cpe map[string]string
|
||||
execRunner mock.ExecMockRunner
|
||||
*mock.FilesMock
|
||||
mta bool
|
||||
maven bool
|
||||
npm bool
|
||||
properties map[string]map[string]string
|
||||
cpe map[string]string
|
||||
execRunner mock.ExecMockRunner
|
||||
}
|
||||
|
||||
func newMockUtilsBundle(usesMta, usesMaven, usesNpm bool) mockUtilsBundle {
|
||||
utils := mockUtilsBundle{mta: usesMta, maven: usesMaven, npm: usesNpm}
|
||||
utils.files = map[string][]byte{}
|
||||
utils.removedFiles = map[string][]byte{}
|
||||
utils := mockUtilsBundle{FilesMock: &mock.FilesMock{}, mta: usesMta, maven: usesMaven, npm: usesNpm}
|
||||
utils.properties = map[string]map[string]string{}
|
||||
utils.cpe = map[string]string{}
|
||||
return utils
|
||||
}
|
||||
|
||||
func (m *mockUtilsBundle) usesMta() bool {
|
||||
func (m *mockUtilsBundle) UsesMta() bool {
|
||||
return m.mta
|
||||
}
|
||||
|
||||
func (m *mockUtilsBundle) usesMaven() bool {
|
||||
func (m *mockUtilsBundle) UsesMaven() bool {
|
||||
return m.maven
|
||||
}
|
||||
|
||||
func (m *mockUtilsBundle) usesNpm() bool {
|
||||
func (m *mockUtilsBundle) UsesNpm() bool {
|
||||
return m.npm
|
||||
}
|
||||
|
||||
func (m *mockUtilsBundle) fileExists(path string) (bool, error) {
|
||||
content := m.files[path]
|
||||
if content == nil {
|
||||
return false, fmt.Errorf("'%s': %w", path, os.ErrNotExist)
|
||||
}
|
||||
return true, nil
|
||||
}
|
||||
|
||||
func (m *mockUtilsBundle) fileRead(path string) ([]byte, error) {
|
||||
content := m.files[path]
|
||||
if content == nil {
|
||||
return nil, fmt.Errorf("could not read '%s'", path)
|
||||
}
|
||||
return content, nil
|
||||
}
|
||||
|
||||
func (m *mockUtilsBundle) fileWrite(path string, content []byte, _ os.FileMode) error {
|
||||
m.files[path] = content
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *mockUtilsBundle) fileRemove(path string) {
|
||||
contents := m.files[path]
|
||||
m.files[path] = nil
|
||||
if contents != nil {
|
||||
m.removedFiles[path] = contents
|
||||
}
|
||||
}
|
||||
|
||||
func (m *mockUtilsBundle) dirExists(path string) (bool, error) {
|
||||
for file := range m.files {
|
||||
dir := filepath.Dir(file)
|
||||
if dir == path {
|
||||
return true, nil
|
||||
}
|
||||
}
|
||||
return false, nil
|
||||
}
|
||||
|
||||
func (m *mockUtilsBundle) getEnvParameter(path, name string) string {
|
||||
path = path + "/" + name
|
||||
return m.cpe[path]
|
||||
@ -117,33 +71,6 @@ func (m *mockUtilsBundle) evaluate(options *maven.EvaluateOptions, expression st
|
||||
return value, nil
|
||||
}
|
||||
|
||||
type byLen []string
|
||||
|
||||
func (a byLen) Len() int {
|
||||
return len(a)
|
||||
}
|
||||
|
||||
func (a byLen) Less(i, j int) bool {
|
||||
return len(a[i]) < len(a[j])
|
||||
}
|
||||
|
||||
func (a byLen) Swap(i, j int) {
|
||||
a[i], a[j] = a[j], a[i]
|
||||
}
|
||||
|
||||
func (m *mockUtilsBundle) glob(pattern string) ([]string, error) {
|
||||
var matches []string
|
||||
for path := range m.files {
|
||||
matched, _ := doublestar.Match(pattern, path)
|
||||
if matched {
|
||||
matches = append(matches, path)
|
||||
}
|
||||
}
|
||||
// The order in m.files is not deterministic, this would result in flaky tests.
|
||||
sort.Sort(byLen(matches))
|
||||
return matches, nil
|
||||
}
|
||||
|
||||
type mockUploader struct {
|
||||
nexus.Upload
|
||||
uploadedArtifacts []nexus.ArtifactDescription
|
||||
@ -205,9 +132,10 @@ var testPackageJson = []byte(`{
|
||||
`)
|
||||
|
||||
func TestUploadMTAProjects(t *testing.T) {
|
||||
t.Parallel()
|
||||
t.Run("Uploading MTA project without groupId parameter fails", func(t *testing.T) {
|
||||
utils := newMockUtilsBundle(true, false, false)
|
||||
utils.files["mta.yaml"] = testMtaYml
|
||||
utils.AddFile("mta.yaml", testMtaYml)
|
||||
utils.cpe[".pipeline/commonPipelineEnvironment/mtarFilePath"] = "test.mtar"
|
||||
uploader := mockUploader{}
|
||||
options := createOptions()
|
||||
@ -220,8 +148,8 @@ func TestUploadMTAProjects(t *testing.T) {
|
||||
})
|
||||
t.Run("Uploading MTA project without artifactId parameter works", func(t *testing.T) {
|
||||
utils := newMockUtilsBundle(true, false, false)
|
||||
utils.files["mta.yaml"] = testMtaYml
|
||||
utils.files["test.mtar"] = []byte("contentsOfMtar")
|
||||
utils.AddFile("mta.yaml", testMtaYml)
|
||||
utils.AddFile("test.mtar", []byte("contentsOfMtar"))
|
||||
utils.cpe[".pipeline/commonPipelineEnvironment/mtarFilePath"] = "test.mtar"
|
||||
uploader := mockUploader{}
|
||||
options := createOptions()
|
||||
@ -246,7 +174,7 @@ func TestUploadMTAProjects(t *testing.T) {
|
||||
})
|
||||
t.Run("Uploading MTA project fails due to garbage YAML content", func(t *testing.T) {
|
||||
utils := newMockUtilsBundle(true, false, false)
|
||||
utils.files["mta.yaml"] = []byte("garbage")
|
||||
utils.AddFile("mta.yaml", []byte("garbage"))
|
||||
utils.cpe[".pipeline/commonPipelineEnvironment/mtarFilePath"] = "test.mtar"
|
||||
uploader := mockUploader{}
|
||||
options := createOptions()
|
||||
@ -259,7 +187,7 @@ func TestUploadMTAProjects(t *testing.T) {
|
||||
})
|
||||
t.Run("Uploading MTA project fails due invalid version in YAML content", func(t *testing.T) {
|
||||
utils := newMockUtilsBundle(true, false, false)
|
||||
utils.files["mta.yaml"] = []byte(testMtaYmlNoVersion)
|
||||
utils.AddFile("mta.yaml", []byte(testMtaYmlNoVersion))
|
||||
utils.cpe[".pipeline/commonPipelineEnvironment/mtarFilePath"] = "test.mtar"
|
||||
uploader := mockUploader{}
|
||||
options := createOptions()
|
||||
@ -272,7 +200,7 @@ func TestUploadMTAProjects(t *testing.T) {
|
||||
})
|
||||
t.Run("Test uploading mta.yaml project fails due to missing mtar file", func(t *testing.T) {
|
||||
utils := newMockUtilsBundle(true, false, false)
|
||||
utils.files["mta.yaml"] = testMtaYml
|
||||
utils.AddFile("mta.yaml", testMtaYml)
|
||||
utils.cpe[".pipeline/commonPipelineEnvironment/mtarFilePath"] = "test.mtar"
|
||||
uploader := mockUploader{}
|
||||
options := createOptions()
|
||||
@ -293,8 +221,8 @@ func TestUploadMTAProjects(t *testing.T) {
|
||||
})
|
||||
t.Run("Test uploading mta.yaml project works", func(t *testing.T) {
|
||||
utils := newMockUtilsBundle(true, false, false)
|
||||
utils.files["mta.yaml"] = testMtaYml
|
||||
utils.files["test.mtar"] = []byte("contentsOfMtar")
|
||||
utils.AddFile("mta.yaml", testMtaYml)
|
||||
utils.AddFile("test.mtar", []byte("contentsOfMtar"))
|
||||
utils.cpe[".pipeline/commonPipelineEnvironment/mtarFilePath"] = "test.mtar"
|
||||
uploader := mockUploader{}
|
||||
options := createOptions()
|
||||
@ -316,8 +244,8 @@ func TestUploadMTAProjects(t *testing.T) {
|
||||
})
|
||||
t.Run("Test uploading mta.yml project works", func(t *testing.T) {
|
||||
utils := newMockUtilsBundle(true, false, false)
|
||||
utils.files["mta.yml"] = testMtaYml
|
||||
utils.files["test.mtar"] = []byte("contentsOfMtar")
|
||||
utils.AddFile("mta.yml", testMtaYml)
|
||||
utils.AddFile("test.mtar", []byte("contentsOfMtar"))
|
||||
utils.cpe[".pipeline/commonPipelineEnvironment/mtarFilePath"] = "test.mtar"
|
||||
uploader := mockUploader{}
|
||||
options := createOptions()
|
||||
@ -340,6 +268,7 @@ func TestUploadMTAProjects(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestUploadArtifacts(t *testing.T) {
|
||||
t.Parallel()
|
||||
t.Run("Uploading MTA project fails without info", func(t *testing.T) {
|
||||
utils := newMockUtilsBundle(false, true, false)
|
||||
uploader := mockUploader{}
|
||||
@ -422,7 +351,7 @@ func TestUploadArtifacts(t *testing.T) {
|
||||
func TestUploadNpmProjects(t *testing.T) {
|
||||
t.Run("Test uploading simple npm project", func(t *testing.T) {
|
||||
utils := newMockUtilsBundle(false, false, true)
|
||||
utils.files["package.json"] = testPackageJson
|
||||
utils.AddFile("package.json", testPackageJson)
|
||||
uploader := mockUploader{}
|
||||
options := createOptions()
|
||||
options.User = "admin"
|
||||
@ -439,6 +368,7 @@ func TestUploadNpmProjects(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestUploadMavenProjects(t *testing.T) {
|
||||
t.Parallel()
|
||||
t.Run("Uploading Maven project fails due to missing pom.xml", func(t *testing.T) {
|
||||
utils := newMockUtilsBundle(false, true, false)
|
||||
uploader := mockUploader{}
|
||||
@ -455,7 +385,7 @@ func TestUploadMavenProjects(t *testing.T) {
|
||||
utils.setProperty("pom.xml", "project.artifactId", "my-app")
|
||||
utils.setProperty("pom.xml", "project.packaging", "pom")
|
||||
utils.setProperty("pom.xml", "project.build.finalName", "my-app-1.0")
|
||||
utils.files["pom.xml"] = testPomXml
|
||||
utils.AddFile("pom.xml", testPomXml)
|
||||
uploader := mockUploader{}
|
||||
options := createOptions()
|
||||
|
||||
@ -477,8 +407,8 @@ func TestUploadMavenProjects(t *testing.T) {
|
||||
utils.setProperty("pom.xml", "project.artifactId", "my-app")
|
||||
utils.setProperty("pom.xml", "project.packaging", "jar")
|
||||
utils.setProperty("pom.xml", "project.build.finalName", "my-app-1.0")
|
||||
utils.files["pom.xml"] = testPomXml
|
||||
utils.files["target/dummy"] = []byte("contentsOfJar") // causes "target" folder to exist
|
||||
utils.AddFile("pom.xml", testPomXml)
|
||||
utils.AddDir("target")
|
||||
uploader := mockUploader{}
|
||||
options := createOptions()
|
||||
|
||||
@ -493,8 +423,8 @@ func TestUploadMavenProjects(t *testing.T) {
|
||||
utils.setProperty("pom.xml", "project.artifactId", "my-app")
|
||||
utils.setProperty("pom.xml", "project.packaging", "jar")
|
||||
utils.setProperty("pom.xml", "project.build.finalName", "my-app-1.0")
|
||||
utils.files["pom.xml"] = testPomXml
|
||||
utils.files["target/my-app-1.0.jar"] = []byte("contentsOfJar")
|
||||
utils.AddFile("pom.xml", testPomXml)
|
||||
utils.AddFile("target/my-app-1.0.jar", []byte("contentsOfJar"))
|
||||
uploader := mockUploader{}
|
||||
options := createOptions()
|
||||
|
||||
@ -520,8 +450,8 @@ func TestUploadMavenProjects(t *testing.T) {
|
||||
utils.setProperty("pom.xml", "project.artifactId", "my-app")
|
||||
utils.setProperty("pom.xml", "project.packaging", "<empty>")
|
||||
utils.setProperty("pom.xml", "project.build.finalName", "my-app-1.0")
|
||||
utils.files["pom.xml"] = testPomXml
|
||||
utils.files["target/my-app-1.0.jar"] = []byte("contentsOfJar")
|
||||
utils.AddFile("pom.xml", testPomXml)
|
||||
utils.AddFile("target/my-app-1.0.jar", []byte("contentsOfJar"))
|
||||
uploader := mockUploader{}
|
||||
options := createOptions()
|
||||
|
||||
@ -545,7 +475,7 @@ func TestUploadMavenProjects(t *testing.T) {
|
||||
utils.setProperty("pom.xml", "project.artifactId", "my-app")
|
||||
utils.setProperty("pom.xml", "project.packaging", "pom")
|
||||
utils.setProperty("pom.xml", "project.build.finalName", "my-app-1.0")
|
||||
utils.files["pom.xml"] = testPomXml
|
||||
utils.AddFile("pom.xml", testPomXml)
|
||||
uploader := mockUploader{}
|
||||
options := createOptions()
|
||||
options.GroupID = "awesome.group"
|
||||
@ -570,8 +500,8 @@ func TestUploadMavenProjects(t *testing.T) {
|
||||
utils.setProperty("pom.xml", "project.groupId", "awesome.group")
|
||||
utils.setProperty("pom.xml", "project.artifactId", "my-app")
|
||||
utils.setProperty("pom.xml", "project.packaging", "jar")
|
||||
utils.files["pom.xml"] = testPomXml
|
||||
utils.files["target/my-app-1.0.jar"] = []byte("contentsOfJar")
|
||||
utils.AddFile("pom.xml", testPomXml)
|
||||
utils.AddFile("target/my-app-1.0.jar", []byte("contentsOfJar"))
|
||||
uploader := mockUploader{}
|
||||
options := createOptions()
|
||||
|
||||
@ -617,45 +547,49 @@ func TestUploadMavenProjects(t *testing.T) {
|
||||
utils.setProperty("performance-tests/pom.xml", "project.groupId", "com.mycompany.app")
|
||||
utils.setProperty("performance-tests/pom.xml", "project.artifactId", "my-app-app")
|
||||
utils.setProperty("performance-tests/pom.xml", "project.packaging", "")
|
||||
utils.files["pom.xml"] = testPomXml
|
||||
utils.files["application/pom.xml"] = testPomXml
|
||||
utils.files["application/target/final-artifact.war"] = []byte("contentsOfJar")
|
||||
utils.files["application/target/final-artifact-classes.jar"] = []byte("contentsOfClassesJar")
|
||||
utils.files["integration-tests/pom.xml"] = testPomXml
|
||||
utils.files["integration-tests/target/final-artifact-integration-tests.jar"] = []byte("contentsOfJar")
|
||||
utils.files["unit-tests/pom.xml"] = testPomXml
|
||||
utils.files["unit-tests/target/final-artifact-unit-tests.jar"] = []byte("contentsOfJar")
|
||||
utils.files["performance-tests/pom.xml"] = testPomXml
|
||||
utils.AddFile("pom.xml", testPomXml)
|
||||
utils.AddFile("application/pom.xml", testPomXml)
|
||||
utils.AddFile("application/target/final-artifact.war", []byte("contentsOfJar"))
|
||||
utils.AddFile("application/target/final-artifact-classes.jar", []byte("contentsOfClassesJar"))
|
||||
utils.AddFile("integration-tests/pom.xml", testPomXml)
|
||||
utils.AddFile("integration-tests/target/final-artifact-integration-tests.jar", []byte("contentsOfJar"))
|
||||
utils.AddFile("unit-tests/pom.xml", testPomXml)
|
||||
utils.AddFile("unit-tests/target/final-artifact-unit-tests.jar", []byte("contentsOfJar"))
|
||||
utils.AddFile("performance-tests/pom.xml", testPomXml)
|
||||
uploader := mockUploader{}
|
||||
options := createOptions()
|
||||
|
||||
err := runNexusUpload(&utils, &uploader, &options)
|
||||
assert.NoError(t, err, "expected upload of maven project with application module to succeed")
|
||||
assert.Equal(t, "1.0", uploader.GetArtifactsVersion())
|
||||
assert.Equal(t, "my-app-app", uploader.GetArtifactsID())
|
||||
assert.Equal(t, "my-app", uploader.GetArtifactsID())
|
||||
|
||||
artifacts := uploader.uploadedArtifacts
|
||||
if assert.Equal(t, 4, len(artifacts)) {
|
||||
assert.Equal(t, "pom.xml", artifacts[0].File)
|
||||
assert.Equal(t, "application/pom.xml", artifacts[0].File)
|
||||
assert.Equal(t, "pom", artifacts[0].Type)
|
||||
|
||||
assert.Equal(t, "application/pom.xml", artifacts[1].File)
|
||||
assert.Equal(t, "pom", artifacts[1].Type)
|
||||
assert.Equal(t, "application/target/final-artifact.war", artifacts[1].File)
|
||||
assert.Equal(t, "war", artifacts[1].Type)
|
||||
|
||||
assert.Equal(t, "application/target/final-artifact.war", artifacts[2].File)
|
||||
assert.Equal(t, "war", artifacts[2].Type)
|
||||
assert.Equal(t, "application/target/final-artifact-classes.jar", artifacts[2].File)
|
||||
assert.Equal(t, "jar", artifacts[2].Type)
|
||||
|
||||
assert.Equal(t, "pom.xml", artifacts[3].File)
|
||||
assert.Equal(t, "pom", artifacts[3].Type)
|
||||
|
||||
assert.Equal(t, "application/target/final-artifact-classes.jar", artifacts[3].File)
|
||||
assert.Equal(t, "jar", artifacts[3].Type)
|
||||
}
|
||||
if assert.Equal(t, 2, len(utils.execRunner.Calls)) {
|
||||
expectedParameters1 := []string{
|
||||
"-Durl=http://localhost:8081/repository/maven-releases/",
|
||||
"-DgroupId=com.mycompany.app",
|
||||
"-Dversion=1.0",
|
||||
"-DartifactId=my-app",
|
||||
"-Dfile=pom.xml",
|
||||
"-DartifactId=my-app-app",
|
||||
"-Dfile=application/pom.xml",
|
||||
"-Dpackaging=pom",
|
||||
"-Dfiles=application/target/final-artifact.war,application/target/final-artifact-classes.jar",
|
||||
"-Dclassifiers=,classes",
|
||||
"-Dtypes=war,jar",
|
||||
"-Dorg.slf4j.simpleLogger.log.org.apache.maven.cli.transfer.Slf4jMavenTransferListener=warn",
|
||||
"--batch-mode",
|
||||
deployGoal}
|
||||
@ -666,12 +600,9 @@ func TestUploadMavenProjects(t *testing.T) {
|
||||
"-Durl=http://localhost:8081/repository/maven-releases/",
|
||||
"-DgroupId=com.mycompany.app",
|
||||
"-Dversion=1.0",
|
||||
"-DartifactId=my-app-app",
|
||||
"-Dfile=application/pom.xml",
|
||||
"-DartifactId=my-app",
|
||||
"-Dfile=pom.xml",
|
||||
"-Dpackaging=pom",
|
||||
"-Dfiles=application/target/final-artifact.war,application/target/final-artifact-classes.jar",
|
||||
"-Dclassifiers=,classes",
|
||||
"-Dtypes=war,jar",
|
||||
"-Dorg.slf4j.simpleLogger.log.org.apache.maven.cli.transfer.Slf4jMavenTransferListener=warn",
|
||||
"--batch-mode",
|
||||
deployGoal}
|
||||
@ -686,7 +617,7 @@ func TestUploadMavenProjects(t *testing.T) {
|
||||
utils.setProperty("pom.xml", "project.artifactId", "my-app")
|
||||
utils.setProperty("pom.xml", "project.packaging", "pom")
|
||||
utils.setProperty("pom.xml", "project.build.finalName", "my-app-1.0")
|
||||
utils.files["pom.xml"] = testPomXml
|
||||
utils.AddFile("pom.xml", testPomXml)
|
||||
uploader := mockUploader{}
|
||||
options := createOptions()
|
||||
options.User = "admin"
|
||||
@ -716,8 +647,8 @@ func TestUploadMavenProjects(t *testing.T) {
|
||||
assert.Equal(t, 2, len(utils.execRunner.Env))
|
||||
assert.Equal(t, expectedEnv, utils.execRunner.Env)
|
||||
|
||||
assert.Nil(t, utils.files[settingsPath])
|
||||
assert.NotNil(t, utils.removedFiles[settingsPath])
|
||||
assert.False(t, utils.HasFile(settingsPath))
|
||||
assert.True(t, utils.HasRemovedFile(settingsPath))
|
||||
})
|
||||
}
|
||||
|
||||
@ -734,5 +665,5 @@ func TestSetupNexusCredentialsSettingsFile(t *testing.T) {
|
||||
assert.Equal(t, expectedEnv, utils.execRunner.Env)
|
||||
|
||||
assert.True(t, settingsPath != "")
|
||||
assert.NotNil(t, utils.files[settingsPath])
|
||||
assert.True(t, utils.HasFile(settingsPath))
|
||||
}
|
||||
|
@ -28,7 +28,7 @@ func (u *npmExecuteScriptsMockUtilsBundle) glob(pattern string) ([]string, error
|
||||
}
|
||||
}
|
||||
// The order in m.files is not deterministic, this would result in flaky tests.
|
||||
sort.Sort(byLen(matches))
|
||||
sort.Strings(matches)
|
||||
return matches, nil
|
||||
}
|
||||
|
||||
|
@ -3,44 +3,203 @@
|
||||
package mock
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"github.com/bmatcuk/doublestar"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"sort"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// FilesMock ...
|
||||
var dirContent []byte
|
||||
|
||||
// FilesMock implements the functions from piperutils.Files with an in-memory file system.
|
||||
type FilesMock struct {
|
||||
Files []string
|
||||
files map[string]*[]byte
|
||||
removedFiles map[string]*[]byte
|
||||
currentDir string
|
||||
}
|
||||
|
||||
// FileExists ...
|
||||
func (f FilesMock) FileExists(filename string) (bool, error) {
|
||||
|
||||
for _, file := range f.Files {
|
||||
if file == filename {
|
||||
return true, nil
|
||||
}
|
||||
|
||||
func (f *FilesMock) init() {
|
||||
if f.files == nil {
|
||||
f.files = map[string]*[]byte{}
|
||||
}
|
||||
if f.removedFiles == nil {
|
||||
f.removedFiles = map[string]*[]byte{}
|
||||
}
|
||||
}
|
||||
|
||||
func (f *FilesMock) toAbsPath(path string) string {
|
||||
if !strings.HasPrefix(path, string(os.PathSeparator)) {
|
||||
path = string(os.PathSeparator) + filepath.Join(f.currentDir, path)
|
||||
}
|
||||
return path
|
||||
}
|
||||
|
||||
// AddFile establishes the existence of a virtual file.
|
||||
func (f *FilesMock) AddFile(path string, contents []byte) {
|
||||
f.init()
|
||||
f.files[f.toAbsPath(path)] = &contents
|
||||
}
|
||||
|
||||
// AddDir establishes the existence of a virtual directory.
|
||||
func (f *FilesMock) AddDir(path string) {
|
||||
f.init()
|
||||
f.files[f.toAbsPath(path)] = &dirContent
|
||||
}
|
||||
|
||||
// HasFile returns true if the virtual file system contains an entry for the given path.
|
||||
func (f *FilesMock) HasFile(path string) bool {
|
||||
_, exists := f.files[f.toAbsPath(path)]
|
||||
return exists
|
||||
}
|
||||
|
||||
// HasRemovedFile returns true if the virtual file system at one point contained an entry for the given path,
|
||||
// and it was removed via FileRemove().
|
||||
func (f *FilesMock) HasRemovedFile(path string) bool {
|
||||
_, exists := f.removedFiles[f.toAbsPath(path)]
|
||||
return exists
|
||||
}
|
||||
|
||||
// FileExists returns true if file content has been associated with the given path, false otherwise.
|
||||
// Only relative paths are supported.
|
||||
func (f *FilesMock) FileExists(path string) (bool, error) {
|
||||
if f.files == nil {
|
||||
return false, nil
|
||||
}
|
||||
content, exists := f.files[f.toAbsPath(path)]
|
||||
if !exists {
|
||||
return false, fmt.Errorf("'%s': %w", path, os.ErrNotExist)
|
||||
}
|
||||
return content != &dirContent, nil
|
||||
}
|
||||
|
||||
// DirExists returns true, if the given path is a previously added directory, or a parent directory for any of the
|
||||
// previously added files.
|
||||
func (f *FilesMock) DirExists(path string) (bool, error) {
|
||||
path = f.toAbsPath(path)
|
||||
for entry, content := range f.files {
|
||||
var dirComponents []string
|
||||
if content == &dirContent {
|
||||
dirComponents = strings.Split(entry, string(os.PathSeparator))
|
||||
} else {
|
||||
dirComponents = strings.Split(filepath.Dir(entry), string(os.PathSeparator))
|
||||
}
|
||||
if len(dirComponents) > 0 {
|
||||
dir := ""
|
||||
for i, component := range dirComponents {
|
||||
if i == 0 {
|
||||
dir = component
|
||||
} else {
|
||||
dir = dir + string(os.PathSeparator) + component
|
||||
}
|
||||
if dir == path {
|
||||
return true, nil
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return false, nil
|
||||
}
|
||||
|
||||
// Copy ...
|
||||
func (f FilesMock) Copy(src, dst string) (int64, error) {
|
||||
return 0, errors.New("Not implemented")
|
||||
// Copy checks if content has been associated with the given src path, and if so copies it under the given path dst.
|
||||
func (f *FilesMock) Copy(src, dst string) (int64, error) {
|
||||
f.init()
|
||||
content, exists := f.files[f.toAbsPath(src)]
|
||||
if !exists || content == &dirContent {
|
||||
return 0, fmt.Errorf("cannot copy '%s': %w", src, os.ErrNotExist)
|
||||
}
|
||||
f.AddFile(dst, *content)
|
||||
return int64(len(*content)), nil
|
||||
}
|
||||
|
||||
// FileRead ...
|
||||
func (f FilesMock) FileRead(path string) ([]byte, error) {
|
||||
return nil, errors.New("Not implemented")
|
||||
// FileRead returns the content previously associated with the given path via AddFile(), or an error if no
|
||||
// content has been associated.
|
||||
func (f *FilesMock) FileRead(path string) ([]byte, error) {
|
||||
f.init()
|
||||
content, exists := f.files[f.toAbsPath(path)]
|
||||
if !exists {
|
||||
return nil, fmt.Errorf("could not read '%s'", path)
|
||||
}
|
||||
// check if trying to open a directory for reading
|
||||
if content == &dirContent {
|
||||
return nil, fmt.Errorf("could not read '%s': %w", path, os.ErrInvalid)
|
||||
}
|
||||
return *content, nil
|
||||
}
|
||||
|
||||
// FileWrite ...
|
||||
func (f FilesMock) FileWrite(path string, content []byte, perm os.FileMode) error {
|
||||
return errors.New("Not implemented")
|
||||
// FileWrite just forwards to AddFile(), i.e. the content is associated with the given path.
|
||||
func (f *FilesMock) FileWrite(path string, content []byte, _ os.FileMode) error {
|
||||
// NOTE: FilesMock could be extended to have a set of paths for which FileWrite should fail.
|
||||
// This is why AddFile() exists separately, to differentiate the notion of setting up the mocking
|
||||
// versus implementing the methods from Files.
|
||||
f.AddFile(path, content)
|
||||
return nil
|
||||
}
|
||||
|
||||
// MkdirAll ...
|
||||
func (f FilesMock) MkdirAll(path string, perm os.FileMode) error {
|
||||
return errors.New("Not implemented")
|
||||
// FileRemove deletes the association of the given path with any content and records the removal of the file.
|
||||
// If the path has not been registered before, it returns an error.
|
||||
func (f *FilesMock) FileRemove(path string) error {
|
||||
if f.files == nil {
|
||||
return fmt.Errorf("the file '%s' does not exist: %w", path, os.ErrNotExist)
|
||||
}
|
||||
absPath := f.toAbsPath(path)
|
||||
content, exists := f.files[absPath]
|
||||
if !exists {
|
||||
return fmt.Errorf("the file '%s' does not exist: %w", path, os.ErrNotExist)
|
||||
}
|
||||
delete(f.files, absPath)
|
||||
f.removedFiles[absPath] = content
|
||||
return nil
|
||||
}
|
||||
|
||||
// MkdirAll creates a directory in the in-memory file system, so that this path is established to exist.
|
||||
func (f *FilesMock) MkdirAll(path string, _ os.FileMode) error {
|
||||
// NOTE: FilesMock could be extended to have a set of paths for which MkdirAll should fail.
|
||||
// This is why AddDir() exists separately, to differentiate the notion of setting up the mocking
|
||||
// versus implementing the methods from Files.
|
||||
f.AddDir(path)
|
||||
return nil
|
||||
}
|
||||
|
||||
// Glob returns an array of path strings which match the given glob-pattern. Double star matching is supported.
|
||||
func (f *FilesMock) Glob(pattern string) ([]string, error) {
|
||||
var matches []string
|
||||
if f.files == nil {
|
||||
return matches, nil
|
||||
}
|
||||
for path := range f.files {
|
||||
path = strings.TrimLeft(path, string(os.PathSeparator))
|
||||
matched, _ := doublestar.Match(pattern, path)
|
||||
if matched {
|
||||
matches = append(matches, path)
|
||||
}
|
||||
}
|
||||
// The order in f.files is not deterministic, this would result in flaky tests.
|
||||
sort.Strings(matches)
|
||||
return matches, nil
|
||||
}
|
||||
|
||||
// Getwd returns the rooted current virtual working directory
|
||||
func (f *FilesMock) Getwd() (string, error) {
|
||||
return f.toAbsPath(""), nil
|
||||
}
|
||||
|
||||
// Chdir changes virtually in to the given directory.
|
||||
// The directory needs to exist according to the files and directories via AddFile() and AddDirectory().
|
||||
// The implementation does not support relative path components such as "..".
|
||||
func (f *FilesMock) Chdir(path string) error {
|
||||
if path == "." || path == "."+string(os.PathSeparator) {
|
||||
return nil
|
||||
}
|
||||
|
||||
path = f.toAbsPath(path)
|
||||
|
||||
exists, _ := f.DirExists(path)
|
||||
if !exists {
|
||||
return fmt.Errorf("failed to change current directory into '%s': %w", path, os.ErrNotExist)
|
||||
}
|
||||
|
||||
f.currentDir = strings.TrimLeft(path, string(os.PathSeparator))
|
||||
return nil
|
||||
}
|
||||
|
244
pkg/mock/fileUtils_test.go
Normal file
244
pkg/mock/fileUtils_test.go
Normal file
@ -0,0 +1,244 @@
|
||||
package mock
|
||||
|
||||
import (
|
||||
"github.com/stretchr/testify/assert"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestFilesMockFileExists(t *testing.T) {
|
||||
t.Parallel()
|
||||
t.Run("no init", func(t *testing.T) {
|
||||
files := FilesMock{}
|
||||
path := filepath.Join("some", "path")
|
||||
exists, err := files.FileExists(path)
|
||||
assert.NoError(t, err)
|
||||
assert.False(t, exists)
|
||||
})
|
||||
t.Run("file exists after AddFile()", func(t *testing.T) {
|
||||
files := FilesMock{}
|
||||
path := filepath.Join("some", "path")
|
||||
files.AddFile(path, []byte("dummy content"))
|
||||
exists, err := files.FileExists(path)
|
||||
assert.NoError(t, err)
|
||||
assert.True(t, exists)
|
||||
})
|
||||
t.Run("path is a directory after AddDir()", func(t *testing.T) {
|
||||
files := FilesMock{}
|
||||
path := filepath.Join("some", "path")
|
||||
files.AddDir(path)
|
||||
exists, err := files.FileExists(path)
|
||||
assert.NoError(t, err)
|
||||
assert.False(t, exists)
|
||||
})
|
||||
t.Run("file exists after changing current dir", func(t *testing.T) {
|
||||
files := FilesMock{}
|
||||
path := filepath.Join("some", "path")
|
||||
files.AddFile(path, []byte("dummy content"))
|
||||
err := files.Chdir("some")
|
||||
assert.NoError(t, err)
|
||||
exists, err := files.FileExists("path")
|
||||
assert.NoError(t, err)
|
||||
assert.True(t, exists)
|
||||
})
|
||||
t.Run("file does not exist after changing current dir", func(t *testing.T) {
|
||||
files := FilesMock{}
|
||||
path := filepath.Join("some", "path")
|
||||
files.AddFile(path, []byte("dummy content"))
|
||||
err := files.Chdir("some")
|
||||
assert.NoError(t, err)
|
||||
exists, err := files.FileExists(path)
|
||||
assert.EqualError(t, err, "'"+path+"': file does not exist")
|
||||
assert.False(t, exists)
|
||||
})
|
||||
}
|
||||
|
||||
func TestFilesMockDirExists(t *testing.T) {
|
||||
t.Parallel()
|
||||
t.Run("no init", func(t *testing.T) {
|
||||
files := FilesMock{}
|
||||
path := filepath.Join("some", "path")
|
||||
exists, err := files.DirExists(path)
|
||||
assert.NoError(t, err)
|
||||
assert.False(t, exists)
|
||||
})
|
||||
t.Run("dir exists after AddDir()", func(t *testing.T) {
|
||||
files := FilesMock{}
|
||||
path := filepath.Join("some", "path")
|
||||
files.AddDir(path)
|
||||
exists, err := files.DirExists(path)
|
||||
assert.NoError(t, err)
|
||||
assert.True(t, exists)
|
||||
})
|
||||
t.Run("absolute dir exists after AddDir()", func(t *testing.T) {
|
||||
files := FilesMock{}
|
||||
path := filepath.Join("some", "path")
|
||||
files.AddDir(path)
|
||||
err := files.Chdir("some")
|
||||
assert.NoError(t, err)
|
||||
exists, err := files.DirExists(string(os.PathSeparator) + path)
|
||||
assert.NoError(t, err)
|
||||
assert.True(t, exists)
|
||||
})
|
||||
t.Run("parent dirs exists after AddFile()", func(t *testing.T) {
|
||||
files := FilesMock{}
|
||||
path := filepath.Join("path", "to", "some", "file")
|
||||
files.AddFile(path, []byte("dummy content"))
|
||||
testDirs := []string{
|
||||
"path",
|
||||
filepath.Join("path", "to"),
|
||||
filepath.Join("path", "to", "some"),
|
||||
}
|
||||
for _, dir := range testDirs {
|
||||
exists, err := files.DirExists(dir)
|
||||
assert.NoError(t, err)
|
||||
assert.True(t, exists, "Should exist: '%s'", dir)
|
||||
}
|
||||
})
|
||||
t.Run("invalid sub-folders do not exist after AddFile()", func(t *testing.T) {
|
||||
files := FilesMock{}
|
||||
path := filepath.Join("path", "to", "some", "file")
|
||||
files.AddFile(path, []byte("dummy content"))
|
||||
testDirs := []string{
|
||||
"to",
|
||||
filepath.Join("to", "some"),
|
||||
"some",
|
||||
filepath.Join("path", "to", "so"),
|
||||
}
|
||||
for _, dir := range testDirs {
|
||||
exists, err := files.DirExists(dir)
|
||||
assert.NoError(t, err)
|
||||
assert.False(t, exists, "Should not exist: '%s'", dir)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func TestFilesMockCopy(t *testing.T) {
|
||||
t.Parallel()
|
||||
t.Run("copy a previously added file successfully", func(t *testing.T) {
|
||||
files := FilesMock{}
|
||||
src := filepath.Join("some", "file")
|
||||
content := []byte("dummy content")
|
||||
files.AddFile(src, content)
|
||||
dst := filepath.Join("another", "file")
|
||||
length, err := files.Copy(src, dst)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, length, int64(len(content)))
|
||||
})
|
||||
t.Run("fail to copy non-existing file", func(t *testing.T) {
|
||||
files := FilesMock{}
|
||||
src := filepath.Join("some", "file")
|
||||
dst := filepath.Join("another", "file")
|
||||
length, err := files.Copy(src, dst)
|
||||
assert.EqualError(t, err, "cannot copy '"+src+"': file does not exist")
|
||||
assert.Equal(t, length, int64(0))
|
||||
})
|
||||
t.Run("fail to copy folder", func(t *testing.T) {
|
||||
files := FilesMock{}
|
||||
src := filepath.Join("some", "file")
|
||||
files.AddDir(src)
|
||||
dst := filepath.Join("another", "file")
|
||||
length, err := files.Copy(src, dst)
|
||||
assert.EqualError(t, err, "cannot copy '"+src+"': file does not exist")
|
||||
assert.Equal(t, length, int64(0))
|
||||
})
|
||||
}
|
||||
|
||||
func TestFilesMockFileRemove(t *testing.T) {
|
||||
t.Parallel()
|
||||
t.Run("fail to remove non-existing file", func(t *testing.T) {
|
||||
files := FilesMock{}
|
||||
path := filepath.Join("some", "file")
|
||||
err := files.FileRemove(path)
|
||||
assert.EqualError(t, err, "the file '"+path+"' does not exist: file does not exist")
|
||||
assert.False(t, files.HasRemovedFile(path))
|
||||
})
|
||||
t.Run("track removing a file", func(t *testing.T) {
|
||||
files := FilesMock{}
|
||||
path := filepath.Join("some", "file")
|
||||
files.AddFile(path, []byte("dummy content"))
|
||||
assert.True(t, files.HasFile(path))
|
||||
err := files.FileRemove(path)
|
||||
assert.NoError(t, err)
|
||||
assert.False(t, files.HasFile(path))
|
||||
assert.True(t, files.HasRemovedFile(path))
|
||||
})
|
||||
}
|
||||
|
||||
func TestFilesMockGetwd(t *testing.T) {
|
||||
t.Parallel()
|
||||
t.Run("test root", func(t *testing.T) {
|
||||
files := FilesMock{}
|
||||
dir, err := files.Getwd()
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, string(os.PathSeparator), dir)
|
||||
})
|
||||
t.Run("test sub folder", func(t *testing.T) {
|
||||
files := FilesMock{}
|
||||
dirChain := []string{"some", "deep", "folder"}
|
||||
files.AddDir(filepath.Join(dirChain...))
|
||||
for _, element := range dirChain {
|
||||
err := files.Chdir(element)
|
||||
assert.NoError(t, err)
|
||||
}
|
||||
dir, err := files.Getwd()
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, string(os.PathSeparator)+filepath.Join(dirChain...), dir)
|
||||
})
|
||||
}
|
||||
|
||||
func TestFilesMockGlob(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
files := FilesMock{}
|
||||
content := []byte("dummy content")
|
||||
files.AddFile(filepath.Join("dir", "foo.xml"), content)
|
||||
files.AddFile(filepath.Join("dir", "another", "foo.xml"), content)
|
||||
files.AddFile(filepath.Join("dir", "baz"), content)
|
||||
files.AddFile(filepath.Join("baz.xml"), content)
|
||||
|
||||
t.Run("one match in root-dir", func(t *testing.T) {
|
||||
matches, err := files.Glob("*.xml")
|
||||
assert.NoError(t, err)
|
||||
if assert.Len(t, matches, 1) {
|
||||
assert.Equal(t, matches[0], "baz.xml")
|
||||
}
|
||||
})
|
||||
t.Run("three matches in all levels", func(t *testing.T) {
|
||||
matches, err := files.Glob("**/*.xml")
|
||||
assert.NoError(t, err)
|
||||
if assert.Len(t, matches, 3) {
|
||||
assert.Equal(t, matches[0], "baz.xml")
|
||||
assert.Equal(t, matches[1], filepath.Join("dir", "another", "foo.xml"))
|
||||
assert.Equal(t, matches[2], filepath.Join("dir", "foo.xml"))
|
||||
}
|
||||
})
|
||||
t.Run("match only in sub-dir", func(t *testing.T) {
|
||||
matches, err := files.Glob("*/*.xml")
|
||||
assert.NoError(t, err)
|
||||
if assert.Len(t, matches, 1) {
|
||||
assert.Equal(t, matches[0], filepath.Join("dir", "foo.xml"))
|
||||
}
|
||||
})
|
||||
t.Run("match for two levels", func(t *testing.T) {
|
||||
matches, err := files.Glob("*/*/*.xml")
|
||||
assert.NoError(t, err)
|
||||
if assert.Len(t, matches, 1) {
|
||||
assert.Equal(t, matches[0], filepath.Join("dir", "another", "foo.xml"))
|
||||
}
|
||||
})
|
||||
t.Run("match prefix", func(t *testing.T) {
|
||||
matches, err := files.Glob("**/baz*")
|
||||
assert.NoError(t, err)
|
||||
if assert.Len(t, matches, 2) {
|
||||
assert.Equal(t, matches[0], filepath.Join("baz.xml"))
|
||||
assert.Equal(t, matches[1], filepath.Join("dir", "baz"))
|
||||
}
|
||||
})
|
||||
t.Run("no matches", func(t *testing.T) {
|
||||
matches, err := files.Glob("**/*bar*")
|
||||
assert.NoError(t, err)
|
||||
assert.Len(t, matches, 0)
|
||||
})
|
||||
}
|
@ -4,6 +4,7 @@ import (
|
||||
"archive/zip"
|
||||
"errors"
|
||||
"fmt"
|
||||
"github.com/bmatcuk/doublestar"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
@ -43,6 +44,20 @@ func FileExists(filename string) (bool, error) {
|
||||
return Files{}.FileExists(filename)
|
||||
}
|
||||
|
||||
// DirExists returns true if the file system entry for the given path exists and is a directory.
|
||||
func (f Files) DirExists(path string) (bool, error) {
|
||||
info, err := os.Stat(path)
|
||||
|
||||
if os.IsNotExist(err) {
|
||||
return false, nil
|
||||
}
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
return info.IsDir(), nil
|
||||
}
|
||||
|
||||
// Copy ...
|
||||
func (f Files) Copy(src, dst string) (int64, error) {
|
||||
|
||||
@ -156,17 +171,37 @@ func Copy(src, dst string) (int64, error) {
|
||||
return Files{}.Copy(src, dst)
|
||||
}
|
||||
|
||||
//FileRead ...
|
||||
// FileRead is a wrapper for ioutil.ReadFile().
|
||||
func (f Files) FileRead(path string) ([]byte, error) {
|
||||
return ioutil.ReadFile(path)
|
||||
}
|
||||
|
||||
// FileWrite ...
|
||||
// FileWrite is a wrapper for ioutil.WriteFile().
|
||||
func (f Files) FileWrite(path string, content []byte, perm os.FileMode) error {
|
||||
return ioutil.WriteFile(path, content, perm)
|
||||
}
|
||||
|
||||
// MkdirAll ...
|
||||
// FileRemove is a wrapper for os.FileRemove().
|
||||
func (f Files) FileRemove(path string) error {
|
||||
return os.Remove(path)
|
||||
}
|
||||
|
||||
// MkdirAll is a wrapper for os.MkdirAll().
|
||||
func (f Files) MkdirAll(path string, perm os.FileMode) error {
|
||||
return os.MkdirAll(path, perm)
|
||||
}
|
||||
|
||||
// Glob is a wrapper for doublestar.Glob().
|
||||
func (f Files) Glob(pattern string) (matches []string, err error) {
|
||||
return doublestar.Glob(pattern)
|
||||
}
|
||||
|
||||
// Getwd is a wrapper for os.Getwd().
|
||||
func (f Files) Getwd() (string, error) {
|
||||
return os.Getwd()
|
||||
}
|
||||
|
||||
// Chdir is a wrapper for os.Chdir().
|
||||
func (f Files) Chdir(path string) error {
|
||||
return os.Chdir(path)
|
||||
}
|
||||
|
@ -9,35 +9,70 @@ import (
|
||||
)
|
||||
|
||||
func TestFileExists(t *testing.T) {
|
||||
dir, err := ioutil.TempDir("", "dir")
|
||||
if err != nil {
|
||||
t.Fatal("Failed to create temporary workspace directory")
|
||||
}
|
||||
// clean up tmp dir
|
||||
defer os.RemoveAll(dir)
|
||||
|
||||
result, err := FileExists(dir)
|
||||
assert.NoError(t, err, "Didn't expert error but got one")
|
||||
assert.Equal(t, false, result, "Expected false but got true")
|
||||
|
||||
file, err := ioutil.TempFile(dir, "testFile")
|
||||
assert.NoError(t, err, "Didn't expert error but got one")
|
||||
result, err = FileExists(file.Name())
|
||||
assert.NoError(t, err, "Didn't expert error but got one")
|
||||
assert.Equal(t, true, result, "Expected true but got false")
|
||||
t.Parallel()
|
||||
runInTempDir(t, "testing dir returns false", "dir", func(t *testing.T) {
|
||||
err := os.Mkdir("test", 0777)
|
||||
if err != nil {
|
||||
t.Fatal("failed to create test dir in temporary dir")
|
||||
}
|
||||
result, err := FileExists("test")
|
||||
assert.NoError(t, err)
|
||||
assert.False(t, result)
|
||||
})
|
||||
runInTempDir(t, "testing file returns true", "dir", func(t *testing.T) {
|
||||
file, err := ioutil.TempFile("", "testFile")
|
||||
assert.NoError(t, err)
|
||||
result, err := FileExists(file.Name())
|
||||
assert.NoError(t, err)
|
||||
assert.True(t, result)
|
||||
})
|
||||
}
|
||||
|
||||
func TestCopy(t *testing.T) {
|
||||
dir, err := ioutil.TempDir("", "dir2")
|
||||
file := filepath.Join(dir, "testFile")
|
||||
err = ioutil.WriteFile(file, []byte{byte(1), byte(2), byte(3)}, 0700)
|
||||
if err != nil {
|
||||
t.Fatal("Failed to create temporary workspace directory")
|
||||
}
|
||||
// clean up tmp dir
|
||||
defer os.RemoveAll(dir)
|
||||
t.Parallel()
|
||||
runInTempDir(t, "copying file succeeds", "dir2", func(t *testing.T) {
|
||||
file := "testFile"
|
||||
err := ioutil.WriteFile(file, []byte{byte(1), byte(2), byte(3)}, 0700)
|
||||
if err != nil {
|
||||
t.Fatal("Failed to create temporary workspace directory")
|
||||
}
|
||||
|
||||
result, err := Copy(file, filepath.Join(dir, "testFile2"))
|
||||
assert.NoError(t, err, "Didn't expert error but got one")
|
||||
assert.Equal(t, int64(3), result, "Expected true but got false")
|
||||
result, err := Copy(file, "testFile2")
|
||||
assert.NoError(t, err, "Didn't expert error but got one")
|
||||
assert.Equal(t, int64(3), result, "Expected true but got false")
|
||||
})
|
||||
runInTempDir(t, "copying directory fails", "dir3", func(t *testing.T) {
|
||||
src := filepath.Join("some", "file")
|
||||
dst := filepath.Join("another", "file")
|
||||
|
||||
err := os.MkdirAll(src, 0777)
|
||||
if err != nil {
|
||||
t.Fatal("Failed to create test directory")
|
||||
}
|
||||
|
||||
files := Files{}
|
||||
exists, err := files.DirExists(src)
|
||||
assert.NoError(t, err)
|
||||
assert.True(t, exists)
|
||||
|
||||
length, err := files.Copy(src, dst)
|
||||
assert.EqualError(t, err, "Source file '"+src+"' does not exist")
|
||||
assert.Equal(t, length, int64(0))
|
||||
})
|
||||
}
|
||||
|
||||
func runInTempDir(t *testing.T, nameOfRun, tempDirPattern string, run func(t *testing.T)) {
|
||||
dir, err := ioutil.TempDir("", tempDirPattern)
|
||||
if err != nil {
|
||||
t.Fatal("Failed to create temporary directory")
|
||||
}
|
||||
oldCWD, _ := os.Getwd()
|
||||
_ = os.Chdir(dir)
|
||||
// clean up tmp dir
|
||||
defer func() {
|
||||
_ = os.Chdir(oldCWD)
|
||||
_ = os.RemoveAll(dir)
|
||||
}()
|
||||
|
||||
t.Run(nameOfRun, run)
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user