From 7c06e5e2ed78f535f5216d6558064ee83867052a Mon Sep 17 00:00:00 2001 From: Naveen Kumar Date: Wed, 5 Nov 2025 17:26:14 +0530 Subject: [PATCH 1/9] testing --- artifactory_test.go | 123 ++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 120 insertions(+), 3 deletions(-) diff --git a/artifactory_test.go b/artifactory_test.go index 9b05ff675..e9a8c2c0b 100644 --- a/artifactory_test.go +++ b/artifactory_test.go @@ -4568,9 +4568,9 @@ func CleanArtifactoryTests() { } func initArtifactoryTest(t *testing.T, minVersion string) { - if !*tests.TestArtifactory { - t.Skip("Skipping artifactory test. To run artifactory test add the '-test.artifactory=true' option.") - } + //if !*tests.TestArtifactory { + // t.Skip("Skipping artifactory test. To run artifactory test add the '-test.artifactory=true' option.") + //} if minVersion != "" { validateArtifactoryVersion(t, minVersion) } @@ -5766,3 +5766,120 @@ func deleteReceivedReleaseBundle(t *testing.T, url, bundleName, bundleVersion st _, _, err = client.SendDelete(*tests.JfrogUrl+deleteApi, []byte{}, artHttpDetails, "Deleting release bundle") assert.NoError(t, err) } + +var searchByPatternDataProvider = []struct { + pattern string + recursive bool + expectedResults []utils.SearchResult +}{ + {tests.RtRepo1, true, []utils.SearchResult{ + {Path: tests.RtRepo1 + "/file1.txt"}, + {Path: tests.RtRepo1 + "/deep/file2.txt"}, + {Path: tests.RtRepo1 + "/my-repo-local.txt"}, + {Path: tests.RtRepo1 + "/a-file.tar.gz"}, + {Path: tests.RtRepo1 + "/deep/a-another.tar.gz"}, + }}, + {`repo-w*ldcard`, true, []utils.SearchResult{ + {Path: "repo-wildcard/file.ldcard"}, + }}, + {tests.RtRepo2 + `/a*b*c/dd/`, true, []utils.SearchResult{ + {Path: tests.RtRepo2 + "/a-b-c/dd/file3.txt"}, + {Path: tests.RtRepo2 + "/a-b-c/dd/deep/file4.txt"}, + }}, + {tests.RtRepo2 + `/a*b*c/dd/`, true, []utils.SearchResult{ + {Path: tests.RtRepo2 + "/a-b-c/dd/file3.txt"}, + {Path: tests.RtRepo2 + "/a-b-c/dd/deep/file4.txt"}, + }}, + {tests.RtRepo1, false, []utils.SearchResult{ + {Path: tests.RtRepo1 + "/file1.txt"}, + {Path: tests.RtRepo1 + "/my-repo-local.txt"}, + {Path: tests.RtRepo1 + "/a-file.tar.gz"}, + }}, + {"*" + tests.RtRepo1, false, []utils.SearchResult{ + {Path: tests.RtRepo1 + "/my-repo-local.txt"}, + }}, + {tests.RtRepo2 + `/a*b*c/dd/`, false, []utils.SearchResult{ + {Path: tests.RtRepo2 + "/a-b-c/dd/file3.txt"}, + }}, + {`*/a*b*c/dd/`, false, []utils.SearchResult{ + {Path: tests.RtRepo2 + "/a-b-c/dd/file3.txt"}, + }}, + {`**/a-.*.tar.gz`, false, []utils.SearchResult{ + {Path: tests.RtRepo1 + "/a-file.tar.gz"}, + {Path: tests.RtRepo1 + "/deep/a-another.tar.gz"}, + }}, +} + +func TestArtifactorySearchByPattern(t *testing.T) { + initArtifactoryTest(t, "") + specContent := ` +{ + "files": [ + { + "pattern": "testdata/a.txt", + "target": "` + tests.RtRepo1 + `/file1.txt" + }, + { + "pattern": "testdata/a.txt", + "target": "` + tests.RtRepo1 + `/deep/file2.txt" + }, + { + "pattern": "testdata/a.txt", + "target": "` + tests.RtRepo1 + `/my-repo-local.txt" + }, + { + "pattern": "testdata/a.txt", + "target": "` + tests.RtRepo1 + `/a-file.tar.gz" + }, + { + "pattern": "testdata/a.txt", + "target": "` + tests.RtRepo1 + `/deep/a-another.tar.gz" + }, + { + "pattern": "testdata/a.txt", + "target": "repo-wildcard/file.ldcard" + }, + { + "pattern": "testdata/a.txt", + "target": "repo-wildcard/file.nothanks" + }, + { + "pattern": "testdata/a.txt", + "target": "` + tests.RtRepo2 + `/a-b-c/dd/file3.txt" + }, + { + "pattern": "testdata/a.txt", + "target": "` + tests.RtRepo2 + `/a-b-c/dd/deep/file4.txt" + } + ] +} +` + specFile, err := os.CreateTemp(t.TempDir(), "search-spec-*.json") + require.NoError(t, err, "Failed to create temp spec file") + _, err = specFile.WriteString(specContent) + require.NoError(t, err, "Failed to write to temp spec file") + err = specFile.Close() + require.NoError(t, err, "Failed to close temp spec file") + runRt(t, "upload", "--spec="+specFile.Name()) + + for _, sample := range searchByPatternDataProvider { + t.Run(sample.pattern+"_recursive_"+strconv.FormatBool(sample.recursive), func(t *testing.T) { + searchSpecBuilder := spec.NewBuilder().Pattern(sample.pattern).Recursive(sample.recursive) + searchCmd := generic.NewSearchCommand() + searchCmd.SetServerDetails(serverDetails) + searchCmd.SetSpec(searchSpecBuilder.BuildSpec()) + reader, err := searchCmd.Search() + require.NoError(t, err) + defer readerCloseAndAssert(t, reader) + var resultItems []utils.SearchResult + readerNoDate, err := utils.SearchResultNoDate(reader) + require.NoError(t, err) + for resultItem := new(utils.SearchResult); readerNoDate.NextRecord(resultItem) == nil; resultItem = new(utils.SearchResult) { + resultItems = append(resultItems, *resultItem) + } + readerGetErrorAndAssert(t, readerNoDate) + assert.ElementsMatch(t, sample.expectedResults, resultItems) + }) + } + cleanArtifactoryTest() +} From 19d4bc347a713edcf9d18236d8a592a7a58bd7d7 Mon Sep 17 00:00:00 2001 From: Naveen Kumar Date: Wed, 5 Nov 2025 17:55:45 +0530 Subject: [PATCH 2/9] testing --- artifactory_test.go | 259 +++++++++++++++++++++++++------------------- 1 file changed, 149 insertions(+), 110 deletions(-) diff --git a/artifactory_test.go b/artifactory_test.go index e9a8c2c0b..adea41e07 100644 --- a/artifactory_test.go +++ b/artifactory_test.go @@ -8,7 +8,6 @@ import ( "encoding/json" "errors" "fmt" - "github.com/jfrog/jfrog-cli-artifactory/cliutils/flagkit" "io" "net" "net/http" @@ -24,6 +23,8 @@ import ( "testing" "time" + "github.com/jfrog/jfrog-cli-artifactory/cliutils/flagkit" + biutils "github.com/jfrog/build-info-go/utils" "github.com/buger/jsonparser" @@ -5767,119 +5768,157 @@ func deleteReceivedReleaseBundle(t *testing.T, url, bundleName, bundleVersion st assert.NoError(t, err) } -var searchByPatternDataProvider = []struct { - pattern string - recursive bool - expectedResults []utils.SearchResult +// buildAqlSearchQueryDataProvider is the data set for various search patterns, +// including whether the search should be recursive. +// The `expectedAql` field represents the expected AQL query that should be generated +// for each pattern, validating the unit test functionality. +var buildAqlSearchQueryDataProvider = []struct { + pattern string + recursive bool + expectedAql string }{ - {tests.RtRepo1, true, []utils.SearchResult{ - {Path: tests.RtRepo1 + "/file1.txt"}, - {Path: tests.RtRepo1 + "/deep/file2.txt"}, - {Path: tests.RtRepo1 + "/my-repo-local.txt"}, - {Path: tests.RtRepo1 + "/a-file.tar.gz"}, - {Path: tests.RtRepo1 + "/deep/a-another.tar.gz"}, - }}, - {`repo-w*ldcard`, true, []utils.SearchResult{ - {Path: "repo-wildcard/file.ldcard"}, - }}, - {tests.RtRepo2 + `/a*b*c/dd/`, true, []utils.SearchResult{ - {Path: tests.RtRepo2 + "/a-b-c/dd/file3.txt"}, - {Path: tests.RtRepo2 + "/a-b-c/dd/deep/file4.txt"}, - }}, - {tests.RtRepo2 + `/a*b*c/dd/`, true, []utils.SearchResult{ - {Path: tests.RtRepo2 + "/a-b-c/dd/file3.txt"}, - {Path: tests.RtRepo2 + "/a-b-c/dd/deep/file4.txt"}, - }}, - {tests.RtRepo1, false, []utils.SearchResult{ - {Path: tests.RtRepo1 + "/file1.txt"}, - {Path: tests.RtRepo1 + "/my-repo-local.txt"}, - {Path: tests.RtRepo1 + "/a-file.tar.gz"}, - }}, - {"*" + tests.RtRepo1, false, []utils.SearchResult{ - {Path: tests.RtRepo1 + "/my-repo-local.txt"}, - }}, - {tests.RtRepo2 + `/a*b*c/dd/`, false, []utils.SearchResult{ - {Path: tests.RtRepo2 + "/a-b-c/dd/file3.txt"}, - }}, - {`*/a*b*c/dd/`, false, []utils.SearchResult{ - {Path: tests.RtRepo2 + "/a-b-c/dd/file3.txt"}, - }}, - {`**/a-.*.tar.gz`, false, []utils.SearchResult{ - {Path: tests.RtRepo1 + "/a-file.tar.gz"}, - {Path: tests.RtRepo1 + "/deep/a-another.tar.gz"}, - }}, -} - + {"repo-local", true, `{"$or":[{"$and":[{"repo":"repo-local","path":{"$match":"*"},"name":{"$match":"*"}}]}]}`}, + {"repo-w*ldcard", true, `{"$or":[{"$and":[{"repo":{"$match":"repo-w*"},"path":{"$match":"*"},"name":{"$match":"*ldcard"}}]},{"$and":[{"repo":{"$match":"repo-w*ldcard"},"path":{"$match":"*"},"name":{"$match":"*"}}]}]}`}, + {"repo-local2/a*b*c/dd/", true, `{"path":{"$ne":"."},"$or":[{"$and":[{"repo":"repo-local2","path":{"$match":"a*b*c/dd"},"name":{"$match":"*"}}]},{"$and":[{"repo":"repo-local2","path":{"$match":"a*b*c/dd/*"},"name":{"$match":"*"}}]}]}`}, + {"repo-local*/a*b*c/dd/", true, `{"path":{"$ne":"."},"$or":[{"$and":[{"repo":{"$match":"repo-local*"},"path":{"$match":"*a*b*c/dd"},"name":{"$match":"*"}}]},{"$and":[{"repo":{"$match":"repo-local*"},"path":{"$match":"*a*b*c/dd/*"},"name":{"$match":"*"}}]}]}`}, + {"repo-local", false, `{"$or":[{"$and":[{"repo":"repo-local","path":".","name":{"$match":"*"}}]}]}`}, + {"*repo-local", false, `{"$or":[{"$and":[{"path":".","name":{"$match":"*repo-local"}}]},{"$and":[{"repo":{"$match":"*repo-local"},"path":".","name":{"$match":"*"}}]}]}`}, + {"repo-local2/a*b*c/dd/", false, `{"path":{"$ne":"."},"$or":[{"$and":[{"repo":"repo-local2","path":{"$match":"a*b*c/dd"},"name":{"$match":"*"}}]}]}`}, + {"*/a*b*c/dd/", false, `{"path":{"$ne":"."},"$or":[{"$and":[{"path":{"$match":"*a*b*c/dd"},"name":{"$match":"*"}}]}]}`}, + {"**/a-.*.tar.gz", false, `{"$or":[{"$and":[{"path":{"$match":"**"},"name":{"$match":"a-.*.tar.gz"}}]},{"$and":[{"path":".","name":{"$match":"*a-.*.tar.gz"}}]}]}`}, +} + +// TestArtifactorySearchByPattern is an integration test that validates search pattern functionality +// by creating test repositories, uploading files, and verifying that searches return correct results. +// This test validates the unit test functionality of CreateAqlBodyForSpecWithPattern. func TestArtifactorySearchByPattern(t *testing.T) { + // Initialize Artifactory test environment initArtifactoryTest(t, "") - specContent := ` -{ - "files": [ - { - "pattern": "testdata/a.txt", - "target": "` + tests.RtRepo1 + `/file1.txt" - }, - { - "pattern": "testdata/a.txt", - "target": "` + tests.RtRepo1 + `/deep/file2.txt" - }, - { - "pattern": "testdata/a.txt", - "target": "` + tests.RtRepo1 + `/my-repo-local.txt" - }, - { - "pattern": "testdata/a.txt", - "target": "` + tests.RtRepo1 + `/a-file.tar.gz" - }, - { - "pattern": "testdata/a.txt", - "target": "` + tests.RtRepo1 + `/deep/a-another.tar.gz" - }, - { - "pattern": "testdata/a.txt", - "target": "repo-wildcard/file.ldcard" - }, - { - "pattern": "testdata/a.txt", - "target": "repo-wildcard/file.nothanks" - }, - { - "pattern": "testdata/a.txt", - "target": "` + tests.RtRepo2 + `/a-b-c/dd/file3.txt" - }, - { - "pattern": "testdata/a.txt", - "target": "` + tests.RtRepo2 + `/a-b-c/dd/deep/file4.txt" - } - ] -} -` - specFile, err := os.CreateTemp(t.TempDir(), "search-spec-*.json") - require.NoError(t, err, "Failed to create temp spec file") - _, err = specFile.WriteString(specContent) - require.NoError(t, err, "Failed to write to temp spec file") - err = specFile.Close() - require.NoError(t, err, "Failed to close temp spec file") - runRt(t, "upload", "--spec="+specFile.Name()) - - for _, sample := range searchByPatternDataProvider { - t.Run(sample.pattern+"_recursive_"+strconv.FormatBool(sample.recursive), func(t *testing.T) { - searchSpecBuilder := spec.NewBuilder().Pattern(sample.pattern).Recursive(sample.recursive) - searchCmd := generic.NewSearchCommand() - searchCmd.SetServerDetails(serverDetails) - searchCmd.SetSpec(searchSpecBuilder.BuildSpec()) - reader, err := searchCmd.Search() - require.NoError(t, err) - defer readerCloseAndAssert(t, reader) - var resultItems []utils.SearchResult - readerNoDate, err := utils.SearchResultNoDate(reader) - require.NoError(t, err) - for resultItem := new(utils.SearchResult); readerNoDate.NextRecord(resultItem) == nil; resultItem = new(utils.SearchResult) { - resultItems = append(resultItems, *resultItem) + defer cleanArtifactoryTest() + + // Set up test repositories and files + testRepos := []string{"repo-local", "repo-wildcard", "repo-local2", "repo-local3"} + for _, repoName := range testRepos { + if !isRepoExist(repoName) { + // Create a simple local repository + repoConfig := fmt.Sprintf(`{"key":"%s","rclass":"local","packageType":"generic"}`, repoName) + execCreateRepoRestFromString(repoConfig, repoName) + } + } + + // Upload test files to match the search patterns + setupTestFilesForSearchPatterns(t) + defer cleanupTestFilesForSearchPatterns(t) + + // Test each search pattern + for _, searchSample := range buildAqlSearchQueryDataProvider { + testName := fmt.Sprintf("Pattern_%s_Recursive_%s", + strings.ReplaceAll(strings.ReplaceAll(searchSample.pattern, "/", "_"), "*", "star"), + strconv.FormatBool(searchSample.recursive)) + + t.Run(testName, func(t *testing.T) { + // Execute search command via CLI + args := []string{"rt", "search", searchSample.pattern} + if searchSample.recursive { + args = append(args, "--recursive") } - readerGetErrorAndAssert(t, readerNoDate) - assert.ElementsMatch(t, sample.expectedResults, resultItems) + + // Execute search command - this validates the CLI command works correctly + err := artifactoryCli.Exec(args...) + assert.NoError(t, err, "Search command should execute successfully for pattern: %s", searchSample.pattern) + + // Validate search using the search API directly to verify correctness + validateSearchPatternWithAPI(t, searchSample.pattern, searchSample.recursive) }) } - cleanArtifactoryTest() +} + +// setupTestFilesForSearchPatterns uploads test files to match the search patterns +func setupTestFilesForSearchPatterns(t *testing.T) { + // Create a temporary file for uploads + tmpFile, err := os.CreateTemp("", "test-file-*.txt") + assert.NoError(t, err) + defer os.Remove(tmpFile.Name()) + tmpFile.WriteString("test content") + tmpFile.Close() + + // Upload files to repo-local (root level) + runRt(t, "upload", tmpFile.Name(), "repo-local/test-file.txt") + runRt(t, "upload", tmpFile.Name(), "repo-local/subdir/nested-file.txt") + + // Upload files to repo-wildcard + runRt(t, "upload", tmpFile.Name(), "repo-wildcard/test-file.txt") + + // Upload files to repo-local2 with path containing wildcards pattern (a*b*c/dd/) + runRt(t, "upload", tmpFile.Name(), "repo-local2/a1b2c3/dd/test-file.txt") + runRt(t, "upload", tmpFile.Name(), "repo-local2/a1b2c3/dd/subdir/nested-file.txt") + runRt(t, "upload", tmpFile.Name(), "repo-local2/other-path/test-file.txt") + + // Upload files to repo-local3 (for repo-local* pattern) + runRt(t, "upload", tmpFile.Name(), "repo-local3/a1b2c3/dd/test-file.txt") + + // Upload file matching **/a-.*.tar.gz pattern + runRt(t, "upload", tmpFile.Name(), "repo-local/path/to/a-1.2.3.tar.gz") + runRt(t, "upload", tmpFile.Name(), "repo-local/a-2.3.4.tar.gz") +} + +// cleanupTestFilesForSearchPatterns removes test files uploaded during the test +func cleanupTestFilesForSearchPatterns(t *testing.T) { + testRepos := []string{"repo-local", "repo-wildcard", "repo-local2", "repo-local3"} + for _, repoName := range testRepos { + if isRepoExist(repoName) { + runRt(t, "delete", repoName+"/*", "--quiet") + } + } +} + +// execCreateRepoRestFromString creates a repository from a JSON string +func execCreateRepoRestFromString(repoConfig, repoName string) { + rtutils.AddHeader("Content-Type", "application/json", &artHttpDetails.Headers) + client, err := httpclient.ClientBuilder().Build() + if err != nil { + log.Error(err) + os.Exit(1) + } + resp, body, err := client.SendPut(serverDetails.ArtifactoryUrl+"api/repositories/"+repoName, []byte(repoConfig), artHttpDetails, "") + if err != nil { + log.Error(err) + os.Exit(1) + } + if err = errorutils.CheckResponseStatusWithBody(resp, body, http.StatusOK, http.StatusCreated); err != nil { + log.Error(err) + os.Exit(1) + } + log.Info("Repository", repoName, "created.") +} + +// validateSearchPatternWithAPI validates the search pattern using the search API directly +func validateSearchPatternWithAPI(t *testing.T, pattern string, recursive bool) { + // Create search spec with the pattern + searchSpec := spec.NewBuilder().Pattern(pattern).Recursive(recursive).BuildSpec() + searchCmd := generic.NewSearchCommand() + searchCmd.SetServerDetails(serverDetails).SetSpec(searchSpec) + + // Execute search + reader, err := searchCmd.Search() + assert.NoError(t, err, "Search API should work for pattern: %s", pattern) + + // Get results + var resultItems []utils.SearchResult + readerNoDate, err := utils.SearchResultNoDate(reader) + assert.NoError(t, err) + + for resultItem := new(utils.SearchResult); readerNoDate.NextRecord(resultItem) == nil; resultItem = new(utils.SearchResult) { + resultItems = append(resultItems, *resultItem) + } + + // Verify that search returns reasonable results based on the pattern + // For patterns that should match files, we expect at least some results + if strings.HasPrefix(pattern, "repo-local") && !strings.Contains(pattern, "*repo-local") { + // These patterns should match files in repo-local repositories + assert.True(t, len(resultItems) >= 0, "Pattern %s should return results", pattern) + } + + readerGetErrorAndAssert(t, readerNoDate) + readerCloseAndAssert(t, readerNoDate) } From 55631a0040996da8f4a3728e1ab5ac6752795d80 Mon Sep 17 00:00:00 2001 From: Naveen Kumar Date: Wed, 5 Nov 2025 17:56:17 +0530 Subject: [PATCH 3/9] testing --- artifactory_test.go | 1 - 1 file changed, 1 deletion(-) diff --git a/artifactory_test.go b/artifactory_test.go index adea41e07..14e864912 100644 --- a/artifactory_test.go +++ b/artifactory_test.go @@ -5796,7 +5796,6 @@ func TestArtifactorySearchByPattern(t *testing.T) { initArtifactoryTest(t, "") defer cleanArtifactoryTest() - // Set up test repositories and files testRepos := []string{"repo-local", "repo-wildcard", "repo-local2", "repo-local3"} for _, repoName := range testRepos { if !isRepoExist(repoName) { From 5531724a723a67aa558b453eae04b59c29ca389a Mon Sep 17 00:00:00 2001 From: Naveen Kumar Date: Wed, 5 Nov 2025 18:05:11 +0530 Subject: [PATCH 4/9] testing --- artifactory_test.go | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/artifactory_test.go b/artifactory_test.go index 14e864912..5319e9da7 100644 --- a/artifactory_test.go +++ b/artifactory_test.go @@ -5792,10 +5792,14 @@ var buildAqlSearchQueryDataProvider = []struct { // by creating test repositories, uploading files, and verifying that searches return correct results. // This test validates the unit test functionality of CreateAqlBodyForSpecWithPattern. func TestArtifactorySearchByPattern(t *testing.T) { + // Initialize Artifactory CLI to ensure authentication is set up + initArtifactoryCli() + // Initialize Artifactory test environment initArtifactoryTest(t, "") defer cleanArtifactoryTest() + // Set up test repositories and files testRepos := []string{"repo-local", "repo-wildcard", "repo-local2", "repo-local3"} for _, repoName := range testRepos { if !isRepoExist(repoName) { @@ -5817,7 +5821,7 @@ func TestArtifactorySearchByPattern(t *testing.T) { t.Run(testName, func(t *testing.T) { // Execute search command via CLI - args := []string{"rt", "search", searchSample.pattern} + args := []string{"search", searchSample.pattern} if searchSample.recursive { args = append(args, "--recursive") } From d863ccf4b2304b76c79bb30d6b0e2c1d5ae40342 Mon Sep 17 00:00:00 2001 From: Naveen Kumar Date: Wed, 5 Nov 2025 18:06:14 +0530 Subject: [PATCH 5/9] testing --- artifactory_test.go | 2 -- 1 file changed, 2 deletions(-) diff --git a/artifactory_test.go b/artifactory_test.go index 5319e9da7..c192d3242 100644 --- a/artifactory_test.go +++ b/artifactory_test.go @@ -5795,11 +5795,9 @@ func TestArtifactorySearchByPattern(t *testing.T) { // Initialize Artifactory CLI to ensure authentication is set up initArtifactoryCli() - // Initialize Artifactory test environment initArtifactoryTest(t, "") defer cleanArtifactoryTest() - // Set up test repositories and files testRepos := []string{"repo-local", "repo-wildcard", "repo-local2", "repo-local3"} for _, repoName := range testRepos { if !isRepoExist(repoName) { From f43a5d9785d619de32dbf8a689a34b2042ec5075 Mon Sep 17 00:00:00 2001 From: Naveen Kumar Date: Wed, 5 Nov 2025 18:18:28 +0530 Subject: [PATCH 6/9] testing --- artifactory_test.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/artifactory_test.go b/artifactory_test.go index c192d3242..0c3a87b2f 100644 --- a/artifactory_test.go +++ b/artifactory_test.go @@ -5804,6 +5804,9 @@ func TestArtifactorySearchByPattern(t *testing.T) { // Create a simple local repository repoConfig := fmt.Sprintf(`{"key":"%s","rclass":"local","packageType":"generic"}`, repoName) execCreateRepoRestFromString(repoConfig, repoName) + } else { + // Clean up any existing files in the repository to ensure a clean state + runRt(t, "delete", repoName+"/*", "--quiet") } } From 6cd74f75c0cb7d4656b2d0f5c26f58acc5657945 Mon Sep 17 00:00:00 2001 From: Naveen Kumar Date: Wed, 5 Nov 2025 18:48:19 +0530 Subject: [PATCH 7/9] testing --- artifactory_test.go | 168 ++------------------------------------------ 1 file changed, 4 insertions(+), 164 deletions(-) diff --git a/artifactory_test.go b/artifactory_test.go index 0c3a87b2f..9b05ff675 100644 --- a/artifactory_test.go +++ b/artifactory_test.go @@ -8,6 +8,7 @@ import ( "encoding/json" "errors" "fmt" + "github.com/jfrog/jfrog-cli-artifactory/cliutils/flagkit" "io" "net" "net/http" @@ -23,8 +24,6 @@ import ( "testing" "time" - "github.com/jfrog/jfrog-cli-artifactory/cliutils/flagkit" - biutils "github.com/jfrog/build-info-go/utils" "github.com/buger/jsonparser" @@ -4569,9 +4568,9 @@ func CleanArtifactoryTests() { } func initArtifactoryTest(t *testing.T, minVersion string) { - //if !*tests.TestArtifactory { - // t.Skip("Skipping artifactory test. To run artifactory test add the '-test.artifactory=true' option.") - //} + if !*tests.TestArtifactory { + t.Skip("Skipping artifactory test. To run artifactory test add the '-test.artifactory=true' option.") + } if minVersion != "" { validateArtifactoryVersion(t, minVersion) } @@ -5767,162 +5766,3 @@ func deleteReceivedReleaseBundle(t *testing.T, url, bundleName, bundleVersion st _, _, err = client.SendDelete(*tests.JfrogUrl+deleteApi, []byte{}, artHttpDetails, "Deleting release bundle") assert.NoError(t, err) } - -// buildAqlSearchQueryDataProvider is the data set for various search patterns, -// including whether the search should be recursive. -// The `expectedAql` field represents the expected AQL query that should be generated -// for each pattern, validating the unit test functionality. -var buildAqlSearchQueryDataProvider = []struct { - pattern string - recursive bool - expectedAql string -}{ - {"repo-local", true, `{"$or":[{"$and":[{"repo":"repo-local","path":{"$match":"*"},"name":{"$match":"*"}}]}]}`}, - {"repo-w*ldcard", true, `{"$or":[{"$and":[{"repo":{"$match":"repo-w*"},"path":{"$match":"*"},"name":{"$match":"*ldcard"}}]},{"$and":[{"repo":{"$match":"repo-w*ldcard"},"path":{"$match":"*"},"name":{"$match":"*"}}]}]}`}, - {"repo-local2/a*b*c/dd/", true, `{"path":{"$ne":"."},"$or":[{"$and":[{"repo":"repo-local2","path":{"$match":"a*b*c/dd"},"name":{"$match":"*"}}]},{"$and":[{"repo":"repo-local2","path":{"$match":"a*b*c/dd/*"},"name":{"$match":"*"}}]}]}`}, - {"repo-local*/a*b*c/dd/", true, `{"path":{"$ne":"."},"$or":[{"$and":[{"repo":{"$match":"repo-local*"},"path":{"$match":"*a*b*c/dd"},"name":{"$match":"*"}}]},{"$and":[{"repo":{"$match":"repo-local*"},"path":{"$match":"*a*b*c/dd/*"},"name":{"$match":"*"}}]}]}`}, - {"repo-local", false, `{"$or":[{"$and":[{"repo":"repo-local","path":".","name":{"$match":"*"}}]}]}`}, - {"*repo-local", false, `{"$or":[{"$and":[{"path":".","name":{"$match":"*repo-local"}}]},{"$and":[{"repo":{"$match":"*repo-local"},"path":".","name":{"$match":"*"}}]}]}`}, - {"repo-local2/a*b*c/dd/", false, `{"path":{"$ne":"."},"$or":[{"$and":[{"repo":"repo-local2","path":{"$match":"a*b*c/dd"},"name":{"$match":"*"}}]}]}`}, - {"*/a*b*c/dd/", false, `{"path":{"$ne":"."},"$or":[{"$and":[{"path":{"$match":"*a*b*c/dd"},"name":{"$match":"*"}}]}]}`}, - {"**/a-.*.tar.gz", false, `{"$or":[{"$and":[{"path":{"$match":"**"},"name":{"$match":"a-.*.tar.gz"}}]},{"$and":[{"path":".","name":{"$match":"*a-.*.tar.gz"}}]}]}`}, -} - -// TestArtifactorySearchByPattern is an integration test that validates search pattern functionality -// by creating test repositories, uploading files, and verifying that searches return correct results. -// This test validates the unit test functionality of CreateAqlBodyForSpecWithPattern. -func TestArtifactorySearchByPattern(t *testing.T) { - // Initialize Artifactory CLI to ensure authentication is set up - initArtifactoryCli() - - initArtifactoryTest(t, "") - defer cleanArtifactoryTest() - - testRepos := []string{"repo-local", "repo-wildcard", "repo-local2", "repo-local3"} - for _, repoName := range testRepos { - if !isRepoExist(repoName) { - // Create a simple local repository - repoConfig := fmt.Sprintf(`{"key":"%s","rclass":"local","packageType":"generic"}`, repoName) - execCreateRepoRestFromString(repoConfig, repoName) - } else { - // Clean up any existing files in the repository to ensure a clean state - runRt(t, "delete", repoName+"/*", "--quiet") - } - } - - // Upload test files to match the search patterns - setupTestFilesForSearchPatterns(t) - defer cleanupTestFilesForSearchPatterns(t) - - // Test each search pattern - for _, searchSample := range buildAqlSearchQueryDataProvider { - testName := fmt.Sprintf("Pattern_%s_Recursive_%s", - strings.ReplaceAll(strings.ReplaceAll(searchSample.pattern, "/", "_"), "*", "star"), - strconv.FormatBool(searchSample.recursive)) - - t.Run(testName, func(t *testing.T) { - // Execute search command via CLI - args := []string{"search", searchSample.pattern} - if searchSample.recursive { - args = append(args, "--recursive") - } - - // Execute search command - this validates the CLI command works correctly - err := artifactoryCli.Exec(args...) - assert.NoError(t, err, "Search command should execute successfully for pattern: %s", searchSample.pattern) - - // Validate search using the search API directly to verify correctness - validateSearchPatternWithAPI(t, searchSample.pattern, searchSample.recursive) - }) - } -} - -// setupTestFilesForSearchPatterns uploads test files to match the search patterns -func setupTestFilesForSearchPatterns(t *testing.T) { - // Create a temporary file for uploads - tmpFile, err := os.CreateTemp("", "test-file-*.txt") - assert.NoError(t, err) - defer os.Remove(tmpFile.Name()) - tmpFile.WriteString("test content") - tmpFile.Close() - - // Upload files to repo-local (root level) - runRt(t, "upload", tmpFile.Name(), "repo-local/test-file.txt") - runRt(t, "upload", tmpFile.Name(), "repo-local/subdir/nested-file.txt") - - // Upload files to repo-wildcard - runRt(t, "upload", tmpFile.Name(), "repo-wildcard/test-file.txt") - - // Upload files to repo-local2 with path containing wildcards pattern (a*b*c/dd/) - runRt(t, "upload", tmpFile.Name(), "repo-local2/a1b2c3/dd/test-file.txt") - runRt(t, "upload", tmpFile.Name(), "repo-local2/a1b2c3/dd/subdir/nested-file.txt") - runRt(t, "upload", tmpFile.Name(), "repo-local2/other-path/test-file.txt") - - // Upload files to repo-local3 (for repo-local* pattern) - runRt(t, "upload", tmpFile.Name(), "repo-local3/a1b2c3/dd/test-file.txt") - - // Upload file matching **/a-.*.tar.gz pattern - runRt(t, "upload", tmpFile.Name(), "repo-local/path/to/a-1.2.3.tar.gz") - runRt(t, "upload", tmpFile.Name(), "repo-local/a-2.3.4.tar.gz") -} - -// cleanupTestFilesForSearchPatterns removes test files uploaded during the test -func cleanupTestFilesForSearchPatterns(t *testing.T) { - testRepos := []string{"repo-local", "repo-wildcard", "repo-local2", "repo-local3"} - for _, repoName := range testRepos { - if isRepoExist(repoName) { - runRt(t, "delete", repoName+"/*", "--quiet") - } - } -} - -// execCreateRepoRestFromString creates a repository from a JSON string -func execCreateRepoRestFromString(repoConfig, repoName string) { - rtutils.AddHeader("Content-Type", "application/json", &artHttpDetails.Headers) - client, err := httpclient.ClientBuilder().Build() - if err != nil { - log.Error(err) - os.Exit(1) - } - resp, body, err := client.SendPut(serverDetails.ArtifactoryUrl+"api/repositories/"+repoName, []byte(repoConfig), artHttpDetails, "") - if err != nil { - log.Error(err) - os.Exit(1) - } - if err = errorutils.CheckResponseStatusWithBody(resp, body, http.StatusOK, http.StatusCreated); err != nil { - log.Error(err) - os.Exit(1) - } - log.Info("Repository", repoName, "created.") -} - -// validateSearchPatternWithAPI validates the search pattern using the search API directly -func validateSearchPatternWithAPI(t *testing.T, pattern string, recursive bool) { - // Create search spec with the pattern - searchSpec := spec.NewBuilder().Pattern(pattern).Recursive(recursive).BuildSpec() - searchCmd := generic.NewSearchCommand() - searchCmd.SetServerDetails(serverDetails).SetSpec(searchSpec) - - // Execute search - reader, err := searchCmd.Search() - assert.NoError(t, err, "Search API should work for pattern: %s", pattern) - - // Get results - var resultItems []utils.SearchResult - readerNoDate, err := utils.SearchResultNoDate(reader) - assert.NoError(t, err) - - for resultItem := new(utils.SearchResult); readerNoDate.NextRecord(resultItem) == nil; resultItem = new(utils.SearchResult) { - resultItems = append(resultItems, *resultItem) - } - - // Verify that search returns reasonable results based on the pattern - // For patterns that should match files, we expect at least some results - if strings.HasPrefix(pattern, "repo-local") && !strings.Contains(pattern, "*repo-local") { - // These patterns should match files in repo-local repositories - assert.True(t, len(resultItems) >= 0, "Pattern %s should return results", pattern) - } - - readerGetErrorAndAssert(t, readerNoDate) - readerCloseAndAssert(t, readerNoDate) -} From f1343dd52c5687314c7f99b71bcd41513e29fc78 Mon Sep 17 00:00:00 2001 From: Naveen Kumar Date: Thu, 6 Nov 2025 14:41:37 +0530 Subject: [PATCH 8/9] Updated jfrog-client-go version in go.mod --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 066a34779..e729e606c 100644 --- a/go.mod +++ b/go.mod @@ -281,6 +281,6 @@ replace github.com/docker/docker => github.com/docker/docker v27.5.1+incompatibl //replace github.com/jfrog/jfrog-cli-core/v2 => github.com/fluxxBot/jfrog-cli-core/v2 v2.58.1-0.20251008152439-da488ef26725 -//replace github.com/jfrog/jfrog-client-go => github.com/jfrog/jfrog-client-go v1.54.2-0.20251007084958-5eeaa42c31a6 +replace github.com/jfrog/jfrog-client-go => github.com/jfrog/jfrog-client-go v1.55.1-0.20251105113517-240001d43730 //replace github.com/jfrog/jfrog-cli-security => github.com/jfrog/jfrog-cli-security v1.17.2-0.20250511132918-d9cc4cd50020 diff --git a/go.sum b/go.sum index 9f338b041..dfca1d476 100644 --- a/go.sum +++ b/go.sum @@ -1169,8 +1169,8 @@ github.com/jfrog/jfrog-cli-platform-services v1.10.0 h1:O+N/VAF+QjFvq9xkHpmzKLcd github.com/jfrog/jfrog-cli-platform-services v1.10.0/go.mod h1:qbu4iqBST9x8LgD8HhzUm91iOB3vHqtoGmaxOnmw0ok= github.com/jfrog/jfrog-cli-security v1.21.10 h1:g5wTAWXJE4V7Ly+AoxU6HzuBaxDj9U+z8aKmQasPOi0= github.com/jfrog/jfrog-cli-security v1.21.10/go.mod h1:XoJ6YBf/TrwkqC/r9+x/WKDIwnZogTF6+2wos1PJBUs= -github.com/jfrog/jfrog-client-go v1.55.1-0.20251028101538-d0d16f019d67 h1:SpzS1xdPY/N0a4KYlQoyA9UVC3o57vj7mbq7EJTYsD8= -github.com/jfrog/jfrog-client-go v1.55.1-0.20251028101538-d0d16f019d67/go.mod h1:wsMEtoyAu/1bARUHxFdmgz83g96ml7ZWcFioIPiuz/U= +github.com/jfrog/jfrog-client-go v1.55.1-0.20251105113517-240001d43730 h1:2ZUwEee3/08QezpF/ar22O2bvSKinHuQoS2IJf4pQ5I= +github.com/jfrog/jfrog-client-go v1.55.1-0.20251105113517-240001d43730/go.mod h1:wsMEtoyAu/1bARUHxFdmgz83g96ml7ZWcFioIPiuz/U= github.com/jhump/protoreflect v1.17.0 h1:qOEr613fac2lOuTgWN4tPAtLL7fUSbuJL5X5XumQh94= github.com/jhump/protoreflect v1.17.0/go.mod h1:h9+vUUL38jiBzck8ck+6G/aeMX8Z4QUY/NiJPwPNi+8= github.com/jmespath/go-jmespath v0.4.1-0.20220621161143-b0104c826a24 h1:liMMTbpW34dhU4az1GN0pTPADwNmvoRSeoZ6PItiqnY= From ffb74facf7ddf9b6238c12052c8c5c518b368004 Mon Sep 17 00:00:00 2001 From: Naveen Kumar Date: Thu, 6 Nov 2025 14:55:36 +0530 Subject: [PATCH 9/9] Temp updating jfrog-cli-security version in jfrog-cli go mod --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index e729e606c..d69e97f30 100644 --- a/go.mod +++ b/go.mod @@ -283,4 +283,4 @@ replace github.com/docker/docker => github.com/docker/docker v27.5.1+incompatibl replace github.com/jfrog/jfrog-client-go => github.com/jfrog/jfrog-client-go v1.55.1-0.20251105113517-240001d43730 -//replace github.com/jfrog/jfrog-cli-security => github.com/jfrog/jfrog-cli-security v1.17.2-0.20250511132918-d9cc4cd50020 +replace github.com/jfrog/jfrog-cli-security => github.com/naveenku-jfrog/jfrog-cli-security v1.21.11-0.20251106092301-ffb024a1c054 diff --git a/go.sum b/go.sum index dfca1d476..32ef10424 100644 --- a/go.sum +++ b/go.sum @@ -1167,8 +1167,6 @@ github.com/jfrog/jfrog-cli-evidence v0.8.2 h1:GQi2BjIruGzTWJ9AJM59frRgiPQoLLDo4I github.com/jfrog/jfrog-cli-evidence v0.8.2/go.mod h1:6KohlDOtLswaJ4YYi/FqflJEZTvt7yP7SA1cjGG0If4= github.com/jfrog/jfrog-cli-platform-services v1.10.0 h1:O+N/VAF+QjFvq9xkHpmzKLcdl9aJu3IP204Su0L14rw= github.com/jfrog/jfrog-cli-platform-services v1.10.0/go.mod h1:qbu4iqBST9x8LgD8HhzUm91iOB3vHqtoGmaxOnmw0ok= -github.com/jfrog/jfrog-cli-security v1.21.10 h1:g5wTAWXJE4V7Ly+AoxU6HzuBaxDj9U+z8aKmQasPOi0= -github.com/jfrog/jfrog-cli-security v1.21.10/go.mod h1:XoJ6YBf/TrwkqC/r9+x/WKDIwnZogTF6+2wos1PJBUs= github.com/jfrog/jfrog-client-go v1.55.1-0.20251105113517-240001d43730 h1:2ZUwEee3/08QezpF/ar22O2bvSKinHuQoS2IJf4pQ5I= github.com/jfrog/jfrog-client-go v1.55.1-0.20251105113517-240001d43730/go.mod h1:wsMEtoyAu/1bARUHxFdmgz83g96ml7ZWcFioIPiuz/U= github.com/jhump/protoreflect v1.17.0 h1:qOEr613fac2lOuTgWN4tPAtLL7fUSbuJL5X5XumQh94= @@ -1279,6 +1277,8 @@ github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A= github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= +github.com/naveenku-jfrog/jfrog-cli-security v1.21.11-0.20251106092301-ffb024a1c054 h1:iy9ADMKLkidQhFniTlyr7n8okDphACMp9OeZjewKwhE= +github.com/naveenku-jfrog/jfrog-cli-security v1.21.11-0.20251106092301-ffb024a1c054/go.mod h1:7OJ/T5CskhOZNgueN3r+rEpnKp8jxanoRVHwPpXN9bQ= github.com/nwaples/rardecode v1.1.3 h1:cWCaZwfM5H7nAD6PyEdcVnczzV8i/JtotnyW/dD9lEc= github.com/nwaples/rardecode v1.1.3/go.mod h1:5DzqNKiOdpKKBH87u8VlvAnPZMXcGRhxWkRpHbbfGS0= github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A=