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

     1  package main
     2  
     3  import (
     4  	"bytes"
     5  	"crypto/tls"
     6  	"encoding/json"
     7  	"errors"
     8  	"fmt"
     9  	"io/ioutil"
    10  	"net"
    11  	"net/http"
    12  	"net/url"
    13  	"os"
    14  	"os/exec"
    15  	"path"
    16  	"path/filepath"
    17  	"regexp"
    18  	"strconv"
    19  	"strings"
    20  	"testing"
    21  	"time"
    22  
    23  	"github.com/buger/jsonparser"
    24  	"github.com/jfrog/gofrog/io"
    25  	"github.com/jfrog/jfrog-cli-go/artifactory/commands/generic"
    26  	"github.com/jfrog/jfrog-cli-go/artifactory/spec"
    27  	"github.com/jfrog/jfrog-cli-go/artifactory/utils"
    28  	"github.com/jfrog/jfrog-cli-go/inttestutils"
    29  	"github.com/jfrog/jfrog-cli-go/utils/cliutils"
    30  	"github.com/jfrog/jfrog-cli-go/utils/config"
    31  	logUtils "github.com/jfrog/jfrog-cli-go/utils/log"
    32  	"github.com/jfrog/jfrog-cli-go/utils/tests"
    33  	cliproxy "github.com/jfrog/jfrog-cli-go/utils/tests/proxy/server"
    34  	"github.com/jfrog/jfrog-cli-go/utils/tests/proxy/server/certificate"
    35  	"github.com/jfrog/jfrog-client-go/artifactory/services"
    36  	rtutils "github.com/jfrog/jfrog-client-go/artifactory/services/utils"
    37  	"github.com/jfrog/jfrog-client-go/artifactory/services/utils/tests/xray"
    38  	"github.com/jfrog/jfrog-client-go/auth"
    39  	"github.com/jfrog/jfrog-client-go/httpclient"
    40  	clientutils "github.com/jfrog/jfrog-client-go/utils"
    41  	"github.com/jfrog/jfrog-client-go/utils/errorutils"
    42  	"github.com/jfrog/jfrog-client-go/utils/io/fileutils"
    43  	"github.com/jfrog/jfrog-client-go/utils/io/httputils"
    44  	"github.com/jfrog/jfrog-client-go/utils/log"
    45  	"github.com/mholt/archiver"
    46  	"github.com/stretchr/testify/assert"
    47  )
    48  
    49  // JFrog CLI for Artifactory commands
    50  var artifactoryCli *tests.JfrogCli
    51  
    52  // JFrog CLI for config command only (doesn't pass the --ssh-passphrase flag)
    53  var configArtifactoryCli *tests.JfrogCli
    54  
    55  var artifactoryDetails *config.ArtifactoryDetails
    56  var artAuth auth.CommonDetails
    57  var artHttpDetails httputils.HttpClientDetails
    58  
    59  func InitArtifactoryTests() {
    60  	initArtifactoryCli()
    61  	createReposIfNeeded()
    62  	cleanArtifactoryTest()
    63  }
    64  
    65  func authenticate() string {
    66  	artifactoryDetails = &config.ArtifactoryDetails{Url: clientutils.AddTrailingSlashIfNeeded(*tests.RtUrl), SshKeyPath: *tests.RtSshKeyPath, SshPassphrase: *tests.RtSshPassphrase, AccessToken: *tests.RtAccessToken}
    67  	cred := "--url=" + *tests.RtUrl
    68  	if *tests.RtDistributionUrl != "" {
    69  		cred += " --dist-url=" + *tests.RtDistributionUrl
    70  	}
    71  	if !fileutils.IsSshUrl(artifactoryDetails.Url) {
    72  		if *tests.RtApiKey != "" {
    73  			artifactoryDetails.ApiKey = *tests.RtApiKey
    74  		} else if *tests.RtAccessToken != "" {
    75  			artifactoryDetails.AccessToken = *tests.RtAccessToken
    76  		} else {
    77  			artifactoryDetails.User = *tests.RtUser
    78  			artifactoryDetails.Password = *tests.RtPassword
    79  		}
    80  	}
    81  	cred += getArtifactoryTestCredentials()
    82  	var err error
    83  	if artAuth, err = artifactoryDetails.CreateArtAuthConfig(); err != nil {
    84  		cliutils.ExitOnErr(errors.New("Failed while attempting to authenticate with Artifactory: " + err.Error()))
    85  	}
    86  	artifactoryDetails.SshAuthHeaders = artAuth.GetSshAuthHeaders()
    87  	artifactoryDetails.Url = artAuth.GetUrl()
    88  	artifactoryDetails.SshUrl = artAuth.GetSshUrl()
    89  	artHttpDetails = artAuth.CreateHttpClientDetails()
    90  	return cred
    91  }
    92  
    93  // A Jfrog CLI to be used to execute a config task.
    94  // Removed the ssh-passphrase flag that cannot be passed to with a config command
    95  func createConfigJfrogCLI(cred string) *tests.JfrogCli {
    96  	if strings.Contains(cred, " --ssh-passphrase=") {
    97  		cred = strings.Replace(cred, " --ssh-passphrase="+*tests.RtSshPassphrase, "", -1)
    98  	}
    99  	return tests.NewJfrogCli(execMain, "jfrog rt", cred)
   100  }
   101  
   102  func getArtifactoryTestCredentials() string {
   103  	if fileutils.IsSshUrl(artifactoryDetails.Url) {
   104  		return getSshCredentials()
   105  	}
   106  	if *tests.RtApiKey != "" {
   107  		return " --apikey=" + *tests.RtApiKey
   108  	}
   109  	if *tests.RtAccessToken != "" {
   110  		return " --access-token=" + *tests.RtAccessToken
   111  	}
   112  	return " --user=" + *tests.RtUser + " --password=" + *tests.RtPassword
   113  }
   114  
   115  func getSshCredentials() string {
   116  	cred := ""
   117  	if *tests.RtSshKeyPath != "" {
   118  		cred += " --ssh-key-path=" + *tests.RtSshKeyPath
   119  	}
   120  	if *tests.RtSshPassphrase != "" {
   121  		cred += " --ssh-passphrase=" + *tests.RtSshPassphrase
   122  	}
   123  	return cred
   124  }
   125  
   126  func TestArtifactorySimpleUploadSpec(t *testing.T) {
   127  	initArtifactoryTest(t)
   128  	specFile, err := tests.CreateSpec(tests.UploadFlatRecursive)
   129  	assert.NoError(t, err)
   130  	artifactoryCli.Exec("upload", "--spec="+specFile)
   131  	searchFilePath, err := tests.CreateSpec(tests.SearchRepo1ByInSuffix)
   132  	assert.NoError(t, err)
   133  	verifyExistInArtifactory(tests.GetSimpleUploadExpectedRepo1(), searchFilePath, t)
   134  	cleanArtifactoryTest()
   135  }
   136  
   137  func TestArtifactorySimpleUploadWithWildcardSpec(t *testing.T) {
   138  	initArtifactoryTest(t)
   139  	// Init tmp dir
   140  	specFile, err := tests.CreateSpec(tests.UploadTempWildcard)
   141  	assert.NoError(t, err)
   142  	err = fileutils.CopyDir(tests.GetTestResourcesPath()+"cache", filepath.Dir(specFile), true)
   143  	assert.NoError(t, err)
   144  	// Upload
   145  	artifactoryCli.Exec("upload", "--spec="+specFile)
   146  	searchFilePath, err := tests.CreateSpec(tests.SearchRepo1ByInSuffix)
   147  	assert.NoError(t, err)
   148  	verifyExistInArtifactory(tests.GetSimpleWildcardUploadExpectedRepo1(), searchFilePath, t)
   149  	cleanArtifactoryTest()
   150  }
   151  
   152  // This test is similar to TestArtifactorySimpleUploadSpec but using "--server-id" flag
   153  func TestArtifactorySimpleUploadSpecUsingConfig(t *testing.T) {
   154  	initArtifactoryTest(t)
   155  	passphrase := createServerConfigAndReturnPassphrase()
   156  	artifactoryCommandExecutor := tests.NewJfrogCli(execMain, "jfrog rt", "")
   157  	specFile, err := tests.CreateSpec(tests.UploadFlatRecursive)
   158  	assert.NoError(t, err)
   159  	artifactoryCommandExecutor.Exec("upload", "--spec="+specFile, "--server-id="+tests.RtServerId, passphrase)
   160  
   161  	searchFilePath, err := tests.CreateSpec(tests.SearchRepo1ByInSuffix)
   162  	assert.NoError(t, err)
   163  	verifyExistInArtifactory(tests.GetSimpleUploadExpectedRepo1(), searchFilePath, t)
   164  	deleteServerConfig()
   165  	cleanArtifactoryTest()
   166  }
   167  
   168  func TestArtifactoryUploadPathWithSpecialCharsAsNoRegex(t *testing.T) {
   169  	initArtifactoryTest(t)
   170  	filePath := getSpecialCharFilePath()
   171  
   172  	artifactoryCli.Exec("upload", filePath, tests.Repo1)
   173  	searchFilePath, err := tests.CreateSpec(tests.SearchRepo1ByInSuffix)
   174  	assert.NoError(t, err)
   175  
   176  	verifyExistInArtifactory(tests.GetSimpleUploadSpecialCharNoRegexExpectedRepo1(), searchFilePath, t)
   177  	cleanArtifactoryTest()
   178  }
   179  
   180  func TestArtifactoryDownloadFromVirtual(t *testing.T) {
   181  	initArtifactoryTest(t)
   182  
   183  	artifactoryCli.Exec("upload", "testsdata/a/*", tests.Repo1, "--flat=false")
   184  	artifactoryCli.Exec("dl", tests.VirtualRepo+"/testsdata/(*)", tests.Out+"/"+"{1}", "--flat=true")
   185  
   186  	paths, _ := fileutils.ListFilesRecursiveWalkIntoDirSymlink(tests.Out, false)
   187  	tests.VerifyExistLocally(tests.GetVirtualDownloadExpected(), paths, t)
   188  
   189  	cleanArtifactoryTest()
   190  }
   191  
   192  func TestArtifactoryDownloadPathWithSpecialChars(t *testing.T) {
   193  	initArtifactoryTest(t)
   194  	artifactoryCli.Exec("upload", getSpecialCharFilePath(), tests.Repo1, "--flat=false")
   195  	artifactoryCli.Exec("upload", "testsdata/c#/a#1.in", tests.Repo1, "--flat=false")
   196  
   197  	artifactoryCli.Exec("dl", tests.Repo1+"/testsdata/a$+~&^a#/a*", tests.Out+fileutils.GetFileSeparator(), "--flat=true")
   198  	artifactoryCli.Exec("dl", tests.Repo1+"/testsdata/c#/a#1.in", tests.Out+fileutils.GetFileSeparator(), "--flat=true")
   199  
   200  	paths, _ := fileutils.ListFilesRecursiveWalkIntoDirSymlink(tests.Out, false)
   201  	tests.VerifyExistLocally([]string{tests.Out + fileutils.GetFileSeparator() + "a1.in", tests.Out + fileutils.GetFileSeparator() + "a#1.in"}, paths, t)
   202  
   203  	cleanArtifactoryTest()
   204  }
   205  
   206  func TestArtifactoryConcurrentDownload(t *testing.T) {
   207  	testArtifactoryDownload(cliutils.DownloadMinSplitKb*1000, t)
   208  }
   209  
   210  func TestArtifactoryBulkDownload(t *testing.T) {
   211  	testArtifactoryDownload(cliutils.DownloadMinSplitKb*1000-1, t)
   212  }
   213  
   214  func testArtifactoryDownload(fileSize int, t *testing.T) {
   215  	initArtifactoryTest(t)
   216  	err := fileutils.CreateDirIfNotExist(tests.Out)
   217  	assert.NoError(t, err)
   218  	randFile, err := io.CreateRandFile(filepath.Join(tests.Out, "randFile"), fileSize)
   219  	assert.NoError(t, err)
   220  	localFileDetails, err := fileutils.GetFileDetails(randFile.Name())
   221  	assert.NoError(t, err)
   222  
   223  	artifactoryCli.Exec("u", randFile.Name(), tests.Repo1+"/testsdata/", "--flat=true")
   224  	randFile.File.Close()
   225  	os.RemoveAll(tests.Out)
   226  	artifactoryCli.Exec("dl", tests.Repo1+"/testsdata/", tests.Out+fileutils.GetFileSeparator(), "--flat=true")
   227  
   228  	paths, err := fileutils.ListFilesRecursiveWalkIntoDirSymlink(tests.Out, false)
   229  	assert.NoError(t, err)
   230  	tests.VerifyExistLocally([]string{tests.Out + fileutils.GetFileSeparator() + "randFile"}, paths, t)
   231  	tests.ValidateChecksums(tests.Out+fileutils.GetFileSeparator()+"randFile", localFileDetails.Checksum, t)
   232  	cleanArtifactoryTest()
   233  }
   234  
   235  func TestArtifactoryDownloadWildcardInRepo(t *testing.T) {
   236  	initArtifactoryTest(t)
   237  	var filePath = getSpecialCharFilePath()
   238  
   239  	// Upload a file to repo1 and another one to repo2
   240  	artifactoryCli.Exec("upload", filePath, tests.Repo1+"/path/a1.in")
   241  	artifactoryCli.Exec("upload", filePath, tests.Repo2+"/path/a2.in")
   242  
   243  	specFile, err := tests.CreateSpec(tests.DownloadWildcardRepo)
   244  	assert.NoError(t, err)
   245  
   246  	// Verify the 2 files exist using `*` in the repository name
   247  	verifyExistInArtifactory(tests.GetDownloadWildcardRepo(), specFile, t)
   248  
   249  	// Download the 2 files with `*` in the repository name
   250  	artifactoryCli.Exec("dl", "--spec="+specFile)
   251  	paths, err := fileutils.ListFilesRecursiveWalkIntoDirSymlink(tests.Out, false)
   252  	assert.NoError(t, err)
   253  	tests.VerifyExistLocally([]string{filepath.Join(tests.Out, "a1.in"), filepath.Join(tests.Out, "a2.in")}, paths, t)
   254  	cleanArtifactoryTest()
   255  }
   256  
   257  func TestArtifactoryCopySingleFileNonFlat(t *testing.T) {
   258  	initArtifactoryTest(t)
   259  	var filePath = getSpecialCharFilePath()
   260  
   261  	artifactoryCli.Exec("upload", filePath, tests.Repo1+"/path/")
   262  	artifactoryCli.Exec("cp", tests.Repo1+"/path/a1.in", tests.Repo2)
   263  	searchPath, err := tests.CreateSpec(tests.SearchRepo2)
   264  	assert.NoError(t, err)
   265  	verifyExistInArtifactory(tests.GetSingleFileCopy(), searchPath, t)
   266  	cleanArtifactoryTest()
   267  }
   268  
   269  func TestAqlFindingItemOnRoot(t *testing.T) {
   270  	initArtifactoryTest(t)
   271  	var filePath = getSpecialCharFilePath()
   272  
   273  	artifactoryCli.Exec("upload", filePath, tests.Repo1+"/path/inner/")
   274  	artifactoryCli.Exec("upload", filePath, tests.Repo1+"/someFile", "--flat=true")
   275  	artifactoryCli.Exec("cp", tests.Repo1+"/*", tests.Repo2)
   276  	searchPath, err := tests.CreateSpec(tests.SearchRepo2)
   277  	assert.NoError(t, err)
   278  	verifyExistInArtifactory(tests.GetAnyItemCopy(), searchPath, t)
   279  	artifactoryCli.Exec("del", tests.Repo2+"/*")
   280  	artifactoryCli.Exec("del", tests.Repo1+"/*")
   281  	artifactoryCli.Exec("upload", filePath, tests.Repo1+"/path/")
   282  	artifactoryCli.Exec("upload", filePath, tests.Repo1+"/someFile", "--flat=true")
   283  	artifactoryCli.Exec("cp", tests.Repo1+"/*/", tests.Repo2)
   284  	verifyExistInArtifactory(tests.GetSingleFileCopy(), searchPath, t)
   285  	cleanArtifactoryTest()
   286  }
   287  
   288  func TestExitCode(t *testing.T) {
   289  	initArtifactoryTest(t)
   290  
   291  	err := artifactoryCli.Exec("upload", "DummyText", tests.Repo1, "--fail-no-op=true")
   292  	checkExitCode(t, cliutils.ExitCodeError, err)
   293  	err = artifactoryCli.Exec("upload", path.Join("testsdata", "a", "a1.in"), "tests.Repo1")
   294  	checkExitCode(t, cliutils.ExitCodeError, err)
   295  	err = artifactoryCli.Exec("upload", "testsdata/a/(*.dummyExt)", tests.Repo1+"/{1}.in", "--fail-no-op=true")
   296  	checkExitCode(t, cliutils.ExitCodeFailNoOp, err)
   297  
   298  	err = artifactoryCli.Exec("dl", "DummyFolder", "--fail-no-op=true")
   299  	checkExitCode(t, cliutils.ExitCodeFailNoOp, err)
   300  
   301  	//upload dummy file inorder to test move & copy
   302  	artifactoryCli.Exec("upload", path.Join("testsdata", "a", "a1.in"), tests.Repo1)
   303  	err = artifactoryCli.Exec("move", tests.Repo1, "DummyTargetPath")
   304  	checkExitCode(t, cliutils.ExitCodeError, err)
   305  	err = artifactoryCli.Exec("move", "DummyText", tests.Repo1, "--fail-no-op=true")
   306  	checkExitCode(t, cliutils.ExitCodeFailNoOp, err)
   307  
   308  	err = artifactoryCli.Exec("copy", tests.Repo1, "DummyTargetPath")
   309  	checkExitCode(t, cliutils.ExitCodeError, err)
   310  	err = artifactoryCli.Exec("copy", "DummyText", tests.Repo1, "--fail-no-op=true")
   311  	checkExitCode(t, cliutils.ExitCodeFailNoOp, err)
   312  
   313  	err = artifactoryCli.Exec("delete", "DummyText", "--fail-no-op=true")
   314  	checkExitCode(t, cliutils.ExitCodeFailNoOp, err)
   315  
   316  	err = artifactoryCli.Exec("s", "DummyText", "--fail-no-op=true")
   317  	checkExitCode(t, cliutils.ExitCodeFailNoOp, err)
   318  
   319  	err = artifactoryCli.Exec("sp", "DummyText", "prop=val;key=value", "--fail-no-op=true")
   320  	checkExitCode(t, cliutils.ExitCodeFailNoOp, err)
   321  
   322  	err = artifactoryCli.Exec("delp", "DummyText", "prop=val;key=value", "--fail-no-op=true")
   323  	checkExitCode(t, cliutils.ExitCodeFailNoOp, err)
   324  
   325  	cleanArtifactoryTest()
   326  }
   327  
   328  func checkExitCode(t *testing.T, expected cliutils.ExitCode, er error) {
   329  	switch underlyingType := er.(type) {
   330  	case cliutils.CliError:
   331  		assert.Equal(t, expected, underlyingType.ExitCode)
   332  	default:
   333  		assert.Fail(t, "Exit code expected error code %v, got %v", expected.Code, er)
   334  	}
   335  }
   336  func TestArtifactoryDirectoryCopy(t *testing.T) {
   337  	initArtifactoryTest(t)
   338  	var filePath = getSpecialCharFilePath()
   339  
   340  	artifactoryCli.Exec("upload", filePath, tests.Repo1+"/path/")
   341  	artifactoryCli.Exec("cp", tests.Repo1+"/path/", tests.Repo2)
   342  	searchPath, err := tests.CreateSpec(tests.SearchRepo2)
   343  	assert.NoError(t, err)
   344  	verifyExistInArtifactory(tests.GetSingleFileCopy(), searchPath, t)
   345  	cleanArtifactoryTest()
   346  }
   347  
   348  func TestArtifactoryDirectoryCopyUsingWildcard(t *testing.T) {
   349  	initArtifactoryTest(t)
   350  	var filePath = getSpecialCharFilePath()
   351  
   352  	artifactoryCli.Exec("upload", filePath, tests.Repo1+"/path/")
   353  	artifactoryCli.Exec("cp", tests.Repo1+"/*/", tests.Repo2)
   354  	searchPath, err := tests.CreateSpec(tests.SearchRepo2)
   355  	assert.NoError(t, err)
   356  	verifyExistInArtifactory(tests.GetSingleFileCopy(), searchPath, t)
   357  	cleanArtifactoryTest()
   358  }
   359  
   360  func TestArtifactoryCopyFilesNameWithParentheses(t *testing.T) {
   361  	initArtifactoryTest(t)
   362  
   363  	artifactoryCli.Exec("upload", "testsdata/b/*", tests.Repo1, "--flat=false")
   364  	artifactoryCli.Exec("cp", tests.Repo1+"/testsdata/b/(/(.in", tests.Repo2)
   365  	artifactoryCli.Exec("cp", tests.Repo1+"/testsdata/b/(b/(b.in", tests.Repo2)
   366  	artifactoryCli.Exec("cp", tests.Repo1+"/testsdata/b/b(/b(.in", tests.Repo2)
   367  	artifactoryCli.Exec("cp", tests.Repo1+"/testsdata/b/b)/b).in", tests.Repo2)
   368  	artifactoryCli.Exec("cp", tests.Repo1+"/testsdata/b/(b)/(b).in", tests.Repo2)
   369  	artifactoryCli.Exec("cp", tests.Repo1+"/testsdata/b/)b/)b.in", tests.Repo2)
   370  	artifactoryCli.Exec("cp", tests.Repo1+"/testsdata/b/)b)/)b).in", tests.Repo2)
   371  	artifactoryCli.Exec("cp", tests.Repo1+"/testsdata/b/(b/(b.in", tests.Repo2+"/()/", "--flat=true")
   372  	artifactoryCli.Exec("cp", tests.Repo1+"/testsdata/b/(b)/(b).in", tests.Repo2+"/()/")
   373  	artifactoryCli.Exec("cp", tests.Repo1+"/testsdata/b/b(/b(.in", tests.Repo2+"/(/", "--flat=true")
   374  	artifactoryCli.Exec("cp", tests.Repo1+"/testsdata/b/(/(*.in)", tests.Repo2+"/c/{1}.zip", "--flat=true")
   375  	artifactoryCli.Exec("cp", tests.Repo1+"/testsdata/b/(/(*.in)", tests.Repo2+"/(/{1}.zip")
   376  	artifactoryCli.Exec("cp", tests.Repo1+"/testsdata/b/b(/(b*.in)", tests.Repo2+"/(/{1}-up", "--flat=true")
   377  	artifactoryCli.Exec("cp", tests.Repo1+"/testsdata/b/b(/(*).(*)", tests.Repo2+"/(/{2}-{1}", "--flat=true")
   378  
   379  	searchPath, err := tests.CreateSpec(tests.SearchRepo2)
   380  	assert.NoError(t, err)
   381  	verifyExistInArtifactory(tests.GetCopyFileNameWithParentheses(), searchPath, t)
   382  
   383  	cleanArtifactoryTest()
   384  }
   385  
   386  func TestArtifactoryUploadFilesNameWithParenthesis(t *testing.T) {
   387  	initArtifactoryTest(t)
   388  
   389  	specFile, err := tests.CreateSpec(tests.UploadFileWithParenthesesSpec)
   390  	assert.NoError(t, err)
   391  	artifactoryCli.Exec("upload", "--spec="+specFile)
   392  
   393  	searchPath, err := tests.CreateSpec(tests.SearchAllRepo1)
   394  	assert.NoError(t, err)
   395  	verifyExistInArtifactory(tests.GetUploadFileNameWithParentheses(), searchPath, t)
   396  
   397  	cleanArtifactoryTest()
   398  }
   399  
   400  func TestArtifactoryDownloadFilesNameWithParenthesis(t *testing.T) {
   401  	initArtifactoryTest(t)
   402  
   403  	artifactoryCli.Exec("upload", "testsdata/b/*", tests.Repo1, "--flat=false")
   404  	artifactoryCli.Exec("download", path.Join(tests.Repo1), tests.Out+"/")
   405  
   406  	paths, err := fileutils.ListFilesRecursiveWalkIntoDirSymlink(tests.Out, false)
   407  	assert.NoError(t, err)
   408  	tests.VerifyExistLocally(tests.GetFileWithParenthesesDownload(), paths, t)
   409  
   410  	cleanArtifactoryTest()
   411  }
   412  
   413  func TestArtifactoryDirectoryCopyUsingWildcardFlat(t *testing.T) {
   414  	initArtifactoryTest(t)
   415  	var filePath = getSpecialCharFilePath()
   416  
   417  	artifactoryCli.Exec("upload", filePath, tests.Repo1+"/path/inner/")
   418  	artifactoryCli.Exec("cp", tests.Repo1+"/path/inner", tests.Repo2, "--flat=true")
   419  	searchPath, err := tests.CreateSpec(tests.SearchRepo2)
   420  	assert.NoError(t, err)
   421  
   422  	verifyExistInArtifactory(tests.GetSingleDirectoryCopyFlat(), searchPath, t)
   423  	cleanArtifactoryTest()
   424  }
   425  
   426  func TestArtifactoryCopyPathsTwice(t *testing.T) {
   427  	initArtifactoryTest(t)
   428  	var filePath = getSpecialCharFilePath()
   429  	artifactoryCli.Exec("upload", filePath, tests.Repo1+"/path/inner/")
   430  
   431  	log.Info("Copy Folder to root twice")
   432  	artifactoryCli.Exec("cp", tests.Repo1+"/path", tests.Repo2)
   433  	searchPath, err := tests.CreateSpec(tests.SearchRepo2)
   434  	assert.NoError(t, err)
   435  
   436  	verifyExistInArtifactory(tests.GetSingleFileCopyFullPath(), searchPath, t)
   437  	artifactoryCli.Exec("cp", tests.Repo1+"/path", tests.Repo2)
   438  	verifyExistInArtifactory(tests.GetSingleFileCopyFullPath(), searchPath, t)
   439  	artifactoryCli.Exec("del", tests.Repo2)
   440  
   441  	log.Info("Copy to from repo1/path to repo2/path twice")
   442  	artifactoryCli.Exec("cp", tests.Repo1+"/path", tests.Repo2+"/path")
   443  	verifyExistInArtifactory(tests.GetSingleFileCopyFullPath(), searchPath, t)
   444  	artifactoryCli.Exec("cp", tests.Repo1+"/path", tests.Repo2+"/path")
   445  	verifyExistInArtifactory(tests.GetFolderCopyTwice(), searchPath, t)
   446  	artifactoryCli.Exec("del", tests.Repo2)
   447  
   448  	log.Info("Copy to from repo1/path/ to repo2/path/ twice")
   449  	artifactoryCli.Exec("cp", tests.Repo1+"/path/", tests.Repo2+"/path/")
   450  	verifyExistInArtifactory(tests.GetSingleInnerFileCopyFullPath(), searchPath, t)
   451  	artifactoryCli.Exec("cp", tests.Repo1+"/path/", tests.Repo2+"/path/")
   452  	verifyExistInArtifactory(tests.GetSingleInnerFileCopyFullPath(), searchPath, t)
   453  	artifactoryCli.Exec("del", tests.Repo2)
   454  
   455  	log.Info("Copy to from repo1/path/ to repo2/path/ twice")
   456  	artifactoryCli.Exec("cp", tests.Repo1+"/path", tests.Repo2+"/path/")
   457  	verifyExistInArtifactory(tests.GetFolderCopyIntoFolder(), searchPath, t)
   458  	artifactoryCli.Exec("cp", tests.Repo1+"/path", tests.Repo2+"/path/")
   459  	verifyExistInArtifactory(tests.GetFolderCopyIntoFolder(), searchPath, t)
   460  	artifactoryCli.Exec("del", tests.Repo2)
   461  
   462  	cleanArtifactoryTest()
   463  }
   464  
   465  func TestArtifactoryDirectoryCopyPatternEndsWithSlash(t *testing.T) {
   466  	initArtifactoryTest(t)
   467  	var filePath = getSpecialCharFilePath()
   468  
   469  	artifactoryCli.Exec("upload", filePath, tests.Repo1+"/path/inner/")
   470  	artifactoryCli.Exec("cp", tests.Repo1+"/path/", tests.Repo2, "--flat=true")
   471  	searchPath, err := tests.CreateSpec(tests.SearchRepo2)
   472  	assert.NoError(t, err)
   473  	verifyExistInArtifactory(tests.GetAnyItemCopyUsingSpec(), searchPath, t)
   474  	cleanArtifactoryTest()
   475  }
   476  
   477  func TestArtifactoryCopyAnyItemUsingWildcardFlat(t *testing.T) {
   478  	initArtifactoryTest(t)
   479  	var filePath = getSpecialCharFilePath()
   480  
   481  	artifactoryCli.Exec("upload", filePath, tests.Repo1+"/path/inner/")
   482  	artifactoryCli.Exec("upload", filePath, tests.Repo1+"/someFile", "--flat=true")
   483  	artifactoryCli.Exec("cp", tests.Repo1+"/*", tests.Repo2)
   484  	searchPath, err := tests.CreateSpec(tests.SearchRepo2)
   485  	assert.NoError(t, err)
   486  
   487  	verifyExistInArtifactory(tests.GetAnyItemCopy(), searchPath, t)
   488  	cleanArtifactoryTest()
   489  }
   490  
   491  func TestArtifactoryCopyAnyItemRecursive(t *testing.T) {
   492  	initArtifactoryTest(t)
   493  	var filePath = getSpecialCharFilePath()
   494  
   495  	artifactoryCli.Exec("upload", filePath, tests.Repo1+"/a/b/")
   496  	artifactoryCli.Exec("upload", filePath, tests.Repo1+"/aFile", "--flat=true")
   497  	artifactoryCli.Exec("cp", tests.Repo1+"/a*", tests.Repo2, "--recursive=true")
   498  	searchPath, err := tests.CreateSpec(tests.SearchRepo2)
   499  	assert.NoError(t, err)
   500  	verifyExistInArtifactory(tests.GetAnyItemCopyRecursive(), searchPath, t)
   501  	cleanArtifactoryTest()
   502  }
   503  
   504  func TestArtifactoryCopyAndRenameFolder(t *testing.T) {
   505  	initArtifactoryTest(t)
   506  	var filePath = getSpecialCharFilePath()
   507  
   508  	artifactoryCli.Exec("upload", filePath, tests.Repo1+"/path/inner/")
   509  	artifactoryCli.Exec("cp", tests.Repo1+"/*", tests.Repo2+"/newPath")
   510  	searchPath, err := tests.CreateSpec(tests.SearchRepo2)
   511  	assert.NoError(t, err)
   512  	verifyExistInArtifactory(tests.GetCopyFolderRename(), searchPath, t)
   513  	cleanArtifactoryTest()
   514  }
   515  
   516  func TestArtifactoryCopyAnyItemUsingSpec(t *testing.T) {
   517  	initArtifactoryTest(t)
   518  	var filePath = getSpecialCharFilePath()
   519  
   520  	specFile, err := tests.CreateSpec(tests.CopyItemsSpec)
   521  	assert.NoError(t, err)
   522  	searchPath, err := tests.CreateSpec(tests.SearchRepo2)
   523  	assert.NoError(t, err)
   524  	artifactoryCli.Exec("upload", filePath, tests.Repo1+"/path/inner/")
   525  	artifactoryCli.Exec("upload", filePath, tests.Repo1+"/someFile", "--flat=true")
   526  	artifactoryCli.Exec("cp", "--spec="+specFile)
   527  	verifyExistInArtifactory(tests.GetAnyItemCopyUsingSpec(), searchPath, t)
   528  	cleanArtifactoryTest()
   529  }
   530  
   531  func getSpecialCharFilePath() string {
   532  	return "testsdata/a$+~&^a#/a*"
   533  }
   534  
   535  func TestArtifactoryCopyNoSpec(t *testing.T) {
   536  	testCopyMoveNoSpec("cp", tests.GetBuildBeforeCopyExpected(), tests.GetBuildCopyExpected(), t)
   537  }
   538  
   539  func TestArtifactoryCopyExcludeByCli(t *testing.T) {
   540  	initArtifactoryTest(t)
   541  
   542  	// Upload files
   543  	specFileA, err := tests.CreateSpec(tests.SplitUploadSpecA)
   544  	assert.NoError(t, err)
   545  	specFileB, err := tests.CreateSpec(tests.SplitUploadSpecB)
   546  	assert.NoError(t, err)
   547  	artifactoryCli.Exec("upload", "--spec="+specFileA)
   548  	artifactoryCli.Exec("upload", "--spec="+specFileB)
   549  
   550  	// Copy by pattern
   551  	artifactoryCli.Exec("cp", tests.Repo1+"/data/ "+tests.Repo2+"/", "--exclude-patterns=*b*;*c*")
   552  
   553  	// Validate files are moved by build number
   554  	cpMvDlByBuildAssertSpec, err := tests.CreateSpec(tests.CpMvDlByBuildAssertSpec)
   555  	assert.NoError(t, err)
   556  	verifyExistInArtifactory(tests.GetBuildCopyExclude(), cpMvDlByBuildAssertSpec, t)
   557  
   558  	// Cleanup
   559  	cleanArtifactoryTest()
   560  }
   561  
   562  func TestArtifactoryCopyExcludeBySpec(t *testing.T) {
   563  	initArtifactoryTest(t)
   564  
   565  	// Upload files
   566  	specFileA, err := tests.CreateSpec(tests.SplitUploadSpecA)
   567  	assert.NoError(t, err)
   568  	specFileB, err := tests.CreateSpec(tests.SplitUploadSpecB)
   569  	assert.NoError(t, err)
   570  	artifactoryCli.Exec("upload", "--spec="+specFileA)
   571  	artifactoryCli.Exec("upload", "--spec="+specFileB)
   572  
   573  	// Copy by spec
   574  	specFile, err := tests.CreateSpec(tests.MoveCopySpecExclude)
   575  	assert.NoError(t, err)
   576  	artifactoryCli.Exec("cp", "--spec="+specFile)
   577  	cpMvDlByBuildAssertSpec, err := tests.CreateSpec(tests.CpMvDlByBuildAssertSpec)
   578  	assert.NoError(t, err)
   579  
   580  	// Validate files are moved by build number
   581  	verifyExistInArtifactory(tests.GetBuildCopyExclude(), cpMvDlByBuildAssertSpec, t)
   582  
   583  	// Cleanup
   584  	cleanArtifactoryTest()
   585  }
   586  
   587  func TestArtifactoryUploadDebian(t *testing.T) {
   588  	initArtifactoryTest(t)
   589  	specFile, err := tests.CreateSpec(tests.DebianUploadSpec)
   590  	assert.NoError(t, err)
   591  	artifactoryCli.Exec("upload", "--spec="+specFile, "--deb=bionic/main/i386")
   592  	verifyExistInArtifactoryByProps(tests.GetUploadDebianExpected(), tests.DebianRepo+"/*", "deb.distribution=bionic;deb.component=main;deb.architecture=i386", t)
   593  	artifactoryCli.Exec("upload", "--spec="+specFile, "--deb=cosmic/main\\/18.10/amd64")
   594  	verifyExistInArtifactoryByProps(tests.GetUploadDebianExpected(), tests.DebianRepo+"/*", "deb.distribution=cosmic;deb.component=main/18.10;deb.architecture=amd64", t)
   595  	cleanArtifactoryTest()
   596  }
   597  
   598  func TestArtifactoryUploadAndExplode(t *testing.T) {
   599  	initArtifactoryTest(t)
   600  	artifactoryCli.Exec("upload", filepath.Join("testsdata", "archives", "a.zip"), tests.Repo1, "--explode=true")
   601  	searchFilePath, err := tests.CreateSpec(tests.SearchRepo1ByInSuffix)
   602  	assert.NoError(t, err)
   603  	verifyExistInArtifactory(tests.GetExplodeUploadExpectedRepo1(), searchFilePath, t)
   604  	cleanArtifactoryTest()
   605  }
   606  
   607  func TestArtifactoryUploadAndSyncDelete(t *testing.T) {
   608  	initArtifactoryTest(t)
   609  	// Upload all testdata/a/
   610  	artifactoryCli.Exec("upload", path.Join("testsdata", "a", "*"), tests.Repo1+"/syncDir/", "--flat=false")
   611  	searchFilePath, err := tests.CreateSpec(tests.SearchAllRepo1)
   612  	assert.NoError(t, err)
   613  	verifyExistInArtifactory(tests.GetUploadExpectedRepo1SyncDeleteStep1(), searchFilePath, t)
   614  	// Upload testdata/a/b/*1.in and sync syncDir/testdata/a/b/
   615  	artifactoryCli.Exec("upload", path.Join("testsdata", "a", "b", "*1.in"), tests.Repo1+"/syncDir/", "--sync-deletes="+tests.Repo1+"/syncDir/testsdata/a/b/", "--flat=false")
   616  	searchFilePath, err = tests.CreateSpec(tests.SearchAllRepo1)
   617  	assert.NoError(t, err)
   618  	verifyExistInArtifactory(tests.GetUploadExpectedRepo1SyncDeleteStep2(), searchFilePath, t)
   619  	// Upload testdata/archives/* and sync syncDir/
   620  	artifactoryCli.Exec("upload", path.Join("testsdata", "archives", "*"), tests.Repo1+"/syncDir/", "--sync-deletes="+tests.Repo1+"/syncDir/")
   621  	searchFilePath, err = tests.CreateSpec(tests.SearchAllRepo1)
   622  	assert.NoError(t, err)
   623  	verifyExistInArtifactory(tests.GetUploadExpectedRepo1SyncDeleteStep3(), searchFilePath, t)
   624  
   625  	cleanArtifactoryTest()
   626  }
   627  
   628  func TestArtifactoryDownloadAndExplode(t *testing.T) {
   629  	initArtifactoryTest(t)
   630  	err := fileutils.CreateDirIfNotExist(tests.Out)
   631  	assert.NoError(t, err)
   632  	randFile, err := io.CreateRandFile(filepath.Join(tests.Out, "randFile"), 100000)
   633  	assert.NoError(t, err)
   634  
   635  	err = archiver.TarGz.Make(filepath.Join(tests.Out, "concurrent.tar.gz"), []string{randFile.Name()})
   636  	assert.NoError(t, err)
   637  	err = archiver.Tar.Make(filepath.Join(tests.Out, "bulk.tar"), []string{randFile.Name()})
   638  	assert.NoError(t, err)
   639  	err = archiver.Zip.Make(filepath.Join(tests.Out, "zipFile.zip"), []string{randFile.Name()})
   640  	assert.NoError(t, err)
   641  	artifactoryCli.Exec("upload", tests.Out+"/*", tests.Repo1, "--flat=true")
   642  	randFile.File.Close()
   643  	os.RemoveAll(tests.Out)
   644  	artifactoryCli.Exec("download", path.Join(tests.Repo1, "randFile"), tests.Out+"/", "--explode=true")
   645  	artifactoryCli.Exec("download", path.Join(tests.Repo1, "concurrent.tar.gz"), tests.Out+"/", "--explode=false", "--min-split=50")
   646  	artifactoryCli.Exec("download", path.Join(tests.Repo1, "bulk.tar"), tests.Out+"/", "--explode=true")
   647  	artifactoryCli.Exec("download", path.Join(tests.Repo1, "zipFile.zip"), tests.Out+"/", "--explode=true", "--min-split=50")
   648  	artifactoryCli.Exec("download", path.Join(tests.Repo1, "zipFile.zip"), tests.Out+"/", "--explode=true")
   649  
   650  	paths, err := fileutils.ListFilesRecursiveWalkIntoDirSymlink(tests.Out, false)
   651  	assert.NoError(t, err)
   652  	tests.VerifyExistLocally(tests.GetExtractedDownload(), paths, t)
   653  
   654  	cleanArtifactoryTest()
   655  }
   656  
   657  func TestArtifactoryDownloadAndSyncDeletes(t *testing.T) {
   658  	initArtifactoryTest(t)
   659  
   660  	outDirPath := tests.Out + string(os.PathSeparator)
   661  	// Upload all testdata/a/ to repo1/syncDir/
   662  	artifactoryCli.Exec("upload", path.Join("testsdata", "a", "*"), tests.Repo1+"/syncDir/", "--flat=false")
   663  	searchFilePath, err := tests.CreateSpec(tests.SearchAllRepo1)
   664  	assert.NoError(t, err)
   665  	verifyExistInArtifactory(tests.GetUploadExpectedRepo1SyncDeleteStep1(), searchFilePath, t)
   666  
   667  	// Download repo1/syncDir/ to out/
   668  	artifactoryCli.Exec("download", tests.Repo1+"/syncDir/", tests.Out+"/")
   669  	paths, err := fileutils.ListFilesRecursiveWalkIntoDirSymlink(tests.Out, false)
   670  	assert.NoError(t, err)
   671  	tests.VerifyExistLocally(tests.GetExpectedSyncDeletesDownloadStep2(), paths, t)
   672  
   673  	// Download repo1/syncDir/ to out/ with flat=true and sync out/
   674  	artifactoryCli.Exec("download", tests.Repo1+"/syncDir/", outDirPath, "--flat=true", "--sync-deletes="+outDirPath)
   675  	paths, err = fileutils.ListFilesRecursiveWalkIntoDirSymlink(tests.Out, false)
   676  	assert.NoError(t, err)
   677  	checkSyncedDirContent(tests.GetExpectedSyncDeletesDownloadStep3(), paths, t)
   678  
   679  	// Download all files ended with 2.in from repo1/syncDir/ to out/ and sync out/
   680  	artifactoryCli.Exec("download", tests.Repo1+"/syncDir/*2.in", outDirPath, "--flat=true", "--sync-deletes="+outDirPath)
   681  	paths, err = fileutils.ListFilesRecursiveWalkIntoDirSymlink(tests.Out, false)
   682  	assert.NoError(t, err)
   683  	checkSyncedDirContent(tests.GetExpectedSyncDeletesDownloadStep4(), paths, t)
   684  
   685  	// Download repo1/syncDir/ to out/, exclude the pattern "*c*.in" and sync out/
   686  	artifactoryCli.Exec("download", tests.Repo1+"/syncDir/", outDirPath, "--sync-deletes="+outDirPath+"syncDir"+string(os.PathSeparator), "--exclude-patterns=syncDir/testsdata/*c*in")
   687  	paths, err = fileutils.ListFilesRecursiveWalkIntoDirSymlink(tests.Out, false)
   688  	assert.NoError(t, err)
   689  	checkSyncedDirContent(tests.GetSyncExpectedDeletesDownloadStep5(), paths, t)
   690  
   691  	// Delete all files from repo1/syncDir/
   692  	artifactoryCli.Exec("delete", tests.Repo1+"/syncDir/")
   693  	searchFilePath, err = tests.CreateSpec(tests.SearchAllRepo1)
   694  	assert.NoError(t, err)
   695  	verifyDoesntExistInArtifactory(searchFilePath, t)
   696  
   697  	// Upload all testdata/archives/ to repo1/syncDir/
   698  	artifactoryCli.Exec("upload", path.Join("testsdata", "archives", "*"), tests.Repo1+"/syncDir/", "--flat=false")
   699  	searchFilePath, err = tests.CreateSpec(tests.SearchAllRepo1)
   700  	assert.NoError(t, err)
   701  	verifyExistInArtifactory(tests.GetSyncExpectedDeletesDownloadStep6(), searchFilePath, t)
   702  
   703  	// Download repo1/syncDir/ to out/ and sync out/
   704  	artifactoryCli.Exec("download", tests.Repo1+"/syncDir/", outDirPath, "--sync-deletes="+outDirPath+"syncDir"+string(os.PathSeparator))
   705  	paths, err = fileutils.ListFilesRecursiveWalkIntoDirSymlink(tests.Out, false)
   706  	assert.NoError(t, err)
   707  	checkSyncedDirContent(tests.GetSyncExpectedDeletesDownloadStep7(), paths, t)
   708  
   709  	cleanArtifactoryTest()
   710  }
   711  
   712  // After syncDeletes we must make sure that the content of the synced directory contains the last operation result only.
   713  // Therefore we verify that there are no other files in the synced directory, other than the list of the expected files.
   714  func checkSyncedDirContent(expected, actual []string, t *testing.T) {
   715  	// Check if all expected files are actually exist
   716  	tests.VerifyExistLocally(expected, actual, t)
   717  	// Check if all the existing files were expected
   718  	err := isExclusivelyExistLocally(expected, actual)
   719  	assert.NoError(t, err)
   720  }
   721  
   722  // 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.
   723  // Since the "actual" list contains paths of both directories and files, for each element in the "actual" list:
   724  // Check if the path equals to an existing file (for a file) OR
   725  // if the path is a prefix of some path of an existing file (for a dir).
   726  func isExclusivelyExistLocally(expected, actual []string) error {
   727  	for _, v := range actual {
   728  		for i, r := range expected {
   729  			if strings.HasPrefix(r, v) || v == r {
   730  				break
   731  			}
   732  			if i == len(actual)-1 {
   733  				return errors.New("Should not have : " + v)
   734  			}
   735  		}
   736  	}
   737  	return nil
   738  }
   739  
   740  // Test self-signed certificates with Artifactory. For the test, we set up a reverse proxy server.
   741  func TestArtifactorySelfSignedCert(t *testing.T) {
   742  	initArtifactoryTest(t)
   743  	tempDirPath, err := ioutil.TempDir("", "jfrog.cli.test.")
   744  	err = errorutils.CheckError(err)
   745  	assert.NoError(t, err)
   746  	defer os.RemoveAll(tempDirPath)
   747  	os.Setenv(cliutils.HomeDir, tempDirPath)
   748  	os.Setenv(tests.HttpsProxyEnvVar, "1024")
   749  	go cliproxy.StartLocalReverseHttpProxy(artifactoryDetails.Url, false)
   750  
   751  	// The two certificate files are created by the reverse proxy on startup in the current directory.
   752  	defer os.Remove(certificate.KEY_FILE)
   753  	defer os.Remove(certificate.CERT_FILE)
   754  	// Let's wait for the reverse proxy to start up.
   755  	err = checkIfServerIsUp(cliproxy.GetProxyHttpsPort(), "https", false)
   756  	assert.NoError(t, err)
   757  
   758  	fileSpec := spec.NewBuilder().Pattern(tests.Repo1 + "/*.zip").Recursive(true).BuildSpec()
   759  	assert.NoError(t, err)
   760  	parsedUrl, err := url.Parse(artifactoryDetails.Url)
   761  	artifactoryDetails.Url = "https://127.0.0.1:" + cliproxy.GetProxyHttpsPort() + parsedUrl.RequestURI()
   762  
   763  	// The server is using self-signed certificates
   764  	// Without loading the certificates (or skipping verification) we expect all actions to fail due to error: "x509: certificate signed by unknown authority"
   765  	searchCmd := generic.NewSearchCommand()
   766  	searchCmd.SetRtDetails(artifactoryDetails).SetSpec(fileSpec)
   767  	err = searchCmd.Search()
   768  	_, isUrlErr := err.(*url.Error)
   769  	assert.True(t, isUrlErr, "Expected a connection failure, since reverse proxy didn't load self-signed-certs. Connection however is successful", err)
   770  
   771  	// Set insecureTls to true and run again. We expect the command to succeed.
   772  	artifactoryDetails.InsecureTls = true
   773  	searchCmd = generic.NewSearchCommand()
   774  	searchCmd.SetRtDetails(artifactoryDetails).SetSpec(fileSpec)
   775  	err = searchCmd.Search()
   776  	assert.NoError(t, err)
   777  
   778  	// Set insecureTls back to false.
   779  	// Copy the server certificates to the CLI security dir and run again. We expect the command to succeed.
   780  	artifactoryDetails.InsecureTls = false
   781  	securityDirPath, err := cliutils.GetJfrogSecurityDir()
   782  	assert.NoError(t, err)
   783  	err = fileutils.CopyFile(securityDirPath, certificate.KEY_FILE)
   784  	assert.NoError(t, err)
   785  	err = fileutils.CopyFile(securityDirPath, certificate.CERT_FILE)
   786  	assert.NoError(t, err)
   787  	searchCmd = generic.NewSearchCommand()
   788  	searchCmd.SetRtDetails(artifactoryDetails).SetSpec(fileSpec)
   789  	err = searchCmd.Search()
   790  	assert.NoError(t, err)
   791  
   792  	artifactoryDetails.Url = artAuth.GetUrl()
   793  	cleanArtifactoryTest()
   794  }
   795  
   796  // Test client certificates with Artifactory. For the test, we set up a reverse proxy server.
   797  func TestArtifactoryClientCert(t *testing.T) {
   798  	initArtifactoryTest(t)
   799  	tempDirPath, err := ioutil.TempDir("", "jfrog.cli.test.")
   800  	err = errorutils.CheckError(err)
   801  	assert.NoError(t, err)
   802  	defer os.RemoveAll(tempDirPath)
   803  	os.Setenv(cliutils.HomeDir, tempDirPath)
   804  	os.Setenv(tests.HttpsProxyEnvVar, "1025")
   805  	go cliproxy.StartLocalReverseHttpProxy(artifactoryDetails.Url, true)
   806  
   807  	// The two certificate files are created by the reverse proxy on startup in the current directory.
   808  	defer os.Remove(certificate.KEY_FILE)
   809  	defer os.Remove(certificate.CERT_FILE)
   810  	// Let's wait for the reverse proxy to start up.
   811  	err = checkIfServerIsUp(cliproxy.GetProxyHttpsPort(), "https", true)
   812  	assert.NoError(t, err)
   813  
   814  	fileSpec := spec.NewBuilder().Pattern(tests.Repo1 + "/*.zip").Recursive(true).BuildSpec()
   815  	assert.NoError(t, err)
   816  	parsedUrl, err := url.Parse(artifactoryDetails.Url)
   817  	artifactoryDetails.Url = "https://127.0.0.1:" + cliproxy.GetProxyHttpsPort() + parsedUrl.RequestURI()
   818  	artifactoryDetails.InsecureTls = true
   819  
   820  	// The server is requiring client certificates
   821  	// Without loading a valid client certificate, we expect all actions to fail due to error: "tls: bad certificate"
   822  	searchCmd := generic.NewSearchCommand()
   823  	searchCmd.SetRtDetails(artifactoryDetails).SetSpec(fileSpec)
   824  	err = searchCmd.Search()
   825  	_, isUrlErr := err.(*url.Error)
   826  	assert.True(t, isUrlErr, "Expected a connection failure, since client did not provide a client certificate. Connection however is successful")
   827  
   828  	// Inject client certificates, we expect the search to succeed
   829  	artifactoryDetails.ClientCertPath = certificate.CERT_FILE
   830  	artifactoryDetails.ClientCertKeyPath = certificate.KEY_FILE
   831  
   832  	searchCmd = generic.NewSearchCommand()
   833  	searchCmd.SetRtDetails(artifactoryDetails).SetSpec(fileSpec)
   834  	err = searchCmd.Search()
   835  	assert.NoError(t, err)
   836  
   837  	artifactoryDetails.Url = artAuth.GetUrl()
   838  	artifactoryDetails.InsecureTls = false
   839  	artifactoryDetails.ClientCertPath = ""
   840  	artifactoryDetails.ClientCertKeyPath = ""
   841  	cleanArtifactoryTest()
   842  }
   843  
   844  func getExternalIP() (string, error) {
   845  	ifaces, err := net.Interfaces()
   846  	if err != nil {
   847  		return "", err
   848  	}
   849  	for _, iface := range ifaces {
   850  		if iface.Flags&net.FlagUp == 0 {
   851  			continue // interface down
   852  		}
   853  		if iface.Flags&net.FlagLoopback != 0 {
   854  			continue // loopback interface
   855  		}
   856  		addrs, err := iface.Addrs()
   857  		if err != nil {
   858  			return "", err
   859  		}
   860  		for _, addr := range addrs {
   861  			var ip net.IP
   862  			switch v := addr.(type) {
   863  			case *net.IPNet:
   864  				ip = v.IP
   865  			case *net.IPAddr:
   866  				ip = v.IP
   867  			}
   868  			if ip == nil || ip.IsLoopback() {
   869  				continue
   870  			}
   871  			ip = ip.To4()
   872  			if ip == nil {
   873  				continue // not an ipv4 address
   874  			}
   875  			return ip.String(), nil
   876  		}
   877  	}
   878  	return "", errors.New("check connection to the network")
   879  }
   880  
   881  // Due the fact that go read the HTTP_PROXY and the HTTPS_PROXY
   882  // argument only once we can't set the env var for specific test.
   883  // We need to start a new process with the env var set to the value we want.
   884  // We decide which var to set by the rtUrl scheme.
   885  func TestArtifactoryProxy(t *testing.T) {
   886  	initArtifactoryTest(t)
   887  	rtUrl, err := url.Parse(artifactoryDetails.Url)
   888  	assert.NoError(t, err)
   889  	var proxyTestArgs []string
   890  	var httpProxyEnv string
   891  	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}
   892  	if rtUrl.Scheme == "https" {
   893  		os.Setenv(tests.HttpsProxyEnvVar, "1026")
   894  		proxyTestArgs = append([]string{"test", "-run=TestArtifactoryHttpsProxyEnvironmentVariableDelegator"}, testArgs...)
   895  		httpProxyEnv = "HTTPS_PROXY=localhost:" + cliproxy.GetProxyHttpsPort()
   896  	} else {
   897  		proxyTestArgs = append([]string{"test", "-run=TestArtifactoryHttpProxyEnvironmentVariableDelegator"}, testArgs...)
   898  		httpProxyEnv = "HTTP_PROXY=localhost:" + cliproxy.GetProxyHttpPort()
   899  	}
   900  	runProxyTest(t, proxyTestArgs, httpProxyEnv)
   901  	cleanArtifactoryTest()
   902  }
   903  
   904  func runProxyTest(t *testing.T, proxyTestArgs []string, httpProxyEnv string) {
   905  	cmd := exec.Command("go", proxyTestArgs...)
   906  	cmd.Env = append(os.Environ(), httpProxyEnv)
   907  
   908  	tempDirPath, err := tests.GetTestsLogsDir()
   909  	assert.NoError(t, err)
   910  	f, err := os.Create(filepath.Join(tempDirPath, "artifactory_proxy_tests.log"))
   911  	assert.NoError(t, err)
   912  
   913  	cmd.Stdout, cmd.Stderr = f, f
   914  	assert.NoError(t, cmd.Run(), "Artifactory proxy tests failed, full report available at the following path:", f.Name())
   915  	log.Info("Full Artifactory proxy testing report available at the following path:", f.Name())
   916  }
   917  
   918  // Should be run only by @TestArtifactoryProxy test.
   919  func TestArtifactoryHttpProxyEnvironmentVariableDelegator(t *testing.T) {
   920  	testArtifactoryProxy(t, false)
   921  }
   922  
   923  // Should be run only by @TestArtifactoryProxy test.
   924  func TestArtifactoryHttpsProxyEnvironmentVariableDelegator(t *testing.T) {
   925  	testArtifactoryProxy(t, true)
   926  }
   927  
   928  func testArtifactoryProxy(t *testing.T, isHttps bool) {
   929  	// Value is set to 'true' via testArgs @TestArtifactoryProxy
   930  	if !*tests.TestArtifactoryProxy {
   931  		t.SkipNow()
   932  	}
   933  	authenticate()
   934  	proxyRtUrl := prepareArtifactoryUrlForProxyTest(t)
   935  	spec := spec.NewBuilder().Pattern(tests.Repo1 + "/*.zip").Recursive(true).BuildSpec()
   936  	artifactoryDetails.Url = proxyRtUrl
   937  	checkForErrDueToMissingProxy(spec, t)
   938  	var port string
   939  	if isHttps {
   940  		go cliproxy.StartHttpsProxy()
   941  		port = cliproxy.GetProxyHttpsPort()
   942  	} else {
   943  		go cliproxy.StartHttpProxy()
   944  		port = cliproxy.GetProxyHttpPort()
   945  	}
   946  	// Let's wait for the reverse proxy to start up.
   947  	err := checkIfServerIsUp(port, "http", false)
   948  	assert.NoError(t, err)
   949  	searchCmd := generic.NewSearchCommand()
   950  	searchCmd.SetRtDetails(artifactoryDetails).SetSpec(spec)
   951  	err = searchCmd.Search()
   952  	assert.NoError(t, err)
   953  	artifactoryDetails.Url = artAuth.GetUrl()
   954  }
   955  
   956  func prepareArtifactoryUrlForProxyTest(t *testing.T) string {
   957  	rtUrl, err := url.Parse(artifactoryDetails.Url)
   958  	assert.NoError(t, err)
   959  	rtHost, port, err := net.SplitHostPort(rtUrl.Host)
   960  	if rtHost == "localhost" || rtHost == "127.0.0.1" {
   961  		externalIp, err := getExternalIP()
   962  		assert.NoError(t, err)
   963  		rtUrl.Host = externalIp + ":" + port
   964  	}
   965  	return rtUrl.String()
   966  }
   967  
   968  func checkForErrDueToMissingProxy(spec *spec.SpecFiles, t *testing.T) {
   969  	searchCmd := generic.NewSearchCommand()
   970  	searchCmd.SetRtDetails(artifactoryDetails).SetSpec(spec)
   971  	err := searchCmd.Search()
   972  	_, isUrlErr := err.(*url.Error)
   973  	assert.True(t, isUrlErr, "Expected the request to fails, since the proxy is down.", err)
   974  }
   975  
   976  func checkIfServerIsUp(port, proxyScheme string, useClientCerts bool) error {
   977  	tr := &http.Transport{
   978  		TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
   979  	}
   980  
   981  	if useClientCerts {
   982  		for attempt := 0; attempt < 10; attempt++ {
   983  			if _, err := os.Stat(certificate.CERT_FILE); os.IsNotExist(err) {
   984  				log.Info("Waiting for certificate to appear...")
   985  				time.Sleep(time.Second)
   986  				continue
   987  			}
   988  
   989  			if _, err := os.Stat(certificate.KEY_FILE); os.IsNotExist(err) {
   990  				log.Info("Waiting for key to appear...")
   991  				time.Sleep(time.Second)
   992  				continue
   993  			}
   994  
   995  			break
   996  		}
   997  
   998  		cert, err := tls.LoadX509KeyPair(certificate.CERT_FILE, certificate.KEY_FILE)
   999  		if err != nil {
  1000  			return fmt.Errorf("failed loading client certificate")
  1001  		}
  1002  		tr.TLSClientConfig.Certificates = []tls.Certificate{cert}
  1003  	}
  1004  	client := &http.Client{Transport: tr}
  1005  
  1006  	for attempt := 0; attempt < 10; attempt++ {
  1007  		log.Info("Checking if proxy server is up and running.", strconv.Itoa(attempt+1), "attempt.", "URL:", proxyScheme+"://localhost:"+port)
  1008  		resp, err := client.Get(proxyScheme + "://localhost:" + port)
  1009  		if err != nil {
  1010  			attempt++
  1011  			time.Sleep(time.Second)
  1012  			continue
  1013  		}
  1014  		resp.Body.Close()
  1015  		if resp.StatusCode != http.StatusOK {
  1016  			continue
  1017  		}
  1018  
  1019  		return nil
  1020  	}
  1021  	return fmt.Errorf("failed while waiting for the proxy server to be accessible")
  1022  }
  1023  
  1024  func TestXrayScanBuild(t *testing.T) {
  1025  	initArtifactoryTest(t)
  1026  	xrayServerPort := xray.StartXrayMockServer()
  1027  	serverUrl := "--url=http://localhost:" + strconv.Itoa(xrayServerPort)
  1028  	artifactoryCommandExecutor := tests.NewJfrogCli(execMain, "jfrog rt", serverUrl+getArtifactoryTestCredentials())
  1029  	artifactoryCommandExecutor.Exec("build-scan", xray.CleanScanBuildName, "3")
  1030  
  1031  	cleanArtifactoryTest()
  1032  }
  1033  
  1034  func TestArtifactorySetProperties(t *testing.T) {
  1035  	initArtifactoryTest(t)
  1036  	// Upload a file.
  1037  	artifactoryCli.Exec("upload", "testsdata/a/a1.in", tests.Repo1+"/a.in")
  1038  	// Set the 'prop=red' property to the file.
  1039  	artifactoryCli.Exec("sp", tests.Repo1+"/a.*", "prop=red")
  1040  	// Now let's change the property value, by searching for the 'prop=red'.
  1041  	specFile, err := tests.CreateSpec(tests.SetDeletePropsSpec)
  1042  	assert.NoError(t, err)
  1043  	artifactoryCli.Exec("sp", "prop=green", "--spec="+specFile)
  1044  
  1045  	resultItems := searchItemsInArtifactory(t)
  1046  	assert.NotZero(t, len(resultItems), "No artifacts were found.")
  1047  	for _, item := range resultItems {
  1048  		properties := item.Properties
  1049  		assert.GreaterOrEqual(t, len(properties), 1, "Failed setting properties on item:", item.GetItemRelativePath())
  1050  		for i, prop := range properties {
  1051  			assert.Zero(t, i, "Expected a single property.")
  1052  			assert.Equal(t, "prop", prop.Key, "Wrong property key")
  1053  			assert.Equal(t, "green", prop.Value, "Wrong property value")
  1054  		}
  1055  	}
  1056  	cleanArtifactoryTest()
  1057  }
  1058  
  1059  func TestArtifactorySetPropertiesExcludeByCli(t *testing.T) {
  1060  	initArtifactoryTest(t)
  1061  	artifactoryCli.Exec("upload", "testsdata/a/a*.in", tests.Repo1+"/")
  1062  	artifactoryCli.Exec("sp", tests.Repo1+"/*", "prop=val", "--exclude-patterns=*a1.in;*a2.in")
  1063  	resultItems := searchItemsInArtifactory(t)
  1064  	assert.NotZero(t, len(resultItems), "No artifacts were found.")
  1065  	for _, item := range resultItems {
  1066  		if item.Name != "a3.in" {
  1067  			continue
  1068  		}
  1069  		properties := item.Properties
  1070  		assert.GreaterOrEqual(t, len(properties), 1, "Failed setting properties on item:", item.GetItemRelativePath())
  1071  		for i, prop := range properties {
  1072  			assert.Zero(t, i, "Expected single property.")
  1073  			assert.Equal(t, "prop", prop.Key, "Wrong property key")
  1074  			assert.Equal(t, "val", prop.Value, "Wrong property value")
  1075  		}
  1076  	}
  1077  	cleanArtifactoryTest()
  1078  }
  1079  
  1080  func TestArtifactorySetPropertiesExclusionsByCli(t *testing.T) {
  1081  	initArtifactoryTest(t)
  1082  	artifactoryCli.Exec("upload", "testsdata/a/a*.in", tests.Repo1+"/")
  1083  	artifactoryCli.Exec("sp", tests.Repo1+"/*", "prop=val", "--exclusions=*/*a1.in;*/*a2.in")
  1084  	resultItems := searchItemsInArtifactory(t)
  1085  	assert.NotZero(t, len(resultItems), "No artifacts were found.")
  1086  	for _, item := range resultItems {
  1087  		if item.Name != "a3.in" {
  1088  			continue
  1089  		}
  1090  		properties := item.Properties
  1091  		assert.GreaterOrEqual(t, len(properties), 1, "Failed setting properties on item:", item.GetItemRelativePath())
  1092  		for i, prop := range properties {
  1093  			assert.Zero(t, i, "Expected single property.")
  1094  			assert.Equal(t, "prop", prop.Key, "Wrong property key")
  1095  			assert.Equal(t, "val", prop.Value, "Wrong property value")
  1096  		}
  1097  	}
  1098  	cleanArtifactoryTest()
  1099  }
  1100  
  1101  func TestArtifactoryDeleteProperties(t *testing.T) {
  1102  	initArtifactoryTest(t)
  1103  	artifactoryCli.Exec("upload", "testsdata/a/a*.in", tests.Repo1+"/a/")
  1104  	artifactoryCli.Exec("sp", tests.Repo1+"/a/*", "color=yellow;prop=red;status=ok")
  1105  	// Delete the 'color' property.
  1106  	artifactoryCli.Exec("delp", tests.Repo1+"/a/*", "color")
  1107  	// Delete the 'status' property, by a spec which filters files by 'prop=red'.
  1108  	specFile, err := tests.CreateSpec(tests.SetDeletePropsSpec)
  1109  	assert.NoError(t, err)
  1110  	artifactoryCli.Exec("delp", "status", "--spec="+specFile)
  1111  
  1112  	resultItems := searchItemsInArtifactory(t)
  1113  	assert.NotZero(t, len(resultItems), "No artifacts were found.")
  1114  
  1115  	for _, item := range resultItems {
  1116  		properties := item.Properties
  1117  		for _, prop := range properties {
  1118  			assert.False(t, prop.Key == "color" || prop.Key == "status", "Properties 'color' and/or 'status' were not deleted from artifact", item.Name)
  1119  		}
  1120  	}
  1121  	cleanArtifactoryTest()
  1122  }
  1123  
  1124  func TestArtifactoryDeletePropertiesWithExclude(t *testing.T) {
  1125  	initArtifactoryTest(t)
  1126  	artifactoryCli.Exec("upload", "testsdata/a/a*.in", tests.Repo1+"/")
  1127  	artifactoryCli.Exec("sp", tests.Repo1+"/*", "prop=val")
  1128  
  1129  	artifactoryCli.Exec("delp", tests.Repo1+"/*", "prop", "--exclude-patterns=*a1.in;*a2.in")
  1130  	resultItems := searchItemsInArtifactory(t)
  1131  	assert.NotZero(t, len(resultItems), "No artifacts were found.")
  1132  
  1133  	for _, item := range resultItems {
  1134  		properties := item.Properties
  1135  		for _, prop := range properties {
  1136  			if item.Name == "a1.in" || item.Name == "a2.in" {
  1137  				// Check that properties were not removed.
  1138  				assert.Equal(t, "prop", prop.Key, "Wrong property key")
  1139  				assert.Equal(t, "val", prop.Value, "Wrong property value")
  1140  			}
  1141  		}
  1142  	}
  1143  	cleanArtifactoryTest()
  1144  }
  1145  
  1146  func TestArtifactoryDeletePropertiesWithExclusions(t *testing.T) {
  1147  	initArtifactoryTest(t)
  1148  	artifactoryCli.Exec("upload", "testsdata/a/a*.in", tests.Repo1+"/")
  1149  	artifactoryCli.Exec("sp", tests.Repo1+"/*", "prop=val")
  1150  
  1151  	artifactoryCli.Exec("delp", tests.Repo1+"/*", "prop", "--exclusions=*/*a1.in;*/*a2.in")
  1152  	resultItems := searchItemsInArtifactory(t)
  1153  	assert.NotZero(t, len(resultItems), "No artifacts were found.")
  1154  
  1155  	for _, item := range resultItems {
  1156  		properties := item.Properties
  1157  		for _, prop := range properties {
  1158  			if item.Name == "a1.in" || item.Name == "a2.in" {
  1159  				// Check that properties were not removed.
  1160  				assert.False(t, prop.Key != "prop" || prop.Value != "val", "Wrong properties")
  1161  			}
  1162  		}
  1163  	}
  1164  	cleanArtifactoryTest()
  1165  }
  1166  
  1167  func TestArtifactoryUploadFromHomeDir(t *testing.T) {
  1168  	initArtifactoryTest(t)
  1169  	testFileRel, testFileAbs := createFileInHomeDir(t, "cliTestFile.txt")
  1170  	artifactoryCli.Exec("upload", testFileRel, tests.Repo1, "--recursive=false")
  1171  	searchTxtPath, err := tests.CreateSpec(tests.SearchTxt)
  1172  	assert.NoError(t, err)
  1173  	verifyExistInArtifactory(tests.GetTxtUploadExpectedRepo1(), searchTxtPath, t)
  1174  	os.Remove(testFileAbs)
  1175  	cleanArtifactoryTest()
  1176  }
  1177  
  1178  func createFileInHomeDir(t *testing.T, fileName string) (testFileRelPath string, testFileAbsPath string) {
  1179  	testFileRelPath = filepath.Join("~", fileName)
  1180  	testFileAbsPath = filepath.Join(fileutils.GetHomeDir(), fileName)
  1181  	d1 := []byte("test file")
  1182  	err := ioutil.WriteFile(testFileAbsPath, d1, 0644)
  1183  	assert.NoError(t, err, "Couldn't create file")
  1184  	return
  1185  }
  1186  
  1187  func TestArtifactoryUploadExcludeByCli1Wildcard(t *testing.T) {
  1188  	initArtifactoryTest(t)
  1189  	// Upload files
  1190  	artifactoryCli.Exec("upload", "testsdata/a/a*", tests.Repo1, "--exclusions=*a2*;*a3.in")
  1191  	searchFilePath, err := tests.CreateSpec(tests.SearchRepo1ByInSuffix)
  1192  	assert.NoError(t, err)
  1193  
  1194  	verifyExistInArtifactory(tests.GetSimpleUploadSpecialCharNoRegexExpectedRepo1(), searchFilePath, t)
  1195  	cleanArtifactoryTest()
  1196  }
  1197  
  1198  func TestArtifactoryUploadExcludeByCli1Regex(t *testing.T) {
  1199  	initArtifactoryTest(t)
  1200  	// Upload files
  1201  	artifactoryCli.Exec("upload", "testsdata/a/a(.*)", tests.Repo1, "--exclusions=(.*)a2.*;.*a3.in", "--regexp=true")
  1202  	searchFilePath, err := tests.CreateSpec(tests.SearchRepo1ByInSuffix)
  1203  	assert.NoError(t, err)
  1204  	verifyExistInArtifactory(tests.GetSimpleUploadSpecialCharNoRegexExpectedRepo1(), searchFilePath, t)
  1205  	cleanArtifactoryTest()
  1206  }
  1207  
  1208  func TestArtifactoryUploadExcludeByCli2Wildcard(t *testing.T) {
  1209  	initArtifactoryTest(t)
  1210  
  1211  	// Create temp dir
  1212  	absDirPath, err := ioutil.TempDir("", "cliTestDir")
  1213  	assert.NoError(t, err, "Couldn't create dir")
  1214  	defer os.Remove(absDirPath)
  1215  
  1216  	// Create temp files
  1217  	d1 := []byte("test file")
  1218  	err = ioutil.WriteFile(filepath.Join(absDirPath, "cliTestFile1.in"), d1, 0644)
  1219  	assert.NoError(t, err, "Couldn't create file")
  1220  	err = ioutil.WriteFile(filepath.Join(absDirPath, "cliTestFile2.in"), d1, 0644)
  1221  	assert.NoError(t, err, "Couldn't create file")
  1222  
  1223  	// Upload files
  1224  	artifactoryCli.Exec("upload", filepath.ToSlash(absDirPath)+"/*", tests.Repo1, "--exclusions=*cliTestFile1*")
  1225  
  1226  	// Check files exists in artifactory
  1227  	searchFilePath, err := tests.CreateSpec(tests.SearchRepo1ByInSuffix)
  1228  	assert.NoError(t, err)
  1229  
  1230  	verifyExistInArtifactory([]string{tests.Repo1 + "/cliTestFile2.in"}, searchFilePath, t)
  1231  
  1232  	// Cleanup
  1233  	cleanArtifactoryTest()
  1234  }
  1235  
  1236  func TestArtifactoryUploadExcludeByCli2Regex(t *testing.T) {
  1237  	initArtifactoryTest(t)
  1238  
  1239  	// Create temp dir
  1240  	absDirPath, err := ioutil.TempDir("", "cliTestDir")
  1241  	assert.NoError(t, err, "Couldn't create dir")
  1242  	defer os.Remove(absDirPath)
  1243  
  1244  	// Create temp files
  1245  	d1 := []byte("test file")
  1246  	err = ioutil.WriteFile(filepath.Join(absDirPath, "cliTestFile1.in"), d1, 0644)
  1247  	assert.NoError(t, err, "Couldn't create file")
  1248  	err = ioutil.WriteFile(filepath.Join(absDirPath, "cliTestFile2.in"), d1, 0644)
  1249  	assert.NoError(t, err, "Couldn't create file")
  1250  
  1251  	// Upload files
  1252  	artifactoryCli.Exec("upload", filepath.ToSlash(absDirPath)+"(.*)", tests.Repo1, "--exclusions=(.*c)liTestFile1.*", "--regexp=true")
  1253  
  1254  	// Check files exists in artifactory
  1255  	searchFilePath, err := tests.CreateSpec(tests.SearchRepo1ByInSuffix)
  1256  	assert.NoError(t, err)
  1257  
  1258  	verifyExistInArtifactory([]string{tests.Repo1 + "/cliTestFile2.in"}, searchFilePath, t)
  1259  
  1260  	// Cleanup
  1261  	cleanArtifactoryTest()
  1262  }
  1263  
  1264  func TestArtifactoryUploadExcludeBySpecWildcard(t *testing.T) {
  1265  	initArtifactoryTest(t)
  1266  
  1267  	// Upload files
  1268  	specFile, err := tests.CreateSpec(tests.UploadSpecExclude)
  1269  	assert.NoError(t, err)
  1270  	artifactoryCli.Exec("upload", "--spec="+specFile)
  1271  
  1272  	// Validate files are moved by build number
  1273  	searchFilePath, err := tests.CreateSpec(tests.SearchRepo1ByInSuffix)
  1274  	assert.NoError(t, err)
  1275  
  1276  	verifyExistInArtifactory(tests.GetUploadSpecExcludeRepo1(), searchFilePath, t)
  1277  
  1278  	// Cleanup
  1279  	cleanArtifactoryTest()
  1280  }
  1281  
  1282  func TestArtifactoryUploadExcludeBySpecRegex(t *testing.T) {
  1283  	initArtifactoryTest(t)
  1284  
  1285  	// Upload files
  1286  	specFile, err := tests.CreateSpec(tests.UploadSpecExcludeRegex)
  1287  	assert.NoError(t, err)
  1288  	artifactoryCli.Exec("upload", "--spec="+specFile)
  1289  
  1290  	// Validate files are moved by build number
  1291  	searchFilePath, err := tests.CreateSpec(tests.SearchRepo1ByInSuffix)
  1292  	assert.NoError(t, err)
  1293  
  1294  	verifyExistInArtifactory(tests.GetUploadSpecExcludeRepo1(), searchFilePath, t)
  1295  
  1296  	// Cleanup
  1297  	cleanArtifactoryTest()
  1298  }
  1299  
  1300  func TestArtifactoryUploadWithRegexEscaping(t *testing.T) {
  1301  	initArtifactoryTest(t)
  1302  	// Upload files
  1303  	artifactoryCli.Exec("upload", "testsdata/regexp"+"(.*)"+"\\."+".*", tests.Repo1, "--regexp=true")
  1304  	searchFilePath, err := tests.CreateSpec(tests.SearchAllRepo1)
  1305  	assert.NoError(t, err)
  1306  
  1307  	verifyExistInArtifactory([]string{tests.Repo1 + "/has.dot"}, searchFilePath, t)
  1308  	cleanArtifactoryTest()
  1309  }
  1310  
  1311  func TestArtifactoryCopySpec(t *testing.T) {
  1312  	testMoveCopySpec("copy", t)
  1313  }
  1314  
  1315  func TestArtifactoryMoveSpec(t *testing.T) {
  1316  	testMoveCopySpec("move", t)
  1317  }
  1318  
  1319  func testMoveCopySpec(command string, t *testing.T) {
  1320  	initArtifactoryTest(t)
  1321  	preUploadBasicTestResources()
  1322  	specFile, err := tests.CreateSpec(tests.CopyMoveSimpleSpec)
  1323  	assert.NoError(t, err)
  1324  	artifactoryCli.Exec(command, "--spec="+specFile)
  1325  
  1326  	// Verify files exist in target location successfully
  1327  	searchMovedCopiedSpec, err := tests.CreateSpec(tests.SearchTargetInRepo2)
  1328  	assert.NoError(t, err)
  1329  	verifyExistInArtifactory(tests.GetMoveCopySpecExpected(), searchMovedCopiedSpec, t)
  1330  
  1331  	searchOriginalSpec, err := tests.CreateSpec(tests.SearchRepo1TestResources)
  1332  	assert.NoError(t, err)
  1333  
  1334  	if command == "copy" {
  1335  		// Verify original files still exist
  1336  		verifyExistInArtifactory(tests.GetRepo1TestResourcesExpected(), searchOriginalSpec, t)
  1337  	} else {
  1338  		// Verify original files were moved
  1339  		verifyDoesntExistInArtifactory(searchOriginalSpec, t)
  1340  	}
  1341  
  1342  	cleanArtifactoryTest()
  1343  }
  1344  
  1345  // Upload symlink by full path to Artifactory and the link content checksum
  1346  // Download the symlink which was uploaded.
  1347  // validate the symlink content checksum
  1348  func TestValidateValidSymlink(t *testing.T) {
  1349  	if cliutils.IsWindows() {
  1350  		t.Skip("Running on windows, skipping...")
  1351  	}
  1352  	initArtifactoryTest(t)
  1353  	// Path to local file
  1354  	localFile := filepath.Join(tests.GetTestResourcesPath()+"a", "a1.in")
  1355  	// Path to valid symLink
  1356  	validLink := filepath.Join(tests.GetTestResourcesPath()+"a", "link")
  1357  
  1358  	// Link valid symLink to local file
  1359  	err := os.Symlink(localFile, validLink)
  1360  	assert.NoError(t, err)
  1361  
  1362  	// Upload symlink to artifactory
  1363  	artifactoryCli.Exec("u", validLink+" "+tests.Repo1+" --symlinks=true")
  1364  
  1365  	// Delete the local symlink
  1366  	err = os.Remove(validLink)
  1367  	assert.NoError(t, err)
  1368  
  1369  	// Download symlink from artifactory
  1370  	artifactoryCli.Exec("dl", tests.Repo1+"/link "+tests.GetTestResourcesPath()+"a/ --validate-symlinks=true")
  1371  
  1372  	// Should be valid if successful
  1373  	validateSymLink(validLink, localFile, t)
  1374  
  1375  	// Delete symlink and clean
  1376  	os.Remove(validLink)
  1377  	cleanArtifactoryTest()
  1378  }
  1379  
  1380  // Upload symlink by full path to Artifactory and the link content checksum
  1381  // Download the symlink which was uploaded.
  1382  // validate the symlink content checksum.
  1383  func TestValidateBrokenSymlink(t *testing.T) {
  1384  	if cliutils.IsWindows() {
  1385  		t.Skip("Running on windows, skipping...")
  1386  	}
  1387  	initArtifactoryTest(t)
  1388  
  1389  	// Path to broken symLink
  1390  	brokenLink := filepath.Join(tests.GetTestResourcesPath()+"a/", "brokenLink")
  1391  
  1392  	// Link broken symLink to non_existing_path
  1393  	err := os.Symlink("non-non_existing_path-path", brokenLink)
  1394  	assert.NoError(t, err)
  1395  
  1396  	// Upload symlink to artifactory
  1397  	artifactoryCli.Exec("u", brokenLink+" "+tests.Repo1+" --symlinks=true")
  1398  
  1399  	// Delete the local symlink
  1400  	err = os.Remove(brokenLink)
  1401  	assert.NoError(t, err)
  1402  
  1403  	// Try downloading symlink from artifactory. Since the link is broken, it shouldn't be downloaded
  1404  	artifactoryCli.Exec("dl", tests.Repo1+"/link "+tests.GetTestResourcesPath()+"a/ --validate-symlinks=true")
  1405  	if fileutils.IsPathExists(brokenLink, true) {
  1406  		os.Remove(brokenLink)
  1407  		assert.Fail(t, "A broken symLink was downloaded although validate-symlinks flag was set to true")
  1408  	}
  1409  
  1410  	// Clean
  1411  	cleanArtifactoryTest()
  1412  }
  1413  
  1414  // Testing exclude pattern with symlinks.
  1415  // This test should not upload any files.
  1416  func TestExcludeBrokenSymlink(t *testing.T) {
  1417  	if cliutils.IsWindows() {
  1418  		t.Skip("Running on windows, skipping...")
  1419  	}
  1420  	initArtifactoryTest(t)
  1421  
  1422  	// Creating broken symlink
  1423  	os.Mkdir(tests.Out, 0777)
  1424  	linkToNonExistingPath := filepath.Join(tests.Out, "link_to_non_existing_path")
  1425  	err := os.Symlink("non_existing_path", linkToNonExistingPath)
  1426  	assert.NoError(t, err)
  1427  
  1428  	// This command should succeed because all artifacts are excluded.
  1429  	artifactoryCli.Exec("u", filepath.Join(tests.Out, "*"), tests.Repo1, "--symlinks=true", "--exclusions=*")
  1430  	cleanArtifactoryTest()
  1431  }
  1432  
  1433  // Upload symlink to Artifactory using wildcard pattern and the link content checksum
  1434  // Download the symlink which was uploaded.
  1435  // validate the symlink content checksum.
  1436  func TestSymlinkWildcardPathHandling(t *testing.T) {
  1437  	if cliutils.IsWindows() {
  1438  		t.Skip("Running on windows, skipping...")
  1439  	}
  1440  	initArtifactoryTest(t)
  1441  	localFile := filepath.Join(tests.GetTestResourcesPath()+"a/", "a1.in")
  1442  	link := filepath.Join(tests.GetTestResourcesPath()+"a/", "link")
  1443  	err := os.Symlink(localFile, link)
  1444  	assert.NoError(t, err)
  1445  	link1 := filepath.Join(tests.GetTestResourcesPath()+"a/", "link*")
  1446  	artifactoryCli.Exec("u", link1+" "+tests.Repo1+" --symlinks=true")
  1447  	err = os.Remove(link)
  1448  	assert.NoError(t, err)
  1449  	artifactoryCli.Exec("dl", tests.Repo1+"/link "+tests.GetTestResourcesPath()+"a/ --validate-symlinks=true")
  1450  	validateSymLink(link, localFile, t)
  1451  	os.Remove(link)
  1452  	cleanArtifactoryTest()
  1453  }
  1454  
  1455  // Upload symlink pointing to directory to Artifactory.
  1456  // Download the symlink which was uploaded.
  1457  func TestSymlinkToDirHandling(t *testing.T) {
  1458  	if cliutils.IsWindows() {
  1459  		t.Skip("Running on windows, skipping...")
  1460  	}
  1461  	initArtifactoryTest(t)
  1462  	localFile := filepath.Join(tests.GetTestResourcesPath(), "a")
  1463  	link := filepath.Join(tests.GetTestResourcesPath()+"a/", "link")
  1464  	err := os.Symlink(localFile, link)
  1465  	assert.NoError(t, err)
  1466  	artifactoryCli.Exec("u", link+" "+tests.Repo1+" --symlinks=true --recursive=true")
  1467  	err = os.Remove(link)
  1468  	assert.NoError(t, err)
  1469  	artifactoryCli.Exec("dl", tests.Repo1+"/link "+tests.GetTestResourcesPath()+"a/")
  1470  	validateSymLink(link, localFile, t)
  1471  	os.Remove(link)
  1472  	cleanArtifactoryTest()
  1473  }
  1474  
  1475  // Upload symlink pointing to directory using wildcard path to Artifactory.
  1476  // Download the symlink which was uploaded.
  1477  func TestSymlinkToDirWildcardHandling(t *testing.T) {
  1478  	if cliutils.IsWindows() {
  1479  		t.Skip("Running on windows, skipping...")
  1480  	}
  1481  	initArtifactoryTest(t)
  1482  	localFile := filepath.Join(tests.GetTestResourcesPath(), "a")
  1483  	link := filepath.Join(tests.GetTestResourcesPath()+"a/", "link")
  1484  	err := os.Symlink(localFile, link)
  1485  	assert.NoError(t, err)
  1486  	link1 := filepath.Join(tests.GetTestResourcesPath()+"a/", "lin*")
  1487  	artifactoryCli.Exec("u", link1+" "+tests.Repo1+" --symlinks=true --recursive=true")
  1488  	err = os.Remove(link)
  1489  	assert.NoError(t, err)
  1490  	artifactoryCli.Exec("dl", tests.Repo1+"/link "+tests.GetTestResourcesPath()+"a/")
  1491  	validateSymLink(link, localFile, t)
  1492  	os.Remove(link)
  1493  	cleanArtifactoryTest()
  1494  }
  1495  
  1496  // Upload symlink pointing to directory using wildcard path to Artifactory.
  1497  // Download the symlink which was uploaded.
  1498  // The test create circular links and the test suppose to prune the circular searching.
  1499  func TestSymlinkInsideSymlinkDirWithRecursionIssueUpload(t *testing.T) {
  1500  	if cliutils.IsWindows() {
  1501  		t.Skip("Running on windows, skipping...")
  1502  	}
  1503  	initArtifactoryTest(t)
  1504  	localDirPath := filepath.Join(tests.GetTestResourcesPath(), "a")
  1505  	link1 := filepath.Join(tests.GetTestResourcesPath()+"a/", "link1")
  1506  	err := os.Symlink(localDirPath, link1)
  1507  	assert.NoError(t, err)
  1508  	localFilePath := filepath.Join(tests.GetTestResourcesPath()+"a/", "a1.in")
  1509  	link2 := filepath.Join(tests.GetTestResourcesPath()+"a/", "link2")
  1510  	err = os.Symlink(localFilePath, link2)
  1511  	assert.NoError(t, err)
  1512  
  1513  	artifactoryCli.Exec("u", localDirPath+"/link* "+tests.Repo1+" --symlinks=true --recursive=true")
  1514  	err = os.Remove(link1)
  1515  	assert.NoError(t, err)
  1516  
  1517  	err = os.Remove(link2)
  1518  	assert.NoError(t, err)
  1519  
  1520  	artifactoryCli.Exec("dl", tests.Repo1+"/link* "+tests.GetTestResourcesPath()+"a/")
  1521  	validateSymLink(link1, localDirPath, t)
  1522  	os.Remove(link1)
  1523  	validateSymLink(link2, localFilePath, t)
  1524  	os.Remove(link2)
  1525  	cleanArtifactoryTest()
  1526  }
  1527  
  1528  func validateSymLink(localLinkPath, localFilePath string, t *testing.T) {
  1529  	exists := fileutils.IsPathSymlink(localLinkPath)
  1530  	assert.True(t, exists, "failed to download symlinks from artifactory")
  1531  	symlinks, err := filepath.EvalSymlinks(localLinkPath)
  1532  	assert.NoError(t, err, "can't eval symlinks")
  1533  	assert.Equal(t, localFilePath, symlinks, "Symlinks wasn't created as expected")
  1534  }
  1535  
  1536  func TestArtifactoryDeleteNoSpec(t *testing.T) {
  1537  	initArtifactoryTest(t)
  1538  	testArtifactorySimpleDelete(t, "")
  1539  }
  1540  
  1541  func TestArtifactoryDeleteBySpec(t *testing.T) {
  1542  	initArtifactoryTest(t)
  1543  	deleteSpecPath, err := tests.CreateSpec(tests.DeleteSimpleSpec)
  1544  	assert.NoError(t, err)
  1545  	testArtifactorySimpleDelete(t, deleteSpecPath)
  1546  }
  1547  
  1548  func testArtifactorySimpleDelete(t *testing.T, deleteSpecPath string) {
  1549  	preUploadBasicTestResources()
  1550  
  1551  	// Verify exists before deleting
  1552  	searchSpec, err := tests.CreateSpec(tests.SearchRepo1TestResources)
  1553  	assert.NoError(t, err)
  1554  	verifyExistInArtifactory(tests.GetRepo1TestResourcesExpected(), searchSpec, t)
  1555  
  1556  	if deleteSpecPath != "" {
  1557  		artifactoryCli.Exec("delete", "--spec="+deleteSpecPath)
  1558  	} else {
  1559  		artifactoryCli.Exec("delete", tests.Repo1+"/test_resources/b/*")
  1560  	}
  1561  
  1562  	verifyExistInArtifactory(tests.GetSimpleDelete(), searchSpec, t)
  1563  	cleanArtifactoryTest()
  1564  }
  1565  
  1566  func TestArtifactoryDeleteFolderWithWildcard(t *testing.T) {
  1567  	initArtifactoryTest(t)
  1568  	preUploadBasicTestResources()
  1569  
  1570  	// Verify exists before deleting
  1571  	searchSpec, err := tests.CreateSpec(tests.SearchRepo1TestResources)
  1572  	assert.NoError(t, err)
  1573  	verifyExistInArtifactory(tests.GetRepo1TestResourcesExpected(), searchSpec, t)
  1574  
  1575  	artifactoryCli.Exec("delete", tests.Repo1+"/test_resources/*/c")
  1576  
  1577  	verifyExistInArtifactory(tests.GetDeleteFolderWithWildcard(), searchSpec, t)
  1578  	cleanArtifactoryTest()
  1579  }
  1580  
  1581  func TestArtifactoryDeleteFolderCompletelyNoSpec(t *testing.T) {
  1582  	testArtifactoryDeleteFoldersNoSpec(t, false)
  1583  }
  1584  
  1585  func TestArtifactoryDeleteFolderContentNoSpec(t *testing.T) {
  1586  	testArtifactoryDeleteFoldersNoSpec(t, true)
  1587  }
  1588  
  1589  func testArtifactoryDeleteFoldersNoSpec(t *testing.T, contentOnly bool) {
  1590  	initArtifactoryTest(t)
  1591  	preUploadBasicTestResources()
  1592  
  1593  	// Verify exists before deleting
  1594  	searchSpec, err := tests.CreateSpec(tests.SearchRepo1TestResources)
  1595  	assert.NoError(t, err)
  1596  	verifyExistInArtifactory(tests.GetRepo1TestResourcesExpected(), searchSpec, t)
  1597  
  1598  	// Delete folder
  1599  	deletePath := tests.Repo1 + "/test_resources"
  1600  	// End with separator if content only
  1601  	if contentOnly {
  1602  		deletePath += "/"
  1603  	}
  1604  	artifactoryCli.Exec("delete", deletePath)
  1605  
  1606  	client, err := httpclient.ClientBuilder().Build()
  1607  	assert.NoError(t, err)
  1608  
  1609  	// Verify folder exists only if content only
  1610  	var expectedStatusCode int
  1611  	if contentOnly {
  1612  		expectedStatusCode = http.StatusOK
  1613  	} else {
  1614  		expectedStatusCode = http.StatusNotFound
  1615  	}
  1616  	resp, body, _, err := client.SendGet(artifactoryDetails.Url+"api/storage/"+tests.Repo1+"/test_resources", true, artHttpDetails)
  1617  	assert.NoError(t, err)
  1618  	assert.Equal(t, expectedStatusCode, resp.StatusCode, "test_resources shouldn't be deleted: "+tests.Repo1+"/test_resources/ "+string(body))
  1619  
  1620  	// Verify no content exists
  1621  	verifyDoesntExistInArtifactory(searchSpec, t)
  1622  	cleanArtifactoryTest()
  1623  }
  1624  
  1625  func TestArtifactoryDeleteFoldersBySpecAllRepo(t *testing.T) {
  1626  	testArtifactoryDeleteFoldersBySpec(t, tests.DeleteSpec)
  1627  }
  1628  
  1629  func TestArtifactoryDeleteFoldersBySpecWildcardInRepo(t *testing.T) {
  1630  	testArtifactoryDeleteFoldersBySpec(t, tests.DeleteSpecWildcardInRepo)
  1631  }
  1632  
  1633  func testArtifactoryDeleteFoldersBySpec(t *testing.T, specPath string) {
  1634  	initArtifactoryTest(t)
  1635  	preUploadBasicTestResources()
  1636  
  1637  	// Verify exists before deleting
  1638  	searchSpec, err := tests.CreateSpec(tests.SearchRepo1TestResources)
  1639  	assert.NoError(t, err)
  1640  	verifyExistInArtifactory(tests.GetRepo1TestResourcesExpected(), searchSpec, t)
  1641  
  1642  	deleteSpecPath, err := tests.CreateSpec(specPath)
  1643  	assert.NoError(t, err)
  1644  	artifactoryCli.Exec("delete", "--spec="+deleteSpecPath)
  1645  
  1646  	completeSearchSpec, err := tests.CreateSpec(tests.SearchAllRepo1)
  1647  	assert.NoError(t, err)
  1648  	verifyDoesntExistInArtifactory(completeSearchSpec, t)
  1649  	cleanArtifactoryTest()
  1650  }
  1651  
  1652  func TestArtifactoryDeleteExcludeByCli(t *testing.T) {
  1653  	initArtifactoryTest(t)
  1654  
  1655  	// Upload files
  1656  	specFileA, err := tests.CreateSpec(tests.SplitUploadSpecA)
  1657  	assert.NoError(t, err)
  1658  	specFileB, err := tests.CreateSpec(tests.SplitUploadSpecB)
  1659  	assert.NoError(t, err)
  1660  
  1661  	artifactoryCli.Exec("upload", "--spec="+specFileA)
  1662  	artifactoryCli.Exec("upload", "--spec="+specFileB)
  1663  
  1664  	// Delete by pattern
  1665  	artifactoryCli.Exec("del", tests.Repo1+"/data/", "--exclude-patterns=*b1.in;*b2.in;*b3.in;*c1.in")
  1666  
  1667  	// Validate files are deleted
  1668  	cpMvDlByBuildAssertSpec, err := tests.CreateSpec(tests.CpMvDlByBuildAssertSpec)
  1669  	assert.NoError(t, err)
  1670  
  1671  	verifyExistInArtifactory(tests.GetBuildDeleteExpected(), cpMvDlByBuildAssertSpec, t)
  1672  
  1673  	// Cleanup
  1674  	cleanArtifactoryTest()
  1675  }
  1676  
  1677  func TestArtifactoryDeleteExclusionsByCli(t *testing.T) {
  1678  	initArtifactoryTest(t)
  1679  
  1680  	// Upload files
  1681  	specFileA, err := tests.CreateSpec(tests.SplitUploadSpecA)
  1682  	assert.NoError(t, err)
  1683  	specFileB, err := tests.CreateSpec(tests.SplitUploadSpecB)
  1684  	assert.NoError(t, err)
  1685  
  1686  	artifactoryCli.Exec("upload", "--spec="+specFileA)
  1687  	artifactoryCli.Exec("upload", "--spec="+specFileB)
  1688  
  1689  	// Delete by pattern
  1690  	artifactoryCli.Exec("del", tests.Repo1+"/data/", "--exclusions=*/*b1.in;*/*b2.in;*/*b3.in;*/*c1.in")
  1691  
  1692  	// Validate files are deleted
  1693  	cpMvDlByBuildAssertSpec, err := tests.CreateSpec(tests.CpMvDlByBuildAssertSpec)
  1694  	assert.NoError(t, err)
  1695  
  1696  	verifyExistInArtifactory(tests.GetBuildDeleteExpected(), cpMvDlByBuildAssertSpec, t)
  1697  
  1698  	// Cleanup
  1699  	cleanArtifactoryTest()
  1700  }
  1701  
  1702  func TestArtifactoryDeleteExcludeBySpec(t *testing.T) {
  1703  	initArtifactoryTest(t)
  1704  	// Upload files
  1705  	specFileA, err := tests.CreateSpec(tests.SplitUploadSpecA)
  1706  	assert.NoError(t, err)
  1707  	specFileB, err := tests.CreateSpec(tests.SplitUploadSpecB)
  1708  	assert.NoError(t, err)
  1709  	artifactoryCli.Exec("upload", "--spec="+specFileA)
  1710  	artifactoryCli.Exec("upload", "--spec="+specFileB)
  1711  
  1712  	specFile, err := tests.CreateSpec(tests.DelSpecExclude)
  1713  	assert.NoError(t, err)
  1714  
  1715  	// Delete by pattern
  1716  	artifactoryCli.Exec("del", "--spec="+specFile)
  1717  
  1718  	// Validate files are deleted
  1719  	cpMvDlByBuildAssertSpec, err := tests.CreateSpec(tests.CpMvDlByBuildAssertSpec)
  1720  	assert.NoError(t, err)
  1721  
  1722  	verifyExistInArtifactory(tests.GetBuildDeleteExpected(), cpMvDlByBuildAssertSpec, t)
  1723  
  1724  	// Cleanup
  1725  	cleanArtifactoryTest()
  1726  }
  1727  
  1728  func TestArtifactoryDeleteExclusionsBySpec(t *testing.T) {
  1729  	initArtifactoryTest(t)
  1730  	// Upload files
  1731  	specFileA, err := tests.CreateSpec(tests.SplitUploadSpecA)
  1732  	assert.NoError(t, err)
  1733  	specFileB, err := tests.CreateSpec(tests.SplitUploadSpecB)
  1734  	assert.NoError(t, err)
  1735  	artifactoryCli.Exec("upload", "--spec="+specFileA)
  1736  	artifactoryCli.Exec("upload", "--spec="+specFileB)
  1737  
  1738  	specFile, err := tests.CreateSpec(tests.DelSpecExclusions)
  1739  	assert.NoError(t, err)
  1740  
  1741  	// Delete by pattern
  1742  	artifactoryCli.Exec("del", "--spec="+specFile)
  1743  
  1744  	// Validate files are deleted
  1745  	cpMvDlByBuildAssertSpec, err := tests.CreateSpec(tests.CpMvDlByBuildAssertSpec)
  1746  	assert.NoError(t, err)
  1747  
  1748  	verifyExistInArtifactory(tests.GetBuildDeleteExpected(), cpMvDlByBuildAssertSpec, t)
  1749  
  1750  	// Cleanup
  1751  	cleanArtifactoryTest()
  1752  }
  1753  
  1754  func TestArtifactoryDeleteByProps(t *testing.T) {
  1755  	initArtifactoryTest(t)
  1756  
  1757  	// Upload files
  1758  	specFile, err := tests.CreateSpec(tests.UploadWithPropsSpec)
  1759  	assert.NoError(t, err)
  1760  	artifactoryCli.Exec("upload", "--spec="+specFile)
  1761  	// Set properties to the directories as well (and their content)
  1762  	artifactoryCli.Exec("sp", tests.Repo1+"/a/b", "D=5", "--include-dirs")
  1763  	artifactoryCli.Exec("sp", tests.Repo1+"/a/b/c", "D=2", "--include-dirs")
  1764  	//  Set the property D=5 to c1.in, which is a different value then its directory c/
  1765  	artifactoryCli.Exec("sp", tests.Repo1+"/a/b/c/c1.in", "D=5")
  1766  
  1767  	// Prepare search command
  1768  	searchSpecBuilder := spec.NewBuilder().Pattern(tests.Repo1).Recursive(true)
  1769  	searchCmd := generic.NewSearchCommand()
  1770  	searchCmd.SetRtDetails(artifactoryDetails)
  1771  	searchCmd.SetSpec(searchSpecBuilder.BuildSpec())
  1772  
  1773  	// Delete all artifacts with D=5 but without c=3
  1774  	artifactoryCli.Exec("delete", tests.Repo1+"/*", "--props=D=5", "--exclude-props=c=3")
  1775  	// Search all artifacts in repo1
  1776  	assert.NoError(t, searchCmd.Search())
  1777  	assert.NoError(t, assertDateInSearchResult(searchCmd.SearchResult()))
  1778  	assert.ElementsMatch(t, searchCmd.SearchResultNoDate(), tests.GetSearchResultAfterDeleteByPropsStep1())
  1779  
  1780  	// Delete all artifacts with c=3 but without a=1
  1781  	artifactoryCli.Exec("delete", tests.Repo1+"/*", "--props=c=3", "--exclude-props=a=1")
  1782  	// Search all artifacts in repo1
  1783  	assert.NoError(t, searchCmd.Search())
  1784  	assert.NoError(t, assertDateInSearchResult(searchCmd.SearchResult()))
  1785  	assert.ElementsMatch(t, searchCmd.SearchResultNoDate(), tests.GetSearchResultAfterDeleteByPropsStep2())
  1786  
  1787  	// Delete all artifacts with a=1 but without b=3&c=3
  1788  	artifactoryCli.Exec("delete", tests.Repo1+"/*", "--props=a=1", "--exclude-props=b=3;c=3")
  1789  	// Search all artifacts in repo1
  1790  	assert.NoError(t, searchCmd.Search())
  1791  	assert.NoError(t, assertDateInSearchResult(searchCmd.SearchResult()))
  1792  	assert.ElementsMatch(t, searchCmd.SearchResultNoDate(), tests.GetSearchResultAfterDeleteByPropsStep3())
  1793  
  1794  	// Cleanup
  1795  	cleanArtifactoryTest()
  1796  }
  1797  
  1798  func TestArtifactoryMultipleFileSpecsUpload(t *testing.T) {
  1799  	initArtifactoryTest(t)
  1800  	specFile, err := tests.CreateSpec(tests.UploadMultipleFileSpecs)
  1801  	assert.NoError(t, err)
  1802  	resultSpecFile, err := tests.CreateSpec(tests.SearchAllRepo1)
  1803  	assert.NoError(t, err)
  1804  	artifactoryCli.Exec("upload", "--spec="+specFile)
  1805  
  1806  	verifyExistInArtifactory(tests.GetMultipleFileSpecs(), resultSpecFile, t)
  1807  	verifyExistInArtifactoryByProps([]string{tests.Repo1 + "/multiple/properties/testsdata/a/b/b2.in"}, tests.Repo1+"/*/properties/*.in", "searchMe=true", t)
  1808  	cleanArtifactoryTest()
  1809  }
  1810  
  1811  func TestArtifactorySimplePlaceHolders(t *testing.T) {
  1812  	initArtifactoryTest(t)
  1813  	specFile, err := tests.CreateSpec(tests.UploadSimplePlaceholders)
  1814  	assert.NoError(t, err)
  1815  
  1816  	resultSpecFile, err := tests.CreateSpec(tests.SearchSimplePlaceholders)
  1817  	assert.NoError(t, err)
  1818  
  1819  	artifactoryCli.Exec("upload", "--spec="+specFile)
  1820  
  1821  	verifyExistInArtifactory(tests.GetSimplePlaceholders(), resultSpecFile, t)
  1822  	cleanArtifactoryTest()
  1823  }
  1824  
  1825  func TestArtifactoryFolderUploadRecursiveNonFlat(t *testing.T) {
  1826  	initArtifactoryTest(t)
  1827  	dirInnerPath := fileutils.GetFileSeparator() + "inner" + fileutils.GetFileSeparator() + "folder"
  1828  	canonicalPath := tests.Out + dirInnerPath
  1829  
  1830  	err := os.MkdirAll(canonicalPath, 0777)
  1831  	assert.NoError(t, err)
  1832  	artifactoryCli.Exec("upload", tests.Out+"/(*)", tests.Repo1+"/{1}/", "--include-dirs=true", "--recursive=true", "--flat=false")
  1833  	err = os.RemoveAll(tests.Out)
  1834  	assert.NoError(t, err)
  1835  	artifactoryCli.Exec("download", tests.Repo1, tests.Out+"/", "--include-dirs=true", "--recursive=true")
  1836  	expectedPath := []string{tests.Out, "inner", "folder", "out", "inner", "folder"}
  1837  	assert.True(t, fileutils.IsPathExists(strings.Join(expectedPath, fileutils.GetFileSeparator()), false), "Failed to download folders from Artifactory")
  1838  	// Cleanup
  1839  	cleanArtifactoryTest()
  1840  }
  1841  
  1842  func TestArtifactoryFlatFolderUpload(t *testing.T) {
  1843  	initArtifactoryTest(t)
  1844  	dirInnerPath := fileutils.GetFileSeparator() + "inner" + fileutils.GetFileSeparator() + "folder"
  1845  	canonicalPath := tests.Out + dirInnerPath
  1846  	err := os.MkdirAll(canonicalPath, 0777)
  1847  	assert.NoError(t, err)
  1848  	artifactoryCli.Exec("upload", tests.Out+"/(*)", tests.Repo1+"/{1}/", "--include-dirs=true", "--flat=true")
  1849  	err = os.RemoveAll(tests.Out)
  1850  	assert.NoError(t, err)
  1851  	// Non flat download
  1852  	artifactoryCli.Exec("download", tests.Repo1, tests.Out+"/", "--include-dirs=true", "--recursive=true")
  1853  	assert.True(t, fileutils.IsPathExists(canonicalPath+fileutils.GetFileSeparator()+"folder", false), "Failed to download folders from Artifactory")
  1854  	// Cleanup
  1855  	cleanArtifactoryTest()
  1856  }
  1857  
  1858  // Test the definition of bottom chain directories - Directories which do not include other directories that match the pattern
  1859  func TestArtifactoryIncludeDirFlatNonEmptyFolderUpload(t *testing.T) {
  1860  	initArtifactoryTest(t)
  1861  	// 'c' folder is defined as bottom chain directory therefore should be uploaded when using flat=true even though 'c' is not empty
  1862  	artifactoryCli.Exec("upload", tests.GetTestResourcesPath()+"a/b/*", tests.Repo1, "--include-dirs=true", "--flat=true")
  1863  	artifactoryCli.Exec("download", tests.Repo1, tests.Out+"/", "--include-dirs=true", "--recursive=true")
  1864  	assert.True(t, fileutils.IsPathExists(tests.Out+"/c", false), "Failed to download folders from Artifactory")
  1865  	// Cleanup
  1866  	cleanArtifactoryTest()
  1867  }
  1868  
  1869  // Test the definition of bottom chain directories - Directories which do not include other directories that match the pattern
  1870  func TestArtifactoryDownloadNotIncludeDirs(t *testing.T) {
  1871  	initArtifactoryTest(t)
  1872  	// 'c' folder is defined as bottom chain directory therefore should be uploaded when using flat=true even though 'c' is not empty
  1873  	artifactoryCli.Exec("upload", tests.GetTestResourcesPath()+"*/c", tests.Repo1, "--include-dirs=true", "--flat=true")
  1874  	artifactoryCli.Exec("download", tests.Repo1, tests.Out+"/", "--recursive=true")
  1875  	assert.False(t, fileutils.IsPathExists(tests.Out+"/c", false), "Failed to download folders from Artifactory")
  1876  	// Cleanup
  1877  	cleanArtifactoryTest()
  1878  }
  1879  
  1880  // Test the definition of bottom chain directories - Directories which do not include other directories that match the pattern
  1881  func TestArtifactoryDownloadFlatTrue(t *testing.T) {
  1882  	initArtifactoryTest(t)
  1883  	canonicalPath := tests.GetTestResourcesPath() + path.Join("an", "empty", "folder")
  1884  	err := os.MkdirAll(canonicalPath, 0777)
  1885  	assert.NoError(t, err)
  1886  
  1887  	// 'c' folder is defined as bottom chain directory therefore should be uploaded when using flat=true even though 'c' is not empty
  1888  	artifactoryCli.Exec("upload", tests.GetTestResourcesPath()+"(a*)/*", tests.Repo1+"/{1}/", "--include-dirs=true", "--flat=true")
  1889  	// Download without include-dirs
  1890  	artifactoryCli.Exec("download", tests.Repo1, tests.Out+"/", "--recursive=true", "--flat=true")
  1891  	assert.False(t, fileutils.IsPathExists(tests.Out+"/c", false), "'c' folder shouldn't exist.")
  1892  
  1893  	artifactoryCli.Exec("download", tests.Repo1, tests.Out+"/", "--include-dirs=true", "--recursive=true", "--flat=true")
  1894  	// Inner folder with files in it
  1895  	assert.True(t, fileutils.IsPathExists(tests.Out+"/c", false), "'c' folder should exist.")
  1896  	// Empty inner folder
  1897  	assert.True(t, fileutils.IsPathExists(tests.Out+"/folder", false), "'folder' folder should exist.")
  1898  	// Folder on root with files
  1899  	assert.True(t, fileutils.IsPathExists(tests.Out+"/a$+~&^a#", false), "'a$+~&^a#' folder should exist.")
  1900  	// None bottom directory - shouldn't exist.
  1901  	assert.False(t, fileutils.IsPathExists(tests.Out+"/a", false), "'a' folder shouldn't exist.")
  1902  	// None bottom directory - shouldn't exist.
  1903  	assert.False(t, fileutils.IsPathExists(tests.Out+"/b", false), "'b' folder shouldn't exist.")
  1904  	// Cleanup
  1905  	cleanArtifactoryTest()
  1906  }
  1907  
  1908  func TestArtifactoryIncludeDirFlatNonEmptyFolderUploadMatchingPattern(t *testing.T) {
  1909  	initArtifactoryTest(t)
  1910  	// 'c' folder is defined as bottom chain directory therefore should be uploaded when using flat=true even though 'c' is not empty
  1911  	artifactoryCli.Exec("upload", tests.GetTestResourcesPath()+"*/c", tests.Repo1, "--include-dirs=true", "--flat=true")
  1912  	artifactoryCli.Exec("download", tests.Repo1, tests.Out+"/", "--include-dirs=true", "--recursive=true")
  1913  	assert.True(t, fileutils.IsPathExists(tests.Out+"/c", false), "Failed to download folders from Artifactory")
  1914  	// Cleanup
  1915  	cleanArtifactoryTest()
  1916  }
  1917  
  1918  // Test the definition of bottom chain directories - Directories which do not include other directories that match the pattern
  1919  func TestArtifactoryUploadFlatFolderWithFileAndInnerEmptyMatchingPattern(t *testing.T) {
  1920  	initArtifactoryTest(t)
  1921  	newFolderPath := tests.GetTestResourcesPath() + "a/b/c/d"
  1922  	err := os.MkdirAll(newFolderPath, 0777)
  1923  	assert.NoError(t, err)
  1924  	// 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.
  1925  	// 'd' should uploaded and 'c' shouldn't
  1926  	artifactoryCli.Exec("upload", tests.GetTestResourcesPath()+"a/b/*", tests.Repo1, "--include-dirs=true", "--flat=true")
  1927  	err = os.RemoveAll(newFolderPath)
  1928  	assert.NoError(t, err)
  1929  	artifactoryCli.Exec("download", tests.Repo1, tests.Out+"/", "--include-dirs=true", "--recursive=true")
  1930  	assert.False(t, fileutils.IsPathExists(tests.Out+"/c", false), "'c' folder shouldn't exist")
  1931  	assert.True(t, fileutils.IsPathExists(tests.Out+"/d", false), "bottom chain directory, 'd', is missing")
  1932  	// Cleanup
  1933  	cleanArtifactoryTest()
  1934  }
  1935  
  1936  // Test the definition of bottom chain directories - Directories which do not include other directories that match the pattern
  1937  func TestArtifactoryUploadFlatFolderWithFileAndInnerEmptyMatchingPatternWithPlaceHolders(t *testing.T) {
  1938  	initArtifactoryTest(t)
  1939  	relativePath := "/b/c/d"
  1940  	fullPath := tests.GetTestResourcesPath() + "a/" + relativePath
  1941  	err := os.MkdirAll(fullPath, 0777)
  1942  	assert.NoError(t, err)
  1943  	// 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.
  1944  	// 'd' should uploaded and 'c' shouldn't
  1945  	artifactoryCli.Exec("upload", tests.GetTestResourcesPath()+"a/(*)/*", tests.Repo1+"/{1}/", "--include-dirs=true", "--flat=true")
  1946  	err = os.RemoveAll(fullPath)
  1947  	assert.NoError(t, err)
  1948  	artifactoryCli.Exec("download", tests.Repo1, tests.Out+"/", "--include-dirs=true", "--recursive=true")
  1949  	assert.True(t, fileutils.IsPathExists(tests.Out+relativePath, false), "bottom chain directory, 'd', is missing")
  1950  
  1951  	// Cleanup
  1952  	cleanArtifactoryTest()
  1953  }
  1954  
  1955  func TestArtifactoryFlatFolderDownload1(t *testing.T) {
  1956  	initArtifactoryTest(t)
  1957  	dirInnerPath := fileutils.GetFileSeparator() + "inner" + fileutils.GetFileSeparator() + "folder"
  1958  	canonicalPath := tests.Out + dirInnerPath
  1959  	err := os.MkdirAll(canonicalPath, 0777)
  1960  	assert.NoError(t, err)
  1961  	// Flat true by default for upload, by using placeholder we indeed create folders hierarchy in Artifactory inner/folder/folder
  1962  	artifactoryCli.Exec("upload", tests.Out+"/(*)", tests.Repo1+"/{1}/", "--include-dirs=true")
  1963  	err = os.RemoveAll(tests.Out)
  1964  	assert.NoError(t, err)
  1965  	// Only the inner folder should be downland e.g 'folder'
  1966  	artifactoryCli.Exec("download", tests.Repo1, tests.Out+"/", "--include-dirs=true", "--flat=true")
  1967  	assert.False(t, !fileutils.IsPathExists(tests.Out+fileutils.GetFileSeparator()+"folder", false) &&
  1968  		fileutils.IsPathExists(tests.Out+fileutils.GetFileSeparator()+"inner", false),
  1969  		"Failed to download folders from Artifactory")
  1970  	// Cleanup
  1971  	cleanArtifactoryTest()
  1972  }
  1973  
  1974  func TestArtifactoryFolderUploadRecursiveUsingSpec(t *testing.T) {
  1975  	initArtifactoryTest(t)
  1976  	dirInnerPath := "empty" + fileutils.GetFileSeparator() + "folder"
  1977  	canonicalPath := tests.GetTestResourcesPath() + dirInnerPath
  1978  	err := os.MkdirAll(canonicalPath, 0777)
  1979  	assert.NoError(t, err)
  1980  	specFile, err := tests.CreateSpec(tests.UploadEmptyDirs)
  1981  	assert.NoError(t, err)
  1982  	artifactoryCli.Exec("upload", "--spec="+specFile)
  1983  
  1984  	specFile, err = tests.CreateSpec(tests.DownloadEmptyDirs)
  1985  	assert.NoError(t, err)
  1986  	artifactoryCli.Exec("download", "--spec="+specFile)
  1987  	assert.True(t, fileutils.IsPathExists(tests.Out+"/folder", false), "Failed to download folders from Artifactory")
  1988  	// Cleanup
  1989  	cleanArtifactoryTest()
  1990  }
  1991  
  1992  func TestArtifactoryFolderUploadNonRecursive(t *testing.T) {
  1993  	initArtifactoryTest(t)
  1994  	canonicalPath := tests.Out + fileutils.GetFileSeparator() + "inner" + fileutils.GetFileSeparator() + "folder"
  1995  	err := os.MkdirAll(canonicalPath, 0777)
  1996  	assert.NoError(t, err)
  1997  	artifactoryCli.Exec("upload", tests.Out+"/", tests.Repo1, "--recursive=true", "--include-dirs=true")
  1998  	err = os.RemoveAll(tests.Out)
  1999  	assert.NoError(t, err)
  2000  	artifactoryCli.Exec("download", tests.Repo1, tests.Out+"/", "--include-dirs=true")
  2001  	assert.True(t, fileutils.IsPathExists(tests.Out+"/folder", false), "Failed to download folder from Artifactory")
  2002  	assert.False(t, fileutils.IsPathExists(canonicalPath, false), "Path should be flat ")
  2003  	// Cleanup
  2004  	cleanArtifactoryTest()
  2005  }
  2006  
  2007  func TestArtifactoryFolderDownloadNonRecursive(t *testing.T) {
  2008  	initArtifactoryTest(t)
  2009  	canonicalPath := tests.Out + fileutils.GetFileSeparator() + "inner" + fileutils.GetFileSeparator() + "folder"
  2010  	err := os.MkdirAll(canonicalPath, 0777)
  2011  	assert.NoError(t, err)
  2012  	artifactoryCli.Exec("upload", tests.Out+"/", tests.Repo1, "--recursive=true", "--include-dirs=true", "--flat=false")
  2013  	err = os.RemoveAll(tests.Out)
  2014  	assert.NoError(t, err)
  2015  	artifactoryCli.Exec("download", tests.Repo1+"/*", "--recursive=false", "--include-dirs=true")
  2016  	assert.True(t, fileutils.IsPathExists(tests.Out, false), "Failed to download folder from Artifactory")
  2017  	assert.False(t, fileutils.IsPathExists(canonicalPath, false), "Path should be flat. ")
  2018  	// Cleanup
  2019  	cleanArtifactoryTest()
  2020  }
  2021  
  2022  func TestArtifactoryChecksumDownload(t *testing.T) {
  2023  	initArtifactoryTest(t)
  2024  
  2025  	var filePath = "testsdata/a/a1.in"
  2026  	artifactoryCli.Exec("upload", filePath, tests.Repo1)
  2027  	testChecksumDownload(t, "/a1.in")
  2028  	// Cleanup
  2029  	cleanArtifactoryTest()
  2030  }
  2031  
  2032  func TestArtifactoryChecksumDownloadRenameFileName(t *testing.T) {
  2033  	initArtifactoryTest(t)
  2034  
  2035  	var filePath = "testsdata/a/a1.in"
  2036  	artifactoryCli.Exec("upload", filePath, tests.Repo1)
  2037  	testChecksumDownload(t, "/a1.out")
  2038  	// Cleanup
  2039  	cleanArtifactoryTest()
  2040  }
  2041  
  2042  func testChecksumDownload(t *testing.T, outFileName string) {
  2043  	artifactoryCli.Exec("download "+tests.Repo1+"/a1.in", tests.Out+outFileName)
  2044  
  2045  	exists, err := fileutils.IsFileExists(tests.Out+outFileName, false)
  2046  	assert.NoError(t, err)
  2047  	assert.True(t, exists, "Failed to download file from Artifactory")
  2048  
  2049  	firstFileInfo, _ := os.Stat(tests.Out + outFileName)
  2050  	firstDownloadTime := firstFileInfo.ModTime()
  2051  
  2052  	artifactoryCli.Exec("download "+tests.Repo1+"/a1.in", tests.Out+outFileName)
  2053  	secondFileInfo, _ := os.Stat(tests.Out + outFileName)
  2054  	secondDownloadTime := secondFileInfo.ModTime()
  2055  
  2056  	assert.Equal(t, firstDownloadTime, secondDownloadTime, "Checksum download failed, the file was downloaded twice")
  2057  }
  2058  
  2059  func TestArtifactoryDownloadByPatternAndBuildUsingSpec(t *testing.T) {
  2060  	initArtifactoryTest(t)
  2061  	buildName, buildNumberA, buildNumberB := "cli-test-build", "10", "11"
  2062  	inttestutils.DeleteBuild(artifactoryDetails.Url, buildName, artHttpDetails)
  2063  	specFile, err := tests.CreateSpec(tests.BuildDownloadSpec)
  2064  	assert.NoError(t, err)
  2065  	// Upload files with buildName and buildNumber
  2066  	specFileA, err := tests.CreateSpec(tests.SplitUploadSpecA)
  2067  	assert.NoError(t, err)
  2068  	specFileB, err := tests.CreateSpec(tests.SplitUploadSpecB)
  2069  	assert.NoError(t, err)
  2070  	artifactoryCli.Exec("upload", "--spec="+specFileA, "--build-name="+buildName, "--build-number="+buildNumberA)
  2071  	artifactoryCli.Exec("upload", "--spec="+specFileB, "--build-name="+buildName, "--build-number="+buildNumberB)
  2072  
  2073  	// Publish buildInfo
  2074  	artifactoryCli.Exec("build-publish", buildName, buildNumberA)
  2075  	artifactoryCli.Exec("build-publish", buildName, buildNumberB)
  2076  
  2077  	// Download by build number
  2078  	artifactoryCli.Exec("download", "--spec="+specFile)
  2079  
  2080  	// Validate files are downloaded by build number
  2081  	paths, _ := fileutils.ListFilesRecursiveWalkIntoDirSymlink(tests.Out, false)
  2082  	err = tests.ValidateListsIdentical(tests.GetBuildDownload(), paths)
  2083  	assert.NoError(t, err)
  2084  
  2085  	// Cleanup
  2086  	inttestutils.DeleteBuild(artifactoryDetails.Url, buildName, artHttpDetails)
  2087  	cleanArtifactoryTest()
  2088  }
  2089  
  2090  func TestArtifactoryGenericBuildnameAndNumberFromEnv(t *testing.T) {
  2091  	initArtifactoryTest(t)
  2092  	buildName, buildNumberA, buildNumberB := "cli-test-build", "10", "11"
  2093  	inttestutils.DeleteBuild(artifactoryDetails.Url, buildName, artHttpDetails)
  2094  	specFile, err := tests.CreateSpec(tests.BuildDownloadSpec)
  2095  	assert.NoError(t, err)
  2096  	// Upload files with buildName and buildNumber
  2097  	specFileA, err := tests.CreateSpec(tests.SplitUploadSpecA)
  2098  	assert.NoError(t, err)
  2099  	specFileB, err := tests.CreateSpec(tests.SplitUploadSpecB)
  2100  	assert.NoError(t, err)
  2101  	os.Setenv(cliutils.BuildName, buildName)
  2102  	os.Setenv(cliutils.BuildNumber, buildNumberA)
  2103  	defer os.Unsetenv(cliutils.BuildName)
  2104  	defer os.Unsetenv(cliutils.BuildNumber)
  2105  	artifactoryCli.Exec("upload", "--spec="+specFileA)
  2106  	os.Setenv(cliutils.BuildNumber, "11")
  2107  	artifactoryCli.Exec("upload", "--spec="+specFileB)
  2108  
  2109  	// Publish buildInfo
  2110  	os.Setenv(cliutils.BuildNumber, buildNumberA)
  2111  	artifactoryCli.Exec("build-publish")
  2112  	os.Setenv(cliutils.BuildNumber, buildNumberB)
  2113  	artifactoryCli.Exec("build-publish")
  2114  
  2115  	// Download by build number
  2116  	artifactoryCli.Exec("download", "--spec="+specFile)
  2117  
  2118  	// Validate files are downloaded by build number
  2119  	paths, _ := fileutils.ListFilesRecursiveWalkIntoDirSymlink(tests.Out, false)
  2120  	err = tests.ValidateListsIdentical(tests.GetBuildDownload(), paths)
  2121  	assert.NoError(t, err)
  2122  
  2123  	// Cleanup
  2124  	inttestutils.DeleteBuild(artifactoryDetails.Url, buildName, artHttpDetails)
  2125  	cleanArtifactoryTest()
  2126  }
  2127  
  2128  func TestArtifactoryDownloadByBuildNoPatternUsingSpec(t *testing.T) {
  2129  	initArtifactoryTest(t)
  2130  	buildName, buildNumberA, buildNumberB := "cli-test-build", "10", "11"
  2131  	inttestutils.DeleteBuild(artifactoryDetails.Url, buildName, artHttpDetails)
  2132  	specFile, err := tests.CreateSpec(tests.BuildDownloadSpecNoPattern)
  2133  	assert.NoError(t, err)
  2134  	// Upload files with buildName and buildNumber
  2135  	specFileA, err := tests.CreateSpec(tests.SplitUploadSpecA)
  2136  	assert.NoError(t, err)
  2137  	specFileB, err := tests.CreateSpec(tests.SplitUploadSpecB)
  2138  	assert.NoError(t, err)
  2139  	artifactoryCli.Exec("upload", "--spec="+specFileA, "--build-name="+buildName, "--build-number="+buildNumberA)
  2140  	artifactoryCli.Exec("upload", "--spec="+specFileB, "--build-name="+buildName, "--build-number="+buildNumberB)
  2141  
  2142  	// Publish buildInfo
  2143  	artifactoryCli.Exec("build-publish", buildName, buildNumberA)
  2144  	artifactoryCli.Exec("build-publish", buildName, buildNumberB)
  2145  
  2146  	// Download by build number
  2147  	artifactoryCli.Exec("download", "--spec="+specFile)
  2148  
  2149  	// Validate files are downloaded by build number
  2150  	paths, _ := fileutils.ListFilesRecursiveWalkIntoDirSymlink(tests.Out, false)
  2151  	err = tests.ValidateListsIdentical(tests.GetBuildDownload(), paths)
  2152  	assert.NoError(t, err)
  2153  
  2154  	// Cleanup
  2155  	inttestutils.DeleteBuild(artifactoryDetails.Url, buildName, artHttpDetails)
  2156  	cleanArtifactoryTest()
  2157  }
  2158  
  2159  // Upload a file to build A.
  2160  // Verify that it doesn't exist in B.
  2161  func TestArtifactoryDownloadArtifactDoesntExistInBuild(t *testing.T) {
  2162  	initArtifactoryTest(t)
  2163  	buildName, buildNumber := "cli-test-build1", "10"
  2164  	inttestutils.DeleteBuild(artifactoryDetails.Url, buildName, artHttpDetails)
  2165  	specFile, err := tests.CreateSpec(tests.BuildDownloadSpecNoBuildNumber)
  2166  	assert.NoError(t, err)
  2167  	// Upload a file
  2168  	artifactoryCli.Exec("upload", "testsdata/a/a1.in", tests.Repo1+"/data/a10.in", "--build-name="+buildName, "--build-number="+buildNumber)
  2169  
  2170  	// Publish buildInfo
  2171  	artifactoryCli.Exec("build-publish", buildName, buildNumber)
  2172  
  2173  	// Download from different build number
  2174  	artifactoryCli.Exec("download", "--spec="+specFile)
  2175  
  2176  	paths, _ := fileutils.ListFilesRecursiveWalkIntoDirSymlink(tests.Out, false)
  2177  	err = tests.ValidateListsIdentical(tests.GetBuildDownloadDoesntExist(), paths)
  2178  	assert.NoError(t, err)
  2179  
  2180  	// Cleanup
  2181  	inttestutils.DeleteBuild(artifactoryDetails.Url, buildName, artHttpDetails)
  2182  	cleanArtifactoryTest()
  2183  }
  2184  
  2185  // Upload a file to 2 different builds.
  2186  // Verify that we don't download files with same sha and different build name and build number.
  2187  func TestArtifactoryDownloadByShaAndBuild(t *testing.T) {
  2188  	initArtifactoryTest(t)
  2189  	buildNameA, buildNameB, buildNumberA, buildNumberB, buildNumberC := "cli-test-build1", "cli-test-build2", "10", "11", "12"
  2190  	inttestutils.DeleteBuild(artifactoryDetails.Url, buildNameA, artHttpDetails)
  2191  	inttestutils.DeleteBuild(artifactoryDetails.Url, buildNameB, artHttpDetails)
  2192  	specFile, err := tests.CreateSpec(tests.BuildDownloadSpecNoBuildNumber)
  2193  	assert.NoError(t, err)
  2194  
  2195  	// Upload 3 similar files to 3 different builds
  2196  	artifactoryCli.Exec("upload", "testsdata/a/a1.in", tests.Repo1+"/data/a10.in", "--build-name="+buildNameB, "--build-number="+buildNumberA)
  2197  	artifactoryCli.Exec("upload", "testsdata/a/a1.in", tests.Repo1+"/data/a11.in", "--build-name="+buildNameA, "--build-number="+buildNumberB)
  2198  	artifactoryCli.Exec("upload", "testsdata/a/a1.in", tests.Repo1+"/data/a12.in", "--build-name="+buildNameA, "--build-number="+buildNumberC)
  2199  
  2200  	// Publish buildInfo
  2201  	artifactoryCli.Exec("build-publish", buildNameB, buildNumberA)
  2202  	artifactoryCli.Exec("build-publish", buildNameA, buildNumberB)
  2203  	artifactoryCli.Exec("build-publish", buildNameA, buildNumberC)
  2204  
  2205  	// Download by build number
  2206  	artifactoryCli.Exec("download", "--spec="+specFile)
  2207  
  2208  	paths, _ := fileutils.ListFilesRecursiveWalkIntoDirSymlink(tests.Out, false)
  2209  	err = tests.ValidateListsIdentical(tests.GetBuildDownloadByShaAndBuild(), paths)
  2210  	assert.NoError(t, err)
  2211  
  2212  	// Cleanup
  2213  	inttestutils.DeleteBuild(artifactoryDetails.Url, buildNameA, artHttpDetails)
  2214  	inttestutils.DeleteBuild(artifactoryDetails.Url, buildNameB, artHttpDetails)
  2215  	cleanArtifactoryTest()
  2216  }
  2217  
  2218  // Upload a file to 2 different builds.
  2219  // Verify that we don't download files with same sha and build name and different build number.
  2220  func TestArtifactoryDownloadByShaAndBuildName(t *testing.T) {
  2221  	initArtifactoryTest(t)
  2222  	buildNameA, buildNameB, buildNumberA, buildNumberB, buildNumberC := "cli-test-build1", "cli-test-build2", "10", "11", "12"
  2223  	inttestutils.DeleteBuild(artifactoryDetails.Url, buildNameA, artHttpDetails)
  2224  	inttestutils.DeleteBuild(artifactoryDetails.Url, buildNameB, artHttpDetails)
  2225  	specFile, err := tests.CreateSpec(tests.BuildDownloadSpecNoBuildNumber)
  2226  	assert.NoError(t, err)
  2227  
  2228  	// Upload 3 similar files to 2 different builds
  2229  	artifactoryCli.Exec("upload", "testsdata/a/a1.in", tests.Repo1+"/data/a10.in", "--build-name="+buildNameB, "--build-number="+buildNumberA)
  2230  	artifactoryCli.Exec("upload", "testsdata/a/a1.in", tests.Repo1+"/data/a11.in", "--build-name="+buildNameB, "--build-number="+buildNumberB)
  2231  	artifactoryCli.Exec("upload", "testsdata/a/a1.in", tests.Repo1+"/data/a12.in", "--build-name="+buildNameA, "--build-number="+buildNumberC)
  2232  
  2233  	// Publish buildInfo
  2234  	artifactoryCli.Exec("build-publish", buildNameA, buildNumberC)
  2235  	artifactoryCli.Exec("build-publish", buildNameB, buildNumberA)
  2236  	artifactoryCli.Exec("build-publish", buildNameB, buildNumberB)
  2237  
  2238  	// Download by build number
  2239  	artifactoryCli.Exec("download", "--spec="+specFile)
  2240  
  2241  	paths, _ := fileutils.ListFilesRecursiveWalkIntoDirSymlink(tests.Out, false)
  2242  	err = tests.ValidateListsIdentical(tests.GetBuildDownloadByShaAndBuildName(), paths)
  2243  	assert.NoError(t, err)
  2244  
  2245  	// Cleanup
  2246  	inttestutils.DeleteBuild(artifactoryDetails.Url, buildNameA, artHttpDetails)
  2247  	inttestutils.DeleteBuild(artifactoryDetails.Url, buildNameB, artHttpDetails)
  2248  	cleanArtifactoryTest()
  2249  }
  2250  
  2251  func TestArtifactoryDownloadByBuildUsingSimpleDownload(t *testing.T) {
  2252  	initArtifactoryTest(t)
  2253  	buildName, buildNumberA, buildNumberB := "cli-test-build", "10", "11"
  2254  	inttestutils.DeleteBuild(artifactoryDetails.Url, buildName, artHttpDetails)
  2255  
  2256  	// Upload files with buildName and buildNumber
  2257  	specFileA, err := tests.CreateSpec(tests.SplitUploadSpecA)
  2258  	assert.NoError(t, err)
  2259  	specFileB, err := tests.CreateSpec(tests.SplitUploadSpecB)
  2260  	assert.NoError(t, err)
  2261  	artifactoryCli.Exec("upload", "--spec="+specFileA, "--build-name="+buildName, "--build-number="+buildNumberA)
  2262  	artifactoryCli.Exec("upload", "--spec="+specFileB, "--build-name="+buildName, "--build-number="+buildNumberB)
  2263  
  2264  	// Publish buildInfo
  2265  	artifactoryCli.Exec("build-publish", buildName, buildNumberA)
  2266  	artifactoryCli.Exec("build-publish", buildName, buildNumberB)
  2267  
  2268  	// Download by build number, a1 should not be downloaded, b1 should
  2269  	artifactoryCli.Exec("download "+tests.Repo1+"/data/a1.in "+tests.Out+fileutils.GetFileSeparator()+"download"+fileutils.GetFileSeparator()+"simple_by_build"+fileutils.GetFileSeparator(), "--build="+buildName)
  2270  	artifactoryCli.Exec("download "+tests.Repo1+"/data/b1.in "+tests.Out+fileutils.GetFileSeparator()+"download"+fileutils.GetFileSeparator()+"simple_by_build"+fileutils.GetFileSeparator(), "--build="+buildName)
  2271  
  2272  	// Validate files are downloaded by build number
  2273  	paths, _ := fileutils.ListFilesRecursiveWalkIntoDirSymlink(tests.Out, false)
  2274  	err = tests.ValidateListsIdentical(tests.GetBuildSimpleDownload(), paths)
  2275  	assert.NoError(t, err)
  2276  
  2277  	// Cleanup
  2278  	inttestutils.DeleteBuild(artifactoryDetails.Url, buildName, artHttpDetails)
  2279  	cleanArtifactoryTest()
  2280  }
  2281  
  2282  func TestArtifactoryDownloadByBuildNoPatternUsingSimpleDownload(t *testing.T) {
  2283  	initArtifactoryTest(t)
  2284  	buildName, buildNumberA, buildNumberB := "cli-test-build", "10", "11"
  2285  	inttestutils.DeleteBuild(artifactoryDetails.Url, buildName, artHttpDetails)
  2286  
  2287  	// Upload files with buildName and buildNumber
  2288  	specFileA, err := tests.CreateSpec(tests.SplitUploadSpecA)
  2289  	assert.NoError(t, err)
  2290  	specFileB, err := tests.CreateSpec(tests.SplitUploadSpecB)
  2291  	assert.NoError(t, err)
  2292  
  2293  	artifactoryCli.Exec("upload", "--spec="+specFileA, "--build-name="+buildName, "--build-number="+buildNumberA)
  2294  	artifactoryCli.Exec("upload", "--spec="+specFileB, "--build-name="+buildName, "--build-number="+buildNumberB)
  2295  
  2296  	// Publish buildInfo
  2297  	artifactoryCli.Exec("build-publish", buildName, buildNumberA)
  2298  	artifactoryCli.Exec("build-publish", buildName, buildNumberB)
  2299  
  2300  	// Download by build number, a1 should not be downloaded, b1 should
  2301  	artifactoryCli.Exec("download * "+tests.Out+fileutils.GetFileSeparator()+"download"+fileutils.GetFileSeparator()+"simple_by_build"+fileutils.GetFileSeparator(), "--build="+buildName+"/"+buildNumberA)
  2302  
  2303  	// Validate files are downloaded by build number
  2304  	paths, _ := fileutils.ListFilesRecursiveWalkIntoDirSymlink(tests.Out, false)
  2305  	err = tests.ValidateListsIdentical(tests.GetBuildSimpleDownloadNoPattern(), paths)
  2306  	assert.NoError(t, err)
  2307  
  2308  	// Cleanup
  2309  	inttestutils.DeleteBuild(artifactoryDetails.Url, buildName, artHttpDetails)
  2310  	cleanArtifactoryTest()
  2311  }
  2312  
  2313  func TestArtifactoryDownloadByArchiveEntriesCli(t *testing.T) {
  2314  	initArtifactoryTest(t)
  2315  	uploadSpecFile, err := tests.CreateSpec(tests.ArchiveEntriesUpload)
  2316  	assert.NoError(t, err)
  2317  
  2318  	// Upload archives
  2319  	artifactoryCli.Exec("upload", "--spec="+uploadSpecFile)
  2320  
  2321  	// Create executor for running with retries
  2322  	retryExecutor := createRetryExecutorForArchiveEntries(tests.GetBuildArchiveEntriesDownloadCli(),
  2323  		[]string{"dl", tests.Repo1, "out/", "--archive-entries=(*)c1.in", "--flat=true"})
  2324  
  2325  	// Perform download by archive-entries only the archives containing c1.in, and validate results
  2326  	assert.NoError(t, retryExecutor.Execute())
  2327  
  2328  	// Cleanup
  2329  	cleanArtifactoryTest()
  2330  }
  2331  
  2332  func TestArtifactoryDownloadByArchiveEntriesSpecificPathCli(t *testing.T) {
  2333  	initArtifactoryTest(t)
  2334  	uploadSpecFile, err := tests.CreateSpec(tests.ArchiveEntriesUpload)
  2335  	assert.NoError(t, err)
  2336  
  2337  	// Upload archives
  2338  	artifactoryCli.Exec("upload", "--spec="+uploadSpecFile)
  2339  
  2340  	// Create executor for running with retries
  2341  	retryExecutor := createRetryExecutorForArchiveEntries(tests.GetBuildArchiveEntriesSpecificPathDownload(),
  2342  		[]string{"dl", tests.Repo1, "out/", "--archive-entries=b/c/c1.in", "--flat=true"})
  2343  
  2344  	// Perform download by archive-entries only the archives containing c1.in, and validate results
  2345  	assert.NoError(t, retryExecutor.Execute())
  2346  
  2347  	// Cleanup
  2348  	cleanArtifactoryTest()
  2349  }
  2350  
  2351  func TestArtifactoryDownloadByArchiveEntriesSpec(t *testing.T) {
  2352  	initArtifactoryTest(t)
  2353  	uploadSpecFile, err := tests.CreateSpec(tests.ArchiveEntriesUpload)
  2354  	assert.NoError(t, err)
  2355  	downloadSpecFile, err := tests.CreateSpec(tests.ArchiveEntriesDownload)
  2356  	assert.NoError(t, err)
  2357  
  2358  	// Upload archives
  2359  	artifactoryCli.Exec("upload", "--spec="+uploadSpecFile)
  2360  
  2361  	// Create executor for running with retries
  2362  	retryExecutor := createRetryExecutorForArchiveEntries(tests.GetBuildArchiveEntriesDownloadSpec(),
  2363  		[]string{"dl", "--spec=" + downloadSpecFile})
  2364  
  2365  	// Perform download by archive-entries only the archives containing d1.in, and validate results
  2366  	assert.NoError(t, retryExecutor.Execute())
  2367  
  2368  	// Cleanup
  2369  	cleanArtifactoryTest()
  2370  }
  2371  
  2372  func createRetryExecutorForArchiveEntries(expected []string, args []string) *clientutils.RetryExecutor {
  2373  	return &clientutils.RetryExecutor{
  2374  		MaxRetries:      120,
  2375  		RetriesInterval: 1,
  2376  		ErrorMessage:    "Waiting for Artifactory to index archives...",
  2377  		ExecutionHandler: func() (bool, error) {
  2378  			err := validateDownloadByArchiveEntries(expected, args)
  2379  			if err != nil {
  2380  				return true, err
  2381  			}
  2382  
  2383  			return false, nil
  2384  		},
  2385  	}
  2386  }
  2387  
  2388  func validateDownloadByArchiveEntries(expected []string, args []string) error {
  2389  	// Execute the requested cli command
  2390  	artifactoryCli.Exec(args...)
  2391  
  2392  	// Validate files are downloaded as expected
  2393  	paths, _ := fileutils.ListFilesRecursiveWalkIntoDirSymlink(tests.Out, false)
  2394  	return tests.ValidateListsIdentical(expected, paths)
  2395  }
  2396  
  2397  func TestArtifactoryDownloadExcludeByCli(t *testing.T) {
  2398  	initArtifactoryTest(t)
  2399  
  2400  	// Upload files
  2401  	specFileA, err := tests.CreateSpec(tests.SplitUploadSpecA)
  2402  	assert.NoError(t, err)
  2403  	specFileB, err := tests.CreateSpec(tests.SplitUploadSpecB)
  2404  	assert.NoError(t, err)
  2405  	artifactoryCli.Exec("upload", "--spec="+specFileA, "--recursive=true")
  2406  	artifactoryCli.Exec("upload", "--spec="+specFileB, "--recursive=true")
  2407  
  2408  	// Download by pattern
  2409  	artifactoryCli.Exec("download", tests.Repo1+" out/download/aql_by_artifacts/", "--exclude-patterns=*/a1.in;*a2.*;data/c2.in")
  2410  
  2411  	// Validate files are excluded
  2412  	paths, _ := fileutils.ListFilesRecursiveWalkIntoDirSymlink(tests.Out, false)
  2413  	err = tests.ValidateListsIdentical(tests.GetBuildExcludeDownload(), paths)
  2414  	assert.NoError(t, err)
  2415  
  2416  	// Cleanup
  2417  	cleanArtifactoryTest()
  2418  }
  2419  
  2420  func TestArtifactoryDownloadExclusionsByCli(t *testing.T) {
  2421  	initArtifactoryTest(t)
  2422  
  2423  	// Upload files
  2424  	specFileA, err := tests.CreateSpec(tests.SplitUploadSpecA)
  2425  	assert.NoError(t, err)
  2426  	specFileB, err := tests.CreateSpec(tests.SplitUploadSpecB)
  2427  	assert.NoError(t, err)
  2428  	artifactoryCli.Exec("upload", "--spec="+specFileA, "--recursive=true")
  2429  	artifactoryCli.Exec("upload", "--spec="+specFileB, "--recursive=true")
  2430  
  2431  	// Download by pattern
  2432  	artifactoryCli.Exec("download", tests.Repo1+" out/download/aql_by_artifacts/", "--exclusions=*/*/a1.in;*/*a2.*;*/data/c2.in")
  2433  
  2434  	// Validate files are excluded
  2435  	paths, _ := fileutils.ListFilesRecursiveWalkIntoDirSymlink(tests.Out, false)
  2436  	err = tests.ValidateListsIdentical(tests.GetBuildExcludeDownload(), paths)
  2437  	assert.NoError(t, err)
  2438  
  2439  	// Cleanup
  2440  	cleanArtifactoryTest()
  2441  }
  2442  
  2443  func TestArtifactoryDownloadExcludeBySpec(t *testing.T) {
  2444  	initArtifactoryTest(t)
  2445  	specFile, err := tests.CreateSpec(tests.DownloadSpecExclude)
  2446  	assert.NoError(t, err)
  2447  
  2448  	// Upload files
  2449  	specFileA, err := tests.CreateSpec(tests.SplitUploadSpecA)
  2450  	assert.NoError(t, err)
  2451  	specFileB, err := tests.CreateSpec(tests.SplitUploadSpecB)
  2452  	assert.NoError(t, err)
  2453  	artifactoryCli.Exec("upload", "--spec="+specFileA, "--recursive=true", "--flat=false")
  2454  	artifactoryCli.Exec("upload", "--spec="+specFileB, "--recursive=true", "--flat=false")
  2455  
  2456  	// Download by spec
  2457  	artifactoryCli.Exec("download", "--spec="+specFile)
  2458  
  2459  	// Validate files are excluded
  2460  	paths, _ := fileutils.ListFilesRecursiveWalkIntoDirSymlink(tests.Out, false)
  2461  	err = tests.ValidateListsIdentical(tests.GetBuildExcludeDownloadBySpec(), paths)
  2462  	assert.NoError(t, err)
  2463  
  2464  	// Cleanup
  2465  	cleanArtifactoryTest()
  2466  }
  2467  
  2468  func TestArtifactoryDownloadExclusionsBySpec(t *testing.T) {
  2469  	initArtifactoryTest(t)
  2470  	specFile, err := tests.CreateSpec(tests.DownloadSpecExclusions)
  2471  	assert.NoError(t, err)
  2472  
  2473  	// Upload files
  2474  	specFileA, err := tests.CreateSpec(tests.SplitUploadSpecA)
  2475  	assert.NoError(t, err)
  2476  	specFileB, err := tests.CreateSpec(tests.SplitUploadSpecB)
  2477  	assert.NoError(t, err)
  2478  	artifactoryCli.Exec("upload", "--spec="+specFileA, "--recursive=true", "--flat=false")
  2479  	artifactoryCli.Exec("upload", "--spec="+specFileB, "--recursive=true", "--flat=false")
  2480  
  2481  	// Download by spec
  2482  	artifactoryCli.Exec("download", "--spec="+specFile)
  2483  
  2484  	// Validate files are excluded
  2485  	paths, _ := fileutils.ListFilesRecursiveWalkIntoDirSymlink(tests.Out, false)
  2486  	err = tests.ValidateListsIdentical(tests.GetBuildExcludeDownloadBySpec(), paths)
  2487  	assert.NoError(t, err)
  2488  
  2489  	// Cleanup
  2490  	cleanArtifactoryTest()
  2491  }
  2492  
  2493  func TestArtifactoryDownloadExcludeBySpecOverride(t *testing.T) {
  2494  	initArtifactoryTest(t)
  2495  
  2496  	// Upload files with buildName and buildNumber
  2497  	specFileA, err := tests.CreateSpec(tests.SplitUploadSpecA)
  2498  	assert.NoError(t, err)
  2499  	specFileB, err := tests.CreateSpec(tests.SplitUploadSpecB)
  2500  	assert.NoError(t, err)
  2501  	artifactoryCli.Exec("upload", "--spec="+specFileA, "--recursive=true", "--flat=false")
  2502  	artifactoryCli.Exec("upload", "--spec="+specFileB, "--recursive=true", "--flat=false")
  2503  
  2504  	// Download by spec
  2505  	specFile, err := tests.CreateSpec(tests.DownloadSpecExclude)
  2506  	assert.NoError(t, err)
  2507  	artifactoryCli.Exec("download", "--spec="+specFile, "--exclude-patterns=*a1.in;*a2.in;*c2.in")
  2508  
  2509  	// Validate files are downloaded by build number
  2510  	paths, _ := fileutils.ListFilesRecursiveWalkIntoDirSymlink(tests.Out, false)
  2511  	err = tests.ValidateListsIdentical(tests.GetBuildExcludeDownload(), paths)
  2512  	assert.NoError(t, err)
  2513  
  2514  	// Cleanup
  2515  	cleanArtifactoryTest()
  2516  }
  2517  
  2518  func TestArtifactoryDownloadExclusionsBySpecOverride(t *testing.T) {
  2519  	initArtifactoryTest(t)
  2520  
  2521  	// Upload files with buildName and buildNumber
  2522  	specFileA, err := tests.CreateSpec(tests.SplitUploadSpecA)
  2523  	assert.NoError(t, err)
  2524  	specFileB, err := tests.CreateSpec(tests.SplitUploadSpecB)
  2525  	assert.NoError(t, err)
  2526  	artifactoryCli.Exec("upload", "--spec="+specFileA, "--recursive=true", "--flat=false")
  2527  	artifactoryCli.Exec("upload", "--spec="+specFileB, "--recursive=true", "--flat=false")
  2528  
  2529  	// Download by spec
  2530  	specFile, err := tests.CreateSpec(tests.DownloadSpecExclusions)
  2531  	assert.NoError(t, err)
  2532  	artifactoryCli.Exec("download", "--spec="+specFile, "--exclusions=*a1.in;*a2.in;*c2.in")
  2533  
  2534  	// Validate files are downloaded by build number
  2535  	paths, _ := fileutils.ListFilesRecursiveWalkIntoDirSymlink(tests.Out, false)
  2536  	err = tests.ValidateListsIdentical(tests.GetBuildExcludeDownload(), paths)
  2537  	assert.NoError(t, err)
  2538  
  2539  	// Cleanup
  2540  	cleanArtifactoryTest()
  2541  }
  2542  
  2543  // Sort and limit changes the way properties are used so this should be tested with symlinks and search by build
  2544  
  2545  // Upload symlink by full path to Artifactory and the link content checksum
  2546  // Download the symlink which was uploaded with limit param.
  2547  // validate the symlink content checksum.
  2548  func TestArtifactoryLimitWithSymlink(t *testing.T) {
  2549  	if cliutils.IsWindows() {
  2550  		t.Skip("Running on windows, skipping...")
  2551  	}
  2552  	initArtifactoryTest(t)
  2553  	localFile := filepath.Join(tests.GetTestResourcesPath()+"a", "a1.in")
  2554  	link := filepath.Join(tests.GetTestResourcesPath()+"a", "link")
  2555  	err := os.Symlink(localFile, link)
  2556  	assert.NoError(t, err)
  2557  	artifactoryCli.Exec("u", link+" "+tests.Repo1+" --symlinks=true")
  2558  	err = os.Remove(link)
  2559  	assert.NoError(t, err)
  2560  	artifactoryCli.Exec("dl", tests.Repo1+"/link "+tests.GetTestResourcesPath()+"a/ --validate-symlinks=true --limit=1")
  2561  	validateSortLimitWithSymLink(link, localFile, t)
  2562  	os.Remove(link)
  2563  	cleanArtifactoryTest()
  2564  }
  2565  
  2566  // Upload symlink by full path to Artifactory and the link content checksum
  2567  // Download the symlink which was uploaded with limit param.
  2568  // validate the symlink content checksum.
  2569  func TestArtifactorySortWithSymlink(t *testing.T) {
  2570  	if cliutils.IsWindows() {
  2571  		t.Skip("Running on windows, skipping...")
  2572  	}
  2573  	initArtifactoryTest(t)
  2574  	localFile := filepath.Join(tests.GetTestResourcesPath()+"a", "a1.in")
  2575  	link := filepath.Join(tests.GetTestResourcesPath()+"a", "link")
  2576  	err := os.Symlink(localFile, link)
  2577  	assert.NoError(t, err)
  2578  	artifactoryCli.Exec("u", link+" "+tests.Repo1+" --symlinks=true")
  2579  	err = os.Remove(link)
  2580  	assert.NoError(t, err)
  2581  	artifactoryCli.Exec("dl", tests.Repo1+"/link "+tests.GetTestResourcesPath()+"a/ --validate-symlinks=true --sort-by=created")
  2582  	validateSortLimitWithSymLink(link, localFile, t)
  2583  	os.Remove(link)
  2584  	cleanArtifactoryTest()
  2585  }
  2586  
  2587  func validateSortLimitWithSymLink(localLinkPath, localFilePath string, t *testing.T) {
  2588  	exists := fileutils.IsPathSymlink(localLinkPath)
  2589  	assert.True(t, exists, "failed to download symlinks from artifactory with Sort/Limit flag")
  2590  	symlinks, err := filepath.EvalSymlinks(localLinkPath)
  2591  	assert.NoError(t, err, "can't eval symlinks with Sort/Limit flag")
  2592  	assert.Equal(t, localFilePath, symlinks, "Symlinks wasn't created as expected with Sort/Limit flag")
  2593  }
  2594  
  2595  // Upload a file to 2 different builds.
  2596  // Verify that we don't download files with same sha and build name and different build number when sort is configured.
  2597  func TestArtifactoryDownloadByShaAndBuildNameWithSort(t *testing.T) {
  2598  	initArtifactoryTest(t)
  2599  	buildNameA, buildNameB, buildNumberA, buildNumberB, buildNumberC := "cli-test-build1", "cli-test-build2", "10", "11", "12"
  2600  	inttestutils.DeleteBuild(artifactoryDetails.Url, buildNameA, artHttpDetails)
  2601  	inttestutils.DeleteBuild(artifactoryDetails.Url, buildNameB, artHttpDetails)
  2602  	specFile, err := tests.CreateSpec(tests.BuildDownloadSpecNoBuildNumberWithSort)
  2603  	assert.NoError(t, err)
  2604  	// Upload 3 similar files to 2 different builds
  2605  	artifactoryCli.Exec("upload", "testsdata/a/a1.in", tests.Repo1+"/data/a10.in", "--build-name="+buildNameB, "--build-number="+buildNumberA)
  2606  	artifactoryCli.Exec("upload", "testsdata/a/a1.in", tests.Repo1+"/data/a11.in", "--build-name="+buildNameB, "--build-number="+buildNumberB)
  2607  	artifactoryCli.Exec("upload", "testsdata/a/a1.in", tests.Repo1+"/data/a12.in", "--build-name="+buildNameA, "--build-number="+buildNumberC)
  2608  
  2609  	// Publish buildInfo
  2610  	artifactoryCli.Exec("build-publish", buildNameA, buildNumberC)
  2611  	artifactoryCli.Exec("build-publish", buildNameB, buildNumberA)
  2612  	artifactoryCli.Exec("build-publish", buildNameB, buildNumberB)
  2613  
  2614  	// Download by build number
  2615  	artifactoryCli.Exec("download", "--sort-by=created --spec="+specFile)
  2616  
  2617  	paths, _ := fileutils.ListFilesRecursiveWalkIntoDirSymlink(filepath.Join(tests.Out, "download", "sort_limit_by_build"), false)
  2618  	err = tests.ValidateListsIdentical(tests.GetBuildDownloadByShaAndBuildNameWithSort(), paths)
  2619  	assert.NoError(t, err)
  2620  
  2621  	// Cleanup
  2622  	inttestutils.DeleteBuild(artifactoryDetails.Url, buildNameA, artHttpDetails)
  2623  	inttestutils.DeleteBuild(artifactoryDetails.Url, buildNameB, artHttpDetails)
  2624  	cleanArtifactoryTest()
  2625  }
  2626  
  2627  func TestArtifactoryCopyByBuildUsingSpec(t *testing.T) {
  2628  	initArtifactoryTest(t)
  2629  	buildName, buildNumberA, buildNumberB := "cli-test-build", "10", "11"
  2630  	inttestutils.DeleteBuild(artifactoryDetails.Url, buildName, artHttpDetails)
  2631  	specFile, err := tests.CreateSpec(tests.CopyByBuildSpec)
  2632  	assert.NoError(t, err)
  2633  	// Upload files with buildName and buildNumber: a* uploaded with build number "10", b* uploaded with build number "11"
  2634  	specFileA, err := tests.CreateSpec(tests.SplitUploadSpecA)
  2635  	assert.NoError(t, err)
  2636  	specFileB, err := tests.CreateSpec(tests.SplitUploadSpecB)
  2637  	assert.NoError(t, err)
  2638  	artifactoryCli.Exec("upload", "--spec="+specFileA, "--build-name="+buildName, "--build-number="+buildNumberA)
  2639  	artifactoryCli.Exec("upload", "--spec="+specFileB, "--build-name="+buildName, "--build-number="+buildNumberB)
  2640  
  2641  	// Publish buildInfo
  2642  	artifactoryCli.Exec("build-publish", buildName, buildNumberA)
  2643  	artifactoryCli.Exec("build-publish", buildName, buildNumberB)
  2644  
  2645  	// Copy by build name "cli-test-build" and build number "10" from spec, a* should be copied
  2646  	artifactoryCli.Exec("copy", "--spec="+specFile)
  2647  
  2648  	// Validate files are Copied by build number
  2649  	cpMvDlByBuildAssertSpec, err := tests.CreateSpec(tests.CpMvDlByBuildAssertSpec)
  2650  	assert.NoError(t, err)
  2651  	verifyExistInArtifactory(tests.GetBuildCopyExpected(), cpMvDlByBuildAssertSpec, t)
  2652  
  2653  	// Cleanup
  2654  	inttestutils.DeleteBuild(artifactoryDetails.Url, buildName, artHttpDetails)
  2655  	cleanArtifactoryTest()
  2656  }
  2657  
  2658  func TestArtifactoryCopyByBuildPatternAllUsingSpec(t *testing.T) {
  2659  	initArtifactoryTest(t)
  2660  	buildName, buildNumberA, buildNumberB := "cli-test-build", "10", "11"
  2661  	inttestutils.DeleteBuild(artifactoryDetails.Url, buildName, artHttpDetails)
  2662  	specFile, err := tests.CreateSpec(tests.CopyByBuildPatternAllSpec)
  2663  	assert.NoError(t, err)
  2664  	// Upload files with buildName and buildNumber: a* uploaded with build number "10", b* uploaded with build number "11"
  2665  	specFileA, err := tests.CreateSpec(tests.SplitUploadSpecA)
  2666  	assert.NoError(t, err)
  2667  	specFileB, err := tests.CreateSpec(tests.SplitUploadSpecB)
  2668  	assert.NoError(t, err)
  2669  	artifactoryCli.Exec("upload", "--spec="+specFileA, "--build-name="+buildName, "--build-number="+buildNumberA)
  2670  	artifactoryCli.Exec("upload", "--spec="+specFileB, "--build-name="+buildName, "--build-number="+buildNumberB)
  2671  
  2672  	// Publish buildInfo
  2673  	artifactoryCli.Exec("build-publish", buildName, buildNumberA)
  2674  	artifactoryCli.Exec("build-publish", buildName, buildNumberB)
  2675  
  2676  	// Copy by build name "cli-test-build" and build number "10" from spec, a* should be copied
  2677  	artifactoryCli.Exec("copy", "--spec="+specFile)
  2678  
  2679  	// Validate files are Copied by build number
  2680  	cpMvDlByBuildAssertSpec, err := tests.CreateSpec(tests.CpMvDlByBuildAssertSpec)
  2681  	assert.NoError(t, err)
  2682  	verifyExistInArtifactory(tests.GetBuildCopyExpected(), cpMvDlByBuildAssertSpec, t)
  2683  
  2684  	// Cleanup
  2685  	inttestutils.DeleteBuild(artifactoryDetails.Url, buildName, artHttpDetails)
  2686  	cleanArtifactoryTest()
  2687  }
  2688  
  2689  func TestArtifactorySortAndLimit(t *testing.T) {
  2690  	initArtifactoryTest(t)
  2691  
  2692  	// Upload all testdata/a/ files
  2693  	artifactoryCli.Exec("upload", "testsdata/a/(*)", tests.Repo1+"/data/{1}")
  2694  
  2695  	// Download 1 sorted by name asc
  2696  	artifactoryCli.Exec("download", tests.Repo1+"/data/ out/download/sort_limit/", "--sort-by=name", "--limit=1")
  2697  
  2698  	// Download 3 sorted by depth desc
  2699  	artifactoryCli.Exec("download", tests.Repo1+"/data/ out/download/sort_limit/", "--sort-by=depth", "--limit=3", "--sort-order=desc")
  2700  
  2701  	paths, _ := fileutils.ListFilesRecursiveWalkIntoDirSymlink(tests.Out, false)
  2702  	err := tests.ValidateListsIdentical(tests.GetSortAndLimit(), paths)
  2703  	assert.NoError(t, err)
  2704  
  2705  	// Cleanup
  2706  	cleanArtifactoryTest()
  2707  }
  2708  
  2709  func TestArtifactoryOffset(t *testing.T) {
  2710  	initArtifactoryTest(t)
  2711  
  2712  	// Upload all testdata/a/ files
  2713  	artifactoryCli.Exec("upload", "testsdata/a/*", path.Join(tests.Repo1, "offset_test")+"/", "--flat=true")
  2714  
  2715  	// Downloading files one by one, to check that the offset is working as expected.
  2716  	// Download only the first file, expecting to download a1.in
  2717  	artifactoryCli.Exec("download", tests.Repo1+"/offset_test/", tests.Out+"/", "--flat=true", "--sort-by=name", "--limit=1", "--offset=0")
  2718  	paths, _ := fileutils.ListFilesRecursiveWalkIntoDirSymlink(tests.Out, false)
  2719  	tests.VerifyExistLocally([]string{tests.Out + fileutils.GetFileSeparator() + "a1.in"}, paths, t)
  2720  
  2721  	// Download the second file, expecting to download a2.in
  2722  	artifactoryCli.Exec("download", tests.Repo1+"/offset_test/", tests.Out+"/", "--flat=true", "--sort-by=name", "--limit=1", "--offset=1")
  2723  	paths, _ = fileutils.ListFilesRecursiveWalkIntoDirSymlink(tests.Out, false)
  2724  	tests.VerifyExistLocally([]string{tests.Out + fileutils.GetFileSeparator() + "a2.in"}, paths, t)
  2725  
  2726  	// Download the third file, expecting to download a3.in
  2727  	artifactoryCli.Exec("download", tests.Repo1+"/offset_test/", tests.Out+"/", "--flat=true", "--sort-by=name", "--limit=1", "--offset=2")
  2728  	paths, _ = fileutils.ListFilesRecursiveWalkIntoDirSymlink(tests.Out, false)
  2729  	tests.VerifyExistLocally([]string{tests.Out + fileutils.GetFileSeparator() + "a3.in"}, paths, t)
  2730  
  2731  	// Cleanup
  2732  	cleanArtifactoryTest()
  2733  }
  2734  
  2735  func TestArtifactoryCopyByBuildOverridingByInlineFlag(t *testing.T) {
  2736  	initArtifactoryTest(t)
  2737  	buildName, buildNumberA, buildNumberB := "cli-test-build", "10", "11"
  2738  	inttestutils.DeleteBuild(artifactoryDetails.Url, buildName, artHttpDetails)
  2739  	specFile, err := tests.CreateSpec(tests.CopyByBuildSpec)
  2740  	assert.NoError(t, err)
  2741  
  2742  	// Upload files with buildName and buildNumber: b* uploaded with build number "10", a* uploaded with build number "11"
  2743  	specFileA, err := tests.CreateSpec(tests.SplitUploadSpecA)
  2744  	assert.NoError(t, err)
  2745  	specFileB, err := tests.CreateSpec(tests.SplitUploadSpecB)
  2746  	assert.NoError(t, err)
  2747  	artifactoryCli.Exec("upload", "--spec="+specFileB, "--build-name="+buildName, "--build-number="+buildNumberA)
  2748  	artifactoryCli.Exec("upload", "--spec="+specFileA, "--build-name="+buildName, "--build-number="+buildNumberB)
  2749  
  2750  	// Publish buildInfo
  2751  	artifactoryCli.Exec("build-publish", buildName, buildNumberA)
  2752  	artifactoryCli.Exec("build-publish", buildName, buildNumberB)
  2753  
  2754  	// 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
  2755  	artifactoryCli.Exec("copy", "--build="+buildName+" --spec="+specFile)
  2756  
  2757  	// Validate files are Copied by build number
  2758  	cpMvDlByBuildAssertSpec, err := tests.CreateSpec(tests.CpMvDlByBuildAssertSpec)
  2759  	assert.NoError(t, err)
  2760  
  2761  	verifyExistInArtifactory(tests.GetBuildCopyExpected(), cpMvDlByBuildAssertSpec, t)
  2762  
  2763  	// Cleanup
  2764  	inttestutils.DeleteBuild(artifactoryDetails.Url, buildName, artHttpDetails)
  2765  	cleanArtifactoryTest()
  2766  }
  2767  
  2768  func TestArtifactoryMoveByBuildUsingFlags(t *testing.T) {
  2769  	initArtifactoryTest(t)
  2770  	buildName, buildNumberA, buildNumberB := "cli-test-build", "10", "11"
  2771  	inttestutils.DeleteBuild(artifactoryDetails.Url, buildName, artHttpDetails)
  2772  	specFile, err := tests.CreateSpec(tests.CopyByBuildSpec)
  2773  	assert.NoError(t, err)
  2774  
  2775  	// Upload files with buildName and buildNumber
  2776  	specFileA, err := tests.CreateSpec(tests.SplitUploadSpecA)
  2777  	assert.NoError(t, err)
  2778  	specFileB, err := tests.CreateSpec(tests.SplitUploadSpecB)
  2779  	assert.NoError(t, err)
  2780  	artifactoryCli.Exec("upload", "--spec="+specFileB, "--build-name="+buildName, "--build-number="+buildNumberA)
  2781  	artifactoryCli.Exec("upload", "--spec="+specFileA, "--build-name="+buildName, "--build-number="+buildNumberB)
  2782  
  2783  	// Publish buildInfo
  2784  	artifactoryCli.Exec("build-publish", buildName, buildNumberA)
  2785  	artifactoryCli.Exec("build-publish", buildName, buildNumberB)
  2786  
  2787  	// Move by build name and number
  2788  	artifactoryCli.Exec("move", "--build="+buildName+"/11 --spec="+specFile)
  2789  
  2790  	// Validate files are moved by build number
  2791  	cpMvDlByBuildAssertSpec, err := tests.CreateSpec(tests.CpMvDlByBuildAssertSpec)
  2792  	assert.NoError(t, err)
  2793  
  2794  	verifyExistInArtifactory(tests.GetBuildMoveExpected(), cpMvDlByBuildAssertSpec, t)
  2795  
  2796  	// Cleanup
  2797  	inttestutils.DeleteBuild(artifactoryDetails.Url, buildName, artHttpDetails)
  2798  	cleanArtifactoryTest()
  2799  }
  2800  
  2801  func TestArtifactoryMoveNoSpec(t *testing.T) {
  2802  	testCopyMoveNoSpec("mv", tests.GetBuildBeforeMoveExpected(), tests.GetBuildMoveExpected(), t)
  2803  }
  2804  
  2805  func TestArtifactoryMoveExcludeByCli(t *testing.T) {
  2806  	initArtifactoryTest(t)
  2807  
  2808  	// Upload files
  2809  	specFileA, err := tests.CreateSpec(tests.SplitUploadSpecA)
  2810  	assert.NoError(t, err)
  2811  	specFileB, err := tests.CreateSpec(tests.SplitUploadSpecB)
  2812  	assert.NoError(t, err)
  2813  	artifactoryCli.Exec("upload", "--spec="+specFileA)
  2814  	artifactoryCli.Exec("upload", "--spec="+specFileB)
  2815  
  2816  	// Move by pattern
  2817  	artifactoryCli.Exec("move", tests.Repo1+"/data/ "+tests.Repo2+"/", "--exclude-patterns=*b*;*c*")
  2818  
  2819  	// Validate excluded files didn't move
  2820  	cpMvDlByBuildAssertSpec, err := tests.CreateSpec(tests.CpMvDlByBuildAssertSpec)
  2821  	assert.NoError(t, err)
  2822  
  2823  	verifyExistInArtifactory(tests.GetBuildMoveExpected(), cpMvDlByBuildAssertSpec, t)
  2824  
  2825  	// Cleanup
  2826  	cleanArtifactoryTest()
  2827  }
  2828  
  2829  func TestArtifactoryMoveExclusionsByCli(t *testing.T) {
  2830  	initArtifactoryTest(t)
  2831  
  2832  	// Upload files
  2833  	specFileA, err := tests.CreateSpec(tests.SplitUploadSpecA)
  2834  	assert.NoError(t, err)
  2835  	specFileB, err := tests.CreateSpec(tests.SplitUploadSpecB)
  2836  	assert.NoError(t, err)
  2837  	artifactoryCli.Exec("upload", "--spec="+specFileA)
  2838  	artifactoryCli.Exec("upload", "--spec="+specFileB)
  2839  
  2840  	// Move by pattern
  2841  	artifactoryCli.Exec("move", tests.Repo1+"/data/ "+tests.Repo2+"/", "--exclusions=*/*b*;*/*c*")
  2842  
  2843  	// Validate excluded files didn't move
  2844  	cpMvDlByBuildAssertSpec, err := tests.CreateSpec(tests.CpMvDlByBuildAssertSpec)
  2845  	assert.NoError(t, err)
  2846  
  2847  	verifyExistInArtifactory(tests.GetBuildMoveExpected(), cpMvDlByBuildAssertSpec, t)
  2848  
  2849  	// Cleanup
  2850  	cleanArtifactoryTest()
  2851  }
  2852  
  2853  func TestArtifactoryMoveExcludeBySpec(t *testing.T) {
  2854  	initArtifactoryTest(t)
  2855  	specFile, err := tests.CreateSpec(tests.MoveCopySpecExclude)
  2856  	assert.NoError(t, err)
  2857  
  2858  	// Upload files
  2859  	specFileA, err := tests.CreateSpec(tests.SplitUploadSpecA)
  2860  	assert.NoError(t, err)
  2861  	specFileB, err := tests.CreateSpec(tests.SplitUploadSpecB)
  2862  	assert.NoError(t, err)
  2863  	artifactoryCli.Exec("upload", "--spec="+specFileA)
  2864  	artifactoryCli.Exec("upload", "--spec="+specFileB)
  2865  
  2866  	// Move by spec
  2867  	artifactoryCli.Exec("move", "--spec="+specFile)
  2868  
  2869  	// Validate excluded files didn't move
  2870  	cpMvDlByBuildAssertSpec, err := tests.CreateSpec(tests.CpMvDlByBuildAssertSpec)
  2871  	assert.NoError(t, err)
  2872  
  2873  	verifyExistInArtifactory(tests.GetBuildMoveExpected(), cpMvDlByBuildAssertSpec, t)
  2874  
  2875  	// Cleanup
  2876  	cleanArtifactoryTest()
  2877  }
  2878  
  2879  func TestArtifactoryMoveExclusionsBySpec(t *testing.T) {
  2880  	initArtifactoryTest(t)
  2881  	specFile, err := tests.CreateSpec(tests.MoveCopySpecExclusions)
  2882  	assert.NoError(t, err)
  2883  
  2884  	// Upload files
  2885  	specFileA, err := tests.CreateSpec(tests.SplitUploadSpecA)
  2886  	assert.NoError(t, err)
  2887  	specFileB, err := tests.CreateSpec(tests.SplitUploadSpecB)
  2888  	assert.NoError(t, err)
  2889  	artifactoryCli.Exec("upload", "--spec="+specFileA)
  2890  	artifactoryCli.Exec("upload", "--spec="+specFileB)
  2891  
  2892  	// Move by spec
  2893  	artifactoryCli.Exec("move", "--spec="+specFile)
  2894  
  2895  	// Validate excluded files didn't move
  2896  	cpMvDlByBuildAssertSpec, err := tests.CreateSpec(tests.CpMvDlByBuildAssertSpec)
  2897  	assert.NoError(t, err)
  2898  
  2899  	verifyExistInArtifactory(tests.GetBuildMoveExpected(), cpMvDlByBuildAssertSpec, t)
  2900  
  2901  	// Cleanup
  2902  	cleanArtifactoryTest()
  2903  }
  2904  
  2905  func TestArtifactoryDeleteByLatestBuild(t *testing.T) {
  2906  	initArtifactoryTest(t)
  2907  	buildName, buildNumberA, buildNumberB := "cli-test-build", "10", "11"
  2908  	inttestutils.DeleteBuild(artifactoryDetails.Url, buildName, artHttpDetails)
  2909  	specFile, err := tests.CreateSpec(tests.CopyByBuildSpec)
  2910  	assert.NoError(t, err)
  2911  
  2912  	// Upload files with buildName and buildNumber
  2913  	specFileA, err := tests.CreateSpec(tests.SplitUploadSpecA)
  2914  	assert.NoError(t, err)
  2915  	specFileB, err := tests.CreateSpec(tests.SplitUploadSpecB)
  2916  	assert.NoError(t, err)
  2917  	artifactoryCli.Exec("upload", "--spec="+specFileB, "--build-name="+buildName, "--build-number="+buildNumberA)
  2918  	artifactoryCli.Exec("upload", "--spec="+specFileA, "--build-name="+buildName, "--build-number="+buildNumberB)
  2919  
  2920  	// Publish buildInfo
  2921  	artifactoryCli.Exec("build-publish", buildName, buildNumberA)
  2922  	artifactoryCli.Exec("build-publish", buildName, buildNumberB)
  2923  
  2924  	// Delete by build name and LATEST
  2925  	artifactoryCli.Exec("delete", "--build="+buildName+"/LATEST --spec="+specFile)
  2926  
  2927  	// Validate files are deleted by build number
  2928  	cpMvDlByBuildAssertSpec, err := tests.CreateSpec(tests.CpMvDlByBuildAssertSpec)
  2929  	assert.NoError(t, err)
  2930  
  2931  	verifyExistInArtifactory(tests.GetBuildDeleteExpected(), cpMvDlByBuildAssertSpec, t)
  2932  
  2933  	// Cleanup
  2934  	inttestutils.DeleteBuild(artifactoryDetails.Url, buildName, artHttpDetails)
  2935  	cleanArtifactoryTest()
  2936  }
  2937  
  2938  func TestGitLfsCleanup(t *testing.T) {
  2939  	initArtifactoryTest(t)
  2940  	var filePath = "testsdata/gitlfs/(4b)(*)"
  2941  	artifactoryCli.Exec("upload", filePath, tests.LfsRepo+"/objects/4b/f4/{2}{1}")
  2942  	artifactoryCli.Exec("upload", filePath, tests.LfsRepo+"/objects/4b/f4/")
  2943  	refs := strings.Join([]string{"refs", "heads", "*"}, fileutils.GetFileSeparator())
  2944  	dotGitPath := getCliDotGitPath(t)
  2945  	artifactoryCli.Exec("glc", dotGitPath, "--repo="+tests.LfsRepo, "--refs=HEAD,"+refs)
  2946  	gitlfsSpecFile, err := tests.CreateSpec(tests.GitLfsAssertSpec)
  2947  	assert.NoError(t, err)
  2948  	verifyExistInArtifactory(tests.GetGitLfsExpected(), gitlfsSpecFile, t)
  2949  	cleanArtifactoryTest()
  2950  }
  2951  
  2952  func TestPing(t *testing.T) {
  2953  	initArtifactoryTest(t)
  2954  	artifactoryCli.Exec("ping")
  2955  	cleanArtifactoryTest()
  2956  }
  2957  
  2958  func TestSummaryReport(t *testing.T) {
  2959  	initArtifactoryTest(t)
  2960  
  2961  	previousLog := log.Logger
  2962  	newLog := log.NewLogger(logUtils.GetCliLogLevel(), nil)
  2963  
  2964  	// Set new logger with output redirection to buffer
  2965  	buffer := &bytes.Buffer{}
  2966  	newLog.SetOutputWriter(buffer)
  2967  	log.SetLogger(newLog)
  2968  
  2969  	specFile, err := tests.CreateSpec(tests.UploadFlatNonRecursive)
  2970  	assert.NoError(t, err)
  2971  	artifactoryCli.Exec("upload", "--spec="+specFile)
  2972  	verifySummary(t, buffer, 3, 0, previousLog)
  2973  
  2974  	artifactoryCli.Exec("move", path.Join(tests.Repo1, "*.in"), tests.Repo2+"/")
  2975  	verifySummary(t, buffer, 3, 0, previousLog)
  2976  
  2977  	artifactoryCli.Exec("copy", path.Join(tests.Repo2, "*.in"), tests.Repo1+"/")
  2978  	verifySummary(t, buffer, 3, 0, previousLog)
  2979  
  2980  	artifactoryCli.Exec("delete", path.Join(tests.Repo2, "*.in"))
  2981  	verifySummary(t, buffer, 3, 0, previousLog)
  2982  
  2983  	artifactoryCli.Exec("set-props", path.Join(tests.Repo1, "*.in"), "prop=val")
  2984  	verifySummary(t, buffer, 3, 0, previousLog)
  2985  
  2986  	specFile, err = tests.CreateSpec(tests.DownloadAllRepo1TestResources)
  2987  	assert.NoError(t, err)
  2988  	artifactoryCli.Exec("download", "--spec="+specFile)
  2989  	verifySummary(t, buffer, 3, 0, previousLog)
  2990  
  2991  	// Restore previous logger
  2992  	log.SetLogger(previousLog)
  2993  	cleanArtifactoryTest()
  2994  }
  2995  
  2996  func TestArtifactoryBuildDiscard(t *testing.T) {
  2997  	// Initialize
  2998  	initArtifactoryTest(t)
  2999  	client, err := httpclient.ClientBuilder().Build()
  3000  	assert.NoError(t, err)
  3001  
  3002  	// Upload files with buildName and buildNumber
  3003  	buildName := "jfrog-cli-discard-builds-test"
  3004  	for i := 1; i <= 5; i++ {
  3005  		artifactoryCli.Exec("upload", "testsdata/a/a1.in", tests.Repo1+"/data/", "--build-name="+buildName, "--build-number="+strconv.Itoa(i))
  3006  		artifactoryCli.Exec("build-publish", buildName, strconv.Itoa(i))
  3007  	}
  3008  
  3009  	// Test discard by max-builds
  3010  	artifactoryCli.Exec("build-discard", buildName, "--max-builds=3")
  3011  	jsonResponse := getAllBuildsByBuildName(client, buildName, t, http.StatusOK)
  3012  	assert.Len(t, jsonResponse.Builds, 3, "Incorrect operation of build-discard by max-builds.")
  3013  
  3014  	// Test discard with exclusion
  3015  	artifactoryCli.Exec("build-discard", buildName, "--max-days=-1", "--exclude-builds=3,5")
  3016  	jsonResponse = getAllBuildsByBuildName(client, buildName, t, http.StatusOK)
  3017  	assert.Len(t, jsonResponse.Builds, 2, "Incorrect operation of build-discard with exclusion.")
  3018  
  3019  	// Test discard by max-days
  3020  	artifactoryCli.Exec("build-discard", buildName, "--max-days=-1")
  3021  	jsonResponse = getAllBuildsByBuildName(client, buildName, t, http.StatusNotFound)
  3022  	assert.Zero(t, jsonResponse, "Incorrect operation of build-discard by max-days.")
  3023  
  3024  	//Cleanup
  3025  	inttestutils.DeleteBuild(artifactoryDetails.Url, buildName, artHttpDetails)
  3026  	cleanArtifactoryTest()
  3027  }
  3028  
  3029  // Tests compatibility to file paths with windows separators.
  3030  // Verifies the upload and download commands work as expected for inputs of both arguments and spec files.
  3031  func TestArtifactoryWinBackwardsCompatibility(t *testing.T) {
  3032  	initArtifactoryTest(t)
  3033  	if !cliutils.IsWindows() {
  3034  		t.Skip("Not running on Windows, skipping...")
  3035  	}
  3036  	uploadSpecFile, err := tests.CreateSpec(tests.WinSimpleUploadSpec)
  3037  	assert.NoError(t, err)
  3038  	artifactoryCli.Exec("upload", "--spec="+uploadSpecFile)
  3039  	artifactoryCli.Exec("upload", "testsdata\\\\a\\\\b\\\\*", tests.Repo1+"/compatibility_arguments/", "--exclusions=*b2.in;*c*")
  3040  
  3041  	downloadSpecFile, err := tests.CreateSpec(tests.WinSimpleDownloadSpec)
  3042  	assert.NoError(t, err)
  3043  	artifactoryCli.Exec("download", "--spec="+downloadSpecFile)
  3044  	artifactoryCli.Exec("download", tests.Repo1+"/*arguments*", "out\\\\win\\\\", "--flat=true")
  3045  
  3046  	// Validate files are downloaded by build number
  3047  	paths, _ := fileutils.ListFilesRecursiveWalkIntoDirSymlink(tests.Out, false)
  3048  	err = tests.ValidateListsIdentical(tests.GetWinCompatibility(), paths)
  3049  	assert.NoError(t, err)
  3050  	cleanArtifactoryTest()
  3051  }
  3052  
  3053  func TestArtifactorySearchIncludeDir(t *testing.T) {
  3054  	initArtifactoryTest(t)
  3055  
  3056  	// Upload files
  3057  	specFileA, err := tests.CreateSpec(tests.SplitUploadSpecA)
  3058  	assert.NoError(t, err)
  3059  	artifactoryCli.Exec("upload", "--spec="+specFileA, "--recursive", "--flat=false")
  3060  
  3061  	// Prepare search command
  3062  	searchSpecBuilder := spec.NewBuilder().Pattern(tests.Repo1).Recursive(true)
  3063  	searchCmd := generic.NewSearchCommand()
  3064  	searchCmd.SetRtDetails(artifactoryDetails)
  3065  
  3066  	// Search without IncludeDirs
  3067  	searchCmd.SetSpec(searchSpecBuilder.IncludeDirs(false).BuildSpec())
  3068  	assert.NoError(t, searchCmd.Search())
  3069  	assert.NoError(t, assertDateInSearchResult(searchCmd.SearchResult()))
  3070  	assert.ElementsMatch(t, searchCmd.SearchResultNoDate(), tests.GetSearchNotIncludeDirsFiles())
  3071  
  3072  	// Search with IncludeDirs
  3073  	searchCmd.SetSpec(searchSpecBuilder.IncludeDirs(true).BuildSpec())
  3074  	assert.NoError(t, searchCmd.Search())
  3075  	assert.NoError(t, assertDateInSearchResult(searchCmd.SearchResult()))
  3076  	assert.ElementsMatch(t, searchCmd.SearchResultNoDate(), tests.GetSearchIncludeDirsFiles())
  3077  
  3078  	// Cleanup
  3079  	cleanArtifactoryTest()
  3080  }
  3081  
  3082  func TestArtifactorySearchProps(t *testing.T) {
  3083  	initArtifactoryTest(t)
  3084  
  3085  	// Upload files
  3086  	specFile, err := tests.CreateSpec(tests.UploadWithPropsSpec)
  3087  	assert.NoError(t, err)
  3088  	artifactoryCli.Exec("upload", "--spec="+specFile, "--recursive")
  3089  
  3090  	// Prepare search command
  3091  	searchSpecBuilder := spec.NewBuilder().Pattern(tests.Repo1).Recursive(true)
  3092  	searchCmd := generic.NewSearchCommand()
  3093  	searchCmd.SetRtDetails(artifactoryDetails)
  3094  
  3095  	// Search artifacts with c=3
  3096  	searchCmd.SetSpec(searchSpecBuilder.Props("c=3").BuildSpec())
  3097  	assert.NoError(t, searchCmd.Search())
  3098  	assert.NoError(t, assertDateInSearchResult(searchCmd.SearchResult()))
  3099  	assert.ElementsMatch(t, searchCmd.SearchResultNoDate(), tests.GetSearchPropsStep1())
  3100  
  3101  	// Search artifacts without c=3
  3102  	searchCmd.SetSpec(searchSpecBuilder.Props("").ExcludeProps("c=3").BuildSpec())
  3103  	assert.NoError(t, searchCmd.Search())
  3104  	assert.NoError(t, assertDateInSearchResult(searchCmd.SearchResult()))
  3105  	assert.ElementsMatch(t, searchCmd.SearchResultNoDate(), tests.GetSearchPropsStep2())
  3106  
  3107  	// Search artifacts without a=1&b=2
  3108  	searchCmd.SetSpec(searchSpecBuilder.Props("").ExcludeProps("a=1;b=2").BuildSpec())
  3109  	assert.NoError(t, searchCmd.Search())
  3110  	assert.NoError(t, assertDateInSearchResult(searchCmd.SearchResult()))
  3111  	assert.ElementsMatch(t, searchCmd.SearchResultNoDate(), tests.GetSearchPropsStep3())
  3112  
  3113  	// Search artifacts without a=1&b=2 and with c=3
  3114  	searchCmd.SetSpec(searchSpecBuilder.Props("c=3").ExcludeProps("a=1;b=2").BuildSpec())
  3115  	assert.NoError(t, searchCmd.Search())
  3116  	assert.NoError(t, assertDateInSearchResult(searchCmd.SearchResult()))
  3117  	assert.ElementsMatch(t, searchCmd.SearchResultNoDate(), tests.GetSearchPropsStep4())
  3118  
  3119  	// Search artifacts without a=1 and with c=5
  3120  	searchCmd.SetSpec(searchSpecBuilder.Props("c=5").ExcludeProps("a=1").BuildSpec())
  3121  	assert.NoError(t, searchCmd.Search())
  3122  	assert.NoError(t, assertDateInSearchResult(searchCmd.SearchResult()))
  3123  	assert.ElementsMatch(t, searchCmd.SearchResultNoDate(), tests.GetSearchPropsStep5())
  3124  
  3125  	// Search artifacts by pattern "*b*", exclude pattern "*3*", with "b=1" and without "c=3"
  3126  	pattern := tests.Repo1 + "/*b*"
  3127  	exclusions := []string{tests.Repo1 + "/*3*"}
  3128  	searchSpecBuilder = spec.NewBuilder().Pattern(pattern).Recursive(true).Exclusions(exclusions).Props("b=1").ExcludeProps("c=3")
  3129  	searchCmd.SetSpec(searchSpecBuilder.BuildSpec())
  3130  	assert.NoError(t, searchCmd.Search())
  3131  	assert.NoError(t, assertDateInSearchResult(searchCmd.SearchResult()))
  3132  	assert.ElementsMatch(t, searchCmd.SearchResultNoDate(), tests.GetSearchPropsStep6())
  3133  
  3134  	// Cleanup
  3135  	cleanArtifactoryTest()
  3136  }
  3137  
  3138  func getAllBuildsByBuildName(client *httpclient.HttpClient, buildName string, t *testing.T, expectedHttpStatusCode int) buildsApiResponseStruct {
  3139  	resp, body, _, _ := client.SendGet(artifactoryDetails.Url+"api/build/"+buildName, true, artHttpDetails)
  3140  	assert.Equal(t, expectedHttpStatusCode, resp.StatusCode, "Failed retrieving build information from artifactory.")
  3141  
  3142  	buildsApiResponse := &buildsApiResponseStruct{}
  3143  	err := json.Unmarshal(body, buildsApiResponse)
  3144  	assert.NoError(t, err, "Unmarshaling failed with an error")
  3145  	return *buildsApiResponse
  3146  }
  3147  
  3148  type buildsApiInnerBuildsStruct struct {
  3149  	Uri     string `json:"uri,omitempty"`
  3150  	Started string `json:"started,omitempty"`
  3151  }
  3152  
  3153  type buildsApiResponseStruct struct {
  3154  	Uri    string                       `json:"uri,omitempty"`
  3155  	Builds []buildsApiInnerBuildsStruct `json:"buildsNumbers,omitempty"`
  3156  }
  3157  
  3158  func verifySummary(t *testing.T, buffer *bytes.Buffer, success, failure int64, logger log.Log) {
  3159  	content := buffer.Bytes()
  3160  	buffer.Reset()
  3161  	logger.Output(string(content))
  3162  
  3163  	status, err := jsonparser.GetString(content, "status")
  3164  	assert.NoError(t, err)
  3165  	assert.Equal(t, "success", status, "Summary validation failed")
  3166  
  3167  	resultSuccess, err := jsonparser.GetInt(content, "totals", "success")
  3168  	assert.NoError(t, err)
  3169  
  3170  	resultFailure, err := jsonparser.GetInt(content, "totals", "failure")
  3171  	assert.NoError(t, err)
  3172  
  3173  	assert.Equal(t, success, resultSuccess, "Summary validation failed")
  3174  	assert.Equal(t, failure, resultFailure, "Summary validation failed")
  3175  }
  3176  
  3177  func CleanArtifactoryTests() {
  3178  	cleanArtifactoryTest()
  3179  	deleteRepos()
  3180  }
  3181  
  3182  func initArtifactoryTest(t *testing.T) {
  3183  	if !*tests.TestArtifactory {
  3184  		t.Skip("Artifactory is not being tested, skipping...")
  3185  	}
  3186  }
  3187  
  3188  func cleanArtifactoryTest() {
  3189  	if !*tests.TestArtifactory && !*tests.TestDistribution {
  3190  		return
  3191  	}
  3192  	os.Unsetenv(cliutils.HomeDir)
  3193  	log.Info("Cleaning test data...")
  3194  	cleanArtifactory()
  3195  	tests.CleanFileSystem()
  3196  }
  3197  
  3198  func preUploadBasicTestResources() {
  3199  	uploadPath := tests.GetTestResourcesPath() + "a/(.*)"
  3200  	targetPath := tests.Repo1 + "/test_resources/{1}"
  3201  	flags := "--threads=10 --regexp=true --props=searchMe=true --flat=false"
  3202  	artifactoryCli.Exec("upload", uploadPath, targetPath, flags)
  3203  }
  3204  
  3205  func execDeleteRepoRest(repoName string) {
  3206  	client, err := httpclient.ClientBuilder().Build()
  3207  	if err != nil {
  3208  		log.Error(err)
  3209  		os.Exit(1)
  3210  	}
  3211  	resp, body, err := client.SendDelete(artifactoryDetails.Url+"api/repositories/"+repoName, nil, artHttpDetails)
  3212  	if err != nil {
  3213  		log.Error(err)
  3214  		return
  3215  	}
  3216  	if resp.StatusCode != http.StatusOK && resp.StatusCode != http.StatusCreated {
  3217  		log.Error(errors.New("Artifactory response: " + resp.Status + "\n" + clientutils.IndentJson(body)))
  3218  		return
  3219  	}
  3220  	log.Info("Repository", repoName, "deleted.")
  3221  }
  3222  
  3223  func execListRepoRest() ([]string, error) {
  3224  	var repositoryKeys []string
  3225  
  3226  	// Build http client
  3227  	client, err := httpclient.ClientBuilder().Build()
  3228  	if err != nil {
  3229  		return nil, err
  3230  	}
  3231  
  3232  	// Send get request
  3233  	resp, body, _, err := client.SendGet(artifactoryDetails.Url+"api/repositories", true, artHttpDetails)
  3234  	if err != nil {
  3235  		return nil, err
  3236  	}
  3237  	if resp.StatusCode != http.StatusOK && resp.StatusCode != http.StatusCreated {
  3238  		return nil, errors.New("Artifactory response: " + resp.Status + "\n" + clientutils.IndentJson(body))
  3239  	}
  3240  
  3241  	// Extract repository keys from the json response
  3242  	var keyError error
  3243  	_, err = jsonparser.ArrayEach(body, func(value []byte, dataType jsonparser.ValueType, offset int, err error) {
  3244  		if err != nil || keyError != nil {
  3245  			return
  3246  		}
  3247  		repoKey, err := jsonparser.GetString(value, "key")
  3248  		if err != nil {
  3249  			keyError = err
  3250  			return
  3251  		}
  3252  		repositoryKeys = append(repositoryKeys, repoKey)
  3253  	})
  3254  	if keyError != nil {
  3255  		return nil, err
  3256  	}
  3257  
  3258  	return repositoryKeys, err
  3259  }
  3260  
  3261  func execCreateRepoRest(repoConfig, repoName string) {
  3262  	content, err := ioutil.ReadFile(repoConfig)
  3263  	if err != nil {
  3264  		log.Error(err)
  3265  		os.Exit(1)
  3266  	}
  3267  	rtutils.AddHeader("Content-Type", "application/json", &artHttpDetails.Headers)
  3268  	client, err := httpclient.ClientBuilder().Build()
  3269  	if err != nil {
  3270  		log.Error(err)
  3271  		os.Exit(1)
  3272  	}
  3273  	resp, body, err := client.SendPut(artifactoryDetails.Url+"api/repositories/"+repoName, content, artHttpDetails)
  3274  	if err != nil {
  3275  		log.Error(err)
  3276  		os.Exit(1)
  3277  	}
  3278  	if resp.StatusCode != http.StatusOK && resp.StatusCode != http.StatusCreated {
  3279  		log.Error(errors.New("Artifactory response: " + resp.Status + "\n" + clientutils.IndentJson(body)))
  3280  		os.Exit(1)
  3281  	}
  3282  	log.Info("Repository", repoName, "created.")
  3283  }
  3284  
  3285  func createReposIfNeeded() {
  3286  	cleanUpOldRepositories()
  3287  	createRandomReposName()
  3288  	nonVirtualRepos := tests.GetNonVirtualRepositories()
  3289  	createRepos(nonVirtualRepos)
  3290  	virtualRepos := tests.GetVirtualRepositories()
  3291  	createRepos(virtualRepos)
  3292  }
  3293  
  3294  func cleanUpOldRepositories() {
  3295  	repositoryKeys, err := execListRepoRest()
  3296  	if err != nil {
  3297  		log.Warn("Couldn't retrieve repository list from Artifactory", err)
  3298  		return
  3299  	}
  3300  
  3301  	now := time.Now()
  3302  	repoPattern := regexp.MustCompile(`^jfrog-cli-tests(-\w*)+-(\d*)$`)
  3303  	for _, repoKey := range repositoryKeys {
  3304  		regexGroups := repoPattern.FindStringSubmatch(repoKey)
  3305  		if regexGroups == nil {
  3306  			// Repository is not "jfrog-cli-tests-..."
  3307  			continue
  3308  		}
  3309  
  3310  		repoTimestamp, err := strconv.ParseInt(regexGroups[len(regexGroups)-1], 10, 64)
  3311  		if err != nil {
  3312  			log.Warn("Error while parsing repository timestamp of repository ", repoKey, err)
  3313  			continue
  3314  		}
  3315  
  3316  		repoTime := time.Unix(repoTimestamp, 0)
  3317  		if now.Sub(repoTime).Hours() > 24.0 {
  3318  			log.Info("Deleting old repository", repoKey)
  3319  			execDeleteRepoRest(repoKey)
  3320  		}
  3321  	}
  3322  }
  3323  
  3324  func createRepos(repos map[string]string) {
  3325  	for repoName, configFile := range repos {
  3326  		if !isRepoExist(repoName) {
  3327  			repoConfig := tests.GetTestResourcesPath() + configFile
  3328  			repoConfig, err := tests.ReplaceTemplateVariables(repoConfig, "")
  3329  			if err != nil {
  3330  				log.Error(err)
  3331  				os.Exit(1)
  3332  			}
  3333  			execCreateRepoRest(repoConfig, repoName)
  3334  		}
  3335  	}
  3336  }
  3337  
  3338  func createRandomReposName() {
  3339  	timestamp := strconv.FormatInt(time.Now().Unix(), 10)
  3340  	tests.Repo1 += "-" + timestamp
  3341  	tests.Repo2 += "-" + timestamp
  3342  	tests.Repo1And2 += "-" + timestamp
  3343  	tests.VirtualRepo += "-" + timestamp
  3344  	tests.LfsRepo += "-" + timestamp
  3345  	tests.DebianRepo += "-" + timestamp
  3346  	tests.JcenterRemoteRepo += "-" + timestamp
  3347  	if *tests.TestNpm {
  3348  		tests.NpmLocalRepo += "-" + timestamp
  3349  		tests.NpmRemoteRepo += "-" + timestamp
  3350  	}
  3351  	if *tests.TestGo {
  3352  		tests.GoLocalRepo += "-" + timestamp
  3353  	}
  3354  	if *tests.TestPip {
  3355  		tests.PypiRemoteRepo += "-" + timestamp
  3356  		tests.PypiVirtualRepo += "-" + timestamp
  3357  	}
  3358  }
  3359  
  3360  // Important - Virtual repositories most be deleted first
  3361  func deleteRepos() {
  3362  	repos := []string{
  3363  		tests.VirtualRepo,
  3364  		tests.Repo1,
  3365  		tests.Repo2,
  3366  		tests.LfsRepo,
  3367  		tests.DebianRepo,
  3368  		tests.JcenterRemoteRepo,
  3369  	}
  3370  
  3371  	if *tests.TestNpm {
  3372  		repos = append(repos, tests.NpmLocalRepo, tests.NpmRemoteRepo)
  3373  	}
  3374  	if *tests.TestGo {
  3375  		repos = append(repos, tests.GoLocalRepo)
  3376  	}
  3377  	if *tests.TestPip {
  3378  		repos = append(repos, tests.PypiVirtualRepo, tests.PypiRemoteRepo)
  3379  	}
  3380  
  3381  	for _, repoName := range repos {
  3382  		if isRepoExist(repoName) {
  3383  			execDeleteRepoRest(repoName)
  3384  		}
  3385  	}
  3386  }
  3387  
  3388  func cleanArtifactory() {
  3389  	deleteSpecFile := tests.GetFilePathForArtifactory(tests.DeleteSpec)
  3390  	fmt.Println(deleteSpecFile)
  3391  	deleteSpecFile, err := tests.ReplaceTemplateVariables(deleteSpecFile, "")
  3392  	fmt.Println(deleteSpecFile)
  3393  	if err != nil {
  3394  		log.Error(err)
  3395  		os.Exit(1)
  3396  	}
  3397  	deleteSpec, _ := spec.CreateSpecFromFile(deleteSpecFile, nil)
  3398  	tests.DeleteFiles(deleteSpec, artifactoryDetails)
  3399  }
  3400  
  3401  func searchInArtifactory(specFile string) ([]generic.SearchResult, error) {
  3402  	searchSpec, _ := spec.CreateSpecFromFile(specFile, nil)
  3403  	searchCmd := generic.NewSearchCommand()
  3404  	searchCmd.SetRtDetails(artifactoryDetails).SetSpec(searchSpec)
  3405  	err := searchCmd.Search()
  3406  	return searchCmd.SearchResult(), err
  3407  }
  3408  
  3409  func getSpecAndCommonFlags(specFile string) (*spec.SpecFiles, rtutils.CommonConf) {
  3410  	searchFlags := new(rtutils.CommonConfImpl)
  3411  	searchSpec, _ := spec.CreateSpecFromFile(specFile, nil)
  3412  	return searchSpec, searchFlags
  3413  }
  3414  
  3415  func verifyExistInArtifactory(expected []string, specFile string, t *testing.T) {
  3416  	results, _ := searchInArtifactory(specFile)
  3417  	tests.CompareExpectedVsActual(expected, results, t)
  3418  }
  3419  
  3420  func verifyDoesntExistInArtifactory(specFile string, t *testing.T) {
  3421  	verifyExistInArtifactory([]string{}, specFile, t)
  3422  }
  3423  
  3424  func verifyExistInArtifactoryByProps(expected []string, pattern, props string, t *testing.T) {
  3425  	searchSpec := spec.NewBuilder().Pattern(pattern).Props(props).Recursive(true).BuildSpec()
  3426  	searchCmd := generic.NewSearchCommand()
  3427  	searchCmd.SetRtDetails(artifactoryDetails).SetSpec(searchSpec)
  3428  	err := searchCmd.Search()
  3429  	assert.NoError(t, err)
  3430  	tests.CompareExpectedVsActual(expected, searchCmd.SearchResult(), t)
  3431  }
  3432  
  3433  func isRepoExist(repoName string) bool {
  3434  	client, err := httpclient.ClientBuilder().Build()
  3435  	if err != nil {
  3436  		log.Error(err)
  3437  		os.Exit(1)
  3438  	}
  3439  	resp, _, _, err := client.SendGet(artifactoryDetails.Url+tests.RepoDetailsUrl+repoName, true, artHttpDetails)
  3440  	if err != nil {
  3441  		log.Error(err)
  3442  		os.Exit(1)
  3443  	}
  3444  
  3445  	if resp.StatusCode != http.StatusBadRequest {
  3446  		return true
  3447  	}
  3448  	return false
  3449  }
  3450  
  3451  func getCliDotGitPath(t *testing.T) string {
  3452  	dotGitPath, err := os.Getwd()
  3453  	assert.NoError(t, err, "Failed to get current dir.")
  3454  	dotGitExists, err := fileutils.IsDirExists(filepath.Join(dotGitPath, ".git"), false)
  3455  	assert.NoError(t, err)
  3456  	assert.True(t, dotGitExists, "Can't find .git")
  3457  	return dotGitPath
  3458  }
  3459  
  3460  func deleteServerConfig() {
  3461  	configArtifactoryCli.Exec("c", "delete", tests.RtServerId, "--interactive=false")
  3462  }
  3463  
  3464  // This function will create server config and return the entire passphrase flag if it needed.
  3465  // For example if passphrase is needed it will return "--ssh-passphrase=${theConfiguredPassphrase}" or empty string.
  3466  func createServerConfigAndReturnPassphrase() (passphrase string) {
  3467  	if *tests.RtSshPassphrase != "" {
  3468  		passphrase = "--ssh-passphrase=" + *tests.RtSshPassphrase
  3469  	}
  3470  	configArtifactoryCli.Exec("c", tests.RtServerId, "--interactive=false")
  3471  	return passphrase
  3472  }
  3473  
  3474  func testCopyMoveNoSpec(command string, beforeCommandExpected, afterCommandExpected []string, t *testing.T) {
  3475  	initArtifactoryTest(t)
  3476  
  3477  	// Upload files
  3478  	specFileA, err := tests.CreateSpec(tests.SplitUploadSpecA)
  3479  	assert.NoError(t, err)
  3480  	specFileB, err := tests.CreateSpec(tests.SplitUploadSpecB)
  3481  	assert.NoError(t, err)
  3482  
  3483  	artifactoryCli.Exec("upload", "--spec="+specFileA)
  3484  	artifactoryCli.Exec("upload", "--spec="+specFileB)
  3485  
  3486  	// Run command with dry-run
  3487  	artifactoryCli.Exec(command, tests.Repo1+"/data/*a* "+tests.Repo2+"/", "--dry-run")
  3488  
  3489  	// Validate files weren't affected
  3490  	cpMvSpecFilePath, err := tests.CreateSpec(tests.CpMvDlByBuildAssertSpec)
  3491  	assert.NoError(t, err)
  3492  	verifyExistInArtifactory(beforeCommandExpected, cpMvSpecFilePath, t)
  3493  
  3494  	// Run command
  3495  	artifactoryCli.Exec(command, tests.Repo1+"/data/*a* "+tests.Repo2+"/")
  3496  
  3497  	// Validate files were affected
  3498  	verifyExistInArtifactory(afterCommandExpected, cpMvSpecFilePath, t)
  3499  
  3500  	// Cleanup
  3501  	cleanArtifactoryTest()
  3502  }
  3503  
  3504  func searchItemsInArtifactory(t *testing.T) []rtutils.ResultItem {
  3505  	fileSpec, err := tests.CreateSpec(tests.SearchRepo1ByInSuffix)
  3506  	assert.NoError(t, err)
  3507  	spec, flags := getSpecAndCommonFlags(fileSpec)
  3508  	flags.SetArtifactoryDetails(artAuth)
  3509  	var resultItems []rtutils.ResultItem
  3510  	for i := 0; i < len(spec.Files); i++ {
  3511  
  3512  		searchParams, err := generic.GetSearchParams(spec.Get(i))
  3513  		assert.NoError(t, err, "Failed Searching files")
  3514  
  3515  		currentResultItems, err := services.SearchBySpecFiles(searchParams, flags, rtutils.ALL)
  3516  		assert.NoError(t, err, "Failed Searching files")
  3517  		resultItems = append(resultItems, currentResultItems...)
  3518  	}
  3519  	return resultItems
  3520  }
  3521  
  3522  func assertDateInSearchResult(searchResult []generic.SearchResult) error {
  3523  	for _, v := range searchResult {
  3524  		if v.Created == "" || v.Modified == "" {
  3525  			message, err := json.Marshal(&v)
  3526  			if err != nil {
  3527  				return errors.New("failed to process search result to assert it includes date: " + err.Error())
  3528  			}
  3529  			return errors.New("search result does not include date: " + string(message))
  3530  		}
  3531  	}
  3532  	return nil
  3533  }
  3534  
  3535  func TestArtifactoryUploadInflatedPath(t *testing.T) {
  3536  	initArtifactoryTest(t)
  3537  	artifactoryCli.Exec("upload", "testsdata/a/../a/a1.*", tests.Repo1)
  3538  	artifactoryCli.Exec("upload", "testsdata/./a/a1.*", tests.Repo1)
  3539  	searchFilePath, err := tests.CreateSpec(tests.SearchRepo1ByInSuffix)
  3540  	assert.NoError(t, err)
  3541  	verifyExistInArtifactory(tests.GetSimpleUploadSpecialCharNoRegexExpectedRepo1(), searchFilePath, t)
  3542  
  3543  	artifactoryCli.Exec("upload", "testsdata/./a/../a/././././a2.*", tests.Repo1)
  3544  	searchFilePath, err = tests.CreateSpec(tests.SearchRepo1ByInSuffix)
  3545  	assert.NoError(t, err)
  3546  	verifyExistInArtifactory(tests.GetSimpleUploadSpecialCharNoRegexExpected2filesRepo1(), searchFilePath, t)
  3547  	if cliutils.IsWindows() {
  3548  		artifactoryCli.Exec("upload", `testsdata\\a\\..\\a\\a1.*`, tests.Repo2)
  3549  		artifactoryCli.Exec("upload", `testsdata\\.\\\a\a1.*`, tests.Repo2)
  3550  		searchFilePath, err = tests.CreateSpec(tests.SearchRepo2)
  3551  		assert.NoError(t, err)
  3552  		verifyExistInArtifactory(tests.GetSimpleUploadSpecialCharNoRegexExpectedRepo2(), searchFilePath, t)
  3553  
  3554  		artifactoryCli.Exec("upload", `testsdata\\.\\a\\..\\a\\.\\.\\.\\.\\a2.*`, tests.Repo2)
  3555  		searchFilePath, err = tests.CreateSpec(tests.SearchRepo2)
  3556  		assert.NoError(t, err)
  3557  		verifyExistInArtifactory(tests.GetSimpleUploadSpecialCharNoRegexExpected2filesRepo2(), searchFilePath, t)
  3558  	}
  3559  	cleanArtifactoryTest()
  3560  }
  3561  
  3562  func TestGetJcenterRemoteDetails(t *testing.T) {
  3563  	initArtifactoryTest(t)
  3564  	createServerConfigAndReturnPassphrase()
  3565  
  3566  	unsetEnvVars := func() {
  3567  		err := os.Unsetenv(utils.JCenterRemoteServerEnv)
  3568  		assert.NoError(t, err)
  3569  		err = os.Unsetenv(utils.JCenterRemoteRepoEnv)
  3570  		assert.NoError(t, err)
  3571  	}
  3572  	unsetEnvVars()
  3573  	defer unsetEnvVars()
  3574  
  3575  	// The utils.JCenterRemoteServerEnv env var is not set, so extractor1.jar should be downloaded from jcenter.
  3576  	downloadPath := "org/jfrog/buildinfo/build-info-extractor/extractor1.jar"
  3577  	expectedRemotePath := path.Join("bintray/jcenter", downloadPath)
  3578  	validateJcenterRemoteDetails(t, downloadPath, expectedRemotePath)
  3579  
  3580  	// Still, the utils.JCenterRemoteServerEnv env var is not set, so the download should be from jcenter.
  3581  	// Expecting a different download path this time.
  3582  	downloadPath = "org/jfrog/buildinfo/build-info-extractor/extractor2.jar"
  3583  	expectedRemotePath = path.Join("bintray/jcenter", downloadPath)
  3584  	validateJcenterRemoteDetails(t, downloadPath, expectedRemotePath)
  3585  
  3586  	// Setting the utils.JCenterRemoteServerEnv env var now,
  3587  	// Expecting therefore the download to be from the the server ID configured by this env var.
  3588  	err := os.Setenv(utils.JCenterRemoteServerEnv, tests.RtServerId)
  3589  	assert.NoError(t, err)
  3590  	downloadPath = "org/jfrog/buildinfo/build-info-extractor/extractor3.jar"
  3591  	expectedRemotePath = path.Join("jcenter", downloadPath)
  3592  	validateJcenterRemoteDetails(t, downloadPath, expectedRemotePath)
  3593  
  3594  	// Still expecting the download to be from the same server ID, but this time, not through a remote repo named
  3595  	// jcenter, but through test-remote-repo.
  3596  	testRemoteRepo := "test-remote-repo"
  3597  	err = os.Setenv(utils.JCenterRemoteRepoEnv, testRemoteRepo)
  3598  	assert.NoError(t, err)
  3599  	downloadPath = "1org/jfrog/buildinfo/build-info-extractor/extractor4.jar"
  3600  	expectedRemotePath = path.Join(testRemoteRepo, downloadPath)
  3601  	validateJcenterRemoteDetails(t, downloadPath, expectedRemotePath)
  3602  	cleanArtifactoryTest()
  3603  }
  3604  
  3605  func validateJcenterRemoteDetails(t *testing.T, downloadPath, expectedRemotePath string) {
  3606  	artDetails, remotePath, err := utils.GetJcenterRemoteDetails(downloadPath)
  3607  	assert.NoError(t, err)
  3608  	assert.Equal(t, expectedRemotePath, remotePath)
  3609  	assert.False(t, os.Getenv(utils.JCenterRemoteServerEnv) != "" && artDetails == nil, "Expected a server to be returned")
  3610  }
  3611  
  3612  func TestVcsProps(t *testing.T) {
  3613  	initArtifactoryTest(t)
  3614  	testDir := initVcsTestDir(t)
  3615  	artifactoryCli.Exec("upload", filepath.Join(testDir, "*"), tests.Repo1, "--flat=false", "--build-name=jfrog-cli-test-vcs-props", "--build-number=2020")
  3616  	resultItems := searchItemsInArtifactory(t)
  3617  	assert.NotZero(t, len(resultItems), "No artifacts were found.")
  3618  	for _, item := range resultItems {
  3619  		properties := item.Properties
  3620  		foundUrl, foundRevision := false, false
  3621  		for _, prop := range properties {
  3622  			if item.Name == "a1.in" || item.Name == "a2.in" {
  3623  				// Check that properties were not removed.
  3624  				if prop.Key == "vcs.url" && prop.Value == "https://github.com/jfrog/jfrog-cli.git" {
  3625  					assert.False(t, foundUrl, "Found duplicate VCS property(url) in artifact")
  3626  					foundUrl = true
  3627  				}
  3628  				if prop.Key == "vcs.revision" && prop.Value == "d63c5957ad6819f4c02a817abe757f210d35ff92" {
  3629  					assert.False(t, foundRevision, "Found duplicate VCS property(revision) in artifact")
  3630  					foundRevision = true
  3631  				}
  3632  			}
  3633  			if item.Name == "b1.in" || item.Name == "b2.in" {
  3634  				if prop.Key == "vcs.url" && prop.Value == "https://github.com/jfrog/jfrog-client-go.git" {
  3635  					assert.False(t, foundUrl, "Found duplicate VCS property(url) in artifact")
  3636  					foundUrl = true
  3637  				}
  3638  				if prop.Key == "vcs.revision" && prop.Value == "ad99b6c068283878fde4d49423728f0bdc00544a" {
  3639  					assert.False(t, foundRevision, "Found duplicate VCS property(revision) in artifact")
  3640  					foundRevision = true
  3641  				}
  3642  			}
  3643  		}
  3644  		assert.True(t, foundUrl && foundRevision, "VCS property was not found on artifact: "+item.Name)
  3645  	}
  3646  	cleanArtifactoryTest()
  3647  }
  3648  
  3649  func initVcsTestDir(t *testing.T) string {
  3650  	testsdataSrc := filepath.Join(filepath.FromSlash(tests.GetTestResourcesPath()), "vcs")
  3651  	testsdataTarget := tests.Temp
  3652  	err := fileutils.CopyDir(testsdataSrc, testsdataTarget, true)
  3653  	assert.NoError(t, err)
  3654  	if found, err := fileutils.IsDirExists(filepath.Join(testsdataTarget, "gitdata"), false); found {
  3655  		assert.NoError(t, err)
  3656  		tests.RenamePath(filepath.Join(testsdataTarget, "gitdata"), filepath.Join(testsdataTarget, ".git"), t)
  3657  	}
  3658  	if found, err := fileutils.IsDirExists(filepath.Join(testsdataTarget, "OtherGit", "gitdata"), false); found {
  3659  		assert.NoError(t, err)
  3660  		tests.RenamePath(filepath.Join(testsdataTarget, "OtherGit", "gitdata"), filepath.Join(testsdataTarget, "OtherGit", ".git"), t)
  3661  	}
  3662  	path, err := filepath.Abs(tests.Temp)
  3663  	assert.NoError(t, err)
  3664  	return path
  3665  }
  3666  
  3667  func TestArtifactoryReplicationCreate(t *testing.T) {
  3668  	initArtifactoryTest(t)
  3669  	configArtifactoryCli.Exec("c", tests.RtServerId, "--url="+*tests.RtUrl, "--user="+*tests.RtUser, "--password="+*tests.RtPassword, "--apikey="+*tests.RtApiKey, "--access-token="+*tests.RtAccessToken, "--interactive=false")
  3670  	defer deleteServerConfig()
  3671  
  3672  	// Init tmp dir
  3673  	specFile, err := tests.CreateSpec(tests.ReplicationTempCreate)
  3674  	assert.NoError(t, err)
  3675  
  3676  	// Create push replication
  3677  	err = artifactoryCli.Exec("rplc", specFile)
  3678  	assert.NoError(t, err)
  3679  
  3680  	// Validate create replication
  3681  	servicesManager, err := utils.CreateServiceManager(artifactoryDetails, false)
  3682  	assert.NoError(t, err)
  3683  	result, err := servicesManager.GetReplication(tests.Repo1)
  3684  	assert.NoError(t, err)
  3685  	result[0].Password = ""
  3686  	assert.ElementsMatch(t, result, tests.GetReplicationConfig())
  3687  
  3688  	// Delete replication
  3689  	err = artifactoryCli.Exec("rpldel", tests.Repo1)
  3690  	assert.NoError(t, err)
  3691  
  3692  	// Validate delete replication
  3693  	result, err = servicesManager.GetReplication(tests.Repo1)
  3694  	assert.Error(t, err)
  3695  	// Cleanup
  3696  	cleanArtifactoryTest()
  3697  }