Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(82)

Side by Side Diff: logdog/appengine/coordinator/hierarchy/hierarchy_test.go

Issue 2991253004: [logdog] Remove list functionality. (Closed)
Patch Set: fix test Created 3 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2015 The LUCI Authors.
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 hierarchy
16
17 import (
18 "fmt"
19 "testing"
20
21 ds "github.com/luci/gae/service/datastore"
22 "github.com/luci/gae/service/info"
23 "github.com/luci/luci-go/logdog/appengine/coordinator"
24 ct "github.com/luci/luci-go/logdog/appengine/coordinator/coordinatorTest "
25 "github.com/luci/luci-go/logdog/common/types"
26 "github.com/luci/luci-go/luci_config/common/cfgtypes"
27
28 . "github.com/luci/luci-go/common/testing/assertions"
29 . "github.com/smartystreets/goconvey/convey"
30 )
31
32 func TestHierarchy(t *testing.T) {
33 t.Parallel()
34
35 FocusConvey(`With a testing configuration`, t, func() {
36 c, env := ct.Install()
37
38 var r Request
39 get := func() *List {
40 l, err := Get(c, r)
41 if err != nil {
42 panic(err)
43 }
44 return l
45 }
46
47 var lv listValidator
48
49 FocusConvey(`When requesting Project-level list`, func() {
50 r.Project = ""
51
52 FocusConvey(`An anonymous user will see all public-acces s projects.`, func() {
53 So(get(), lv.shouldHaveComponents, "proj-bar", " proj-foo")
54 })
55
56 Convey(`An authenticated user will see all projects.`, f unc() {
57 env.LogIn()
58 env.JoinGroup("auth")
59
60 allProjects := []interface{}{"proj-bar", "proj-e xclusive", "proj-foo"}
61
62 Convey(`Will see all projects.`, func() {
63 So(get(), lv.shouldHaveComponents, allPr ojects...)
64 })
65
66 Convey(`Cursor and limit work.`, func() {
67 r.Limit = 1
68
69 var l *List
70 for len(allProjects) > 0 {
71 l = get()
72 So(l, lv.shouldHaveComponents, a llProjects[0])
73 So(l.Next, ShouldNotEqual, "")
74 allProjects = allProjects[1:]
75
76 r.Next = l.Next
77 }
78
79 So(len(allProjects), ShouldEqual, 0)
80
81 // End of iteration.
82 l = get()
83 So(l, lv.shouldHaveComponents)
84 So(l.Next, ShouldEqual, "")
85 })
86
87 Convey(`Offset and limit work.`, func() {
88 r.Limit = 1
89
90 for i, proj := range allProjects {
91 r.Skip = i
92
93 l := get()
94 So(l, lv.shouldHaveComponents, p roj)
95 So(l.Next, ShouldNotEqual, "")
96 }
97
98 // End of iteration.
99 r.Skip = len(allProjects)
100 l := get()
101 So(l, lv.shouldHaveComponents)
102 So(l.Next, ShouldEqual, "")
103 })
104 })
105 })
106
107 Convey(`If the user is logged in`, func() {
108 env.LogIn()
109
110 Convey(`When accessing a restricted project`, func() {
111 r.Project = "proj-exclusive"
112
113 Convey(`Will succeed if the user can access the project.`, func() {
114 env.JoinGroup("auth")
115
116 _, err := Get(c, r)
117 So(err, ShouldBeRPCOK)
118 })
119
120 Convey(`Will fail with PermissionDenied if the u ser can't access the project.`, func() {
121 _, err := Get(c, r)
122 So(err, ShouldBeRPCPermissionDenied)
123 })
124 })
125
126 Convey(`Will fail with PermissionDenied if the project d oes not exist.`, func() {
127 r.Project = "does-not-exist"
128
129 _, err := Get(c, r)
130 So(err, ShouldBeRPCPermissionDenied)
131 })
132 })
133
134 Convey(`Get within a project that the user cannot access will re turn Unauthenticated.`, func() {
135 r.Project = "proj-exclusive"
136
137 _, err := Get(c, r)
138 So(err, ShouldBeRPCUnauthenticated)
139 })
140
141 Convey(`Get within a project that does not exist will return Una uthenticated.`, func() {
142 r.Project = "proj-does-not-exist"
143
144 _, err := Get(c, r)
145 So(err, ShouldBeRPCUnauthenticated)
146 })
147
148 Convey(`Get will return nothing when no components are registere d.`, func() {
149 r.Project = "proj-foo"
150 lv.project = "proj-foo"
151
152 So(get(), lv.shouldHaveComponents)
153
154 r.PathBase = "foo"
155 lv.pathBase = "foo"
156 So(get(), lv.shouldHaveComponents)
157
158 r.PathBase = "foo/+/bar"
159 lv.pathBase = "foo/+/bar"
160 So(get(), lv.shouldHaveComponents)
161 })
162
163 Convey(`Can register a hierarchy of name components in multiple namespaces.`, func() {
164 for _, proj := range []cfgtypes.ProjectName{
165 "proj-foo", "proj-bar", "proj-exclusive",
166 } {
167 // Bypass access check.
168 ic := info.MustNamespace(c, coordinator.ProjectN amespace(proj))
169
170 for _, p := range []types.StreamPath{
171 "foo/+/baz",
172 "foo/+/qux",
173 "foo/+/qux",
174 "foo/+/qux/2468",
175 "foo/+/qux/0002468",
176 "foo/+/14",
177 "foo/+/001337",
178 "foo/+/bar",
179 "foo/+/bar/baz",
180 "foo/bar/+/baz",
181 "bar/+/baz",
182 "bar/+/baz/qux",
183 } {
184 comps, err := Missing(ic, Components(p, true))
185 if err != nil {
186 panic(err)
187 }
188
189 for _, c := range comps {
190 if err := c.Put(ic); err != nil {
191 panic(err)
192 }
193 }
194 }
195 }
196 ds.GetTestable(c).CatchupIndexes()
197
198 Convey(`Can list the hierarchy immediate paths (discrete ).`, func() {
199 r.Project = "proj-foo"
200 lv.project = cfgtypes.ProjectName(r.Project)
201
202 list := func(b string) *List {
203 r.Project = "proj-foo"
204 r.PathBase = b
205
206 // Set up our validator for these query results.
207 lv.pathBase = types.StreamPath(r.PathBas e)
208 return get()
209 }
210
211 So(list(""), lv.shouldHaveComponents, "bar", "fo o")
212 So(list("foo"), lv.shouldHaveComponents, "+", "b ar")
213 So(list("foo/+"), lv.shouldHaveComponents, "14$" , "001337$", "bar$", "baz$", "qux$", "bar", "qux")
214 So(list("foo/+/bar"), lv.shouldHaveComponents, " baz$")
215 So(list("foo/bar"), lv.shouldHaveComponents, "+" )
216 So(list("foo/bar/+"), lv.shouldHaveComponents, " baz$")
217 So(list("bar"), lv.shouldHaveComponents, "+")
218 So(list("bar/+"), lv.shouldHaveComponents, "baz$ ", "baz")
219 So(list("baz"), lv.shouldHaveComponents)
220 })
221
222 Convey(`Performing discrete queries`, func() {
223 r.Project = "proj-foo"
224 lv.project = cfgtypes.ProjectName(r.Project)
225
226 Convey(`When listing "proj-foo/foo/+"`, func() {
227 r.PathBase = "foo/+"
228 lv.pathBase = types.StreamPath(r.PathBas e)
229
230 Convey(`Can list the first 2 elements.`, func() {
231 r.Limit = 2
232 So(get(), lv.shouldHaveComponent s, "14$", "001337$")
233 })
234
235 Convey(`Can list 3 elements, skipping th e first four.`, func() {
236 r.Limit = 2
237 r.Skip = 4
238 So(get(), lv.shouldHaveComponent s, "qux$", "bar")
239 })
240 })
241
242 Convey(`Can list the immediate hierarchy iterati vely.`, func() {
243 r.PathBase = "foo/+"
244 lv.pathBase = types.StreamPath(r.PathBas e)
245
246 var all []interface{}
247 for _, s := range norm(get().Comp) {
248 all = append(all, s)
249 }
250
251 r.Limit = 2
252 for len(all) > 0 {
253 l := get()
254
255 count := r.Limit
256 if count > len(all) {
257 count = len(all)
258 }
259
260 So(l, lv.shouldHaveComponents, a ll[:count]...)
261 all = all[count:]
262
263 if len(all) > 0 {
264 So(l.Next, ShouldNotEqua l, "")
265 }
266 r.Next = l.Next
267 }
268 })
269 })
270 })
271 })
272 }
273
274 type listValidator struct {
275 project cfgtypes.ProjectName
276 pathBase types.StreamPath
277 }
278
279 func (lv *listValidator) shouldHaveComponents(actual interface{}, expected ...in terface{}) string {
280 a, ok := actual.(*List)
281 if !ok {
282 return fmt.Sprintf("Actual value must be a *List, not %T", actua l)
283 }
284
285 // The project and path base components should match.
286 if a.Project != lv.project {
287 return fmt.Sprintf("Actual project %q doesn't match expected %q. ", a.Project, lv.project)
288 }
289 if a.PathBase != lv.pathBase {
290 return fmt.Sprintf("Actual path base %q doesn't match expected % q.", a.PathBase, lv.pathBase)
291 }
292
293 for i, c := range a.Comp {
294 expPath := types.StreamPath(types.Construct(string(lv.pathBase), c.Name))
295 if p := a.Path(c); p != expPath {
296 return fmt.Sprintf("Component %d doesn't have expected p ath (%q != %q)", i, p, expPath)
297 }
298 }
299
300 // Check normalized component values.
301 comps := make([]string, len(expected))
302 for i, exp := range expected {
303 comps[i], ok = exp.(string)
304 if !ok {
305 return fmt.Sprintf("Expected values must be strings, %d is %T.", i, exp)
306 }
307 }
308 if err := ShouldResemble(norm(a.Comp), comps); err != "" {
309 return err
310 }
311 return ""
312 }
313
314 func norm(c []*ListComponent) []string {
315 result := make([]string, len(c))
316 for i, e := range c {
317 result[i] = e.Name
318 if e.Stream {
319 result[i] += "$"
320 }
321 }
322 return result
323 }
OLDNEW
« no previous file with comments | « logdog/appengine/coordinator/hierarchy/hierarchy.go ('k') | logdog/appengine/coordinator/hierarchy/project.go » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698