github.com/jfrog/jfrog-cli@v1.54.1/artifactory_test.go (about)

     1  package main
     2  
     3  import (
     4  	"bytes"
     5  	"crypto/tls"
     6  	"encoding/csv"
     7  	"encoding/json"
     8  	"errors"
     9  	"fmt"
    10  	"github.com/jfrog/jfrog-cli-core/common/commands"
    11  	"github.com/jfrog/jfrog-client-go/artifactory"
    12  	"io"
    13  	"net"
    14  	"net/http"
    15  	"net/url"
    16  	"os"
    17  	"os/exec"
    18  	"path"
    19  	"path/filepath"
    20  	"reflect"
    21  	"sort"
    22  	"strconv"
    23  	"strings"
    24  	"testing"
    25  	"time"
    26  
    27  	"github.com/jfrog/jfrog-cli-core/utils/coreutils"
    28  	coretests "github.com/jfrog/jfrog-cli-core/utils/tests"
    29  
    30  	"github.com/buger/jsonparser"
    31  	gofrogio "github.com/jfrog/gofrog/io"
    32  	"github.com/jfrog/jfrog-cli-core/artifactory/commands/generic"
    33  	"github.com/jfrog/jfrog-cli-core/artifactory/spec"
    34  	"github.com/jfrog/jfrog-cli-core/artifactory/utils"
    35  	"github.com/jfrog/jfrog-cli-core/utils/config"
    36  	"github.com/jfrog/jfrog-cli/inttestutils"
    37  	"github.com/jfrog/jfrog-cli/utils/cliutils"
    38  	"github.com/jfrog/jfrog-cli/utils/tests"
    39  	cliproxy "github.com/jfrog/jfrog-cli/utils/tests/proxy/server"
    40  	"github.com/jfrog/jfrog-cli/utils/tests/proxy/server/certificate"
    41  	accessServices "github.com/jfrog/jfrog-client-go/access/services"
    42  	"github.com/jfrog/jfrog-client-go/artifactory/services"
    43  	rtutils "github.com/jfrog/jfrog-client-go/artifactory/services/utils"
    44  	"github.com/jfrog/jfrog-client-go/artifactory/services/utils/tests/xray"
    45  	"github.com/jfrog/jfrog-client-go/auth"
    46  	"github.com/jfrog/jfrog-client-go/http/httpclient"
    47  	clientutils "github.com/jfrog/jfrog-client-go/utils"
    48  	"github.com/jfrog/jfrog-client-go/utils/errorutils"
    49  	"github.com/jfrog/jfrog-client-go/utils/io/fileutils"
    50  	"github.com/jfrog/jfrog-client-go/utils/io/httputils"
    51  	"github.com/jfrog/jfrog-client-go/utils/log"
    52  	"github.com/mholt/archiver/v3"
    53  	"github.com/stretchr/testify/assert"
    54  )
    55  
    56  // JFrog CLI for Artifactory commands
    57  var artifactoryCli *tests.JfrogCli
    58  
    59  // JFrog CLI for config command only (doesn't pass the --ssh-passphrase flag)
    60  var configCli *tests.JfrogCli
    61  
    62  var serverDetails *config.ServerDetails
    63  var artAuth auth.ServiceDetails
    64  var artHttpDetails httputils.HttpClientDetails
    65  
    66  func InitArtifactoryTests() {
    67  	initArtifactoryCli()
    68  	cleanUpOldBuilds()
    69  	cleanUpOldRepositories()
    70  	cleanUpOldUsers()
    71  	tests.AddTimestampToGlobalVars()
    72  	createRequiredRepos()
    73  	cleanArtifactoryTest()
    74  }
    75  
    76  func authenticate(configCli bool) string {
    77  	serverDetails = &config.ServerDetails{ArtifactoryUrl: clientutils.AddTrailingSlashIfNeeded(*tests.RtUrl), SshKeyPath: *tests.RtSshKeyPath, SshPassphrase: *tests.RtSshPassphrase}
    78  	var cred string
    79  	if configCli {
    80  		cred += "--artifactory-url=" + *tests.RtUrl
    81  	} else {
    82  		cred += "--url=" + *tests.RtUrl
    83  	}
    84  	if !fileutils.IsSshUrl(serverDetails.ArtifactoryUrl) {
    85  		if *tests.RtApiKey != "" {
    86  			serverDetails.ApiKey = *tests.RtApiKey
    87  		} else if *tests.RtAccessToken != "" {
    88  			serverDetails.AccessToken = *tests.RtAccessToken
    89  		} else {
    90  			serverDetails.User = *tests.RtUser
    91  			serverDetails.Password = *tests.RtPassword
    92  		}
    93  	}
    94  	cred += getArtifactoryTestCredentials()
    95  	var err error
    96  	if artAuth, err = serverDetails.CreateArtAuthConfig(); err != nil {
    97  		coreutils.ExitOnErr(errors.New("Failed while attempting to authenticate with Artifactory: " + err.Error()))
    98  	}
    99  	serverDetails.ArtifactoryUrl = artAuth.GetUrl()
   100  	serverDetails.SshUrl = artAuth.GetSshUrl()
   101  	serverDetails.AccessUrl = clientutils.AddTrailingSlashIfNeeded(*tests.AccessUrl)
   102  	artHttpDetails = artAuth.CreateHttpClientDetails()
   103  	return cred
   104  }
   105  
   106  // A Jfrog CLI to be used to execute a config task.
   107  // Removed the ssh-passphrase flag that cannot be passed to with a config command
   108  func createConfigJfrogCLI(cred string) *tests.JfrogCli {
   109  	if strings.Contains(cred, " --ssh-passphrase=") {
   110  		cred = strings.Replace(cred, " --ssh-passphrase="+*tests.RtSshPassphrase, "", -1)
   111  	}
   112  	return tests.NewJfrogCli(execMain, "jfrog config", cred)
   113  }
   114  
   115  func getArtifactoryTestCredentials() string {
   116  	if fileutils.IsSshUrl(serverDetails.ArtifactoryUrl) {
   117  		return getSshCredentials()
   118  	}
   119  	if *tests.RtApiKey != "" {
   120  		return " --apikey=" + *tests.RtApiKey
   121  	}
   122  	if *tests.RtAccessToken != "" {
   123  		return " --access-token=" + *tests.RtAccessToken
   124  	}
   125  	return " --user=" + *tests.RtUser + " --password=" + *tests.RtPassword
   126  }
   127  
   128  func getSshCredentials() string {
   129  	cred := ""
   130  	if *tests.RtSshKeyPath != "" {
   131  		cred += " --ssh-key-path=" + *tests.RtSshKeyPath
   132  	}
   133  	if *tests.RtSshPassphrase != "" {
   134  		cred += " --ssh-passphrase=" + *tests.RtSshPassphrase
   135  	}
   136  	return cred
   137  }
   138  
   139  func TestArtifactorySimpleUploadSpec(t *testing.T) {
   140  	initArtifactoryTest(t)
   141  	specFile, err := tests.CreateSpec(tests.UploadFlatRecursive)
   142  	assert.NoError(t, err)
   143  	artifactoryCli.Exec("upload", "--spec="+specFile)
   144  	searchFilePath, err := tests.CreateSpec(tests.SearchRepo1ByInSuffix)
   145  	assert.NoError(t, err)
   146  	verifyExistInArtifactory(tests.GetSimpleUploadExpectedRepo1(), searchFilePath, t)
   147  	cleanArtifactoryTest()
   148  }
   149  
   150  func TestArtifactorySimpleUploadWithWildcardSpec(t *testing.T) {
   151  	initArtifactoryTest(t)
   152  	// Init tmp dir
   153  	specFile, err := tests.CreateSpec(tests.UploadTempWildcard)
   154  	assert.NoError(t, err)
   155  	err = fileutils.CopyDir(tests.GetTestResourcesPath()+"cache", filepath.Dir(specFile), true, nil)
   156  	assert.NoError(t, err)
   157  	// Upload
   158  	artifactoryCli.Exec("upload", "--spec="+specFile)
   159  	searchFilePath, err := tests.CreateSpec(tests.SearchRepo1ByInSuffix)
   160  	assert.NoError(t, err)
   161  	verifyExistInArtifactory(tests.GetSimpleWildcardUploadExpectedRepo1(), searchFilePath, t)
   162  	cleanArtifactoryTest()
   163  }
   164  
   165  // This test is similar to TestArtifactorySimpleUploadSpec but using "--server-id" flag
   166  func TestArtifactorySimpleUploadSpecUsingConfig(t *testing.T) {
   167  	initArtifactoryTest(t)
   168  	passphrase, err := createServerConfigAndReturnPassphrase()
   169  	defer deleteServerConfig()
   170  	assert.NoError(t, err)
   171  	artifactoryCommandExecutor := tests.NewJfrogCli(execMain, "jfrog rt", "")
   172  	specFile, err := tests.CreateSpec(tests.UploadFlatRecursive)
   173  	assert.NoError(t, err)
   174  	artifactoryCommandExecutor.Exec("upload", "--spec="+specFile, "--server-id="+tests.RtServerId, passphrase)
   175  
   176  	searchFilePath, err := tests.CreateSpec(tests.SearchRepo1ByInSuffix)
   177  	assert.NoError(t, err)
   178  	verifyExistInArtifactory(tests.GetSimpleUploadExpectedRepo1(), searchFilePath, t)
   179  	cleanArtifactoryTest()
   180  }
   181  
   182  func TestArtifactoryUploadPathWithSpecialCharsAsNoRegex(t *testing.T) {
   183  	initArtifactoryTest(t)
   184  	filePath := getSpecialCharFilePath()
   185  
   186  	artifactoryCli.Exec("upload", filePath, tests.RtRepo1)
   187  	searchFilePath, err := tests.CreateSpec(tests.SearchRepo1ByInSuffix)
   188  	assert.NoError(t, err)
   189  
   190  	verifyExistInArtifactory(tests.GetSimpleUploadSpecialCharNoRegexExpectedRepo1(), searchFilePath, t)
   191  	cleanArtifactoryTest()
   192  }
   193  
   194  func TestArtifactoryEmptyBuild(t *testing.T) {
   195  	initArtifactoryTest(t)
   196  	inttestutils.DeleteBuild(serverDetails.ArtifactoryUrl, tests.RtBuildName1, artHttpDetails)
   197  	buildNumber := "5"
   198  
   199  	// Try to upload with non existent pattern
   200  	err := artifactoryCli.Exec("upload", "*.notExist", tests.RtRepo1, "--build-name="+tests.RtBuildName1, "--build-number="+buildNumber)
   201  	assert.NoError(t, err)
   202  
   203  	// Try to download with non existent pattern
   204  	err = artifactoryCli.Exec("download", tests.RtRepo1+"/*.notExist", "--build-name="+tests.RtBuildName1, "--build-number="+buildNumber)
   205  	assert.NoError(t, err)
   206  
   207  	// Publish empty build info
   208  	err = artifactoryCli.Exec("build-publish", tests.RtBuildName1, buildNumber)
   209  	assert.NoError(t, err)
   210  
   211  	inttestutils.DeleteBuild(serverDetails.ArtifactoryUrl, tests.RtBuildName1, artHttpDetails)
   212  	cleanArtifactoryTest()
   213  }
   214  
   215  func TestArtifactoryDownloadFromVirtual(t *testing.T) {
   216  	initArtifactoryTest(t)
   217  
   218  	artifactoryCli.Exec("upload", "testdata/a/*", tests.RtRepo1, "--flat=false")
   219  	artifactoryCli.Exec("dl", tests.RtVirtualRepo+"/testdata/(*)", tests.Out+"/"+"{1}", "--flat=true")
   220  
   221  	paths, _ := fileutils.ListFilesRecursiveWalkIntoDirSymlink(tests.Out, false)
   222  	tests.VerifyExistLocally(tests.GetVirtualDownloadExpected(), paths, t)
   223  
   224  	cleanArtifactoryTest()
   225  }
   226  
   227  func TestArtifactoryDownloadPathWithSpecialChars(t *testing.T) {
   228  	initArtifactoryTest(t)
   229  	artifactoryCli.Exec("upload", getSpecialCharFilePath(), tests.RtRepo1, "--flat=false")
   230  	artifactoryCli.Exec("upload", "testdata/c#/a#1.in", tests.RtRepo1, "--flat=false")
   231  
   232  	artifactoryCli.Exec("dl", tests.RtRepo1+"/testdata/a$+~&^a#/a*", tests.Out+fileutils.GetFileSeparator(), "--flat=true")
   233  	artifactoryCli.Exec("dl", tests.RtRepo1+"/testdata/c#/a#1.in", tests.Out+fileutils.GetFileSeparator(), "--flat=true")
   234  
   235  	paths, _ := fileutils.ListFilesRecursiveWalkIntoDirSymlink(tests.Out, false)
   236  	tests.VerifyExistLocally([]string{filepath.Join(tests.Out, "a1.in"), filepath.Join(tests.Out, "a#1.in")}, paths, t)
   237  
   238  	cleanArtifactoryTest()
   239  }
   240  
   241  func TestArtifactoryDownloadPatternWithUnicodeChars(t *testing.T) {
   242  	initArtifactoryTest(t)
   243  	artifactoryCli.Exec("upload", "testdata/unicode/", tests.RtRepo1, "--flat=false")
   244  
   245  	// Verify files exist
   246  	specFile, err := tests.CreateSpec(tests.SearchAllRepo1)
   247  	assert.NoError(t, err)
   248  	verifyExistInArtifactory(tests.GetDownloadUnicode(), specFile, t)
   249  
   250  	artifactoryCli.Exec("dl", tests.RtRepo1+"/testdata/unicode/(dirλrectory)/", filepath.Join(tests.Out, "{1}")+fileutils.GetFileSeparator(), "--flat=true")
   251  
   252  	paths, _ := fileutils.ListFilesRecursiveWalkIntoDirSymlink(tests.Out, false)
   253  	err = tests.ValidateListsIdentical([]string{
   254  		tests.Out,
   255  		filepath.Join(tests.Out, "dirλrectory"),
   256  		filepath.Join(tests.Out, "dirλrectory", "文件.in"),
   257  		filepath.Join(tests.Out, "dirλrectory", "aȩ.ȥ1"),
   258  	}, paths)
   259  	assert.NoError(t, err)
   260  
   261  	cleanArtifactoryTest()
   262  }
   263  
   264  func TestArtifactoryConcurrentDownload(t *testing.T) {
   265  	testArtifactoryDownload(cliutils.DownloadMinSplitKb*1000, t)
   266  }
   267  
   268  func TestArtifactoryBulkDownload(t *testing.T) {
   269  	testArtifactoryDownload(cliutils.DownloadMinSplitKb*1000-1, t)
   270  }
   271  
   272  func testArtifactoryDownload(fileSize int, t *testing.T) {
   273  	initArtifactoryTest(t)
   274  	err := fileutils.CreateDirIfNotExist(tests.Out)
   275  	assert.NoError(t, err)
   276  	randFile, err := gofrogio.CreateRandFile(filepath.Join(tests.Out, "randFile"), fileSize)
   277  	assert.NoError(t, err)
   278  	localFileDetails, err := fileutils.GetFileDetails(randFile.Name())
   279  	assert.NoError(t, err)
   280  
   281  	artifactoryCli.Exec("u", randFile.Name(), tests.RtRepo1+"/testdata/", "--flat=true")
   282  	randFile.File.Close()
   283  	os.RemoveAll(tests.Out)
   284  	artifactoryCli.Exec("dl", tests.RtRepo1+"/testdata/", tests.Out+fileutils.GetFileSeparator(), "--flat=true")
   285  
   286  	paths, err := fileutils.ListFilesRecursiveWalkIntoDirSymlink(tests.Out, false)
   287  	assert.NoError(t, err)
   288  	tests.VerifyExistLocally([]string{filepath.Join(tests.Out, "randFile")}, paths, t)
   289  	tests.ValidateChecksums(filepath.Join(tests.Out, "randFile"), localFileDetails.Checksum, t)
   290  	cleanArtifactoryTest()
   291  }
   292  
   293  func TestArtifactoryDownloadWildcardInRepo(t *testing.T) {
   294  	initArtifactoryTest(t)
   295  	var filePath = getSpecialCharFilePath()
   296  
   297  	// Upload a file to repo1 and another one to repo2
   298  	artifactoryCli.Exec("upload", filePath, tests.RtRepo1+"/path/a1.in")
   299  	artifactoryCli.Exec("upload", filePath, tests.RtRepo2+"/path/a2.in")
   300  
   301  	specFile, err := tests.CreateSpec(tests.DownloadWildcardRepo)
   302  	assert.NoError(t, err)
   303  
   304  	// Verify the 2 files exist using `*` in the repository name
   305  	verifyExistInArtifactory(tests.GetDownloadWildcardRepo(), specFile, t)
   306  
   307  	// Download the 2 files with `*` in the repository name
   308  	artifactoryCli.Exec("dl", "--spec="+specFile)
   309  	paths, err := fileutils.ListFilesRecursiveWalkIntoDirSymlink(tests.Out, false)
   310  	assert.NoError(t, err)
   311  	tests.VerifyExistLocally([]string{filepath.Join(tests.Out, "a1.in"), filepath.Join(tests.Out, "a2.in")}, paths, t)
   312  	cleanArtifactoryTest()
   313  }
   314  
   315  func TestArtifactoryDownloadPlaceholderInRepo(t *testing.T) {
   316  	initArtifactoryTest(t)
   317  	var filePath = getSpecialCharFilePath()
   318  
   319  	// Upload a file to repo1 and another one to repo2
   320  	artifactoryCli.Exec("upload", filePath, tests.RtRepo1+"/path/a1.in")
   321  	artifactoryCli.Exec("upload", filePath, tests.RtRepo2+"/path/a2.in")
   322  
   323  	specFile, err := tests.CreateSpec(tests.DownloadWildcardRepo)
   324  	assert.NoError(t, err)
   325  
   326  	// Verify the 2 files exist
   327  	verifyExistInArtifactory(tests.GetDownloadWildcardRepo(), specFile, t)
   328  
   329  	// Download the 2 files with placeholders in the repository name
   330  	artifactoryCli.Exec("dl", tests.RtRepo1And2Placeholder, tests.Out+"/a/{1}/", "--flat=true")
   331  	paths, err := fileutils.ListFilesRecursiveWalkIntoDirSymlink(tests.Out, false)
   332  	assert.NoError(t, err)
   333  	tests.VerifyExistLocally([]string{filepath.Join(tests.Out, "a", "1", "a1.in"), filepath.Join(tests.Out, "a", "2", "a2.in")}, paths, t)
   334  	cleanArtifactoryTest()
   335  }
   336  
   337  func TestArtifactoryCopySingleFileNonFlat(t *testing.T) {
   338  	initArtifactoryTest(t)
   339  	var filePath = getSpecialCharFilePath()
   340  
   341  	artifactoryCli.Exec("upload", filePath, tests.RtRepo1+"/path/")
   342  	artifactoryCli.Exec("cp", tests.RtRepo1+"/path/a1.in", tests.RtRepo2)
   343  	searchPath, err := tests.CreateSpec(tests.SearchRepo2)
   344  	assert.NoError(t, err)
   345  	verifyExistInArtifactory(tests.GetSingleFileCopy(), searchPath, t)
   346  	cleanArtifactoryTest()
   347  }
   348  
   349  func TestArtifactoryCopyPrefixFilesFlat(t *testing.T) {
   350  	initArtifactoryTest(t)
   351  
   352  	artifactoryCli.Exec("upload", "testdata/prefix/(*)", tests.RtRepo1+"/prefix/prefix-{1}")
   353  	artifactoryCli.Exec("cp", tests.RtRepo1+"/prefix/*", tests.RtRepo2, "--flat")
   354  	searchPath, err := tests.CreateSpec(tests.SearchRepo2)
   355  	assert.NoError(t, err)
   356  	verifyExistInArtifactory(tests.GetPrefixFilesCopy(), searchPath, t)
   357  	cleanArtifactoryTest()
   358  }
   359  
   360  func TestAqlFindingItemOnRoot(t *testing.T) {
   361  	initArtifactoryTest(t)
   362  	var filePath = getSpecialCharFilePath()
   363  
   364  	artifactoryCli.Exec("upload", filePath, tests.RtRepo1+"/path/inner/")
   365  	artifactoryCli.Exec("upload", filePath, tests.RtRepo1+"/someFile", "--flat=true")
   366  	artifactoryCli.Exec("cp", tests.RtRepo1+"/*", tests.RtRepo2)
   367  	searchPath, err := tests.CreateSpec(tests.SearchRepo2)
   368  	assert.NoError(t, err)
   369  	verifyExistInArtifactory(tests.GetAnyItemCopy(), searchPath, t)
   370  	artifactoryCli.Exec("del", tests.RtRepo2+"/*")
   371  	artifactoryCli.Exec("del", tests.RtRepo1+"/*")
   372  	artifactoryCli.Exec("upload", filePath, tests.RtRepo1+"/path/")
   373  	artifactoryCli.Exec("upload", filePath, tests.RtRepo1+"/someFile", "--flat=true")
   374  	artifactoryCli.Exec("cp", tests.RtRepo1+"/*/", tests.RtRepo2)
   375  	verifyExistInArtifactory(tests.GetSingleFileCopy(), searchPath, t)
   376  	cleanArtifactoryTest()
   377  }
   378  
   379  func TestExitCode(t *testing.T) {
   380  	initArtifactoryTest(t)
   381  
   382  	// Upload dummy file in order to test move and copy commands
   383  	artifactoryCli.Exec("upload", path.Join("testdata", "a", "a1.in"), tests.RtRepo1)
   384  
   385  	// Discard output logging to prevent negative logs
   386  	previousLogger := tests.RedirectLogOutputToNil()
   387  	defer log.SetLogger(previousLogger)
   388  
   389  	// Test upload commands
   390  	err := artifactoryCli.Exec("upload", "DummyText", tests.RtRepo1, "--fail-no-op=true")
   391  	checkExitCode(t, coreutils.ExitCodeError, err)
   392  	err = artifactoryCli.Exec("upload", path.Join("testdata", "a", "a1.in"), "DummyTargetPath")
   393  	checkExitCode(t, coreutils.ExitCodeError, err)
   394  	err = artifactoryCli.Exec("upload", "testdata/a/(*.dummyExt)", tests.RtRepo1+"/{1}.in", "--fail-no-op=true")
   395  	checkExitCode(t, coreutils.ExitCodeFailNoOp, err)
   396  
   397  	// Test download command
   398  	err = artifactoryCli.Exec("dl", "DummyFolder", "--fail-no-op=true")
   399  	checkExitCode(t, coreutils.ExitCodeFailNoOp, err)
   400  
   401  	// Test move commands
   402  	err = artifactoryCli.Exec("move", tests.RtRepo1, "DummyTargetPath")
   403  	checkExitCode(t, coreutils.ExitCodeError, err)
   404  	err = artifactoryCli.Exec("move", "DummyText", tests.RtRepo1, "--fail-no-op=true")
   405  	checkExitCode(t, coreutils.ExitCodeFailNoOp, err)
   406  
   407  	// Test copy commands
   408  	err = artifactoryCli.Exec("copy", tests.RtRepo1, "DummyTargetPath")
   409  	checkExitCode(t, coreutils.ExitCodeError, err)
   410  	err = artifactoryCli.Exec("copy", "DummyText", tests.RtRepo1, "--fail-no-op=true")
   411  	checkExitCode(t, coreutils.ExitCodeFailNoOp, err)
   412  
   413  	// Test delete command
   414  	err = artifactoryCli.Exec("delete", "DummyText", "--fail-no-op=true")
   415  	checkExitCode(t, coreutils.ExitCodeFailNoOp, err)
   416  
   417  	// Test search command
   418  	err = artifactoryCli.Exec("s", "DummyText", "--fail-no-op=true")
   419  	checkExitCode(t, coreutils.ExitCodeFailNoOp, err)
   420  
   421  	// Test props commands
   422  	err = artifactoryCli.Exec("sp", "DummyText", "prop=val;key=value", "--fail-no-op=true")
   423  	checkExitCode(t, coreutils.ExitCodeFailNoOp, err)
   424  	err = artifactoryCli.Exec("delp", "DummyText", "prop=val;key=value", "--fail-no-op=true")
   425  	checkExitCode(t, coreutils.ExitCodeFailNoOp, err)
   426  
   427  	cleanArtifactoryTest()
   428  }
   429  
   430  func checkExitCode(t *testing.T, expected coreutils.ExitCode, er error) {
   431  	switch underlyingType := er.(type) {
   432  	case coreutils.CliError:
   433  		assert.Equal(t, expected, underlyingType.ExitCode)
   434  	default:
   435  		assert.Fail(t, "Exit code expected error code %v, got %v", expected.Code, er)
   436  	}
   437  }
   438  func TestArtifactoryDirectoryCopy(t *testing.T) {
   439  	initArtifactoryTest(t)
   440  	var filePath = getSpecialCharFilePath()
   441  
   442  	artifactoryCli.Exec("upload", filePath, tests.RtRepo1+"/path/")
   443  	artifactoryCli.Exec("cp", tests.RtRepo1+"/path/", tests.RtRepo2)
   444  	searchPath, err := tests.CreateSpec(tests.SearchRepo2)
   445  	assert.NoError(t, err)
   446  	verifyExistInArtifactory(tests.GetSingleFileCopy(), searchPath, t)
   447  	cleanArtifactoryTest()
   448  }
   449  
   450  func TestArtifactoryDirectoryCopyUsingWildcard(t *testing.T) {
   451  	initArtifactoryTest(t)
   452  	var filePath = getSpecialCharFilePath()
   453  
   454  	artifactoryCli.Exec("upload", filePath, tests.RtRepo1+"/path/")
   455  	artifactoryCli.Exec("cp", tests.RtRepo1+"/*/", tests.RtRepo2)
   456  	searchPath, err := tests.CreateSpec(tests.SearchRepo2)
   457  	assert.NoError(t, err)
   458  	verifyExistInArtifactory(tests.GetSingleFileCopy(), searchPath, t)
   459  	cleanArtifactoryTest()
   460  }
   461  
   462  func TestArtifactoryCopyFilesNameWithParentheses(t *testing.T) {
   463  	initArtifactoryTest(t)
   464  
   465  	artifactoryCli.Exec("upload", "testdata/b/*", tests.RtRepo1, "--flat=false")
   466  	artifactoryCli.Exec("cp", tests.RtRepo1+"/testdata/b/(/(.in", tests.RtRepo2)
   467  	artifactoryCli.Exec("cp", tests.RtRepo1+"/testdata/b/(b/(b.in", tests.RtRepo2)
   468  	artifactoryCli.Exec("cp", tests.RtRepo1+"/testdata/b/b(/b(.in", tests.RtRepo2)
   469  	artifactoryCli.Exec("cp", tests.RtRepo1+"/testdata/b/b)/b).in", tests.RtRepo2)
   470  	artifactoryCli.Exec("cp", tests.RtRepo1+"/testdata/b/(b)/(b).in", tests.RtRepo2)
   471  	artifactoryCli.Exec("cp", tests.RtRepo1+"/testdata/b/)b/)b.in", tests.RtRepo2)
   472  	artifactoryCli.Exec("cp", tests.RtRepo1+"/testdata/b/)b)/)b).in", tests.RtRepo2)
   473  	artifactoryCli.Exec("cp", tests.RtRepo1+"/testdata/b/(b/(b.in", tests.RtRepo2+"/()/", "--flat=true")
   474  	artifactoryCli.Exec("cp", tests.RtRepo1+"/testdata/b/(b)/(b).in", tests.RtRepo2+"/()/")
   475  	artifactoryCli.Exec("cp", tests.RtRepo1+"/testdata/b/b(/b(.in", tests.RtRepo2+"/(/", "--flat=true")
   476  	artifactoryCli.Exec("cp", tests.RtRepo1+"/testdata/b/(/(*.in)", tests.RtRepo2+"/c/{1}.zip", "--flat=true")
   477  	artifactoryCli.Exec("cp", tests.RtRepo1+"/testdata/b/(/(*.in)", tests.RtRepo2+"/(/{1}.zip")
   478  	artifactoryCli.Exec("cp", tests.RtRepo1+"/testdata/b/b(/(b*.in)", tests.RtRepo2+"/(/{1}-up", "--flat=true")
   479  	artifactoryCli.Exec("cp", tests.RtRepo1+"/testdata/b/b(/(*).(*)", tests.RtRepo2+"/(/{2}-{1}", "--flat=true")
   480  
   481  	searchPath, err := tests.CreateSpec(tests.SearchRepo2)
   482  	assert.NoError(t, err)
   483  	verifyExistInArtifactory(tests.GetCopyFileNameWithParentheses(), searchPath, t)
   484  
   485  	cleanArtifactoryTest()
   486  }
   487  
   488  func TestArtifactoryCreateUsers(t *testing.T) {
   489  	initArtifactoryTest(t)
   490  	usersCSVPath := "testdata/usersmanagement/users.csv"
   491  	randomUsersCSVPath, err := tests.ReplaceTemplateVariables(usersCSVPath, "")
   492  	assert.NoError(t, err)
   493  	err = artifactoryCli.Exec("users-create", "--csv="+randomUsersCSVPath)
   494  	// Clean up
   495  	defer func() {
   496  		err = artifactoryCli.Exec("users-delete", "--csv="+randomUsersCSVPath)
   497  		assert.NoError(t, err)
   498  		cleanArtifactoryTest()
   499  	}()
   500  	assert.NoError(t, err)
   501  
   502  	verifyUsersExistInArtifactory(randomUsersCSVPath, t)
   503  }
   504  
   505  func verifyUsersExistInArtifactory(csvFilePath string, t *testing.T) {
   506  	// Parse input CSV
   507  	content, err := os.Open(csvFilePath)
   508  	assert.NoError(t, err)
   509  	csvReader := csv.NewReader(content)
   510  	// Ignore the header
   511  	csvReader.Read()
   512  	for {
   513  		// Read each record from csv
   514  		record, err := csvReader.Read()
   515  		if err == io.EOF {
   516  			break
   517  		}
   518  		user, password := record[0], record[1]
   519  		err = tests.NewJfrogCli(execMain, "jfrog rt", "--url="+serverDetails.ArtifactoryUrl+" --user="+user+" --password="+password).Exec("ping")
   520  		assert.NoError(t, err)
   521  	}
   522  
   523  }
   524  
   525  func TestArtifactoryUploadFilesNameWithParenthesis(t *testing.T) {
   526  	initArtifactoryTest(t)
   527  
   528  	specFile, err := tests.CreateSpec(tests.UploadFileWithParenthesesSpec)
   529  	assert.NoError(t, err)
   530  	artifactoryCli.Exec("upload", "--spec="+specFile)
   531  
   532  	searchPath, err := tests.CreateSpec(tests.SearchAllRepo1)
   533  	assert.NoError(t, err)
   534  	verifyExistInArtifactory(tests.GetUploadFileNameWithParentheses(), searchPath, t)
   535  
   536  	cleanArtifactoryTest()
   537  }
   538  
   539  func TestArtifactoryDownloadFilesNameWithParenthesis(t *testing.T) {
   540  	initArtifactoryTest(t)
   541  
   542  	artifactoryCli.Exec("upload", "testdata/b/*", tests.RtRepo1, "--flat=false")
   543  	artifactoryCli.Exec("download", path.Join(tests.RtRepo1), tests.Out+"/")
   544  
   545  	paths, err := fileutils.ListFilesRecursiveWalkIntoDirSymlink(tests.Out, false)
   546  	assert.NoError(t, err)
   547  	tests.VerifyExistLocally(tests.GetFileWithParenthesesDownload(), paths, t)
   548  
   549  	cleanArtifactoryTest()
   550  }
   551  func TestArtifactoryDownloadDotAsTarget(t *testing.T) {
   552  	initArtifactoryTest(t)
   553  	assert.NoError(t, fileutils.CreateDirIfNotExist(tests.Out))
   554  	randFile, err := gofrogio.CreateRandFile(filepath.Join(tests.Out, "DownloadDotAsTarget"), 100000)
   555  	randFile.File.Close()
   556  	assert.NoError(t, artifactoryCli.Exec("upload", tests.Out+"/*", tests.RtRepo1+"/p-modules/", "--flat=true"))
   557  	assert.NoError(t, os.RemoveAll(tests.Out))
   558  	assert.NoError(t, fileutils.CreateDirIfNotExist(tests.Out))
   559  
   560  	wd, err := os.Getwd()
   561  	assert.NoError(t, err)
   562  	os.Chdir(tests.Out)
   563  
   564  	assert.NoError(t, artifactoryCli.Exec("download", tests.RtRepo1+"/p-modules/DownloadDotAsTarget", "."))
   565  	assert.NoError(t, os.Chdir(wd))
   566  
   567  	paths, err := fileutils.ListFilesRecursiveWalkIntoDirSymlink(tests.Out, false)
   568  	assert.NoError(t, err)
   569  	tests.VerifyExistLocally([]string{tests.Out, filepath.Join(tests.Out, "p-modules"), filepath.Join(tests.Out, "p-modules", "DownloadDotAsTarget")}, paths, t)
   570  	os.RemoveAll(tests.Out)
   571  	cleanArtifactoryTest()
   572  }
   573  
   574  func TestArtifactoryDirectoryCopyUsingWildcardFlat(t *testing.T) {
   575  	initArtifactoryTest(t)
   576  	var filePath = getSpecialCharFilePath()
   577  
   578  	artifactoryCli.Exec("upload", filePath, tests.RtRepo1+"/path/inner/")
   579  	artifactoryCli.Exec("cp", tests.RtRepo1+"/path/inner", tests.RtRepo2, "--flat=true")
   580  	searchPath, err := tests.CreateSpec(tests.SearchRepo2)
   581  	assert.NoError(t, err)
   582  
   583  	verifyExistInArtifactory(tests.GetSingleDirectoryCopyFlat(), searchPath, t)
   584  	cleanArtifactoryTest()
   585  }
   586  
   587  func TestArtifactoryCopyPathsTwice(t *testing.T) {
   588  	initArtifactoryTest(t)
   589  	var filePath = getSpecialCharFilePath()
   590  	artifactoryCli.Exec("upload", filePath, tests.RtRepo1+"/path/inner/")
   591  
   592  	log.Info("Copy Folder to root twice")
   593  	artifactoryCli.Exec("cp", tests.RtRepo1+"/path", tests.RtRepo2)
   594  	searchPath, err := tests.CreateSpec(tests.SearchRepo2)
   595  	assert.NoError(t, err)
   596  
   597  	verifyExistInArtifactory(tests.GetSingleFileCopyFullPath(), searchPath, t)
   598  	artifactoryCli.Exec("cp", tests.RtRepo1+"/path", tests.RtRepo2)
   599  	verifyExistInArtifactory(tests.GetSingleFileCopyFullPath(), searchPath, t)
   600  	artifactoryCli.Exec("del", tests.RtRepo2)
   601  
   602  	log.Info("Copy to from repo1/path to repo2/path twice")
   603  	artifactoryCli.Exec("cp", tests.RtRepo1+"/path", tests.RtRepo2+"/path")
   604  	verifyExistInArtifactory(tests.GetSingleFileCopyFullPath(), searchPath, t)
   605  	artifactoryCli.Exec("cp", tests.RtRepo1+"/path", tests.RtRepo2+"/path")
   606  	verifyExistInArtifactory(tests.GetFolderCopyTwice(), searchPath, t)
   607  	artifactoryCli.Exec("del", tests.RtRepo2)
   608  
   609  	log.Info("Copy to from repo1/path/ to repo2/path/ twice")
   610  	artifactoryCli.Exec("cp", tests.RtRepo1+"/path/", tests.RtRepo2+"/path/")
   611  	verifyExistInArtifactory(tests.GetSingleInnerFileCopyFullPath(), searchPath, t)
   612  	artifactoryCli.Exec("cp", tests.RtRepo1+"/path/", tests.RtRepo2+"/path/")
   613  	verifyExistInArtifactory(tests.GetSingleInnerFileCopyFullPath(), searchPath, t)
   614  	artifactoryCli.Exec("del", tests.RtRepo2)
   615  
   616  	log.Info("Copy to from repo1/path/ to repo2/path/ twice")
   617  	artifactoryCli.Exec("cp", tests.RtRepo1+"/path", tests.RtRepo2+"/path/")
   618  	verifyExistInArtifactory(tests.GetFolderCopyIntoFolder(), searchPath, t)
   619  	artifactoryCli.Exec("cp", tests.RtRepo1+"/path", tests.RtRepo2+"/path/")
   620  	verifyExistInArtifactory(tests.GetFolderCopyIntoFolder(), searchPath, t)
   621  	artifactoryCli.Exec("del", tests.RtRepo2)
   622  
   623  	cleanArtifactoryTest()
   624  }
   625  
   626  func TestArtifactoryDirectoryCopyPatternEndsWithSlash(t *testing.T) {
   627  	initArtifactoryTest(t)
   628  	var filePath = getSpecialCharFilePath()
   629  
   630  	artifactoryCli.Exec("upload", filePath, tests.RtRepo1+"/path/inner/")
   631  	artifactoryCli.Exec("cp", tests.RtRepo1+"/path/", tests.RtRepo2, "--flat=true")
   632  	searchPath, err := tests.CreateSpec(tests.SearchRepo2)
   633  	assert.NoError(t, err)
   634  	verifyExistInArtifactory(tests.GetAnyItemCopyUsingSpec(), searchPath, t)
   635  	cleanArtifactoryTest()
   636  }
   637  
   638  func TestArtifactoryCopyAnyItemUsingWildcardFlat(t *testing.T) {
   639  	initArtifactoryTest(t)
   640  	var filePath = getSpecialCharFilePath()
   641  
   642  	artifactoryCli.Exec("upload", filePath, tests.RtRepo1+"/path/inner/")
   643  	artifactoryCli.Exec("upload", filePath, tests.RtRepo1+"/someFile", "--flat=true")
   644  	artifactoryCli.Exec("cp", tests.RtRepo1+"/*", tests.RtRepo2)
   645  	searchPath, err := tests.CreateSpec(tests.SearchRepo2)
   646  	assert.NoError(t, err)
   647  
   648  	verifyExistInArtifactory(tests.GetAnyItemCopy(), searchPath, t)
   649  	cleanArtifactoryTest()
   650  }
   651  
   652  func TestArtifactoryCopyAnyItemRecursive(t *testing.T) {
   653  	initArtifactoryTest(t)
   654  	var filePath = getSpecialCharFilePath()
   655  
   656  	artifactoryCli.Exec("upload", filePath, tests.RtRepo1+"/a/b/")
   657  	artifactoryCli.Exec("upload", filePath, tests.RtRepo1+"/aFile", "--flat=true")
   658  	artifactoryCli.Exec("cp", tests.RtRepo1+"/a*", tests.RtRepo2, "--recursive=true")
   659  	searchPath, err := tests.CreateSpec(tests.SearchRepo2)
   660  	assert.NoError(t, err)
   661  	verifyExistInArtifactory(tests.GetAnyItemCopyRecursive(), searchPath, t)
   662  	cleanArtifactoryTest()
   663  }
   664  
   665  func TestArtifactoryCopyAndRenameFolder(t *testing.T) {
   666  	initArtifactoryTest(t)
   667  	var filePath = getSpecialCharFilePath()
   668  
   669  	artifactoryCli.Exec("upload", filePath, tests.RtRepo1+"/path/inner/")
   670  	artifactoryCli.Exec("cp", tests.RtRepo1+"/*", tests.RtRepo2+"/newPath")
   671  	searchPath, err := tests.CreateSpec(tests.SearchRepo2)
   672  	assert.NoError(t, err)
   673  	verifyExistInArtifactory(tests.GetCopyFolderRename(), searchPath, t)
   674  	cleanArtifactoryTest()
   675  }
   676  
   677  func TestArtifactoryCopyAnyItemUsingSpec(t *testing.T) {
   678  	initArtifactoryTest(t)
   679  	var filePath = getSpecialCharFilePath()
   680  
   681  	specFile, err := tests.CreateSpec(tests.CopyItemsSpec)
   682  	assert.NoError(t, err)
   683  	searchPath, err := tests.CreateSpec(tests.SearchRepo2)
   684  	assert.NoError(t, err)
   685  	artifactoryCli.Exec("upload", filePath, tests.RtRepo1+"/path/inner/")
   686  	artifactoryCli.Exec("upload", filePath, tests.RtRepo1+"/someFile", "--flat=true")
   687  	artifactoryCli.Exec("cp", "--spec="+specFile)
   688  	verifyExistInArtifactory(tests.GetAnyItemCopyUsingSpec(), searchPath, t)
   689  	cleanArtifactoryTest()
   690  }
   691  
   692  func getSpecialCharFilePath() string {
   693  	return "testdata/a$+~&^a#/a*"
   694  }
   695  
   696  func getAntPatternFilePath() string {
   697  	return "testdata/cache/downloa?/**/*.in"
   698  }
   699  
   700  func TestArtifactoryCopyNoSpec(t *testing.T) {
   701  	testCopyMoveNoSpec("cp", tests.GetBuildBeforeCopyExpected(), tests.GetBuildCopyExpected(), t)
   702  }
   703  
   704  func TestArtifactoryCopyExcludeByCli(t *testing.T) {
   705  	initArtifactoryTest(t)
   706  
   707  	// Upload files
   708  	specFileA, err := tests.CreateSpec(tests.SplitUploadSpecA)
   709  	assert.NoError(t, err)
   710  	specFileB, err := tests.CreateSpec(tests.SplitUploadSpecB)
   711  	assert.NoError(t, err)
   712  	artifactoryCli.Exec("upload", "--spec="+specFileA)
   713  	artifactoryCli.Exec("upload", "--spec="+specFileB)
   714  
   715  	// Copy by pattern
   716  	artifactoryCli.Exec("cp", tests.RtRepo1+"/data/", tests.RtRepo2+"/", "--exclude-patterns=*b*;*c*")
   717  
   718  	// Validate files are moved by build number
   719  	cpMvDlByBuildAssertSpec, err := tests.CreateSpec(tests.CpMvDlByBuildAssertSpec)
   720  	assert.NoError(t, err)
   721  	verifyExistInArtifactory(tests.GetBuildCopyExclude(), cpMvDlByBuildAssertSpec, t)
   722  
   723  	// Cleanup
   724  	cleanArtifactoryTest()
   725  }
   726  
   727  func TestArtifactoryCopyExcludeBySpec(t *testing.T) {
   728  	initArtifactoryTest(t)
   729  
   730  	// Upload files
   731  	specFileA, err := tests.CreateSpec(tests.SplitUploadSpecA)
   732  	assert.NoError(t, err)
   733  	specFileB, err := tests.CreateSpec(tests.SplitUploadSpecB)
   734  	assert.NoError(t, err)
   735  	artifactoryCli.Exec("upload", "--spec="+specFileA)
   736  	artifactoryCli.Exec("upload", "--spec="+specFileB)
   737  
   738  	// Copy by spec
   739  	specFile, err := tests.CreateSpec(tests.MoveCopySpecExclude)
   740  	assert.NoError(t, err)
   741  	artifactoryCli.Exec("cp", "--spec="+specFile)
   742  	cpMvDlByBuildAssertSpec, err := tests.CreateSpec(tests.CpMvDlByBuildAssertSpec)
   743  	assert.NoError(t, err)
   744  
   745  	// Validate files are moved by build number
   746  	verifyExistInArtifactory(tests.GetBuildCopyExclude(), cpMvDlByBuildAssertSpec, t)
   747  
   748  	// Cleanup
   749  	cleanArtifactoryTest()
   750  }
   751  
   752  func TestArtifactoryUploadDebian(t *testing.T) {
   753  	initArtifactoryTest(t)
   754  	specFile, err := tests.CreateSpec(tests.DebianUploadSpec)
   755  	assert.NoError(t, err)
   756  	artifactoryCli.Exec("upload", "--spec="+specFile, "--deb=bionic/main/i386")
   757  	verifyExistInArtifactoryByProps(tests.GetUploadDebianExpected(), tests.RtDebianRepo+"/*", "deb.distribution=bionic;deb.component=main;deb.architecture=i386", t)
   758  	artifactoryCli.Exec("upload", "--spec="+specFile, "--deb=cosmic/main\\/18.10/amd64")
   759  	verifyExistInArtifactoryByProps(tests.GetUploadDebianExpected(), tests.RtDebianRepo+"/*", "deb.distribution=cosmic;deb.component=main/18.10;deb.architecture=amd64", t)
   760  	cleanArtifactoryTest()
   761  }
   762  
   763  func TestArtifactoryUploadAndExplode(t *testing.T) {
   764  	initArtifactoryTest(t)
   765  	artifactoryCli.Exec("upload", filepath.Join("testdata", "archives", "a.zip"), tests.RtRepo1, "--explode=true")
   766  	searchFilePath, err := tests.CreateSpec(tests.SearchRepo1ByInSuffix)
   767  	assert.NoError(t, err)
   768  	verifyExistInArtifactory(tests.GetExplodeUploadExpectedRepo1(), searchFilePath, t)
   769  	cleanArtifactoryTest()
   770  }
   771  
   772  func TestArtifactoryUploadAndSyncDelete(t *testing.T) {
   773  	initArtifactoryTest(t)
   774  	// Upload all testdata/a/
   775  	artifactoryCli.Exec("upload", path.Join("testdata", "a", "*"), tests.RtRepo1+"/syncDir/", "--flat=false")
   776  	searchFilePath, err := tests.CreateSpec(tests.SearchAllRepo1)
   777  	assert.NoError(t, err)
   778  	verifyExistInArtifactory(tests.GetUploadExpectedRepo1SyncDeleteStep1(), searchFilePath, t)
   779  	// Upload testdata/a/b/*1.in and sync syncDir/testdata/a/b/
   780  	artifactoryCli.Exec("upload", path.Join("testdata", "a", "b", "*1.in"), tests.RtRepo1+"/syncDir/", "--sync-deletes="+tests.RtRepo1+"/syncDir/testdata/a/b/", "--flat=false")
   781  	searchFilePath, err = tests.CreateSpec(tests.SearchAllRepo1)
   782  	assert.NoError(t, err)
   783  	verifyExistInArtifactory(tests.GetUploadExpectedRepo1SyncDeleteStep2(), searchFilePath, t)
   784  	// Upload testdata/archives/* and sync syncDir/
   785  	artifactoryCli.Exec("upload", path.Join("testdata", "archives", "*"), tests.RtRepo1+"/syncDir/", "--sync-deletes="+tests.RtRepo1+"/syncDir/")
   786  	searchFilePath, err = tests.CreateSpec(tests.SearchAllRepo1)
   787  	assert.NoError(t, err)
   788  	verifyExistInArtifactory(tests.GetUploadExpectedRepo1SyncDeleteStep3(), searchFilePath, t)
   789  	// Upload testdata/b/ and sync syncDir/testdata/b/b
   790  	// Noticed that testdata/c/ includes sub folders with special chars like '-' and '#'
   791  	artifactoryCli.Exec("upload", path.Join("testdata", "c", "*"), tests.RtRepo1+"/syncDir/", "--sync-deletes="+tests.RtRepo1+"/syncDir/", "--flat=false")
   792  	searchFilePath, err = tests.CreateSpec(tests.SearchAllRepo1)
   793  	assert.NoError(t, err)
   794  	verifyExistInArtifactory(tests.GetUploadExpectedRepo1SyncDeleteStep4(), searchFilePath, t)
   795  
   796  	cleanArtifactoryTest()
   797  }
   798  
   799  func TestArtifactoryDownloadAndExplode(t *testing.T) {
   800  	initArtifactoryTest(t)
   801  	err := fileutils.CreateDirIfNotExist(tests.Out)
   802  	assert.NoError(t, err)
   803  
   804  	randFile, err := gofrogio.CreateRandFile(filepath.Join(tests.Out, "randFile"), 100000)
   805  	assert.NoError(t, err)
   806  
   807  	err = archiver.Archive([]string{randFile.Name()}, filepath.Join(tests.Out, "concurrent.tar.gz"))
   808  	assert.NoError(t, err)
   809  	err = archiver.Archive([]string{randFile.Name()}, filepath.Join(tests.Out, "bulk.tar"))
   810  	assert.NoError(t, err)
   811  	err = archiver.Archive([]string{randFile.Name()}, filepath.Join(tests.Out, "zipFile.zip"))
   812  	assert.NoError(t, err)
   813  	artifactoryCli.Exec("upload", tests.Out+"/*", tests.RtRepo1, "--flat=true")
   814  	randFile.File.Close()
   815  	os.RemoveAll(tests.Out)
   816  	// Download 'concurrent.tar.gz' as 'concurrent' file name and explode it.
   817  	assert.NoError(t, artifactoryCli.Exec("download", path.Join(tests.RtRepo1, "concurrent.tar.gz"), tests.Out+"/concurrent", "--explode=true"))
   818  	// Download 'concurrent.tar.gz' and explode it.
   819  	assert.NoError(t, artifactoryCli.Exec("download", path.Join(tests.RtRepo1, "concurrent.tar.gz"), tests.Out+"/", "--explode=true"))
   820  	// Download 'concurrent.tar.gz' without explode it.
   821  	assert.NoError(t, artifactoryCli.Exec("download", path.Join(tests.RtRepo1, "concurrent.tar.gz"), tests.Out+"/", "--explode=false"))
   822  	// Try to explode the archive that already been downloaded.
   823  	assert.NoError(t, artifactoryCli.Exec("download", path.Join(tests.RtRepo1, "concurrent.tar.gz"), tests.Out+"/", "--explode=true"))
   824  	os.RemoveAll(tests.Out)
   825  	assert.NoError(t, artifactoryCli.Exec("download", path.Join(tests.RtRepo1, "randFile"), tests.Out+"/", "--explode=true"))
   826  	assert.NoError(t, artifactoryCli.Exec("download", path.Join(tests.RtRepo1, "concurrent.tar.gz"), tests.Out+"/", "--explode=false"))
   827  	assert.NoError(t, artifactoryCli.Exec("download", path.Join(tests.RtRepo1, "bulk.tar"), tests.Out+"/", "--explode=true"))
   828  	assert.NoError(t, artifactoryCli.Exec("download", path.Join(tests.RtRepo1, "zipFile.zip"), tests.Out+"/", "--explode=true"))
   829  	verifyExistAndCleanDir(t, tests.GetExtractedDownload)
   830  
   831  	cleanArtifactoryTest()
   832  }
   833  
   834  func TestArtifactoryDownloadAndExplodeCurDirAsTarget(t *testing.T) {
   835  	initArtifactoryTest(t)
   836  	err := fileutils.CreateDirIfNotExist(tests.Out)
   837  	assert.NoError(t, err)
   838  
   839  	randFile, err := gofrogio.CreateRandFile(filepath.Join(tests.Out, "DownloadAndExplodeCurDirTarget"), 100000)
   840  	assert.NoError(t, err)
   841  
   842  	err = archiver.Archive([]string{randFile.Name()}, filepath.Join(tests.Out, "curDir.tar.gz"))
   843  	assert.NoError(t, err)
   844  
   845  	artifactoryCli.Exec("upload", tests.Out+"/*", tests.RtRepo1, "--flat=true")
   846  	assert.NoError(t, artifactoryCli.Exec("upload", tests.Out+"/*", tests.RtRepo1+"/p-modules/", "--flat=true"))
   847  	randFile.File.Close()
   848  	os.RemoveAll(tests.Out)
   849  
   850  	// Change working dir to tests temp "out" dir
   851  	assert.NoError(t, fileutils.CreateDirIfNotExist(tests.Out))
   852  	wd, err := os.Getwd()
   853  	assert.NoError(t, err)
   854  	assert.NoError(t, os.Chdir(tests.Out))
   855  
   856  	// Dot as target
   857  	assert.NoError(t, artifactoryCli.Exec("download", tests.RtRepo1+"/p-modules/curDir.tar.gz", ".", "--explode=true"))
   858  	// Changing current working dir to "out" dir
   859  	assert.NoError(t, os.Chdir(wd))
   860  	verifyExistAndCleanDir(t, tests.GetExtractedDownloadCurDir)
   861  	assert.NoError(t, os.Chdir(tests.Out))
   862  
   863  	// No target
   864  	assert.NoError(t, artifactoryCli.Exec("download", tests.RtRepo1+"/p-modules/curDir.tar.gz", "--explode=true"))
   865  	// Changing working dir for testing
   866  	assert.NoError(t, os.Chdir(wd))
   867  	verifyExistAndCleanDir(t, tests.GetExtractedDownloadCurDir)
   868  	assert.NoError(t, os.Chdir(tests.Out))
   869  
   870  	assert.NoError(t, os.Chdir(wd))
   871  	cleanArtifactoryTest()
   872  }
   873  
   874  func TestArtifactoryDownloadAndExplodeFlat(t *testing.T) {
   875  	initArtifactoryTest(t)
   876  	err := fileutils.CreateDirIfNotExist(tests.Out)
   877  	assert.NoError(t, err)
   878  
   879  	file1, err := gofrogio.CreateRandFile(filepath.Join(tests.Out, "file1"), 100000)
   880  	assert.NoError(t, err)
   881  
   882  	err = archiver.Archive([]string{file1.Name()}, filepath.Join(tests.Out, "flat.tar"))
   883  	assert.NoError(t, err)
   884  	err = archiver.Archive([]string{tests.Out + "/flat.tar"}, filepath.Join(tests.Out, "tarZipFile.zip"))
   885  	assert.NoError(t, err)
   886  
   887  	artifactoryCli.Exec("upload", tests.Out+"/*", tests.RtRepo1+"/checkFlat/dir/")
   888  	file1.File.Close()
   889  	os.RemoveAll(tests.Out)
   890  	assert.NoError(t, fileutils.CreateDirIfNotExist(tests.Out))
   891  
   892  	assert.NoError(t, artifactoryCli.Exec("download", path.Join(tests.RtRepo1, "checkFlat", "dir", "flat.tar"), tests.Out+"/checkFlat/", "--explode=true", "--flat=true", "--min-split=50"))
   893  	assert.NoError(t, artifactoryCli.Exec("download", path.Join(tests.RtRepo1, "checkFlat", "dir", "tarZipFile.zip"), tests.Out+"/", "--explode=true", "--flat=false"))
   894  	verifyExistAndCleanDir(t, tests.GetExtractedDownloadFlatFalse)
   895  	// Explode 'flat.tar' while the file exists in the file system using --flat
   896  	assert.NoError(t, artifactoryCli.Exec("download", path.Join(tests.RtRepo1, "checkFlat", "dir", "tarZipFile.zip"), tests.Out+"/", "--explode=true", "--flat=false"))
   897  	assert.NoError(t, artifactoryCli.Exec("download", path.Join(tests.RtRepo1, "checkFlat", "dir", "flat.tar"), tests.Out+"/checkFlat/dir/", "--explode=true", "--flat", "--min-split=50"))
   898  	verifyExistAndCleanDir(t, tests.GetExtractedDownloadTarFileFlatFalse)
   899  
   900  	cleanArtifactoryTest()
   901  }
   902  
   903  func TestArtifactoryDownloadAndExplodeConcurrent(t *testing.T) {
   904  	initArtifactoryTest(t)
   905  	err := fileutils.CreateDirIfNotExist(tests.Out)
   906  	assert.NoError(t, err)
   907  
   908  	artifactoryCli.Exec("upload", path.Join("testdata", "archives", "a.zip"), tests.RtRepo1, "--flat=true")
   909  	assert.NoError(t, fileutils.CreateDirIfNotExist(tests.Out))
   910  	assert.NoError(t, artifactoryCli.Exec("download", path.Join(tests.RtRepo1, "a.zip"), tests.Out+"/", "--explode=true", "--min-split=50"))
   911  	verifyExistAndCleanDir(t, tests.GetExtractedDownloadConcurrent)
   912  	assert.NoError(t, artifactoryCli.Exec("download", path.Join(tests.RtRepo1, "a.zip"), tests.Out+"/", "--explode=false", "--min-split=50"))
   913  	verifyExistAndCleanDir(t, tests.GetArchiveConcurrent)
   914  	assert.NoError(t, artifactoryCli.Exec("download", path.Join(tests.RtRepo1, "a.zip"), tests.Out+"/", "--explode=true", "--split-count=15", "--min-split=50"))
   915  	verifyExistAndCleanDir(t, tests.GetExtractedDownloadConcurrent)
   916  
   917  	cleanArtifactoryTest()
   918  }
   919  
   920  func TestArtifactoryDownloadAndExplodeSpecialChars(t *testing.T) {
   921  	initArtifactoryTest(t)
   922  	err := fileutils.CreateDirIfNotExist(tests.Out)
   923  	assert.NoError(t, err)
   924  	file1, err := gofrogio.CreateRandFile(filepath.Join(tests.Out, "file $+~&^a#1"), 1000)
   925  	assert.NoError(t, err)
   926  	err = archiver.Archive([]string{file1.Name()}, filepath.Join(tests.Out, "a$+~&^a#.tar"))
   927  	assert.NoError(t, err)
   928  
   929  	artifactoryCli.Exec("upload", tests.Out+"/*", tests.RtRepo1+"/dir/", "--flat=true")
   930  	os.RemoveAll(tests.Out)
   931  	err = fileutils.CreateDirIfNotExist(tests.Out)
   932  	assert.NoError(t, err)
   933  	artifactoryCli.Exec("dl", tests.RtRepo1+"/dir/a$+~&^a#.tar", tests.Out+"/dir $+~&^a# test/", "--flat=true", "--explode")
   934  	artifactoryCli.Exec("dl", tests.RtRepo1+"/dir/a$+~&^a#.tar", tests.Out+"/dir $+~&^a# test/", "--flat=false", "--explode")
   935  	verifyExistAndCleanDir(t, tests.GetExtractedDownloadTarFileSpecialChars)
   936  	// Concurrently download
   937  	artifactoryCli.Exec("dl", tests.RtRepo1+"/dir/a$+~&^a#.tar", tests.Out+"/dir $+~&^a# test/", "--flat=true", "--explode", "--min-split=50")
   938  	artifactoryCli.Exec("dl", tests.RtRepo1+"/dir/a$+~&^a#.tar", tests.Out+"/dir $+~&^a# test/", "--flat=false", "--explode", "--min-split=50")
   939  	verifyExistAndCleanDir(t, tests.GetExtractedDownloadTarFileSpecialChars)
   940  	cleanArtifactoryTest()
   941  }
   942  
   943  func verifyExistAndCleanDir(t *testing.T, GetExtractedDownload func() []string) {
   944  	paths, err := fileutils.ListFilesRecursiveWalkIntoDirSymlink(tests.Out, false)
   945  	assert.NoError(t, err)
   946  	tests.VerifyExistLocally(GetExtractedDownload(), paths, t)
   947  	os.RemoveAll(tests.Out)
   948  	assert.NoError(t, fileutils.CreateDirIfNotExist(tests.Out))
   949  }
   950  
   951  func TestArtifactoryUploadAsArchive(t *testing.T) {
   952  	initArtifactoryTest(t)
   953  
   954  	uploadSpecFile, err := tests.CreateSpec(tests.UploadAsArchive)
   955  	assert.NoError(t, err)
   956  	artifactoryCli.Exec("upload", "--spec="+uploadSpecFile)
   957  	searchFilePath, err := tests.CreateSpec(tests.SearchAllRepo1)
   958  	verifyExistInArtifactory(tests.GetUploadAsArchive(), searchFilePath, t)
   959  
   960  	// Verify the properties are valid
   961  	resultItems := searchItemsInArtifactory(t, tests.SearchAllRepo1)
   962  	assert.NotZero(t, len(resultItems))
   963  	for _, item := range resultItems {
   964  		if item.Name != "a.zip" {
   965  			assert.Zero(t, len(item.Properties))
   966  			continue
   967  		}
   968  		properties := item.Properties
   969  		assert.Equal(t, 3, len(properties))
   970  
   971  		// Sort the properties alphabetically by key and value to make the comparison easier
   972  		sort.Slice(properties, func(i, j int) bool {
   973  			if properties[i].Key == properties[j].Key {
   974  				return properties[i].Value < properties[j].Value
   975  			}
   976  			return properties[i].Key < properties[j].Key
   977  		})
   978  		assert.Contains(t, properties, rtutils.Property{Key: "k1", Value: "v11"})
   979  		assert.Contains(t, properties, rtutils.Property{Key: "k1", Value: "v12"})
   980  		assert.Contains(t, properties, rtutils.Property{Key: "k2", Value: "v2"})
   981  	}
   982  
   983  	// Check the files inside the archives by downloading and exploding them
   984  	downloadSpecFile, err := tests.CreateSpec(tests.DownloadAndExplodeArchives)
   985  	assert.NoError(t, err)
   986  	artifactoryCli.Exec("download", "--spec="+downloadSpecFile)
   987  	paths, err := fileutils.ListFilesRecursiveWalkIntoDirSymlink(tests.Out, false)
   988  	assert.NoError(t, err)
   989  	tests.VerifyExistLocally(tests.GetDownloadArchiveAndExplode(), paths, t)
   990  
   991  	cleanArtifactoryTest()
   992  }
   993  
   994  func TestArtifactoryUploadAsArchiveWithExplodeAndSymlinks(t *testing.T) {
   995  	initArtifactoryTest(t)
   996  
   997  	uploadSpecFile, err := tests.CreateSpec(tests.UploadAsArchive)
   998  	assert.NoError(t, err)
   999  	err = artifactoryCli.Exec("upload", "--spec="+uploadSpecFile, "--symlinks", "--explode")
  1000  	assert.Error(t, err)
  1001  
  1002  	cleanArtifactoryTest()
  1003  }
  1004  
  1005  func TestArtifactoryUploadAsArchiveToDir(t *testing.T) {
  1006  	initArtifactoryTest(t)
  1007  
  1008  	uploadSpecFile, err := tests.CreateSpec(tests.UploadAsArchiveToDir)
  1009  	assert.NoError(t, err)
  1010  	err = artifactoryCli.Exec("upload", "--spec="+uploadSpecFile)
  1011  	assert.Error(t, err)
  1012  
  1013  	cleanArtifactoryTest()
  1014  }
  1015  
  1016  func TestArtifactoryDownloadAndSyncDeletes(t *testing.T) {
  1017  	initArtifactoryTest(t)
  1018  
  1019  	outDirPath := tests.Out + string(os.PathSeparator)
  1020  	// Upload all testdata/a/ to repo1/syncDir/
  1021  	artifactoryCli.Exec("upload", path.Join("testdata", "a", "*"), tests.RtRepo1+"/syncDir/", "--flat=false")
  1022  	searchFilePath, err := tests.CreateSpec(tests.SearchAllRepo1)
  1023  	assert.NoError(t, err)
  1024  	verifyExistInArtifactory(tests.GetUploadExpectedRepo1SyncDeleteStep1(), searchFilePath, t)
  1025  
  1026  	// Download repo1/syncDir/ to out/
  1027  	artifactoryCli.Exec("download", tests.RtRepo1+"/syncDir/", tests.Out+"/")
  1028  	paths, err := fileutils.ListFilesRecursiveWalkIntoDirSymlink(tests.Out, false)
  1029  	assert.NoError(t, err)
  1030  	tests.VerifyExistLocally(tests.GetExpectedSyncDeletesDownloadStep2(), paths, t)
  1031  
  1032  	// Download repo1/syncDir/ to out/ with flat=true and sync out/
  1033  	artifactoryCli.Exec("download", tests.RtRepo1+"/syncDir/", outDirPath, "--flat=true", "--sync-deletes="+outDirPath)
  1034  	paths, err = fileutils.ListFilesRecursiveWalkIntoDirSymlink(tests.Out, false)
  1035  	assert.NoError(t, err)
  1036  	checkSyncedDirContent(tests.GetExpectedSyncDeletesDownloadStep3(), paths, t)
  1037  
  1038  	// Download all files ended with 2.in from repo1/syncDir/ to out/ and sync out/
  1039  	artifactoryCli.Exec("download", tests.RtRepo1+"/syncDir/*2.in", outDirPath, "--flat=true", "--sync-deletes="+outDirPath)
  1040  	paths, err = fileutils.ListFilesRecursiveWalkIntoDirSymlink(tests.Out, false)
  1041  	assert.NoError(t, err)
  1042  	checkSyncedDirContent(tests.GetExpectedSyncDeletesDownloadStep4(), paths, t)
  1043  
  1044  	// Download repo1/syncDir/ to out/, exclude the pattern "*c*.in" and sync out/
  1045  	artifactoryCli.Exec("download", tests.RtRepo1+"/syncDir/", outDirPath, "--sync-deletes="+outDirPath+"syncDir"+string(os.PathSeparator), "--exclude-patterns=syncDir/testdata/*c*in")
  1046  	paths, err = fileutils.ListFilesRecursiveWalkIntoDirSymlink(tests.Out+string(os.PathSeparator)+"syncDir"+string(os.PathSeparator), false)
  1047  	assert.NoError(t, err)
  1048  	checkSyncedDirContent(tests.GetSyncExpectedDeletesDownloadStep5(), paths, t)
  1049  
  1050  	// Delete all files from repo1/syncDir/
  1051  	artifactoryCli.Exec("delete", tests.RtRepo1+"/syncDir/")
  1052  	searchFilePath, err = tests.CreateSpec(tests.SearchAllRepo1)
  1053  	assert.NoError(t, err)
  1054  	verifyDoesntExistInArtifactory(searchFilePath, t)
  1055  
  1056  	// Upload all testdata/archives/ to repo1/syncDir/
  1057  	artifactoryCli.Exec("upload", path.Join("testdata", "archives", "*"), tests.RtRepo1+"/syncDir/", "--flat=false")
  1058  	searchFilePath, err = tests.CreateSpec(tests.SearchAllRepo1)
  1059  	assert.NoError(t, err)
  1060  	verifyExistInArtifactory(tests.GetSyncExpectedDeletesDownloadStep6(), searchFilePath, t)
  1061  
  1062  	// Download repo1/syncDir/ to out/ and sync out/
  1063  	artifactoryCli.Exec("download", tests.RtRepo1+"/syncDir/", outDirPath, "--sync-deletes="+outDirPath+"syncDir"+string(os.PathSeparator))
  1064  	paths, err = fileutils.ListFilesRecursiveWalkIntoDirSymlink(tests.Out+string(os.PathSeparator)+"syncDir"+string(os.PathSeparator), false)
  1065  	assert.NoError(t, err)
  1066  	checkSyncedDirContent(tests.GetSyncExpectedDeletesDownloadStep7(), paths, t)
  1067  
  1068  	cleanArtifactoryTest()
  1069  }
  1070  
  1071  // After syncDeletes we must make sure that the content of the synced directory contains the last operation result only.
  1072  // Therefore we verify that there are no other files in the synced directory, other than the list of the expected files.
  1073  func checkSyncedDirContent(expected, actual []string, t *testing.T) {
  1074  	// Check if all expected files are actually exist
  1075  	tests.VerifyExistLocally(expected, actual, t)
  1076  	// Check if all the existing files were expected
  1077  	err := isExclusivelyExistLocally(expected, actual)
  1078  	assert.NoError(t, err)
  1079  }
  1080  
  1081  // Check if only the files we were expect, exist locally, i.e return an error if there is a local file we didn't expect.
  1082  // Since the "actual" list contains paths of both directories and files, for each element in the "actual" list:
  1083  // Check if the path equals to an existing file (for a file) OR
  1084  // if the path is a prefix of some path of an existing file (for a dir).
  1085  func isExclusivelyExistLocally(expected, actual []string) error {
  1086  	expectedLastIndex := len(expected) - 1
  1087  	for _, v := range actual {
  1088  		for i, r := range expected {
  1089  			if strings.HasPrefix(r, v) || v == r {
  1090  				break
  1091  			}
  1092  			if i == expectedLastIndex {
  1093  				return errors.New("Should not have : " + v)
  1094  			}
  1095  		}
  1096  	}
  1097  	return nil
  1098  }
  1099  
  1100  // Test self-signed certificates with Artifactory. For the test, we set up a reverse proxy server.
  1101  func TestArtifactorySelfSignedCert(t *testing.T) {
  1102  	initArtifactoryTest(t)
  1103  	tempDirPath, err := fileutils.CreateTempDir()
  1104  	err = errorutils.CheckError(err)
  1105  	assert.NoError(t, err)
  1106  	defer fileutils.RemoveTempDir(tempDirPath)
  1107  	os.Setenv(coreutils.HomeDir, tempDirPath)
  1108  	os.Setenv(tests.HttpsProxyEnvVar, "1024")
  1109  	go cliproxy.StartLocalReverseHttpProxy(serverDetails.ArtifactoryUrl, false)
  1110  
  1111  	// The two certificate files are created by the reverse proxy on startup in the current directory.
  1112  	defer os.Remove(certificate.KEY_FILE)
  1113  	defer os.Remove(certificate.CERT_FILE)
  1114  	// Let's wait for the reverse proxy to start up.
  1115  	err = checkIfServerIsUp(cliproxy.GetProxyHttpsPort(), "https", false)
  1116  	assert.NoError(t, err)
  1117  
  1118  	fileSpec := spec.NewBuilder().Pattern(tests.RtRepo1 + "/*.zip").Recursive(true).BuildSpec()
  1119  	assert.NoError(t, err)
  1120  	parsedUrl, err := url.Parse(serverDetails.ArtifactoryUrl)
  1121  	serverDetails.ArtifactoryUrl = "https://127.0.0.1:" + cliproxy.GetProxyHttpsPort() + parsedUrl.RequestURI()
  1122  
  1123  	// The server is using self-signed certificates
  1124  	// Without loading the certificates (or skipping verification) we expect all actions to fail due to error: "x509: certificate signed by unknown authority"
  1125  	searchCmd := generic.NewSearchCommand()
  1126  	searchCmd.SetServerDetails(serverDetails).SetSpec(fileSpec)
  1127  	reader, err := searchCmd.Search()
  1128  	if reader != nil {
  1129  		assert.NoError(t, reader.Close())
  1130  	}
  1131  	_, isUrlErr := err.(*url.Error)
  1132  	assert.True(t, isUrlErr, "Expected a connection failure, since reverse proxy didn't load self-signed-certs. Connection however is successful", err)
  1133  
  1134  	// Set insecureTls to true and run again. We expect the command to succeed.
  1135  	serverDetails.InsecureTls = true
  1136  	searchCmd = generic.NewSearchCommand()
  1137  	searchCmd.SetServerDetails(serverDetails).SetSpec(fileSpec)
  1138  	reader, err = searchCmd.Search()
  1139  	assert.NoError(t, err)
  1140  	assert.NoError(t, reader.Close())
  1141  
  1142  	// Set insecureTls back to false.
  1143  	// Copy the server certificates to the CLI security dir and run again. We expect the command to succeed.
  1144  	serverDetails.InsecureTls = false
  1145  	certsPath, err := coreutils.GetJfrogCertsDir()
  1146  	assert.NoError(t, err)
  1147  	err = fileutils.CopyFile(certsPath, certificate.KEY_FILE)
  1148  	assert.NoError(t, err)
  1149  	err = fileutils.CopyFile(certsPath, certificate.CERT_FILE)
  1150  	assert.NoError(t, err)
  1151  	searchCmd = generic.NewSearchCommand()
  1152  	searchCmd.SetServerDetails(serverDetails).SetSpec(fileSpec)
  1153  	reader, err = searchCmd.Search()
  1154  	assert.NoError(t, err)
  1155  	assert.NoError(t, reader.Close())
  1156  
  1157  	serverDetails.ArtifactoryUrl = artAuth.GetUrl()
  1158  	cleanArtifactoryTest()
  1159  }
  1160  
  1161  func TestArtifactoryUploadAsArchiveWithIncludeDirs(t *testing.T) {
  1162  	initArtifactoryTest(t)
  1163  	assert.NoError(t, createEmptyTestDir())
  1164  	uploadSpecFile, err := tests.CreateSpec(tests.UploadAsArchiveEmptyDirs)
  1165  	assert.NoError(t, err)
  1166  	err = artifactoryCli.Exec("upload", "--spec="+uploadSpecFile)
  1167  	assert.NoError(t, err)
  1168  
  1169  	// Check the empty directories inside the archive by downloading and exploding it.
  1170  	downloadSpecFile, err := tests.CreateSpec(tests.DownloadAndExplodeArchives)
  1171  	assert.NoError(t, err)
  1172  	artifactoryCli.Exec("download", "--spec="+downloadSpecFile)
  1173  	paths, err := fileutils.ListFilesRecursiveWalkIntoDirSymlink(tests.Out, false)
  1174  	assert.NoError(t, err)
  1175  	downloadedEmptyDirs := tests.GetDownloadArchiveAndExplodeWithIncludeDirs()
  1176  	// Verify dirs exists.
  1177  	tests.VerifyExistLocally(downloadedEmptyDirs, paths, t)
  1178  	// Verify empty dirs.
  1179  	for _, path := range downloadedEmptyDirs {
  1180  		empty, err := fileutils.IsDirEmpty(path)
  1181  		assert.NoError(t, err)
  1182  		assert.True(t, empty)
  1183  	}
  1184  	cleanArtifactoryTest()
  1185  }
  1186  
  1187  func createEmptyTestDir() error {
  1188  	dirInnerPath := filepath.Join("empty", "folder")
  1189  	canonicalPath := tests.GetTestResourcesPath() + dirInnerPath
  1190  	return os.MkdirAll(canonicalPath, 0777)
  1191  }
  1192  
  1193  // Test client certificates with Artifactory. For the test, we set up a reverse proxy server.
  1194  func TestArtifactoryClientCert(t *testing.T) {
  1195  	initArtifactoryTest(t)
  1196  	tempDirPath, err := fileutils.CreateTempDir()
  1197  	err = errorutils.CheckError(err)
  1198  	assert.NoError(t, err)
  1199  	defer fileutils.RemoveTempDir(tempDirPath)
  1200  	os.Setenv(coreutils.HomeDir, tempDirPath)
  1201  	os.Setenv(tests.HttpsProxyEnvVar, "1025")
  1202  	go cliproxy.StartLocalReverseHttpProxy(serverDetails.ArtifactoryUrl, true)
  1203  
  1204  	// The two certificate files are created by the reverse proxy on startup in the current directory.
  1205  	defer os.Remove(certificate.KEY_FILE)
  1206  	defer os.Remove(certificate.CERT_FILE)
  1207  	// Let's wait for the reverse proxy to start up.
  1208  	err = checkIfServerIsUp(cliproxy.GetProxyHttpsPort(), "https", true)
  1209  	assert.NoError(t, err)
  1210  
  1211  	fileSpec := spec.NewBuilder().Pattern(tests.RtRepo1 + "/*.zip").Recursive(true).BuildSpec()
  1212  	assert.NoError(t, err)
  1213  	parsedUrl, err := url.Parse(serverDetails.ArtifactoryUrl)
  1214  	serverDetails.ArtifactoryUrl = "https://127.0.0.1:" + cliproxy.GetProxyHttpsPort() + parsedUrl.RequestURI()
  1215  	serverDetails.InsecureTls = true
  1216  
  1217  	// The server is requiring client certificates
  1218  	// Without loading a valid client certificate, we expect all actions to fail due to error: "tls: bad certificate"
  1219  	searchCmd := generic.NewSearchCommand()
  1220  	searchCmd.SetServerDetails(serverDetails).SetSpec(fileSpec)
  1221  	reader, err := searchCmd.Search()
  1222  	if reader != nil {
  1223  		assert.NoError(t, reader.Close())
  1224  	}
  1225  	_, isUrlErr := err.(*url.Error)
  1226  	assert.True(t, isUrlErr, "Expected a connection failure, since client did not provide a client certificate. Connection however is successful")
  1227  
  1228  	// Inject client certificates, we expect the search to succeed
  1229  	serverDetails.ClientCertPath = certificate.CERT_FILE
  1230  	serverDetails.ClientCertKeyPath = certificate.KEY_FILE
  1231  
  1232  	searchCmd = generic.NewSearchCommand()
  1233  	searchCmd.SetServerDetails(serverDetails).SetSpec(fileSpec)
  1234  	reader, err = searchCmd.Search()
  1235  	if reader != nil {
  1236  		assert.NoError(t, reader.Close())
  1237  	}
  1238  	assert.NoError(t, err)
  1239  
  1240  	serverDetails.ArtifactoryUrl = artAuth.GetUrl()
  1241  	serverDetails.InsecureTls = false
  1242  	serverDetails.ClientCertPath = ""
  1243  	serverDetails.ClientCertKeyPath = ""
  1244  	cleanArtifactoryTest()
  1245  }
  1246  
  1247  func getExternalIP() (string, error) {
  1248  	ifaces, err := net.Interfaces()
  1249  	if err != nil {
  1250  		return "", err
  1251  	}
  1252  	for _, iface := range ifaces {
  1253  		if iface.Flags&net.FlagUp == 0 {
  1254  			continue // interface down
  1255  		}
  1256  		if iface.Flags&net.FlagLoopback != 0 {
  1257  			continue // loopback interface
  1258  		}
  1259  		addrs, err := iface.Addrs()
  1260  		if err != nil {
  1261  			return "", err
  1262  		}
  1263  		for _, addr := range addrs {
  1264  			var ip net.IP
  1265  			switch v := addr.(type) {
  1266  			case *net.IPNet:
  1267  				ip = v.IP
  1268  			case *net.IPAddr:
  1269  				ip = v.IP
  1270  			}
  1271  			if ip == nil || ip.IsLoopback() {
  1272  				continue
  1273  			}
  1274  			ip = ip.To4()
  1275  			if ip == nil {
  1276  				continue // not an ipv4 address
  1277  			}
  1278  			return ip.String(), nil
  1279  		}
  1280  	}
  1281  	return "", errors.New("check connection to the network")
  1282  }
  1283  
  1284  // Due the fact that go read the HTTP_PROXY and the HTTPS_PROXY
  1285  // argument only once we can't set the env var for specific test.
  1286  // We need to start a new process with the env var set to the value we want.
  1287  // We decide which var to set by the rtUrl scheme.
  1288  func TestArtifactoryProxy(t *testing.T) {
  1289  	initArtifactoryTest(t)
  1290  	rtUrl, err := url.Parse(serverDetails.ArtifactoryUrl)
  1291  	assert.NoError(t, err)
  1292  	var proxyTestArgs []string
  1293  	var httpProxyEnv string
  1294  	testArgs := []string{"-test.artifactoryProxy=true", "-rt.url=" + *tests.RtUrl, "-rt.user=" + *tests.RtUser, "-rt.password=" + *tests.RtPassword, "-rt.apikey=" + *tests.RtApiKey, "-rt.sshKeyPath=" + *tests.RtSshKeyPath, "-rt.sshPassphrase=" + *tests.RtSshPassphrase, "-rt.accessToken=" + *tests.RtAccessToken}
  1295  	if rtUrl.Scheme == "https" {
  1296  		os.Setenv(tests.HttpsProxyEnvVar, "1026")
  1297  		proxyTestArgs = append([]string{"test", "-run=TestArtifactoryHttpsProxyEnvironmentVariableDelegator"}, testArgs...)
  1298  		httpProxyEnv = "HTTPS_PROXY=localhost:" + cliproxy.GetProxyHttpsPort()
  1299  	} else {
  1300  		proxyTestArgs = append([]string{"test", "-run=TestArtifactoryHttpProxyEnvironmentVariableDelegator"}, testArgs...)
  1301  		httpProxyEnv = "HTTP_PROXY=localhost:" + cliproxy.GetProxyHttpPort()
  1302  	}
  1303  	runProxyTest(t, proxyTestArgs, httpProxyEnv)
  1304  	cleanArtifactoryTest()
  1305  }
  1306  
  1307  func runProxyTest(t *testing.T, proxyTestArgs []string, httpProxyEnv string) {
  1308  	cmd := exec.Command("go", proxyTestArgs...)
  1309  	cmd.Env = append(os.Environ(), httpProxyEnv)
  1310  
  1311  	tempDirPath, err := tests.GetTestsLogsDir()
  1312  	assert.NoError(t, err)
  1313  	f, err := os.Create(filepath.Join(tempDirPath, "artifactory_proxy_tests.log"))
  1314  	assert.NoError(t, err)
  1315  
  1316  	cmd.Stdout, cmd.Stderr = f, f
  1317  	assert.NoError(t, cmd.Run(), "Artifactory proxy tests failed, full report available at the following path:", f.Name())
  1318  	log.Info("Full Artifactory proxy testing report available at the following path:", f.Name())
  1319  }
  1320  
  1321  // Should be run only by @TestArtifactoryProxy test.
  1322  func TestArtifactoryHttpProxyEnvironmentVariableDelegator(t *testing.T) {
  1323  	testArtifactoryProxy(t, false)
  1324  }
  1325  
  1326  // Should be run only by @TestArtifactoryProxy test.
  1327  func TestArtifactoryHttpsProxyEnvironmentVariableDelegator(t *testing.T) {
  1328  	testArtifactoryProxy(t, true)
  1329  }
  1330  
  1331  func testArtifactoryProxy(t *testing.T, isHttps bool) {
  1332  	// Value is set to 'true' via testArgs @TestArtifactoryProxy
  1333  	if !*tests.TestArtifactoryProxy {
  1334  		t.SkipNow()
  1335  	}
  1336  	authenticate(true)
  1337  	proxyRtUrl := prepareArtifactoryUrlForProxyTest(t)
  1338  	spec := spec.NewBuilder().Pattern(tests.RtRepo1 + "/*.zip").Recursive(true).BuildSpec()
  1339  	serverDetails.ArtifactoryUrl = proxyRtUrl
  1340  	checkForErrDueToMissingProxy(spec, t)
  1341  	var port string
  1342  	if isHttps {
  1343  		go cliproxy.StartHttpsProxy()
  1344  		port = cliproxy.GetProxyHttpsPort()
  1345  	} else {
  1346  		go cliproxy.StartHttpProxy()
  1347  		port = cliproxy.GetProxyHttpPort()
  1348  	}
  1349  	// Let's wait for the reverse proxy to start up.
  1350  	err := checkIfServerIsUp(port, "http", false)
  1351  	assert.NoError(t, err)
  1352  	searchCmd := generic.NewSearchCommand()
  1353  	searchCmd.SetServerDetails(serverDetails).SetSpec(spec)
  1354  	reader, err := searchCmd.Search()
  1355  	assert.NoError(t, err)
  1356  	if reader != nil {
  1357  		assert.NoError(t, reader.Close())
  1358  	}
  1359  	serverDetails.ArtifactoryUrl = artAuth.GetUrl()
  1360  }
  1361  
  1362  func prepareArtifactoryUrlForProxyTest(t *testing.T) string {
  1363  	rtUrl, err := url.Parse(serverDetails.ArtifactoryUrl)
  1364  	assert.NoError(t, err)
  1365  	rtHost, port, err := net.SplitHostPort(rtUrl.Host)
  1366  	if rtHost == "localhost" || rtHost == "127.0.0.1" {
  1367  		externalIp, err := getExternalIP()
  1368  		assert.NoError(t, err)
  1369  		rtUrl.Host = externalIp + ":" + port
  1370  	}
  1371  	return rtUrl.String()
  1372  }
  1373  
  1374  func checkForErrDueToMissingProxy(spec *spec.SpecFiles, t *testing.T) {
  1375  	searchCmd := generic.NewSearchCommand()
  1376  	searchCmd.SetServerDetails(serverDetails).SetSpec(spec)
  1377  	reader, err := searchCmd.Search()
  1378  	if reader != nil {
  1379  		assert.NoError(t, reader.Close())
  1380  	}
  1381  	_, isUrlErr := err.(*url.Error)
  1382  	assert.True(t, isUrlErr, "Expected the request to fails, since the proxy is down.", err)
  1383  }
  1384  
  1385  func checkIfServerIsUp(port, proxyScheme string, useClientCerts bool) error {
  1386  	tr := &http.Transport{
  1387  		TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
  1388  	}
  1389  
  1390  	if useClientCerts {
  1391  		for attempt := 0; attempt < 10; attempt++ {
  1392  			if _, err := os.Stat(certificate.CERT_FILE); os.IsNotExist(err) {
  1393  				log.Info("Waiting for certificate to appear...")
  1394  				time.Sleep(time.Second)
  1395  				continue
  1396  			}
  1397  
  1398  			if _, err := os.Stat(certificate.KEY_FILE); os.IsNotExist(err) {
  1399  				log.Info("Waiting for key to appear...")
  1400  				time.Sleep(time.Second)
  1401  				continue
  1402  			}
  1403  
  1404  			break
  1405  		}
  1406  
  1407  		cert, err := tls.LoadX509KeyPair(certificate.CERT_FILE, certificate.KEY_FILE)
  1408  		if err != nil {
  1409  			return fmt.Errorf("failed loading client certificate")
  1410  		}
  1411  		tr.TLSClientConfig.Certificates = []tls.Certificate{cert}
  1412  	}
  1413  	client := &http.Client{Transport: tr}
  1414  
  1415  	for attempt := 0; attempt < 20; attempt++ {
  1416  		log.Info("Checking if proxy server is up and running.", strconv.Itoa(attempt+1), "attempt.", "URL:", proxyScheme+"://localhost:"+port)
  1417  		resp, err := client.Get(proxyScheme + "://localhost:" + port)
  1418  		if err != nil {
  1419  			time.Sleep(time.Second)
  1420  			continue
  1421  		}
  1422  		resp.Body.Close()
  1423  		if resp.StatusCode != http.StatusOK {
  1424  			time.Sleep(time.Second)
  1425  			continue
  1426  		}
  1427  		return nil
  1428  	}
  1429  	return fmt.Errorf("failed while waiting for the proxy server to be accessible")
  1430  }
  1431  
  1432  func TestXrayScanBuild(t *testing.T) {
  1433  	initArtifactoryTest(t)
  1434  	xrayServerPort := xray.StartXrayMockServer()
  1435  	serverUrl := "--url=http://localhost:" + strconv.Itoa(xrayServerPort)
  1436  	artifactoryCommandExecutor := tests.NewJfrogCli(execMain, "jfrog rt", serverUrl+getArtifactoryTestCredentials())
  1437  	artifactoryCommandExecutor.Exec("build-scan", xray.CleanScanBuildName, "3")
  1438  
  1439  	cleanArtifactoryTest()
  1440  }
  1441  
  1442  func TestArtifactorySetProperties(t *testing.T) {
  1443  	initArtifactoryTest(t)
  1444  	// Upload a file.
  1445  	artifactoryCli.Exec("upload", "testdata/a/a1.in", tests.RtRepo1+"/a.in")
  1446  	// Set the 'prop=red' property to the file.
  1447  	artifactoryCli.Exec("sp", tests.RtRepo1+"/a.*", "prop=red")
  1448  	// Now let's change the property value, by searching for the 'prop=red'.
  1449  	specFile, err := tests.CreateSpec(tests.SetDeletePropsSpec)
  1450  	assert.NoError(t, err)
  1451  	artifactoryCli.Exec("sp", "prop=green", "--spec="+specFile)
  1452  
  1453  	resultItems := searchItemsInArtifactory(t, tests.SearchRepo1ByInSuffix)
  1454  	assert.NotZero(t, len(resultItems), "No artifacts were found.")
  1455  	for _, item := range resultItems {
  1456  		properties := item.Properties
  1457  		assert.GreaterOrEqual(t, len(properties), 1, "Failed setting properties on item:", item.GetItemRelativePath())
  1458  		for i, prop := range properties {
  1459  			assert.Zero(t, i, "Expected a single property.")
  1460  			assert.Equal(t, "prop", prop.Key, "Wrong property key")
  1461  			assert.Equal(t, "green", prop.Value, "Wrong property value")
  1462  		}
  1463  	}
  1464  	cleanArtifactoryTest()
  1465  }
  1466  
  1467  func TestArtifactorySetPropertiesOnSpecialCharsArtifact(t *testing.T) {
  1468  	initArtifactoryTest(t)
  1469  	targetPath := path.Join(tests.RtRepo1, "a$+~&^a#")
  1470  	// Upload a file with special chars.
  1471  	artifactoryCli.Exec("upload", "testdata/a/a1.in", targetPath)
  1472  	// Set the 'prop=red' property to the file.
  1473  	artifactoryCli.Exec("sp", targetPath, "prop=red")
  1474  
  1475  	searchSpec, err := tests.CreateSpec(tests.SearchAllRepo1)
  1476  	assert.NoError(t, err)
  1477  	resultItems, err := searchInArtifactory(searchSpec, t)
  1478  	assert.NoError(t, err)
  1479  
  1480  	assert.Equal(t, len(resultItems), 1)
  1481  	for _, item := range resultItems {
  1482  		properties := item.Props
  1483  		assert.Equal(t, len(properties), 1)
  1484  		for k, v := range properties {
  1485  			assert.Equal(t, "prop", k, "Wrong property key")
  1486  			assert.Len(t, v, 1)
  1487  			assert.Equal(t, "red", v[0], "Wrong property value")
  1488  		}
  1489  	}
  1490  	cleanArtifactoryTest()
  1491  }
  1492  
  1493  func TestArtifactorySetPropertiesExcludeByCli(t *testing.T) {
  1494  	initArtifactoryTest(t)
  1495  	artifactoryCli.Exec("upload", "testdata/a/a*.in", tests.RtRepo1+"/")
  1496  	artifactoryCli.Exec("sp", tests.RtRepo1+"/*", "prop=val", "--exclude-patterns=*a1.in;*a2.in")
  1497  	resultItems := searchItemsInArtifactory(t, tests.SearchRepo1ByInSuffix)
  1498  	assert.NotZero(t, len(resultItems), "No artifacts were found.")
  1499  	for _, item := range resultItems {
  1500  		if item.Name != "a3.in" {
  1501  			continue
  1502  		}
  1503  		properties := item.Properties
  1504  		assert.GreaterOrEqual(t, len(properties), 1, "Failed setting properties on item:", item.GetItemRelativePath())
  1505  		for i, prop := range properties {
  1506  			assert.Zero(t, i, "Expected single property.")
  1507  			assert.Equal(t, "prop", prop.Key, "Wrong property key")
  1508  			assert.Equal(t, "val", prop.Value, "Wrong property value")
  1509  		}
  1510  	}
  1511  	cleanArtifactoryTest()
  1512  }
  1513  
  1514  func TestArtifactorySetPropertiesExclusionsByCli(t *testing.T) {
  1515  	initArtifactoryTest(t)
  1516  	artifactoryCli.Exec("upload", "testdata/a/a*.in", tests.RtRepo1+"/")
  1517  	artifactoryCli.Exec("sp", tests.RtRepo1+"/*", "prop=val", "--exclusions=*/*a1.in;*/*a2.in")
  1518  	resultItems := searchItemsInArtifactory(t, tests.SearchRepo1ByInSuffix)
  1519  	assert.NotZero(t, len(resultItems), "No artifacts were found.")
  1520  	for _, item := range resultItems {
  1521  		if item.Name != "a3.in" {
  1522  			continue
  1523  		}
  1524  		properties := item.Properties
  1525  		assert.GreaterOrEqual(t, len(properties), 1, "Failed setting properties on item:", item.GetItemRelativePath())
  1526  		for i, prop := range properties {
  1527  			assert.Zero(t, i, "Expected single property.")
  1528  			assert.Equal(t, "prop", prop.Key, "Wrong property key")
  1529  			assert.Equal(t, "val", prop.Value, "Wrong property value")
  1530  		}
  1531  	}
  1532  	cleanArtifactoryTest()
  1533  }
  1534  
  1535  func TestArtifactoryDeleteProperties(t *testing.T) {
  1536  	initArtifactoryTest(t)
  1537  	artifactoryCli.Exec("upload", "testdata/a/a*.in", tests.RtRepo1+"/a/")
  1538  	artifactoryCli.Exec("sp", tests.RtRepo1+"/a/*", "color=yellow;prop=red;status=ok")
  1539  	// Delete the 'color' property.
  1540  	artifactoryCli.Exec("delp", tests.RtRepo1+"/a/*", "color")
  1541  	// Delete the 'status' property, by a spec which filters files by 'prop=red'.
  1542  	specFile, err := tests.CreateSpec(tests.SetDeletePropsSpec)
  1543  	assert.NoError(t, err)
  1544  	artifactoryCli.Exec("delp", "status", "--spec="+specFile)
  1545  
  1546  	resultItems := searchItemsInArtifactory(t, tests.SearchRepo1ByInSuffix)
  1547  	assert.NotZero(t, len(resultItems), "No artifacts were found.")
  1548  
  1549  	for _, item := range resultItems {
  1550  		properties := item.Properties
  1551  		for _, prop := range properties {
  1552  			assert.False(t, prop.Key == "color" || prop.Key == "status", "Properties 'color' and/or 'status' were not deleted from artifact", item.Name)
  1553  		}
  1554  	}
  1555  	cleanArtifactoryTest()
  1556  }
  1557  
  1558  func TestArtifactoryDeletePropertiesWithExclude(t *testing.T) {
  1559  	initArtifactoryTest(t)
  1560  	artifactoryCli.Exec("upload", "testdata/a/a*.in", tests.RtRepo1+"/")
  1561  	artifactoryCli.Exec("sp", tests.RtRepo1+"/*", "prop=val")
  1562  
  1563  	artifactoryCli.Exec("delp", tests.RtRepo1+"/*", "prop", "--exclude-patterns=*a1.in;*a2.in")
  1564  	resultItems := searchItemsInArtifactory(t, tests.SearchRepo1ByInSuffix)
  1565  	assert.NotZero(t, len(resultItems), "No artifacts were found.")
  1566  
  1567  	for _, item := range resultItems {
  1568  		properties := item.Properties
  1569  		for _, prop := range properties {
  1570  			if item.Name == "a1.in" || item.Name == "a2.in" {
  1571  				// Check that properties were not removed.
  1572  				assert.Equal(t, "prop", prop.Key, "Wrong property key")
  1573  				assert.Equal(t, "val", prop.Value, "Wrong property value")
  1574  			}
  1575  		}
  1576  	}
  1577  	cleanArtifactoryTest()
  1578  }
  1579  
  1580  func TestArtifactoryDeletePropertiesWithExclusions(t *testing.T) {
  1581  	initArtifactoryTest(t)
  1582  	artifactoryCli.Exec("upload", "testdata/a/a*.in", tests.RtRepo1+"/")
  1583  	artifactoryCli.Exec("sp", tests.RtRepo1+"/*", "prop=val")
  1584  
  1585  	artifactoryCli.Exec("delp", tests.RtRepo1+"/*", "prop", "--exclusions=*/*a1.in;*/*a2.in")
  1586  	resultItems := searchItemsInArtifactory(t, tests.SearchRepo1ByInSuffix)
  1587  	assert.NotZero(t, len(resultItems), "No artifacts were found.")
  1588  
  1589  	for _, item := range resultItems {
  1590  		properties := item.Properties
  1591  		for _, prop := range properties {
  1592  			if item.Name == "a1.in" || item.Name == "a2.in" {
  1593  				// Check that properties were not removed.
  1594  				assert.False(t, prop.Key != "prop" || prop.Value != "val", "Wrong properties")
  1595  			}
  1596  		}
  1597  	}
  1598  	cleanArtifactoryTest()
  1599  }
  1600  
  1601  func TestArtifactoryUploadFromHomeDir(t *testing.T) {
  1602  	initArtifactoryTest(t)
  1603  	testFileRel, testFileAbs := createFileInHomeDir(t, "cliTestFile.txt")
  1604  	artifactoryCli.Exec("upload", testFileRel, tests.RtRepo1, "--recursive=false")
  1605  	searchTxtPath, err := tests.CreateSpec(tests.SearchTxt)
  1606  	assert.NoError(t, err)
  1607  	verifyExistInArtifactory(tests.GetTxtUploadExpectedRepo1(), searchTxtPath, t)
  1608  	os.Remove(testFileAbs)
  1609  	cleanArtifactoryTest()
  1610  }
  1611  
  1612  func createFileInHomeDir(t *testing.T, fileName string) (testFileRelPath string, testFileAbsPath string) {
  1613  	testFileRelPath = filepath.Join("~", fileName)
  1614  	testFileAbsPath = filepath.Join(fileutils.GetHomeDir(), fileName)
  1615  	d1 := []byte("test file")
  1616  	err := os.WriteFile(testFileAbsPath, d1, 0644)
  1617  	assert.NoError(t, err, "Couldn't create file")
  1618  	return
  1619  }
  1620  
  1621  func TestArtifactoryUploadLegacyProps(t *testing.T) {
  1622  	initArtifactoryTest(t)
  1623  	artifactoryCli.Exec("upload", "testdata/a/a*", tests.RtRepo1+"/data/", "--props=key1=val1;key2=val2,val3")
  1624  	verifyExistInArtifactoryByProps(tests.GetUploadLegacyPropsExpected(), tests.RtRepo1, "key1=val1;key2=val2;key2=val3", t)
  1625  	cleanArtifactoryTest()
  1626  }
  1627  
  1628  func TestArtifactoryUploadExcludeByCli1Wildcard(t *testing.T) {
  1629  	initArtifactoryTest(t)
  1630  	// Upload files
  1631  	artifactoryCli.Exec("upload", "testdata/a/a*", tests.RtRepo1, "--exclusions=*a2*;*a3.in")
  1632  	searchFilePath, err := tests.CreateSpec(tests.SearchRepo1ByInSuffix)
  1633  	assert.NoError(t, err)
  1634  
  1635  	verifyExistInArtifactory(tests.GetSimpleUploadSpecialCharNoRegexExpectedRepo1(), searchFilePath, t)
  1636  	cleanArtifactoryTest()
  1637  }
  1638  
  1639  func TestArtifactoryUploadExcludeByCli1Regex(t *testing.T) {
  1640  	initArtifactoryTest(t)
  1641  	// Upload files
  1642  	artifactoryCli.Exec("upload", "testdata/a/a(.*)", tests.RtRepo1, "--exclusions=(.*)a2.*;.*a3.in", "--regexp=true")
  1643  	searchFilePath, err := tests.CreateSpec(tests.SearchRepo1ByInSuffix)
  1644  	assert.NoError(t, err)
  1645  	verifyExistInArtifactory(tests.GetSimpleUploadSpecialCharNoRegexExpectedRepo1(), searchFilePath, t)
  1646  	cleanArtifactoryTest()
  1647  }
  1648  
  1649  func TestArtifactoryUploadExcludeByCli2Wildcard(t *testing.T) {
  1650  	initArtifactoryTest(t)
  1651  
  1652  	// Create temp dir
  1653  	absDirPath, err := fileutils.CreateTempDir()
  1654  	assert.NoError(t, err, "Couldn't create dir")
  1655  	defer fileutils.RemoveTempDir(absDirPath)
  1656  
  1657  	// Create temp files
  1658  	d1 := []byte("test file")
  1659  	err = os.WriteFile(filepath.Join(absDirPath, "cliTestFile1.in"), d1, 0644)
  1660  	assert.NoError(t, err, "Couldn't create file")
  1661  	err = os.WriteFile(filepath.Join(absDirPath, "cliTestFile2.in"), d1, 0644)
  1662  	assert.NoError(t, err, "Couldn't create file")
  1663  
  1664  	// Upload files
  1665  	artifactoryCli.Exec("upload", filepath.ToSlash(absDirPath)+"/*", tests.RtRepo1, "--exclusions=*cliTestFile1*")
  1666  
  1667  	// Check files exists in artifactory
  1668  	searchFilePath, err := tests.CreateSpec(tests.SearchRepo1ByInSuffix)
  1669  	assert.NoError(t, err)
  1670  
  1671  	verifyExistInArtifactory([]string{tests.RtRepo1 + "/cliTestFile2.in"}, searchFilePath, t)
  1672  
  1673  	// Cleanup
  1674  	cleanArtifactoryTest()
  1675  }
  1676  
  1677  func TestArtifactoryUploadExcludeByCli2Regex(t *testing.T) {
  1678  	initArtifactoryTest(t)
  1679  
  1680  	// Create temp dir
  1681  	absDirPath, err := fileutils.CreateTempDir()
  1682  	assert.NoError(t, err, "Couldn't create dir")
  1683  	defer fileutils.RemoveTempDir(absDirPath)
  1684  
  1685  	// Create temp files
  1686  	d1 := []byte("test file")
  1687  	err = os.WriteFile(filepath.Join(absDirPath, "cliTestFile1.in"), d1, 0644)
  1688  	assert.NoError(t, err, "Couldn't create file")
  1689  	err = os.WriteFile(filepath.Join(absDirPath, "cliTestFile2.in"), d1, 0644)
  1690  	assert.NoError(t, err, "Couldn't create file")
  1691  
  1692  	// Upload files
  1693  	artifactoryCli.Exec("upload", filepath.ToSlash(absDirPath)+"(.*)", tests.RtRepo1, "--exclusions=(.*c)liTestFile1.*", "--regexp=true")
  1694  
  1695  	// Check files exists in artifactory
  1696  	searchFilePath, err := tests.CreateSpec(tests.SearchRepo1ByInSuffix)
  1697  	assert.NoError(t, err)
  1698  
  1699  	verifyExistInArtifactory([]string{tests.RtRepo1 + "/cliTestFile2.in"}, searchFilePath, t)
  1700  
  1701  	// Cleanup
  1702  	cleanArtifactoryTest()
  1703  }
  1704  
  1705  func TestArtifactoryUploadExcludeBySpecWildcard(t *testing.T) {
  1706  	initArtifactoryTest(t)
  1707  
  1708  	// Upload files
  1709  	specFile, err := tests.CreateSpec(tests.UploadSpecExclude)
  1710  	assert.NoError(t, err)
  1711  	artifactoryCli.Exec("upload", "--spec="+specFile)
  1712  
  1713  	// Validate files are moved by build number
  1714  	searchFilePath, err := tests.CreateSpec(tests.SearchRepo1ByInSuffix)
  1715  	assert.NoError(t, err)
  1716  
  1717  	verifyExistInArtifactory(tests.GetUploadSpecExcludeRepo1(), searchFilePath, t)
  1718  
  1719  	// Cleanup
  1720  	cleanArtifactoryTest()
  1721  }
  1722  
  1723  func TestArtifactoryUploadExcludeBySpecRegex(t *testing.T) {
  1724  	initArtifactoryTest(t)
  1725  
  1726  	// Upload files
  1727  	specFile, err := tests.CreateSpec(tests.UploadSpecExcludeRegex)
  1728  	assert.NoError(t, err)
  1729  	artifactoryCli.Exec("upload", "--spec="+specFile)
  1730  
  1731  	// Validate files are moved by build number
  1732  	searchFilePath, err := tests.CreateSpec(tests.SearchRepo1ByInSuffix)
  1733  	assert.NoError(t, err)
  1734  
  1735  	verifyExistInArtifactory(tests.GetUploadSpecExcludeRepo1(), searchFilePath, t)
  1736  
  1737  	// Cleanup
  1738  	cleanArtifactoryTest()
  1739  }
  1740  
  1741  func TestArtifactoryUploadWithRegexEscaping(t *testing.T) {
  1742  	initArtifactoryTest(t)
  1743  	// Upload files
  1744  	artifactoryCli.Exec("upload", "testdata/regexp"+"(.*)"+"\\."+".*", tests.RtRepo1, "--regexp=true")
  1745  	searchFilePath, err := tests.CreateSpec(tests.SearchAllRepo1)
  1746  	assert.NoError(t, err)
  1747  
  1748  	verifyExistInArtifactory([]string{tests.RtRepo1 + "/has.dot"}, searchFilePath, t)
  1749  	cleanArtifactoryTest()
  1750  }
  1751  
  1752  func TestArtifactoryCopySpec(t *testing.T) {
  1753  	testMoveCopySpec("copy", t)
  1754  }
  1755  
  1756  func TestArtifactoryMoveSpec(t *testing.T) {
  1757  	testMoveCopySpec("move", t)
  1758  }
  1759  
  1760  func testMoveCopySpec(command string, t *testing.T) {
  1761  	initArtifactoryTest(t)
  1762  	preUploadBasicTestResources()
  1763  	specFile, err := tests.CreateSpec(tests.CopyMoveSimpleSpec)
  1764  	assert.NoError(t, err)
  1765  	artifactoryCli.Exec(command, "--spec="+specFile)
  1766  
  1767  	// Verify files exist in target location successfully
  1768  	searchMovedCopiedSpec, err := tests.CreateSpec(tests.SearchTargetInRepo2)
  1769  	assert.NoError(t, err)
  1770  	verifyExistInArtifactory(tests.GetMoveCopySpecExpected(), searchMovedCopiedSpec, t)
  1771  
  1772  	searchOriginalSpec, err := tests.CreateSpec(tests.SearchRepo1TestResources)
  1773  	assert.NoError(t, err)
  1774  
  1775  	if command == "copy" {
  1776  		// Verify original files still exist
  1777  		verifyExistInArtifactory(tests.GetRepo1TestResourcesExpected(), searchOriginalSpec, t)
  1778  	} else {
  1779  		// Verify original files were moved
  1780  		verifyDoesntExistInArtifactory(searchOriginalSpec, t)
  1781  	}
  1782  
  1783  	cleanArtifactoryTest()
  1784  }
  1785  
  1786  // Upload symlink by full path to Artifactory and the link content checksum
  1787  // Download the symlink which was uploaded.
  1788  // validate the symlink content checksum
  1789  func TestValidateValidSymlink(t *testing.T) {
  1790  	if coreutils.IsWindows() {
  1791  		t.Skip("Running on windows, skipping...")
  1792  	}
  1793  	initArtifactoryTest(t)
  1794  	// Path to local file
  1795  	localFile := filepath.Join(tests.GetTestResourcesPath()+"a", "a1.in")
  1796  	// Path to valid symLink
  1797  	validLink := filepath.Join(tests.GetTestResourcesPath()+"a", "link")
  1798  
  1799  	// Link valid symLink to local file
  1800  	err := os.Symlink(localFile, validLink)
  1801  	assert.NoError(t, err)
  1802  
  1803  	// Upload symlink to artifactory
  1804  	artifactoryCli.Exec("u", validLink, tests.RtRepo1, "--symlinks=true")
  1805  
  1806  	// Delete the local symlink
  1807  	err = os.Remove(validLink)
  1808  	assert.NoError(t, err)
  1809  
  1810  	// Download symlink from artifactory
  1811  	artifactoryCli.Exec("dl", tests.RtRepo1+"/link", tests.GetTestResourcesPath()+"a/", "--validate-symlinks=true")
  1812  
  1813  	// Should be valid if successful
  1814  	validateSymLink(validLink, localFile, t)
  1815  
  1816  	// Delete symlink and clean
  1817  	os.Remove(validLink)
  1818  	cleanArtifactoryTest()
  1819  }
  1820  
  1821  // Upload symlink by full path to Artifactory and the link content checksum
  1822  // Unlink and delete the pointed file.
  1823  // Download the symlink which was uploaded with validation. The command should failed.
  1824  func TestValidateBrokenSymlink(t *testing.T) {
  1825  	if coreutils.IsWindows() {
  1826  		t.Skip("Running on windows, skipping...")
  1827  	}
  1828  	initArtifactoryTest(t)
  1829  	// Create temporary file in resourcesPath/a/
  1830  	tmpFile, err := os.CreateTemp(tests.GetTestResourcesPath()+"a/", "a.in.")
  1831  	if assert.NoError(t, err) {
  1832  		tmpFile.Close()
  1833  	}
  1834  	localFile := tmpFile.Name()
  1835  
  1836  	// Path to the symLink
  1837  	linkPath := filepath.Join(tests.GetTestResourcesPath()+"a/", "link")
  1838  	// Link to the temporary file
  1839  	err = os.Symlink(localFile, linkPath)
  1840  	assert.NoError(t, err)
  1841  
  1842  	// Upload symlink to artifactory
  1843  	artifactoryCli.Exec("u", linkPath, tests.RtRepo1, "--symlinks=true")
  1844  
  1845  	// Delete the local symlink and the temporary file
  1846  	err = os.Remove(linkPath)
  1847  	assert.NoError(t, err)
  1848  	err = os.Remove(localFile)
  1849  	assert.NoError(t, err)
  1850  
  1851  	// Try downloading symlink from artifactory. Since the link should be broken, it shouldn't be downloaded
  1852  	err = artifactoryCli.Exec("dl", tests.RtRepo1+"/link", tests.GetTestResourcesPath()+"a/", "--validate-symlinks=true")
  1853  	if !assert.Error(t, err, "A broken symLink was downloaded although validate-symlinks flag was set to true") {
  1854  		os.Remove(linkPath)
  1855  	}
  1856  
  1857  	// Clean
  1858  	cleanArtifactoryTest()
  1859  }
  1860  
  1861  // Testing exclude pattern with symlinks.
  1862  // This test should not upload any files.
  1863  func TestExcludeBrokenSymlink(t *testing.T) {
  1864  	if coreutils.IsWindows() {
  1865  		t.Skip("Running on windows, skipping...")
  1866  	}
  1867  	initArtifactoryTest(t)
  1868  
  1869  	// Creating broken symlink
  1870  	os.Mkdir(tests.Out, 0777)
  1871  	linkToNonExistingPath := filepath.Join(tests.Out, "link_to_non_existing_path")
  1872  	err := os.Symlink("non_existing_path", linkToNonExistingPath)
  1873  	assert.NoError(t, err)
  1874  
  1875  	// This command should succeed because all artifacts are excluded.
  1876  	artifactoryCli.Exec("u", filepath.Join(tests.Out, "*"), tests.RtRepo1, "--symlinks=true", "--exclusions=*")
  1877  	cleanArtifactoryTest()
  1878  }
  1879  
  1880  // Upload symlink to Artifactory using wildcard pattern and the link content checksum
  1881  // Download the symlink which was uploaded.
  1882  // validate the symlink content checksum.
  1883  func TestSymlinkWildcardPathHandling(t *testing.T) {
  1884  	if coreutils.IsWindows() {
  1885  		t.Skip("Running on windows, skipping...")
  1886  	}
  1887  	initArtifactoryTest(t)
  1888  	localFile := filepath.Join(tests.GetTestResourcesPath()+"a/", "a1.in")
  1889  	link := filepath.Join(tests.GetTestResourcesPath()+"a/", "link")
  1890  	err := os.Symlink(localFile, link)
  1891  	assert.NoError(t, err)
  1892  	link1 := filepath.Join(tests.GetTestResourcesPath()+"a/", "link*")
  1893  	artifactoryCli.Exec("u", link1, tests.RtRepo1, "--symlinks=true")
  1894  	err = os.Remove(link)
  1895  	assert.NoError(t, err)
  1896  	artifactoryCli.Exec("dl", tests.RtRepo1+"/link", tests.GetTestResourcesPath()+"a/", "--validate-symlinks=true")
  1897  	validateSymLink(link, localFile, t)
  1898  	os.Remove(link)
  1899  	cleanArtifactoryTest()
  1900  }
  1901  
  1902  func TestUploadWithArchiveAndSymlink(t *testing.T) {
  1903  	initArtifactoryTest(t)
  1904  	symlinkTarget := filepath.Join(tests.GetTestResourcesPath(), "a", "a2.in")
  1905  	// Path to local file with a different name from symlinkTarget
  1906  	testFile := filepath.Join(tests.GetTestResourcesPath(), "a", "a1.in")
  1907  	tmpDir, err := fileutils.CreateTempDir()
  1908  	assert.NoError(t, err)
  1909  	defer func() { assert.NoError(t, os.RemoveAll(tmpDir)) }()
  1910  	// Link valid symLink to local file
  1911  	err = os.Symlink(symlinkTarget, filepath.Join(tmpDir, "symlink"))
  1912  	assert.NoError(t, err)
  1913  	err = fileutils.CopyFile(tmpDir, testFile)
  1914  	assert.NoError(t, err)
  1915  	// Upload symlink and local file to artifactory
  1916  	assert.NoError(t, artifactoryCli.Exec("u", tmpDir+"/*", tests.RtRepo1+"/test-archive.zip", "--archive=zip", "--symlinks=true"))
  1917  	assert.NoError(t, os.RemoveAll(tmpDir))
  1918  	assert.NoError(t, os.Mkdir(tmpDir, 0777))
  1919  	assert.NoError(t, artifactoryCli.Exec("download", tests.RtRepo1+"/test-archive.zip", tmpDir+"/", "--explode=true"))
  1920  	// Validate
  1921  	assert.True(t, fileutils.IsPathExists(filepath.Join(tmpDir, "a1.in"), false), "Failed to download file from Artifactory")
  1922  	validateSymLink(filepath.Join(tmpDir, "symlink"), symlinkTarget, t)
  1923  
  1924  	cleanArtifactoryTest()
  1925  }
  1926  
  1927  // Upload symlink pointing to directory to Artifactory.
  1928  // Download the symlink which was uploaded.
  1929  func TestSymlinkToDirHandling(t *testing.T) {
  1930  	if coreutils.IsWindows() {
  1931  		t.Skip("Running on windows, skipping...")
  1932  	}
  1933  	initArtifactoryTest(t)
  1934  	localFile := filepath.Join(tests.GetTestResourcesPath(), "a")
  1935  	link := filepath.Join(tests.GetTestResourcesPath()+"a/", "link")
  1936  	err := os.Symlink(localFile, link)
  1937  	assert.NoError(t, err)
  1938  	artifactoryCli.Exec("u", link, tests.RtRepo1, "--symlinks=true", "--recursive=true")
  1939  	err = os.Remove(link)
  1940  	assert.NoError(t, err)
  1941  	artifactoryCli.Exec("dl", tests.RtRepo1+"/link", tests.GetTestResourcesPath()+"a/")
  1942  	validateSymLink(link, localFile, t)
  1943  	os.Remove(link)
  1944  	cleanArtifactoryTest()
  1945  }
  1946  
  1947  // Upload symlink pointing to directory using wildcard path to Artifactory.
  1948  // Download the symlink which was uploaded.
  1949  func TestSymlinkToDirWildcardHandling(t *testing.T) {
  1950  	if coreutils.IsWindows() {
  1951  		t.Skip("Running on windows, skipping...")
  1952  	}
  1953  	initArtifactoryTest(t)
  1954  	localFile := filepath.Join(tests.GetTestResourcesPath(), "a")
  1955  	link := filepath.Join(tests.GetTestResourcesPath()+"a/", "link")
  1956  	err := os.Symlink(localFile, link)
  1957  	assert.NoError(t, err)
  1958  	link1 := filepath.Join(tests.GetTestResourcesPath()+"a/", "lin*")
  1959  	artifactoryCli.Exec("u", link1, tests.RtRepo1, "--symlinks=true", "--recursive=true")
  1960  	err = os.Remove(link)
  1961  	assert.NoError(t, err)
  1962  	artifactoryCli.Exec("dl", tests.RtRepo1+"/link", tests.GetTestResourcesPath()+"a/")
  1963  	validateSymLink(link, localFile, t)
  1964  	os.Remove(link)
  1965  	cleanArtifactoryTest()
  1966  }
  1967  
  1968  // Upload symlink pointing to directory using wildcard path to Artifactory.
  1969  // Download the symlink which was uploaded.
  1970  // The test create circular links and the test suppose to prune the circular searching.
  1971  func TestSymlinkInsideSymlinkDirWithRecursionIssueUpload(t *testing.T) {
  1972  	if coreutils.IsWindows() {
  1973  		t.Skip("Running on windows, skipping...")
  1974  	}
  1975  	initArtifactoryTest(t)
  1976  	localDirPath := filepath.Join(tests.GetTestResourcesPath(), "a")
  1977  	link1 := filepath.Join(tests.GetTestResourcesPath()+"a/", "link1")
  1978  	err := os.Symlink(localDirPath, link1)
  1979  	assert.NoError(t, err)
  1980  	localFilePath := filepath.Join(tests.GetTestResourcesPath()+"a/", "a1.in")
  1981  	link2 := filepath.Join(tests.GetTestResourcesPath()+"a/", "link2")
  1982  	err = os.Symlink(localFilePath, link2)
  1983  	assert.NoError(t, err)
  1984  
  1985  	artifactoryCli.Exec("u", localDirPath+"/link*", tests.RtRepo1, "--symlinks=true", "--recursive=true")
  1986  	err = os.Remove(link1)
  1987  	assert.NoError(t, err)
  1988  
  1989  	err = os.Remove(link2)
  1990  	assert.NoError(t, err)
  1991  
  1992  	artifactoryCli.Exec("dl", tests.RtRepo1+"/link*", tests.GetTestResourcesPath()+"a/")
  1993  	validateSymLink(link1, localDirPath, t)
  1994  	os.Remove(link1)
  1995  	validateSymLink(link2, localFilePath, t)
  1996  	os.Remove(link2)
  1997  	cleanArtifactoryTest()
  1998  }
  1999  
  2000  func validateSymLink(localLinkPath, localFilePath string, t *testing.T) {
  2001  	exists := fileutils.IsPathSymlink(localLinkPath)
  2002  	assert.True(t, exists, "failed to download symlinks from artifactory")
  2003  	symlinks, err := filepath.EvalSymlinks(localLinkPath)
  2004  	assert.NoError(t, err, "can't eval symlinks")
  2005  	assert.Equal(t, localFilePath, symlinks, "Symlinks wasn't created as expected")
  2006  }
  2007  
  2008  func TestArtifactoryDeleteNoSpec(t *testing.T) {
  2009  	initArtifactoryTest(t)
  2010  	testArtifactorySimpleDelete(t, "")
  2011  }
  2012  
  2013  func TestArtifactoryDeleteBySpec(t *testing.T) {
  2014  	initArtifactoryTest(t)
  2015  	deleteSpecPath, err := tests.CreateSpec(tests.DeleteSimpleSpec)
  2016  	assert.NoError(t, err)
  2017  	testArtifactorySimpleDelete(t, deleteSpecPath)
  2018  }
  2019  
  2020  func testArtifactorySimpleDelete(t *testing.T, deleteSpecPath string) {
  2021  	preUploadBasicTestResources()
  2022  
  2023  	// Verify exists before deleting
  2024  	searchSpec, err := tests.CreateSpec(tests.SearchRepo1TestResources)
  2025  	assert.NoError(t, err)
  2026  	verifyExistInArtifactory(tests.GetRepo1TestResourcesExpected(), searchSpec, t)
  2027  
  2028  	if deleteSpecPath != "" {
  2029  		artifactoryCli.Exec("delete", "--spec="+deleteSpecPath)
  2030  	} else {
  2031  		artifactoryCli.Exec("delete", tests.RtRepo1+"/test_resources/b/*")
  2032  	}
  2033  
  2034  	verifyExistInArtifactory(tests.GetSimpleDelete(), searchSpec, t)
  2035  	cleanArtifactoryTest()
  2036  }
  2037  
  2038  func TestArtifactoryDeleteFolderWithWildcard(t *testing.T) {
  2039  	initArtifactoryTest(t)
  2040  	preUploadBasicTestResources()
  2041  
  2042  	// Verify exists before deleting
  2043  	searchSpec, err := tests.CreateSpec(tests.SearchRepo1TestResources)
  2044  	assert.NoError(t, err)
  2045  	verifyExistInArtifactory(tests.GetRepo1TestResourcesExpected(), searchSpec, t)
  2046  
  2047  	artifactoryCli.Exec("delete", tests.RtRepo1+"/test_resources/*/c")
  2048  
  2049  	verifyExistInArtifactory(tests.GetDeleteFolderWithWildcard(), searchSpec, t)
  2050  	cleanArtifactoryTest()
  2051  }
  2052  
  2053  func TestArtifactoryDeleteFolderCompletelyNoSpec(t *testing.T) {
  2054  	testArtifactoryDeleteFoldersNoSpec(t, false)
  2055  }
  2056  
  2057  func TestArtifactoryDeleteFolderContentNoSpec(t *testing.T) {
  2058  	testArtifactoryDeleteFoldersNoSpec(t, true)
  2059  }
  2060  
  2061  func testArtifactoryDeleteFoldersNoSpec(t *testing.T, contentOnly bool) {
  2062  	initArtifactoryTest(t)
  2063  	preUploadBasicTestResources()
  2064  
  2065  	// Verify exists before deleting
  2066  	searchSpec, err := tests.CreateSpec(tests.SearchRepo1TestResources)
  2067  	assert.NoError(t, err)
  2068  	verifyExistInArtifactory(tests.GetRepo1TestResourcesExpected(), searchSpec, t)
  2069  
  2070  	// Delete folder
  2071  	deletePath := tests.RtRepo1 + "/test_resources"
  2072  	// End with separator if content only
  2073  	if contentOnly {
  2074  		deletePath += "/"
  2075  	}
  2076  	artifactoryCli.Exec("delete", deletePath)
  2077  
  2078  	client, err := httpclient.ClientBuilder().Build()
  2079  	assert.NoError(t, err)
  2080  
  2081  	// Verify folder exists only if content only
  2082  	var expectedStatusCode int
  2083  	if contentOnly {
  2084  		expectedStatusCode = http.StatusOK
  2085  	} else {
  2086  		expectedStatusCode = http.StatusNotFound
  2087  	}
  2088  	resp, body, _, err := client.SendGet(serverDetails.ArtifactoryUrl+"api/storage/"+tests.RtRepo1+"/test_resources", true, artHttpDetails, "")
  2089  	assert.NoError(t, err)
  2090  	assert.Equal(t, expectedStatusCode, resp.StatusCode, "test_resources shouldn't be deleted: "+tests.RtRepo1+"/test_resources/ "+string(body))
  2091  
  2092  	// Verify no content exists
  2093  	verifyDoesntExistInArtifactory(searchSpec, t)
  2094  	cleanArtifactoryTest()
  2095  }
  2096  
  2097  func TestArtifactoryDeleteFoldersBySpecAllRepo(t *testing.T) {
  2098  	testArtifactoryDeleteFoldersBySpec(t, tests.DeleteSpec)
  2099  }
  2100  
  2101  func TestArtifactoryDeleteFoldersBySpecWildcardInRepo(t *testing.T) {
  2102  	testArtifactoryDeleteFoldersBySpec(t, tests.DeleteSpecWildcardInRepo)
  2103  }
  2104  
  2105  func testArtifactoryDeleteFoldersBySpec(t *testing.T, specPath string) {
  2106  	initArtifactoryTest(t)
  2107  	preUploadBasicTestResources()
  2108  
  2109  	// Verify exists before deleting
  2110  	searchSpec, err := tests.CreateSpec(tests.SearchRepo1TestResources)
  2111  	assert.NoError(t, err)
  2112  	verifyExistInArtifactory(tests.GetRepo1TestResourcesExpected(), searchSpec, t)
  2113  
  2114  	deleteSpecPath, err := tests.CreateSpec(specPath)
  2115  	assert.NoError(t, err)
  2116  	artifactoryCli.Exec("delete", "--spec="+deleteSpecPath)
  2117  
  2118  	completeSearchSpec, err := tests.CreateSpec(tests.SearchAllRepo1)
  2119  	assert.NoError(t, err)
  2120  	verifyDoesntExistInArtifactory(completeSearchSpec, t)
  2121  	cleanArtifactoryTest()
  2122  }
  2123  
  2124  func TestArtifactoryDeleteExcludeByCli(t *testing.T) {
  2125  	initArtifactoryTest(t)
  2126  
  2127  	// Upload files
  2128  	specFileA, err := tests.CreateSpec(tests.SplitUploadSpecA)
  2129  	assert.NoError(t, err)
  2130  	specFileB, err := tests.CreateSpec(tests.SplitUploadSpecB)
  2131  	assert.NoError(t, err)
  2132  
  2133  	artifactoryCli.Exec("upload", "--spec="+specFileA)
  2134  	artifactoryCli.Exec("upload", "--spec="+specFileB)
  2135  
  2136  	// Delete by pattern
  2137  	artifactoryCli.Exec("del", tests.RtRepo1+"/data/", "--exclude-patterns=*b1.in;*b2.in;*b3.in;*c1.in")
  2138  
  2139  	// Validate files are deleted
  2140  	cpMvDlByBuildAssertSpec, err := tests.CreateSpec(tests.CpMvDlByBuildAssertSpec)
  2141  	assert.NoError(t, err)
  2142  
  2143  	verifyExistInArtifactory(tests.GetBuildDeleteExpected(), cpMvDlByBuildAssertSpec, t)
  2144  
  2145  	// Cleanup
  2146  	cleanArtifactoryTest()
  2147  }
  2148  
  2149  func TestArtifactoryDeleteExclusionsByCli(t *testing.T) {
  2150  	initArtifactoryTest(t)
  2151  
  2152  	// Upload files
  2153  	specFileA, err := tests.CreateSpec(tests.SplitUploadSpecA)
  2154  	assert.NoError(t, err)
  2155  	specFileB, err := tests.CreateSpec(tests.SplitUploadSpecB)
  2156  	assert.NoError(t, err)
  2157  
  2158  	artifactoryCli.Exec("upload", "--spec="+specFileA)
  2159  	artifactoryCli.Exec("upload", "--spec="+specFileB)
  2160  
  2161  	// Delete by pattern
  2162  	artifactoryCli.Exec("del", tests.RtRepo1+"/data/", "--exclusions=*/*b1.in;*/*b2.in;*/*b3.in;*/*c1.in")
  2163  
  2164  	// Validate files are deleted
  2165  	cpMvDlByBuildAssertSpec, err := tests.CreateSpec(tests.CpMvDlByBuildAssertSpec)
  2166  	assert.NoError(t, err)
  2167  
  2168  	verifyExistInArtifactory(tests.GetBuildDeleteExpected(), cpMvDlByBuildAssertSpec, t)
  2169  
  2170  	// Cleanup
  2171  	cleanArtifactoryTest()
  2172  }
  2173  
  2174  func TestArtifactoryDeleteExcludeBySpec(t *testing.T) {
  2175  	initArtifactoryTest(t)
  2176  	// Upload files
  2177  	specFileA, err := tests.CreateSpec(tests.SplitUploadSpecA)
  2178  	assert.NoError(t, err)
  2179  	specFileB, err := tests.CreateSpec(tests.SplitUploadSpecB)
  2180  	assert.NoError(t, err)
  2181  	artifactoryCli.Exec("upload", "--spec="+specFileA)
  2182  	artifactoryCli.Exec("upload", "--spec="+specFileB)
  2183  
  2184  	specFile, err := tests.CreateSpec(tests.DelSpecExclude)
  2185  	assert.NoError(t, err)
  2186  
  2187  	// Delete by pattern
  2188  	artifactoryCli.Exec("del", "--spec="+specFile)
  2189  
  2190  	// Validate files are deleted
  2191  	cpMvDlByBuildAssertSpec, err := tests.CreateSpec(tests.CpMvDlByBuildAssertSpec)
  2192  	assert.NoError(t, err)
  2193  
  2194  	verifyExistInArtifactory(tests.GetBuildDeleteExpected(), cpMvDlByBuildAssertSpec, t)
  2195  
  2196  	// Cleanup
  2197  	cleanArtifactoryTest()
  2198  }
  2199  
  2200  func TestArtifactoryDeleteExclusionsBySpec(t *testing.T) {
  2201  	initArtifactoryTest(t)
  2202  	// Upload files
  2203  	specFileA, err := tests.CreateSpec(tests.SplitUploadSpecA)
  2204  	assert.NoError(t, err)
  2205  	specFileB, err := tests.CreateSpec(tests.SplitUploadSpecB)
  2206  	assert.NoError(t, err)
  2207  	artifactoryCli.Exec("upload", "--spec="+specFileA)
  2208  	artifactoryCli.Exec("upload", "--spec="+specFileB)
  2209  
  2210  	specFile, err := tests.CreateSpec(tests.DelSpecExclusions)
  2211  	assert.NoError(t, err)
  2212  
  2213  	// Delete by pattern
  2214  	artifactoryCli.Exec("del", "--spec="+specFile)
  2215  
  2216  	// Validate files are deleted
  2217  	cpMvDlByBuildAssertSpec, err := tests.CreateSpec(tests.CpMvDlByBuildAssertSpec)
  2218  	assert.NoError(t, err)
  2219  
  2220  	verifyExistInArtifactory(tests.GetBuildDeleteExpected(), cpMvDlByBuildAssertSpec, t)
  2221  
  2222  	// Cleanup
  2223  	cleanArtifactoryTest()
  2224  }
  2225  
  2226  // Deleting files when one file name is a prefix to another in the same dir
  2227  func TestArtifactoryDeletePrefixFiles(t *testing.T) {
  2228  	initArtifactoryTest(t)
  2229  
  2230  	// Prepare search command
  2231  	searchSpecBuilder := spec.NewBuilder().Pattern(tests.RtRepo1).Recursive(true)
  2232  	searchCmd := generic.NewSearchCommand()
  2233  	searchCmd.SetServerDetails(serverDetails)
  2234  	searchCmd.SetSpec(searchSpecBuilder.BuildSpec())
  2235  
  2236  	// Upload files
  2237  	specFile, err := tests.CreateSpec(tests.UploadPrefixFiles)
  2238  	assert.NoError(t, err)
  2239  	artifactoryCli.Exec("upload", "--spec="+specFile)
  2240  
  2241  	// Delete by pattern
  2242  	artifactoryCli.Exec("delete", tests.RtRepo1+"/*")
  2243  
  2244  	// Validate files are deleted
  2245  	reader, err := searchCmd.Search()
  2246  	assert.NoError(t, err)
  2247  	length, err := reader.Length()
  2248  	assert.NoError(t, err)
  2249  	assert.Equal(t, 0, length)
  2250  	assert.NoError(t, reader.Close())
  2251  
  2252  	// Cleanup
  2253  	cleanArtifactoryTest()
  2254  }
  2255  
  2256  func TestArtifactoryDeleteByProps(t *testing.T) {
  2257  	initArtifactoryTest(t)
  2258  
  2259  	// Upload files
  2260  	specFile, err := tests.CreateSpec(tests.UploadWithPropsSpec)
  2261  	assert.NoError(t, err)
  2262  	artifactoryCli.Exec("upload", "--spec="+specFile)
  2263  
  2264  	// Set properties to the directories as well (and their content)
  2265  	artifactoryCli.Exec("sp", tests.RtRepo1+"/a/b/", "D=5", "--include-dirs")
  2266  	artifactoryCli.Exec("sp", tests.RtRepo1+"/a/b/c/", "D=2", "--include-dirs")
  2267  
  2268  	//  Set the property D=5 to c1.in, which is a different value then its directory c/
  2269  	artifactoryCli.Exec("sp", tests.RtRepo1+"/a/b/c/c1.in", "D=5")
  2270  
  2271  	// Prepare search command
  2272  	searchSpecBuilder := spec.NewBuilder().Pattern(tests.RtRepo1).Recursive(true)
  2273  	searchCmd := generic.NewSearchCommand()
  2274  	searchCmd.SetServerDetails(serverDetails)
  2275  	searchCmd.SetSpec(searchSpecBuilder.BuildSpec())
  2276  
  2277  	// Delete all artifacts with D=5 but without c=3
  2278  	artifactoryCli.Exec("delete", tests.RtRepo1+"/*", "--props=D=5", "--exclude-props=c=3")
  2279  
  2280  	// Search all artifacts in repo1
  2281  	reader, err := searchCmd.Search()
  2282  	assert.NoError(t, err)
  2283  	for resultItem := new(utils.SearchResult); reader.NextRecord(resultItem) == nil; resultItem = new(utils.SearchResult) {
  2284  		assert.NoError(t, assertDateInSearchResult(*resultItem))
  2285  	}
  2286  	assert.NoError(t, reader.GetError())
  2287  	reader.Reset()
  2288  
  2289  	var resultItems []utils.SearchResult
  2290  	readerNoDate, err := utils.SearchResultNoDate(reader)
  2291  	assert.NoError(t, err)
  2292  	for resultItem := new(utils.SearchResult); readerNoDate.NextRecord(resultItem) == nil; resultItem = new(utils.SearchResult) {
  2293  		resultItems = append(resultItems, *resultItem)
  2294  	}
  2295  	assert.NoError(t, readerNoDate.GetError())
  2296  	assert.ElementsMatch(t, resultItems, tests.GetSearchResultAfterDeleteByPropsStep1())
  2297  	assert.NoError(t, readerNoDate.Close())
  2298  	assert.NoError(t, reader.Close())
  2299  
  2300  	// Delete all artifacts with c=3 but without a=1
  2301  	artifactoryCli.Exec("delete", tests.RtRepo1+"/*", "--props=c=3", "--exclude-props=a=1")
  2302  
  2303  	// Search all artifacts in repo1
  2304  	reader, err = searchCmd.Search()
  2305  	assert.NoError(t, err)
  2306  	for resultItem := new(utils.SearchResult); reader.NextRecord(resultItem) == nil; resultItem = new(utils.SearchResult) {
  2307  		assert.NoError(t, assertDateInSearchResult(*resultItem))
  2308  	}
  2309  	assert.NoError(t, reader.GetError())
  2310  	reader.Reset()
  2311  
  2312  	resultItems = []utils.SearchResult{}
  2313  	readerNoDate, err = utils.SearchResultNoDate(reader)
  2314  	assert.NoError(t, err)
  2315  	for resultItem := new(utils.SearchResult); readerNoDate.NextRecord(resultItem) == nil; resultItem = new(utils.SearchResult) {
  2316  		resultItems = append(resultItems, *resultItem)
  2317  	}
  2318  	assert.NoError(t, readerNoDate.GetError())
  2319  	assert.ElementsMatch(t, resultItems, tests.GetSearchResultAfterDeleteByPropsStep2())
  2320  	assert.NoError(t, readerNoDate.Close())
  2321  	assert.NoError(t, reader.Close())
  2322  
  2323  	// Delete all artifacts with a=1 but without b=3&c=3
  2324  	artifactoryCli.Exec("delete", tests.RtRepo1+"/*", "--props=a=1", "--exclude-props=b=3;c=3")
  2325  
  2326  	// Search all artifacts in repo1
  2327  	reader, err = searchCmd.Search()
  2328  	assert.NoError(t, err)
  2329  	for resultItem := new(utils.SearchResult); reader.NextRecord(resultItem) == nil; resultItem = new(utils.SearchResult) {
  2330  		assert.NoError(t, assertDateInSearchResult(*resultItem))
  2331  	}
  2332  	assert.NoError(t, reader.GetError())
  2333  	reader.Reset()
  2334  
  2335  	resultItems = []utils.SearchResult{}
  2336  	readerNoDate, err = utils.SearchResultNoDate(reader)
  2337  	assert.NoError(t, err)
  2338  	for resultItem := new(utils.SearchResult); readerNoDate.NextRecord(resultItem) == nil; resultItem = new(utils.SearchResult) {
  2339  		resultItems = append(resultItems, *resultItem)
  2340  	}
  2341  	assert.NoError(t, readerNoDate.GetError())
  2342  	assert.ElementsMatch(t, resultItems, tests.GetSearchResultAfterDeleteByPropsStep3())
  2343  	assert.NoError(t, readerNoDate.Close())
  2344  	assert.NoError(t, reader.Close())
  2345  
  2346  	// Cleanup
  2347  	cleanArtifactoryTest()
  2348  }
  2349  
  2350  func TestArtifactoryMultipleFileSpecsUpload(t *testing.T) {
  2351  	initArtifactoryTest(t)
  2352  	specFile, err := tests.CreateSpec(tests.UploadMultipleFileSpecs)
  2353  	assert.NoError(t, err)
  2354  	resultSpecFile, err := tests.CreateSpec(tests.SearchAllRepo1)
  2355  	assert.NoError(t, err)
  2356  	artifactoryCli.Exec("upload", "--spec="+specFile)
  2357  
  2358  	verifyExistInArtifactory(tests.GetMultipleFileSpecs(), resultSpecFile, t)
  2359  	verifyExistInArtifactoryByProps([]string{tests.RtRepo1 + "/multiple/properties/testdata/a/b/b2.in"}, tests.RtRepo1+"/*/properties/*.in", "searchMe=true", t)
  2360  	cleanArtifactoryTest()
  2361  }
  2362  
  2363  func TestArtifactorySimplePlaceHolders(t *testing.T) {
  2364  	initArtifactoryTest(t)
  2365  	specFile, err := tests.CreateSpec(tests.UploadSimplePlaceholders)
  2366  	assert.NoError(t, err)
  2367  
  2368  	resultSpecFile, err := tests.CreateSpec(tests.SearchSimplePlaceholders)
  2369  	assert.NoError(t, err)
  2370  
  2371  	artifactoryCli.Exec("upload", "--spec="+specFile)
  2372  
  2373  	verifyExistInArtifactory(tests.GetSimplePlaceholders(), resultSpecFile, t)
  2374  	cleanArtifactoryTest()
  2375  }
  2376  
  2377  func TestArtifactoryFolderUploadRecursiveNonFlat(t *testing.T) {
  2378  	initArtifactoryTest(t)
  2379  	dirInnerPath := fileutils.GetFileSeparator() + filepath.Join("inner", "folder")
  2380  	canonicalPath := tests.Out + dirInnerPath
  2381  
  2382  	err := os.MkdirAll(canonicalPath, 0777)
  2383  	assert.NoError(t, err)
  2384  	artifactoryCli.Exec("upload", tests.Out+"/(*)", tests.RtRepo1+"/{1}/", "--include-dirs=true", "--recursive=true", "--flat=false")
  2385  	err = os.RemoveAll(tests.Out)
  2386  	assert.NoError(t, err)
  2387  	artifactoryCli.Exec("download", tests.RtRepo1, tests.Out+"/", "--include-dirs=true", "--recursive=true")
  2388  	assert.True(t, fileutils.IsPathExists(filepath.Join(tests.Out, "inner", "folder", "out", "inner", "folder"), false), "Failed to download folders from Artifactory")
  2389  	// Cleanup
  2390  	cleanArtifactoryTest()
  2391  }
  2392  
  2393  func TestArtifactoryFlatFolderUpload(t *testing.T) {
  2394  	initArtifactoryTest(t)
  2395  	dirInnerPath := fileutils.GetFileSeparator() + filepath.Join("inner", "folder")
  2396  	canonicalPath := tests.Out + dirInnerPath
  2397  	err := os.MkdirAll(canonicalPath, 0777)
  2398  	assert.NoError(t, err)
  2399  	artifactoryCli.Exec("upload", tests.Out+"/(*)", tests.RtRepo1+"/{1}/", "--include-dirs=true", "--flat=true")
  2400  	err = os.RemoveAll(tests.Out)
  2401  	assert.NoError(t, err)
  2402  	// Non flat download
  2403  	artifactoryCli.Exec("download", tests.RtRepo1, tests.Out+"/", "--include-dirs=true", "--recursive=true")
  2404  	assert.True(t, fileutils.IsPathExists(filepath.Join(canonicalPath, "folder"), false), "Failed to download folders from Artifactory")
  2405  	// Cleanup
  2406  	cleanArtifactoryTest()
  2407  }
  2408  
  2409  // Test the definition of bottom chain directories - Directories which do not include other directories that match the pattern
  2410  func TestArtifactoryIncludeDirFlatNonEmptyFolderUpload(t *testing.T) {
  2411  	initArtifactoryTest(t)
  2412  	// 'c' folder is defined as bottom chain directory therefore should be uploaded when using flat=true even though 'c' is not empty
  2413  	artifactoryCli.Exec("upload", tests.GetTestResourcesPath()+"a/b/*", tests.RtRepo1, "--include-dirs=true", "--flat=true")
  2414  	artifactoryCli.Exec("download", tests.RtRepo1, tests.Out+"/", "--include-dirs=true", "--recursive=true")
  2415  	assert.True(t, fileutils.IsPathExists(tests.Out+"/c", false), "Failed to download folders from Artifactory")
  2416  	// Cleanup
  2417  	cleanArtifactoryTest()
  2418  }
  2419  
  2420  // Test the definition of bottom chain directories - Directories which do not include other directories that match the pattern
  2421  func TestArtifactoryDownloadNotIncludeDirs(t *testing.T) {
  2422  	initArtifactoryTest(t)
  2423  	// 'c' folder is defined as bottom chain directory therefore should be uploaded when using flat=true even though 'c' is not empty
  2424  	artifactoryCli.Exec("upload", tests.GetTestResourcesPath()+"*/c", tests.RtRepo1, "--include-dirs=true", "--flat=true")
  2425  	artifactoryCli.Exec("download", tests.RtRepo1, tests.Out+"/", "--recursive=true")
  2426  	assert.False(t, fileutils.IsPathExists(tests.Out+"/c", false), "Failed to download folders from Artifactory")
  2427  	// Cleanup
  2428  	cleanArtifactoryTest()
  2429  }
  2430  
  2431  // Test the definition of bottom chain directories - Directories which do not include other directories that match the pattern
  2432  func TestArtifactoryDownloadFlatTrue(t *testing.T) {
  2433  	initArtifactoryTest(t)
  2434  	canonicalPath := tests.GetTestResourcesPath() + path.Join("an", "empty", "folder")
  2435  	err := os.MkdirAll(canonicalPath, 0777)
  2436  	assert.NoError(t, err)
  2437  
  2438  	// 'c' folder is defined as bottom chain directory therefore should be uploaded when using flat=true even though 'c' is not empty
  2439  	artifactoryCli.Exec("upload", tests.GetTestResourcesPath()+"(a*)/*", tests.RtRepo1+"/{1}/", "--include-dirs=true", "--flat=true")
  2440  	// Download without include-dirs
  2441  	artifactoryCli.Exec("download", tests.RtRepo1, tests.Out+"/", "--recursive=true", "--flat=true")
  2442  	assert.False(t, fileutils.IsPathExists(tests.Out+"/c", false), "'c' folder shouldn't exist.")
  2443  
  2444  	artifactoryCli.Exec("download", tests.RtRepo1, tests.Out+"/", "--include-dirs=true", "--recursive=true", "--flat=true")
  2445  	// Inner folder with files in it
  2446  	assert.True(t, fileutils.IsPathExists(tests.Out+"/c", false), "'c' folder should exist.")
  2447  	// Empty inner folder
  2448  	assert.True(t, fileutils.IsPathExists(tests.Out+"/folder", false), "'folder' folder should exist.")
  2449  	// Folder on root with files
  2450  	assert.True(t, fileutils.IsPathExists(tests.Out+"/a$+~&^a#", false), "'a$+~&^a#' folder should exist.")
  2451  	// None bottom directory - shouldn't exist.
  2452  	assert.False(t, fileutils.IsPathExists(tests.Out+"/a", false), "'a' folder shouldn't exist.")
  2453  	// None bottom directory - shouldn't exist.
  2454  	assert.False(t, fileutils.IsPathExists(tests.Out+"/b", false), "'b' folder shouldn't exist.")
  2455  	// Cleanup
  2456  	cleanArtifactoryTest()
  2457  }
  2458  
  2459  func TestArtifactoryIncludeDirFlatNonEmptyFolderUploadMatchingPattern(t *testing.T) {
  2460  	initArtifactoryTest(t)
  2461  	// 'c' folder is defined as bottom chain directory therefore should be uploaded when using flat=true even though 'c' is not empty
  2462  	artifactoryCli.Exec("upload", tests.GetTestResourcesPath()+"*/c", tests.RtRepo1, "--include-dirs=true", "--flat=true")
  2463  	artifactoryCli.Exec("download", tests.RtRepo1, tests.Out+"/", "--include-dirs=true", "--recursive=true")
  2464  	assert.True(t, fileutils.IsPathExists(tests.Out+"/c", false), "Failed to download folders from Artifactory")
  2465  	// Cleanup
  2466  	cleanArtifactoryTest()
  2467  }
  2468  
  2469  // Test the definition of bottom chain directories - Directories which do not include other directories that match the pattern
  2470  func TestArtifactoryUploadFlatFolderWithFileAndInnerEmptyMatchingPattern(t *testing.T) {
  2471  	initArtifactoryTest(t)
  2472  	newFolderPath := tests.GetTestResourcesPath() + "a/b/c/d"
  2473  	err := os.MkdirAll(newFolderPath, 0777)
  2474  	assert.NoError(t, err)
  2475  	// We created an empty child folder to 'c' therefore 'c' is not longer a bottom chain and new 'd' inner directory is indeed bottom chain directory.
  2476  	// 'd' should uploaded and 'c' shouldn't
  2477  	artifactoryCli.Exec("upload", tests.GetTestResourcesPath()+"a/b/*", tests.RtRepo1, "--include-dirs=true", "--flat=true")
  2478  	err = os.RemoveAll(newFolderPath)
  2479  	assert.NoError(t, err)
  2480  	artifactoryCli.Exec("download", tests.RtRepo1, tests.Out+"/", "--include-dirs=true", "--recursive=true")
  2481  	assert.False(t, fileutils.IsPathExists(tests.Out+"/c", false), "'c' folder shouldn't exist")
  2482  	assert.True(t, fileutils.IsPathExists(tests.Out+"/d", false), "bottom chain directory, 'd', is missing")
  2483  	// Cleanup
  2484  	cleanArtifactoryTest()
  2485  }
  2486  
  2487  // Test the definition of bottom chain directories - Directories which do not include other directories that match the pattern
  2488  func TestArtifactoryUploadFlatFolderWithFileAndInnerEmptyMatchingPatternWithPlaceHolders(t *testing.T) {
  2489  	initArtifactoryTest(t)
  2490  	relativePath := "/b/c/d"
  2491  	fullPath := tests.GetTestResourcesPath() + "a/" + relativePath
  2492  	err := os.MkdirAll(fullPath, 0777)
  2493  	assert.NoError(t, err)
  2494  	// We created a empty child folder to 'c' therefore 'c' is not longer a bottom chain and new 'd' inner directory is indeed bottom chain directory.
  2495  	// 'd' should uploaded and 'c' shouldn't
  2496  	artifactoryCli.Exec("upload", tests.GetTestResourcesPath()+"a/(*)/*", tests.RtRepo1+"/{1}/", "--include-dirs=true", "--flat=true")
  2497  	err = os.RemoveAll(fullPath)
  2498  	assert.NoError(t, err)
  2499  	artifactoryCli.Exec("download", tests.RtRepo1, tests.Out+"/", "--include-dirs=true", "--recursive=true")
  2500  	assert.True(t, fileutils.IsPathExists(tests.Out+relativePath, false), "bottom chain directory, 'd', is missing")
  2501  
  2502  	// Cleanup
  2503  	cleanArtifactoryTest()
  2504  }
  2505  
  2506  func TestArtifactoryFlatFolderDownload1(t *testing.T) {
  2507  	initArtifactoryTest(t)
  2508  	dirInnerPath := fileutils.GetFileSeparator() + filepath.Join("inner", "folder")
  2509  	canonicalPath := tests.Out + dirInnerPath
  2510  	err := os.MkdirAll(canonicalPath, 0777)
  2511  	assert.NoError(t, err)
  2512  	// Flat true by default for upload, by using placeholder we indeed create folders hierarchy in Artifactory inner/folder/folder
  2513  	artifactoryCli.Exec("upload", tests.Out+"/(*)", tests.RtRepo1+"/{1}/", "--include-dirs=true")
  2514  	err = os.RemoveAll(tests.Out)
  2515  	assert.NoError(t, err)
  2516  	// Only the inner folder should be downland e.g 'folder'
  2517  	artifactoryCli.Exec("download", tests.RtRepo1, tests.Out+"/", "--include-dirs=true", "--flat=true")
  2518  	assert.False(t, !fileutils.IsPathExists(filepath.Join(tests.Out, "folder"), false) &&
  2519  		fileutils.IsPathExists(filepath.Join(tests.Out, "inner"), false),
  2520  		"Failed to download folders from Artifactory")
  2521  	// Cleanup
  2522  	cleanArtifactoryTest()
  2523  }
  2524  
  2525  func TestArtifactoryFolderUploadRecursiveUsingSpec(t *testing.T) {
  2526  	initArtifactoryTest(t)
  2527  	assert.NoError(t, createEmptyTestDir())
  2528  	specFile, err := tests.CreateSpec(tests.UploadEmptyDirs)
  2529  	assert.NoError(t, err)
  2530  	artifactoryCli.Exec("upload", "--spec="+specFile)
  2531  
  2532  	specFile, err = tests.CreateSpec(tests.DownloadEmptyDirs)
  2533  	assert.NoError(t, err)
  2534  	artifactoryCli.Exec("download", "--spec="+specFile)
  2535  	assert.True(t, fileutils.IsPathExists(tests.Out+"/folder", false), "Failed to download folders from Artifactory")
  2536  	// Cleanup
  2537  	cleanArtifactoryTest()
  2538  }
  2539  
  2540  func TestArtifactoryFolderUploadNonRecursive(t *testing.T) {
  2541  	initArtifactoryTest(t)
  2542  	canonicalPath := filepath.Join(tests.Out, "inner", "folder")
  2543  	err := os.MkdirAll(canonicalPath, 0777)
  2544  	assert.NoError(t, err)
  2545  	artifactoryCli.Exec("upload", tests.Out+"/", tests.RtRepo1, "--recursive=true", "--include-dirs=true")
  2546  	err = os.RemoveAll(tests.Out)
  2547  	assert.NoError(t, err)
  2548  	artifactoryCli.Exec("download", tests.RtRepo1, tests.Out+"/", "--include-dirs=true")
  2549  	assert.True(t, fileutils.IsPathExists(tests.Out+"/folder", false), "Failed to download folder from Artifactory")
  2550  	assert.False(t, fileutils.IsPathExists(canonicalPath, false), "Path should be flat ")
  2551  	// Cleanup
  2552  	cleanArtifactoryTest()
  2553  }
  2554  
  2555  func TestArtifactoryFolderDownloadNonRecursive(t *testing.T) {
  2556  	initArtifactoryTest(t)
  2557  	canonicalPath := filepath.Join(tests.Out, "inner", "folder")
  2558  	err := os.MkdirAll(canonicalPath, 0777)
  2559  	assert.NoError(t, err)
  2560  	artifactoryCli.Exec("upload", tests.Out+"/", tests.RtRepo1, "--recursive=true", "--include-dirs=true", "--flat=false")
  2561  	err = os.RemoveAll(tests.Out)
  2562  	assert.NoError(t, err)
  2563  	artifactoryCli.Exec("download", tests.RtRepo1+"/*", "--recursive=false", "--include-dirs=true")
  2564  	assert.True(t, fileutils.IsPathExists(tests.Out, false), "Failed to download folder from Artifactory")
  2565  	assert.False(t, fileutils.IsPathExists(canonicalPath, false), "Path should be flat. ")
  2566  	// Cleanup
  2567  	cleanArtifactoryTest()
  2568  }
  2569  
  2570  func TestArtifactoryChecksumDownload(t *testing.T) {
  2571  	initArtifactoryTest(t)
  2572  
  2573  	var filePath = "testdata/a/a1.in"
  2574  	artifactoryCli.Exec("upload", filePath, tests.RtRepo1)
  2575  	testChecksumDownload(t, "/a1.in")
  2576  	// Cleanup
  2577  	cleanArtifactoryTest()
  2578  }
  2579  
  2580  func TestArtifactoryChecksumDownloadRenameFileName(t *testing.T) {
  2581  	initArtifactoryTest(t)
  2582  
  2583  	var filePath = "testdata/a/a1.in"
  2584  	artifactoryCli.Exec("upload", filePath, tests.RtRepo1)
  2585  	testChecksumDownload(t, "/a1.out")
  2586  	// Cleanup
  2587  	cleanArtifactoryTest()
  2588  }
  2589  
  2590  func testChecksumDownload(t *testing.T, outFileName string) {
  2591  	artifactoryCli.Exec("download", tests.RtRepo1+"/a1.in", tests.Out+outFileName)
  2592  
  2593  	exists, err := fileutils.IsFileExists(tests.Out+outFileName, false)
  2594  	assert.NoError(t, err)
  2595  	assert.True(t, exists, "Failed to download file from Artifactory")
  2596  
  2597  	firstFileInfo, _ := os.Stat(tests.Out + outFileName)
  2598  	firstDownloadTime := firstFileInfo.ModTime()
  2599  
  2600  	artifactoryCli.Exec("download", tests.RtRepo1+"/a1.in", tests.Out+outFileName)
  2601  	secondFileInfo, _ := os.Stat(tests.Out + outFileName)
  2602  	secondDownloadTime := secondFileInfo.ModTime()
  2603  
  2604  	assert.Equal(t, firstDownloadTime, secondDownloadTime, "Checksum download failed, the file was downloaded twice")
  2605  }
  2606  
  2607  func TestArtifactoryDownloadByPatternAndBuildUsingSpec(t *testing.T) {
  2608  	initArtifactoryTest(t)
  2609  	buildNumberA, buildNumberB := "10", "11"
  2610  	inttestutils.DeleteBuild(serverDetails.ArtifactoryUrl, tests.RtBuildName1, artHttpDetails)
  2611  	specFile, err := tests.CreateSpec(tests.BuildDownloadSpec)
  2612  	assert.NoError(t, err)
  2613  	// Upload files with buildName and buildNumber
  2614  	specFileA, err := tests.CreateSpec(tests.SplitUploadSpecA)
  2615  	assert.NoError(t, err)
  2616  	specFileB, err := tests.CreateSpec(tests.SplitUploadSpecB)
  2617  	assert.NoError(t, err)
  2618  	artifactoryCli.Exec("upload", "--spec="+specFileA, "--build-name="+tests.RtBuildName1, "--build-number="+buildNumberA)
  2619  	artifactoryCli.Exec("upload", "--spec="+specFileB, "--build-name="+tests.RtBuildName1, "--build-number="+buildNumberB)
  2620  
  2621  	// Publish buildInfo
  2622  	artifactoryCli.Exec("build-publish", tests.RtBuildName1, buildNumberA)
  2623  	artifactoryCli.Exec("build-publish", tests.RtBuildName1, buildNumberB)
  2624  
  2625  	// Download by build number
  2626  	artifactoryCli.Exec("download", "--spec="+specFile)
  2627  
  2628  	// Validate files are downloaded by build number
  2629  	paths, _ := fileutils.ListFilesRecursiveWalkIntoDirSymlink(tests.Out, false)
  2630  	err = tests.ValidateListsIdentical(tests.GetBuildDownload(), paths)
  2631  	assert.NoError(t, err)
  2632  
  2633  	// Cleanup
  2634  	inttestutils.DeleteBuild(serverDetails.ArtifactoryUrl, tests.RtBuildName1, artHttpDetails)
  2635  	cleanArtifactoryTest()
  2636  }
  2637  
  2638  func TestArtifactoryGenericBuildnameAndNumberFromEnv(t *testing.T) {
  2639  	initArtifactoryTest(t)
  2640  	buildNumberA, buildNumberB := "10", "11"
  2641  	inttestutils.DeleteBuild(serverDetails.ArtifactoryUrl, tests.RtBuildName1, artHttpDetails)
  2642  	specFile, err := tests.CreateSpec(tests.BuildDownloadSpec)
  2643  	assert.NoError(t, err)
  2644  	// Upload files with buildName and buildNumber
  2645  	specFileA, err := tests.CreateSpec(tests.SplitUploadSpecA)
  2646  	assert.NoError(t, err)
  2647  	specFileB, err := tests.CreateSpec(tests.SplitUploadSpecB)
  2648  	assert.NoError(t, err)
  2649  	os.Setenv(coreutils.BuildName, tests.RtBuildName1)
  2650  	os.Setenv(coreutils.BuildNumber, buildNumberA)
  2651  	defer os.Unsetenv(coreutils.BuildName)
  2652  	defer os.Unsetenv(coreutils.BuildNumber)
  2653  	artifactoryCli.Exec("upload", "--spec="+specFileA)
  2654  	os.Setenv(coreutils.BuildNumber, "11")
  2655  	artifactoryCli.Exec("upload", "--spec="+specFileB)
  2656  
  2657  	// Publish buildInfo
  2658  	os.Setenv(coreutils.BuildNumber, buildNumberA)
  2659  	artifactoryCli.Exec("build-publish")
  2660  	os.Setenv(coreutils.BuildNumber, buildNumberB)
  2661  	artifactoryCli.Exec("build-publish")
  2662  
  2663  	// Download by build number
  2664  	artifactoryCli.Exec("download", "--spec="+specFile)
  2665  
  2666  	// Validate files are downloaded by build number
  2667  	paths, _ := fileutils.ListFilesRecursiveWalkIntoDirSymlink(tests.Out, false)
  2668  	err = tests.ValidateListsIdentical(tests.GetBuildDownload(), paths)
  2669  	assert.NoError(t, err)
  2670  
  2671  	// Cleanup
  2672  	inttestutils.DeleteBuild(serverDetails.ArtifactoryUrl, tests.RtBuildName1, artHttpDetails)
  2673  	cleanArtifactoryTest()
  2674  }
  2675  
  2676  func TestArtifactoryDownloadByBuildNoPatternUsingSpec(t *testing.T) {
  2677  	initArtifactoryTest(t)
  2678  	buildNumberA, buildNumberB := "10", "11"
  2679  	inttestutils.DeleteBuild(serverDetails.ArtifactoryUrl, tests.RtBuildName1, artHttpDetails)
  2680  	specFile, err := tests.CreateSpec(tests.BuildDownloadSpecNoPattern)
  2681  	assert.NoError(t, err)
  2682  	// Upload files with buildName and buildNumber
  2683  	specFileA, err := tests.CreateSpec(tests.SplitUploadSpecA)
  2684  	assert.NoError(t, err)
  2685  	specFileB, err := tests.CreateSpec(tests.SplitUploadSpecB)
  2686  	assert.NoError(t, err)
  2687  	artifactoryCli.Exec("upload", "--spec="+specFileA, "--build-name="+tests.RtBuildName1, "--build-number="+buildNumberA)
  2688  	artifactoryCli.Exec("upload", "--spec="+specFileB, "--build-name="+tests.RtBuildName1, "--build-number="+buildNumberB)
  2689  
  2690  	// Publish buildInfo
  2691  	artifactoryCli.Exec("build-publish", tests.RtBuildName1, buildNumberA)
  2692  	artifactoryCli.Exec("build-publish", tests.RtBuildName1, buildNumberB)
  2693  
  2694  	// Download by build number
  2695  	artifactoryCli.Exec("download", "--spec="+specFile)
  2696  
  2697  	// Validate files are downloaded by build number
  2698  	paths, _ := fileutils.ListFilesRecursiveWalkIntoDirSymlink(tests.Out, false)
  2699  	err = tests.ValidateListsIdentical(tests.GetBuildDownload(), paths)
  2700  	assert.NoError(t, err)
  2701  
  2702  	// Cleanup
  2703  	inttestutils.DeleteBuild(serverDetails.ArtifactoryUrl, tests.RtBuildName1, artHttpDetails)
  2704  	cleanArtifactoryTest()
  2705  }
  2706  
  2707  func prepareDownloadByBuildWithDependenciesTests(t *testing.T) {
  2708  	// Init
  2709  	initArtifactoryTest(t)
  2710  	buildNumber := "1337"
  2711  	inttestutils.DeleteBuild(serverDetails.ArtifactoryUrl, tests.RtBuildName1, artHttpDetails)
  2712  
  2713  	// Upload files with buildName and buildNumber
  2714  	specFileA, err := tests.CreateSpec(tests.SplitUploadSpecA)
  2715  	assert.NoError(t, err)
  2716  	specFileB, err := tests.CreateSpec(tests.SplitUploadSpecB)
  2717  	assert.NoError(t, err)
  2718  
  2719  	// Add build artifacts.
  2720  	artifactoryCli.Exec("upload", "--spec="+specFileA, "--build-name="+tests.RtBuildName1, "--build-number="+buildNumber)
  2721  	artifactoryCli.Exec("upload", "--spec="+specFileB)
  2722  
  2723  	// Add build dependencies.
  2724  	artifactoryCliNoCreds := tests.NewJfrogCli(execMain, "jfrog rt", "")
  2725  	artifactoryCliNoCreds.Exec("bad", "--spec="+specFileB, tests.RtBuildName1, buildNumber)
  2726  
  2727  	// Publish build.
  2728  	artifactoryCli.Exec("build-publish", tests.RtBuildName1, buildNumber)
  2729  }
  2730  
  2731  func TestArtifactoryDownloadByBuildWithDependenciesSpecNoPattern(t *testing.T) {
  2732  	prepareDownloadByBuildWithDependenciesTests(t)
  2733  
  2734  	// Download with exclude-artifacts.
  2735  	specFile, err := tests.CreateSpec(tests.BuildDownloadSpecExcludeArtifacts)
  2736  	assert.NoError(t, err)
  2737  	artifactoryCli.Exec("download", "--spec="+specFile)
  2738  	// Validate.
  2739  	paths, _ := fileutils.ListFilesRecursiveWalkIntoDirSymlink(tests.Out, false)
  2740  	err = tests.ValidateListsIdentical(tests.GetBuildDownloadDoesntExist(), paths)
  2741  	assert.NoError(t, err)
  2742  
  2743  	// Download deps-only.
  2744  	specFile, err = tests.CreateSpec(tests.BuildDownloadSpecDepsOnly)
  2745  	assert.NoError(t, err)
  2746  	artifactoryCli.Exec("download", "--spec="+specFile)
  2747  	// Validate.
  2748  	paths, _ = fileutils.ListFilesRecursiveWalkIntoDirSymlink(tests.Out, false)
  2749  	err = tests.ValidateListsIdentical(tests.GetDownloadByBuildOnlyDeps(), paths)
  2750  	assert.NoError(t, err)
  2751  
  2752  	// Download artifacts and deps.
  2753  	specFile, err = tests.CreateSpec(tests.BuildDownloadSpecIncludeDeps)
  2754  	assert.NoError(t, err)
  2755  	artifactoryCli.Exec("download", "--spec="+specFile)
  2756  	// Validate.
  2757  	paths, _ = fileutils.ListFilesRecursiveWalkIntoDirSymlink(tests.Out+string(os.PathSeparator)+"download"+string(os.PathSeparator)+"download_build_with_dependencies", false)
  2758  	err = tests.ValidateListsIdentical(tests.GetDownloadByBuildIncludeDeps(), paths)
  2759  	assert.NoError(t, err)
  2760  
  2761  	// Cleanup
  2762  	inttestutils.DeleteBuild(serverDetails.ArtifactoryUrl, tests.RtBuildName1, artHttpDetails)
  2763  	cleanArtifactoryTest()
  2764  }
  2765  
  2766  func TestArtifactoryDownloadByBuildWithDependencies(t *testing.T) {
  2767  	prepareDownloadByBuildWithDependenciesTests(t)
  2768  
  2769  	// Download with exclude-artifacts.
  2770  	artifactoryCli.Exec("download", tests.RtRepo1, "out/download/download_build_with_dependencies/", "--build="+tests.RtBuildName1, "--exclude-artifacts=true", "--flat=true")
  2771  	// Validate.
  2772  	paths, _ := fileutils.ListFilesRecursiveWalkIntoDirSymlink(tests.Out, false)
  2773  	err := tests.ValidateListsIdentical(tests.GetBuildDownloadDoesntExist(), paths)
  2774  	assert.NoError(t, err)
  2775  
  2776  	// Download deps-only.
  2777  	artifactoryCli.Exec("download", tests.RtRepo1, "out/download/download_build_only_dependencies/", "--build="+tests.RtBuildName1, "--exclude-artifacts=true", "--include-deps=true", "--flat=true")
  2778  	// Validate.
  2779  	paths, _ = fileutils.ListFilesRecursiveWalkIntoDirSymlink(tests.Out, false)
  2780  	err = tests.ValidateListsIdentical(tests.GetDownloadByBuildOnlyDeps(), paths)
  2781  	assert.NoError(t, err)
  2782  
  2783  	// Download artifacts and deps.
  2784  	artifactoryCli.Exec("download", tests.RtRepo1, "out/download/download_build_with_dependencies/", "--build="+tests.RtBuildName1, "--include-deps=true", "--flat=true")
  2785  	// Validate.
  2786  	paths, _ = fileutils.ListFilesRecursiveWalkIntoDirSymlink(tests.Out+string(os.PathSeparator)+"download"+string(os.PathSeparator)+"download_build_with_dependencies", false)
  2787  	err = tests.ValidateListsIdentical(tests.GetDownloadByBuildIncludeDeps(), paths)
  2788  	assert.NoError(t, err)
  2789  
  2790  	// Cleanup
  2791  	inttestutils.DeleteBuild(serverDetails.ArtifactoryUrl, tests.RtBuildName1, artHttpDetails)
  2792  	cleanArtifactoryTest()
  2793  }
  2794  
  2795  // Upload a file to build A.
  2796  // Verify that it doesn't exist in B.
  2797  func TestArtifactoryDownloadArtifactDoesntExistInBuild(t *testing.T) {
  2798  	initArtifactoryTest(t)
  2799  	buildNumber := "10"
  2800  	inttestutils.DeleteBuild(serverDetails.ArtifactoryUrl, tests.RtBuildName1, artHttpDetails)
  2801  	specFile, err := tests.CreateSpec(tests.BuildDownloadSpecNoBuildNumber)
  2802  	assert.NoError(t, err)
  2803  	// Upload a file
  2804  	artifactoryCli.Exec("upload", "testdata/a/a1.in", tests.RtRepo1+"/data/a10.in", "--build-name="+tests.RtBuildName1, "--build-number="+buildNumber)
  2805  
  2806  	// Publish buildInfo
  2807  	artifactoryCli.Exec("build-publish", tests.RtBuildName1, buildNumber)
  2808  
  2809  	// Download from different build number
  2810  	artifactoryCli.Exec("download", "--spec="+specFile)
  2811  
  2812  	paths, _ := fileutils.ListFilesRecursiveWalkIntoDirSymlink(tests.Out, false)
  2813  	err = tests.ValidateListsIdentical(tests.GetBuildDownloadDoesntExist(), paths)
  2814  	assert.NoError(t, err)
  2815  
  2816  	// Cleanup
  2817  	inttestutils.DeleteBuild(serverDetails.ArtifactoryUrl, tests.RtBuildName1, artHttpDetails)
  2818  	cleanArtifactoryTest()
  2819  }
  2820  
  2821  // Upload a file to 2 different builds.
  2822  // Verify that we don't download files with same sha and different build name and build number.
  2823  func TestArtifactoryDownloadByShaAndBuild(t *testing.T) {
  2824  	initArtifactoryTest(t)
  2825  	buildNumberA, buildNumberB, buildNumberC := "10", "11", "12"
  2826  	inttestutils.DeleteBuild(serverDetails.ArtifactoryUrl, tests.RtBuildName1, artHttpDetails)
  2827  	inttestutils.DeleteBuild(serverDetails.ArtifactoryUrl, tests.RtBuildName2, artHttpDetails)
  2828  	specFile, err := tests.CreateSpec(tests.BuildDownloadSpecNoBuildNumber)
  2829  	assert.NoError(t, err)
  2830  
  2831  	// Upload 3 similar files to 3 different builds
  2832  	artifactoryCli.Exec("upload", "testdata/a/a1.in", tests.RtRepo1+"/data/a10.in", "--build-name="+tests.RtBuildName2, "--build-number="+buildNumberA)
  2833  	artifactoryCli.Exec("upload", "testdata/a/a1.in", tests.RtRepo1+"/data/a11.in", "--build-name="+tests.RtBuildName1, "--build-number="+buildNumberB)
  2834  	artifactoryCli.Exec("upload", "testdata/a/a1.in", tests.RtRepo1+"/data/a12.in", "--build-name="+tests.RtBuildName1, "--build-number="+buildNumberC)
  2835  
  2836  	// Publish buildInfo
  2837  	artifactoryCli.Exec("build-publish", tests.RtBuildName2, buildNumberA)
  2838  	artifactoryCli.Exec("build-publish", tests.RtBuildName1, buildNumberB)
  2839  	artifactoryCli.Exec("build-publish", tests.RtBuildName1, buildNumberC)
  2840  
  2841  	// Download by build number
  2842  	artifactoryCli.Exec("download", "--spec="+specFile)
  2843  
  2844  	paths, _ := fileutils.ListFilesRecursiveWalkIntoDirSymlink(tests.Out, false)
  2845  	err = tests.ValidateListsIdentical(tests.GetBuildDownloadByShaAndBuild(), paths)
  2846  	assert.NoError(t, err)
  2847  
  2848  	// Cleanup
  2849  	inttestutils.DeleteBuild(serverDetails.ArtifactoryUrl, tests.RtBuildName1, artHttpDetails)
  2850  	inttestutils.DeleteBuild(serverDetails.ArtifactoryUrl, tests.RtBuildName2, artHttpDetails)
  2851  	cleanArtifactoryTest()
  2852  }
  2853  
  2854  // Upload a file to 2 different builds.
  2855  // Verify that we don't download files with same sha and build name and different build number.
  2856  func TestArtifactoryDownloadByShaAndBuildName(t *testing.T) {
  2857  	initArtifactoryTest(t)
  2858  	buildNumberA, buildNumberB, buildNumberC := "10", "11", "12"
  2859  	inttestutils.DeleteBuild(serverDetails.ArtifactoryUrl, tests.RtBuildName1, artHttpDetails)
  2860  	inttestutils.DeleteBuild(serverDetails.ArtifactoryUrl, tests.RtBuildName2, artHttpDetails)
  2861  	specFile, err := tests.CreateSpec(tests.BuildDownloadSpecNoBuildNumber)
  2862  	assert.NoError(t, err)
  2863  
  2864  	// Upload 3 similar files to 2 different builds
  2865  	artifactoryCli.Exec("upload", "testdata/a/a1.in", tests.RtRepo1+"/data/a10.in", "--build-name="+tests.RtBuildName2, "--build-number="+buildNumberA)
  2866  	artifactoryCli.Exec("upload", "testdata/a/a1.in", tests.RtRepo1+"/data/a11.in", "--build-name="+tests.RtBuildName2, "--build-number="+buildNumberB)
  2867  	artifactoryCli.Exec("upload", "testdata/a/a1.in", tests.RtRepo1+"/data/a12.in", "--build-name="+tests.RtBuildName1, "--build-number="+buildNumberC)
  2868  
  2869  	// Publish buildInfo
  2870  	artifactoryCli.Exec("build-publish", tests.RtBuildName1, buildNumberC)
  2871  	artifactoryCli.Exec("build-publish", tests.RtBuildName2, buildNumberA)
  2872  	artifactoryCli.Exec("build-publish", tests.RtBuildName2, buildNumberB)
  2873  
  2874  	// Download by build number
  2875  	artifactoryCli.Exec("download", "--spec="+specFile)
  2876  
  2877  	paths, _ := fileutils.ListFilesRecursiveWalkIntoDirSymlink(tests.Out, false)
  2878  	err = tests.ValidateListsIdentical(tests.GetBuildDownloadByShaAndBuildName(), paths)
  2879  	assert.NoError(t, err)
  2880  
  2881  	// Cleanup
  2882  	inttestutils.DeleteBuild(serverDetails.ArtifactoryUrl, tests.RtBuildName1, artHttpDetails)
  2883  	inttestutils.DeleteBuild(serverDetails.ArtifactoryUrl, tests.RtBuildName2, artHttpDetails)
  2884  	cleanArtifactoryTest()
  2885  }
  2886  
  2887  func TestArtifactoryDownloadByBuildUsingSimpleDownload(t *testing.T) {
  2888  	initArtifactoryTest(t)
  2889  	buildNumberA, buildNumberB := "a", "b"
  2890  	inttestutils.DeleteBuild(serverDetails.ArtifactoryUrl, tests.RtBuildName1, artHttpDetails)
  2891  
  2892  	// Upload files with buildName and buildNumber
  2893  	specFileA, err := tests.CreateSpec(tests.SplitUploadSpecA)
  2894  	assert.NoError(t, err)
  2895  	specFileB, err := tests.CreateSpec(tests.SplitUploadSpecB)
  2896  	assert.NoError(t, err)
  2897  	assert.NoError(t, artifactoryCli.Exec("upload", "--spec="+specFileA, "--build-name="+tests.RtBuildName1, "--build-number="+buildNumberA))
  2898  	assert.NoError(t, artifactoryCli.Exec("upload", "--spec="+specFileB, "--build-name="+tests.RtBuildName1, "--build-number="+buildNumberB))
  2899  
  2900  	// Publish buildInfo
  2901  	assert.NoError(t, artifactoryCli.Exec("build-publish", tests.RtBuildName1, buildNumberA))
  2902  	assert.NoError(t, artifactoryCli.Exec("build-publish", tests.RtBuildName1, buildNumberB))
  2903  
  2904  	// Download by build number, a1 should not be downloaded, b1 should
  2905  	assert.NoError(t, artifactoryCli.Exec("download", tests.RtRepo1+"/data/a1.in", filepath.Join(tests.Out, "download", "simple_by_build")+fileutils.GetFileSeparator(), "--build="+tests.RtBuildName1))
  2906  	assert.NoError(t, artifactoryCli.Exec("download", tests.RtRepo1+"/data/b1.in", filepath.Join(tests.Out, "download", "simple_by_build")+fileutils.GetFileSeparator(), "--build="+tests.RtBuildName1))
  2907  
  2908  	// Validate files are downloaded by build number
  2909  	paths, _ := fileutils.ListFilesRecursiveWalkIntoDirSymlink(tests.Out, false)
  2910  	err = tests.ValidateListsIdentical(tests.GetBuildSimpleDownload(), paths)
  2911  	assert.NoError(t, err)
  2912  
  2913  	// Cleanup
  2914  	inttestutils.DeleteBuild(serverDetails.ArtifactoryUrl, tests.RtBuildName1, artHttpDetails)
  2915  	cleanArtifactoryTest()
  2916  }
  2917  
  2918  func TestArtifactoryDownloadByBuildUsingSimpleDownloadWithProject(t *testing.T) {
  2919  	initArtifactoryTest(t)
  2920  	accessManager, err := utils.CreateAccessServiceManager(serverDetails, false)
  2921  	assert.NoError(t, err)
  2922  	timestamp := strconv.FormatInt(time.Now().Unix(), 10)
  2923  	projectKey := "jc" + timestamp[len(timestamp)-4:]
  2924  
  2925  	// Delete the project if already exists
  2926  	_ = accessManager.DeleteProject(projectKey)
  2927  
  2928  	// Create new project
  2929  	projectParams := accessServices.ProjectParams{
  2930  		ProjectDetails: accessServices.Project{
  2931  			ProjectKey:  projectKey,
  2932  			DisplayName: "JFrog CLI Tests " + projectKey,
  2933  			Description: "Project created by JFrog CLI tests suite",
  2934  		},
  2935  	}
  2936  	err = accessManager.CreateProject(projectParams)
  2937  	if err != nil {
  2938  		assert.NoError(t, err)
  2939  		return
  2940  	}
  2941  	defer func() {
  2942  		assert.NoError(t, accessManager.DeleteProject(projectKey))
  2943  	}()
  2944  
  2945  	// Assign the repository to the project
  2946  	assert.NoError(t, accessManager.AssignRepoToProject(tests.RtRepo1, projectKey, true))
  2947  	defer func() {
  2948  		assert.NoError(t, accessManager.UnassignRepoFromProject(tests.RtRepo1))
  2949  	}()
  2950  
  2951  	// Delete the build if exists
  2952  	inttestutils.DeleteBuild(serverDetails.ArtifactoryUrl, tests.RtBuildName1, artHttpDetails)
  2953  
  2954  	specFileB, err := tests.CreateSpec(tests.SplitUploadSpecB)
  2955  	assert.NoError(t, err)
  2956  	buildNumberA := "123"
  2957  
  2958  	// Upload files with buildName, buildNumber and project flags
  2959  	assert.NoError(t, artifactoryCli.Exec("upload", "--spec="+specFileB, "--build-name="+tests.RtBuildName1, "--build-number="+buildNumberA, "--project="+projectKey))
  2960  
  2961  	// Publish buildInfo with project flag
  2962  	assert.NoError(t, artifactoryCli.Exec("build-publish", tests.RtBuildName1, buildNumberA, "--project="+projectKey))
  2963  
  2964  	// Download by project, b1 should be downloaded
  2965  	assert.NoError(t, artifactoryCli.Exec("download", tests.RtRepo1+"/data/b1.in", filepath.Join(tests.Out, "download", "simple_by_build")+fileutils.GetFileSeparator(),
  2966  		"--build="+tests.RtBuildName1, "--project="+projectKey))
  2967  
  2968  	// Validate files are downloaded by build number
  2969  	paths, err := fileutils.ListFilesRecursiveWalkIntoDirSymlink(tests.Out, false)
  2970  	assert.NoError(t, err)
  2971  	err = tests.ValidateListsIdentical(tests.GetBuildSimpleDownload(), paths)
  2972  	assert.NoError(t, err)
  2973  
  2974  	// Cleanup
  2975  	inttestutils.DeleteBuild(serverDetails.ArtifactoryUrl, tests.RtBuildName1, artHttpDetails)
  2976  	cleanArtifactoryTest()
  2977  }
  2978  
  2979  func TestArtifactoryDownloadByBuildNoPatternUsingSimpleDownload(t *testing.T) {
  2980  	initArtifactoryTest(t)
  2981  	buildNumberA, buildNumberB := "a", "b"
  2982  	inttestutils.DeleteBuild(serverDetails.ArtifactoryUrl, tests.RtBuildName1, artHttpDetails)
  2983  
  2984  	// Upload files with buildName and buildNumber
  2985  	specFileA, err := tests.CreateSpec(tests.SplitUploadSpecA)
  2986  	assert.NoError(t, err)
  2987  	specFileB, err := tests.CreateSpec(tests.SplitUploadSpecB)
  2988  	assert.NoError(t, err)
  2989  
  2990  	assert.NoError(t, artifactoryCli.Exec("upload", "--spec="+specFileA, "--build-name="+tests.RtBuildName1, "--build-number="+buildNumberA))
  2991  	assert.NoError(t, artifactoryCli.Exec("upload", "--spec="+specFileB, "--build-name="+tests.RtBuildName1, "--build-number="+buildNumberB))
  2992  
  2993  	// Publish buildInfo
  2994  	assert.NoError(t, artifactoryCli.Exec("build-publish", tests.RtBuildName1, buildNumberA))
  2995  	assert.NoError(t, artifactoryCli.Exec("build-publish", tests.RtBuildName1, buildNumberB))
  2996  
  2997  	// Download by build number, a1 should not be downloaded, b1 should
  2998  	assert.NoError(t, artifactoryCli.Exec("download", "*", filepath.Join(tests.Out, "download", "simple_by_build")+fileutils.GetFileSeparator(), "--build="+tests.RtBuildName1+"/"+buildNumberA))
  2999  
  3000  	// Validate files are downloaded by build number
  3001  	paths, _ := fileutils.ListFilesRecursiveWalkIntoDirSymlink(tests.Out, false)
  3002  	err = tests.ValidateListsIdentical(tests.GetBuildSimpleDownloadNoPattern(), paths)
  3003  	assert.NoError(t, err)
  3004  
  3005  	// Cleanup
  3006  	inttestutils.DeleteBuild(serverDetails.ArtifactoryUrl, tests.RtBuildName1, artHttpDetails)
  3007  	cleanArtifactoryTest()
  3008  }
  3009  
  3010  func TestArtifactoryDownloadByArchiveEntriesCli(t *testing.T) {
  3011  	initArtifactoryTest(t)
  3012  	uploadSpecFile, err := tests.CreateSpec(tests.ArchiveEntriesUpload)
  3013  	assert.NoError(t, err)
  3014  
  3015  	// Upload archives
  3016  	artifactoryCli.Exec("upload", "--spec="+uploadSpecFile)
  3017  
  3018  	// Create executor for running with retries
  3019  	retryExecutor := createRetryExecutorForArchiveEntries(tests.GetBuildArchiveEntriesDownloadCli(),
  3020  		[]string{"dl", tests.RtRepo1, "out/", "--archive-entries=(*)c1.in", "--flat=true"})
  3021  
  3022  	// Perform download by archive-entries only the archives containing c1.in, and validate results
  3023  	assert.NoError(t, retryExecutor.Execute())
  3024  
  3025  	// Cleanup
  3026  	cleanArtifactoryTest()
  3027  }
  3028  
  3029  func TestArtifactoryDownloadByArchiveEntriesSpecificPathCli(t *testing.T) {
  3030  	initArtifactoryTest(t)
  3031  	uploadSpecFile, err := tests.CreateSpec(tests.ArchiveEntriesUpload)
  3032  	assert.NoError(t, err)
  3033  
  3034  	// Upload archives
  3035  	artifactoryCli.Exec("upload", "--spec="+uploadSpecFile)
  3036  
  3037  	// Create executor for running with retries
  3038  	retryExecutor := createRetryExecutorForArchiveEntries(tests.GetBuildArchiveEntriesSpecificPathDownload(),
  3039  		[]string{"dl", tests.RtRepo1, "out/", "--archive-entries=b/c/c1.in", "--flat=true"})
  3040  
  3041  	// Perform download by archive-entries only the archives containing c1.in, and validate results
  3042  	assert.NoError(t, retryExecutor.Execute())
  3043  
  3044  	// Cleanup
  3045  	cleanArtifactoryTest()
  3046  }
  3047  
  3048  func TestArtifactoryDownloadByArchiveEntriesSpec(t *testing.T) {
  3049  	initArtifactoryTest(t)
  3050  	uploadSpecFile, err := tests.CreateSpec(tests.ArchiveEntriesUpload)
  3051  	assert.NoError(t, err)
  3052  	downloadSpecFile, err := tests.CreateSpec(tests.ArchiveEntriesDownload)
  3053  	assert.NoError(t, err)
  3054  
  3055  	// Upload archives
  3056  	artifactoryCli.Exec("upload", "--spec="+uploadSpecFile)
  3057  
  3058  	// Create executor for running with retries
  3059  	retryExecutor := createRetryExecutorForArchiveEntries(tests.GetBuildArchiveEntriesDownloadSpec(),
  3060  		[]string{"dl", "--spec=" + downloadSpecFile})
  3061  
  3062  	// Perform download by archive-entries only the archives containing d1.in, and validate results
  3063  	assert.NoError(t, retryExecutor.Execute())
  3064  
  3065  	// Cleanup
  3066  	cleanArtifactoryTest()
  3067  }
  3068  
  3069  func createRetryExecutorForArchiveEntries(expected []string, args []string) *clientutils.RetryExecutor {
  3070  	return &clientutils.RetryExecutor{
  3071  		MaxRetries:      120,
  3072  		RetriesInterval: 1,
  3073  		ErrorMessage:    "Waiting for Artifactory to index archives...",
  3074  		ExecutionHandler: func() (bool, error) {
  3075  			err := validateDownloadByArchiveEntries(expected, args)
  3076  			if err != nil {
  3077  				return true, err
  3078  			}
  3079  
  3080  			return false, nil
  3081  		},
  3082  	}
  3083  }
  3084  
  3085  func validateDownloadByArchiveEntries(expected []string, args []string) error {
  3086  	// Execute the requested cli command
  3087  	artifactoryCli.Exec(args...)
  3088  
  3089  	// Validate files are downloaded as expected
  3090  	paths, _ := fileutils.ListFilesRecursiveWalkIntoDirSymlink(tests.Out, false)
  3091  	return tests.ValidateListsIdentical(expected, paths)
  3092  }
  3093  
  3094  func TestArtifactoryDownloadExcludeByCli(t *testing.T) {
  3095  	initArtifactoryTest(t)
  3096  
  3097  	// Upload files
  3098  	specFileA, err := tests.CreateSpec(tests.SplitUploadSpecA)
  3099  	assert.NoError(t, err)
  3100  	specFileB, err := tests.CreateSpec(tests.SplitUploadSpecB)
  3101  	assert.NoError(t, err)
  3102  	artifactoryCli.Exec("upload", "--spec="+specFileA, "--recursive=true")
  3103  	artifactoryCli.Exec("upload", "--spec="+specFileB, "--recursive=true")
  3104  
  3105  	// Download by pattern
  3106  	artifactoryCli.Exec("download", tests.RtRepo1, "out/download/aql_by_artifacts/", "--exclude-patterns=*/a1.in;*a2.*;data/c2.in")
  3107  
  3108  	// Validate files are excluded
  3109  	paths, _ := fileutils.ListFilesRecursiveWalkIntoDirSymlink(tests.Out, false)
  3110  	err = tests.ValidateListsIdentical(tests.GetBuildExcludeDownload(), paths)
  3111  	assert.NoError(t, err)
  3112  
  3113  	// Cleanup
  3114  	cleanArtifactoryTest()
  3115  }
  3116  
  3117  func TestArtifactoryDownloadExclusionsByCli(t *testing.T) {
  3118  	initArtifactoryTest(t)
  3119  
  3120  	// Upload files
  3121  	specFileA, err := tests.CreateSpec(tests.SplitUploadSpecA)
  3122  	assert.NoError(t, err)
  3123  	specFileB, err := tests.CreateSpec(tests.SplitUploadSpecB)
  3124  	assert.NoError(t, err)
  3125  	artifactoryCli.Exec("upload", "--spec="+specFileA, "--recursive=true")
  3126  	artifactoryCli.Exec("upload", "--spec="+specFileB, "--recursive=true")
  3127  
  3128  	// Download by pattern
  3129  	artifactoryCli.Exec("download", tests.RtRepo1, "out/download/aql_by_artifacts/", "--exclusions=*/*/a1.in;*/*a2.*;*/data/c2.in")
  3130  
  3131  	// Validate files are excluded
  3132  	paths, _ := fileutils.ListFilesRecursiveWalkIntoDirSymlink(tests.Out, false)
  3133  	err = tests.ValidateListsIdentical(tests.GetBuildExcludeDownload(), paths)
  3134  	assert.NoError(t, err)
  3135  
  3136  	// Cleanup
  3137  	cleanArtifactoryTest()
  3138  }
  3139  
  3140  func TestArtifactoryDownloadExcludeBySpec(t *testing.T) {
  3141  	initArtifactoryTest(t)
  3142  	specFile, err := tests.CreateSpec(tests.DownloadSpecExclude)
  3143  	assert.NoError(t, err)
  3144  
  3145  	// Upload files
  3146  	specFileA, err := tests.CreateSpec(tests.SplitUploadSpecA)
  3147  	assert.NoError(t, err)
  3148  	specFileB, err := tests.CreateSpec(tests.SplitUploadSpecB)
  3149  	assert.NoError(t, err)
  3150  	artifactoryCli.Exec("upload", "--spec="+specFileA, "--recursive=true", "--flat=false")
  3151  	artifactoryCli.Exec("upload", "--spec="+specFileB, "--recursive=true", "--flat=false")
  3152  
  3153  	// Download by spec
  3154  	artifactoryCli.Exec("download", "--spec="+specFile)
  3155  
  3156  	// Validate files are excluded
  3157  	paths, _ := fileutils.ListFilesRecursiveWalkIntoDirSymlink(tests.Out, false)
  3158  	err = tests.ValidateListsIdentical(tests.GetBuildExcludeDownloadBySpec(), paths)
  3159  	assert.NoError(t, err)
  3160  
  3161  	// Cleanup
  3162  	cleanArtifactoryTest()
  3163  }
  3164  
  3165  func TestArtifactoryDownloadExclusionsBySpec(t *testing.T) {
  3166  	initArtifactoryTest(t)
  3167  	specFile, err := tests.CreateSpec(tests.DownloadSpecExclusions)
  3168  	assert.NoError(t, err)
  3169  
  3170  	// Upload files
  3171  	specFileA, err := tests.CreateSpec(tests.SplitUploadSpecA)
  3172  	assert.NoError(t, err)
  3173  	specFileB, err := tests.CreateSpec(tests.SplitUploadSpecB)
  3174  	assert.NoError(t, err)
  3175  	artifactoryCli.Exec("upload", "--spec="+specFileA, "--recursive=true", "--flat=false")
  3176  	artifactoryCli.Exec("upload", "--spec="+specFileB, "--recursive=true", "--flat=false")
  3177  
  3178  	// Download by spec
  3179  	artifactoryCli.Exec("download", "--spec="+specFile)
  3180  
  3181  	// Validate files are excluded
  3182  	paths, _ := fileutils.ListFilesRecursiveWalkIntoDirSymlink(tests.Out, false)
  3183  	err = tests.ValidateListsIdentical(tests.GetBuildExcludeDownloadBySpec(), paths)
  3184  	assert.NoError(t, err)
  3185  
  3186  	// Cleanup
  3187  	cleanArtifactoryTest()
  3188  }
  3189  
  3190  func TestArtifactoryDownloadExcludeBySpecOverride(t *testing.T) {
  3191  	initArtifactoryTest(t)
  3192  
  3193  	// Upload files with buildName and buildNumber
  3194  	specFileA, err := tests.CreateSpec(tests.SplitUploadSpecA)
  3195  	assert.NoError(t, err)
  3196  	specFileB, err := tests.CreateSpec(tests.SplitUploadSpecB)
  3197  	assert.NoError(t, err)
  3198  	artifactoryCli.Exec("upload", "--spec="+specFileA, "--recursive=true", "--flat=false")
  3199  	artifactoryCli.Exec("upload", "--spec="+specFileB, "--recursive=true", "--flat=false")
  3200  
  3201  	// Download by spec
  3202  	specFile, err := tests.CreateSpec(tests.DownloadSpecExclude)
  3203  	assert.NoError(t, err)
  3204  	artifactoryCli.Exec("download", "--spec="+specFile, "--exclude-patterns=*a1.in;*a2.in;*c2.in")
  3205  
  3206  	// Validate files are downloaded by build number
  3207  	paths, _ := fileutils.ListFilesRecursiveWalkIntoDirSymlink(tests.Out, false)
  3208  	err = tests.ValidateListsIdentical(tests.GetBuildExcludeDownload(), paths)
  3209  	assert.NoError(t, err)
  3210  
  3211  	// Cleanup
  3212  	cleanArtifactoryTest()
  3213  }
  3214  
  3215  func TestArtifactoryDownloadExclusionsBySpecOverride(t *testing.T) {
  3216  	initArtifactoryTest(t)
  3217  
  3218  	// Upload files with buildName and buildNumber
  3219  	specFileA, err := tests.CreateSpec(tests.SplitUploadSpecA)
  3220  	assert.NoError(t, err)
  3221  	specFileB, err := tests.CreateSpec(tests.SplitUploadSpecB)
  3222  	assert.NoError(t, err)
  3223  	artifactoryCli.Exec("upload", "--spec="+specFileA, "--recursive=true", "--flat=false")
  3224  	artifactoryCli.Exec("upload", "--spec="+specFileB, "--recursive=true", "--flat=false")
  3225  
  3226  	// Download by spec
  3227  	specFile, err := tests.CreateSpec(tests.DownloadSpecExclusions)
  3228  	assert.NoError(t, err)
  3229  	artifactoryCli.Exec("download", "--spec="+specFile, "--exclusions=*a1.in;*a2.in;*c2.in")
  3230  
  3231  	// Validate files are downloaded by build number
  3232  	paths, _ := fileutils.ListFilesRecursiveWalkIntoDirSymlink(tests.Out, false)
  3233  	err = tests.ValidateListsIdentical(tests.GetBuildExcludeDownload(), paths)
  3234  	assert.NoError(t, err)
  3235  
  3236  	// Cleanup
  3237  	cleanArtifactoryTest()
  3238  }
  3239  
  3240  // Sort and limit changes the way properties are used so this should be tested with symlinks and search by build
  3241  
  3242  // Upload symlink by full path to Artifactory and the link content checksum
  3243  // Download the symlink which was uploaded with limit param.
  3244  // validate the symlink content checksum.
  3245  func TestArtifactoryLimitWithSymlink(t *testing.T) {
  3246  	if coreutils.IsWindows() {
  3247  		t.Skip("Running on windows, skipping...")
  3248  	}
  3249  	initArtifactoryTest(t)
  3250  	localFile := filepath.Join(tests.GetTestResourcesPath()+"a", "a1.in")
  3251  	link := filepath.Join(tests.GetTestResourcesPath()+"a", "link")
  3252  	err := os.Symlink(localFile, link)
  3253  	assert.NoError(t, err)
  3254  	artifactoryCli.Exec("u", link, tests.RtRepo1, "--symlinks=true")
  3255  	err = os.Remove(link)
  3256  	assert.NoError(t, err)
  3257  	artifactoryCli.Exec("dl", tests.RtRepo1+"/link", tests.GetTestResourcesPath()+"a/", "--validate-symlinks=true", "--limit=1")
  3258  	validateSortLimitWithSymLink(link, localFile, t)
  3259  	os.Remove(link)
  3260  	cleanArtifactoryTest()
  3261  }
  3262  
  3263  // Upload symlink by full path to Artifactory and the link content checksum
  3264  // Download the symlink which was uploaded with limit param.
  3265  // validate the symlink content checksum.
  3266  func TestArtifactorySortWithSymlink(t *testing.T) {
  3267  	if coreutils.IsWindows() {
  3268  		t.Skip("Running on windows, skipping...")
  3269  	}
  3270  	initArtifactoryTest(t)
  3271  	localFile := filepath.Join(tests.GetTestResourcesPath()+"a", "a1.in")
  3272  	link := filepath.Join(tests.GetTestResourcesPath()+"a", "link")
  3273  	err := os.Symlink(localFile, link)
  3274  	assert.NoError(t, err)
  3275  	artifactoryCli.Exec("u", link, tests.RtRepo1, "--symlinks=true")
  3276  	err = os.Remove(link)
  3277  	assert.NoError(t, err)
  3278  	artifactoryCli.Exec("dl", tests.RtRepo1+"/link", tests.GetTestResourcesPath()+"a/", "--validate-symlinks=true", "--sort-by=created")
  3279  	validateSortLimitWithSymLink(link, localFile, t)
  3280  	os.Remove(link)
  3281  	cleanArtifactoryTest()
  3282  }
  3283  
  3284  func validateSortLimitWithSymLink(localLinkPath, localFilePath string, t *testing.T) {
  3285  	exists := fileutils.IsPathSymlink(localLinkPath)
  3286  	assert.True(t, exists, "failed to download symlinks from artifactory with Sort/Limit flag")
  3287  	symlinks, err := filepath.EvalSymlinks(localLinkPath)
  3288  	assert.NoError(t, err, "can't eval symlinks with Sort/Limit flag")
  3289  	assert.Equal(t, localFilePath, symlinks, "Symlinks wasn't created as expected with Sort/Limit flag")
  3290  }
  3291  
  3292  // Upload a file to 2 different builds.
  3293  // Verify that we don't download files with same sha and build name and different build number when sort is configured.
  3294  func TestArtifactoryDownloadByShaAndBuildNameWithSort(t *testing.T) {
  3295  	initArtifactoryTest(t)
  3296  	buildNumberA, buildNumberB, buildNumberC := "10", "11", "12"
  3297  	inttestutils.DeleteBuild(serverDetails.ArtifactoryUrl, tests.RtBuildName1, artHttpDetails)
  3298  	inttestutils.DeleteBuild(serverDetails.ArtifactoryUrl, tests.RtBuildName2, artHttpDetails)
  3299  	specFile, err := tests.CreateSpec(tests.BuildDownloadSpecNoBuildNumberWithSort)
  3300  	assert.NoError(t, err)
  3301  	// Upload 3 similar files to 2 different builds
  3302  	artifactoryCli.Exec("upload", "testdata/a/a1.in", tests.RtRepo1+"/data/a10.in", "--build-name="+tests.RtBuildName2, "--build-number="+buildNumberA)
  3303  	artifactoryCli.Exec("upload", "testdata/a/a1.in", tests.RtRepo1+"/data/a11.in", "--build-name="+tests.RtBuildName2, "--build-number="+buildNumberB)
  3304  	artifactoryCli.Exec("upload", "testdata/a/a1.in", tests.RtRepo1+"/data/a12.in", "--build-name="+tests.RtBuildName1, "--build-number="+buildNumberC)
  3305  
  3306  	// Publish buildInfo
  3307  	artifactoryCli.Exec("build-publish", tests.RtBuildName1, buildNumberC)
  3308  	artifactoryCli.Exec("build-publish", tests.RtBuildName2, buildNumberA)
  3309  	artifactoryCli.Exec("build-publish", tests.RtBuildName2, buildNumberB)
  3310  
  3311  	// Download by build number
  3312  	artifactoryCli.Exec("download", "--sort-by=created", "--spec="+specFile)
  3313  
  3314  	paths, _ := fileutils.ListFilesRecursiveWalkIntoDirSymlink(filepath.Join(tests.Out, "download", "sort_limit_by_build"), false)
  3315  	err = tests.ValidateListsIdentical(tests.GetBuildDownloadByShaAndBuildNameWithSort(), paths)
  3316  	assert.NoError(t, err)
  3317  
  3318  	// Cleanup
  3319  	inttestutils.DeleteBuild(serverDetails.ArtifactoryUrl, tests.RtBuildName1, artHttpDetails)
  3320  	inttestutils.DeleteBuild(serverDetails.ArtifactoryUrl, tests.RtBuildName2, artHttpDetails)
  3321  	cleanArtifactoryTest()
  3322  }
  3323  
  3324  func TestArtifactoryCopyByBuildUsingSpec(t *testing.T) {
  3325  	initArtifactoryTest(t)
  3326  	buildNumberA, buildNumberB := "10", "11"
  3327  	inttestutils.DeleteBuild(serverDetails.ArtifactoryUrl, tests.RtBuildName1, artHttpDetails)
  3328  	specFile, err := tests.CreateSpec(tests.CopyByBuildSpec)
  3329  	assert.NoError(t, err)
  3330  	// Upload files with buildName and buildNumber: a* uploaded with build number "10", b* uploaded with build number "11"
  3331  	specFileA, err := tests.CreateSpec(tests.SplitUploadSpecA)
  3332  	assert.NoError(t, err)
  3333  	specFileB, err := tests.CreateSpec(tests.SplitUploadSpecB)
  3334  	assert.NoError(t, err)
  3335  	artifactoryCli.Exec("upload", "--spec="+specFileA, "--build-name="+tests.RtBuildName1, "--build-number="+buildNumberA)
  3336  	artifactoryCli.Exec("upload", "--spec="+specFileB, "--build-name="+tests.RtBuildName1, "--build-number="+buildNumberB)
  3337  
  3338  	// Publish buildInfo
  3339  	artifactoryCli.Exec("build-publish", tests.RtBuildName1, buildNumberA)
  3340  	artifactoryCli.Exec("build-publish", tests.RtBuildName1, buildNumberB)
  3341  
  3342  	// Copy by build name "cli-test-build" and build number "10" from spec, a* should be copied
  3343  	artifactoryCli.Exec("copy", "--spec="+specFile)
  3344  
  3345  	// Validate files are Copied by build number
  3346  	cpMvDlByBuildAssertSpec, err := tests.CreateSpec(tests.CpMvDlByBuildAssertSpec)
  3347  	assert.NoError(t, err)
  3348  	verifyExistInArtifactory(tests.GetBuildCopyExpected(), cpMvDlByBuildAssertSpec, t)
  3349  
  3350  	// Cleanup
  3351  	inttestutils.DeleteBuild(serverDetails.ArtifactoryUrl, tests.RtBuildName1, artHttpDetails)
  3352  	cleanArtifactoryTest()
  3353  }
  3354  
  3355  func TestArtifactoryCopyByBuildPatternAllUsingSpec(t *testing.T) {
  3356  	initArtifactoryTest(t)
  3357  	buildNumberA, buildNumberB := "10", "11"
  3358  	inttestutils.DeleteBuild(serverDetails.ArtifactoryUrl, tests.RtBuildName1, artHttpDetails)
  3359  	specFile, err := tests.CreateSpec(tests.CopyByBuildPatternAllSpec)
  3360  	assert.NoError(t, err)
  3361  	// Upload files with buildName and buildNumber: a* uploaded with build number "10", b* uploaded with build number "11"
  3362  	specFileA, err := tests.CreateSpec(tests.SplitUploadSpecA)
  3363  	assert.NoError(t, err)
  3364  	specFileB, err := tests.CreateSpec(tests.SplitUploadSpecB)
  3365  	assert.NoError(t, err)
  3366  	artifactoryCli.Exec("upload", "--spec="+specFileA, "--build-name="+tests.RtBuildName1, "--build-number="+buildNumberA)
  3367  	artifactoryCli.Exec("upload", "--spec="+specFileB, "--build-name="+tests.RtBuildName1, "--build-number="+buildNumberB)
  3368  
  3369  	// Publish buildInfo
  3370  	artifactoryCli.Exec("build-publish", tests.RtBuildName1, buildNumberA)
  3371  	artifactoryCli.Exec("build-publish", tests.RtBuildName1, buildNumberB)
  3372  
  3373  	// Copy by build name "cli-test-build" and build number "10" from spec, a* should be copied
  3374  	artifactoryCli.Exec("copy", "--spec="+specFile)
  3375  
  3376  	// Validate files are Copied by build number
  3377  	cpMvDlByBuildAssertSpec, err := tests.CreateSpec(tests.CpMvDlByBuildAssertSpec)
  3378  	assert.NoError(t, err)
  3379  	verifyExistInArtifactory(tests.GetBuildCopyExpected(), cpMvDlByBuildAssertSpec, t)
  3380  
  3381  	// Cleanup
  3382  	inttestutils.DeleteBuild(serverDetails.ArtifactoryUrl, tests.RtBuildName1, artHttpDetails)
  3383  	cleanArtifactoryTest()
  3384  }
  3385  
  3386  func TestArtifactorySortAndLimit(t *testing.T) {
  3387  	initArtifactoryTest(t)
  3388  
  3389  	// Upload all testdata/a/ files
  3390  	artifactoryCli.Exec("upload", "testdata/a/(*)", tests.RtRepo1+"/data/{1}")
  3391  
  3392  	// Download 1 sorted by name asc
  3393  	artifactoryCli.Exec("download", tests.RtRepo1+"/data/", "out/download/sort_limit/", "--sort-by=name", "--limit=1")
  3394  
  3395  	// Download 3 sorted by depth desc
  3396  	artifactoryCli.Exec("download", tests.RtRepo1+"/data/", "out/download/sort_limit/", "--sort-by=depth", "--limit=3", "--sort-order=desc")
  3397  
  3398  	paths, _ := fileutils.ListFilesRecursiveWalkIntoDirSymlink(tests.Out, false)
  3399  	err := tests.ValidateListsIdentical(tests.GetSortAndLimit(), paths)
  3400  	assert.NoError(t, err)
  3401  
  3402  	// Cleanup
  3403  	cleanArtifactoryTest()
  3404  }
  3405  
  3406  func TestArtifactorySortByCreated(t *testing.T) {
  3407  	initArtifactoryTest(t)
  3408  
  3409  	// Upload files separately so we can sort by created.
  3410  	artifactoryCli.Exec("upload", "testdata/created/or", tests.RtRepo1, `--target-props=k1=v1`)
  3411  	artifactoryCli.Exec("upload", "testdata/created/o", tests.RtRepo1)
  3412  	artifactoryCli.Exec("upload", "testdata/created/org", tests.RtRepo1)
  3413  
  3414  	// Prepare search command
  3415  	searchCmd := generic.NewSearchCommand()
  3416  	searchCmd.SetServerDetails(serverDetails)
  3417  	searchSpecBuilder := spec.NewBuilder().Pattern(tests.RtRepo1).SortBy([]string{"created"}).SortOrder("asc").Limit(3)
  3418  	searchCmd.SetSpec(searchSpecBuilder.BuildSpec())
  3419  	reader, err := searchCmd.Search()
  3420  	assert.NoError(t, err)
  3421  	reader, err = utils.SearchResultNoDate(reader)
  3422  	assert.NoError(t, err)
  3423  
  3424  	var resultItems []utils.SearchResult
  3425  	for resultItem := new(utils.SearchResult); reader.NextRecord(resultItem) == nil; resultItem = new(utils.SearchResult) {
  3426  		resultItems = append(resultItems, *resultItem)
  3427  
  3428  	}
  3429  	assert.Len(t, resultItems, 3)
  3430  	// Verify the sort by checking if the item results are ordereds by asc.
  3431  	assert.True(t, reflect.DeepEqual(resultItems[0], tests.GetFirstSearchResultSortedByAsc()))
  3432  	assert.True(t, reflect.DeepEqual(resultItems[1], tests.GetSecondSearchResultSortedByAsc()))
  3433  	assert.True(t, reflect.DeepEqual(resultItems[2], tests.GetThirdSearchResultSortedByAsc()))
  3434  
  3435  	assert.NoError(t, reader.Close())
  3436  	searchCmd.SetSpec(searchSpecBuilder.SortOrder("desc").BuildSpec())
  3437  	reader, err = searchCmd.Search()
  3438  	assert.NoError(t, err)
  3439  	reader, err = utils.SearchResultNoDate(reader)
  3440  	assert.NoError(t, err)
  3441  	resultItems = nil
  3442  	for resultItem := new(utils.SearchResult); reader.NextRecord(resultItem) == nil; resultItem = new(utils.SearchResult) {
  3443  		resultItems = append(resultItems, *resultItem)
  3444  	}
  3445  	assert.Len(t, resultItems, 3)
  3446  	// Verify the sort by checking if the item results are ordered by desc.
  3447  	assert.True(t, reflect.DeepEqual(resultItems[2], tests.GetFirstSearchResultSortedByAsc()))
  3448  	assert.True(t, reflect.DeepEqual(resultItems[1], tests.GetSecondSearchResultSortedByAsc()))
  3449  	assert.True(t, reflect.DeepEqual(resultItems[0], tests.GetThirdSearchResultSortedByAsc()))
  3450  	assert.NoError(t, reader.Close())
  3451  
  3452  	// Cleanup
  3453  	cleanArtifactoryTest()
  3454  }
  3455  func TestArtifactoryOffset(t *testing.T) {
  3456  	initArtifactoryTest(t)
  3457  
  3458  	// Upload all testdata/a/ files
  3459  	artifactoryCli.Exec("upload", "testdata/a/*", path.Join(tests.RtRepo1, "offset_test")+"/", "--flat=true")
  3460  
  3461  	// Downloading files one by one, to check that the offset is working as expected.
  3462  	// Download only the first file, expecting to download a1.in
  3463  	artifactoryCli.Exec("download", tests.RtRepo1+"/offset_test/", tests.Out+"/", "--flat=true", "--sort-by=name", "--limit=1", "--offset=0")
  3464  	paths, _ := fileutils.ListFilesRecursiveWalkIntoDirSymlink(tests.Out, false)
  3465  	tests.VerifyExistLocally([]string{filepath.Join(tests.Out, "a1.in")}, paths, t)
  3466  
  3467  	// Download the second file, expecting to download a2.in
  3468  	artifactoryCli.Exec("download", tests.RtRepo1+"/offset_test/", tests.Out+"/", "--flat=true", "--sort-by=name", "--limit=1", "--offset=1")
  3469  	paths, _ = fileutils.ListFilesRecursiveWalkIntoDirSymlink(tests.Out, false)
  3470  	tests.VerifyExistLocally([]string{filepath.Join(tests.Out, "a2.in")}, paths, t)
  3471  
  3472  	// Download the third file, expecting to download a3.in
  3473  	artifactoryCli.Exec("download", tests.RtRepo1+"/offset_test/", tests.Out+"/", "--flat=true", "--sort-by=name", "--limit=1", "--offset=2")
  3474  	paths, _ = fileutils.ListFilesRecursiveWalkIntoDirSymlink(tests.Out, false)
  3475  	tests.VerifyExistLocally([]string{filepath.Join(tests.Out, "a3.in")}, paths, t)
  3476  
  3477  	// Cleanup
  3478  	cleanArtifactoryTest()
  3479  }
  3480  
  3481  func TestArtifactoryCopyByBuildOverridingByInlineFlag(t *testing.T) {
  3482  	initArtifactoryTest(t)
  3483  	buildNumberA, buildNumberB := "10", "11"
  3484  	inttestutils.DeleteBuild(serverDetails.ArtifactoryUrl, tests.RtBuildName1, artHttpDetails)
  3485  	specFile, err := tests.CreateSpec(tests.CopyByBuildSpec)
  3486  	assert.NoError(t, err)
  3487  
  3488  	// Upload files with buildName and buildNumber: b* uploaded with build number "10", a* uploaded with build number "11"
  3489  	specFileA, err := tests.CreateSpec(tests.SplitUploadSpecA)
  3490  	assert.NoError(t, err)
  3491  	specFileB, err := tests.CreateSpec(tests.SplitUploadSpecB)
  3492  	assert.NoError(t, err)
  3493  	artifactoryCli.Exec("upload", "--spec="+specFileB, "--build-name="+tests.RtBuildName1, "--build-number="+buildNumberA)
  3494  	artifactoryCli.Exec("upload", "--spec="+specFileA, "--build-name="+tests.RtBuildName1, "--build-number="+buildNumberB)
  3495  
  3496  	// Publish buildInfo
  3497  	artifactoryCli.Exec("build-publish", tests.RtBuildName1, buildNumberA)
  3498  	artifactoryCli.Exec("build-publish", tests.RtBuildName1, buildNumberB)
  3499  
  3500  	// Copy by build number: using override of build by flag from inline (no number set so LATEST build should be copied), a* should be copied
  3501  	artifactoryCli.Exec("copy", "--build="+tests.RtBuildName1, "--spec="+specFile)
  3502  
  3503  	// Validate files are Copied by build number
  3504  	cpMvDlByBuildAssertSpec, err := tests.CreateSpec(tests.CpMvDlByBuildAssertSpec)
  3505  	assert.NoError(t, err)
  3506  
  3507  	verifyExistInArtifactory(tests.GetBuildCopyExpected(), cpMvDlByBuildAssertSpec, t)
  3508  
  3509  	// Cleanup
  3510  	inttestutils.DeleteBuild(serverDetails.ArtifactoryUrl, tests.RtBuildName1, artHttpDetails)
  3511  	cleanArtifactoryTest()
  3512  }
  3513  
  3514  func TestArtifactoryMoveByBuildUsingFlags(t *testing.T) {
  3515  	initArtifactoryTest(t)
  3516  	buildNumberA, buildNumberB := "10", "11"
  3517  	inttestutils.DeleteBuild(serverDetails.ArtifactoryUrl, tests.RtBuildName1, artHttpDetails)
  3518  	specFile, err := tests.CreateSpec(tests.CopyByBuildSpec)
  3519  	assert.NoError(t, err)
  3520  
  3521  	// Upload files with buildName and buildNumber
  3522  	specFileA, err := tests.CreateSpec(tests.SplitUploadSpecA)
  3523  	assert.NoError(t, err)
  3524  	specFileB, err := tests.CreateSpec(tests.SplitUploadSpecB)
  3525  	assert.NoError(t, err)
  3526  	artifactoryCli.Exec("upload", "--spec="+specFileB, "--build-name="+tests.RtBuildName1, "--build-number="+buildNumberA)
  3527  	artifactoryCli.Exec("upload", "--spec="+specFileA, "--build-name="+tests.RtBuildName1, "--build-number="+buildNumberB)
  3528  
  3529  	// Publish buildInfo
  3530  	artifactoryCli.Exec("build-publish", tests.RtBuildName1, buildNumberA)
  3531  	artifactoryCli.Exec("build-publish", tests.RtBuildName1, buildNumberB)
  3532  
  3533  	// Move by build name and number
  3534  	artifactoryCli.Exec("move", "--build="+tests.RtBuildName1+"/11", "--spec="+specFile)
  3535  
  3536  	// Validate files are moved by build number
  3537  	cpMvDlByBuildAssertSpec, err := tests.CreateSpec(tests.CpMvDlByBuildAssertSpec)
  3538  	assert.NoError(t, err)
  3539  
  3540  	verifyExistInArtifactory(tests.GetBuildMoveExpected(), cpMvDlByBuildAssertSpec, t)
  3541  
  3542  	// Cleanup
  3543  	inttestutils.DeleteBuild(serverDetails.ArtifactoryUrl, tests.RtBuildName1, artHttpDetails)
  3544  	cleanArtifactoryTest()
  3545  }
  3546  
  3547  func TestArtifactoryMoveNoSpec(t *testing.T) {
  3548  	testCopyMoveNoSpec("mv", tests.GetBuildBeforeMoveExpected(), tests.GetBuildMoveExpected(), t)
  3549  }
  3550  
  3551  func TestArtifactoryMoveExcludeByCli(t *testing.T) {
  3552  	initArtifactoryTest(t)
  3553  
  3554  	// Upload files
  3555  	specFileA, err := tests.CreateSpec(tests.SplitUploadSpecA)
  3556  	assert.NoError(t, err)
  3557  	specFileB, err := tests.CreateSpec(tests.SplitUploadSpecB)
  3558  	assert.NoError(t, err)
  3559  	artifactoryCli.Exec("upload", "--spec="+specFileA)
  3560  	artifactoryCli.Exec("upload", "--spec="+specFileB)
  3561  
  3562  	// Move by pattern
  3563  	artifactoryCli.Exec("move", tests.RtRepo1+"/data/", tests.RtRepo2+"/", "--exclude-patterns=*b*;*c*")
  3564  
  3565  	// Validate excluded files didn't move
  3566  	cpMvDlByBuildAssertSpec, err := tests.CreateSpec(tests.CpMvDlByBuildAssertSpec)
  3567  	assert.NoError(t, err)
  3568  
  3569  	verifyExistInArtifactory(tests.GetBuildMoveExpected(), cpMvDlByBuildAssertSpec, t)
  3570  
  3571  	// Cleanup
  3572  	cleanArtifactoryTest()
  3573  }
  3574  
  3575  func TestArtifactoryMoveExclusionsByCli(t *testing.T) {
  3576  	initArtifactoryTest(t)
  3577  
  3578  	// Upload files
  3579  	specFileA, err := tests.CreateSpec(tests.SplitUploadSpecA)
  3580  	assert.NoError(t, err)
  3581  	specFileB, err := tests.CreateSpec(tests.SplitUploadSpecB)
  3582  	assert.NoError(t, err)
  3583  	artifactoryCli.Exec("upload", "--spec="+specFileA)
  3584  	artifactoryCli.Exec("upload", "--spec="+specFileB)
  3585  
  3586  	// Move by pattern
  3587  	artifactoryCli.Exec("move", tests.RtRepo1+"/data/", tests.RtRepo2+"/", "--exclusions=*/*b*;*/*c*")
  3588  
  3589  	// Validate excluded files didn't move
  3590  	cpMvDlByBuildAssertSpec, err := tests.CreateSpec(tests.CpMvDlByBuildAssertSpec)
  3591  	assert.NoError(t, err)
  3592  
  3593  	verifyExistInArtifactory(tests.GetBuildMoveExpected(), cpMvDlByBuildAssertSpec, t)
  3594  
  3595  	// Cleanup
  3596  	cleanArtifactoryTest()
  3597  }
  3598  
  3599  func TestArtifactoryMoveExcludeBySpec(t *testing.T) {
  3600  	initArtifactoryTest(t)
  3601  	specFile, err := tests.CreateSpec(tests.MoveCopySpecExclude)
  3602  	assert.NoError(t, err)
  3603  
  3604  	// Upload files
  3605  	specFileA, err := tests.CreateSpec(tests.SplitUploadSpecA)
  3606  	assert.NoError(t, err)
  3607  	specFileB, err := tests.CreateSpec(tests.SplitUploadSpecB)
  3608  	assert.NoError(t, err)
  3609  	artifactoryCli.Exec("upload", "--spec="+specFileA)
  3610  	artifactoryCli.Exec("upload", "--spec="+specFileB)
  3611  
  3612  	// Move by spec
  3613  	artifactoryCli.Exec("move", "--spec="+specFile)
  3614  
  3615  	// Validate excluded files didn't move
  3616  	cpMvDlByBuildAssertSpec, err := tests.CreateSpec(tests.CpMvDlByBuildAssertSpec)
  3617  	assert.NoError(t, err)
  3618  
  3619  	verifyExistInArtifactory(tests.GetBuildMoveExpected(), cpMvDlByBuildAssertSpec, t)
  3620  
  3621  	// Cleanup
  3622  	cleanArtifactoryTest()
  3623  }
  3624  
  3625  func TestArtifactoryMoveExclusionsBySpec(t *testing.T) {
  3626  	initArtifactoryTest(t)
  3627  	specFile, err := tests.CreateSpec(tests.MoveCopySpecExclusions)
  3628  	assert.NoError(t, err)
  3629  
  3630  	// Upload files
  3631  	specFileA, err := tests.CreateSpec(tests.SplitUploadSpecA)
  3632  	assert.NoError(t, err)
  3633  	specFileB, err := tests.CreateSpec(tests.SplitUploadSpecB)
  3634  	assert.NoError(t, err)
  3635  	artifactoryCli.Exec("upload", "--spec="+specFileA)
  3636  	artifactoryCli.Exec("upload", "--spec="+specFileB)
  3637  
  3638  	// Move by spec
  3639  	artifactoryCli.Exec("move", "--spec="+specFile)
  3640  
  3641  	// Validate excluded files didn't move
  3642  	cpMvDlByBuildAssertSpec, err := tests.CreateSpec(tests.CpMvDlByBuildAssertSpec)
  3643  	assert.NoError(t, err)
  3644  
  3645  	verifyExistInArtifactory(tests.GetBuildMoveExpected(), cpMvDlByBuildAssertSpec, t)
  3646  
  3647  	// Cleanup
  3648  	cleanArtifactoryTest()
  3649  }
  3650  
  3651  func TestArtifactoryDeleteByLatestBuild(t *testing.T) {
  3652  	initArtifactoryTest(t)
  3653  	buildNumberA, buildNumberB := "10", "11"
  3654  	inttestutils.DeleteBuild(serverDetails.ArtifactoryUrl, tests.RtBuildName1, artHttpDetails)
  3655  	specFile, err := tests.CreateSpec(tests.CopyByBuildSpec)
  3656  	assert.NoError(t, err)
  3657  
  3658  	// Upload files with buildName and buildNumber
  3659  	specFileA, err := tests.CreateSpec(tests.SplitUploadSpecA)
  3660  	assert.NoError(t, err)
  3661  	specFileB, err := tests.CreateSpec(tests.SplitUploadSpecB)
  3662  	assert.NoError(t, err)
  3663  	artifactoryCli.Exec("upload", "--spec="+specFileB, "--build-name="+tests.RtBuildName1, "--build-number="+buildNumberA)
  3664  	artifactoryCli.Exec("upload", "--spec="+specFileA, "--build-name="+tests.RtBuildName1, "--build-number="+buildNumberB)
  3665  
  3666  	// Publish buildInfo
  3667  	artifactoryCli.Exec("build-publish", tests.RtBuildName1, buildNumberA)
  3668  	artifactoryCli.Exec("build-publish", tests.RtBuildName1, buildNumberB)
  3669  
  3670  	// Delete by build name and LATEST
  3671  	artifactoryCli.Exec("delete", "--build="+tests.RtBuildName1+"/LATEST", "--spec="+specFile)
  3672  
  3673  	// Validate files are deleted by build number
  3674  	cpMvDlByBuildAssertSpec, err := tests.CreateSpec(tests.CpMvDlByBuildAssertSpec)
  3675  	assert.NoError(t, err)
  3676  
  3677  	verifyExistInArtifactory(tests.GetBuildDeleteExpected(), cpMvDlByBuildAssertSpec, t)
  3678  
  3679  	// Cleanup
  3680  	inttestutils.DeleteBuild(serverDetails.ArtifactoryUrl, tests.RtBuildName1, artHttpDetails)
  3681  	cleanArtifactoryTest()
  3682  }
  3683  
  3684  func TestGitLfsCleanup(t *testing.T) {
  3685  	initArtifactoryTest(t)
  3686  	var filePath = "testdata/gitlfs/(4b)(*)"
  3687  	artifactoryCli.Exec("upload", filePath, tests.RtLfsRepo+"/objects/4b/f4/{2}{1}")
  3688  	artifactoryCli.Exec("upload", filePath, tests.RtLfsRepo+"/objects/4b/f4/")
  3689  	refs := filepath.Join("refs", "heads", "*")
  3690  	dotGitPath := getCliDotGitPath(t)
  3691  	artifactoryCli.Exec("glc", dotGitPath, "--repo="+tests.RtLfsRepo, "--refs=HEAD,"+refs)
  3692  	gitlfsSpecFile, err := tests.CreateSpec(tests.GitLfsAssertSpec)
  3693  	assert.NoError(t, err)
  3694  	verifyExistInArtifactory(tests.GetGitLfsExpected(), gitlfsSpecFile, t)
  3695  	cleanArtifactoryTest()
  3696  }
  3697  
  3698  func TestPing(t *testing.T) {
  3699  	initArtifactoryTest(t)
  3700  	artifactoryCli.Exec("ping")
  3701  	cleanArtifactoryTest()
  3702  }
  3703  
  3704  func TestSummaryReport(t *testing.T) {
  3705  	initArtifactoryTest(t)
  3706  
  3707  	buffer, previousLog := tests.RedirectLogOutputToBuffer()
  3708  	// Restore previous logger when the function returns
  3709  	defer log.SetLogger(previousLog)
  3710  
  3711  	specFile, err := tests.CreateSpec(tests.UploadFlatNonRecursive)
  3712  	assert.NoError(t, err)
  3713  	artifactoryCli.Exec("upload", "--spec="+specFile)
  3714  	verifySummary(t, buffer, 3, 0, previousLog)
  3715  
  3716  	artifactoryCli.Exec("move", path.Join(tests.RtRepo1, "*.in"), tests.RtRepo2+"/")
  3717  	verifySummary(t, buffer, 3, 0, previousLog)
  3718  
  3719  	artifactoryCli.Exec("copy", path.Join(tests.RtRepo2, "*.in"), tests.RtRepo1+"/")
  3720  	verifySummary(t, buffer, 3, 0, previousLog)
  3721  
  3722  	artifactoryCli.Exec("delete", path.Join(tests.RtRepo2, "*.in"))
  3723  	verifySummary(t, buffer, 3, 0, previousLog)
  3724  
  3725  	artifactoryCli.Exec("set-props", path.Join(tests.RtRepo1, "*.in"), "prop=val")
  3726  	verifySummary(t, buffer, 3, 0, previousLog)
  3727  
  3728  	specFile, err = tests.CreateSpec(tests.DownloadAllRepo1TestResources)
  3729  	assert.NoError(t, err)
  3730  	artifactoryCli.Exec("download", "--spec="+specFile)
  3731  	verifySummary(t, buffer, 3, 0, previousLog)
  3732  
  3733  	cleanArtifactoryTest()
  3734  }
  3735  
  3736  func TestUploadDetailedSummary(t *testing.T) {
  3737  	initArtifactoryTest(t)
  3738  	uploadCmd := generic.NewUploadCommand()
  3739  	fileSpec := spec.NewBuilder().Pattern(filepath.Join("testdata", "a", "a*.in")).Target(tests.RtRepo1).BuildSpec()
  3740  	uploadCmd.SetUploadConfiguration(createUploadConfiguration()).SetSpec(fileSpec).SetServerDetails(serverDetails).SetDetailedSummary(true)
  3741  	commands.Exec(uploadCmd)
  3742  	result := uploadCmd.Result()
  3743  	reader := result.Reader()
  3744  	assert.NoError(t, reader.GetError())
  3745  	defer reader.Close()
  3746  	var files []clientutils.FileTransferDetails
  3747  	for transferDetails := new(clientutils.FileTransferDetails); reader.NextRecord(transferDetails) == nil; transferDetails = new(clientutils.FileTransferDetails) {
  3748  		files = append(files, *transferDetails)
  3749  	}
  3750  	assert.ElementsMatch(t, files, tests.GetExpectedUploadSummaryDetails(*tests.RtUrl))
  3751  	cleanArtifactoryTest()
  3752  }
  3753  
  3754  func createUploadConfiguration() *utils.UploadConfiguration {
  3755  	uploadConfiguration := new(utils.UploadConfiguration)
  3756  	uploadConfiguration.Threads = cliutils.Threads
  3757  	return uploadConfiguration
  3758  }
  3759  
  3760  func TestArtifactoryBuildDiscard(t *testing.T) {
  3761  	// Initialize
  3762  	initArtifactoryTest(t)
  3763  	client, err := httpclient.ClientBuilder().Build()
  3764  	assert.NoError(t, err)
  3765  
  3766  	// Upload files with buildName and buildNumber
  3767  	for i := 1; i <= 5; i++ {
  3768  		artifactoryCli.Exec("upload", "testdata/a/a1.in", tests.RtRepo1+"/data/", "--build-name="+tests.RtBuildName1, "--build-number="+strconv.Itoa(i))
  3769  		artifactoryCli.Exec("build-publish", tests.RtBuildName1, strconv.Itoa(i))
  3770  	}
  3771  
  3772  	// Test discard by max-builds
  3773  	artifactoryCli.Exec("build-discard", tests.RtBuildName1, "--max-builds=3")
  3774  	jsonResponse := getAllBuildsByBuildName(client, tests.RtBuildName1, t, http.StatusOK)
  3775  	assert.Len(t, jsonResponse.Builds, 3, "Incorrect operation of build-discard by max-builds.")
  3776  
  3777  	// Test discard with exclusion
  3778  	artifactoryCli.Exec("build-discard", tests.RtBuildName1, "--max-days=-1", "--exclude-builds=3,5")
  3779  	jsonResponse = getAllBuildsByBuildName(client, tests.RtBuildName1, t, http.StatusOK)
  3780  	assert.Len(t, jsonResponse.Builds, 2, "Incorrect operation of build-discard with exclusion.")
  3781  
  3782  	// Test discard by max-days
  3783  	artifactoryCli.Exec("build-discard", tests.RtBuildName1, "--max-days=-1")
  3784  	jsonResponse = getAllBuildsByBuildName(client, tests.RtBuildName1, t, http.StatusNotFound)
  3785  	assert.Zero(t, jsonResponse, "Incorrect operation of build-discard by max-days.")
  3786  
  3787  	//Cleanup
  3788  	inttestutils.DeleteBuild(serverDetails.ArtifactoryUrl, tests.RtBuildName1, artHttpDetails)
  3789  	cleanArtifactoryTest()
  3790  }
  3791  
  3792  // Tests compatibility to file paths with windows separators.
  3793  // Verifies the upload and download commands work as expected for inputs of both arguments and spec files.
  3794  func TestArtifactoryWinBackwardsCompatibility(t *testing.T) {
  3795  	initArtifactoryTest(t)
  3796  	if !coreutils.IsWindows() {
  3797  		t.Skip("Not running on Windows, skipping...")
  3798  	}
  3799  	uploadSpecFile, err := tests.CreateSpec(tests.WinSimpleUploadSpec)
  3800  	assert.NoError(t, err)
  3801  	artifactoryCli.Exec("upload", "--spec="+uploadSpecFile)
  3802  	artifactoryCli.Exec("upload", "testdata\\\\a\\\\b\\\\*", tests.RtRepo1+"/compatibility_arguments/", "--exclusions=*b2.in;*c*")
  3803  
  3804  	downloadSpecFile, err := tests.CreateSpec(tests.WinSimpleDownloadSpec)
  3805  	assert.NoError(t, err)
  3806  	artifactoryCli.Exec("download", "--spec="+downloadSpecFile)
  3807  	artifactoryCli.Exec("download", tests.RtRepo1+"/*arguments*", "out\\\\win\\\\", "--flat=true")
  3808  
  3809  	// Validate files are downloaded by build number
  3810  	paths, _ := fileutils.ListFilesRecursiveWalkIntoDirSymlink(tests.Out, false)
  3811  	err = tests.ValidateListsIdentical(tests.GetWinCompatibility(), paths)
  3812  	assert.NoError(t, err)
  3813  	cleanArtifactoryTest()
  3814  }
  3815  
  3816  func TestArtifactorySearchIncludeDir(t *testing.T) {
  3817  	initArtifactoryTest(t)
  3818  
  3819  	// Upload files
  3820  	specFileA, err := tests.CreateSpec(tests.SplitUploadSpecA)
  3821  	assert.NoError(t, err)
  3822  	artifactoryCli.Exec("upload", "--spec="+specFileA, "--recursive", "--flat=false")
  3823  
  3824  	// Prepare search command
  3825  	searchSpecBuilder := spec.NewBuilder().Pattern(tests.RtRepo1).Recursive(true)
  3826  	searchCmd := generic.NewSearchCommand()
  3827  	searchCmd.SetServerDetails(serverDetails)
  3828  	searchCmd.SetSpec(searchSpecBuilder.IncludeDirs(false).BuildSpec())
  3829  	reader, err := searchCmd.Search()
  3830  	assert.NoError(t, err)
  3831  
  3832  	// Search without IncludeDirs
  3833  	for resultItem := new(utils.SearchResult); reader.NextRecord(resultItem) == nil; resultItem = new(utils.SearchResult) {
  3834  		assert.NoError(t, assertDateInSearchResult(*resultItem))
  3835  	}
  3836  	assert.NoError(t, reader.GetError())
  3837  	reader.Reset()
  3838  
  3839  	var resultItems []utils.SearchResult
  3840  	readerNoDate, err := utils.SearchResultNoDate(reader)
  3841  	assert.NoError(t, err)
  3842  	for resultItem := new(utils.SearchResult); readerNoDate.NextRecord(resultItem) == nil; resultItem = new(utils.SearchResult) {
  3843  		resultItems = append(resultItems, *resultItem)
  3844  	}
  3845  	assert.NoError(t, readerNoDate.GetError())
  3846  	assert.ElementsMatch(t, resultItems, tests.GetSearchNotIncludeDirsFiles())
  3847  	assert.NoError(t, readerNoDate.Close())
  3848  	assert.NoError(t, reader.Close())
  3849  
  3850  	// Search with IncludeDirs
  3851  	searchCmd.SetSpec(searchSpecBuilder.IncludeDirs(true).BuildSpec())
  3852  	reader, err = searchCmd.Search()
  3853  	assert.NoError(t, err)
  3854  
  3855  	for resultItem := new(utils.SearchResult); reader.NextRecord(resultItem) == nil; resultItem = new(utils.SearchResult) {
  3856  		assert.NoError(t, assertDateInSearchResult(*resultItem))
  3857  	}
  3858  	assert.NoError(t, reader.GetError())
  3859  	reader.Reset()
  3860  
  3861  	resultItems = []utils.SearchResult{}
  3862  	readerNoDate, err = utils.SearchResultNoDate(reader)
  3863  	assert.NoError(t, err)
  3864  	for resultItem := new(utils.SearchResult); readerNoDate.NextRecord(resultItem) == nil; resultItem = new(utils.SearchResult) {
  3865  		resultItems = append(resultItems, *resultItem)
  3866  	}
  3867  	assert.NoError(t, readerNoDate.GetError())
  3868  	assert.ElementsMatch(t, resultItems, tests.GetSearchIncludeDirsFiles())
  3869  	assert.NoError(t, readerNoDate.Close())
  3870  	assert.NoError(t, reader.Close())
  3871  
  3872  	// Cleanup
  3873  	cleanArtifactoryTest()
  3874  }
  3875  
  3876  func TestArtifactorySearchProps(t *testing.T) {
  3877  	initArtifactoryTest(t)
  3878  
  3879  	// Upload files
  3880  	specFile, err := tests.CreateSpec(tests.UploadWithPropsSpec)
  3881  	assert.NoError(t, err)
  3882  	artifactoryCli.Exec("upload", "--spec="+specFile, "--recursive")
  3883  
  3884  	// Prepare search command
  3885  	searchSpecBuilder := spec.NewBuilder().Pattern(tests.RtRepo1).Recursive(true)
  3886  	searchCmd := generic.NewSearchCommand()
  3887  	searchCmd.SetServerDetails(serverDetails)
  3888  
  3889  	// Search artifacts with c=3
  3890  	searchCmd.SetSpec(searchSpecBuilder.Props("c=3").BuildSpec())
  3891  	reader, err := searchCmd.Search()
  3892  	assert.NoError(t, err)
  3893  	for resultItem := new(utils.SearchResult); reader.NextRecord(resultItem) == nil; resultItem = new(utils.SearchResult) {
  3894  		assert.NoError(t, assertDateInSearchResult(*resultItem))
  3895  	}
  3896  	assert.NoError(t, reader.GetError())
  3897  	reader.Reset()
  3898  
  3899  	var resultItems []utils.SearchResult
  3900  	readerNoDate, err := utils.SearchResultNoDate(reader)
  3901  	assert.NoError(t, err)
  3902  	for resultItem := new(utils.SearchResult); readerNoDate.NextRecord(resultItem) == nil; resultItem = new(utils.SearchResult) {
  3903  		resultItems = append(resultItems, *resultItem)
  3904  	}
  3905  	assert.NoError(t, readerNoDate.GetError())
  3906  	assert.ElementsMatch(t, resultItems, tests.GetSearchPropsStep1())
  3907  	assert.NoError(t, readerNoDate.Close())
  3908  	assert.NoError(t, reader.Close())
  3909  
  3910  	// Search artifacts without c=3
  3911  	searchCmd.SetSpec(searchSpecBuilder.Props("").ExcludeProps("c=3").BuildSpec())
  3912  	reader, err = searchCmd.Search()
  3913  	assert.NoError(t, err)
  3914  
  3915  	for resultItem := new(utils.SearchResult); reader.NextRecord(resultItem) == nil; resultItem = new(utils.SearchResult) {
  3916  		assert.NoError(t, assertDateInSearchResult(*resultItem))
  3917  	}
  3918  	assert.NoError(t, reader.GetError())
  3919  	reader.Reset()
  3920  
  3921  	resultItems = []utils.SearchResult{}
  3922  	readerNoDate, err = utils.SearchResultNoDate(reader)
  3923  	assert.NoError(t, err)
  3924  	for resultItem := new(utils.SearchResult); readerNoDate.NextRecord(resultItem) == nil; resultItem = new(utils.SearchResult) {
  3925  		resultItems = append(resultItems, *resultItem)
  3926  	}
  3927  	assert.NoError(t, readerNoDate.GetError())
  3928  	assert.ElementsMatch(t, resultItems, tests.GetSearchPropsStep2())
  3929  	assert.NoError(t, readerNoDate.Close())
  3930  	assert.NoError(t, reader.Close())
  3931  
  3932  	// Search artifacts without a=1&b=2
  3933  	searchCmd.SetSpec(searchSpecBuilder.Props("").ExcludeProps("a=1;b=2").BuildSpec())
  3934  	reader, err = searchCmd.Search()
  3935  	assert.NoError(t, err)
  3936  
  3937  	for resultItem := new(utils.SearchResult); reader.NextRecord(resultItem) == nil; resultItem = new(utils.SearchResult) {
  3938  		assert.NoError(t, assertDateInSearchResult(*resultItem))
  3939  	}
  3940  	assert.NoError(t, reader.GetError())
  3941  	reader.Reset()
  3942  
  3943  	resultItems = []utils.SearchResult{}
  3944  	readerNoDate, err = utils.SearchResultNoDate(reader)
  3945  	assert.NoError(t, err)
  3946  	for resultItem := new(utils.SearchResult); readerNoDate.NextRecord(resultItem) == nil; resultItem = new(utils.SearchResult) {
  3947  		resultItems = append(resultItems, *resultItem)
  3948  	}
  3949  	assert.NoError(t, readerNoDate.GetError())
  3950  	assert.ElementsMatch(t, resultItems, tests.GetSearchPropsStep3())
  3951  	assert.NoError(t, readerNoDate.Close())
  3952  	assert.NoError(t, reader.Close())
  3953  
  3954  	// Search artifacts without a=1&b=2 and with c=3
  3955  	searchCmd.SetSpec(searchSpecBuilder.Props("c=3").ExcludeProps("a=1;b=2").BuildSpec())
  3956  	reader, err = searchCmd.Search()
  3957  	assert.NoError(t, err)
  3958  
  3959  	for resultItem := new(utils.SearchResult); reader.NextRecord(resultItem) == nil; resultItem = new(utils.SearchResult) {
  3960  		assert.NoError(t, assertDateInSearchResult(*resultItem))
  3961  	}
  3962  	assert.NoError(t, reader.GetError())
  3963  	reader.Reset()
  3964  
  3965  	resultItems = []utils.SearchResult{}
  3966  	readerNoDate, err = utils.SearchResultNoDate(reader)
  3967  	assert.NoError(t, err)
  3968  	for resultItem := new(utils.SearchResult); readerNoDate.NextRecord(resultItem) == nil; resultItem = new(utils.SearchResult) {
  3969  		resultItems = append(resultItems, *resultItem)
  3970  	}
  3971  	assert.NoError(t, readerNoDate.GetError())
  3972  	assert.ElementsMatch(t, resultItems, tests.GetSearchPropsStep4())
  3973  	assert.NoError(t, readerNoDate.Close())
  3974  	assert.NoError(t, reader.Close())
  3975  
  3976  	// Search artifacts without a=1 and with c=5
  3977  	searchCmd.SetSpec(searchSpecBuilder.Props("c=5").ExcludeProps("a=1").BuildSpec())
  3978  	reader, err = searchCmd.Search()
  3979  	assert.NoError(t, err)
  3980  
  3981  	for resultItem := new(utils.SearchResult); reader.NextRecord(resultItem) == nil; resultItem = new(utils.SearchResult) {
  3982  		assert.NoError(t, assertDateInSearchResult(*resultItem))
  3983  	}
  3984  	assert.NoError(t, reader.GetError())
  3985  	reader.Reset()
  3986  
  3987  	resultItems = []utils.SearchResult{}
  3988  	readerNoDate, err = utils.SearchResultNoDate(reader)
  3989  	assert.NoError(t, err)
  3990  	for resultItem := new(utils.SearchResult); readerNoDate.NextRecord(resultItem) == nil; resultItem = new(utils.SearchResult) {
  3991  		resultItems = append(resultItems, *resultItem)
  3992  	}
  3993  	assert.NoError(t, readerNoDate.GetError())
  3994  	assert.ElementsMatch(t, resultItems, tests.GetSearchPropsStep5())
  3995  	assert.NoError(t, readerNoDate.Close())
  3996  	assert.NoError(t, reader.Close())
  3997  
  3998  	// Search artifacts by pattern "*b*", exclude pattern "*3*", with "b=1" and without "c=3"
  3999  	pattern := tests.RtRepo1 + "/*b*"
  4000  	exclusions := []string{tests.RtRepo1 + "/*3*"}
  4001  	searchSpecBuilder = spec.NewBuilder().Pattern(pattern).Recursive(true).Exclusions(exclusions).Props("b=1").ExcludeProps("c=3")
  4002  	searchCmd.SetSpec(searchSpecBuilder.BuildSpec())
  4003  	reader, err = searchCmd.Search()
  4004  	assert.NoError(t, err)
  4005  
  4006  	for resultItem := new(utils.SearchResult); reader.NextRecord(resultItem) == nil; resultItem = new(utils.SearchResult) {
  4007  		assert.NoError(t, assertDateInSearchResult(*resultItem))
  4008  	}
  4009  	assert.NoError(t, reader.GetError())
  4010  	reader.Reset()
  4011  
  4012  	resultItems = []utils.SearchResult{}
  4013  	readerNoDate, err = utils.SearchResultNoDate(reader)
  4014  	assert.NoError(t, err)
  4015  	for resultItem := new(utils.SearchResult); readerNoDate.NextRecord(resultItem) == nil; resultItem = new(utils.SearchResult) {
  4016  		resultItems = append(resultItems, *resultItem)
  4017  	}
  4018  	assert.NoError(t, readerNoDate.GetError())
  4019  	assert.ElementsMatch(t, resultItems, tests.GetSearchPropsStep6())
  4020  	assert.NoError(t, readerNoDate.Close())
  4021  	assert.NoError(t, reader.Close())
  4022  
  4023  	// Cleanup
  4024  	cleanArtifactoryTest()
  4025  }
  4026  
  4027  // Remove not to be deleted dirs from delete command from path to delete.
  4028  func TestArtifactoryDeleteExcludeProps(t *testing.T) {
  4029  	initArtifactoryTest(t)
  4030  
  4031  	// Upload files
  4032  	specFile, err := tests.CreateSpec(tests.UploadWithPropsSpecdeleteExcludeProps)
  4033  	assert.NoError(t, err)
  4034  	artifactoryCli.Exec("upload", "--spec="+specFile, "--recursive")
  4035  
  4036  	// Prepare search command
  4037  	searchSpecBuilder := spec.NewBuilder().Pattern(tests.RtRepo1).Recursive(true)
  4038  	searchCmd := generic.NewSearchCommand()
  4039  	searchCmd.SetServerDetails(serverDetails)
  4040  
  4041  	// Delete all artifacts without c=1 but keep dirs that has at least one artifact with c=1 props
  4042  	artifactoryCli.Exec("delete", tests.RtRepo1+"/*", "--exclude-props=c=1")
  4043  
  4044  	// Search artifacts with c=1
  4045  	searchCmd.SetSpec(searchSpecBuilder.BuildSpec())
  4046  	reader, err := searchCmd.Search()
  4047  	assert.NoError(t, err)
  4048  	resultItems := []utils.SearchResult{}
  4049  	readerNoDate, err := utils.SearchResultNoDate(reader)
  4050  	assert.NoError(t, err)
  4051  	for resultItem := new(utils.SearchResult); readerNoDate.NextRecord(resultItem) == nil; resultItem = new(utils.SearchResult) {
  4052  		resultItems = append(resultItems, *resultItem)
  4053  	}
  4054  	assert.NoError(t, readerNoDate.GetError())
  4055  	assert.ElementsMatch(t, resultItems, tests.GetSearchAfterDeleteWithExcludeProps())
  4056  	assert.NoError(t, readerNoDate.Close())
  4057  	assert.NoError(t, reader.Close())
  4058  
  4059  	// Cleanup
  4060  	cleanArtifactoryTest()
  4061  }
  4062  
  4063  func getAllBuildsByBuildName(client *httpclient.HttpClient, buildName string, t *testing.T, expectedHttpStatusCode int) buildsApiResponseStruct {
  4064  	resp, body, _, _ := client.SendGet(serverDetails.ArtifactoryUrl+"api/build/"+buildName, true, artHttpDetails, "")
  4065  	assert.Equal(t, expectedHttpStatusCode, resp.StatusCode, "Failed retrieving build information from artifactory.")
  4066  
  4067  	buildsApiResponse := &buildsApiResponseStruct{}
  4068  	err := json.Unmarshal(body, buildsApiResponse)
  4069  	assert.NoError(t, err, "Unmarshaling failed with an error")
  4070  	return *buildsApiResponse
  4071  }
  4072  
  4073  type buildsApiInnerBuildsStruct struct {
  4074  	Uri     string `json:"uri,omitempty"`
  4075  	Started string `json:"started,omitempty"`
  4076  }
  4077  
  4078  type buildsApiResponseStruct struct {
  4079  	Uri    string                       `json:"uri,omitempty"`
  4080  	Builds []buildsApiInnerBuildsStruct `json:"buildsNumbers,omitempty"`
  4081  }
  4082  
  4083  func verifySummary(t *testing.T, buffer *bytes.Buffer, success, failure int64, logger log.Log) {
  4084  	content := buffer.Bytes()
  4085  	buffer.Reset()
  4086  	logger.Output(string(content))
  4087  
  4088  	status, err := jsonparser.GetString(content, "status")
  4089  	assert.NoError(t, err)
  4090  	assert.Equal(t, "success", status, "Summary validation failed")
  4091  
  4092  	resultSuccess, err := jsonparser.GetInt(content, "totals", "success")
  4093  	assert.NoError(t, err)
  4094  
  4095  	resultFailure, err := jsonparser.GetInt(content, "totals", "failure")
  4096  	assert.NoError(t, err)
  4097  
  4098  	assert.Equal(t, success, resultSuccess, "Summary validation failed")
  4099  	assert.Equal(t, failure, resultFailure, "Summary validation failed")
  4100  }
  4101  
  4102  func CleanArtifactoryTests() {
  4103  	cleanArtifactoryTest()
  4104  	deleteCreatedRepos()
  4105  }
  4106  
  4107  func initArtifactoryTest(t *testing.T) {
  4108  	if !*tests.TestArtifactory {
  4109  		t.Skip("Skipping artifactory test. To run artifactory test add the '-test.artifactory=true' option.")
  4110  	}
  4111  }
  4112  
  4113  func cleanArtifactoryTest() {
  4114  	if !*tests.TestArtifactory {
  4115  		return
  4116  	}
  4117  	os.Unsetenv(coreutils.HomeDir)
  4118  	os.Unsetenv(coreutils.BuildName)
  4119  	os.Unsetenv(coreutils.BuildNumber)
  4120  	log.Info("Cleaning test data...")
  4121  	cleanArtifactory()
  4122  	tests.CleanFileSystem()
  4123  }
  4124  
  4125  func preUploadBasicTestResources() {
  4126  	uploadPath := tests.GetTestResourcesPath() + "a/(.*)"
  4127  	targetPath := tests.RtRepo1 + "/test_resources/{1}"
  4128  	artifactoryCli.Exec("upload", uploadPath, targetPath,
  4129  		"--threads=10", "--regexp=true", "--target-props=searchMe=true", "--flat=false")
  4130  }
  4131  
  4132  func execDeleteRepo(repoName string) {
  4133  	err := artifactoryCli.Exec("repo-delete", repoName, "--quiet")
  4134  	if err != nil {
  4135  		log.Warn(err)
  4136  	}
  4137  }
  4138  
  4139  func execDeleteUser(username string) {
  4140  	err := artifactoryCli.Exec("users-delete", username, "--quiet")
  4141  	if err != nil {
  4142  		log.Error(err)
  4143  		os.Exit(1)
  4144  	}
  4145  }
  4146  
  4147  func getAllRepos() (repositoryKeys []string, err error) {
  4148  	servicesManager, err := utils.CreateServiceManager(serverDetails, -1, false)
  4149  	if err != nil {
  4150  		return nil, err
  4151  	}
  4152  	repos, err := servicesManager.GetAllRepositories()
  4153  	if err != nil {
  4154  		return nil, err
  4155  	}
  4156  	for _, repo := range *repos {
  4157  		repositoryKeys = append(repositoryKeys, repo.Key)
  4158  	}
  4159  	return
  4160  }
  4161  
  4162  func execListBuildNamesRest() ([]string, error) {
  4163  	var buildNames []string
  4164  
  4165  	// Build http client
  4166  	client, err := httpclient.ClientBuilder().Build()
  4167  	if err != nil {
  4168  		return nil, err
  4169  	}
  4170  
  4171  	// Send get request
  4172  	resp, body, _, err := client.SendGet(serverDetails.ArtifactoryUrl+"api/build", true, artHttpDetails, "")
  4173  	if err != nil {
  4174  		return nil, err
  4175  	}
  4176  	if resp.StatusCode != http.StatusOK && resp.StatusCode != http.StatusCreated {
  4177  		return nil, errors.New("Artifactory response: " + resp.Status + "\n" + clientutils.IndentJson(body))
  4178  	}
  4179  
  4180  	builds, _, _, err := jsonparser.Get(body, "builds")
  4181  	if err != nil {
  4182  		return nil, err
  4183  	}
  4184  
  4185  	// Extract repository keys from the json response
  4186  	var keyError error
  4187  	_, err = jsonparser.ArrayEach(builds, func(value []byte, dataType jsonparser.ValueType, offset int, err error) {
  4188  		if err != nil || keyError != nil {
  4189  			return
  4190  		}
  4191  		buildName, err := jsonparser.GetString(value, "uri")
  4192  		if err != nil {
  4193  			keyError = err
  4194  			return
  4195  		}
  4196  		buildNames = append(buildNames, strings.TrimPrefix(buildName, "/"))
  4197  	})
  4198  	if keyError != nil {
  4199  		return nil, err
  4200  	}
  4201  
  4202  	return buildNames, err
  4203  }
  4204  
  4205  func execCreateRepoRest(repoConfig, repoName string) {
  4206  	content, err := os.ReadFile(repoConfig)
  4207  	if err != nil {
  4208  		log.Error(err)
  4209  		os.Exit(1)
  4210  	}
  4211  	rtutils.AddHeader("Content-Type", "application/json", &artHttpDetails.Headers)
  4212  	client, err := httpclient.ClientBuilder().Build()
  4213  	if err != nil {
  4214  		log.Error(err)
  4215  		os.Exit(1)
  4216  	}
  4217  	resp, body, err := client.SendPut(serverDetails.ArtifactoryUrl+"api/repositories/"+repoName, content, artHttpDetails, "")
  4218  	if err != nil {
  4219  		log.Error(err)
  4220  		os.Exit(1)
  4221  	}
  4222  	if resp.StatusCode != http.StatusOK && resp.StatusCode != http.StatusCreated {
  4223  		log.Error(errors.New("Artifactory response: " + resp.Status + "\n" + clientutils.IndentJson(body)))
  4224  		os.Exit(1)
  4225  	}
  4226  	log.Info("Repository", repoName, "created.")
  4227  }
  4228  
  4229  func getAllUsernames() (usersnames []string, err error) {
  4230  	servicesManager, err := utils.CreateServiceManager(serverDetails, -1, false)
  4231  	if err != nil {
  4232  		return nil, err
  4233  	}
  4234  	users, err := servicesManager.GetAllUsers()
  4235  	if err != nil {
  4236  		return nil, err
  4237  	}
  4238  	for _, user := range users {
  4239  		usersnames = append(usersnames, user.Name)
  4240  	}
  4241  	return
  4242  }
  4243  
  4244  func createRequiredRepos() {
  4245  	tests.CreatedNonVirtualRepositories = tests.GetNonVirtualRepositories()
  4246  	createRepos(tests.CreatedNonVirtualRepositories)
  4247  	tests.CreatedVirtualRepositories = tests.GetVirtualRepositories()
  4248  	createRepos(tests.CreatedVirtualRepositories)
  4249  }
  4250  
  4251  func cleanUpOldBuilds() {
  4252  	tests.CleanUpOldItems(tests.GetBuildNames(), execListBuildNamesRest, func(buildName string) {
  4253  		inttestutils.DeleteBuild(serverDetails.ArtifactoryUrl, buildName, artHttpDetails)
  4254  		log.Info("Build", buildName, "deleted.")
  4255  	})
  4256  }
  4257  
  4258  func cleanUpOldRepositories() {
  4259  	tests.CleanUpOldItems(tests.GetAllRepositoriesNames(), getAllRepos, execDeleteRepo)
  4260  }
  4261  
  4262  func cleanUpOldUsers() {
  4263  	tests.CleanUpOldItems(tests.GetTestUsersNames(), getAllUsernames, execDeleteUser)
  4264  }
  4265  
  4266  func createRepos(repos map[*string]string) {
  4267  	for repoName, configFile := range repos {
  4268  		if !isRepoExist(*repoName) {
  4269  			repoConfig := tests.GetTestResourcesPath() + configFile
  4270  			repoConfig, err := tests.ReplaceTemplateVariables(repoConfig, "")
  4271  			if err != nil {
  4272  				log.Error(err)
  4273  				os.Exit(1)
  4274  			}
  4275  			execCreateRepoRest(repoConfig, *repoName)
  4276  		}
  4277  	}
  4278  }
  4279  
  4280  func deleteCreatedRepos() {
  4281  	// Important - Virtual repositories most be deleted first
  4282  	deleteRepos(tests.CreatedVirtualRepositories)
  4283  	deleteRepos(tests.CreatedNonVirtualRepositories)
  4284  }
  4285  
  4286  func deleteRepos(repos map[*string]string) {
  4287  	for repoName := range repos {
  4288  		if isRepoExist(*repoName) {
  4289  			execDeleteRepo(*repoName)
  4290  		}
  4291  	}
  4292  }
  4293  
  4294  func cleanArtifactory() {
  4295  	deleteSpecFile := tests.GetFilePathForArtifactory(tests.DeleteSpec)
  4296  	fmt.Println(deleteSpecFile)
  4297  	deleteSpecFile, err := tests.ReplaceTemplateVariables(deleteSpecFile, "")
  4298  	fmt.Println(deleteSpecFile)
  4299  	if err != nil {
  4300  		log.Error(err)
  4301  		os.Exit(1)
  4302  	}
  4303  	deleteSpec, _ := spec.CreateSpecFromFile(deleteSpecFile, nil)
  4304  	tests.DeleteFiles(deleteSpec, serverDetails)
  4305  }
  4306  
  4307  func searchInArtifactory(specFile string, t *testing.T) ([]utils.SearchResult, error) {
  4308  	searchSpec, _ := spec.CreateSpecFromFile(specFile, nil)
  4309  	searchCmd := generic.NewSearchCommand()
  4310  	searchCmd.SetServerDetails(serverDetails).SetSpec(searchSpec)
  4311  	reader, err := searchCmd.Search()
  4312  	assert.NoError(t, err)
  4313  	var resultItems []utils.SearchResult
  4314  	readerNoDate, err := utils.SearchResultNoDate(reader)
  4315  	assert.NoError(t, err)
  4316  	for searchResult := new(utils.SearchResult); readerNoDate.NextRecord(searchResult) == nil; searchResult = new(utils.SearchResult) {
  4317  		resultItems = append(resultItems, *searchResult)
  4318  	}
  4319  	assert.NoError(t, readerNoDate.GetError())
  4320  	assert.NoError(t, readerNoDate.Close())
  4321  	assert.NoError(t, reader.Close())
  4322  	return resultItems, err
  4323  }
  4324  
  4325  func getSpecAndCommonFlags(specFile string) (*spec.SpecFiles, rtutils.CommonConf) {
  4326  	searchFlags, _ := rtutils.NewCommonConfImpl(artAuth)
  4327  	searchSpec, _ := spec.CreateSpecFromFile(specFile, nil)
  4328  	return searchSpec, searchFlags
  4329  }
  4330  
  4331  func verifyExistInArtifactory(expected []string, specFile string, t *testing.T) {
  4332  	results, _ := searchInArtifactory(specFile, t)
  4333  	tests.CompareExpectedVsActual(expected, results, t)
  4334  }
  4335  
  4336  func verifyDoesntExistInArtifactory(specFile string, t *testing.T) {
  4337  	verifyExistInArtifactory([]string{}, specFile, t)
  4338  }
  4339  
  4340  func verifyExistInArtifactoryByProps(expected []string, pattern, props string, t *testing.T) {
  4341  	searchSpec := spec.NewBuilder().Pattern(pattern).Props(props).Recursive(true).BuildSpec()
  4342  	searchCmd := generic.NewSearchCommand()
  4343  	searchCmd.SetServerDetails(serverDetails).SetSpec(searchSpec)
  4344  	reader, err := searchCmd.Search()
  4345  	assert.NoError(t, err)
  4346  	var resultItems []utils.SearchResult
  4347  	readerNoDate, err := utils.SearchResultNoDate(reader)
  4348  	assert.NoError(t, err)
  4349  	for resultItem := new(utils.SearchResult); readerNoDate.NextRecord(resultItem) == nil; resultItem = new(utils.SearchResult) {
  4350  		resultItems = append(resultItems, *resultItem)
  4351  	}
  4352  	assert.NoError(t, readerNoDate.GetError())
  4353  	tests.CompareExpectedVsActual(expected, resultItems, t)
  4354  	assert.NoError(t, reader.Close())
  4355  	assert.NoError(t, readerNoDate.Close())
  4356  }
  4357  
  4358  func isRepoExist(repoName string) bool {
  4359  	client, err := httpclient.ClientBuilder().Build()
  4360  	if err != nil {
  4361  		log.Error(err)
  4362  		os.Exit(1)
  4363  	}
  4364  	resp, _, _, err := client.SendGet(serverDetails.ArtifactoryUrl+tests.RepoDetailsUrl+repoName, true, artHttpDetails, "")
  4365  	if err != nil {
  4366  		log.Error(err)
  4367  		os.Exit(1)
  4368  	}
  4369  
  4370  	if resp.StatusCode != http.StatusBadRequest {
  4371  		return true
  4372  	}
  4373  	return false
  4374  }
  4375  
  4376  func getCliDotGitPath(t *testing.T) string {
  4377  	dotGitPath, err := os.Getwd()
  4378  	assert.NoError(t, err, "Failed to get current dir.")
  4379  	dotGitExists, err := fileutils.IsDirExists(filepath.Join(dotGitPath, ".git"), false)
  4380  	assert.NoError(t, err)
  4381  	assert.True(t, dotGitExists, "Can't find .git")
  4382  	return dotGitPath
  4383  }
  4384  
  4385  func deleteServerConfig() {
  4386  	configCli.WithoutCredentials().Exec("rm", tests.RtServerId, "--quiet")
  4387  }
  4388  
  4389  // This function will create server config and return the entire passphrase flag if it needed.
  4390  // For example if passphrase is needed it will return "--ssh-passphrase=${theConfiguredPassphrase}" or empty string.
  4391  func createServerConfigAndReturnPassphrase() (passphrase string, err error) {
  4392  	deleteServerConfig()
  4393  	if *tests.RtSshPassphrase != "" {
  4394  		passphrase = "--ssh-passphrase=" + *tests.RtSshPassphrase
  4395  	}
  4396  	return passphrase, configCli.Exec("add", tests.RtServerId)
  4397  }
  4398  
  4399  func testCopyMoveNoSpec(command string, beforeCommandExpected, afterCommandExpected []string, t *testing.T) {
  4400  	initArtifactoryTest(t)
  4401  
  4402  	// Upload files
  4403  	specFileA, err := tests.CreateSpec(tests.SplitUploadSpecA)
  4404  	assert.NoError(t, err)
  4405  	specFileB, err := tests.CreateSpec(tests.SplitUploadSpecB)
  4406  	assert.NoError(t, err)
  4407  
  4408  	artifactoryCli.Exec("upload", "--spec="+specFileA)
  4409  	artifactoryCli.Exec("upload", "--spec="+specFileB)
  4410  
  4411  	// Run command with dry-run
  4412  	artifactoryCli.Exec(command, tests.RtRepo1+"/data/*a*", tests.RtRepo2+"/", "--dry-run")
  4413  
  4414  	// Validate files weren't affected
  4415  	cpMvSpecFilePath, err := tests.CreateSpec(tests.CpMvDlByBuildAssertSpec)
  4416  	assert.NoError(t, err)
  4417  	verifyExistInArtifactory(beforeCommandExpected, cpMvSpecFilePath, t)
  4418  
  4419  	// Run command
  4420  	artifactoryCli.Exec(command, tests.RtRepo1+"/data/*a*", tests.RtRepo2+"/")
  4421  
  4422  	// Validate files were affected
  4423  	verifyExistInArtifactory(afterCommandExpected, cpMvSpecFilePath, t)
  4424  
  4425  	// Cleanup
  4426  	cleanArtifactoryTest()
  4427  }
  4428  
  4429  func searchItemsInArtifactory(t *testing.T, specSource string) []rtutils.ResultItem {
  4430  	fileSpec, err := tests.CreateSpec(specSource)
  4431  	assert.NoError(t, err)
  4432  	spec, flags := getSpecAndCommonFlags(fileSpec)
  4433  	var resultItems []rtutils.ResultItem
  4434  	for i := 0; i < len(spec.Files); i++ {
  4435  		searchParams, err := utils.GetSearchParams(spec.Get(i))
  4436  		assert.NoError(t, err, "Failed Searching files")
  4437  		reader, err := services.SearchBySpecFiles(searchParams, flags, rtutils.ALL)
  4438  		assert.NoError(t, err, "Failed Searching files")
  4439  		for resultItem := new(rtutils.ResultItem); reader.NextRecord(resultItem) == nil; resultItem = new(rtutils.ResultItem) {
  4440  			resultItems = append(resultItems, *resultItem)
  4441  		}
  4442  		assert.NoError(t, reader.GetError())
  4443  		assert.NoError(t, reader.Close())
  4444  	}
  4445  	return resultItems
  4446  }
  4447  
  4448  func assertDateInSearchResult(searchResult utils.SearchResult) error {
  4449  	if searchResult.Created == "" || searchResult.Modified == "" {
  4450  		message, err := json.Marshal(&searchResult)
  4451  		if err != nil {
  4452  			return errors.New("failed to process search result to assert it includes date: " + err.Error())
  4453  		}
  4454  		return errors.New("search result does not include date: " + string(message))
  4455  	}
  4456  	return nil
  4457  }
  4458  
  4459  func TestArtifactoryUploadInflatedPath(t *testing.T) {
  4460  	initArtifactoryTest(t)
  4461  	artifactoryCli.Exec("upload", "testdata/a/../a/a1.*", tests.RtRepo1)
  4462  	artifactoryCli.Exec("upload", "testdata/./a/a1.*", tests.RtRepo1)
  4463  	searchFilePath, err := tests.CreateSpec(tests.SearchRepo1ByInSuffix)
  4464  	assert.NoError(t, err)
  4465  	verifyExistInArtifactory(tests.GetSimpleUploadSpecialCharNoRegexExpectedRepo1(), searchFilePath, t)
  4466  
  4467  	artifactoryCli.Exec("upload", "testdata/./a/../a/././././a2.*", tests.RtRepo1)
  4468  	searchFilePath, err = tests.CreateSpec(tests.SearchRepo1ByInSuffix)
  4469  	assert.NoError(t, err)
  4470  	verifyExistInArtifactory(tests.GetSimpleUploadSpecialCharNoRegexExpected2filesRepo1(), searchFilePath, t)
  4471  	if coreutils.IsWindows() {
  4472  		artifactoryCli.Exec("upload", `testdata\\a\\..\\a\\a1.*`, tests.RtRepo2)
  4473  		artifactoryCli.Exec("upload", `testdata\\.\\\a\a1.*`, tests.RtRepo2)
  4474  		searchFilePath, err = tests.CreateSpec(tests.SearchRepo2)
  4475  		assert.NoError(t, err)
  4476  		verifyExistInArtifactory(tests.GetSimpleUploadSpecialCharNoRegexExpectedRepo2(), searchFilePath, t)
  4477  
  4478  		artifactoryCli.Exec("upload", `testdata\\.\\a\\..\\a\\.\\.\\.\\.\\a2.*`, tests.RtRepo2)
  4479  		searchFilePath, err = tests.CreateSpec(tests.SearchRepo2)
  4480  		assert.NoError(t, err)
  4481  		verifyExistInArtifactory(tests.GetSimpleUploadSpecialCharNoRegexExpected2filesRepo2(), searchFilePath, t)
  4482  	}
  4483  	cleanArtifactoryTest()
  4484  }
  4485  
  4486  func TestGetExtractorsRemoteDetails(t *testing.T) {
  4487  	initArtifactoryTest(t)
  4488  	_, err := createServerConfigAndReturnPassphrase()
  4489  	defer deleteServerConfig()
  4490  	assert.NoError(t, err)
  4491  
  4492  	unsetEnvVars := func() {
  4493  		err := os.Unsetenv(utils.JCenterRemoteServerEnv)
  4494  		assert.NoError(t, err)
  4495  		err = os.Unsetenv(utils.JCenterRemoteRepoEnv)
  4496  		assert.NoError(t, err)
  4497  		err = os.Unsetenv(utils.ExtractorsRemoteEnv)
  4498  		assert.NoError(t, err)
  4499  	}
  4500  	unsetEnvVars()
  4501  	defer unsetEnvVars()
  4502  
  4503  	// Make sure extractor1.jar downloaded from oss.jfrog.org.
  4504  	downloadPath := "org/jfrog/buildinfo/build-info-extractor/extractor1.jar"
  4505  	expectedRemotePath := path.Join("oss-release-local", downloadPath)
  4506  	validateExtractorRemoteDetails(t, downloadPath, expectedRemotePath)
  4507  
  4508  	// Make sure extractor2.jar also downloaded from oss.jfrog.org.
  4509  	downloadPath = "org/jfrog/buildinfo/build-info-extractor/extractor2.jar"
  4510  	expectedRemotePath = path.Join("oss-release-local", downloadPath)
  4511  	validateExtractorRemoteDetails(t, downloadPath, expectedRemotePath)
  4512  
  4513  	// Set 'JFROG_CLI_EXTRACTORS_REMOTE' and make sure extractor3.jar downloaded from a remote repo 'test-remote-repo' in RtServerId.
  4514  	testRemoteRepo := "test-remote-repo"
  4515  	err = os.Setenv(utils.ExtractorsRemoteEnv, tests.RtServerId+"/"+testRemoteRepo)
  4516  	assert.NoError(t, err)
  4517  	downloadPath = "org/jfrog/buildinfo/build-info-extractor/extractor3.jar"
  4518  	expectedRemotePath = path.Join(testRemoteRepo, downloadPath)
  4519  	validateExtractorRemoteDetails(t, downloadPath, expectedRemotePath)
  4520  	err = os.Unsetenv(utils.ExtractorsRemoteEnv)
  4521  	assert.NoError(t, err)
  4522  
  4523  	// Set 'JFROG_CLI_JCENTER_REMOTE_SERVER' and make sure extractor4.jar downloaded from the default 'jcenter' repo in RtServerId.
  4524  	err = os.Setenv(utils.JCenterRemoteServerEnv, tests.RtServerId)
  4525  	assert.NoError(t, err)
  4526  	downloadPath = "org/jfrog/buildinfo/build-info-extractor/extractor4.jar"
  4527  	expectedRemotePath = path.Join("jcenter", downloadPath)
  4528  	validateExtractorRemoteDetails(t, downloadPath, expectedRemotePath)
  4529  
  4530  	// Set 'JFROG_CLI_JCENTER_REMOTE_REPO' to 'test-remote-repo' and make sure extractor5.jar downloaded from this repository.
  4531  	err = os.Setenv(utils.JCenterRemoteRepoEnv, testRemoteRepo)
  4532  	assert.NoError(t, err)
  4533  	downloadPath = "org/jfrog/buildinfo/build-info-extractor/extractor5.jar"
  4534  	expectedRemotePath = path.Join(testRemoteRepo, downloadPath)
  4535  	validateExtractorRemoteDetails(t, downloadPath, expectedRemotePath)
  4536  
  4537  	cleanArtifactoryTest()
  4538  }
  4539  
  4540  func validateExtractorRemoteDetails(t *testing.T, downloadPath, expectedRemotePath string) {
  4541  	serverDetails, remotePath, err := utils.GetExtractorsRemoteDetails(downloadPath)
  4542  	assert.NoError(t, err)
  4543  	assert.Equal(t, expectedRemotePath, remotePath)
  4544  	assert.False(t, os.Getenv(utils.JCenterRemoteServerEnv) != "" && serverDetails == nil, "Expected a server to be returned")
  4545  }
  4546  
  4547  func TestVcsProps(t *testing.T) {
  4548  	initArtifactoryTest(t)
  4549  	defer inttestutils.DeleteBuild(serverDetails.ArtifactoryUrl, tests.RtBuildName1, artHttpDetails)
  4550  	testDir := initVcsTestDir(t)
  4551  	artifactoryCli.Exec("upload", filepath.Join(testDir, "*"), tests.RtRepo1, "--flat=false", "--build-name="+tests.RtBuildName1, "--build-number=2020")
  4552  	resultItems := searchItemsInArtifactory(t, tests.SearchRepo1ByInSuffix)
  4553  	assert.NotZero(t, len(resultItems), "No artifacts were found.")
  4554  	for _, item := range resultItems {
  4555  		properties := item.Properties
  4556  		foundUrl, foundRevision := false, false
  4557  		for _, prop := range properties {
  4558  			if item.Name == "a1.in" || item.Name == "a2.in" {
  4559  				// Check that properties were not removed.
  4560  				if prop.Key == "vcs.url" && prop.Value == "https://github.com/jfrog/jfrog-cli.git" {
  4561  					assert.False(t, foundUrl, "Found duplicate VCS property(url) in artifact")
  4562  					foundUrl = true
  4563  				}
  4564  				if prop.Key == "vcs.revision" && prop.Value == "d63c5957ad6819f4c02a817abe757f210d35ff92" {
  4565  					assert.False(t, foundRevision, "Found duplicate VCS property(revision) in artifact")
  4566  					foundRevision = true
  4567  				}
  4568  			}
  4569  			if item.Name == "b1.in" || item.Name == "b2.in" {
  4570  				if prop.Key == "vcs.url" && prop.Value == "https://github.com/jfrog/jfrog-client-go.git" {
  4571  					assert.False(t, foundUrl, "Found duplicate VCS property(url) in artifact")
  4572  					foundUrl = true
  4573  				}
  4574  				if prop.Key == "vcs.revision" && prop.Value == "ad99b6c068283878fde4d49423728f0bdc00544a" {
  4575  					assert.False(t, foundRevision, "Found duplicate VCS property(revision) in artifact")
  4576  					foundRevision = true
  4577  				}
  4578  			}
  4579  		}
  4580  		assert.True(t, foundUrl && foundRevision, "VCS property was not found on artifact: "+item.Name)
  4581  	}
  4582  	cleanArtifactoryTest()
  4583  }
  4584  
  4585  func initVcsTestDir(t *testing.T) string {
  4586  	testdataSrc := filepath.Join(filepath.FromSlash(tests.GetTestResourcesPath()), "vcs")
  4587  	testdataTarget := tests.Temp
  4588  	err := fileutils.CopyDir(testdataSrc, testdataTarget, true, nil)
  4589  	assert.NoError(t, err)
  4590  	if found, err := fileutils.IsDirExists(filepath.Join(testdataTarget, "gitdata"), false); found {
  4591  		assert.NoError(t, err)
  4592  		coretests.RenamePath(filepath.Join(testdataTarget, "gitdata"), filepath.Join(testdataTarget, ".git"), t)
  4593  	}
  4594  	if found, err := fileutils.IsDirExists(filepath.Join(testdataTarget, "OtherGit", "gitdata"), false); found {
  4595  		assert.NoError(t, err)
  4596  		coretests.RenamePath(filepath.Join(testdataTarget, "OtherGit", "gitdata"), filepath.Join(testdataTarget, "OtherGit", ".git"), t)
  4597  	}
  4598  	path, err := filepath.Abs(tests.Temp)
  4599  	assert.NoError(t, err)
  4600  	return path
  4601  }
  4602  
  4603  func TestConfigAddOverwrite(t *testing.T) {
  4604  	initArtifactoryTest(t)
  4605  	// Add a new instance.
  4606  	err := tests.NewJfrogCli(execMain, "jfrog config", "").Exec("add", tests.RtServerId, "--artifactory-url="+*tests.RtUrl, "--user=admin", "--password=password", "--enc-password=false")
  4607  	// Remove the instance at the end of the test.
  4608  	defer tests.NewJfrogCli(execMain, "jfrog config", "").Exec("rm", tests.RtServerId, "--quiet")
  4609  	// Expect no error, because the instance we created has a unique ID.
  4610  	assert.NoError(t, err)
  4611  	// Try creating an instance with the same ID, and expect to fail, because an instance with the
  4612  	// same ID already exists.
  4613  	err = tests.NewJfrogCli(execMain, "jfrog config", "").Exec("add", tests.RtServerId, "--artifactory-url="+*tests.RtUrl, "--user=admin", "--password=password", "--enc-password=false")
  4614  	assert.Error(t, err)
  4615  	// Now create it again, this time with the --overwrite option and expect no error.
  4616  	err = tests.NewJfrogCli(execMain, "jfrog config", "").Exec("add", tests.RtServerId, "--overwrite", "--artifactory-url="+*tests.RtUrl, "--user=admin2", "--password=password", "--enc-password=false")
  4617  	assert.NoError(t, err)
  4618  }
  4619  
  4620  func TestArtifactoryReplicationCreate(t *testing.T) {
  4621  	initArtifactoryTest(t)
  4622  	// Configure server with dummy credentials
  4623  	err := tests.NewJfrogCli(execMain, "jfrog config", "").Exec("add", tests.RtServerId, "--artifactory-url="+*tests.RtUrl, "--user=admin", "--password=password", "--enc-password=false")
  4624  	defer deleteServerConfig()
  4625  	assert.NoError(t, err)
  4626  
  4627  	// Init tmp dir
  4628  	specFile, err := tests.CreateSpec(tests.ReplicationTempCreate)
  4629  	assert.NoError(t, err)
  4630  
  4631  	// Create push replication
  4632  	err = artifactoryCli.Exec("rplc", specFile)
  4633  	assert.NoError(t, err)
  4634  
  4635  	// Validate create replication
  4636  	servicesManager, err := utils.CreateServiceManager(serverDetails, -1, false)
  4637  	assert.NoError(t, err)
  4638  	result, err := servicesManager.GetReplication(tests.RtRepo1)
  4639  	assert.NoError(t, err)
  4640  	// The Replicator may encrypt the password internally, therefore we should only check that the password is not empty
  4641  	assert.NotEmpty(t, result[0].Password)
  4642  	result[0].Password = ""
  4643  	assert.ElementsMatch(t, result, tests.GetReplicationConfig())
  4644  
  4645  	// Delete replication
  4646  	err = artifactoryCli.Exec("rpldel", tests.RtRepo1)
  4647  	assert.NoError(t, err)
  4648  
  4649  	// Validate delete replication
  4650  	result, err = servicesManager.GetReplication(tests.RtRepo1)
  4651  	assert.Error(t, err)
  4652  	// Cleanup
  4653  	cleanArtifactoryTest()
  4654  }
  4655  
  4656  func TestAccessTokenCreate(t *testing.T) {
  4657  	initArtifactoryTest(t)
  4658  
  4659  	buffer, previousLog := tests.RedirectLogOutputToBuffer()
  4660  	// Restore previous logger when the function returns
  4661  	defer log.SetLogger(previousLog)
  4662  
  4663  	// Create access token for current user, implicitly
  4664  	if *tests.RtAccessToken != "" {
  4665  		// Use Artifactory CLI with basic auth to allow running `jfrog rt atc` without arguments
  4666  		origAccessToken := *tests.RtAccessToken
  4667  		origUsername, origPassword := tests.SetBasicAuthFromAccessToken(t)
  4668  		defer func() {
  4669  			*tests.RtUser = origUsername
  4670  			*tests.RtPassword = origPassword
  4671  			*tests.RtAccessToken = origAccessToken
  4672  		}()
  4673  		*tests.RtAccessToken = ""
  4674  		err := tests.NewJfrogCli(execMain, "jfrog rt", authenticate(false)).Exec("atc")
  4675  		assert.NoError(t, err)
  4676  	} else {
  4677  		err := artifactoryCli.Exec("atc")
  4678  		assert.NoError(t, err)
  4679  	}
  4680  
  4681  	// Check access token
  4682  	checkAccessToken(t, buffer)
  4683  
  4684  	// Create access token for current user, explicitly
  4685  	err := artifactoryCli.Exec("atc", *tests.RtUser)
  4686  	assert.NoError(t, err)
  4687  
  4688  	// Check access token
  4689  	checkAccessToken(t, buffer)
  4690  
  4691  	// Cleanup
  4692  	cleanArtifactoryTest()
  4693  }
  4694  
  4695  func checkAccessToken(t *testing.T, buffer *bytes.Buffer) {
  4696  	// Write the command output to the origin
  4697  	content := buffer.Bytes()
  4698  	buffer.Reset()
  4699  
  4700  	// Extract the the token from the output
  4701  	token, err := jsonparser.GetString(content, "access_token")
  4702  	assert.NoError(t, err)
  4703  
  4704  	// Try ping with the new token
  4705  	err = tests.NewJfrogCli(execMain, "jfrog rt", "--url="+*tests.RtUrl+" --access-token="+token).Exec("ping")
  4706  	assert.NoError(t, err)
  4707  }
  4708  
  4709  func TestRefreshableTokens(t *testing.T) {
  4710  	initArtifactoryTest(t)
  4711  
  4712  	if *tests.RtAccessToken != "" {
  4713  		t.Skip("Test only with username and password / APIkey, skipping...")
  4714  	}
  4715  
  4716  	// Create server with initialized refreshable tokens.
  4717  	_, err := createServerConfigAndReturnPassphrase()
  4718  	defer deleteServerConfig()
  4719  	assert.NoError(t, err)
  4720  
  4721  	// Upload a file and assert the refreshable tokens were generated.
  4722  	artifactoryCommandExecutor := tests.NewJfrogCli(execMain, "jfrog rt", "")
  4723  	uploadedFiles := 1
  4724  	err = uploadWithSpecificServerAndVerify(t, artifactoryCommandExecutor, tests.RtServerId, "testdata/a/a1.in", uploadedFiles)
  4725  	if err != nil {
  4726  		return
  4727  	}
  4728  	curAccessToken, curRefreshToken, err := getTokensFromConfig(t, tests.RtServerId)
  4729  	if err != nil {
  4730  		return
  4731  	}
  4732  	assert.NotEmpty(t, curAccessToken)
  4733  	assert.NotEmpty(t, curRefreshToken)
  4734  
  4735  	// Make the token always refresh.
  4736  	auth.RefreshBeforeExpiryMinutes = 60
  4737  
  4738  	// Upload a file and assert tokens were refreshed.
  4739  	uploadedFiles++
  4740  	err = uploadWithSpecificServerAndVerify(t, artifactoryCommandExecutor, tests.RtServerId, "testdata/a/a2.in", uploadedFiles)
  4741  	if err != nil {
  4742  		return
  4743  	}
  4744  	curAccessToken, curRefreshToken, err = assertTokensChanged(t, tests.RtServerId, curAccessToken, curRefreshToken)
  4745  	if err != nil {
  4746  		return
  4747  	}
  4748  
  4749  	// Make refresh token invalid. Refreshing using tokens should fail, so new tokens should be generated using credentials.
  4750  	err = setRefreshTokenInConfig(t, tests.RtServerId, "invalid-token")
  4751  	if err != nil {
  4752  		return
  4753  	}
  4754  	uploadedFiles++
  4755  	err = uploadWithSpecificServerAndVerify(t, artifactoryCommandExecutor, tests.RtServerId, "testdata/a/a3.in", uploadedFiles)
  4756  	if err != nil {
  4757  		return
  4758  	}
  4759  	curAccessToken, curRefreshToken, err = assertTokensChanged(t, tests.RtServerId, curAccessToken, curRefreshToken)
  4760  	if err != nil {
  4761  		return
  4762  	}
  4763  
  4764  	// Make password invalid. Refreshing should succeed, and new token should be obtained.
  4765  	err = setPasswordInConfig(t, tests.RtServerId, "invalid-pass")
  4766  	if err != nil {
  4767  		return
  4768  	}
  4769  	uploadedFiles++
  4770  	err = uploadWithSpecificServerAndVerify(t, artifactoryCommandExecutor, tests.RtServerId, "testdata/a/b/b1.in", uploadedFiles)
  4771  	if err != nil {
  4772  		return
  4773  	}
  4774  	curAccessToken, curRefreshToken, err = assertTokensChanged(t, tests.RtServerId, curAccessToken, curRefreshToken)
  4775  	if err != nil {
  4776  		return
  4777  	}
  4778  
  4779  	// Make the token not refresh. Verify Tokens did not refresh.
  4780  	auth.RefreshBeforeExpiryMinutes = 0
  4781  	uploadedFiles++
  4782  	err = uploadWithSpecificServerAndVerify(t, artifactoryCommandExecutor, tests.RtServerId, "testdata/a/b/b2.in", uploadedFiles)
  4783  	if err != nil {
  4784  		return
  4785  	}
  4786  	newAccessToken, newRefreshToken, err := getTokensFromConfig(t, tests.RtServerId)
  4787  	if err != nil {
  4788  		return
  4789  	}
  4790  	assert.Equal(t, curAccessToken, newAccessToken)
  4791  	assert.Equal(t, curRefreshToken, newRefreshToken)
  4792  
  4793  	// Cleanup
  4794  	cleanArtifactoryTest()
  4795  }
  4796  
  4797  func setRefreshTokenInConfig(t *testing.T, serverId, token string) error {
  4798  	details, err := config.GetAllServersConfigs()
  4799  	if err != nil {
  4800  		assert.NoError(t, err)
  4801  		return err
  4802  	}
  4803  	for _, server := range details {
  4804  		if server.ServerId == serverId {
  4805  			server.SetRefreshToken(token)
  4806  		}
  4807  	}
  4808  	assert.NoError(t, config.SaveServersConf(details))
  4809  	return nil
  4810  }
  4811  
  4812  func setPasswordInConfig(t *testing.T, serverId, password string) error {
  4813  	details, err := config.GetAllServersConfigs()
  4814  	if err != nil {
  4815  		assert.NoError(t, err)
  4816  		return err
  4817  	}
  4818  	for _, server := range details {
  4819  		if server.ServerId == serverId {
  4820  			server.SetPassword(password)
  4821  		}
  4822  	}
  4823  	assert.NoError(t, config.SaveServersConf(details))
  4824  	return nil
  4825  }
  4826  
  4827  func getTokensFromConfig(t *testing.T, serverId string) (accessToken, refreshToken string, err error) {
  4828  	details, err := config.GetSpecificConfig(serverId, false, false)
  4829  	if err != nil {
  4830  		assert.NoError(t, err)
  4831  		return "", "", err
  4832  	}
  4833  	return details.AccessToken, details.RefreshToken, nil
  4834  }
  4835  
  4836  func assertTokensChanged(t *testing.T, serverId, curAccessToken, curRefreshToken string) (newAccessToken, newRefreshToken string, err error) {
  4837  	newAccessToken, newRefreshToken, err = getTokensFromConfig(t, serverId)
  4838  	if err != nil {
  4839  		assert.NoError(t, err)
  4840  		return "", "", err
  4841  	}
  4842  	assert.NotEqual(t, curAccessToken, newAccessToken)
  4843  	assert.NotEqual(t, curRefreshToken, newRefreshToken)
  4844  	return newAccessToken, newRefreshToken, nil
  4845  }
  4846  
  4847  func uploadWithSpecificServerAndVerify(t *testing.T, cli *tests.JfrogCli, serverId string, source string, expectedResults int) error {
  4848  	err := cli.Exec("upload", source, tests.RtRepo1, "--server-id="+serverId)
  4849  	if err != nil {
  4850  		assert.NoError(t, err)
  4851  		return err
  4852  	}
  4853  	assert.Len(t, searchItemsInArtifactory(t, tests.SearchRepo1ByInSuffix), expectedResults)
  4854  	return nil
  4855  }
  4856  
  4857  func TestArtifactorySimpleUploadAntPattern(t *testing.T) {
  4858  	initArtifactoryTest(t)
  4859  
  4860  	// --ant and --regexp together: should get an error
  4861  	uploadUsingAntAndRegexpTogether(t)
  4862  	// Upload empty dir
  4863  	uploadUsingAntAIncludeDirsAndFlat(t)
  4864  	// Simple uploads
  4865  	simpleUploadAntIsTrueRegexpIsFalse(t)
  4866  	simpleUploadWithAntPatternSpec(t)
  4867  
  4868  	cleanArtifactoryTest()
  4869  }
  4870  
  4871  func uploadUsingAntAndRegexpTogether(t *testing.T) {
  4872  	filePath := getAntPatternFilePath()
  4873  	err := artifactoryCli.Exec("upload", filePath, tests.RtRepo1, "--regexp", "--ant")
  4874  	assert.Error(t, err)
  4875  }
  4876  
  4877  func simpleUploadAntIsTrueRegexpIsFalse(t *testing.T) {
  4878  	filePath := getAntPatternFilePath()
  4879  	err := artifactoryCli.Exec("upload", filePath, tests.RtRepo1, "--ant", "--regexp=false")
  4880  	assert.NoError(t, err)
  4881  	searchFilePath, err := tests.CreateSpec(tests.SearchRepo1ByInSuffix)
  4882  	assert.NoError(t, err)
  4883  	verifyExistInArtifactory(tests.GetSimpleAntPatternUploadExpectedRepo1(), searchFilePath, t)
  4884  }
  4885  
  4886  func simpleUploadWithAntPatternSpec(t *testing.T) {
  4887  	// Init tmp dir
  4888  	specFile, err := tests.CreateSpec(tests.UploadAntPattern)
  4889  	assert.NoError(t, err)
  4890  	err = fileutils.CopyDir(tests.GetTestResourcesPath()+"cache", filepath.Dir(specFile), true, nil)
  4891  	assert.NoError(t, err)
  4892  	// Upload
  4893  	artifactoryCli.Exec("upload", "--spec="+specFile)
  4894  	searchFilePath, err := tests.CreateSpec(tests.SearchRepo1ByInSuffix)
  4895  	assert.NoError(t, err)
  4896  	verifyExistInArtifactory(tests.GetSimpleAntPatternUploadExpectedRepo1(), searchFilePath, t)
  4897  	searchFilePath, err = tests.CreateSpec(tests.SearchRepo1NonExistFile)
  4898  	verifyDoesntExistInArtifactory(searchFilePath, t)
  4899  }
  4900  
  4901  func uploadUsingAntAIncludeDirsAndFlat(t *testing.T) {
  4902  	filePath := "testdata/*/empt?/**"
  4903  	err := artifactoryCli.Exec("upload", filePath, tests.RtRepo1, "--ant", "--include-dirs=true", "--flat=true")
  4904  	assert.NoError(t, err)
  4905  	err = artifactoryCli.Exec("upload", filePath, tests.RtRepo1, "--ant", "--include-dirs=true", "--flat=false")
  4906  	assert.NoError(t, err)
  4907  	searchFilePath, err := tests.CreateSpec(tests.SearchRepo1IncludeDirs)
  4908  	assert.NoError(t, err)
  4909  	verifyExistInArtifactory(tests.GetAntPatternUploadWithIncludeDirsExpectedRepo1(), searchFilePath, t)
  4910  }
  4911  
  4912  func TestUploadWithAntPatternAndExclusionsSpec(t *testing.T) {
  4913  	initArtifactoryTest(t)
  4914  	// Init tmp dir
  4915  	specFile, err := tests.CreateSpec(tests.UploadAntPatternExclusions)
  4916  	assert.NoError(t, err)
  4917  	err = fileutils.CopyDir(tests.GetTestResourcesPath(), filepath.Dir(specFile), true, nil)
  4918  	assert.NoError(t, err)
  4919  	// Upload
  4920  	artifactoryCli.Exec("upload", "--spec="+specFile)
  4921  	searchFilePath, err := tests.CreateSpec(tests.SearchRepo1ByInSuffix)
  4922  	assert.NoError(t, err)
  4923  	verifyExistInArtifactory(tests.GetAntPatternUploadWithExclusionsExpectedRepo1(), searchFilePath, t)
  4924  	searchFilePath, err = tests.CreateSpec(tests.SearchRepo1NonExistFileAntExclusions)
  4925  	verifyDoesntExistInArtifactory(searchFilePath, t)
  4926  	cleanArtifactoryTest()
  4927  }
  4928  
  4929  func TestPermissionTargets(t *testing.T) {
  4930  	initArtifactoryTest(t)
  4931  	servicesManager, err := utils.CreateServiceManager(serverDetails, -1, false)
  4932  	if err != nil {
  4933  		assert.NoError(t, err)
  4934  		return
  4935  	}
  4936  	templatePath := filepath.Join(tests.GetTestResourcesPath(), "permissiontarget", "template")
  4937  
  4938  	// Create permission target on specific repo.
  4939  	assert.NoError(t, artifactoryCli.Exec("ptc", templatePath, createPermissionTargetsTemplateVars(tests.RtRepo1)))
  4940  	assertPermissionTarget(t, servicesManager, tests.RtRepo1)
  4941  
  4942  	// Update permission target to ANY repo.
  4943  	any := "ANY"
  4944  	assert.NoError(t, artifactoryCli.Exec("ptu", templatePath, createPermissionTargetsTemplateVars(any)))
  4945  	assertPermissionTarget(t, servicesManager, any)
  4946  
  4947  	// Delete permission target.
  4948  	assert.NoError(t, artifactoryCli.Exec("ptdel", tests.RtPermissionTargetName))
  4949  	assertPermissionTargetDeleted(t, servicesManager)
  4950  
  4951  	cleanArtifactoryTest()
  4952  }
  4953  
  4954  func createPermissionTargetsTemplateVars(reposValue string) string {
  4955  	ptNameVarKey := "pt_name"
  4956  	reposVarKey := "repos_var"
  4957  	return fmt.Sprintf("--vars=%s=%s;%s=%s", ptNameVarKey, tests.RtPermissionTargetName, reposVarKey, reposValue)
  4958  }
  4959  
  4960  func assertPermissionTarget(t *testing.T, manager artifactory.ArtifactoryServicesManager, repoValue string) {
  4961  	actual, err := manager.GetPermissionTarget(tests.RtPermissionTargetName)
  4962  	if err != nil {
  4963  		assert.NoError(t, err)
  4964  		return
  4965  	}
  4966  	expected := tests.GetExpectedPermissionTarget(repoValue)
  4967  	assert.EqualValues(t, expected, *actual)
  4968  }
  4969  
  4970  func assertPermissionTargetDeleted(t *testing.T, manager artifactory.ArtifactoryServicesManager) {
  4971  	permission, err := manager.GetPermissionTarget(tests.RtPermissionTargetName)
  4972  	assert.NoError(t, err)
  4973  	assert.Nil(t, permission)
  4974  }
  4975  
  4976  func cleanPermissionTarget() {
  4977  	_ = artifactoryCli.Exec("ptdel", tests.RtPermissionTargetName)
  4978  }
  4979  
  4980  func TestArtifactoryCurl(t *testing.T) {
  4981  	initArtifactoryTest(t)
  4982  	_, err := createServerConfigAndReturnPassphrase()
  4983  	defer deleteServerConfig()
  4984  	assert.NoError(t, err)
  4985  	// Check curl command with config default server
  4986  	err = artifactoryCli.WithoutCredentials().Exec("curl", "-XGET", "/api/system/version")
  4987  	assert.NoError(t, err)
  4988  	// Check curl command with '--server-id' flag
  4989  	err = artifactoryCli.WithoutCredentials().Exec("curl", "-XGET", "/api/system/version", "--server-id="+tests.RtServerId)
  4990  	assert.NoError(t, err)
  4991  	// Check curl command with invalid server id - should get an error.
  4992  	err = artifactoryCli.WithoutCredentials().Exec("curl", "-XGET", "/api/system/version", "--server-id=not_configured_name_"+tests.RtServerId)
  4993  	assert.Error(t, err)
  4994  
  4995  	cleanArtifactoryTest()
  4996  }