diff options
author | Jhon Honce <jhonce@redhat.com> | 2021-08-02 14:09:55 -0700 |
---|---|---|
committer | Jhon Honce <jhonce@redhat.com> | 2021-08-24 16:36:10 -0700 |
commit | 1dc6d14735eef1e51368103aefba3d7c704dcfe3 (patch) | |
tree | 61109c0b3d99cb3bcf85f53b0f8a837a995b0569 /pkg/bindings/test/resource_test.go | |
parent | e9daaf62e3921b8c696f3abd92f001a9447c8aa1 (diff) | |
download | podman-1dc6d14735eef1e51368103aefba3d7c704dcfe3.tar.gz podman-1dc6d14735eef1e51368103aefba3d7c704dcfe3.tar.bz2 podman-1dc6d14735eef1e51368103aefba3d7c704dcfe3.zip |
Fix file descriptor leaks and add test
* Add response.Body.Close() where needed to release HTTP
connections to API server.
* Add tests to ensure no general leaks occur. 100% coverage would be
required to ensure no leaks on any call.
* Update code comments to be godoc correct
Signed-off-by: Jhon Honce <jhonce@redhat.com>
Diffstat (limited to 'pkg/bindings/test/resource_test.go')
-rw-r--r-- | pkg/bindings/test/resource_test.go | 116 |
1 files changed, 116 insertions, 0 deletions
diff --git a/pkg/bindings/test/resource_test.go b/pkg/bindings/test/resource_test.go new file mode 100644 index 000000000..b12d1ccd6 --- /dev/null +++ b/pkg/bindings/test/resource_test.go @@ -0,0 +1,116 @@ +package test_bindings + +import ( + "context" + "fmt" + "io/fs" + "os" + "os/exec" + "path/filepath" + "reflect" + "strconv" + "syscall" + + "github.com/containers/podman/v3/pkg/bindings" + "github.com/containers/podman/v3/pkg/bindings/containers" + "github.com/containers/podman/v3/pkg/bindings/images" + "github.com/containers/podman/v3/pkg/bindings/pods" + "github.com/containers/podman/v3/pkg/bindings/system" + . "github.com/onsi/ginkgo" + . "github.com/onsi/gomega" + . "github.com/onsi/gomega/gexec" +) + +var _ = Describe("Verify Podman resources", func() { + var ( + bt *bindingTest + s *Session + ) + + BeforeEach(func() { + bt = newBindingTest() + s = bt.startAPIService() + err := bt.NewConnection() + Expect(err).ShouldNot(HaveOccurred()) + }) + + AfterEach(func() { + s.Kill() + bt.cleanup() + }) + + It("no leaked connections", func() { + conn, err := bindings.NewConnection(context.Background(), bt.sock) + Expect(err).ShouldNot(HaveOccurred()) + + // Record details on open file descriptors before using API + buffer := lsof() + + // Record open fd from /proc + start, err := readProc() + Expect(err).ShouldNot(HaveOccurred()) + + // Run some operations + _, err = system.Info(conn, nil) + Expect(err).ShouldNot(HaveOccurred()) + _, err = images.List(conn, nil) + Expect(err).ShouldNot(HaveOccurred()) + _, err = containers.List(conn, nil) + Expect(err).ShouldNot(HaveOccurred()) + _, err = pods.List(conn, nil) + Expect(err).ShouldNot(HaveOccurred()) + + podman, _ := bindings.GetClient(conn) + podman.Client.CloseIdleConnections() + + // Record open fd from /proc + finished, err := readProc() + Expect(err).ShouldNot(HaveOccurred()) + if !reflect.DeepEqual(finished, start) { + fmt.Fprintf(GinkgoWriter, "Open FDs:\nlsof Before:\n%s\n", buffer) + + // Record details on open file descriptors after using API + buffer := lsof() + fmt.Fprintf(GinkgoWriter, "lsof After:\n%s\n", buffer) + + // We know test has failed. Easier to let ginkgo format output. + Expect(finished).Should(Equal(start)) + } + }) +}) + +func lsof() string { + lsof := exec.Command("lsof", "+E", "-p", strconv.Itoa(os.Getpid())) + buffer, err := lsof.Output() + Expect(err).ShouldNot(HaveOccurred()) + return string(buffer) +} + +func readProc() ([]string, error) { + syscall.Sync() + + names := make([]string, 0) + err := filepath.WalkDir(fmt.Sprintf("/proc/%d/fd", os.Getpid()), + func(path string, d fs.DirEntry, err error) error { + name := path + " -> " + + switch { + case d.IsDir(): + return nil + case err != nil: + name += err.Error() + case d.Type()&fs.ModeSymlink != 0: + n, err := os.Readlink(path) + if err != nil && !os.IsNotExist(err) { + return err + } + if n == "" { + n = d.Type().String() + } + name += n + } + names = append(names, name) + return nil + }) + return names, err +} |