github.com/inspektor-gadget/inspektor-gadget@v0.28.1/pkg/ig-manager/ig-manager_test.go (about)

     1  // Copyright 2021-2023 The Inspektor Gadget authors
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package igmanager
    16  
    17  import (
    18  	"context"
    19  	"fmt"
    20  	"os"
    21  	"strconv"
    22  	"testing"
    23  	"time"
    24  
    25  	containercollection "github.com/inspektor-gadget/inspektor-gadget/pkg/container-collection"
    26  	containerutilsTypes "github.com/inspektor-gadget/inspektor-gadget/pkg/container-utils/types"
    27  
    28  	// Yes, not the better naming for these two.
    29  	utilstest "github.com/inspektor-gadget/inspektor-gadget/internal/test"
    30  	"github.com/inspektor-gadget/inspektor-gadget/pkg/container-utils/testutils"
    31  )
    32  
    33  const (
    34  	// The product of these to contansts defines the maximum wait
    35  	// time before failing the checkFdList condition. These should
    36  	// be large enough to allow all resources to be freeded. These
    37  	// only affect the duration of the failing tests, hence it's not
    38  	// a big problem to have big delays here.
    39  	checkFdListInterval = 100 * time.Millisecond
    40  	checkFdListAttempts = 20
    41  )
    42  
    43  func TestBasic(t *testing.T) {
    44  	utilstest.RequireRoot(t)
    45  
    46  	igManager, err := NewManager(nil)
    47  	if err != nil {
    48  		t.Fatalf("Failed to start ig manager: %s", err)
    49  	}
    50  	igManager.Close()
    51  }
    52  
    53  func TestContainersMap(t *testing.T) {
    54  	utilstest.RequireRoot(t)
    55  
    56  	igManager, err := NewManager(nil)
    57  	if err != nil {
    58  		t.Fatalf("Failed to start ig manager: %s", err)
    59  	}
    60  	defer igManager.Close()
    61  
    62  	if m := igManager.ContainersMap(); m == nil {
    63  		t.Fatal("container map is nil")
    64  	}
    65  }
    66  
    67  func TestMountNsMap(t *testing.T) {
    68  	utilstest.RequireRoot(t)
    69  
    70  	igManager, err := NewManager(nil)
    71  	if err != nil {
    72  		t.Fatalf("Failed to start ig manager: %s", err)
    73  	}
    74  	defer igManager.Close()
    75  
    76  	id := "foo"
    77  
    78  	m, err := igManager.CreateMountNsMap(id, containercollection.ContainerSelector{})
    79  	if err != nil {
    80  		t.Fatalf("Failed to create mount namespace map: %s", err)
    81  	}
    82  	if m == nil {
    83  		t.Fatalf("mount namespace map is nil: %s", err)
    84  	}
    85  
    86  	err = igManager.RemoveMountNsMap(id)
    87  	if err != nil {
    88  		t.Fatalf("Failed to remove mount namespace map: %s", err)
    89  	}
    90  }
    91  
    92  func currentFdList(t *testing.T) (ret string) {
    93  	files, err := os.ReadDir("/proc/self/fd")
    94  	if err != nil {
    95  		t.Fatalf("Failed to list fds: %s", err)
    96  	}
    97  	for _, file := range files {
    98  		fd, err := strconv.Atoi(file.Name())
    99  		if err != nil {
   100  			continue
   101  		}
   102  		dest, err := os.Readlink("/proc/self/fd/" + file.Name())
   103  		if err != nil {
   104  			continue
   105  		}
   106  		ret += fmt.Sprintf("%d: %s\n", fd, dest)
   107  	}
   108  	return
   109  }
   110  
   111  func checkFdList(t *testing.T, initialFdList string, attempts int, sleep time.Duration) {
   112  	for i := 0; ; i++ {
   113  		finalFdList := currentFdList(t)
   114  		if initialFdList == finalFdList {
   115  			return
   116  		}
   117  
   118  		if i >= (attempts - 1) {
   119  			t.Fatalf("After %d attempts, fd leaked:\n%s\n%s", attempts, initialFdList, finalFdList)
   120  		}
   121  
   122  		time.Sleep(sleep)
   123  	}
   124  }
   125  
   126  // TestClose tests that resources aren't leaked after calling Close()
   127  func TestClose(t *testing.T) {
   128  	utilstest.RequireRoot(t)
   129  
   130  	c := testutils.NewDockerContainer("test-ig-close", "sleep inf", testutils.WithoutLogs())
   131  	c.Start(t)
   132  	t.Cleanup(func() {
   133  		c.Stop(t)
   134  	})
   135  
   136  	initialFdList := currentFdList(t)
   137  
   138  	for i := 0; i < 4; i++ {
   139  		igManager, err := NewManager([]*containerutilsTypes.RuntimeConfig{{Name: "docker"}})
   140  		if err != nil {
   141  			t.Fatalf("Failed to start ig manager: %s", err)
   142  		}
   143  
   144  		if i%2 == 0 {
   145  			testutils.RunDockerFailedContainer(context.Background(), t)
   146  		}
   147  
   148  		igManager.Close()
   149  	}
   150  
   151  	checkFdList(t, initialFdList, checkFdListAttempts, checkFdListInterval)
   152  }