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