git.frostfs.info/TrueCloudLab/frostfs-sdk-go@v0.0.0-20241022124111-5361f0ecebd3/object/search_test.go (about)

     1  package object_test
     2  
     3  import (
     4  	"crypto/rand"
     5  	"crypto/sha256"
     6  	"testing"
     7  
     8  	v2object "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object"
     9  	"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object"
    10  	oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id"
    11  	"github.com/stretchr/testify/require"
    12  )
    13  
    14  var eqV2Matches = map[object.SearchMatchType]v2object.MatchType{
    15  	object.MatchUnknown:        v2object.MatchUnknown,
    16  	object.MatchStringEqual:    v2object.MatchStringEqual,
    17  	object.MatchStringNotEqual: v2object.MatchStringNotEqual,
    18  	object.MatchNotPresent:     v2object.MatchNotPresent,
    19  	object.MatchCommonPrefix:   v2object.MatchCommonPrefix,
    20  }
    21  
    22  func TestMatch(t *testing.T) {
    23  	t.Run("known matches", func(t *testing.T) {
    24  		for matchType, matchTypeV2 := range eqV2Matches {
    25  			require.Equal(t, matchTypeV2, matchType.ToV2())
    26  			require.Equal(t, object.SearchMatchFromV2(matchTypeV2), matchType)
    27  		}
    28  	})
    29  
    30  	t.Run("unknown matches", func(t *testing.T) {
    31  		var unknownMatchType object.SearchMatchType
    32  
    33  		for matchType := range eqV2Matches {
    34  			unknownMatchType += matchType
    35  		}
    36  
    37  		unknownMatchType++
    38  
    39  		require.Equal(t, unknownMatchType.ToV2(), v2object.MatchUnknown)
    40  
    41  		var unknownMatchTypeV2 v2object.MatchType
    42  
    43  		for _, matchTypeV2 := range eqV2Matches {
    44  			unknownMatchTypeV2 += matchTypeV2
    45  		}
    46  
    47  		unknownMatchTypeV2++
    48  
    49  		require.Equal(t, object.SearchMatchFromV2(unknownMatchTypeV2), object.MatchUnknown)
    50  	})
    51  }
    52  
    53  func TestFilter(t *testing.T) {
    54  	inputs := [][]string{
    55  		{"user-header", "user-value"},
    56  	}
    57  
    58  	filters := object.NewSearchFilters()
    59  	for i := range inputs {
    60  		filters.AddFilter(inputs[i][0], inputs[i][1], object.MatchStringEqual)
    61  	}
    62  
    63  	require.Len(t, filters, len(inputs))
    64  	for i := range inputs {
    65  		require.Equal(t, inputs[i][0], filters[i].Header())
    66  		require.Equal(t, inputs[i][1], filters[i].Value())
    67  		require.Equal(t, object.MatchStringEqual, filters[i].Operation())
    68  	}
    69  
    70  	v2 := filters.ToV2()
    71  	newFilters := object.NewSearchFiltersFromV2(v2)
    72  	require.Equal(t, filters, newFilters)
    73  }
    74  
    75  func TestSearchFilters_AddRootFilter(t *testing.T) {
    76  	fs := new(object.SearchFilters)
    77  
    78  	fs.AddRootFilter()
    79  
    80  	require.Len(t, *fs, 1)
    81  
    82  	f := (*fs)[0]
    83  
    84  	require.Equal(t, object.MatchUnknown, f.Operation())
    85  	require.Equal(t, v2object.FilterPropertyRoot, f.Header())
    86  	require.Equal(t, "", f.Value())
    87  }
    88  
    89  func TestSearchFilters_AddPhyFilter(t *testing.T) {
    90  	fs := new(object.SearchFilters)
    91  
    92  	fs.AddPhyFilter()
    93  
    94  	require.Len(t, *fs, 1)
    95  
    96  	f := (*fs)[0]
    97  
    98  	require.Equal(t, object.MatchUnknown, f.Operation())
    99  	require.Equal(t, v2object.FilterPropertyPhy, f.Header())
   100  	require.Equal(t, "", f.Value())
   101  }
   102  
   103  func testOID() oid.ID {
   104  	cs := [sha256.Size]byte{}
   105  
   106  	rand.Read(cs[:])
   107  
   108  	var id oid.ID
   109  	id.SetSHA256(cs)
   110  
   111  	return id
   112  }
   113  
   114  func TestSearchFilters_AddParentIDFilter(t *testing.T) {
   115  	par := testOID()
   116  
   117  	fs := object.SearchFilters{}
   118  	fs.AddParentIDFilter(object.MatchStringEqual, par)
   119  
   120  	fsV2 := fs.ToV2()
   121  
   122  	require.Len(t, fsV2, 1)
   123  
   124  	require.Equal(t, v2object.FilterHeaderParent, fsV2[0].GetKey())
   125  	require.Equal(t, par.EncodeToString(), fsV2[0].GetValue())
   126  	require.Equal(t, v2object.MatchStringEqual, fsV2[0].GetMatchType())
   127  }
   128  
   129  func TestSearchFilters_AddObjectIDFilter(t *testing.T) {
   130  	id := testOID()
   131  
   132  	fs := new(object.SearchFilters)
   133  	fs.AddObjectIDFilter(object.MatchStringEqual, id)
   134  
   135  	t.Run("v2", func(t *testing.T) {
   136  		fsV2 := fs.ToV2()
   137  
   138  		require.Len(t, fsV2, 1)
   139  
   140  		require.Equal(t, v2object.FilterHeaderObjectID, fsV2[0].GetKey())
   141  		require.Equal(t, id.EncodeToString(), fsV2[0].GetValue())
   142  		require.Equal(t, v2object.MatchStringEqual, fsV2[0].GetMatchType())
   143  	})
   144  }
   145  
   146  func TestSearchFilters_AddSplitIDFilter(t *testing.T) {
   147  	id := object.NewSplitID()
   148  
   149  	fs := new(object.SearchFilters)
   150  	fs.AddSplitIDFilter(object.MatchStringEqual, id)
   151  
   152  	t.Run("v2", func(t *testing.T) {
   153  		fsV2 := fs.ToV2()
   154  
   155  		require.Len(t, fsV2, 1)
   156  
   157  		require.Equal(t, v2object.FilterHeaderSplitID, fsV2[0].GetKey())
   158  		require.Equal(t, id.String(), fsV2[0].GetValue())
   159  		require.Equal(t, v2object.MatchStringEqual, fsV2[0].GetMatchType())
   160  	})
   161  }
   162  
   163  func TestSearchFilters_AddECParentFilter(t *testing.T) {
   164  	id := testOID()
   165  
   166  	fs := new(object.SearchFilters)
   167  	fs.AddECParentFilter(object.MatchStringEqual, id)
   168  
   169  	t.Run("v2", func(t *testing.T) {
   170  		fsV2 := fs.ToV2()
   171  
   172  		require.Len(t, fsV2, 1)
   173  
   174  		require.Equal(t, v2object.FilterHeaderECParent, fsV2[0].GetKey())
   175  		require.Equal(t, id.String(), fsV2[0].GetValue())
   176  		require.Equal(t, v2object.MatchStringEqual, fsV2[0].GetMatchType())
   177  	})
   178  }
   179  
   180  func TestSearchFilters_AddTypeFilter(t *testing.T) {
   181  	typ := object.TypeTombstone
   182  
   183  	fs := new(object.SearchFilters)
   184  	fs.AddTypeFilter(object.MatchStringEqual, typ)
   185  
   186  	t.Run("v2", func(t *testing.T) {
   187  		fsV2 := fs.ToV2()
   188  
   189  		require.Len(t, fsV2, 1)
   190  
   191  		require.Equal(t, v2object.FilterHeaderObjectType, fsV2[0].GetKey())
   192  		require.Equal(t, typ.String(), fsV2[0].GetValue())
   193  		require.Equal(t, v2object.MatchStringEqual, fsV2[0].GetMatchType())
   194  	})
   195  }
   196  
   197  func TestSearchFiltersEncoding(t *testing.T) {
   198  	fs := object.NewSearchFilters()
   199  	fs.AddFilter("key 1", "value 2", object.MatchStringEqual)
   200  	fs.AddFilter("key 2", "value 2", object.MatchStringNotEqual)
   201  	fs.AddFilter("key 2", "value 2", object.MatchCommonPrefix)
   202  
   203  	t.Run("json", func(t *testing.T) {
   204  		data, err := fs.MarshalJSON()
   205  		require.NoError(t, err)
   206  
   207  		fs2 := object.NewSearchFilters()
   208  		require.NoError(t, fs2.UnmarshalJSON(data))
   209  
   210  		require.Equal(t, fs, fs2)
   211  	})
   212  }
   213  
   214  func TestSearchMatchType_String(t *testing.T) {
   215  	toPtr := func(v object.SearchMatchType) *object.SearchMatchType {
   216  		return &v
   217  	}
   218  
   219  	testEnumStrings(t, new(object.SearchMatchType), []enumStringItem{
   220  		{val: toPtr(object.MatchCommonPrefix), str: "COMMON_PREFIX"},
   221  		{val: toPtr(object.MatchStringEqual), str: "STRING_EQUAL"},
   222  		{val: toPtr(object.MatchStringNotEqual), str: "STRING_NOT_EQUAL"},
   223  		{val: toPtr(object.MatchNotPresent), str: "NOT_PRESENT"},
   224  		{val: toPtr(object.MatchUnknown), str: "MATCH_TYPE_UNSPECIFIED"},
   225  	})
   226  }