gvisor.dev/gvisor@v0.0.0-20240520182842-f9d4d51c7e0f/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 "gvisor.dev/gvisor/pkg/errors/linuxerr" 23 "gvisor.dev/gvisor/pkg/marshal/primitive" 24 "gvisor.dev/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 conn, _, err := newTestConnection(s, maxActiveRequestsDefault) 36 if err != nil { 37 t.Fatalf("newTestConnection: %v", err) 38 } 39 40 select { 41 case <-conn.initializedChan: 42 t.Fatalf("initializedChan should be blocking before SetInitialized") 43 default: 44 } 45 46 conn.SetInitialized() 47 48 select { 49 case <-conn.initializedChan: 50 default: 51 t.Fatalf("initializedChan should not be blocking after SetInitialized") 52 } 53 } 54 55 func TestConnectionAbort(t *testing.T) { 56 s := setup(t) 57 defer s.Destroy() 58 59 creds := auth.CredentialsFromContext(s.Ctx) 60 61 const numRequests uint64 = 256 62 63 conn, _, err := newTestConnection(s, numRequests) 64 if err != nil { 65 t.Fatalf("newTestConnection: %v", err) 66 } 67 68 var futNormal []*futureResponse 69 testObj := primitive.Uint32(rand.Uint32()) 70 for i := 0; i < int(numRequests); i++ { 71 req := conn.NewRequest(creds, uint32(i), uint64(i), 0, &testObj) 72 conn.fd.mu.Lock() 73 fut, err := conn.callFutureLocked(req) 74 conn.fd.mu.Unlock() 75 if err != nil { 76 t.Fatalf("callFutureLocked failed: %v", err) 77 } 78 futNormal = append(futNormal, fut) 79 } 80 81 conn.fd.mu.Lock() 82 conn.Abort(s.Ctx) 83 conn.fd.mu.Unlock() 84 85 // Abort should unblock the initialization channel. 86 // Note: no test requests are actually blocked on `conn.initializedChan`. 87 select { 88 case <-conn.initializedChan: 89 default: 90 t.Fatalf("initializedChan should not be blocking after SetInitialized") 91 } 92 93 // Abort will return ECONNABORTED error to unblocked requests. 94 for _, fut := range futNormal { 95 if fut.getResponse().hdr.Error != -int32(unix.ECONNABORTED) { 96 t.Fatalf("Incorrect error code received for aborted connection: %v", fut.getResponse().hdr.Error) 97 } 98 } 99 100 // After abort, Call() should return directly with ENOTCONN. 101 req := conn.NewRequest(creds, 0, 0, 0, &testObj) 102 _, err = conn.Call(s.Ctx, req) 103 if !linuxerr.Equals(linuxerr.ENOTCONN, err) { 104 t.Fatalf("Incorrect error code received for Call() after connection aborted") 105 } 106 107 }