github.com/m3db/m3@v1.5.0/src/query/api/v1/handler/database/kvstore_test.go (about)

     1  // Copyright (c) 2021 Uber Technologies, Inc.
     2  //
     3  // Permission is hereby granted, free of charge, to any person obtaining a copy
     4  // of this software and associated documentation files (the "Software"), to deal
     5  // in the Software without restriction, including without limitation the rights
     6  // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
     7  // copies of the Software, and to permit persons to whom the Software is
     8  // furnished to do so, subject to the following conditions:
     9  //
    10  // The above copyright notice and this permission notice shall be included in
    11  // all copies or substantial portions of the Software.
    12  //
    13  // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    14  // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    15  // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    16  // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    17  // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    18  // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
    19  // THE SOFTWARE.
    20  
    21  package database
    22  
    23  import (
    24  	"encoding/json"
    25  	"errors"
    26  	"testing"
    27  
    28  	"github.com/gogo/protobuf/jsonpb"
    29  	"github.com/golang/mock/gomock"
    30  	"github.com/stretchr/testify/require"
    31  	"go.uber.org/zap"
    32  	"google.golang.org/protobuf/runtime/protoiface"
    33  
    34  	"github.com/m3db/m3/src/cluster/generated/proto/commonpb"
    35  	"github.com/m3db/m3/src/cluster/generated/proto/kvpb"
    36  	"github.com/m3db/m3/src/cluster/kv"
    37  	"github.com/m3db/m3/src/dbnode/kvconfig"
    38  )
    39  
    40  func TestUpdateQueryLimits(t *testing.T) {
    41  	ctrl := gomock.NewController(t)
    42  	defer ctrl.Finish()
    43  
    44  	tests := []struct {
    45  		name          string
    46  		limits        *kvpb.QueryLimits
    47  		commit        bool
    48  		expectedError string
    49  	}{
    50  		{
    51  			name:   `nil`,
    52  			limits: nil,
    53  			commit: true,
    54  		},
    55  		{
    56  			name:   `empty`,
    57  			limits: &kvpb.QueryLimits{},
    58  			commit: true,
    59  		},
    60  		{
    61  			name: `only block - commit`,
    62  			limits: &kvpb.QueryLimits{
    63  				MaxRecentlyQueriedSeriesBlocks: &kvpb.QueryLimit{
    64  					Limit:           1,
    65  					LookbackSeconds: 15,
    66  					ForceExceeded:   true,
    67  				},
    68  			},
    69  			commit: true,
    70  		},
    71  		{
    72  			name: `only metadata - commit`,
    73  			limits: &kvpb.QueryLimits{
    74  				MaxRecentlyQueriedMetadataRead: &kvpb.QueryLimit{
    75  					Limit:           1,
    76  					LookbackSeconds: 15,
    77  					ForceExceeded:   true,
    78  				},
    79  			},
    80  			commit: true,
    81  		},
    82  		{
    83  			name: `only block - no commit`,
    84  			limits: &kvpb.QueryLimits{
    85  				MaxRecentlyQueriedSeriesBlocks: &kvpb.QueryLimit{
    86  					Limit:           1,
    87  					LookbackSeconds: 15,
    88  					ForceExceeded:   true,
    89  				},
    90  			},
    91  			commit: false,
    92  		},
    93  		{
    94  			name: `all - commit`,
    95  			limits: &kvpb.QueryLimits{
    96  				MaxRecentlyQueriedSeriesBlocks: &kvpb.QueryLimit{
    97  					Limit:           1,
    98  					LookbackSeconds: 15,
    99  					ForceExceeded:   true,
   100  				},
   101  				MaxRecentlyQueriedSeriesDiskBytesRead: &kvpb.QueryLimit{
   102  					Limit:           1,
   103  					LookbackSeconds: 15,
   104  					ForceExceeded:   true,
   105  				},
   106  				MaxRecentlyQueriedSeriesDiskRead: &kvpb.QueryLimit{
   107  					Limit:           1,
   108  					LookbackSeconds: 15,
   109  					ForceExceeded:   true,
   110  				},
   111  				MaxRecentlyQueriedMetadataRead: &kvpb.QueryLimit{
   112  					Limit:           1,
   113  					LookbackSeconds: 15,
   114  					ForceExceeded:   true,
   115  				},
   116  			},
   117  			commit: true,
   118  		},
   119  		{
   120  			name: `all - no commit`,
   121  			limits: &kvpb.QueryLimits{
   122  				MaxRecentlyQueriedSeriesBlocks: &kvpb.QueryLimit{
   123  					Limit:           1,
   124  					LookbackSeconds: 15,
   125  					ForceExceeded:   true,
   126  				},
   127  				MaxRecentlyQueriedSeriesDiskBytesRead: &kvpb.QueryLimit{
   128  					Limit:           1,
   129  					LookbackSeconds: 15,
   130  					ForceExceeded:   true,
   131  				},
   132  				MaxRecentlyQueriedSeriesDiskRead: &kvpb.QueryLimit{
   133  					Limit:           1,
   134  					LookbackSeconds: 15,
   135  					ForceExceeded:   true,
   136  				},
   137  			},
   138  			commit: false,
   139  		},
   140  	}
   141  
   142  	for _, test := range tests {
   143  		limitJSON, err := json.Marshal(test.limits)
   144  		require.NoError(t, err)
   145  
   146  		update := &KeyValueUpdate{
   147  			Key:    kvconfig.QueryLimits,
   148  			Value:  json.RawMessage(limitJSON),
   149  			Commit: test.commit,
   150  		}
   151  
   152  		storeMock := kv.NewMockStore(ctrl)
   153  
   154  		// (A) test no old value.
   155  		storeMock.EXPECT().Get(kvconfig.QueryLimits).Return(nil, kv.ErrNotFound)
   156  		if test.commit {
   157  			storeMock.EXPECT().Set(kvconfig.QueryLimits, gomock.Any()).Return(0, nil)
   158  		}
   159  
   160  		handler := &KeyValueStoreHandler{}
   161  		r, err := handler.update(zap.NewNop(), storeMock, update)
   162  		require.NoError(t, err)
   163  		require.Equal(t, kvconfig.QueryLimits, r.Key)
   164  		require.Equal(t, json.RawMessage("{}"), r.Old)
   165  		require.Equal(t, json.RawMessage(limitJSON), r.New)
   166  		require.Equal(t, 0, r.Version)
   167  
   168  		// (B) test old value.
   169  		oldLimits := &kvpb.QueryLimits{
   170  			MaxRecentlyQueriedSeriesBlocks: &kvpb.QueryLimit{
   171  				Limit:           10,
   172  				LookbackSeconds: 30,
   173  				ForceExceeded:   false,
   174  			},
   175  			MaxRecentlyQueriedSeriesDiskRead: &kvpb.QueryLimit{
   176  				Limit:           100,
   177  				LookbackSeconds: 300,
   178  				ForceExceeded:   false,
   179  			},
   180  		}
   181  		mockVal := kv.NewMockValue(ctrl)
   182  		storeMock.EXPECT().Get(kvconfig.QueryLimits).Return(mockVal, nil)
   183  		mockVal.EXPECT().Unmarshal(gomock.Any()).DoAndReturn(func(v *kvpb.QueryLimits) error {
   184  			v.MaxRecentlyQueriedSeriesBlocks = oldLimits.MaxRecentlyQueriedSeriesBlocks
   185  			v.MaxRecentlyQueriedSeriesDiskRead = oldLimits.MaxRecentlyQueriedSeriesDiskRead
   186  			return nil
   187  		})
   188  		if test.commit {
   189  			storeMock.EXPECT().Set(kvconfig.QueryLimits, gomock.Any()).Return(0, nil)
   190  		}
   191  
   192  		handler = &KeyValueStoreHandler{}
   193  		r, err = handler.update(zap.NewNop(), storeMock, update)
   194  		require.NoError(t, err)
   195  
   196  		var oldResult kvpb.QueryLimits
   197  		err = jsonpb.UnmarshalString(string(r.Old), &oldResult)
   198  		require.NoError(t, err)
   199  
   200  		require.Equal(t, kvconfig.QueryLimits, r.Key)
   201  		require.Equal(t, *oldLimits.MaxRecentlyQueriedSeriesBlocks, *oldResult.MaxRecentlyQueriedSeriesBlocks)
   202  		require.Nil(t, oldResult.MaxRecentlyQueriedSeriesDiskBytesRead)
   203  		require.Equal(t, *oldLimits.MaxRecentlyQueriedSeriesDiskRead, *oldResult.MaxRecentlyQueriedSeriesDiskRead)
   204  		require.Equal(t, json.RawMessage(limitJSON), r.New)
   205  		require.Equal(t, 0, r.Version)
   206  	}
   207  }
   208  
   209  func TestProtoParser(t *testing.T) {
   210  	handler := &KeyValueStoreHandler{
   211  		kvStoreProtoParser: func(k string) (protoiface.MessageV1, error) {
   212  			if k == "test-key" {
   213  				return &commonpb.Int64Proto{}, nil
   214  			}
   215  			return nil, errors.New("invalid")
   216  		},
   217  	}
   218  
   219  	s, err := handler.newKVProtoMessage("not-present")
   220  	require.Error(t, err)
   221  	require.Nil(t, s)
   222  
   223  	s, err = handler.newKVProtoMessage("test-key")
   224  	require.NoError(t, err)
   225  	require.NotNil(t, s)
   226  
   227  	s, err = handler.newKVProtoMessage(kvconfig.NamespacesKey)
   228  	require.NoError(t, err)
   229  	require.NotNil(t, s)
   230  }