-
Notifications
You must be signed in to change notification settings - Fork 2k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
tests: add tests for
cli-plugins/socket
Signed-off-by: Laura Brehm <[email protected]> (cherry picked from commit 469bfc0) Signed-off-by: Sebastiaan van Stijn <[email protected]>
- Loading branch information
Showing
1 changed file
with
129 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,129 @@ | ||
package socket | ||
|
||
import ( | ||
"io/fs" | ||
"net" | ||
"os" | ||
"runtime" | ||
"testing" | ||
"time" | ||
|
||
"gotest.tools/v3/assert" | ||
"gotest.tools/v3/poll" | ||
) | ||
|
||
func TestSetupConn(t *testing.T) { | ||
t.Run("updates conn when connected", func(t *testing.T) { | ||
var conn *net.UnixConn | ||
listener, err := SetupConn(&conn) | ||
assert.NilError(t, err) | ||
assert.Check(t, listener != nil, "returned nil listener but no error") | ||
addr, err := net.ResolveUnixAddr("unix", listener.Addr().String()) | ||
assert.NilError(t, err, "failed to resolve listener address") | ||
|
||
_, err = net.DialUnix("unix", nil, addr) | ||
assert.NilError(t, err, "failed to dial returned listener") | ||
|
||
pollConnNotNil(t, &conn) | ||
}) | ||
|
||
t.Run("allows reconnects", func(t *testing.T) { | ||
var conn *net.UnixConn | ||
listener, err := SetupConn(&conn) | ||
assert.NilError(t, err) | ||
assert.Check(t, listener != nil, "returned nil listener but no error") | ||
addr, err := net.ResolveUnixAddr("unix", listener.Addr().String()) | ||
assert.NilError(t, err, "failed to resolve listener address") | ||
|
||
otherConn, err := net.DialUnix("unix", nil, addr) | ||
assert.NilError(t, err, "failed to dial returned listener") | ||
|
||
otherConn.Close() | ||
|
||
_, err = net.DialUnix("unix", nil, addr) | ||
assert.NilError(t, err, "failed to redial listener") | ||
}) | ||
|
||
t.Run("does not leak sockets to local directory", func(t *testing.T) { | ||
var conn *net.UnixConn | ||
listener, err := SetupConn(&conn) | ||
assert.NilError(t, err) | ||
assert.Check(t, listener != nil, "returned nil listener but no error") | ||
checkDirClean(t) | ||
|
||
addr, err := net.ResolveUnixAddr("unix", listener.Addr().String()) | ||
assert.NilError(t, err, "failed to resolve listener address") | ||
_, err = net.DialUnix("unix", nil, addr) | ||
assert.NilError(t, err, "failed to dial returned listener") | ||
checkDirClean(t) | ||
}) | ||
} | ||
|
||
func checkDirClean(t *testing.T) { | ||
t.Helper() | ||
|
||
files, err := os.ReadDir(".") | ||
assert.NilError(t, err, "failed to list files in dir to check for leaked sockets") | ||
|
||
for _, f := range files { | ||
info, err := f.Info() | ||
assert.NilError(t, err, "failed to check file info") | ||
if info.Mode().Type() == fs.ModeSocket { | ||
t.Fatal("found socket in a local directory") | ||
} | ||
} | ||
} | ||
|
||
func TestConnectAndWait(t *testing.T) { | ||
t.Run("calls cancel func on EOF", func(t *testing.T) { | ||
var conn *net.UnixConn | ||
listener, err := SetupConn(&conn) | ||
assert.NilError(t, err, "failed to setup listener") | ||
|
||
done := make(chan struct{}) | ||
t.Setenv(EnvKey, listener.Addr().String()) | ||
cancelFunc := func() { | ||
done <- struct{}{} | ||
} | ||
ConnectAndWait(cancelFunc) | ||
pollConnNotNil(t, &conn) | ||
conn.Close() | ||
|
||
select { | ||
case <-done: | ||
case <-time.After(10 * time.Millisecond): | ||
t.Fatal("cancel function not closed after 10ms") | ||
} | ||
}) | ||
|
||
t.Run("connect goroutine exits after EOF", func(t *testing.T) { | ||
var conn *net.UnixConn | ||
listener, err := SetupConn(&conn) | ||
assert.NilError(t, err, "failed to setup listener") | ||
t.Setenv(EnvKey, listener.Addr().String()) | ||
numGoroutines := runtime.NumGoroutine() | ||
|
||
ConnectAndWait(func() {}) | ||
assert.Equal(t, runtime.NumGoroutine(), numGoroutines+1) | ||
|
||
pollConnNotNil(t, &conn) | ||
conn.Close() | ||
poll.WaitOn(t, func(t poll.LogT) poll.Result { | ||
if runtime.NumGoroutine() > numGoroutines+1 { | ||
return poll.Continue("waiting for connect goroutine to exit") | ||
} | ||
return poll.Success() | ||
}, poll.WithDelay(1*time.Millisecond), poll.WithTimeout(10*time.Millisecond)) | ||
}) | ||
} | ||
|
||
func pollConnNotNil(t *testing.T, conn **net.UnixConn) { | ||
t.Helper() | ||
|
||
poll.WaitOn(t, func(t poll.LogT) poll.Result { | ||
if *conn == nil { | ||
return poll.Continue("waiting for conn to not be nil") | ||
} | ||
return poll.Success() | ||
}, poll.WithDelay(1*time.Millisecond), poll.WithTimeout(10*time.Millisecond)) | ||
} |