github.com/jfrog/jfrog-cli-go@v1.22.1-0.20200318093948-4826ef344ffd/utils/tests/utils.go (about)

     1  package tests
     2  
     3  import (
     4  	"bytes"
     5  	"errors"
     6  	"flag"
     7  	"fmt"
     8  	"io/ioutil"
     9  	"os"
    10  	"os/exec"
    11  	"path/filepath"
    12  	"strconv"
    13  	"strings"
    14  	"testing"
    15  
    16  	"github.com/stretchr/testify/assert"
    17  
    18  	"github.com/jfrog/jfrog-cli-go/artifactory/commands/generic"
    19  	"github.com/jfrog/jfrog-cli-go/artifactory/spec"
    20  	"github.com/jfrog/jfrog-cli-go/utils/cliutils"
    21  	"github.com/jfrog/jfrog-cli-go/utils/config"
    22  	"github.com/jfrog/jfrog-client-go/artifactory/services/utils"
    23  	"github.com/jfrog/jfrog-client-go/utils/errorutils"
    24  	"github.com/jfrog/jfrog-client-go/utils/io/fileutils"
    25  	"github.com/jfrog/jfrog-client-go/utils/log"
    26  )
    27  
    28  var RtUrl *string
    29  var RtUser *string
    30  var RtPassword *string
    31  var RtApiKey *string
    32  var RtSshKeyPath *string
    33  var RtSshPassphrase *string
    34  var RtAccessToken *string
    35  var RtDistributionUrl *string
    36  var BtUser *string
    37  var BtKey *string
    38  var BtOrg *string
    39  var TestArtifactory *bool
    40  var TestBintray *bool
    41  var TestArtifactoryProxy *bool
    42  var TestDistribution *bool
    43  var TestDocker *bool
    44  var TestGo *bool
    45  var TestNpm *bool
    46  var TestGradle *bool
    47  var TestMaven *bool
    48  var DockerRepoDomain *string
    49  var DockerTargetRepo *string
    50  var TestNuget *bool
    51  var HideUnitTestLog *bool
    52  var TestPip *bool
    53  var PipVirtualEnv *string
    54  
    55  func init() {
    56  	RtUrl = flag.String("rt.url", "http://127.0.0.1:8081/artifactory/", "Artifactory url")
    57  	RtUser = flag.String("rt.user", "admin", "Artifactory username")
    58  	RtPassword = flag.String("rt.password", "password", "Artifactory password")
    59  	RtApiKey = flag.String("rt.apikey", "", "Artifactory user API key")
    60  	RtSshKeyPath = flag.String("rt.sshKeyPath", "", "Ssh key file path")
    61  	RtSshPassphrase = flag.String("rt.sshPassphrase", "", "Ssh key passphrase")
    62  	RtAccessToken = flag.String("rt.accessToken", "", "Artifactory access token")
    63  	RtDistributionUrl = flag.String("rt.distUrl", "", "Distribution url")
    64  	TestArtifactory = flag.Bool("test.artifactory", false, "Test Artifactory")
    65  	TestArtifactoryProxy = flag.Bool("test.artifactoryProxy", false, "Test Artifactory proxy")
    66  	TestBintray = flag.Bool("test.bintray", false, "Test Bintray")
    67  	BtUser = flag.String("bt.user", "", "Bintray username")
    68  	BtKey = flag.String("bt.key", "", "Bintray API Key")
    69  	BtOrg = flag.String("bt.org", "", "Bintray organization")
    70  	TestDistribution = flag.Bool("test.distribution", false, "Test distribution")
    71  	TestDocker = flag.Bool("test.docker", false, "Test Docker build")
    72  	TestGo = flag.Bool("test.go", false, "Test Go")
    73  	TestNpm = flag.Bool("test.npm", false, "Test Npm")
    74  	TestGradle = flag.Bool("test.gradle", false, "Test Gradle")
    75  	TestMaven = flag.Bool("test.maven", false, "Test Maven")
    76  	DockerRepoDomain = flag.String("rt.dockerRepoDomain", "", "Docker repository domain")
    77  	DockerTargetRepo = flag.String("rt.dockerTargetRepo", "", "Docker repository domain")
    78  	TestNuget = flag.Bool("test.nuget", false, "Test Nuget")
    79  	HideUnitTestLog = flag.Bool("test.hideUnitTestLog", false, "Hide unit tests logs and print it in a file")
    80  	TestPip = flag.Bool("test.pip", false, "Test Pip")
    81  	PipVirtualEnv = flag.String("rt.pipVirtualEnv", "", "Pip virtual-environment path")
    82  }
    83  
    84  func CleanFileSystem() {
    85  	removeDirs(Out, Temp)
    86  }
    87  
    88  func removeDirs(dirs ...string) {
    89  	for _, dir := range dirs {
    90  		isExist, err := fileutils.IsDirExists(dir, false)
    91  		if err != nil {
    92  			log.Error(err)
    93  		}
    94  		if isExist {
    95  			os.RemoveAll(dir)
    96  		}
    97  	}
    98  }
    99  
   100  func VerifyExistLocally(expected, actual []string, t *testing.T) {
   101  	if len(actual) == 0 && len(expected) != 0 {
   102  		t.Error("Couldn't find all expected files, expected: " + strconv.Itoa(len(expected)) + ", found: " + strconv.Itoa(len(actual)))
   103  	}
   104  	err := compare(expected, actual)
   105  	assert.NoError(t, err)
   106  }
   107  
   108  func ValidateListsIdentical(expected, actual []string) error {
   109  	if len(actual) != len(expected) {
   110  		return errors.New("Unexpected behavior, expected: " + strconv.Itoa(len(expected)) + " files, found: " + strconv.Itoa(len(actual)))
   111  	}
   112  	err := compare(expected, actual)
   113  	return err
   114  }
   115  
   116  func ValidateChecksums(filePath string, expectedChecksum fileutils.ChecksumDetails, t *testing.T) {
   117  	localFileDetails, err := fileutils.GetFileDetails(filePath)
   118  	if err != nil {
   119  		t.Error("Couldn't calculate sha1, " + err.Error())
   120  	}
   121  	if localFileDetails.Checksum.Sha1 != expectedChecksum.Sha1 {
   122  		t.Error("sha1 mismatch for "+filePath+", expected: "+expectedChecksum.Sha1, "found: "+localFileDetails.Checksum.Sha1)
   123  	}
   124  	if localFileDetails.Checksum.Md5 != expectedChecksum.Md5 {
   125  		t.Error("md5 mismatch for "+filePath+", expected: "+expectedChecksum.Md5, "found: "+localFileDetails.Checksum.Sha1)
   126  	}
   127  	if localFileDetails.Checksum.Sha256 != expectedChecksum.Sha256 {
   128  		t.Error("sha256 mismatch for "+filePath+", expected: "+expectedChecksum.Sha256, "found: "+localFileDetails.Checksum.Sha1)
   129  	}
   130  }
   131  
   132  func compare(expected, actual []string) error {
   133  	for _, v := range expected {
   134  		for i, r := range actual {
   135  			if v == r {
   136  				break
   137  			}
   138  			if i == len(actual)-1 {
   139  				return errors.New("Missing file : " + v)
   140  			}
   141  		}
   142  	}
   143  	return nil
   144  }
   145  
   146  func getPathsFromSearchResults(searchResults []generic.SearchResult) []string {
   147  	var paths []string
   148  	for _, result := range searchResults {
   149  		paths = append(paths, result.Path)
   150  	}
   151  	return paths
   152  }
   153  
   154  func CompareExpectedVsActual(expected []string, actual []generic.SearchResult, t *testing.T) {
   155  	if len(actual) != len(expected) {
   156  		t.Error(fmt.Sprintf("Unexpected behavior, expected: %s, \n%s\nfound: %s \n%s", strconv.Itoa(len(expected)), expected, strconv.Itoa(len(actual)), getPathsFromSearchResults(actual)))
   157  	}
   158  	for _, v := range expected {
   159  		for i, r := range actual {
   160  			if v == r.Path {
   161  				break
   162  			}
   163  			if i == len(actual)-1 {
   164  				t.Error("Missing file: " + v)
   165  			}
   166  		}
   167  	}
   168  
   169  	for _, r := range actual {
   170  		found := false
   171  		for _, v := range expected {
   172  			if v == r.Path {
   173  				found = true
   174  				break
   175  			}
   176  		}
   177  		if !found {
   178  			t.Error("Unexpected file: " + r.Path)
   179  		}
   180  	}
   181  }
   182  
   183  func GetTestResourcesPath() string {
   184  	dir, _ := os.Getwd()
   185  	return filepath.ToSlash(dir + "/testsdata/")
   186  }
   187  
   188  func GetFilePathForBintray(filename, path string, a ...string) string {
   189  	for i := 0; i < len(a); i++ {
   190  		path += a[i] + "/"
   191  	}
   192  	if filename != "" {
   193  		path += filename
   194  	}
   195  	return path
   196  }
   197  
   198  func GetFilePathForArtifactory(fileName string) string {
   199  	return GetTestResourcesPath() + "specs/" + fileName
   200  }
   201  
   202  func GetTestsLogsDir() (string, error) {
   203  	tempDirPath := filepath.Join(cliutils.GetCliPersistentTempDirPath(), "jfrog_tests_logs")
   204  	return tempDirPath, fileutils.CreateDirIfNotExist(tempDirPath)
   205  }
   206  
   207  type PackageSearchResultItem struct {
   208  	Name      string
   209  	Path      string
   210  	Package   string
   211  	Version   string
   212  	Repo      string
   213  	Owner     string
   214  	Created   string
   215  	Size      int64
   216  	Sha1      string
   217  	Published bool
   218  }
   219  
   220  type JfrogCli struct {
   221  	main        func() error
   222  	prefix      string
   223  	credentials string
   224  }
   225  
   226  func NewJfrogCli(mainFunc func() error, prefix, credentials string) *JfrogCli {
   227  	return &JfrogCli{mainFunc, prefix, credentials}
   228  }
   229  
   230  func (cli *JfrogCli) Exec(args ...string) error {
   231  	spaceSplit := " "
   232  	os.Args = strings.Split(cli.prefix, spaceSplit)
   233  	output := strings.Split(cli.prefix, spaceSplit)
   234  	for _, v := range args {
   235  		if v == "" {
   236  			continue
   237  		}
   238  		args := strings.Split(v, spaceSplit)
   239  		os.Args = append(os.Args, args...)
   240  		output = append(output, args...)
   241  	}
   242  	if cli.credentials != "" {
   243  		args := strings.Split(cli.credentials, spaceSplit)
   244  		os.Args = append(os.Args, args...)
   245  	}
   246  
   247  	log.Info("[Command]", strings.Join(output, " "))
   248  	return cli.main()
   249  }
   250  
   251  func (cli *JfrogCli) LegacyBuildToolExec(args ...string) error {
   252  	spaceSplit := " "
   253  	os.Args = strings.Split(cli.prefix, spaceSplit)
   254  	output := strings.Split(cli.prefix, spaceSplit)
   255  	for _, v := range args {
   256  		if v == "" {
   257  			continue
   258  		}
   259  		os.Args = append(os.Args, v)
   260  		output = append(output, v)
   261  	}
   262  	if cli.credentials != "" {
   263  		args := strings.Split(cli.credentials, spaceSplit)
   264  		os.Args = append(os.Args, args...)
   265  	}
   266  
   267  	log.Info("[Command]", strings.Join(output, " "))
   268  	return cli.main()
   269  }
   270  
   271  func (cli *JfrogCli) WithSuffix(suffix string) *JfrogCli {
   272  	return &JfrogCli{cli.main, cli.prefix, suffix}
   273  }
   274  
   275  type gitManager struct {
   276  	dotGitPath string
   277  }
   278  
   279  func GitExecutor(dotGitPath string) *gitManager {
   280  	return &gitManager{dotGitPath: dotGitPath}
   281  }
   282  
   283  func (m *gitManager) GetUrl() (string, string, error) {
   284  	return m.execGit("config", "--get", "remote.origin.url")
   285  }
   286  
   287  func (m *gitManager) GetRevision() (string, string, error) {
   288  	return m.execGit("show", "-s", "--format=%H", "HEAD")
   289  }
   290  
   291  func (m *gitManager) execGit(args ...string) (string, string, error) {
   292  	var stdout bytes.Buffer
   293  	var stderr bytes.Buffer
   294  	cmd := exec.Command("git", args...)
   295  	cmd.Dir = m.dotGitPath
   296  	cmd.Stdin = nil
   297  	cmd.Stdout = &stdout
   298  	cmd.Stderr = &stderr
   299  	err := cmd.Run()
   300  	errorutils.CheckError(err)
   301  	return strings.TrimSpace(stdout.String()), strings.TrimSpace(stderr.String()), err
   302  }
   303  
   304  // Prepare the .git environment for the test. Takes an existing folder and making it .git dir.
   305  // sourceDirPath - Relative path to the source dir to change to .git
   306  // targetDirPath - Relative path to the target created .git dir, usually 'testdata' under the parent dir.
   307  func PrepareDotGitDir(t *testing.T, sourceDirPath, targetDirPath string) (string, string) {
   308  	// Get path to create .git folder in
   309  	baseDir, _ := os.Getwd()
   310  	baseDir = filepath.Join(baseDir, targetDirPath)
   311  	// Create .git path and make sure it is clean
   312  	dotGitPath := filepath.Join(baseDir, ".git")
   313  	RemovePath(dotGitPath, t)
   314  	// Get the path of the .git candidate path
   315  	dotGitPathTest := filepath.Join(baseDir, sourceDirPath)
   316  	// Rename the .git candidate
   317  	RenamePath(dotGitPathTest, dotGitPath, t)
   318  	return baseDir, dotGitPath
   319  }
   320  
   321  // Removing the provided path from the filesystem
   322  func RemovePath(testPath string, t *testing.T) {
   323  	err := fileutils.RemovePath(testPath)
   324  	if err != nil {
   325  		t.Error(err)
   326  		t.FailNow()
   327  	}
   328  }
   329  
   330  // Renaming from old path to new path.
   331  func RenamePath(oldPath, newPath string, t *testing.T) {
   332  	err := fileutils.RenamePath(oldPath, newPath)
   333  	if err != nil {
   334  		t.Error(err)
   335  		t.FailNow()
   336  	}
   337  }
   338  
   339  func DeleteFiles(deleteSpec *spec.SpecFiles, artifactoryDetails *config.ArtifactoryDetails) (successCount, failCount int, err error) {
   340  	deleteCommand := generic.NewDeleteCommand()
   341  	deleteCommand.SetThreads(3).SetSpec(deleteSpec).SetRtDetails(artifactoryDetails).SetDryRun(false)
   342  	err = deleteCommand.GetPathsToDelete()
   343  	if err != nil {
   344  		return 0, 0, err
   345  	}
   346  
   347  	return deleteCommand.DeleteFiles()
   348  }
   349  
   350  func GetNonVirtualRepositories() map[string]string {
   351  	nonVirtualRepos := map[string]string{
   352  		Repo1:             SpecsTestRepositoryConfig,
   353  		Repo2:             MoveRepositoryConfig,
   354  		LfsRepo:           GitLfsTestRepositoryConfig,
   355  		DebianRepo:        DebianTestRepositoryConfig,
   356  		JcenterRemoteRepo: JcenterRemoteRepositoryConfig,
   357  	}
   358  	if *TestNpm {
   359  		nonVirtualRepos[NpmLocalRepo] = NpmLocalRepositoryConfig
   360  		nonVirtualRepos[NpmRemoteRepo] = NpmRemoteRepositoryConfig
   361  	}
   362  	if *TestPip {
   363  		nonVirtualRepos[PypiRemoteRepo] = PypiRemoteRepositoryConfig
   364  	}
   365  
   366  	return nonVirtualRepos
   367  }
   368  
   369  func GetVirtualRepositories() map[string]string {
   370  	virtualRepos := map[string]string{
   371  		VirtualRepo: VirtualRepositoryConfig,
   372  	}
   373  
   374  	if *TestPip {
   375  		virtualRepos[PypiVirtualRepo] = PypiVirtualRepositoryConfig
   376  	}
   377  
   378  	return virtualRepos
   379  }
   380  
   381  func getRepositoriesNameMap() map[string]string {
   382  	return map[string]string{
   383  		"${REPO1}":               Repo1,
   384  		"${REPO2}":               Repo2,
   385  		"${REPO_1_AND_2}":        Repo1And2,
   386  		"${VIRTUAL_REPO}":        VirtualRepo,
   387  		"${LFS_REPO}":            LfsRepo,
   388  		"${DEBIAN_REPO}":         DebianRepo,
   389  		"${JCENTER_REMOTE_REPO}": JcenterRemoteRepo,
   390  		"${NPM_LOCAL_REPO}":      NpmLocalRepo,
   391  		"${NPM_REMOTE_REPO}":     NpmRemoteRepo,
   392  		"${GO_REPO}":             GoLocalRepo,
   393  		"${RT_SERVER_ID}":        RtServerId,
   394  		"${RT_URL}":              *RtUrl,
   395  		"${RT_API_KEY}":          *RtApiKey,
   396  		"${RT_USERNAME}":         *RtUser,
   397  		"${RT_PASSWORD}":         *RtPassword,
   398  		"${RT_ACCESS_TOKEN}":     *RtAccessToken,
   399  		"${PYPI_REMOTE_REPO}":    PypiRemoteRepo,
   400  		"${PYPI_VIRTUAL_REPO}":   PypiVirtualRepo,
   401  	}
   402  }
   403  
   404  func ReplaceTemplateVariables(path, destPath string) (string, error) {
   405  	content, err := ioutil.ReadFile(path)
   406  	if err != nil {
   407  		return "", errorutils.CheckError(err)
   408  	}
   409  
   410  	repos := getRepositoriesNameMap()
   411  	for repoName, repoValue := range repos {
   412  		content = bytes.Replace(content, []byte(repoName), []byte(repoValue), -1)
   413  	}
   414  	if destPath == "" {
   415  		destPath, err = os.Getwd()
   416  		if err != nil {
   417  			return "", errorutils.CheckError(err)
   418  		}
   419  		destPath = filepath.Join(destPath, Temp)
   420  	}
   421  	err = os.MkdirAll(destPath, 0700)
   422  	if err != nil {
   423  		return "", errorutils.CheckError(err)
   424  	}
   425  	specPath := filepath.Join(destPath, filepath.Base(path))
   426  	log.Info("Creating spec file at:", specPath)
   427  	err = ioutil.WriteFile(specPath, []byte(content), 0700)
   428  	if err != nil {
   429  		return "", errorutils.CheckError(err)
   430  	}
   431  
   432  	return specPath, nil
   433  }
   434  
   435  func CreateSpec(fileName string) (string, error) {
   436  	searchFilePath := GetFilePathForArtifactory(fileName)
   437  	searchFilePath, err := ReplaceTemplateVariables(searchFilePath, "")
   438  	return searchFilePath, err
   439  }
   440  
   441  func ConvertSliceToMap(props []utils.Property) map[string]string {
   442  	propsMap := make(map[string]string)
   443  	for _, item := range props {
   444  		propsMap[item.Key] = item.Value
   445  	}
   446  	return propsMap
   447  }