go.chromium.org/luci@v0.0.0-20240309015107-7cdc2e660f33/logdog/client/butlerlib/streamproto/handshake_test.go (about) 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 streamproto 16 17 import ( 18 "bytes" 19 "encoding/binary" 20 "fmt" 21 "testing" 22 "time" 23 24 . "github.com/smartystreets/goconvey/convey" 25 "go.chromium.org/luci/common/clock/clockflag" 26 . "go.chromium.org/luci/common/testing/assertions" 27 ) 28 29 func TestHandshakeProtocol(t *testing.T) { 30 Convey(`test WriteHandshake/FromHandshake`, t, func() { 31 buf := &bytes.Buffer{} 32 writeUvarint := func(val uint64) { 33 uvarBuf := make([]byte, binary.MaxVarintLen64) 34 buf.Write(uvarBuf[:binary.PutUvarint(uvarBuf, val)]) 35 } 36 37 f := &Flags{} 38 39 Convey(`Will fail if no handshake data is provided.`, func() { 40 So(f.FromHandshake(buf), ShouldErrLike, "reading magic number: EOF") 41 }) 42 43 Convey(`Will fail with an invalid handshake protocol.`, func() { 44 buf.Write([]byte{0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA}) 45 So(f.FromHandshake(buf), ShouldErrLike, "magic number mismatch") 46 }) 47 48 Convey(`Loading a handshake frame starting with an invalid size varint value must fail.`, func() { 49 buf.Write(ProtocolFrameHeaderMagic) 50 buf.Write([]byte{ 51 // invalid uvarint 52 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x79, 53 }) 54 So(f.FromHandshake(buf), ShouldErrLike, "overflows a 64-bit integer") 55 }) 56 57 Convey(`Loading a handshake frame larger than the maximum header size must fail.`, func() { 58 buf.Write(ProtocolFrameHeaderMagic) 59 writeUvarint(maxFrameSize + 1) 60 So(f.FromHandshake(buf), ShouldErrLike, "frame size exceeds maximum") 61 }) 62 63 Convey(`Loading an JSON object with just a name`, func() { 64 data := `{"name": "test"}` 65 buf.Write(ProtocolFrameHeaderMagic) 66 writeUvarint(uint64(len(data))) 67 buf.Write([]byte(data)) 68 69 So(f.FromHandshake(buf), ShouldBeNil) 70 So(f.Name, ShouldEqual, StreamNameFlag("test")) 71 }) 72 73 Convey(`Loading a fully-specified configuration`, func() { 74 date := "2015-05-07T01:29:51+00:00" 75 timestamp, err := time.ParseInLocation(time.RFC3339, date, nil) 76 So(err, ShouldBeNil) 77 78 Convey(`manually written handshake`, func() { 79 data := fmt.Sprintf(`{ 80 "name": "test", "timestamp": %q, 81 "contentType": "text/plain; charset=utf-8", 82 "tags": {"foo": "bar", "baz": "qux"} 83 }`, date) 84 buf.Write(ProtocolFrameHeaderMagic) 85 writeUvarint(uint64(len(data))) 86 buf.Write([]byte(data)) 87 }) 88 Convey(`WriteHandshake`, func() { 89 f.Name = "test" 90 f.Timestamp = clockflag.Time(timestamp) 91 f.ContentType = "text/plain; charset=utf-8" 92 f.Tags = TagMap{ 93 "foo": "bar", 94 "baz": "qux", 95 } 96 So(f.WriteHandshake(buf), ShouldBeNil) 97 f = &Flags{} 98 }) 99 100 So(f.FromHandshake(buf), ShouldBeNil) 101 102 So(f, ShouldResemble, &Flags{ 103 Name: "test", 104 ContentType: "text/plain; charset=utf-8", 105 Timestamp: clockflag.Time(timestamp), 106 Tags: map[string]string{ 107 "baz": "qux", 108 "foo": "bar", 109 }, 110 }) 111 }) 112 113 Convey(`Loading a (valid) JSON array should fail to load.`, func() { 114 data := `["This is an array!"]` 115 buf.Write(ProtocolFrameHeaderMagic) 116 writeUvarint(uint64(len(data))) 117 buf.Write([]byte(data)) 118 119 So(f.FromHandshake(buf), ShouldErrLike, "cannot unmarshal array") 120 }) 121 122 Convey(`Loading an empty JSON object with a larger-than-necessary header size should fail.`, func() { 123 data := `{}` 124 buf.Write(ProtocolFrameHeaderMagic) 125 writeUvarint(uint64(len(data) + 10)) 126 buf.Write([]byte(data)) 127 128 So(f.FromHandshake(buf), ShouldErrLike, "handshake had 10 bytes of trailing data") 129 }) 130 131 Convey(`Loading a JSON with bad field contents should fail.`, func() { 132 data := `{"timestamp": "text-for-some-reason"}` 133 buf.Write(ProtocolFrameHeaderMagic) 134 writeUvarint(uint64(len(data))) 135 buf.Write([]byte(data)) 136 137 So(f.FromHandshake(buf), ShouldErrLike, "cannot parse") 138 }) 139 140 Convey(`Loading an invalid JSON descriptor should fail.`, func() { 141 data := `invalid` 142 buf.Write(ProtocolFrameHeaderMagic) 143 writeUvarint(uint64(len(data))) 144 buf.Write([]byte(data)) 145 146 So(f.FromHandshake(buf), ShouldErrLike, "invalid character 'i'") 147 }) 148 149 }) 150 }