summaryrefslogtreecommitdiff
path: root/pkg/bindings/test
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
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')
-rw-r--r--pkg/bindings/test/attach_test.go5
-rw-r--r--pkg/bindings/test/common_test.go21
-rw-r--r--pkg/bindings/test/resource_test.go116
3 files changed, 134 insertions, 8 deletions
diff --git a/pkg/bindings/test/attach_test.go b/pkg/bindings/test/attach_test.go
index fbdf18d44..5c3ec48e4 100644
--- a/pkg/bindings/test/attach_test.go
+++ b/pkg/bindings/test/attach_test.go
@@ -81,10 +81,9 @@ var _ = Describe("Podman containers attach", func() {
tickTock := time.NewTimer(2 * time.Second)
go func() {
<-tickTock.C
- timeout := uint(5)
- err := containers.Stop(bt.conn, ctnr.ID, new(containers.StopOptions).WithTimeout(timeout))
+ err := containers.Stop(bt.conn, ctnr.ID, new(containers.StopOptions).WithTimeout(uint(5)))
if err != nil {
- GinkgoWriter.Write([]byte(err.Error()))
+ fmt.Fprint(GinkgoWriter, err.Error())
}
}()
diff --git a/pkg/bindings/test/common_test.go b/pkg/bindings/test/common_test.go
index 9bac4b620..91ebe21fc 100644
--- a/pkg/bindings/test/common_test.go
+++ b/pkg/bindings/test/common_test.go
@@ -8,6 +8,7 @@ import (
"os/exec"
"path/filepath"
"strings"
+ "time"
"github.com/containers/podman/v3/libpod/define"
. "github.com/containers/podman/v3/pkg/bindings"
@@ -150,11 +151,21 @@ func createTempDirInTempDir() (string, error) {
}
func (b *bindingTest) startAPIService() *gexec.Session {
- var (
- cmd []string
- )
- cmd = append(cmd, "--log-level=debug", "--events-backend=file", "system", "service", "--timeout=0", b.sock)
- return b.runPodman(cmd)
+ cmd := []string{"--log-level=debug", "--events-backend=file", "system", "service", "--timeout=0", b.sock}
+ session := b.runPodman(cmd)
+
+ sock := strings.TrimPrefix(b.sock, "unix://")
+ for i := 0; i < 10; i++ {
+ if _, err := os.Stat(sock); err != nil {
+ if !os.IsNotExist(err) {
+ break
+ }
+ time.Sleep(time.Second)
+ continue
+ }
+ break
+ }
+ return session
}
func (b *bindingTest) cleanup() {
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
+}