66 "errors"
77 "fmt"
88 "io"
9- "io/ioutil"
109 "os"
1110 "os/exec"
1211 "strings"
@@ -17,21 +16,9 @@ import (
1716 "golang.org/x/sys/unix"
1817)
1918
20- type pid struct {
21- Pid int `json:"Pid"`
22- }
23-
24- type logentry struct {
25- Msg string `json:"msg"`
26- Level string `json:"level"`
27- }
28-
2919func TestNsenterValidPaths (t * testing.T ) {
3020 args := []string {"nsenter-exec" }
31- parent , child , err := newPipe ()
32- if err != nil {
33- t .Fatalf ("failed to create pipe %v" , err )
34- }
21+ parent , child := newPipe (t )
3522
3623 namespaces := []string {
3724 // join pid ns of the current process
@@ -47,8 +34,9 @@ func TestNsenterValidPaths(t *testing.T) {
4734 }
4835
4936 if err := cmd .Start (); err != nil {
50- t .Fatalf ("nsenter failed to start %v" , err )
37+ t .Fatalf ("nsenter failed to start: %v" , err )
5138 }
39+ child .Close ()
5240
5341 // write cloneFlags
5442 r := nl .NewNetlinkRequest (int (libcontainer .InitMsg ), 0 )
@@ -66,36 +54,18 @@ func TestNsenterValidPaths(t *testing.T) {
6654
6755 initWaiter (t , parent )
6856
69- decoder := json .NewDecoder (parent )
70- var pid * pid
71-
7257 if err := cmd .Wait (); err != nil {
73- t .Fatalf ("nsenter exits with a non-zero exit status" )
74- }
75- if err := decoder .Decode (& pid ); err != nil {
76- dir , _ := ioutil .ReadDir (fmt .Sprintf ("/proc/%d/ns" , os .Getpid ()))
77- for _ , d := range dir {
78- t .Log (d .Name ())
79- }
80- t .Fatalf ("%v" , err )
58+ t .Fatalf ("nsenter error: %v" , err )
8159 }
8260
83- p , err := os .FindProcess (pid .Pid )
84- if err != nil {
85- t .Fatalf ("%v" , err )
86- }
87- _ , _ = p .Wait ()
61+ reapChildren (t , parent )
8862}
8963
9064func TestNsenterInvalidPaths (t * testing.T ) {
9165 args := []string {"nsenter-exec" }
92- parent , child , err := newPipe ()
93- if err != nil {
94- t .Fatalf ("failed to create pipe %v" , err )
95- }
66+ parent , child := newPipe (t )
9667
9768 namespaces := []string {
98- // join pid ns of the current process
9969 fmt .Sprintf ("pid:/proc/%d/ns/pid" , - 1 ),
10070 }
10171 cmd := & exec.Cmd {
@@ -106,8 +76,10 @@ func TestNsenterInvalidPaths(t *testing.T) {
10676 }
10777
10878 if err := cmd .Start (); err != nil {
109- t .Fatal ( err )
79+ t .Fatalf ( "nsenter failed to start: %v" , err )
11080 }
81+ child .Close ()
82+
11183 // write cloneFlags
11284 r := nl .NewNetlinkRequest (int (libcontainer .InitMsg ), 0 )
11385 r .AddData (& libcontainer.Int32msg {
@@ -130,13 +102,9 @@ func TestNsenterInvalidPaths(t *testing.T) {
130102
131103func TestNsenterIncorrectPathType (t * testing.T ) {
132104 args := []string {"nsenter-exec" }
133- parent , child , err := newPipe ()
134- if err != nil {
135- t .Fatalf ("failed to create pipe %v" , err )
136- }
105+ parent , child := newPipe (t )
137106
138107 namespaces := []string {
139- // join pid ns of the current process
140108 fmt .Sprintf ("net:/proc/%d/ns/pid" , os .Getpid ()),
141109 }
142110 cmd := & exec.Cmd {
@@ -147,8 +115,10 @@ func TestNsenterIncorrectPathType(t *testing.T) {
147115 }
148116
149117 if err := cmd .Start (); err != nil {
150- t .Fatal ( err )
118+ t .Fatalf ( "nsenter failed to start: %v" , err )
151119 }
120+ child .Close ()
121+
152122 // write cloneFlags
153123 r := nl .NewNetlinkRequest (int (libcontainer .InitMsg ), 0 )
154124 r .AddData (& libcontainer.Int32msg {
@@ -165,24 +135,14 @@ func TestNsenterIncorrectPathType(t *testing.T) {
165135
166136 initWaiter (t , parent )
167137 if err := cmd .Wait (); err == nil {
168- t .Fatalf ("nsenter exits with a zero exit status" )
138+ t .Fatalf ("nsenter error: %v" , err )
169139 }
170140}
171141
172142func TestNsenterChildLogging (t * testing.T ) {
173143 args := []string {"nsenter-exec" }
174- parent , child , err := newPipe ()
175- if err != nil {
176- t .Fatalf ("failed to create exec pipe %v" , err )
177- }
178- logread , logwrite , err := os .Pipe ()
179- if err != nil {
180- t .Fatalf ("failed to create log pipe %v" , err )
181- }
182- defer func () {
183- _ = logwrite .Close ()
184- _ = logread .Close ()
185- }()
144+ parent , child := newPipe (t )
145+ logread , logwrite := newPipe (t )
186146
187147 namespaces := []string {
188148 // join pid ns of the current process
@@ -198,8 +158,11 @@ func TestNsenterChildLogging(t *testing.T) {
198158 }
199159
200160 if err := cmd .Start (); err != nil {
201- t .Fatalf ("nsenter failed to start %v" , err )
161+ t .Fatalf ("nsenter failed to start: %v" , err )
202162 }
163+ child .Close ()
164+ logwrite .Close ()
165+
203166 // write cloneFlags
204167 r := nl .NewNetlinkRequest (int (libcontainer .InitMsg ), 0 )
205168 r .AddData (& libcontainer.Int32msg {
@@ -216,20 +179,12 @@ func TestNsenterChildLogging(t *testing.T) {
216179
217180 initWaiter (t , parent )
218181
219- logsDecoder := json .NewDecoder (logread )
220- var logentry * logentry
221-
222- err = logsDecoder .Decode (& logentry )
223- if err != nil {
224- t .Fatalf ("child log: %v" , err )
225- }
226- if logentry .Level == "" || logentry .Msg == "" {
227- t .Fatalf ("child log: empty log fields: level=\" %s\" msg=\" %s\" " , logentry .Level , logentry .Msg )
228- }
229-
182+ getLogs (t , logread )
230183 if err := cmd .Wait (); err != nil {
231- t .Fatalf ("nsenter exits with a non-zero exit status" )
184+ t .Fatalf ("nsenter error: %v" , err )
232185 }
186+
187+ reapChildren (t , parent )
233188}
234189
235190func init () {
@@ -238,12 +193,19 @@ func init() {
238193 }
239194}
240195
241- func newPipe () (parent * os.File , child * os.File , err error ) {
196+ func newPipe (t * testing.T ) (parent * os.File , child * os.File ) {
197+ t .Helper ()
242198 fds , err := unix .Socketpair (unix .AF_LOCAL , unix .SOCK_STREAM | unix .SOCK_CLOEXEC , 0 )
243199 if err != nil {
244- return nil , nil , err
200+ t . Fatal ( "socketpair failed:" , err )
245201 }
246- return os .NewFile (uintptr (fds [1 ]), "parent" ), os .NewFile (uintptr (fds [0 ]), "child" ), nil
202+ parent = os .NewFile (uintptr (fds [1 ]), "parent" )
203+ child = os .NewFile (uintptr (fds [0 ]), "child" )
204+ t .Cleanup (func () {
205+ parent .Close ()
206+ child .Close ()
207+ })
208+ return
247209}
248210
249211// initWaiter reads back the initial \0 from runc init
@@ -261,3 +223,47 @@ func initWaiter(t *testing.T, r io.Reader) {
261223 }
262224 t .Fatalf ("waiting for init preliminary setup: %v" , err )
263225}
226+
227+ func reapChildren (t * testing.T , parent * os.File ) {
228+ t .Helper ()
229+ decoder := json .NewDecoder (parent )
230+ decoder .DisallowUnknownFields ()
231+ var pid struct {
232+ Pid2 int `json:"stage2_pid"`
233+ Pid1 int `json:"stage1_pid"`
234+ }
235+ if err := decoder .Decode (& pid ); err != nil {
236+ t .Fatal (err )
237+ }
238+
239+ // Reap children.
240+ _ , _ = unix .Wait4 (pid .Pid1 , nil , 0 , nil )
241+ _ , _ = unix .Wait4 (pid .Pid2 , nil , 0 , nil )
242+
243+ // Sanity check.
244+ if pid .Pid1 == 0 || pid .Pid2 == 0 {
245+ t .Fatal ("got pids:" , pid )
246+ }
247+ }
248+
249+ func getLogs (t * testing.T , logread * os.File ) {
250+ logsDecoder := json .NewDecoder (logread )
251+ logsDecoder .DisallowUnknownFields ()
252+ var logentry struct {
253+ Level string `json:"level"`
254+ Msg string `json:"msg"`
255+ }
256+
257+ for {
258+ if err := logsDecoder .Decode (& logentry ); err != nil {
259+ if errors .Is (err , io .EOF ) {
260+ return
261+ }
262+ t .Fatal ("init log decoding error:" , err )
263+ }
264+ t .Logf ("logentry: %+v" , logentry )
265+ if logentry .Level == "" || logentry .Msg == "" {
266+ t .Fatalf ("init log: empty log entry: %+v" , logentry )
267+ }
268+ }
269+ }
0 commit comments