github.com/jfrog/jfrog-cli-core/v2@v2.51.0/artifactory/commands/transferfiles/longpropertycheck_test.go (about) 1 package transferfiles 2 3 import ( 4 "encoding/json" 5 "io" 6 "net/http" 7 "net/http/httptest" 8 "strings" 9 "sync" 10 "testing" 11 12 "github.com/jfrog/gofrog/parallel" 13 "github.com/jfrog/jfrog-cli-core/v2/artifactory/commands/transferfiles/api" 14 "github.com/jfrog/jfrog-cli-core/v2/artifactory/commands/utils/precheckrunner" 15 commonTests "github.com/jfrog/jfrog-cli-core/v2/common/tests" 16 "github.com/jfrog/jfrog-cli-core/v2/utils/config" 17 "github.com/jfrog/jfrog-client-go/artifactory" 18 servicesUtils "github.com/jfrog/jfrog-client-go/artifactory/services/utils" 19 clientutils "github.com/jfrog/jfrog-client-go/utils" 20 "github.com/stretchr/testify/assert" 21 ) 22 23 var ( 24 property = Property{Key: "test.key", Value: "value"} 25 shorterProperty = Property{Key: "shorter.key", Value: strings.Repeat("a", maxAllowedValLength-1)} 26 borderProperty = Property{Key: "border.key", Value: strings.Repeat("b", maxAllowedValLength)} 27 longProperty = Property{Key: "too.long.key", Value: strings.Repeat("c", maxAllowedValLength+1)} 28 longProperty2 = Property{Key: "too.long.2.key", Value: strings.Repeat("dd", maxAllowedValLength)} 29 30 file1 = api.FileRepresentation{Repo: "Repo", Path: "Path", Name: "Name"} 31 file2 = api.FileRepresentation{Repo: "OtherRepo", Path: "Path", Name: "Name"} 32 33 propertyToFiles = map[Property][]api.FileRepresentation{ 34 property: {}, 35 shorterProperty: {file1}, 36 borderProperty: {file2}, 37 longProperty: {file1, file2}, 38 longProperty2: {file1}, 39 } 40 ) 41 42 func TestProperty(t *testing.T) { 43 cases := []struct { 44 property Property 45 isLong bool 46 }{ 47 {Property{}, false}, 48 {shorterProperty, false}, 49 {borderProperty, false}, 50 {longProperty, true}, 51 } 52 53 for _, testCase := range cases { 54 testProperty(t, testCase.property, testCase.isLong) 55 } 56 } 57 58 func testProperty(t *testing.T, property Property, isLong bool) { 59 assert.Len(t, property.Value, int(property.valueLength())) 60 long := isLongProperty(property) 61 assert.Equal(t, isLong, long) 62 } 63 64 func TestGetLongProperties(t *testing.T) { 65 cases := []struct { 66 serverProperties []Property 67 longProperties []Property 68 }{ 69 {[]Property{}, []Property{}}, 70 {[]Property{property, shorterProperty}, []Property{}}, 71 {[]Property{property, shorterProperty, longProperty2, borderProperty, longProperty}, []Property{longProperty, longProperty2}}, 72 } 73 74 for _, testCase := range cases { 75 testGetLongProperties(t, testCase.serverProperties, testCase.longProperties) 76 } 77 } 78 79 func testGetLongProperties(t *testing.T, serverProperties, expectedLongProperties []Property) { 80 testServer, serverDetails, _ := getLongPropertyCheckStubServer(t, serverProperties, propertyToFiles, false) 81 defer testServer.Close() 82 83 longPropertyCheck := NewLongPropertyCheck([]string{}, true) 84 longPropertyCheck.filesChan = make(chan FileWithLongProperty, threadCount) 85 86 count := longPropertyCheck.longPropertiesTaskProducer(nil, precheckrunner.RunArguments{Context: nil, ServerDetails: serverDetails}) 87 assert.Len(t, expectedLongProperties, count) 88 } 89 90 func TestSearchPropertyInFilesTask(t *testing.T) { 91 cases := []struct { 92 prop Property 93 specificRepos []string 94 expected []FileWithLongProperty 95 }{ 96 {property, []string{"Repo", "OtherRepo"}, []FileWithLongProperty{}}, 97 {borderProperty, []string{"Repo", "OtherRepo"}, []FileWithLongProperty{{file2, borderProperty.valueLength(), borderProperty}}}, 98 {longProperty, []string{"Repo", "OtherRepo"}, []FileWithLongProperty{{file1, longProperty.valueLength(), longProperty}, {file2, longProperty.valueLength(), longProperty}}}, 99 {longProperty, []string{"Repo"}, []FileWithLongProperty{{file1, longProperty.valueLength(), longProperty}}}, 100 } 101 102 for _, testCase := range cases { 103 testSearchPropertyInFilesTask(t, testCase.prop, testCase.specificRepos, propertyToFiles, testCase.expected) 104 } 105 } 106 107 func testSearchPropertyInFilesTask(t *testing.T, prop Property, specificRepos []string, propertiesFiles map[Property][]api.FileRepresentation, expected []FileWithLongProperty) { 108 testServer, serverDetails, _ := getLongPropertyCheckStubServer(t, nil, propertiesFiles, false) 109 defer testServer.Close() 110 111 var result []FileWithLongProperty 112 filesChan := make(chan FileWithLongProperty) 113 114 var wait sync.WaitGroup 115 wait.Add(1) 116 go func() { 117 for current := range filesChan { 118 result = append(result, current) 119 } 120 wait.Done() 121 }() 122 123 longPropertyCheck := LongPropertyCheck{ 124 filesChan: filesChan, 125 repos: specificRepos, 126 } 127 task := longPropertyCheck.createSearchPropertyTask(prop, precheckrunner.RunArguments{Context: nil, ServerDetails: serverDetails}, nil) 128 assert.NoError(t, task(0)) 129 close(filesChan) 130 wait.Wait() 131 assert.ElementsMatch(t, expected, result) 132 } 133 134 func TestSearchLongPropertiesInFiles(t *testing.T) { 135 cases := []struct { 136 properties []Property 137 specificRepos []string 138 expected []FileWithLongProperty 139 }{ 140 {[]Property{}, []string{"Repo", "OtherRepo"}, []FileWithLongProperty{}}, 141 {[]Property{property, borderProperty}, []string{"Repo", "OtherRepo"}, []FileWithLongProperty{}}, 142 {[]Property{property, shorterProperty, borderProperty, longProperty, longProperty2}, []string{"Repo", "OtherRepo"}, []FileWithLongProperty{ 143 {file1, longProperty.valueLength(), longProperty}, 144 {file2, longProperty.valueLength(), longProperty}, 145 {file1, longProperty2.valueLength(), longProperty2}, 146 }}, 147 {[]Property{property, shorterProperty, borderProperty, longProperty, longProperty2}, []string{"Repo"}, []FileWithLongProperty{ 148 {file1, longProperty.valueLength(), longProperty}, 149 {file1, longProperty2.valueLength(), longProperty2}, 150 }}, 151 } 152 153 for _, testCase := range cases { 154 testSearchPropertiesInFiles(t, testCase.properties, testCase.specificRepos, propertyToFiles, testCase.expected) 155 } 156 } 157 158 func testSearchPropertiesInFiles(t *testing.T, properties []Property, specificRepos []string, propertiesFiles map[Property][]api.FileRepresentation, expected []FileWithLongProperty) { 159 testServer, serverDetails, _ := getLongPropertyCheckStubServer(t, properties, propertiesFiles, false) 160 defer testServer.Close() 161 162 longPropertyCheck := NewLongPropertyCheck(specificRepos, false) 163 longPropertyCheck.producerConsumer = parallel.NewRunner(threadCount, maxThreadCapacity, false) 164 longPropertyCheck.filesChan = make(chan FileWithLongProperty, threadCount) 165 longPropertyCheck.errorsQueue = clientutils.NewErrorsQueue(1) 166 167 var files []FileWithLongProperty 168 var waitCollection sync.WaitGroup 169 170 waitCollection.Add(1) 171 go func() { 172 for current := range longPropertyCheck.filesChan { 173 files = append(files, current) 174 } 175 waitCollection.Done() 176 }() 177 178 longPropertyCheck.longPropertiesTaskProducer(nil, precheckrunner.RunArguments{Context: nil, ServerDetails: serverDetails}) 179 longPropertyCheck.producerConsumer.Done() 180 longPropertyCheck.producerConsumer.Run() 181 close(longPropertyCheck.filesChan) 182 waitCollection.Wait() 183 assert.ElementsMatch(t, expected, files) 184 } 185 186 func TestLongPropertyExecuteCheck(t *testing.T) { 187 cases := []struct { 188 serverProperties []Property 189 specificRepos []string 190 disabledDistinctiveAql bool 191 shouldPass bool 192 }{ 193 {[]Property{}, []string{"Repo", "OtherRepo"}, true, true}, 194 {[]Property{property, shorterProperty, borderProperty}, []string{"Repo", "OtherRepo"}, false, true}, 195 {[]Property{property, shorterProperty, borderProperty, longProperty, longProperty2}, []string{"Repo", "OtherRepo"}, true, false}, 196 {[]Property{property, shorterProperty, borderProperty, longProperty2}, []string{"Repo", "OtherRepo"}, false, false}, 197 {[]Property{property, shorterProperty, borderProperty, longProperty2}, []string{"OtherRepo"}, true, true}, 198 } 199 200 for _, testCase := range cases { 201 testLongPropertyCheckWithStubServer(t, testCase.serverProperties, testCase.specificRepos, propertyToFiles, testCase.disabledDistinctiveAql, testCase.shouldPass) 202 } 203 } 204 205 func testLongPropertyCheckWithStubServer(t *testing.T, serverProperties []Property, specificRepos []string, propertiesFiles map[Property][]api.FileRepresentation, disabledDistinctiveAql, shouldPass bool) { 206 testServer, serverDetails, _ := getLongPropertyCheckStubServer(t, serverProperties, propertiesFiles, disabledDistinctiveAql) 207 defer testServer.Close() 208 209 longPropertyCheck := NewLongPropertyCheck(specificRepos, disabledDistinctiveAql) 210 passed, err := longPropertyCheck.ExecuteCheck(precheckrunner.RunArguments{Context: nil, ServerDetails: serverDetails}) 211 assert.NoError(t, err) 212 assert.Equal(t, shouldPass, passed) 213 } 214 215 func getLongPropertyCheckStubServer(t *testing.T, serverProperties []Property, propertiesFiles map[Property][]api.FileRepresentation, disabledDistinctiveAql bool) (*httptest.Server, *config.ServerDetails, artifactory.ArtifactoryServicesManager) { 216 return commonTests.CreateRtRestsMockServer(t, func(w http.ResponseWriter, r *http.Request) { 217 if r.RequestURI == "/"+"api/search/aql" { 218 content, err := io.ReadAll(r.Body) 219 assert.NoError(t, err) 220 strContent := string(content) 221 if strings.Contains(strContent, "properties.find") { 222 // Return all known properties 223 result := &AqlPropertySearchResult{serverProperties} 224 content, err = json.Marshal(result) 225 assert.NoError(t, err) 226 _, err = w.Write(content) 227 assert.NoError(t, err) 228 } else if strings.Contains(strContent, "items.find") { 229 // Return all known files with the requested properties 230 res := &servicesUtils.AqlSearchResult{} 231 for prop, files := range propertiesFiles { 232 if strings.Contains(strContent, prop.Key) && strings.Contains(strContent, prop.Value) { 233 for _, file := range files { 234 res.Results = append(res.Results, servicesUtils.ResultItem{ 235 Repo: file.Repo, 236 Path: file.Path, 237 Name: file.Name, 238 }) 239 } 240 } 241 } 242 content, err = json.Marshal(res) 243 assert.NoError(t, err) 244 _, err = w.Write(content) 245 assert.NoError(t, err) 246 if disabledDistinctiveAql { 247 assert.Contains(t, strContent, ".distinct(false)") 248 } else { 249 assert.NotContains(t, strContent, ".distinct(false)") 250 } 251 } 252 } 253 }) 254 }