chore: Update pion/udp and improve parallel/non-parallel tests (#7164)

* test(all): Improve and fix subtests with parallell/nonparallel parents

* chore: Update pion/udp to fix buffer close
This commit is contained in:
Mathias Fredriksson 2023-04-17 20:23:10 +03:00 committed by GitHub
parent c6b2861493
commit bf0fed4f3f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 215 additions and 222 deletions

View File

@ -30,42 +30,42 @@ func TestReap(t *testing.T) {
// OK checks that's the reaper is successfully reaping
// exited processes and passing the PIDs through the shared
// channel.
}
//nolint:paralleltest // Signal handling.
t.Run("OK", func(t *testing.T) {
pids := make(reap.PidCh, 1)
err := reaper.ForkReap(
reaper.WithPIDCallback(pids),
// Provide some argument that immediately exits.
reaper.WithExecArgs("/bin/sh", "-c", "exit 0"),
)
require.NoError(t, err)
//nolint:paralleltest // Signal handling.
func TestReap_OK(t *testing.T) {
pids := make(reap.PidCh, 1)
err := reaper.ForkReap(
reaper.WithPIDCallback(pids),
// Provide some argument that immediately exits.
reaper.WithExecArgs("/bin/sh", "-c", "exit 0"),
)
require.NoError(t, err)
cmd := exec.Command("tail", "-f", "/dev/null")
err = cmd.Start()
require.NoError(t, err)
cmd := exec.Command("tail", "-f", "/dev/null")
err = cmd.Start()
require.NoError(t, err)
cmd2 := exec.Command("tail", "-f", "/dev/null")
err = cmd2.Start()
require.NoError(t, err)
cmd2 := exec.Command("tail", "-f", "/dev/null")
err = cmd2.Start()
require.NoError(t, err)
err = cmd.Process.Kill()
require.NoError(t, err)
err = cmd.Process.Kill()
require.NoError(t, err)
err = cmd2.Process.Kill()
require.NoError(t, err)
err = cmd2.Process.Kill()
require.NoError(t, err)
expectedPIDs := []int{cmd.Process.Pid, cmd2.Process.Pid}
expectedPIDs := []int{cmd.Process.Pid, cmd2.Process.Pid}
for i := 0; i < len(expectedPIDs); i++ {
select {
case <-time.After(testutil.WaitShort):
t.Fatalf("Timed out waiting for process")
case pid := <-pids:
require.Contains(t, expectedPIDs, pid)
}
for i := 0; i < len(expectedPIDs); i++ {
select {
case <-time.After(testutil.WaitShort):
t.Fatalf("Timed out waiting for process")
case pid := <-pids:
require.Contains(t, expectedPIDs, pid)
}
})
}
}
//nolint:paralleltest // Signal handling.

View File

@ -21,10 +21,8 @@ import (
"github.com/coder/coder/testutil"
)
//nolint:tparallel,paralleltest // Subtests require setup that must not be done in parallel.
func TestPortForward(t *testing.T) {
t.Parallel()
t.Skip("These tests flake... a lot. It seems related to the Tailscale change, but all other tests pass...")
t.Run("None", func(t *testing.T) {
t.Parallel()
@ -116,106 +114,102 @@ func TestPortForward(t *testing.T) {
workspace = runAgent(t, client, user.UserID)
)
for _, c := range cases { //nolint:paralleltest // the `c := c` confuses the linter
for _, c := range cases {
c := c
// Delay parallel tests here because setupLocal reserves
// a free open port which is not guaranteed to be free
// between the listener closing and port-forward ready.
t.Run(c.name, func(t *testing.T) {
t.Run("OnePort", func(t *testing.T) {
p1 := setupTestListener(t, c.setupRemote(t))
t.Run(c.name+"_OnePort", func(t *testing.T) {
p1 := setupTestListener(t, c.setupRemote(t))
// Create a flag that forwards from local to listener 1.
localAddress, localFlag := c.setupLocal(t)
flag := fmt.Sprintf(c.flag, localFlag, p1)
// Create a flag that forwards from local to listener 1.
localAddress, localFlag := c.setupLocal(t)
flag := fmt.Sprintf(c.flag, localFlag, p1)
// Launch port-forward in a goroutine so we can start dialing
// the "local" listener.
inv, root := clitest.New(t, "-v", "port-forward", workspace.Name, flag)
clitest.SetupConfig(t, client, root)
pty := ptytest.New(t)
inv.Stdin = pty.Input()
inv.Stdout = pty.Output()
inv.Stderr = pty.Output()
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
errC := make(chan error)
go func() {
errC <- inv.WithContext(ctx).Run()
}()
pty.ExpectMatch("Ready!")
// Launch port-forward in a goroutine so we can start dialing
// the "local" listener.
inv, root := clitest.New(t, "-v", "port-forward", workspace.Name, flag)
clitest.SetupConfig(t, client, root)
pty := ptytest.New(t)
inv.Stdin = pty.Input()
inv.Stdout = pty.Output()
inv.Stderr = pty.Output()
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
errC := make(chan error)
go func() {
errC <- inv.WithContext(ctx).Run()
}()
pty.ExpectMatch("Ready!")
t.Parallel() // Port is reserved, enable parallel execution.
t.Parallel() // Port is reserved, enable parallel execution.
// Open two connections simultaneously and test them out of
// sync.
d := net.Dialer{Timeout: testutil.WaitShort}
c1, err := d.DialContext(ctx, c.network, localAddress)
require.NoError(t, err, "open connection 1 to 'local' listener")
defer c1.Close()
c2, err := d.DialContext(ctx, c.network, localAddress)
require.NoError(t, err, "open connection 2 to 'local' listener")
defer c2.Close()
testDial(t, c2)
testDial(t, c1)
// Open two connections simultaneously and test them out of
// sync.
d := net.Dialer{Timeout: testutil.WaitShort}
c1, err := d.DialContext(ctx, c.network, localAddress)
require.NoError(t, err, "open connection 1 to 'local' listener")
defer c1.Close()
c2, err := d.DialContext(ctx, c.network, localAddress)
require.NoError(t, err, "open connection 2 to 'local' listener")
defer c2.Close()
testDial(t, c2)
testDial(t, c1)
cancel()
err = <-errC
require.ErrorIs(t, err, context.Canceled)
})
cancel()
err = <-errC
require.ErrorIs(t, err, context.Canceled)
})
//nolint:paralleltest
t.Run("TwoPorts", func(t *testing.T) {
var (
p1 = setupTestListener(t, c.setupRemote(t))
p2 = setupTestListener(t, c.setupRemote(t))
)
t.Run(c.name+"_TwoPorts", func(t *testing.T) {
var (
p1 = setupTestListener(t, c.setupRemote(t))
p2 = setupTestListener(t, c.setupRemote(t))
)
// Create a flags for listener 1 and listener 2.
localAddress1, localFlag1 := c.setupLocal(t)
localAddress2, localFlag2 := c.setupLocal(t)
flag1 := fmt.Sprintf(c.flag, localFlag1, p1)
flag2 := fmt.Sprintf(c.flag, localFlag2, p2)
// Create a flags for listener 1 and listener 2.
localAddress1, localFlag1 := c.setupLocal(t)
localAddress2, localFlag2 := c.setupLocal(t)
flag1 := fmt.Sprintf(c.flag, localFlag1, p1)
flag2 := fmt.Sprintf(c.flag, localFlag2, p2)
// Launch port-forward in a goroutine so we can start dialing
// the "local" listeners.
inv, root := clitest.New(t, "-v", "port-forward", workspace.Name, flag1, flag2)
clitest.SetupConfig(t, client, root)
pty := ptytest.New(t)
inv.Stdin = pty.Input()
inv.Stdout = pty.Output()
inv.Stderr = pty.Output()
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
errC := make(chan error)
go func() {
errC <- inv.WithContext(ctx).Run()
}()
pty.ExpectMatch("Ready!")
// Launch port-forward in a goroutine so we can start dialing
// the "local" listeners.
inv, root := clitest.New(t, "-v", "port-forward", workspace.Name, flag1, flag2)
clitest.SetupConfig(t, client, root)
pty := ptytest.New(t)
inv.Stdin = pty.Input()
inv.Stdout = pty.Output()
inv.Stderr = pty.Output()
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
errC := make(chan error)
go func() {
errC <- inv.WithContext(ctx).Run()
}()
pty.ExpectMatch("Ready!")
t.Parallel() // Port is reserved, enable parallel execution.
t.Parallel() // Port is reserved, enable parallel execution.
// Open a connection to both listener 1 and 2 simultaneously and
// then test them out of order.
d := net.Dialer{Timeout: testutil.WaitShort}
c1, err := d.DialContext(ctx, c.network, localAddress1)
require.NoError(t, err, "open connection 1 to 'local' listener 1")
defer c1.Close()
c2, err := d.DialContext(ctx, c.network, localAddress2)
require.NoError(t, err, "open connection 2 to 'local' listener 2")
defer c2.Close()
testDial(t, c2)
testDial(t, c1)
// Open a connection to both listener 1 and 2 simultaneously and
// then test them out of order.
d := net.Dialer{Timeout: testutil.WaitShort}
c1, err := d.DialContext(ctx, c.network, localAddress1)
require.NoError(t, err, "open connection 1 to 'local' listener 1")
defer c1.Close()
c2, err := d.DialContext(ctx, c.network, localAddress2)
require.NoError(t, err, "open connection 2 to 'local' listener 2")
defer c2.Close()
testDial(t, c2)
testDial(t, c1)
cancel()
err = <-errC
require.ErrorIs(t, err, context.Canceled)
})
cancel()
err = <-errC
require.ErrorIs(t, err, context.Canceled)
})
}
// Test doing TCP and UDP at the same time.
//nolint:paralleltest
t.Run("All", func(t *testing.T) {
var (
dials = []addr{}

View File

@ -104,35 +104,9 @@ func TestReadGitAuthProvidersFromEnv(t *testing.T) {
})
}
// This cannot be ran in parallel because it uses a signal.
// nolint:tparallel,paralleltest
func TestServer(t *testing.T) {
t.Run("Production", func(t *testing.T) {
if runtime.GOOS != "linux" || testing.Short() {
// Skip on non-Linux because it spawns a PostgreSQL instance.
t.SkipNow()
}
connectionURL, closeFunc, err := postgres.Open()
require.NoError(t, err)
defer closeFunc()
t.Parallel()
// Postgres + race detector + CI = slow.
ctx := testutil.Context(t, testutil.WaitSuperLong*3)
inv, cfg := clitest.New(t,
"server",
"--http-address", ":0",
"--access-url", "http://example.com",
"--postgres-url", connectionURL,
"--cache-dir", t.TempDir(),
)
clitest.Start(t, inv.WithContext(ctx))
accessURL := waitAccessURL(t, cfg)
client := codersdk.New(accessURL)
_, err = client.CreateFirstUser(ctx, coderdtest.FirstUserParams)
require.NoError(t, err)
})
t.Run("BuiltinPostgres", func(t *testing.T) {
t.Parallel()
if testing.Short() {
@ -855,38 +829,6 @@ func TestServer(t *testing.T) {
})
})
// This cannot be ran in parallel because it uses a signal.
//nolint:paralleltest
t.Run("Shutdown", func(t *testing.T) {
if runtime.GOOS == "windows" {
// Sending interrupt signal isn't supported on Windows!
t.SkipNow()
}
ctx, cancelFunc := context.WithCancel(context.Background())
defer cancelFunc()
root, cfg := clitest.New(t,
"server",
"--in-memory",
"--http-address", ":0",
"--access-url", "http://example.com",
"--provisioner-daemons", "1",
"--cache-dir", t.TempDir(),
)
serverErr := make(chan error, 1)
go func() {
serverErr <- root.WithContext(ctx).Run()
}()
_ = waitAccessURL(t, cfg)
currentProcess, err := os.FindProcess(os.Getpid())
require.NoError(t, err)
err = currentProcess.Signal(os.Interrupt)
require.NoError(t, err)
// We cannot send more signals here, because it's possible Coder
// has already exited, which could cause the test to fail due to interrupt.
err = <-serverErr
require.NoError(t, err)
})
t.Run("TracerNoLeak", func(t *testing.T) {
t.Parallel()
@ -1518,6 +1460,66 @@ func TestServer(t *testing.T) {
})
}
//nolint:tparallel,paralleltest // This test spawns or connects to an existing PostgreSQL instance.
func TestServer_Production(t *testing.T) {
if runtime.GOOS != "linux" || testing.Short() {
// Skip on non-Linux because it spawns a PostgreSQL instance.
t.SkipNow()
}
connectionURL, closeFunc, err := postgres.Open()
require.NoError(t, err)
defer closeFunc()
// Postgres + race detector + CI = slow.
ctx := testutil.Context(t, testutil.WaitSuperLong*3)
inv, cfg := clitest.New(t,
"server",
"--http-address", ":0",
"--access-url", "http://example.com",
"--postgres-url", connectionURL,
"--cache-dir", t.TempDir(),
)
clitest.Start(t, inv.WithContext(ctx))
accessURL := waitAccessURL(t, cfg)
client := codersdk.New(accessURL)
_, err = client.CreateFirstUser(ctx, coderdtest.FirstUserParams)
require.NoError(t, err)
}
//nolint:tparallel,paralleltest // This test cannot be run in parallel due to signal handling.
func TestServer_Shutdown(t *testing.T) {
if runtime.GOOS == "windows" {
// Sending interrupt signal isn't supported on Windows!
t.SkipNow()
}
ctx, cancelFunc := context.WithCancel(context.Background())
defer cancelFunc()
root, cfg := clitest.New(t,
"server",
"--in-memory",
"--http-address", ":0",
"--access-url", "http://example.com",
"--provisioner-daemons", "1",
"--cache-dir", t.TempDir(),
)
serverErr := make(chan error, 1)
go func() {
serverErr <- root.WithContext(ctx).Run()
}()
_ = waitAccessURL(t, cfg)
currentProcess, err := os.FindProcess(os.Getpid())
require.NoError(t, err)
err = currentProcess.Signal(os.Interrupt)
require.NoError(t, err)
// We cannot send more signals here, because it's possible Coder
// has already exited, which could cause the test to fail due to interrupt.
err = <-serverErr
require.NoError(t, err)
}
func generateTLSCertificate(t testing.TB, commonName ...string) (certPath, keyPath string) {
dir := t.TempDir()

View File

@ -156,8 +156,6 @@ func TestTemplatePush(t *testing.T) {
require.Equal(t, "example", templateVersions[1].Name)
})
// This test modifies the working directory.
//nolint:paralleltest
t.Run("UseWorkingDir", func(t *testing.T) {
t.Parallel()

View File

@ -1570,7 +1570,6 @@ func TestPaginatedUsers(t *testing.T) {
{name: "username search", limit: 3, allUsers: specialUsers, opt: usernameSearch},
{name: "username search", limit: 3, allUsers: specialUsers, opt: usernameSearch},
}
//nolint:paralleltest // Does not detect range value.
for _, tt := range tests {
tt := tt
t.Run(fmt.Sprintf("%s %d", tt.name, tt.limit), func(t *testing.T) {

View File

@ -91,7 +91,6 @@ func TestStringCharset(t *testing.T) {
},
}
//nolint:paralleltest
for _, test := range tests {
test := test
t.Run(test.Name, func(t *testing.T) {

4
go.mod
View File

@ -122,7 +122,7 @@ require (
github.com/muesli/reflow v0.3.0
github.com/open-policy-agent/opa v0.44.0
github.com/ory/dockertest/v3 v3.9.1
github.com/pion/udp v0.1.1
github.com/pion/udp v0.1.2
github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8
github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e
github.com/pkg/sftp v1.13.6-0.20221018182125-7da137aa03f0
@ -157,7 +157,7 @@ require (
golang.org/x/mod v0.8.0
golang.org/x/oauth2 v0.5.0
golang.org/x/sync v0.1.0
golang.org/x/sys v0.6.0
golang.org/x/sys v0.7.0
golang.org/x/term v0.6.0
golang.org/x/tools v0.6.0
golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2

10
go.sum
View File

@ -1588,11 +1588,10 @@ github.com/phpdave11/gofpdi v1.0.12/go.mod h1:vBmVV0Do6hSBHC8uKUQ71JGW+ZGQq74llk
github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY=
github.com/pierrec/lz4/v4 v4.1.8/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4=
github.com/pion/logging v0.2.2/go.mod h1:k0/tDVsRCX2Mb2ZEmTqNa7CWsQPc+YYCB7Q+5pahoms=
github.com/pion/transport v0.12.2/go.mod h1:N3+vZQD9HlDP5GWkZ85LohxNsDcNgofQmyL6ojX5d8Q=
github.com/pion/transport v0.14.1 h1:XSM6olwW+o8J4SCmOBb/BpwZypkHeyM0PGFCxNQBr40=
github.com/pion/transport v0.14.1/go.mod h1:4tGmbk00NeYA3rUa9+n+dzCCoKkcy3YlYb99Jn2fNnI=
github.com/pion/udp v0.1.1 h1:8UAPvyqmsxK8oOjloDk4wUt63TzFe9WEJkg5lChlj7o=
github.com/pion/udp v0.1.1/go.mod h1:6AFo+CMdKQm7UiA0eUPA8/eVCTx8jBIITLZHc9DWX5M=
github.com/pion/udp v0.1.2 h1:Bl1ifOcoVYg9gnk1+9yyTX8XgAUORiDvM7UqBb3skhg=
github.com/pion/udp v0.1.2/go.mod h1:CuqU2J4MmF3sjqKfk1SaIhuNXdum5PJRqd2LHuLMQSk=
github.com/pkg/browser v0.0.0-20210706143420-7d21f8c997e2/go.mod h1:HKlIX3XHQyzLZPlr7++PzdhaXEj94dEiJgZDTsxEqUI=
github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8 h1:KoWmjvw+nsYOo29YJK9vDA65RGE3NrOnUtO7a+RF9HU=
github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8/go.mod h1:HKlIX3XHQyzLZPlr7++PzdhaXEj94dEiJgZDTsxEqUI=
@ -2196,7 +2195,6 @@ golang.org/x/net v0.0.0-20201010224723-4f7140c49acb/go.mod h1:sp8m0HH+o8qH0wwXwY
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20201031054903-ff519b6c9102/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20201201195509-5d6afe98e0b7/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20201202161906-c7110b5ffcbb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
@ -2441,8 +2439,8 @@ golang.org/x/sys v0.0.0-20221010170243-090e33056c14/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.4.1-0.20230131160137-e7d7f63158de/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0 h1:MVltZSvRTcU2ljQOhs94SXPftV6DCNnZViHeQps87pQ=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.7.0 h1:3jlCCIQZPdOYu1h8BkNvLz8Kgwtae2cagcG/VamtZRU=
golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=

View File

@ -58,44 +58,6 @@ func Test_Runner(t *testing.T) {
require.NotContains(t, logStr, "Waiting for ")
})
//nolint:paralleltest // Measures timing as part of the test.
t.Run("Direct+Hold", func(t *testing.T) {
client, agentID := setupRunnerTest(t)
runner := agentconn.NewRunner(client, agentconn.Config{
AgentID: agentID,
ConnectionMode: agentconn.ConnectionModeDirect,
HoldDuration: httpapi.Duration(testutil.WaitShort),
})
ctx, cancel := context.WithTimeout(context.Background(), testutil.WaitLong)
defer cancel()
logs := bytes.NewBuffer(nil)
start := time.Now()
err := runner.Run(ctx, "1", logs)
logStr := logs.String()
t.Log("Runner logs:\n\n" + logStr)
require.NoError(t, err)
require.WithinRange(t,
time.Now(),
start.Add(testutil.WaitShort-time.Second),
start.Add(testutil.WaitShort+5*time.Second),
)
require.Contains(t, logStr, "Opening connection to workspace agent")
require.Contains(t, logStr, "Using direct connection")
require.Contains(t, logStr, "Disco ping attempt 1/10...")
require.Contains(t, logStr, "Direct connection check 1/30...")
require.Contains(t, logStr, "Connection established")
require.Contains(t, logStr, "Verify connection attempt 1/30...")
require.Contains(t, logStr, "Connection verified")
require.NotContains(t, logStr, "Performing initial service connections")
require.NotContains(t, logStr, "Starting connection loops")
require.Contains(t, logStr, fmt.Sprintf("Waiting for %s", testutil.WaitShort))
})
t.Run("Derp+ServicesNoHold", func(t *testing.T) {
t.Parallel()
@ -143,8 +105,49 @@ func Test_Runner(t *testing.T) {
require.EqualValues(t, 1, service1Count())
require.EqualValues(t, 1, service2Count())
})
}
//nolint:paralleltest // Measures timing as part of the test.
//nolint:paralleltest // Measures timing as part of the test.
func Test_Runner_Timing(t *testing.T) {
//nolint:paralleltest
t.Run("Direct+Hold", func(t *testing.T) {
client, agentID := setupRunnerTest(t)
runner := agentconn.NewRunner(client, agentconn.Config{
AgentID: agentID,
ConnectionMode: agentconn.ConnectionModeDirect,
HoldDuration: httpapi.Duration(testutil.WaitShort),
})
ctx, cancel := context.WithTimeout(context.Background(), testutil.WaitLong)
defer cancel()
logs := bytes.NewBuffer(nil)
start := time.Now()
err := runner.Run(ctx, "1", logs)
logStr := logs.String()
t.Log("Runner logs:\n\n" + logStr)
require.NoError(t, err)
require.WithinRange(t,
time.Now(),
start.Add(testutil.WaitShort-time.Second),
start.Add(testutil.WaitShort+5*time.Second),
)
require.Contains(t, logStr, "Opening connection to workspace agent")
require.Contains(t, logStr, "Using direct connection")
require.Contains(t, logStr, "Disco ping attempt 1/10...")
require.Contains(t, logStr, "Direct connection check 1/30...")
require.Contains(t, logStr, "Connection established")
require.Contains(t, logStr, "Verify connection attempt 1/30...")
require.Contains(t, logStr, "Connection verified")
require.NotContains(t, logStr, "Performing initial service connections")
require.NotContains(t, logStr, "Starting connection loops")
require.Contains(t, logStr, fmt.Sprintf("Waiting for %s", testutil.WaitShort))
})
//nolint:paralleltest
t.Run("Derp+Hold+Services", func(t *testing.T) {
client, agentID := setupRunnerTest(t)
service1URL, service1Count := testServer(t)