github.com/SagerNet/gvisor@v0.0.0-20210707092255-7731c139d75c/pkg/sentry/kernel/pipe/pipe_test.go (about) 1 // Copyright 2018 The gVisor 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 pipe 16 17 import ( 18 "bytes" 19 "testing" 20 21 "github.com/SagerNet/gvisor/pkg/sentry/contexttest" 22 "github.com/SagerNet/gvisor/pkg/syserror" 23 "github.com/SagerNet/gvisor/pkg/usermem" 24 "github.com/SagerNet/gvisor/pkg/waiter" 25 ) 26 27 func TestPipeRW(t *testing.T) { 28 ctx := contexttest.Context(t) 29 r, w := NewConnectedPipe(ctx, 65536) 30 defer r.DecRef(ctx) 31 defer w.DecRef(ctx) 32 33 msg := []byte("here's some bytes") 34 wantN := int64(len(msg)) 35 n, err := w.Writev(ctx, usermem.BytesIOSequence(msg)) 36 if n != wantN || err != nil { 37 t.Fatalf("Writev: got (%d, %v), wanted (%d, nil)", n, err, wantN) 38 } 39 40 buf := make([]byte, len(msg)) 41 n, err = r.Readv(ctx, usermem.BytesIOSequence(buf)) 42 if n != wantN || err != nil || !bytes.Equal(buf, msg) { 43 t.Fatalf("Readv: got (%d, %v) %q, wanted (%d, nil) %q", n, err, buf, wantN, msg) 44 } 45 } 46 47 func TestPipeReadBlock(t *testing.T) { 48 ctx := contexttest.Context(t) 49 r, w := NewConnectedPipe(ctx, 65536) 50 defer r.DecRef(ctx) 51 defer w.DecRef(ctx) 52 53 n, err := r.Readv(ctx, usermem.BytesIOSequence(make([]byte, 1))) 54 if n != 0 || err != syserror.ErrWouldBlock { 55 t.Fatalf("Readv: got (%d, %v), wanted (0, %v)", n, err, syserror.ErrWouldBlock) 56 } 57 } 58 59 func TestPipeWriteBlock(t *testing.T) { 60 const atomicIOBytes = 2 61 const capacity = MinimumPipeSize 62 63 ctx := contexttest.Context(t) 64 r, w := NewConnectedPipe(ctx, capacity) 65 defer r.DecRef(ctx) 66 defer w.DecRef(ctx) 67 68 msg := make([]byte, capacity+1) 69 n, err := w.Writev(ctx, usermem.BytesIOSequence(msg)) 70 if wantN, wantErr := int64(capacity), syserror.ErrWouldBlock; n != wantN || err != wantErr { 71 t.Fatalf("Writev: got (%d, %v), wanted (%d, %v)", n, err, wantN, wantErr) 72 } 73 } 74 75 func TestPipeWriteUntilEnd(t *testing.T) { 76 const atomicIOBytes = 2 77 78 ctx := contexttest.Context(t) 79 r, w := NewConnectedPipe(ctx, atomicIOBytes) 80 defer r.DecRef(ctx) 81 defer w.DecRef(ctx) 82 83 msg := []byte("here's some bytes") 84 85 wDone := make(chan struct{}, 0) 86 rDone := make(chan struct{}, 0) 87 defer func() { 88 // Signal the reader to stop and wait until it does so. 89 close(wDone) 90 <-rDone 91 }() 92 93 go func() { 94 defer close(rDone) 95 // Read from r until done is closed. 96 ctx := contexttest.Context(t) 97 buf := make([]byte, len(msg)+1) 98 dst := usermem.BytesIOSequence(buf) 99 e, ch := waiter.NewChannelEntry(nil) 100 r.EventRegister(&e, waiter.ReadableEvents) 101 defer r.EventUnregister(&e) 102 for { 103 n, err := r.Readv(ctx, dst) 104 dst = dst.DropFirst64(n) 105 if err == syserror.ErrWouldBlock { 106 select { 107 case <-ch: 108 continue 109 case <-wDone: 110 // We expect to have 1 byte left in dst since len(buf) == 111 // len(msg)+1. 112 if dst.NumBytes() != 1 || !bytes.Equal(buf[:len(msg)], msg) { 113 t.Errorf("Reader: got %q (%d bytes remaining), wanted %q", buf, dst.NumBytes(), msg) 114 } 115 return 116 } 117 } 118 if err != nil { 119 t.Errorf("Readv: got unexpected error %v", err) 120 return 121 } 122 } 123 }() 124 125 src := usermem.BytesIOSequence(msg) 126 e, ch := waiter.NewChannelEntry(nil) 127 w.EventRegister(&e, waiter.WritableEvents) 128 defer w.EventUnregister(&e) 129 for src.NumBytes() != 0 { 130 n, err := w.Writev(ctx, src) 131 src = src.DropFirst64(n) 132 if err == syserror.ErrWouldBlock { 133 <-ch 134 continue 135 } 136 if err != nil { 137 t.Fatalf("Writev: got (%d, %v)", n, err) 138 } 139 } 140 }