1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 package approval
16
17 import (
18 "reflect"
19 "testing"
20
21 "github.com/stretchr/testify/require"
22 "gopkg.in/yaml.v2"
23
24 "edge-infra.dev/pkg/f8n/devinfra/repo/owners/policybot/policy/common"
25 )
26
27 func TestParsePolicy(t *testing.T) {
28 policyText := `
29 - rule1
30 - rule2
31 - or:
32 - and:
33 - rule3
34 - rule4
35 - rule5
36 - and:
37 - rule6
38 - rule7
39 `
40
41 ruleText := `
42 - name: rule1
43 options:
44 allow_author: true
45 - name: rule2
46 options:
47 allow_author: true
48 allow_contributor: true
49 - name: rule3
50 options:
51 allow_author: true
52 allow_contributor: true
53 # invalidate_on_push: true
54 - name: rule4
55 options:
56 allow_author: true
57 # invalidate_on_push: true
58 - name: rule5
59 options:
60 allow_contributor: true
61 # invalidate_on_push: true
62 - name: rule6
63 options:
64 allow_contributor: true
65 - name: rule7
66 options:
67 request_review:
68 enabled: true
69 requires:
70 admins: true
71 `
72
73 var policy Policy
74 err := yaml.UnmarshalStrict([]byte(policyText), &policy)
75 require.NoError(t, err, "failed to unmarshal policy")
76
77 var rules []*Rule
78 err = yaml.UnmarshalStrict([]byte(ruleText), &rules)
79 require.NoError(t, err, "failed to unmarshal rules")
80
81 rulesByName := make(map[string]*Rule)
82 for _, r := range rules {
83 rulesByName[r.Name] = r
84 }
85
86 req, err := policy.Parse(rulesByName)
87 require.NoError(t, err, "failed to parse policy")
88
89 expected := &evaluator{
90 root: &AndRequirement{
91 requirements: []common.Evaluator{
92 &RuleRequirement{
93 rule: rules[0],
94 },
95 &RuleRequirement{
96 rule: rules[1],
97 },
98 &OrRequirement{
99 requirements: []common.Evaluator{
100 &AndRequirement{
101 requirements: []common.Evaluator{
102 &RuleRequirement{
103 rule: rules[2],
104 },
105 &RuleRequirement{
106 rule: rules[3],
107 },
108 },
109 },
110 &RuleRequirement{
111 rule: rules[4],
112 },
113 },
114 },
115 &AndRequirement{
116 requirements: []common.Evaluator{
117 &RuleRequirement{
118 rule: rules[5],
119 },
120 &RuleRequirement{
121 rule: rules[6],
122 },
123 },
124 },
125 },
126 },
127 }
128
129 require.True(t, reflect.DeepEqual(expected, req))
130 }
131
132 func TestParsePolicyError_empty(t *testing.T) {
133
134 policy := `
135 - rule1
136 - or: []
137 `
138
139 rules := `
140 - name: rule1
141 `
142
143 _, err := loadAndParsePolicy(t, policy, rules)
144 require.Error(t, err)
145 }
146
147 func TestParsePolicyError_unknownRule(t *testing.T) {
148
149 policy := `
150 - rule1
151 `
152
153 rules := `
154 - name: rule2
155 `
156
157 _, err := loadAndParsePolicy(t, policy, rules)
158 require.Error(t, err)
159 }
160
161 func TestParsePolicyError_illegalType(t *testing.T) {
162
163 policy := `
164 - or:
165 - rule1
166 - [a, b]
167 `
168
169 rules := `
170 - name: rule1
171 `
172
173 _, err := loadAndParsePolicy(t, policy, rules)
174 require.Error(t, err)
175 }
176
177 func TestParsePolicyError_multikey(t *testing.T) {
178
179 policy := `
180 - or:
181 - rule1
182 and:
183 - rule1
184 `
185
186 rules := `
187 - name: rule1
188 `
189
190 _, err := loadAndParsePolicy(t, policy, rules)
191 require.Error(t, err)
192 }
193
194 func TestParsePolicyError_recursiveDepth(t *testing.T) {
195
196 policy := `
197 - or:
198 - or:
199 - or:
200 - or:
201 - or:
202 - or:
203 - or:
204 - or:
205 - or:
206 - rule1
207 `
208
209 rules := `
210 - name: rule1
211 `
212
213 _, err := loadAndParsePolicy(t, policy, rules)
214 require.NoError(t, err)
215
216
217 policy = `
218 - or:
219 - or:
220 - or:
221 - or:
222 - or:
223 - or:
224 - or:
225 - or:
226 - or:
227 - or:
228 - rule1
229 `
230
231 _, err = loadAndParsePolicy(t, policy, rules)
232 require.Error(t, err)
233 }
234
235 func loadAndParsePolicy(t *testing.T, policyText string, ruleText string) (common.Evaluator, error) {
236 var policy Policy
237 err := yaml.UnmarshalStrict([]byte(policyText), &policy)
238 require.NoError(t, err, "failed to unmarshal policy")
239
240 var rules []*Rule
241 err = yaml.UnmarshalStrict([]byte(ruleText), &rules)
242 require.NoError(t, err, "failed to unmarshal rules")
243
244 rulesByName := make(map[string]*Rule)
245 for _, r := range rules {
246 rulesByName[r.Name] = r
247 }
248
249 return policy.Parse(rulesByName)
250 }
251
View as plain text