| 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 registration | 5 package registration |
| 6 | 6 |
| 7 import ( | 7 import ( |
| 8 "errors" | 8 "errors" |
| 9 "testing" | 9 "testing" |
| 10 "time" |
| 10 | 11 |
| 11 "github.com/luci/gae/filter/featureBreaker" | 12 "github.com/luci/gae/filter/featureBreaker" |
| 12 ds "github.com/luci/gae/service/datastore" | 13 ds "github.com/luci/gae/service/datastore" |
| 14 "github.com/luci/luci-go/appengine/logdog/coordinator" |
| 13 ct "github.com/luci/luci-go/appengine/logdog/coordinator/coordinatorTest
" | 15 ct "github.com/luci/luci-go/appengine/logdog/coordinator/coordinatorTest
" |
| 14 "github.com/luci/luci-go/appengine/logdog/coordinator/hierarchy" | 16 "github.com/luci/luci-go/appengine/logdog/coordinator/hierarchy" |
| 15 "github.com/luci/luci-go/common/api/logdog_coordinator/registration/v1" | 17 "github.com/luci/luci-go/common/api/logdog_coordinator/registration/v1" |
| 18 "github.com/luci/luci-go/common/clock" |
| 19 "github.com/luci/luci-go/common/config" |
| 16 "github.com/luci/luci-go/common/cryptorand" | 20 "github.com/luci/luci-go/common/cryptorand" |
| 21 "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/logdog/svcconfig" |
| 24 |
| 25 "golang.org/x/net/context" |
| 17 | 26 |
| 18 . "github.com/luci/luci-go/common/testing/assertions" | 27 . "github.com/luci/luci-go/common/testing/assertions" |
| 19 . "github.com/smartystreets/goconvey/convey" | 28 . "github.com/smartystreets/goconvey/convey" |
| 20 ) | 29 ) |
| 21 | 30 |
| 22 func TestRegisterPrefix(t *testing.T) { | 31 func TestRegisterPrefix(t *testing.T) { |
| 23 t.Parallel() | 32 t.Parallel() |
| 24 | 33 |
| 25 Convey(`With a testing configuration`, t, func() { | 34 Convey(`With a testing configuration`, t, func() { |
| 26 » » c, _ := ct.Install() | 35 » » c, env := ct.Install() |
| 27 c, fb := featureBreaker.FilterRDS(c, nil) | 36 c, fb := featureBreaker.FilterRDS(c, nil) |
| 28 ds.Get(c).Testable().Consistent(true) | 37 ds.Get(c).Testable().Consistent(true) |
| 29 | 38 |
| 30 // Mock random number generator so we can predict secrets. | 39 // Mock random number generator so we can predict secrets. |
| 31 c = cryptorand.MockForTest(c, 0) | 40 c = cryptorand.MockForTest(c, 0) |
| 32 randSecret := []byte{ | 41 randSecret := []byte{ |
| 33 250, 18, 249, 42, 251, 224, 15, 133, 8, 208, 232, 59, | 42 250, 18, 249, 42, 251, 224, 15, 133, 8, 208, 232, 59, |
| 34 171, 156, 248, 206, 191, 66, 226, 94, 139, 20, 234, 252, | 43 171, 156, 248, 206, 191, 66, 226, 94, 139, 20, 234, 252, |
| 35 129, 234, 224, 208, 15, 44, 173, 228, 193, 124, 22, 209, | 44 129, 234, 224, 208, 15, 44, 173, 228, 193, 124, 22, 209, |
| 36 } | 45 } |
| 37 | 46 |
| 38 svr := New() | 47 svr := New() |
| 39 | 48 |
| 49 const project = config.ProjectName("proj-foo") |
| 40 req := logdog.RegisterPrefixRequest{ | 50 req := logdog.RegisterPrefixRequest{ |
| 41 » » » Project: "proj-foo", | 51 » » » Project: string(project), |
| 42 Prefix: "testing/prefix", | 52 Prefix: "testing/prefix", |
| 43 SourceInfo: []string{"unit test"}, | 53 SourceInfo: []string{"unit test"}, |
| 44 } | 54 } |
| 55 pfx := &coordinator.LogPrefix{ID: coordinator.LogPrefixID(types.
StreamName(req.Prefix))} |
| 45 | 56 |
| 46 Convey(`Returns PermissionDenied error if not user does not have
write access.`, func() { | 57 Convey(`Returns PermissionDenied error if not user does not have
write access.`, func() { |
| 47 // "proj-bar" does not have anonymous write. | 58 // "proj-bar" does not have anonymous write. |
| 48 req.Project = "proj-bar" | 59 req.Project = "proj-bar" |
| 49 | 60 |
| 50 _, err := svr.RegisterPrefix(c, &req) | 61 _, err := svr.RegisterPrefix(c, &req) |
| 51 So(err, ShouldBeRPCPermissionDenied) | 62 So(err, ShouldBeRPCPermissionDenied) |
| 52 }) | 63 }) |
| 53 | 64 |
| 54 Convey(`Will register a new prefix.`, func() { | 65 Convey(`Will register a new prefix.`, func() { |
| 55 resp, err := svr.RegisterPrefix(c, &req) | 66 resp, err := svr.RegisterPrefix(c, &req) |
| 56 So(err, ShouldBeNil) | 67 So(err, ShouldBeNil) |
| 57 So(resp, ShouldResemble, &logdog.RegisterPrefixResponse{ | 68 So(resp, ShouldResemble, &logdog.RegisterPrefixResponse{ |
| 58 LogBundleTopic: "projects/app/topics/test-topic"
, | 69 LogBundleTopic: "projects/app/topics/test-topic"
, |
| 59 Secret: randSecret, | 70 Secret: randSecret, |
| 60 }) | 71 }) |
| 61 | 72 |
| 73 ct.WithProjectNamespace(c, project, func(c context.Conte
xt) { |
| 74 So(ds.Get(c).Get(pfx), ShouldBeNil) |
| 75 }) |
| 76 So(pfx, ShouldResemble, &coordinator.LogPrefix{ |
| 77 Schema: coordinator.CurrentSchemaVersion, |
| 78 ID: pfx.ID, |
| 79 Prefix: "testing/prefix", |
| 80 Created: ds.RoundTime(clock.Now(c)), |
| 81 Source: []string{"unit test"}, |
| 82 Secret: randSecret, |
| 83 |
| 84 // 24 hours is default service prefix expiration
. |
| 85 Expiration: ds.RoundTime(clock.Now(c).Add(24 * t
ime.Hour)), |
| 86 }) |
| 87 |
| 62 // Should have registered path components. | 88 // Should have registered path components. |
| 63 getComponents := func(b string) []string { | 89 getComponents := func(b string) []string { |
| 64 l, err := hierarchy.Get(c, hierarchy.Request{Pro
ject: "proj-foo", PathBase: b}) | 90 l, err := hierarchy.Get(c, hierarchy.Request{Pro
ject: "proj-foo", PathBase: b}) |
| 65 if err != nil { | 91 if err != nil { |
| 66 panic(err) | 92 panic(err) |
| 67 } | 93 } |
| 68 names := make([]string, len(l.Comp)) | 94 names := make([]string, len(l.Comp)) |
| 69 for i, e := range l.Comp { | 95 for i, e := range l.Comp { |
| 70 names[i] = e.Name | 96 names[i] = e.Name |
| 71 } | 97 } |
| 72 return names | 98 return names |
| 73 } | 99 } |
| 74 So(getComponents(""), ShouldResemble, []string{"testing"
}) | 100 So(getComponents(""), ShouldResemble, []string{"testing"
}) |
| 75 So(getComponents("testing"), ShouldResemble, []string{"p
refix"}) | 101 So(getComponents("testing"), ShouldResemble, []string{"p
refix"}) |
| 76 So(getComponents("testing/prefix"), ShouldResemble, []st
ring{"+"}) | 102 So(getComponents("testing/prefix"), ShouldResemble, []st
ring{"+"}) |
| 77 So(getComponents("testing/prefix/+"), ShouldResemble, []
string{}) | 103 So(getComponents("testing/prefix/+"), ShouldResemble, []
string{}) |
| 78 | 104 |
| 79 Convey(`Will refuse to register it again.`, func() { | 105 Convey(`Will refuse to register it again.`, func() { |
| 80 _, err := svr.RegisterPrefix(c, &req) | 106 _, err := svr.RegisterPrefix(c, &req) |
| 81 So(err, ShouldBeRPCAlreadyExists) | 107 So(err, ShouldBeRPCAlreadyExists) |
| 82 }) | 108 }) |
| 83 }) | 109 }) |
| 84 | 110 |
| 111 Convey(`Uses the correct prefix expiration`, func() { |
| 112 |
| 113 Convey(`When service, project, and request have expirati
on, chooses smallest.`, func() { |
| 114 env.ModProjectConfig(c, project, func(pcfg *svcc
onfig.ProjectConfig) { |
| 115 pcfg.PrefixExpiration = google.NewDurati
on(time.Hour) |
| 116 }) |
| 117 req.Expiration = google.NewDuration(time.Minute) |
| 118 |
| 119 _, err := svr.RegisterPrefix(c, &req) |
| 120 So(err, ShouldBeNil) |
| 121 |
| 122 ct.WithProjectNamespace(c, project, func(c conte
xt.Context) { |
| 123 So(ds.Get(c).Get(pfx), ShouldBeNil) |
| 124 }) |
| 125 So(pfx.Expiration, ShouldResemble, clock.Now(c).
Add(time.Minute)) |
| 126 }) |
| 127 |
| 128 Convey(`When service, and project have expiration, choos
es smallest.`, func() { |
| 129 env.ModProjectConfig(c, project, func(pcfg *svcc
onfig.ProjectConfig) { |
| 130 pcfg.PrefixExpiration = google.NewDurati
on(time.Hour) |
| 131 }) |
| 132 |
| 133 _, err := svr.RegisterPrefix(c, &req) |
| 134 So(err, ShouldBeNil) |
| 135 |
| 136 ct.WithProjectNamespace(c, project, func(c conte
xt.Context) { |
| 137 So(ds.Get(c).Get(pfx), ShouldBeNil) |
| 138 }) |
| 139 So(pfx.Expiration, ShouldResemble, clock.Now(c).
Add(time.Hour)) |
| 140 }) |
| 141 |
| 142 Convey(`When no expiration is defined, failed with inter
nal error.`, func() { |
| 143 env.ModServiceConfig(c, func(cfg *svcconfig.Conf
ig) { |
| 144 cfg.Coordinator.PrefixExpiration = nil |
| 145 }) |
| 146 |
| 147 _, err := svr.RegisterPrefix(c, &req) |
| 148 So(err, ShouldBeRPCInvalidArgument, "no prefix e
xpiration defined") |
| 149 }) |
| 150 }) |
| 151 |
| 85 Convey(`Will fail to register the prefix if Put is broken.`, fun
c() { | 152 Convey(`Will fail to register the prefix if Put is broken.`, fun
c() { |
| 86 fb.BreakFeatures(errors.New("test error"), "PutMulti") | 153 fb.BreakFeatures(errors.New("test error"), "PutMulti") |
| 87 _, err := svr.RegisterPrefix(c, &req) | 154 _, err := svr.RegisterPrefix(c, &req) |
| 88 So(err, ShouldBeRPCInternal) | 155 So(err, ShouldBeRPCInternal) |
| 89 }) | 156 }) |
| 90 }) | 157 }) |
| 91 } | 158 } |
| OLD | NEW |