OLD | NEW |
1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 package logs | 5 package logs |
6 | 6 |
7 import ( | 7 import ( |
8 "fmt" | 8 "fmt" |
9 "sort" | 9 "sort" |
10 "testing" | 10 "testing" |
11 "time" | 11 "time" |
12 | 12 |
13 "github.com/luci/gae/filter/featureBreaker" | 13 "github.com/luci/gae/filter/featureBreaker" |
14 "github.com/luci/gae/impl/memory" | 14 "github.com/luci/gae/impl/memory" |
15 ds "github.com/luci/gae/service/datastore" | 15 ds "github.com/luci/gae/service/datastore" |
16 "github.com/luci/luci-go/appengine/logdog/coordinator" | 16 "github.com/luci/luci-go/appengine/logdog/coordinator" |
17 ct "github.com/luci/luci-go/appengine/logdog/coordinator/coordinatorTest
" | 17 ct "github.com/luci/luci-go/appengine/logdog/coordinator/coordinatorTest
" |
18 "github.com/luci/luci-go/common/api/logdog_coordinator/logs/v1" | 18 "github.com/luci/luci-go/common/api/logdog_coordinator/logs/v1" |
19 "github.com/luci/luci-go/common/clock/testclock" | 19 "github.com/luci/luci-go/common/clock/testclock" |
| 20 "github.com/luci/luci-go/common/config" |
20 "github.com/luci/luci-go/common/errors" | 21 "github.com/luci/luci-go/common/errors" |
21 "github.com/luci/luci-go/common/logdog/types" | 22 "github.com/luci/luci-go/common/logdog/types" |
22 "github.com/luci/luci-go/common/proto/google" | 23 "github.com/luci/luci-go/common/proto/google" |
23 "github.com/luci/luci-go/common/proto/logdog/logpb" | 24 "github.com/luci/luci-go/common/proto/logdog/logpb" |
24 "github.com/luci/luci-go/server/auth" | 25 "github.com/luci/luci-go/server/auth" |
25 "github.com/luci/luci-go/server/auth/authtest" | 26 "github.com/luci/luci-go/server/auth/authtest" |
26 "golang.org/x/net/context" | 27 "golang.org/x/net/context" |
27 | 28 |
28 "github.com/luci/luci-go/common/logging/gologger" | |
29 | |
30 . "github.com/luci/luci-go/common/testing/assertions" | 29 . "github.com/luci/luci-go/common/testing/assertions" |
31 . "github.com/smartystreets/goconvey/convey" | 30 . "github.com/smartystreets/goconvey/convey" |
32 ) | 31 ) |
33 | 32 |
34 func shouldHaveLogPaths(actual interface{}, expected ...interface{}) string { | 33 func shouldHaveLogPaths(actual interface{}, expected ...interface{}) string { |
35 resp := actual.(*logdog.QueryResponse) | 34 resp := actual.(*logdog.QueryResponse) |
36 var paths []string | 35 var paths []string |
37 if len(resp.Streams) > 0 { | 36 if len(resp.Streams) > 0 { |
38 paths = make([]string, len(resp.Streams)) | 37 paths = make([]string, len(resp.Streams)) |
39 for i, s := range resp.Streams { | 38 for i, s := range resp.Streams { |
(...skipping 20 matching lines...) Expand all Loading... |
60 | 59 |
61 return ShouldResemble(paths, exp) | 60 return ShouldResemble(paths, exp) |
62 } | 61 } |
63 | 62 |
64 func TestQuery(t *testing.T) { | 63 func TestQuery(t *testing.T) { |
65 t.Parallel() | 64 t.Parallel() |
66 | 65 |
67 Convey(`With a testing configuration, a Query request`, t, func() { | 66 Convey(`With a testing configuration, a Query request`, t, func() { |
68 c, tc := testclock.UseTime(context.Background(), testclock.TestT
imeLocal) | 67 c, tc := testclock.UseTime(context.Background(), testclock.TestT
imeLocal) |
69 c = memory.Use(c) | 68 c = memory.Use(c) |
70 c = gologger.StdConfig.Use(c) | |
71 c, fb := featureBreaker.FilterRDS(c, nil) | 69 c, fb := featureBreaker.FilterRDS(c, nil) |
72 | 70 |
73 di := ds.Get(c) | |
74 | |
75 // Add LogStream indexes. | 71 // Add LogStream indexes. |
76 // | 72 // |
77 // These should be kept in sync with the "query endpoint" indexe
s in the | 73 // These should be kept in sync with the "query endpoint" indexe
s in the |
78 // vmuser module's "index.yaml" file. | 74 // vmuser module's "index.yaml" file. |
79 indexDefs := [][]string{ | 75 indexDefs := [][]string{ |
80 {"Prefix", "-Created"}, | 76 {"Prefix", "-Created"}, |
81 {"Name", "-Created"}, | 77 {"Name", "-Created"}, |
82 {"State", "-Created"}, | 78 {"State", "-Created"}, |
83 {"Purged", "-Created"}, | 79 {"Purged", "-Created"}, |
84 {"ProtoVersion", "-Created"}, | 80 {"ProtoVersion", "-Created"}, |
(...skipping 10 matching lines...) Expand all Loading... |
95 cols := make([]ds.IndexColumn, len(id)) | 91 cols := make([]ds.IndexColumn, len(id)) |
96 for j, ic := range id { | 92 for j, ic := range id { |
97 var err error | 93 var err error |
98 cols[j], err = ds.ParseIndexColumn(ic) | 94 cols[j], err = ds.ParseIndexColumn(ic) |
99 if err != nil { | 95 if err != nil { |
100 panic(fmt.Errorf("failed to parse index
%q: %s", ic, err)) | 96 panic(fmt.Errorf("failed to parse index
%q: %s", ic, err)) |
101 } | 97 } |
102 } | 98 } |
103 indexes[i] = &ds.IndexDefinition{Kind: "LogStream", Sort
By: cols} | 99 indexes[i] = &ds.IndexDefinition{Kind: "LogStream", Sort
By: cols} |
104 } | 100 } |
105 » » di.Testable().AddIndexes(indexes...) | 101 » » ds.Get(c).Testable().AddIndexes(indexes...) |
106 » » di.Testable().Consistent(true) | 102 » » ds.Get(c).Testable().Consistent(true) |
107 | 103 |
108 fs := authtest.FakeState{} | 104 fs := authtest.FakeState{} |
109 c = auth.WithState(c, &fs) | 105 c = auth.WithState(c, &fs) |
110 | 106 |
111 svcStub := ct.Services{} | 107 svcStub := ct.Services{} |
112 svcStub.InitConfig() | 108 svcStub.InitConfig() |
113 svcStub.ServiceConfig.Coordinator.AdminAuthGroup = "test-adminis
trators" | 109 svcStub.ServiceConfig.Coordinator.AdminAuthGroup = "test-adminis
trators" |
114 c = coordinator.WithServices(c, &svcStub) | 110 c = coordinator.WithServices(c, &svcStub) |
115 | 111 |
116 var svrBase server | 112 var svrBase server |
117 svr := newService(&svrBase) | 113 svr := newService(&svrBase) |
118 | 114 |
| 115 // di is a datastore bound to the test project namespace. |
| 116 const project = "test-project" |
| 117 if err := coordinator.WithProjectNamespace(&c, config.ProjectNam
e(project)); err != nil { |
| 118 panic(err) |
| 119 } |
| 120 di := ds.Get(c) |
| 121 |
| 122 // Stock query request, will be modified by each test. |
119 req := logdog.QueryRequest{ | 123 req := logdog.QueryRequest{ |
120 » » » Tags: map[string]string{}, | 124 » » » Project: project, |
| 125 » » » Tags: map[string]string{}, |
121 } | 126 } |
122 | 127 |
123 // Install a set of stock log streams to query against. | 128 // Install a set of stock log streams to query against. |
124 var streamPaths []string | 129 var streamPaths []string |
125 var purgedStreamPaths []string | 130 var purgedStreamPaths []string |
126 streams := map[string]*coordinator.LogStream{} | 131 streams := map[string]*coordinator.LogStream{} |
127 descs := map[string]*logpb.LogStreamDescriptor{} | 132 descs := map[string]*logpb.LogStreamDescriptor{} |
128 for i, v := range []types.StreamPath{ | 133 for i, v := range []types.StreamPath{ |
129 "testing/+/foo", | 134 "testing/+/foo", |
130 "testing/+/foo/bar", | 135 "testing/+/foo/bar", |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
180 | 185 |
181 case "datagram": | 186 case "datagram": |
182 ls.StreamType = logpb.StreamType
_DATAGRAM | 187 ls.StreamType = logpb.StreamType
_DATAGRAM |
183 | 188 |
184 case "binary": | 189 case "binary": |
185 ls.StreamType = logpb.StreamType
_BINARY | 190 ls.StreamType = logpb.StreamType
_BINARY |
186 } | 191 } |
187 } | 192 } |
188 } | 193 } |
189 | 194 |
190 » » » if err := ds.Get(c).Put(ls); err != nil { | 195 » » » if err := di.Put(ls); err != nil { |
191 panic(fmt.Errorf("failed to put log stream %d: %
v", i, err)) | 196 panic(fmt.Errorf("failed to put log stream %d: %
v", i, err)) |
192 } | 197 } |
193 | 198 |
194 descs[string(v)] = desc | 199 descs[string(v)] = desc |
195 streams[string(v)] = ls | 200 streams[string(v)] = ls |
196 if !ls.Purged { | 201 if !ls.Purged { |
197 streamPaths = append(streamPaths, string(v)) | 202 streamPaths = append(streamPaths, string(v)) |
198 } | 203 } |
199 purgedStreamPaths = append(purgedStreamPaths, string(v)) | 204 purgedStreamPaths = append(purgedStreamPaths, string(v)) |
200 tc.Add(time.Second) | 205 tc.Add(time.Second) |
(...skipping 10 matching lines...) Expand all Loading... |
211 } | 216 } |
212 invert(streamPaths) | 217 invert(streamPaths) |
213 invert(purgedStreamPaths) | 218 invert(purgedStreamPaths) |
214 | 219 |
215 Convey(`An empty query will return all log streams.`, func() { | 220 Convey(`An empty query will return all log streams.`, func() { |
216 resp, err := svr.Query(c, &req) | 221 resp, err := svr.Query(c, &req) |
217 So(err, ShouldBeRPCOK) | 222 So(err, ShouldBeRPCOK) |
218 So(resp, shouldHaveLogPaths, streamPaths) | 223 So(resp, shouldHaveLogPaths, streamPaths) |
219 }) | 224 }) |
220 | 225 |
| 226 Convey(`An empty query to a different project return no log stre
ams.`, func() { |
| 227 req.Project = "does-not-exist" |
| 228 |
| 229 resp, err := svr.Query(c, &req) |
| 230 So(err, ShouldBeRPCOK) |
| 231 So(resp, shouldHaveLogPaths) |
| 232 }) |
| 233 |
221 Convey(`An empty query will include purged streams if admin.`, f
unc() { | 234 Convey(`An empty query will include purged streams if admin.`, f
unc() { |
222 fs.IdentityGroups = []string{"test-administrators"} | 235 fs.IdentityGroups = []string{"test-administrators"} |
223 | 236 |
224 resp, err := svr.Query(c, &req) | 237 resp, err := svr.Query(c, &req) |
225 So(err, ShouldBeRPCOK) | 238 So(err, ShouldBeRPCOK) |
226 So(resp, shouldHaveLogPaths, purgedStreamPaths) | 239 So(resp, shouldHaveLogPaths, purgedStreamPaths) |
227 }) | 240 }) |
228 | 241 |
229 Convey(`A query with an invalid path will return BadRequest erro
r.`, func() { | 242 Convey(`A query with an invalid path will return BadRequest erro
r.`, func() { |
230 req.Path = "***" | 243 req.Path = "***" |
(...skipping 283 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
514 | 527 |
515 Convey(`When an invalid tag is specified, returns BadReq
uest error`, func() { | 528 Convey(`When an invalid tag is specified, returns BadReq
uest error`, func() { |
516 req.Tags["+++not a valid tag+++"] = "" | 529 req.Tags["+++not a valid tag+++"] = "" |
517 | 530 |
518 _, err := svr.Query(c, &req) | 531 _, err := svr.Query(c, &req) |
519 So(err, ShouldBeRPCInvalidArgument, "invalid tag
constraint") | 532 So(err, ShouldBeRPCInvalidArgument, "invalid tag
constraint") |
520 }) | 533 }) |
521 }) | 534 }) |
522 }) | 535 }) |
523 } | 536 } |
OLD | NEW |