github.com/SagerNet/gvisor@v0.0.0-20210707092255-7731c139d75c/pkg/sentry/fsimpl/fuse/connection_test.go (about) 1 // Copyright 2020 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 fuse 16 17 import ( 18 "math/rand" 19 "testing" 20 21 "golang.org/x/sys/unix" 22 "github.com/SagerNet/gvisor/pkg/errors/linuxerr" 23 "github.com/SagerNet/gvisor/pkg/sentry/kernel" 24 "github.com/SagerNet/gvisor/pkg/sentry/kernel/auth" 25 ) 26 27 // TestConnectionInitBlock tests if initialization 28 // correctly blocks and unblocks the connection. 29 // Since it's unfeasible to test kernelTask.Block() in unit test, 30 // the code in Call() are not tested here. 31 func TestConnectionInitBlock(t *testing.T) { 32 s := setup(t) 33 defer s.Destroy() 34 35 k := kernel.KernelFromContext(s.Ctx) 36 37 conn, _, err := newTestConnection(s, k, maxActiveRequestsDefault) 38 if err != nil { 39 t.Fatalf("newTestConnection: %v", err) 40 } 41 42 select { 43 case <-conn.initializedChan: 44 t.Fatalf("initializedChan should be blocking before SetInitialized") 45 default: 46 } 47 48 conn.SetInitialized() 49 50 select { 51 case <-conn.initializedChan: 52 default: 53 t.Fatalf("initializedChan should not be blocking after SetInitialized") 54 } 55 } 56 57 func TestConnectionAbort(t *testing.T) { 58 s := setup(t) 59 defer s.Destroy() 60 61 k := kernel.KernelFromContext(s.Ctx) 62 creds := auth.CredentialsFromContext(s.Ctx) 63 task := kernel.TaskFromContext(s.Ctx) 64 65 const numRequests uint64 = 256 66 67 conn, _, err := newTestConnection(s, k, numRequests) 68 if err != nil { 69 t.Fatalf("newTestConnection: %v", err) 70 } 71 72 testObj := &testPayload{ 73 data: rand.Uint32(), 74 } 75 76 var futNormal []*futureResponse 77 78 for i := 0; i < int(numRequests); i++ { 79 req := conn.NewRequest(creds, uint32(i), uint64(i), 0, testObj) 80 fut, err := conn.callFutureLocked(task, req) 81 if err != nil { 82 t.Fatalf("callFutureLocked failed: %v", err) 83 } 84 futNormal = append(futNormal, fut) 85 } 86 87 conn.Abort(s.Ctx) 88 89 // Abort should unblock the initialization channel. 90 // Note: no test requests are actually blocked on `conn.initializedChan`. 91 select { 92 case <-conn.initializedChan: 93 default: 94 t.Fatalf("initializedChan should not be blocking after SetInitialized") 95 } 96 97 // Abort will return ECONNABORTED error to unblocked requests. 98 for _, fut := range futNormal { 99 if fut.getResponse().hdr.Error != -int32(unix.ECONNABORTED) { 100 t.Fatalf("Incorrect error code received for aborted connection: %v", fut.getResponse().hdr.Error) 101 } 102 } 103 104 // After abort, Call() should return directly with ENOTCONN. 105 req := conn.NewRequest(creds, 0, 0, 0, testObj) 106 _, err = conn.Call(task, req) 107 if !linuxerr.Equals(linuxerr.ENOTCONN, err) { 108 t.Fatalf("Incorrect error code received for Call() after connection aborted") 109 } 110 111 }