vitess.io/vitess@v0.16.2/go/vt/vttablet/tabletserver/rules/map_test.go (about) 1 /* 2 Copyright 2019 The Vitess Authors. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package rules 18 19 import ( 20 "reflect" 21 "strings" 22 "testing" 23 24 "vitess.io/vitess/go/vt/vttablet/tabletserver/planbuilder" 25 ) 26 27 var ( 28 denyRules *Rules 29 otherRules *Rules 30 ) 31 32 const ( 33 // mimic query rules from denylist 34 denyListQueryRules string = "DENYLIST_QUERY_RULES" 35 // mimic query rules from custom source 36 customQueryRules string = "CUSTOM_QUERY_RULES" 37 ) 38 39 func setupRules() { 40 var qr *Rule 41 42 // mock denied tables 43 denyRules = New() 44 deniedTables := []string{"bannedtable1", "bannedtable2", "bannedtable3"} 45 qr = NewQueryRule("enforce denied tables", "denied_table", QRFailRetry) 46 for _, t := range deniedTables { 47 qr.AddTableCond(t) 48 } 49 denyRules.Add(qr) 50 51 // mock custom rules 52 otherRules = New() 53 qr = NewQueryRule("sample custom rule", "customrule_ban_bindvar", QRFail) 54 qr.AddTableCond("t_customer") 55 qr.AddBindVarCond("bindvar1", true, false, QRNoOp, nil) 56 otherRules.Add(qr) 57 } 58 59 func TestMapRegisterARegisteredSource(t *testing.T) { 60 setupRules() 61 qri := NewMap() 62 qri.RegisterSource(denyListQueryRules) 63 defer func() { 64 err := recover() 65 if err == nil { 66 t.Fatalf("should get an error for registering a registered query rule source ") 67 } 68 }() 69 qri.RegisterSource(denyListQueryRules) 70 } 71 72 func TestMapSetRulesWithNil(t *testing.T) { 73 setupRules() 74 qri := NewMap() 75 76 qri.RegisterSource(denyListQueryRules) 77 err := qri.SetRules(denyListQueryRules, denyRules) 78 if err != nil { 79 t.Errorf("Failed to set denyListQueryRules Rules : %s", err) 80 } 81 qrs, err := qri.Get(denyListQueryRules) 82 if err != nil { 83 t.Errorf("GetRules failed to retrieve denyListQueryRules that has been set: %s", err) 84 } 85 if !reflect.DeepEqual(qrs, denyRules) { 86 t.Errorf("denyListQueryRules retrieved is %v, but the expected value should be %v", qrs, denyListQueryRules) 87 } 88 89 qri.SetRules(denyListQueryRules, nil) 90 91 qrs, err = qri.Get(denyListQueryRules) 92 if err != nil { 93 t.Errorf("GetRules failed to retrieve denyListQueryRules that has been set: %s", err) 94 } 95 if !reflect.DeepEqual(qrs, New()) { 96 t.Errorf("denyListQueryRules retrieved is %v, but the expected value should be %v", qrs, denyListQueryRules) 97 } 98 } 99 100 func TestMapGetSetQueryRules(t *testing.T) { 101 setupRules() 102 qri := NewMap() 103 104 qri.RegisterSource(denyListQueryRules) 105 qri.RegisterSource(customQueryRules) 106 107 // Test if we can get a Rules without a predefined rule set name 108 qrs, err := qri.Get("Foo") 109 if err == nil { 110 t.Errorf("GetRules shouldn't succeed with 'Foo' as the rule set name") 111 } 112 if qrs == nil { 113 t.Errorf("GetRules should always return empty Rules and never nil") 114 } 115 if !reflect.DeepEqual(qrs, New()) { 116 t.Errorf("Map contains only empty Rules at the beginning") 117 } 118 119 // Test if we can set a Rules without a predefined rule set name 120 err = qri.SetRules("Foo", New()) 121 if err == nil { 122 t.Errorf("SetRules shouldn't succeed with 'Foo' as the rule set name") 123 } 124 125 // Test if we can successfully set Rules previously mocked into Map 126 err = qri.SetRules(denyListQueryRules, denyRules) 127 if err != nil { 128 t.Errorf("Failed to set denylist Rules : %s", err) 129 } 130 err = qri.SetRules(denyListQueryRules, denyRules) 131 if err != nil { 132 t.Errorf("Failed to set denylist Rules: %s", err) 133 } 134 err = qri.SetRules(customQueryRules, otherRules) 135 if err != nil { 136 t.Errorf("Failed to set custom Rules: %s", err) 137 } 138 139 // Test if we can successfully retrieve rules that've been set 140 qrs, err = qri.Get(denyListQueryRules) 141 if err != nil { 142 t.Errorf("GetRules failed to retrieve denyListQueryRules that has been set: %s", err) 143 } 144 if !reflect.DeepEqual(qrs, denyRules) { 145 t.Errorf("denyListQueryRules retrieved is %v, but the expected value should be %v", qrs, denyRules) 146 } 147 148 qrs, err = qri.Get(denyListQueryRules) 149 if err != nil { 150 t.Errorf("GetRules failed to retrieve denyListQueryRules that has been set: %s", err) 151 } 152 if !reflect.DeepEqual(qrs, denyRules) { 153 t.Errorf("denyListQueryRules retrieved is %v, but the expected value should be %v", qrs, denyRules) 154 } 155 156 qrs, err = qri.Get(customQueryRules) 157 if err != nil { 158 t.Errorf("GetRules failed to retrieve customQueryRules that has been set: %s", err) 159 } 160 if !reflect.DeepEqual(qrs, otherRules) { 161 t.Errorf("customQueryRules retrieved is %v, but the expected value should be %v", qrs, customQueryRules) 162 } 163 } 164 165 func TestMapFilterByPlan(t *testing.T) { 166 var qrs *Rules 167 setupRules() 168 qri := NewMap() 169 170 qri.RegisterSource(denyListQueryRules) 171 qri.RegisterSource(customQueryRules) 172 173 qri.SetRules(denyListQueryRules, denyRules) 174 qri.SetRules(customQueryRules, otherRules) 175 176 // Test filter by denylist rule 177 qrs = qri.FilterByPlan("select * from bannedtable2", planbuilder.PlanSelect, "bannedtable2") 178 if l := len(qrs.rules); l != 1 { 179 t.Errorf("Select from bannedtable matches %d rules, but we expect %d", l, 1) 180 } 181 if !strings.HasPrefix(qrs.rules[0].Name, "denied_table") { 182 t.Errorf("Select from bannedtable query matches rule '%s', but we expect rule with prefix '%s'", qrs.rules[0].Name, "denied_table") 183 } 184 185 // Test filter by custom rule 186 qrs = qri.FilterByPlan("select cid from t_customer limit 10", planbuilder.PlanSelect, "t_customer") 187 if l := len(qrs.rules); l != 1 { 188 t.Errorf("Select from t_customer matches %d rules, but we expect %d", l, 1) 189 } 190 if !strings.HasPrefix(qrs.rules[0].Name, "customrule_ban_bindvar") { 191 t.Errorf("Select from t_customer matches rule '%s', but we expect rule with prefix '%s'", qrs.rules[0].Name, "customrule_ban_bindvar") 192 } 193 194 // Test match two rules: both denylist rule and custom rule will be matched 195 otherRules = New() 196 qr := NewQueryRule("sample custom rule", "customrule_ban_bindvar", QRFail) 197 qr.AddBindVarCond("bindvar1", true, false, QRNoOp, nil) 198 otherRules.Add(qr) 199 qri.SetRules(customQueryRules, otherRules) 200 qrs = qri.FilterByPlan("select * from bannedtable2", planbuilder.PlanSelect, "bannedtable2") 201 if l := len(qrs.rules); l != 2 { 202 t.Errorf("Insert into bannedtable2 matches %d rules: %v, but we expect %d rules to be matched", l, qrs.rules, 2) 203 } 204 } 205 206 func TestMapJSON(t *testing.T) { 207 setupRules() 208 qri := NewMap() 209 qri.RegisterSource(denyListQueryRules) 210 _ = qri.SetRules(denyListQueryRules, denyRules) 211 qri.RegisterSource(customQueryRules) 212 _ = qri.SetRules(customQueryRules, otherRules) 213 got := marshalled(qri) 214 want := compacted(`{ 215 "CUSTOM_QUERY_RULES":[{ 216 "Description":"sample custom rule", 217 "Name":"customrule_ban_bindvar", 218 "TableNames":["t_customer"], 219 "BindVarConds":[{"Name":"bindvar1","OnAbsent":true,"Operator":""}], 220 "Action":"FAIL" 221 }], 222 "DENYLIST_QUERY_RULES":[{ 223 "Description":"enforce denied tables", 224 "Name":"denied_table", 225 "TableNames":["bannedtable1","bannedtable2","bannedtable3"], 226 "Action":"FAIL_RETRY" 227 }] 228 }`) 229 if got != want { 230 t.Errorf("MapJSON:\n%v, want\n%v", got, want) 231 } 232 }