gvisor.dev/gvisor@v0.0.0-20240520182842-f9d4d51c7e0f/pkg/sentry/fsimpl/devpts/devpts_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 devpts 16 17 import ( 18 "testing" 19 20 "gvisor.dev/gvisor/pkg/abi/linux" 21 "gvisor.dev/gvisor/pkg/sentry/contexttest" 22 "gvisor.dev/gvisor/pkg/usermem" 23 "gvisor.dev/gvisor/pkg/waiter" 24 ) 25 26 func TestSimpleMasterToReplica(t *testing.T) { 27 ld := newLineDiscipline(linux.DefaultReplicaTermios, nil) 28 ctx := contexttest.Context(t) 29 inBytes := []byte("hello, tty\n") 30 src := usermem.BytesIOSequence(inBytes) 31 outBytes := make([]byte, 32) 32 dst := usermem.BytesIOSequence(outBytes) 33 34 // Write to the input queue. 35 nw, err := ld.inputQueueWrite(ctx, src) 36 if err != nil { 37 t.Fatalf("error writing to input queue: %v", err) 38 } 39 if nw != int64(len(inBytes)) { 40 t.Fatalf("wrote wrong length: got %d, want %d", nw, len(inBytes)) 41 } 42 43 // Read from the input queue. 44 nr, err := ld.inputQueueRead(ctx, dst) 45 if err != nil { 46 t.Fatalf("error reading from input queue: %v", err) 47 } 48 if nr != int64(len(inBytes)) { 49 t.Fatalf("read wrong length: got %d, want %d", nr, len(inBytes)) 50 } 51 52 outStr := string(outBytes[:nr]) 53 inStr := string(inBytes) 54 if outStr != inStr { 55 t.Fatalf("written and read strings do not match: got %q, want %q", outStr, inStr) 56 } 57 } 58 59 func TestEchoDeadlock(t *testing.T) { 60 ctx := contexttest.Context(t) 61 termios := linux.DefaultReplicaTermios 62 termios.LocalFlags |= linux.ECHO 63 ld := newLineDiscipline(termios, nil) 64 outBytes := make([]byte, 32) 65 dst := usermem.BytesIOSequence(outBytes) 66 entry := waiter.NewFunctionEntry(waiter.ReadableEvents, func(waiter.EventMask) { 67 ld.inputQueueRead(ctx, dst) 68 }) 69 ld.masterWaiter.EventRegister(&entry) 70 defer ld.masterWaiter.EventUnregister(&entry) 71 inBytes := []byte("hello, tty\n") 72 n, err := ld.inputQueueWrite(ctx, usermem.BytesIOSequence(inBytes)) 73 if err != nil { 74 t.Fatalf("inputQueueWrite: %v", err) 75 } 76 if int(n) != len(inBytes) { 77 t.Fatalf("read wrong length: got %d, want %d", n, len(inBytes)) 78 } 79 outStr := string(outBytes[:n]) 80 inStr := string(inBytes) 81 if outStr != inStr { 82 t.Fatalf("written and read strings do not match: got %q, want %q", outStr, inStr) 83 } 84 } 85 86 func TestEndOfFileHandling(t *testing.T) { 87 ctx := contexttest.Context(t) 88 termios := linux.DefaultReplicaTermios 89 ld := newLineDiscipline(termios, nil) 90 91 // EOF with non-empty read buffer. 92 inBytes := []byte("hello, tty") 93 inBytes = append(inBytes, termios.ControlCharacters[linux.VEOF]) 94 outBytes := make([]byte, 32) 95 dst := usermem.BytesIOSequence(outBytes) 96 // Write to the input queue. 97 nw, err := ld.inputQueueWrite(ctx, usermem.BytesIOSequence(inBytes)) 98 if err != nil { 99 t.Fatalf("error writing to input queue: %v", err) 100 } 101 if nw != int64(len(inBytes)) { 102 t.Fatalf("wrote wrong length: got %d, want %d", nw, len(inBytes)) 103 } 104 105 // Read from the input queue. 106 nr, err := ld.inputQueueRead(ctx, dst) 107 if err != nil { 108 t.Fatalf("error reading from input queue: %v", err) 109 } 110 if nr != int64(len(inBytes)-1) { 111 t.Fatalf("read wrong length: got %d, want %d", nr, len(inBytes)-1) 112 } 113 114 // EOF with empty read buffer. 115 inBytes = []byte{termios.ControlCharacters[linux.VEOF]} 116 outBytes = make([]byte, 32) 117 dst = usermem.BytesIOSequence(outBytes) 118 // Write to the input queue. 119 nw, err = ld.inputQueueWrite(ctx, usermem.BytesIOSequence(inBytes)) 120 if err != nil { 121 t.Fatalf("error writing to input queue: %v", err) 122 } 123 if nw != int64(len(inBytes)) { 124 t.Fatalf("wrote wrong length: got %d, want %d", nw, len(inBytes)) 125 } 126 127 // Read from the input queue. 128 nr, err = ld.inputQueueRead(ctx, dst) 129 if err != nil { 130 t.Fatalf("error reading from input queue: %v", err) 131 } 132 if nr != 0 { 133 t.Fatalf("read length should be zero: got %d", nr) 134 } 135 }