| OLD | NEW |
| 1 // Copyright 2015 The LUCI Authors. All rights reserved. | 1 // Copyright 2015 The LUCI Authors. All rights reserved. |
| 2 // Use of this source code is governed under the Apache License, Version 2.0 | 2 // Use of this source code is governed under the Apache License, Version 2.0 |
| 3 // that can be found in the LICENSE file. | 3 // that can be found in the LICENSE file. |
| 4 | 4 |
| 5 package bootstrap | 5 package bootstrap |
| 6 | 6 |
| 7 import ( | 7 import ( |
| 8 » "errors" | 8 » "fmt" |
| 9 "testing" | 9 "testing" |
| 10 | 10 |
| 11 "github.com/luci/luci-go/client/environ" | 11 "github.com/luci/luci-go/client/environ" |
| 12 "github.com/luci/luci-go/common/errors" |
| 12 "github.com/luci/luci-go/logdog/client/butlerlib/streamclient" | 13 "github.com/luci/luci-go/logdog/client/butlerlib/streamclient" |
| 13 "github.com/luci/luci-go/logdog/client/butlerlib/streamproto" | 14 "github.com/luci/luci-go/logdog/client/butlerlib/streamproto" |
| 15 "github.com/luci/luci-go/logdog/common/types" |
| 14 | 16 |
| 15 . "github.com/luci/luci-go/common/testing/assertions" | 17 . "github.com/luci/luci-go/common/testing/assertions" |
| 16 . "github.com/smartystreets/goconvey/convey" | 18 . "github.com/smartystreets/goconvey/convey" |
| 17 ) | 19 ) |
| 18 | 20 |
| 19 type sentinelClient struct{} | 21 type sentinelClient struct{} |
| 20 | 22 |
| 21 func (*sentinelClient) NewStream(f streamproto.Flags) (streamclient.Stream, erro
r) { return nil, nil } | 23 func (sc *sentinelClient) NewStream(f streamproto.Flags) (streamclient.Stream, e
rror) { |
| 24 » return &sentinelStream{props: f.Properties()}, nil |
| 25 } |
| 26 |
| 27 type sentinelStream struct { |
| 28 » streamclient.Stream |
| 29 » props *streamproto.Properties |
| 30 } |
| 31 |
| 32 func (ss *sentinelStream) Properties() *streamproto.Properties { return ss.props
} |
| 33 func (ss *sentinelStream) Close() error { return nil } |
| 22 | 34 |
| 23 func TestBootstrap(t *testing.T) { | 35 func TestBootstrap(t *testing.T) { |
| 36 t.Parallel() |
| 37 |
| 24 Convey(`A test Environment`, t, func() { | 38 Convey(`A test Environment`, t, func() { |
| 25 reg := &streamclient.Registry{} | 39 reg := &streamclient.Registry{} |
| 26 regSpec := "" | 40 regSpec := "" |
| 27 regErr := error(nil) | 41 regErr := error(nil) |
| 28 reg.Register("test", func(spec string) (streamclient.Client, err
or) { | 42 reg.Register("test", func(spec string) (streamclient.Client, err
or) { |
| 29 regSpec = spec | 43 regSpec = spec |
| 30 return &sentinelClient{}, regErr | 44 return &sentinelClient{}, regErr |
| 31 }) | 45 }) |
| 32 | 46 |
| 33 env := environ.Environment{ | 47 env := environ.Environment{ |
| (...skipping 20 matching lines...) Expand all Loading... |
| 54 }) | 68 }) |
| 55 | 69 |
| 56 Convey(`And the remaining environment parameters`, func(
) { | 70 Convey(`And the remaining environment parameters`, func(
) { |
| 57 env[EnvStreamServerPath] = "test:client:params" | 71 env[EnvStreamServerPath] = "test:client:params" |
| 58 env[EnvCoordinatorHost] = "example.appspot.com" | 72 env[EnvCoordinatorHost] = "example.appspot.com" |
| 59 | 73 |
| 60 Convey(`Yields a fully-populated Bootstrap.`, fu
nc() { | 74 Convey(`Yields a fully-populated Bootstrap.`, fu
nc() { |
| 61 bs, err := getFromEnv(env, reg) | 75 bs, err := getFromEnv(env, reg) |
| 62 So(err, ShouldBeNil) | 76 So(err, ShouldBeNil) |
| 63 | 77 |
| 78 // Check that the client is populated, s
o we can test the remaining |
| 79 // fields without reconstructing it. |
| 80 So(bs.Client, ShouldHaveSameTypeAs, &sen
tinelClient{}) |
| 81 bs.Client = nil |
| 82 |
| 64 So(bs, ShouldResemble, &Bootstrap{ | 83 So(bs, ShouldResemble, &Bootstrap{ |
| 65 CoordinatorHost: "example.appspo
t.com", | 84 CoordinatorHost: "example.appspo
t.com", |
| 66 Project: "test-project", | 85 Project: "test-project", |
| 67 Prefix: "butler/prefix"
, | 86 Prefix: "butler/prefix"
, |
| 68 Client: &sentinelClient
{}, | |
| 69 }) | 87 }) |
| 70 So(regSpec, ShouldEqual, "client:params"
) | 88 So(regSpec, ShouldEqual, "client:params"
) |
| 71 }) | 89 }) |
| 72 | 90 |
| 73 Convey(`If Client creation fails, will fail.`, f
unc() { | 91 Convey(`If Client creation fails, will fail.`, f
unc() { |
| 74 regErr = errors.New("testing error") | 92 regErr = errors.New("testing error") |
| 75 _, err := getFromEnv(env, reg) | 93 _, err := getFromEnv(env, reg) |
| 76 So(err, ShouldErrLike, "failed to create
stream client") | 94 So(err, ShouldErrLike, "failed to create
stream client") |
| 77 }) | 95 }) |
| 78 }) | 96 }) |
| (...skipping 11 matching lines...) Expand all Loading... |
| 90 }) | 108 }) |
| 91 | 109 |
| 92 Convey(`With an invalid Butler project, will fail.`, fun
c() { | 110 Convey(`With an invalid Butler project, will fail.`, fun
c() { |
| 93 env[EnvStreamProject] = "_notavaildproject" | 111 env[EnvStreamProject] = "_notavaildproject" |
| 94 _, err := getFromEnv(env, reg) | 112 _, err := getFromEnv(env, reg) |
| 95 So(err, ShouldErrLike, "failed to validate proje
ct") | 113 So(err, ShouldErrLike, "failed to validate proje
ct") |
| 96 }) | 114 }) |
| 97 }) | 115 }) |
| 98 }) | 116 }) |
| 99 } | 117 } |
| 118 |
| 119 func TestBootstrapURLGeneration(t *testing.T) { |
| 120 t.Parallel() |
| 121 |
| 122 Convey(`A bootstrap instance`, t, func() { |
| 123 bs := &Bootstrap{ |
| 124 Project: "test", |
| 125 Prefix: "foo", |
| 126 CoordinatorHost: "example.appspot.com", |
| 127 } |
| 128 |
| 129 Convey(`Can generate viewer URLs`, func() { |
| 130 for _, tc := range []struct { |
| 131 paths []types.StreamPath |
| 132 url string |
| 133 }{ |
| 134 {[]types.StreamPath{"foo/bar/+/baz"}, "https://e
xample.appspot.com/v/?s=test%2Ffoo%2Fbar%2F%2B%2Fbaz"}, |
| 135 {[]types.StreamPath{"foo/bar/+/**"}, "https://ex
ample.appspot.com/v/?s=test%2Ffoo%2Fbar%2F%2B%2F%2A%2A"}, |
| 136 {[]types.StreamPath{ |
| 137 "foo/bar/+/baz", |
| 138 "foo/bar/+/qux", |
| 139 }, "https://example.appspot.com/v/?s=test%2Ffoo%
2Fbar%2F%2B%2Fbaz&s=test%2Ffoo%2Fbar%2F%2B%2Fqux"}, |
| 140 } { |
| 141 Convey(fmt.Sprintf(`Will generate [%s] from %q`,
tc.url, tc.paths), func() { |
| 142 url, err := bs.GetViewerURL(tc.paths...) |
| 143 So(err, ShouldBeNil) |
| 144 So(url, ShouldEqual, tc.url) |
| 145 }) |
| 146 } |
| 147 }) |
| 148 |
| 149 Convey(`With no project, will not generate URLs.`, func() { |
| 150 bs.Project = "" |
| 151 |
| 152 _, err := bs.GetViewerURL("bar") |
| 153 So(err, ShouldErrLike, "no project is configured") |
| 154 }) |
| 155 |
| 156 Convey(`With no coordinator host, will not generate URLs.`, func
() { |
| 157 bs.CoordinatorHost = "" |
| 158 |
| 159 _, err := bs.GetViewerURL("bar") |
| 160 So(err, ShouldErrLike, "no coordinator host is configure
d") |
| 161 }) |
| 162 |
| 163 Convey(`With a stream client configured`, func() { |
| 164 reg := streamclient.Registry{} |
| 165 reg.Register("test", func(spec string) (streamclient.Cli
ent, error) { |
| 166 return &sentinelClient{}, nil |
| 167 }) |
| 168 |
| 169 So(bs.initializeClient("test:", ®), ShouldBeNil) |
| 170 So(bs.Client, ShouldHaveSameTypeAs, &sentinelClient{}) |
| 171 |
| 172 Convey(`Can generate viewer URLs for streams.`, func() { |
| 173 barS, err := bs.Client.NewStream(streamproto.Fla
gs{Name: "bar"}) |
| 174 So(err, ShouldBeNil) |
| 175 defer barS.Close() |
| 176 |
| 177 bazS, err := bs.Client.NewStream(streamproto.Fla
gs{Name: "baz"}) |
| 178 So(err, ShouldBeNil) |
| 179 defer bazS.Close() |
| 180 |
| 181 url, err := bs.GetViewerURLForStreams(barS, bazS
) |
| 182 So(err, ShouldBeNil) |
| 183 So(url, ShouldEqual, "https://example.appspot.co
m/v/?s=test%2Ffoo%2F%2B%2Fbar&s=test%2Ffoo%2F%2B%2Fbaz") |
| 184 }) |
| 185 |
| 186 Convey(`Will not generate viewer URLs if a prefix is not
defined.`, func() { |
| 187 bs.Prefix = "" |
| 188 |
| 189 barS, err := bs.Client.NewStream(streamproto.Fla
gs{Name: "bar"}) |
| 190 So(err, ShouldBeNil) |
| 191 defer barS.Close() |
| 192 |
| 193 _, err = bs.GetViewerURLForStreams(barS) |
| 194 So(err, ShouldErrLike, "no prefix is configured"
) |
| 195 }) |
| 196 }) |
| 197 }) |
| 198 } |
| OLD | NEW |