github.com/inspektor-gadget/inspektor-gadget@v0.28.1/pkg/gadgets/snapshot/socket/tracer/tracer_test.go (about)

     1  // Copyright 2022-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  //go:build linux
    16  // +build linux
    17  
    18  package tracer
    19  
    20  import (
    21  	"fmt"
    22  	"net"
    23  	"testing"
    24  
    25  	"github.com/stretchr/testify/require"
    26  
    27  	utilstest "github.com/inspektor-gadget/inspektor-gadget/internal/test"
    28  	"github.com/inspektor-gadget/inspektor-gadget/pkg/gadgets/snapshot/socket/types"
    29  	eventtypes "github.com/inspektor-gadget/inspektor-gadget/pkg/types"
    30  )
    31  
    32  func TestSocketTracerCreate(t *testing.T) {
    33  	t.Parallel()
    34  
    35  	utilstest.RequireRoot(t)
    36  
    37  	tracer, err := NewTracer(types.ALL)
    38  	require.Nil(t, err, "creating tracer: %v", err)
    39  
    40  	tracer.CloseIters()
    41  }
    42  
    43  type testCase struct {
    44  	name          string
    45  	proto         types.Proto
    46  	addr          string
    47  	port          int
    48  	expectedEvent func(info *utilstest.RunnerInfo, _ any) *types.Event
    49  	socketCreator func(addr string, port int) error
    50  }
    51  
    52  func TestSnapshotSocket(t *testing.T) {
    53  	t.Parallel()
    54  
    55  	utilstest.RequireRoot(t)
    56  
    57  	cases := []testCase{
    58  		{
    59  			name:  "listen_tcp_v4",
    60  			proto: types.TCP,
    61  			addr:  "127.0.0.1",
    62  			port:  8082,
    63  			expectedEvent: func(info *utilstest.RunnerInfo, _ any) *types.Event {
    64  				return &types.Event{
    65  					Event:       eventtypes.Event{Type: eventtypes.NORMAL},
    66  					WithNetNsID: eventtypes.WithNetNsID{NetNsID: info.NetworkNsID},
    67  					Protocol:    "TCP",
    68  					Status:      "LISTEN",
    69  					SrcEndpoint: eventtypes.L4Endpoint{
    70  						L3Endpoint: eventtypes.L3Endpoint{
    71  							Addr:    "127.0.0.1",
    72  							Version: 4,
    73  						},
    74  						Port: 8082,
    75  					},
    76  					DstEndpoint: eventtypes.L4Endpoint{
    77  						L3Endpoint: eventtypes.L3Endpoint{
    78  							// There is no connection in this test, so there remote address is null.
    79  							Addr:    "0.0.0.0",
    80  							Version: 4,
    81  						},
    82  					},
    83  				}
    84  			},
    85  			socketCreator: func(addr string, port int) error {
    86  				conn, err := net.Listen("tcp", fmt.Sprintf("%s:%d", addr, port))
    87  				if err != nil {
    88  					return fmt.Errorf("listening to %s: %w", addr, err)
    89  				}
    90  				t.Cleanup(func() { conn.Close() })
    91  
    92  				return nil
    93  			},
    94  		},
    95  		{
    96  			name:  "listen_tcp_v6",
    97  			proto: types.TCP,
    98  			addr:  "::1",
    99  			port:  8082,
   100  			expectedEvent: func(info *utilstest.RunnerInfo, _ any) *types.Event {
   101  				return &types.Event{
   102  					Event:       eventtypes.Event{Type: eventtypes.NORMAL},
   103  					WithNetNsID: eventtypes.WithNetNsID{NetNsID: info.NetworkNsID},
   104  					Protocol:    "TCP",
   105  					Status:      "LISTEN",
   106  					SrcEndpoint: eventtypes.L4Endpoint{
   107  						L3Endpoint: eventtypes.L3Endpoint{
   108  							Addr:    "::1",
   109  							Version: 6,
   110  						},
   111  						Port: 8082,
   112  					},
   113  					DstEndpoint: eventtypes.L4Endpoint{
   114  						L3Endpoint: eventtypes.L3Endpoint{
   115  							// There is no connection in this test, so the remote address is null.
   116  							Addr:    "::",
   117  							Version: 6,
   118  						},
   119  					},
   120  				}
   121  			},
   122  			socketCreator: func(addr string, port int) error {
   123  				conn, err := net.Listen("tcp", fmt.Sprintf("[%s]:%d", addr, port))
   124  				if err != nil {
   125  					return fmt.Errorf("listening to %s: %w", addr, err)
   126  				}
   127  				t.Cleanup(func() { conn.Close() })
   128  
   129  				return nil
   130  			},
   131  		},
   132  		{
   133  			name:  "listen_udp_v4",
   134  			proto: types.UDP,
   135  			addr:  "127.0.0.1",
   136  			port:  8082,
   137  			expectedEvent: func(info *utilstest.RunnerInfo, _ any) *types.Event {
   138  				return &types.Event{
   139  					Event:       eventtypes.Event{Type: eventtypes.NORMAL},
   140  					WithNetNsID: eventtypes.WithNetNsID{NetNsID: info.NetworkNsID},
   141  					Protocol:    "UDP",
   142  					Status:      "INACTIVE",
   143  					SrcEndpoint: eventtypes.L4Endpoint{
   144  						L3Endpoint: eventtypes.L3Endpoint{
   145  							Addr:    "127.0.0.1",
   146  							Version: 4,
   147  						},
   148  						Port: 8082,
   149  					},
   150  					DstEndpoint: eventtypes.L4Endpoint{
   151  						L3Endpoint: eventtypes.L3Endpoint{
   152  							// There is no connection in this test, so there remote address is null.
   153  							Addr:    "0.0.0.0",
   154  							Version: 4,
   155  						},
   156  					},
   157  				}
   158  			},
   159  			socketCreator: func(addr string, port int) error {
   160  				conn, err := net.ListenUDP("udp", &net.UDPAddr{
   161  					Port: port,
   162  					IP:   net.ParseIP(addr),
   163  				})
   164  				if err != nil {
   165  					return fmt.Errorf("listening to %s: %w", addr, err)
   166  				}
   167  				t.Cleanup(func() { conn.Close() })
   168  
   169  				return nil
   170  			},
   171  		},
   172  		{
   173  			name:  "listen_udp_v6",
   174  			proto: types.UDP,
   175  			addr:  "::1",
   176  			port:  8082,
   177  			expectedEvent: func(info *utilstest.RunnerInfo, _ any) *types.Event {
   178  				return &types.Event{
   179  					Event:       eventtypes.Event{Type: eventtypes.NORMAL},
   180  					WithNetNsID: eventtypes.WithNetNsID{NetNsID: info.NetworkNsID},
   181  					Protocol:    "UDP",
   182  					Status:      "INACTIVE",
   183  					SrcEndpoint: eventtypes.L4Endpoint{
   184  						L3Endpoint: eventtypes.L3Endpoint{
   185  							Addr:    "::1",
   186  							Version: 6,
   187  						},
   188  						Port: 8082,
   189  					},
   190  					DstEndpoint: eventtypes.L4Endpoint{
   191  						L3Endpoint: eventtypes.L3Endpoint{
   192  							// There is no connection in this test, so there remote address is null.
   193  							Addr:    "::",
   194  							Version: 6,
   195  						},
   196  					},
   197  				}
   198  			},
   199  			socketCreator: func(addr string, port int) error {
   200  				conn, err := net.ListenUDP("udp6", &net.UDPAddr{
   201  					Port: port,
   202  					IP:   net.ParseIP(addr),
   203  				})
   204  				if err != nil {
   205  					return fmt.Errorf("listening to %s: %w", addr, err)
   206  				}
   207  				t.Cleanup(func() { conn.Close() })
   208  
   209  				return nil
   210  			},
   211  		},
   212  	}
   213  
   214  	for _, c := range cases {
   215  		c := c
   216  		t.Run(c.name, func(t *testing.T) {
   217  			t.Parallel()
   218  
   219  			runner := utilstest.NewRunnerWithTest(t, nil)
   220  			utilstest.RunWithRunner(t, runner, func() error {
   221  				return c.socketCreator(c.addr, c.port)
   222  			})
   223  
   224  			tracer, err := NewTracer(c.proto)
   225  			require.NoError(t, err, "creating tracer: %v", err)
   226  			defer tracer.CloseIters()
   227  
   228  			evs, err := tracer.runCollector(uint32(runner.Info.Tid), runner.Info.NetworkNsID)
   229  			require.NoError(t, err, "running collector: %v", err)
   230  
   231  			events := make([]types.Event, len(evs))
   232  			for i, ev := range evs {
   233  				events[i] = *ev
   234  
   235  				// This is hard to guess the inode number, let's normalize it for the
   236  				// moment.
   237  				events[i].InodeNumber = 0
   238  			}
   239  
   240  			utilstest.ExpectAtLeastOneEvent(c.expectedEvent)(t, runner.Info, nil, events)
   241  		})
   242  	}
   243  }