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

Side by Side Diff: client/internal/logdog/butler/streamserver/handshake_test.go

Issue 1429993002: LogDog: Add Butler stream server package. (Closed) Base URL: https://github.com/luci/luci-go@logdog-review-butlerproto
Patch Set: Bind POSIX test to POSIX domains. Created 5 years, 1 month 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 Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 package streamserver
6
7 import (
8 "bytes"
9 "encoding/binary"
10 "fmt"
11 "io"
12 "testing"
13 "time"
14
15 "github.com/luci/luci-go/client/logdog/butlerlib/streamproto"
16 "github.com/luci/luci-go/common/clock/testclock"
17 "github.com/luci/luci-go/common/logdog/protocol"
18 "github.com/luci/luci-go/common/logdog/types"
19 "github.com/luci/luci-go/common/proto/google"
20 ta "github.com/luci/luci-go/common/testing/assertions"
21 . "github.com/smartystreets/goconvey/convey"
22 "golang.org/x/net/context"
23 )
24
25 func writePanic(w io.Writer, d []byte) {
26 amt, err := w.Write(d)
27 if err != nil {
28 panic(err)
29 }
30 if amt != len(d) {
31 panic("failed to write full buffer")
32 }
33 }
34
35 type handshakeBuilder struct {
36 magic []byte // The frame header. If empty, don't include a frame header .
37 size uint64 // The size. If zero, calculate the size.
38 }
39
40 func (b *handshakeBuilder) writeTo(w io.Writer, handshake string, data []byte) {
41 // Frame header
42 if len(b.magic) > 0 {
43 writePanic(w, b.magic)
44 }
45
46 // Size
47 size := b.size
48 if size == 0 {
49 size = uint64(len(handshake))
50 }
51 sizeBuf := make([]byte, binary.MaxVarintLen64)
52 count := binary.PutUvarint(sizeBuf, uint64(size))
53 writePanic(w, sizeBuf[:count])
54
55 if handshake != "" {
56 writePanic(w, []byte(handshake))
57 }
58 writePanic(w, data)
59 }
60
61 // Generate a reader from the configuration.
62 func (b *handshakeBuilder) reader(handshake string, data []byte) io.Reader {
63 r := bytes.Buffer{}
64 b.writeTo(&r, handshake, data)
65 return &r
66 }
67
68 // Tests for handshakeProtocol
69 func testHandshakeProtocol(t *testing.T, verbose bool) {
70 Convey(fmt.Sprintf(`A handshakeProtocol instance (verbose=%v)`, verbose) , t, func() {
71 hb := handshakeBuilder{
72 magic: streamproto.ProtocolFrameHeaderMagic,
73 }
74
75 ctx, tc := testclock.UseTime(context.Background(), testclock.Tes tTimeUTC)
76 p := &handshakeProtocol{}
77 p.forceVerbose = verbose
78
79 Convey(`Will fail if no handshake data is provided.`, func() {
80 hb.magic = []byte{}
81
82 _, err := p.Handshake(ctx, hb.reader("{}", nil))
83 So(err, ShouldNotBeNil)
84 })
85
86 Convey(`Will fail with an invalid handshake protocol.`, func() {
87 hb.magic = []byte{0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA}
88
89 _, err := p.Handshake(ctx, hb.reader("{}", nil))
90 So(err, ShouldNotBeNil)
91 })
92
93 Convey(`Loading a handshake frame starting with an invalid size varint value must fail.`, func() {
94 // This exceeds the maximum 64-bit varint size (10 bytes ) and never
95 // terminates (no MSB).
96 _, err := p.Handshake(ctx, bytes.NewReader([]byte{
97 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
98 }))
99 So(err, ShouldNotBeNil)
100 })
101
102 Convey(`Loading a handshake frame larger than the maximum header size must fail.`, func() {
103 hb.size = maxHeaderSize + 1
104 _, err := p.Handshake(ctx, hb.reader("", nil))
105 So(err, ShouldNotBeNil)
106 })
107
108 Convey(`Loading an JSON object with just a name`, func() {
109 props, err := p.Handshake(ctx, hb.reader(`{"name": "test "}`, nil))
110 So(err, ShouldBeNil)
111
112 Convey(`Should produce a valid stream configuration.`, f unc() {
113 So(props, ta.ShouldResembleV, &streamproto.Prope rties{
114 LogStreamDescriptor: protocol.LogStreamD escriptor{
115 Name: "test",
116 Timestamp: google.NewTimestamp (tc.Now()),
117 StreamType: protocol.LogStreamD escriptor_TEXT,
118 ContentType: string(types.Conten tTypeText),
119 },
120 })
121 })
122 })
123
124 Convey(`Loading a fully-specified configuration`, func() {
125 data := `{
126 "name": "test", "tee": "stdout", "timestamp": "2 015-05-07T01:29:51+00:00",
127 "contentType": "text/plain",
128 "tags": {"foo": "bar", "baz": "qux"}
129 }`
130 props, err := p.Handshake(ctx, hb.reader(data, nil))
131 So(err, ShouldBeNil)
132
133 Convey(`Should produce a specific configuration.`, func( ) {
134 So(props, ta.ShouldResembleV, &streamproto.Prope rties{
135 LogStreamDescriptor: protocol.LogStreamD escriptor{
136 Name: "test",
137 ContentType: "text/plain",
138 Timestamp: google.NewTimestamp (time.Date(2015, 05, 07, 1, 29, 51, 0, time.UTC)),
139 Tags: []*protocol.LogStreamDescr iptor_Tag{
140 {Key: "baz", Value: "qux "},
141 {Key: "foo", Value: "bar "},
142 },
143 },
144 Tee: streamproto.TeeStdout,
145 })
146 })
147 })
148
149 Convey(`Loading a (valid) JSON array should fail to load.`, func () {
150 data := `["This is an array!"]`
151 _, err := p.Handshake(ctx, hb.reader(data, nil))
152 So(err, ShouldNotBeNil)
153 })
154
155 Convey(`Loading a JSON descriptor with just a name should succee d.`, func() {
156 data := `{"name": "test"}`
157 props, err := p.Handshake(ctx, hb.reader(data, nil))
158 So(err, ShouldBeNil)
159 So(props, ShouldNotBeNil)
160 })
161
162 Convey(`Loading an empty JSON object with a larger-than-necessar y header size should fail.`, func() {
163 data := `{}`
164 hb.size = uint64(len(data) + 10)
165 _, err := p.Handshake(ctx, hb.reader(data, nil))
166 So(err, ShouldNotBeNil)
167 })
168
169 Convey(`Loading an JSON with an erroneous config should fail.`, func() {
170 data := `{"timestamp": "text-for-some-reason"}`
171 _, err := p.Handshake(ctx, hb.reader(data, nil))
172 So(err, ShouldNotBeNil)
173 })
174
175 Convey(`Loading an invalid JSON descriptor should fail.`, func() {
176 data := `invalid`
177 _, err := p.Handshake(ctx, hb.reader(data, nil))
178 So(err, ShouldNotBeNil)
179 })
180
181 for idx, v := range []string{"none", "stdout", "stderr", "clearl y invalid"} {
182 Convey(fmt.Sprintf(`A protocol with a tee type of: %s`, v), func() {
183 ctx := context.Background()
184 data := fmt.Sprintf(`{"name": "test", "tee": "%s "}`, v)
185 _, err := p.Handshake(ctx, hb.reader(data, nil))
186 if idx <= 2 {
187 Convey(`Should successfully parse.`, fun c() {
188 So(err, ShouldBeNil)
189 })
190 } else {
191 Convey(`Should fail to parse.`, func() {
192 So(err, ShouldNotBeNil)
193 })
194 }
195 })
196 }
197 })
198 }
199
200 func TestHandshakeProtocol(t *testing.T) {
201 testHandshakeProtocol(t, false)
202 }
203
204 // As an optimization, we buffer data differently for verbose output. This
205 // creates a separate code path that we have to take if logging verbose function
206 // is set.
207 func TestHandshakeProtocolVerbose(t *testing.T) {
208 testHandshakeProtocol(t, true)
209 }
OLDNEW
« no previous file with comments | « client/internal/logdog/butler/streamserver/handshake.go ('k') | client/internal/logdog/butler/streamserver/namedPipe.go » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698