|
5 | 5 |
|
6 | 6 | // This doesn't need BPF, but it's built with this tag to only run with |
7 | 7 | // system-probe tests. |
8 | | -//go:build test && linux_bpf |
| 8 | +//go:build test && linux_bpf && !dd_discovery_cgo |
9 | 9 |
|
10 | 10 | package module |
11 | 11 |
|
12 | 12 | import ( |
13 | | - "bytes" |
14 | | - "context" |
15 | | - "encoding/json" |
16 | 13 | "net" |
17 | | - "net/http" |
18 | | - "net/http/httptest" |
19 | 14 | "os" |
20 | 15 | "os/exec" |
21 | 16 | "path/filepath" |
22 | 17 | "strconv" |
23 | 18 | "strings" |
24 | | - "syscall" |
25 | 19 | "testing" |
26 | 20 |
|
27 | | - gorillamux "github.com/gorilla/mux" |
28 | 21 | "github.com/prometheus/procfs" |
29 | | - "github.com/shirou/gopsutil/v4/process" |
30 | 22 | "github.com/stretchr/testify/require" |
31 | | - "golang.org/x/sys/unix" |
32 | 23 |
|
33 | | - "github.com/DataDog/datadog-agent/pkg/discovery/core" |
34 | 24 | "github.com/DataDog/datadog-agent/pkg/discovery/language" |
35 | | - "github.com/DataDog/datadog-agent/pkg/discovery/model" |
36 | 25 | "github.com/DataDog/datadog-agent/pkg/network" |
37 | 26 | "github.com/DataDog/datadog-agent/pkg/network/protocols/http/testutil" |
38 | | - usmtestutil "github.com/DataDog/datadog-agent/pkg/network/usm/testutil" |
39 | | - "github.com/DataDog/datadog-agent/pkg/system-probe/api/module" |
40 | | - "github.com/DataDog/datadog-agent/pkg/system-probe/config" |
41 | 27 | "github.com/DataDog/datadog-agent/pkg/util/kernel" |
42 | 28 | ) |
43 | 29 |
|
44 | | -func findService(pid int, services []model.Service) *model.Service { |
45 | | - for _, s := range services { |
46 | | - if s.PID == pid { |
47 | | - return &s |
48 | | - } |
49 | | - } |
50 | | - |
51 | | - return nil |
52 | | -} |
53 | | - |
54 | | -type testDiscoveryModule struct { |
55 | | - url string |
56 | | -} |
57 | | - |
58 | | -func setupDiscoveryModule(t *testing.T) *testDiscoveryModule { |
59 | | - t.Helper() |
60 | | - mux := gorillamux.NewRouter() |
61 | | - |
62 | | - mod, err := NewDiscoveryModule(nil, module.FactoryDependencies{}) |
63 | | - require.NoError(t, err) |
64 | | - discovery := mod.(*discovery) |
65 | | - |
66 | | - discovery.Register(module.NewRouter(string(config.DiscoveryModule), mux)) |
67 | | - t.Cleanup(discovery.Close) |
68 | | - |
69 | | - srv := httptest.NewServer(mux) |
70 | | - t.Cleanup(srv.Close) |
71 | | - |
72 | | - return &testDiscoveryModule{ |
73 | | - url: srv.URL, |
74 | | - } |
75 | | -} |
76 | | - |
77 | | -// makeRequest wraps the request to the discovery module, setting the JSON body if provided, |
78 | | -// and returning the response as the given type. |
79 | | -func makeRequest[T any](t require.TestingT, url string, params *core.Params) *T { |
80 | | - var body *bytes.Buffer |
81 | | - if params != nil { |
82 | | - jsonData, err := params.ToJSON() |
83 | | - require.NoError(t, err, "failed to serialize params to JSON") |
84 | | - body = bytes.NewBuffer(jsonData) |
85 | | - } |
86 | | - |
87 | | - var req *http.Request |
88 | | - var err error |
89 | | - if body != nil { |
90 | | - req, err = http.NewRequest(http.MethodPost, url, body) |
91 | | - req.Header.Set("Content-Type", "application/json") |
92 | | - } else { |
93 | | - req, err = http.NewRequest(http.MethodPost, url, nil) |
94 | | - } |
95 | | - require.NoError(t, err, "failed to create request") |
96 | | - |
97 | | - resp, err := http.DefaultClient.Do(req) |
98 | | - require.NoError(t, err, "failed to send request") |
99 | | - defer resp.Body.Close() |
100 | | - |
101 | | - res := new(T) |
102 | | - err = json.NewDecoder(resp.Body).Decode(res) |
103 | | - require.NoError(t, err, "failed to decode response") |
104 | | - |
105 | | - return res |
106 | | -} |
107 | | - |
108 | | -// getRunningPids wraps the process.Pids function, returning a slice of ints |
109 | | -// that can be used as the pids query param. |
110 | | -func getRunningPids(t require.TestingT) []int32 { |
111 | | - pids, err := process.Pids() |
112 | | - require.NoError(t, err) |
113 | | - return pids |
114 | | -} |
115 | | - |
116 | | -func startTCPServer(t *testing.T, proto string, address string) (*os.File, *net.TCPAddr) { |
117 | | - listener, err := net.Listen(proto, address) |
118 | | - require.NoError(t, err) |
119 | | - t.Cleanup(func() { _ = listener.Close() }) |
120 | | - tcpAddr := listener.Addr().(*net.TCPAddr) |
121 | | - |
122 | | - f, err := listener.(*net.TCPListener).File() |
123 | | - defer listener.Close() |
124 | | - require.NoError(t, err) |
125 | | - |
126 | | - return f, tcpAddr |
127 | | -} |
128 | | - |
129 | | -func startTCPClient(t *testing.T, proto string, server *net.TCPAddr) (*os.File, *net.TCPAddr) { |
130 | | - client, err := net.DialTCP(proto, nil, server) |
131 | | - require.NoError(t, err) |
132 | | - t.Cleanup(func() { _ = client.Close() }) |
133 | | - |
134 | | - f, err := client.File() |
135 | | - defer client.Close() |
136 | | - require.NoError(t, err) |
137 | | - |
138 | | - return f, client.LocalAddr().(*net.TCPAddr) |
139 | | -} |
140 | | - |
141 | | -func startUDPServer(t *testing.T, proto string, address string) (*os.File, *net.UDPAddr) { |
142 | | - lnPacket, err := net.ListenPacket(proto, address) |
143 | | - require.NoError(t, err) |
144 | | - t.Cleanup(func() { _ = lnPacket.Close() }) |
145 | | - |
146 | | - f, err := lnPacket.(*net.UDPConn).File() |
147 | | - defer lnPacket.Close() |
148 | | - require.NoError(t, err) |
149 | | - |
150 | | - return f, lnPacket.LocalAddr().(*net.UDPAddr) |
151 | | -} |
152 | | - |
153 | | -func startUDPClient(t *testing.T, proto string, server *net.UDPAddr) (*os.File, *net.UDPAddr) { |
154 | | - udpClient, err := net.DialUDP(proto, nil, server) |
155 | | - require.NoError(t, err) |
156 | | - t.Cleanup(func() { _ = udpClient.Close() }) |
157 | | - |
158 | | - f, err := udpClient.File() |
159 | | - defer udpClient.Close() |
160 | | - require.NoError(t, err) |
161 | | - |
162 | | - return f, udpClient.LocalAddr().(*net.UDPAddr) |
163 | | -} |
164 | | - |
165 | | -func disableCloseOnExec(t *testing.T, f *os.File) { |
166 | | - _, _, syserr := syscall.Syscall(syscall.SYS_FCNTL, f.Fd(), syscall.F_SETFD, 0) |
167 | | - require.Equal(t, syscall.Errno(0x0), syserr) |
168 | | -} |
169 | | - |
170 | | -func startProcessWithFile(t *testing.T, f *os.File) *exec.Cmd { |
171 | | - ctx, cancel := context.WithCancel(context.Background()) |
172 | | - |
173 | | - // Disable close-on-exec so that the process gets it |
174 | | - t.Cleanup(func() { f.Close() }) |
175 | | - disableCloseOnExec(t, f) |
176 | | - |
177 | | - cmd := exec.CommandContext(ctx, "sleep", "1000") |
178 | | - t.Cleanup(func() { |
179 | | - cancel() |
180 | | - _ = cmd.Wait() |
181 | | - }) |
182 | | - err := cmd.Start() |
183 | | - require.NoError(t, err) |
184 | | - f.Close() |
185 | | - |
186 | | - return cmd |
187 | | -} |
188 | | - |
189 | | -func makeAlias(t *testing.T, alias string, serverBin string) string { |
190 | | - binDir := filepath.Dir(serverBin) |
191 | | - aliasPath := filepath.Join(binDir, alias) |
192 | | - |
193 | | - target, err := os.Readlink(aliasPath) |
194 | | - if err == nil && target == serverBin { |
195 | | - return aliasPath |
196 | | - } |
197 | | - |
198 | | - os.Remove(aliasPath) |
199 | | - err = os.Symlink(serverBin, aliasPath) |
200 | | - require.NoError(t, err) |
201 | | - |
202 | | - return aliasPath |
203 | | -} |
204 | | - |
205 | | -func buildFakeServer(t *testing.T) string { |
206 | | - curDir, err := testutil.CurDir() |
207 | | - require.NoError(t, err) |
208 | | - serverBin, err := usmtestutil.BuildGoBinaryWrapper(filepath.Join(curDir, "testutil"), "fake_server") |
209 | | - require.NoError(t, err) |
210 | | - |
211 | | - for _, alias := range []string{"java", "node", "sshd", "dotnet"} { |
212 | | - makeAlias(t, alias, serverBin) |
213 | | - } |
214 | | - |
215 | | - return filepath.Dir(serverBin) |
216 | | -} |
217 | | - |
218 | | -func newDiscovery() *discovery { |
219 | | - mod, err := NewDiscoveryModule(nil, module.FactoryDependencies{}) |
220 | | - if err != nil { |
221 | | - panic(err) |
222 | | - } |
223 | | - return mod.(*discovery) |
224 | | -} |
225 | | - |
226 | 30 | // addSockets adds only listening sockets to a map to be used for later looksups. |
227 | 31 | func addSockets[P procfs.NetTCP | procfs.NetUDP](sockMap map[uint64]socketInfo, sockets P, |
228 | 32 | family network.ConnectionFamily, ctype network.ConnectionType, state uint64, |
@@ -315,21 +119,6 @@ func BenchmarkGetNSInfoOld(b *testing.B) { |
315 | 119 | } |
316 | 120 | } |
317 | 121 |
|
318 | | -func createTracerMemfd(t *testing.T, data []byte) int { |
319 | | - t.Helper() |
320 | | - fd, err := unix.MemfdCreate("datadog-tracer-info-xxx", 0) |
321 | | - require.NoError(t, err) |
322 | | - t.Cleanup(func() { unix.Close(fd) }) |
323 | | - err = unix.Ftruncate(fd, int64(len(data))) |
324 | | - require.NoError(t, err) |
325 | | - mappedData, err := unix.Mmap(fd, 0, len(data), unix.PROT_READ|unix.PROT_WRITE, unix.MAP_SHARED) |
326 | | - require.NoError(t, err) |
327 | | - copy(mappedData, data) |
328 | | - err = unix.Munmap(mappedData) |
329 | | - require.NoError(t, err) |
330 | | - return fd |
331 | | -} |
332 | | - |
333 | 122 | func TestValidInvalidTracerMetadata(t *testing.T) { |
334 | 123 | discovery := newDiscovery() |
335 | 124 | require.NotEmpty(t, discovery) |
|
0 commit comments