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  }