summaryrefslogtreecommitdiff
path: root/pkg/bindings/test/resource_test.go
diff options
context:
space:
mode:
authorJhon Honce <jhonce@redhat.com>2021-08-02 14:09:55 -0700
committerJhon Honce <jhonce@redhat.com>2021-08-24 16:36:10 -0700
commit1dc6d14735eef1e51368103aefba3d7c704dcfe3 (patch)
tree61109c0b3d99cb3bcf85f53b0f8a837a995b0569 /pkg/bindings/test/resource_test.go
parente9daaf62e3921b8c696f3abd92f001a9447c8aa1 (diff)
downloadpodman-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.go116
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
+}