Skip to content

Commit 7701486

Browse files
committed
test(internal/utils/executil): add unit testing for exec
1 parent 72372ed commit 7701486

1 file changed

Lines changed: 165 additions & 0 deletions

File tree

Lines changed: 165 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,165 @@
1+
// Copyright 2026 The HuaTuo 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 executil
16+
17+
import (
18+
"bytes"
19+
"fmt"
20+
"os"
21+
"path/filepath"
22+
"runtime"
23+
"testing"
24+
25+
"huatuo-bamai/internal/procfs"
26+
27+
"github.com/stretchr/testify/assert"
28+
)
29+
30+
func withProcRoot(t *testing.T, root string) {
31+
originalPrefix := filepath.Dir(procfs.DefaultPath())
32+
procfs.RootPrefix(root)
33+
t.Cleanup(func() { procfs.RootPrefix(originalPrefix) })
34+
}
35+
36+
func writeCmdline(t *testing.T, procRoot string, pid uint32, data []byte) {
37+
path := filepath.Join(procRoot, fmt.Sprintf("%d", pid), "cmdline")
38+
assert.NoError(t, os.MkdirAll(filepath.Dir(path), 0o755))
39+
assert.NoError(t, os.WriteFile(path, data, 0o600))
40+
}
41+
42+
func assertNoErrorNotEmpty(t *testing.T, got string, err error) {
43+
assert.NoError(t, err)
44+
assert.NotEmpty(t, got)
45+
}
46+
47+
func assertErrorEmpty(t *testing.T, got string, err error) {
48+
assert.Error(t, err)
49+
assert.Empty(t, got)
50+
}
51+
52+
func TestRunningDir(t *testing.T) {
53+
dir, err := RunningDir()
54+
assertNoErrorNotEmpty(t, dir, err)
55+
assert.True(t, filepath.IsAbs(dir))
56+
57+
info, err := os.Stat(dir)
58+
assert.NoError(t, err)
59+
assert.True(t, info.IsDir())
60+
}
61+
62+
func TestProcNameByPid_Filesystem(t *testing.T) {
63+
procRoot := filepath.Join(t.TempDir(), "proc")
64+
withProcRoot(t, filepath.Dir(procRoot))
65+
66+
tests := []struct {
67+
name string
68+
pid uint32
69+
setup func(*testing.T, uint32)
70+
validate func(*testing.T, string, error)
71+
}{
72+
{
73+
name: "ok/multi-argument cmdline",
74+
pid: 1002,
75+
setup: func(t *testing.T, pid uint32) {
76+
writeCmdline(t, procRoot, pid, []byte("/usr/bin/docker\x00run\x00--rm\x00alpine\x00"))
77+
},
78+
validate: func(t *testing.T, got string, err error) {
79+
assert.NoError(t, err)
80+
assert.Equal(t, "/usr/bin/docker run --rm alpine ", got)
81+
},
82+
},
83+
{
84+
name: "ok/empty cmdline",
85+
pid: 1003,
86+
setup: func(t *testing.T, pid uint32) {
87+
writeCmdline(t, procRoot, pid, nil)
88+
},
89+
validate: func(t *testing.T, got string, err error) {
90+
assert.NoError(t, err)
91+
assert.Equal(t, "", got)
92+
},
93+
},
94+
{
95+
name: "ok/truncate and sanitize",
96+
pid: 1004,
97+
setup: func(t *testing.T, pid uint32) {
98+
longCmdline := bytes.Repeat([]byte{'a'}, 130)
99+
longCmdline[5] = 0
100+
longCmdline[127] = 0
101+
writeCmdline(t, procRoot, pid, longCmdline)
102+
},
103+
validate: func(t *testing.T, got string, err error) {
104+
assert.NoError(t, err)
105+
assert.Len(t, got, 128)
106+
assert.NotContains(t, got, string(rune(0)))
107+
assert.Equal(t, byte(' '), got[5])
108+
assert.Equal(t, byte(' '), got[127])
109+
},
110+
},
111+
{
112+
name: "invalid pid",
113+
pid: 1999,
114+
setup: func(_ *testing.T, pid uint32) {},
115+
validate: assertErrorEmpty,
116+
},
117+
}
118+
119+
for _, tt := range tests {
120+
t.Run(tt.name, func(t *testing.T) {
121+
tt.setup(t, tt.pid)
122+
got, err := ProcNameByPid(tt.pid)
123+
tt.validate(t, got, err)
124+
})
125+
}
126+
}
127+
128+
func TestHostnameByPid(t *testing.T) {
129+
if runtime.GOOS != "linux" {
130+
t.Skip("only meaningful on Linux / requires CAP_SYS_ADMIN or proper namespace access")
131+
}
132+
133+
selfPid := uint32(os.Getpid())
134+
135+
tests := []struct {
136+
name string
137+
pid uint32
138+
validate func(*testing.T, string, string, error)
139+
}{
140+
{
141+
name: "self pid - should get current hostname",
142+
pid: selfPid,
143+
validate: func(t *testing.T, got, expected string, err error) {
144+
assertNoErrorNotEmpty(t, got, err)
145+
assert.Equal(t, got, expected)
146+
},
147+
},
148+
{
149+
name: "invalid pid",
150+
pid: 99999999,
151+
validate: func(t *testing.T, got, expected string, err error) {
152+
assertErrorEmpty(t, got, err)
153+
},
154+
},
155+
}
156+
157+
for _, tt := range tests {
158+
t.Run(tt.name, func(t *testing.T) {
159+
currentHost, err := os.Hostname()
160+
assert.NoError(t, err)
161+
got, err := HostnameByPid(tt.pid)
162+
tt.validate(t, got, currentHost, err)
163+
})
164+
}
165+
}

0 commit comments

Comments
 (0)