go.chromium.org/luci@v0.0.0-20240309015107-7cdc2e660f33/logdog/client/butlerlib/streamclient/fake_test.go (about) 1 // Copyright 2019 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 streamclient 16 17 import ( 18 "context" 19 "io" 20 "testing" 21 22 "go.chromium.org/luci/common/clock/clockflag" 23 "go.chromium.org/luci/common/clock/testclock" 24 "go.chromium.org/luci/common/errors" 25 "go.chromium.org/luci/logdog/api/logpb" 26 "go.chromium.org/luci/logdog/client/butlerlib/streamproto" 27 28 . "github.com/smartystreets/goconvey/convey" 29 . "go.chromium.org/luci/common/testing/assertions" 30 ) 31 32 func TestFakeProtocol(t *testing.T) { 33 t.Parallel() 34 35 Convey(`"fake" protocol Client`, t, func() { 36 ctx, _ := testclock.UseTime(context.Background(), testclock.TestTimeUTC) 37 38 Convey(`good`, func() { 39 scFake, client := NewUnregisteredFake("namespace") 40 41 Convey(`can use a text stream`, func() { 42 stream, err := client.NewStream(ctx, "test") 43 So(err, ShouldBeNil) 44 45 n, err := stream.Write([]byte("hi")) 46 So(n, ShouldEqual, 2) 47 So(err, ShouldBeNil) 48 So(stream.Close(), ShouldBeNil) 49 50 streamData := scFake.Data()["namespace/test"] 51 So(streamData, ShouldNotBeNil) 52 So(streamData.GetStreamData(), ShouldEqual, "hi") 53 So(streamData.GetDatagrams(), ShouldResemble, []string{}) 54 So(streamData.GetFlags(), ShouldResemble, streamproto.Flags{ 55 Name: "namespace/test", 56 ContentType: "text/plain; charset=utf-8", 57 Type: streamproto.StreamType(logpb.StreamType_TEXT), 58 Timestamp: clockflag.Time(testclock.TestTimeUTC), 59 Tags: nil, 60 }) 61 }) 62 63 Convey(`can use a binary stream`, func() { 64 stream, err := client.NewStream(ctx, "test", Binary()) 65 So(err, ShouldBeNil) 66 67 n, err := stream.Write([]byte{0, 1, 2, 3}) 68 So(n, ShouldEqual, 4) 69 So(err, ShouldBeNil) 70 So(stream.Close(), ShouldBeNil) 71 72 streamData := scFake.Data()["namespace/test"] 73 So(streamData, ShouldNotBeNil) 74 So(streamData.GetStreamData(), ShouldEqual, "\x00\x01\x02\x03") 75 So(streamData.GetDatagrams(), ShouldResemble, []string{}) 76 So(streamData.GetFlags(), ShouldResemble, streamproto.Flags{ 77 Name: "namespace/test", 78 ContentType: "application/octet-stream", 79 Type: streamproto.StreamType(logpb.StreamType_BINARY), 80 Timestamp: clockflag.Time(testclock.TestTimeUTC), 81 Tags: nil, 82 }) 83 }) 84 85 Convey(`can use a datagram stream`, func() { 86 stream, err := client.NewDatagramStream(ctx, "test") 87 So(err, ShouldBeNil) 88 89 So(stream.WriteDatagram([]byte("hi")), ShouldBeNil) 90 So(stream.WriteDatagram([]byte("there")), ShouldBeNil) 91 So(stream.Close(), ShouldBeNil) 92 93 streamData := scFake.Data()["namespace/test"] 94 So(streamData, ShouldNotBeNil) 95 So(streamData.GetStreamData(), ShouldEqual, "") 96 So(streamData.GetDatagrams(), ShouldResemble, []string{"hi", "there"}) 97 So(streamData.GetFlags(), ShouldResemble, streamproto.Flags{ 98 Name: "namespace/test", 99 ContentType: "application/x-logdog-datagram", 100 Type: streamproto.StreamType(logpb.StreamType_DATAGRAM), 101 Timestamp: clockflag.Time(testclock.TestTimeUTC), 102 Tags: nil, 103 }) 104 }) 105 }) 106 107 Convey(`bad`, func() { 108 Convey(`duplicate stream`, func() { 109 _, client := NewUnregisteredFake("") 110 111 stream, err := client.NewStream(ctx, "test") 112 So(err, ShouldBeNil) 113 So(stream.Close(), ShouldBeNil) 114 115 _, err = client.NewStream(ctx, "test") 116 So(err, ShouldErrLike, `stream "test": stream "test" already dialed`) 117 118 _, err = client.NewStream(ctx, "test", Binary()) 119 So(err, ShouldErrLike, `stream "test": stream "test" already dialed`) 120 121 _, err = client.NewDatagramStream(ctx, "test") 122 So(err, ShouldErrLike, `datagram stream "test": stream "test" already dialed`) 123 }) 124 125 Convey(`simulated stream errors`, func() { 126 Convey(`connection error`, func() { 127 scFake, client := NewUnregisteredFake("") 128 scFake.SetError(errors.New("bad juju")) 129 130 _, err := client.NewStream(ctx, "test") 131 So(err, ShouldErrLike, `stream "test": bad juju`) 132 }) 133 134 Convey(`use of a stream after close`, func() { 135 _, client := NewUnregisteredFake("") 136 137 stream, err := client.NewStream(ctx, "test") 138 So(err, ShouldBeNil) 139 So(stream.Close(), ShouldBeNil) 140 141 So(stream.Close(), ShouldErrLike, io.ErrClosedPipe) 142 _, err = stream.Write([]byte("hi")) 143 So(err, ShouldErrLike, io.ErrClosedPipe) 144 145 stream2, err := client.NewDatagramStream(ctx, "test2") 146 So(err, ShouldBeNil) 147 So(stream2.Close(), ShouldBeNil) 148 149 So(stream2.Close(), ShouldErrLike, io.ErrClosedPipe) 150 So(stream2.WriteDatagram([]byte("hi")), ShouldErrLike, io.ErrClosedPipe) 151 }) 152 }) 153 }) 154 }) 155 }