github.com/zorawar87/trillian@v1.2.1/quota/etcd/quotaapi/conversions_test.go (about) 1 // Copyright 2017 Google Inc. All Rights Reserved. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package quotaapi 16 17 import ( 18 "testing" 19 20 "github.com/golang/protobuf/proto" 21 "github.com/google/trillian/quota/etcd/quotapb" 22 "github.com/google/trillian/quota/etcd/storagepb" 23 "github.com/kylelemons/godebug/pretty" 24 "google.golang.org/genproto/protobuf/field_mask" 25 ) 26 27 var ( 28 apiSequencingConfig = "apb.Config{ 29 Name: "quotas/global/write/config", 30 State: quotapb.Config_ENABLED, 31 MaxTokens: 100, 32 ReplenishmentStrategy: "apb.Config_SequencingBased{ 33 SequencingBased: "apb.SequencingBasedStrategy{}, 34 }, 35 } 36 apiTimeConfig = "apb.Config{ 37 Name: "quotas/users/llama/write/config", 38 State: quotapb.Config_DISABLED, 39 MaxTokens: 200, 40 ReplenishmentStrategy: "apb.Config_TimeBased{ 41 TimeBased: "apb.TimeBasedStrategy{ 42 TokensToReplenish: 10, 43 ReplenishIntervalSeconds: 30, 44 }, 45 }, 46 } 47 storageSequencingConfig = &storagepb.Config{ 48 Name: apiSequencingConfig.Name, 49 State: storagepb.Config_ENABLED, 50 MaxTokens: apiSequencingConfig.MaxTokens, 51 ReplenishmentStrategy: &storagepb.Config_SequencingBased{ 52 SequencingBased: &storagepb.SequencingBasedStrategy{}, 53 }, 54 } 55 storageTimeConfig = &storagepb.Config{ 56 Name: apiTimeConfig.Name, 57 State: storagepb.Config_DISABLED, 58 MaxTokens: apiTimeConfig.MaxTokens, 59 ReplenishmentStrategy: &storagepb.Config_TimeBased{ 60 TimeBased: &storagepb.TimeBasedStrategy{ 61 TokensToReplenish: apiTimeConfig.GetTimeBased().TokensToReplenish, 62 ReplenishIntervalSeconds: apiTimeConfig.GetTimeBased().ReplenishIntervalSeconds, 63 }, 64 }, 65 } 66 ) 67 68 func TestValidateMask(t *testing.T) { 69 tests := []struct { 70 desc string 71 mask *field_mask.FieldMask 72 wantErr bool 73 }{ 74 { 75 desc: "commonFields", 76 mask: commonMask, 77 }, 78 { 79 desc: "sequencingBased", 80 mask: sequencingBasedMask, 81 }, 82 { 83 desc: "timeBased", 84 mask: timeBasedMask, 85 }, 86 { 87 desc: "sequencingAndTime", 88 mask: &field_mask.FieldMask{Paths: []string{sequencingBasedPath, timeBasedPath}}, 89 wantErr: true, 90 }, 91 { 92 desc: "timeAndSequencing", 93 mask: &field_mask.FieldMask{Paths: []string{timeBasedPath, sequencingBasedPath}}, 94 wantErr: true, 95 }, 96 { 97 desc: "unknownPaths", 98 mask: &field_mask.FieldMask{Paths: []string{statePath, "NOT_A_FIELD", maxTokensPath}}, 99 wantErr: true, 100 }, 101 { 102 desc: "namePath", // readonly 103 mask: &field_mask.FieldMask{Paths: []string{"name"}}, 104 wantErr: true, 105 }, 106 } 107 for _, test := range tests { 108 err := validateMask(test.mask) 109 if gotErr := err != nil; gotErr != test.wantErr { 110 t.Errorf("%v: validateMask() returned err = %v, wantErr = %v", test.desc, err, test.wantErr) 111 } 112 } 113 } 114 115 func TestApplyMask(t *testing.T) { 116 // destSequencingConfig must match apiSequencingConfig after the test 117 // name is manually copied, as it's a readonly field. 118 destSequencingConfig := *storageTimeConfig 119 destSequencingConfig.Name = apiSequencingConfig.Name 120 121 // destTimeConfig must match apiTimeConfig after the test 122 destTimeConfig := *storageSequencingConfig 123 destTimeConfig.Name = apiTimeConfig.Name 124 125 destClearSequencing := *storageSequencingConfig 126 wantClearSequencing := destClearSequencing 127 wantClearSequencing.ReplenishmentStrategy = nil 128 129 destClearTime := *storageTimeConfig 130 wantClearTime := destClearTime 131 wantClearTime.ReplenishmentStrategy = nil 132 133 tests := []struct { 134 desc string 135 src *quotapb.Config 136 dest, want *storagepb.Config 137 mask *field_mask.FieldMask 138 }{ 139 { 140 desc: "applyToBlank", 141 src: apiTimeConfig, 142 dest: &storagepb.Config{}, 143 mask: &field_mask.FieldMask{Paths: []string{statePath, maxTokensPath}}, 144 want: &storagepb.Config{ 145 State: storagepb.Config_DISABLED, 146 MaxTokens: apiTimeConfig.MaxTokens, 147 }, 148 }, 149 { 150 desc: "sequencingBasedOverwrite", 151 src: apiSequencingConfig, 152 dest: &destSequencingConfig, 153 mask: sequencingBasedMask, 154 want: storageSequencingConfig, 155 }, 156 { 157 desc: "timeBasedOverwrite", 158 src: apiTimeConfig, 159 dest: &destTimeConfig, 160 mask: timeBasedMask, 161 want: storageTimeConfig, 162 }, 163 { 164 desc: "clearSequencingIfNil", 165 src: "apb.Config{}, 166 dest: &destClearSequencing, 167 mask: &field_mask.FieldMask{Paths: []string{sequencingBasedPath}}, 168 want: &wantClearSequencing, 169 }, 170 { 171 desc: "clearTimeIfNil", 172 src: "apb.Config{}, 173 dest: &destClearTime, 174 mask: &field_mask.FieldMask{Paths: []string{timeBasedPath}}, 175 want: &wantClearTime, 176 }, 177 } 178 for _, test := range tests { 179 applyMask(test.src, test.dest, test.mask) 180 if !proto.Equal(test.dest, test.want) { 181 t.Errorf("%v: post-applyMask() diff (-got +want):\n%v", test.desc, pretty.Compare(test.dest, test.want)) 182 } 183 } 184 } 185 186 func TestConvert_APIAndStorage(t *testing.T) { 187 tests := []struct { 188 desc string 189 api *quotapb.Config 190 storage *storagepb.Config 191 }{ 192 { 193 desc: "sequencingBased", 194 api: apiSequencingConfig, 195 storage: storageSequencingConfig, 196 }, 197 { 198 desc: "timeBased", 199 api: apiTimeConfig, 200 storage: storageTimeConfig, 201 }, 202 { 203 desc: "zeroed", 204 api: "apb.Config{}, 205 storage: &storagepb.Config{}, 206 }, 207 } 208 for _, test := range tests { 209 if got, want := convertToAPI(test.storage), test.api; !proto.Equal(got, want) { 210 t.Errorf("%v: post-convertToAPI() diff (-got +want):\n%v", test.desc, pretty.Compare(got, want)) 211 } 212 if got, want := convertToStorage(test.api), test.storage; !proto.Equal(got, want) { 213 t.Errorf("%v: post-convertToStorage() diff (-got +want):\n%v", test.desc, pretty.Compare(got, want)) 214 } 215 } 216 }