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  }