github.com/m3db/m3@v1.5.0/src/dbnode/network/server/tchannelthrift/cluster/service_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 cluster 22 23 import ( 24 "fmt" 25 "testing" 26 "time" 27 28 "github.com/golang/mock/gomock" 29 "github.com/stretchr/testify/require" 30 "github.com/uber/tchannel-go/thrift" 31 32 "github.com/m3db/m3/src/dbnode/client" 33 "github.com/m3db/m3/src/dbnode/encoding" 34 "github.com/m3db/m3/src/dbnode/generated/thrift/rpc" 35 "github.com/m3db/m3/src/dbnode/storage/index" 36 "github.com/m3db/m3/src/dbnode/topology" 37 xtest "github.com/m3db/m3/src/x/test" 38 ) 39 40 func TestSessionOpts(t *testing.T) { 41 clientOpts := client.NewOptions(). 42 SetIterationOptions(index.IterationOptions{ 43 IterateEqualTimestampStrategy: encoding.IterateLowestValue, 44 }). 45 SetReadConsistencyLevel(topology.ReadConsistencyLevelMajority) 46 rcAll := rpc.ReadConsistency_ALL 47 csHighest := rpc.EqualTimestampStrategy_HIGHEST_VALUE 48 cases := []struct { 49 name string 50 reqOpts *rpc.ClusterQueryOptions 51 sessOpts sessionOpts 52 }{ 53 { 54 name: "nil opts", 55 sessOpts: sessionOpts{ 56 readConsistency: topology.ReadConsistencyLevelMajority, 57 equalTimestampStrategy: encoding.IterateLowestValue, 58 }, 59 }, 60 { 61 name: "not set", 62 reqOpts: &rpc.ClusterQueryOptions{}, 63 sessOpts: sessionOpts{ 64 readConsistency: topology.ReadConsistencyLevelMajority, 65 equalTimestampStrategy: encoding.IterateLowestValue, 66 }, 67 }, 68 { 69 name: "only read consistency", 70 reqOpts: &rpc.ClusterQueryOptions{ 71 ReadConsistency: &rcAll, 72 }, 73 sessOpts: sessionOpts{ 74 readConsistency: topology.ReadConsistencyLevelAll, 75 equalTimestampStrategy: encoding.IterateLowestValue, 76 consistencyOverride: true, 77 }, 78 }, 79 { 80 name: "only conflict strategy", 81 reqOpts: &rpc.ClusterQueryOptions{ 82 ConflictResolutionStrategy: &csHighest, 83 }, 84 sessOpts: sessionOpts{ 85 readConsistency: topology.ReadConsistencyLevelMajority, 86 equalTimestampStrategy: encoding.IterateHighestValue, 87 }, 88 }, 89 { 90 name: "both set", 91 reqOpts: &rpc.ClusterQueryOptions{ 92 ReadConsistency: &rcAll, 93 ConflictResolutionStrategy: &csHighest, 94 }, 95 sessOpts: sessionOpts{ 96 readConsistency: topology.ReadConsistencyLevelAll, 97 equalTimestampStrategy: encoding.IterateHighestValue, 98 consistencyOverride: true, 99 }, 100 }, 101 } 102 103 for _, tc := range cases { 104 tc := tc 105 t.Run(tc.name, func(t *testing.T) { 106 ctrl := xtest.NewController(t) 107 defer ctrl.Finish() 108 109 c := client.NewMockClient(ctrl) 110 c.EXPECT().Options().Return(clientOpts).AnyTimes() 111 sess := client.NewMockSession(ctrl) 112 iters := encoding.NewMockSeriesIterators(ctrl) 113 sess.EXPECT().FetchTagged(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return( 114 iters, client.FetchResponseMetadata{}, nil) 115 iters.EXPECT().Len().Return(0) 116 iters.EXPECT().Iters().Return(nil) 117 iters.EXPECT().Close() 118 119 ctx, cancel := thrift.NewContext(time.Second) 120 defer cancel() 121 req := &rpc.QueryRequest{ 122 ClusterOptions: tc.reqOpts, 123 } 124 c.EXPECT().NewSessionWithOptions(tc.sessOpts).Return(sess, nil) 125 s := NewService(c).(*service) 126 res, err := s.Query(ctx, req) 127 require.NoError(t, err) 128 require.NotNil(t, res) 129 }) 130 } 131 } 132 133 func (s sessionOpts) Matches(x interface{}) bool { 134 if c, ok := x.(client.Options); ok { 135 if s.equalTimestampStrategy != c.IterationOptions().IterateEqualTimestampStrategy { 136 return false 137 } 138 if s.readConsistency != c.ReadConsistencyLevel() { 139 return false 140 } 141 if s.consistencyOverride && c.RuntimeOptionsManager() != nil { 142 return false 143 } 144 return true 145 } 146 return false 147 } 148 149 func (s sessionOpts) String() string { 150 return fmt.Sprintf("%v %v", s.readConsistency, s.equalTimestampStrategy) 151 } 152 153 var _ gomock.Matcher = &sessionOpts{}