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  }