mirror of https://github.com/coder/coder.git
chore: skip timing-sensistive AgentMetadata test in the standard suite (#7237)
* chore: skip timing-sensistive AgentMetadata test in the standard suite * Add test-timing target * fix windows? * Works on my Windows desktop? * Use tag system * fixup! Use tag system
This commit is contained in:
parent
398d08a0cf
commit
465fe8658d
|
@ -210,25 +210,31 @@ func (a *agent) collectMetadata(ctx context.Context, md codersdk.WorkspaceAgentM
|
|||
var out bytes.Buffer
|
||||
result := &codersdk.WorkspaceAgentMetadataResult{
|
||||
// CollectedAt is set here for testing purposes and overrode by
|
||||
// the server to the time the server received the result to protect
|
||||
// against clock skew.
|
||||
// coderd to the time of server receipt to solve clock skew.
|
||||
//
|
||||
// In the future, the server may accept the timestamp from the agent
|
||||
// if it is certain the clocks are in sync.
|
||||
// if it can guarantee the clocks are synchronized.
|
||||
CollectedAt: time.Now(),
|
||||
}
|
||||
cmd, err := a.sshServer.CreateCommand(ctx, md.Script, nil)
|
||||
if err != nil {
|
||||
result.Error = err.Error()
|
||||
result.Error = fmt.Sprintf("create cmd: %+v", err)
|
||||
return result
|
||||
}
|
||||
|
||||
cmd.Stdout = &out
|
||||
cmd.Stderr = &out
|
||||
cmd.Stdin = io.LimitReader(nil, 0)
|
||||
|
||||
// The error isn't mutually exclusive with useful output.
|
||||
err = cmd.Run()
|
||||
// We split up Start and Wait instead of calling Run so that we can return a more precise error.
|
||||
err = cmd.Start()
|
||||
if err != nil {
|
||||
result.Error = fmt.Sprintf("start cmd: %+v", err)
|
||||
return result
|
||||
}
|
||||
|
||||
// This error isn't mutually exclusive with useful output.
|
||||
err = cmd.Wait()
|
||||
const bufLimit = 10 << 10
|
||||
if out.Len() > bufLimit {
|
||||
err = errors.Join(
|
||||
|
@ -238,8 +244,12 @@ func (a *agent) collectMetadata(ctx context.Context, md codersdk.WorkspaceAgentM
|
|||
out.Truncate(bufLimit)
|
||||
}
|
||||
|
||||
// Important: if the command times out, we may see a misleading error like
|
||||
// "exit status 1", so it's important to include the context error.
|
||||
err = errors.Join(err, ctx.Err())
|
||||
|
||||
if err != nil {
|
||||
result.Error = err.Error()
|
||||
result.Error = fmt.Sprintf("run cmd: %+v", err)
|
||||
}
|
||||
result.Value = out.String()
|
||||
return result
|
||||
|
|
|
@ -951,19 +951,17 @@ func TestAgent_StartupScript(t *testing.T) {
|
|||
func TestAgent_Metadata(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
echoHello := "echo 'hello'"
|
||||
|
||||
t.Run("Once", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
script := "echo -n hello"
|
||||
if runtime.GOOS == "windows" {
|
||||
script = "powershell " + script
|
||||
}
|
||||
//nolint:dogsled
|
||||
_, client, _, _, _ := setupAgent(t, agentsdk.Manifest{
|
||||
Metadata: []codersdk.WorkspaceAgentMetadataDescription{
|
||||
{
|
||||
Key: "greeting",
|
||||
Interval: 0,
|
||||
Script: script,
|
||||
Script: echoHello,
|
||||
},
|
||||
},
|
||||
}, 0)
|
||||
|
@ -986,11 +984,46 @@ func TestAgent_Metadata(t *testing.T) {
|
|||
})
|
||||
|
||||
t.Run("Many", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
//nolint:dogsled
|
||||
_, client, _, _, _ := setupAgent(t, agentsdk.Manifest{
|
||||
Metadata: []codersdk.WorkspaceAgentMetadataDescription{
|
||||
{
|
||||
Key: "greeting",
|
||||
Interval: 1,
|
||||
Timeout: 100,
|
||||
Script: echoHello,
|
||||
},
|
||||
},
|
||||
}, 0)
|
||||
|
||||
var gotMd map[string]agentsdk.PostMetadataRequest
|
||||
require.Eventually(t, func() bool {
|
||||
gotMd = client.getMetadata()
|
||||
return len(gotMd) == 1
|
||||
}, testutil.WaitShort, testutil.IntervalMedium)
|
||||
|
||||
collectedAt1 := gotMd["greeting"].CollectedAt
|
||||
if !assert.Equal(t, "hello", strings.TrimSpace(gotMd["greeting"].Value)) {
|
||||
t.Errorf("got: %+v", gotMd)
|
||||
}
|
||||
|
||||
if !assert.Eventually(t, func() bool {
|
||||
gotMd = client.getMetadata()
|
||||
return gotMd["greeting"].CollectedAt.After(collectedAt1)
|
||||
}, testutil.WaitShort, testutil.IntervalMedium) {
|
||||
t.Fatalf("expected metadata to be collected again")
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func TestAgentMetadata_Timing(t *testing.T) {
|
||||
if runtime.GOOS == "windows" {
|
||||
// Shell scripting in Windows is a pain, and we have already tested
|
||||
// that the OS logic works in the simpler "Once" test above.
|
||||
// that the OS logic works in the simpler tests.
|
||||
t.Skip()
|
||||
}
|
||||
testutil.SkipIfNotTiming(t)
|
||||
t.Parallel()
|
||||
|
||||
dir := t.TempDir()
|
||||
|
@ -1001,6 +1034,7 @@ func TestAgent_Metadata(t *testing.T) {
|
|||
greetingPath = filepath.Join(dir, "greeting")
|
||||
script = "echo hello | tee -a " + greetingPath
|
||||
)
|
||||
//nolint:dogsled
|
||||
_, client, _, _, _ := setupAgent(t, agentsdk.Manifest{
|
||||
Metadata: []codersdk.WorkspaceAgentMetadataDescription{
|
||||
{
|
||||
|
@ -1022,12 +1056,10 @@ func TestAgent_Metadata(t *testing.T) {
|
|||
|
||||
for start := time.Now(); time.Since(start) < testutil.WaitMedium; time.Sleep(testutil.IntervalMedium) {
|
||||
md := client.getMetadata()
|
||||
if len(md) != 2 {
|
||||
panic("unexpected number of metadata entries")
|
||||
}
|
||||
require.Len(t, md, 2, "got: %+v", md)
|
||||
|
||||
require.Equal(t, "hello\n", md["greeting"].Value)
|
||||
require.Equal(t, "exit status 1", md["bad"].Error)
|
||||
require.Equal(t, "run cmd: exit status 1", md["bad"].Error)
|
||||
|
||||
greetingByt, err := os.ReadFile(greetingPath)
|
||||
require.NoError(t, err)
|
||||
|
@ -1057,7 +1089,6 @@ func TestAgent_Metadata(t *testing.T) {
|
|||
t.Fatalf("too few greetings: %d < %d", numGreetings, lowerBound)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func TestAgent_Lifecycle(t *testing.T) {
|
||||
|
|
|
@ -0,0 +1,8 @@
|
|||
//go:build timing
|
||||
|
||||
package testutil
|
||||
|
||||
var _ = func() any {
|
||||
timing = true
|
||||
return nil
|
||||
}()
|
|
@ -0,0 +1,20 @@
|
|||
package testutil
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
// We can't run timing-sensitive tests in CI because of the
|
||||
// great variance in runner performance. Instead of not testing timing at all,
|
||||
// we relegate it to humans manually running certain tests with the "-timing"
|
||||
// flag from time to time.
|
||||
//
|
||||
// Eventually, we should run all timing tests in a self-hosted runner.
|
||||
|
||||
var timing bool
|
||||
|
||||
func SkipIfNotTiming(t *testing.T) {
|
||||
if !timing {
|
||||
t.Skip("skipping timing-sensitive test")
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue