github.com/containers/podman/v4@v4.9.4/pkg/bindings/test/resource_test.go (about) 1 package bindings_test 2 3 import ( 4 "context" 5 "fmt" 6 "io/fs" 7 "os" 8 "os/exec" 9 "path/filepath" 10 "reflect" 11 "strconv" 12 "syscall" 13 14 "github.com/containers/podman/v4/pkg/bindings" 15 "github.com/containers/podman/v4/pkg/bindings/containers" 16 "github.com/containers/podman/v4/pkg/bindings/images" 17 "github.com/containers/podman/v4/pkg/bindings/pods" 18 "github.com/containers/podman/v4/pkg/bindings/system" 19 . "github.com/onsi/ginkgo/v2" 20 . "github.com/onsi/gomega" 21 . "github.com/onsi/gomega/gexec" 22 ) 23 24 var _ = Describe("Verify Podman resources", func() { 25 var ( 26 bt *bindingTest 27 s *Session 28 ) 29 30 BeforeEach(func() { 31 bt = newBindingTest() 32 s = bt.startAPIService() 33 err := bt.NewConnection() 34 Expect(err).ShouldNot(HaveOccurred()) 35 }) 36 37 AfterEach(func() { 38 s.Kill() 39 bt.cleanup() 40 }) 41 42 It("no leaked connections", func() { 43 conn, err := bindings.NewConnection(context.Background(), bt.sock) 44 Expect(err).ShouldNot(HaveOccurred()) 45 46 // Record details on open file descriptors before using API 47 buffer := lsof() 48 49 // Record open fd from /proc 50 start, err := readProc() 51 Expect(err).ShouldNot(HaveOccurred()) 52 53 // Run some operations 54 _, err = system.Info(conn, nil) 55 Expect(err).ShouldNot(HaveOccurred()) 56 _, err = images.List(conn, nil) 57 Expect(err).ShouldNot(HaveOccurred()) 58 _, err = containers.List(conn, nil) 59 Expect(err).ShouldNot(HaveOccurred()) 60 _, err = pods.List(conn, nil) 61 Expect(err).ShouldNot(HaveOccurred()) 62 63 podman, _ := bindings.GetClient(conn) 64 podman.Client.CloseIdleConnections() 65 66 // Record open fd from /proc 67 finished, err := readProc() 68 Expect(err).ShouldNot(HaveOccurred()) 69 if !reflect.DeepEqual(finished, start) { 70 fmt.Fprintf(GinkgoWriter, "Open FDs:\nlsof Before:\n%s\n", buffer) 71 72 // Record details on open file descriptors after using API 73 buffer := lsof() 74 fmt.Fprintf(GinkgoWriter, "lsof After:\n%s\n", buffer) 75 76 // We know test has failed. Easier to let ginkgo format output. 77 Expect(finished).Should(Equal(start)) 78 } 79 }) 80 }) 81 82 func lsof() string { 83 lsof := exec.Command("lsof", "+E", "-p", strconv.Itoa(os.Getpid())) 84 buffer, err := lsof.Output() 85 Expect(err).ShouldNot(HaveOccurred()) 86 return string(buffer) 87 } 88 89 func readProc() ([]string, error) { 90 syscall.Sync() 91 92 names := make([]string, 0) 93 err := filepath.WalkDir(fmt.Sprintf("/proc/%d/fd", os.Getpid()), 94 func(path string, d fs.DirEntry, err error) error { 95 name := path + " -> " 96 97 switch { 98 case d.IsDir(): 99 return nil 100 case err != nil: 101 name += err.Error() 102 case d.Type()&fs.ModeSymlink != 0: 103 n, err := os.Readlink(path) 104 if err != nil && !os.IsNotExist(err) { 105 return err 106 } 107 if n == "" { 108 n = d.Type().String() 109 } 110 name += n 111 } 112 names = append(names, name) 113 return nil 114 }) 115 return names, err 116 }