DockerCLI/cli/command/telemetry_utils_test.go

190 lines
3.9 KiB
Go

package command
import (
"bytes"
"context"
"io"
"reflect"
"strings"
"testing"
"github.com/docker/cli/cli/streams"
"github.com/spf13/cobra"
"go.opentelemetry.io/otel/attribute"
"gotest.tools/v3/assert"
)
func setupCobraCommands() (*cobra.Command, *cobra.Command, *cobra.Command) {
rootCmd := &cobra.Command{
Use: "root [OPTIONS] COMMAND [ARG...]",
}
childCmd := &cobra.Command{
Use: "child [OPTIONS] COMMAND [ARG...]",
}
grandchildCmd := &cobra.Command{
Use: "grandchild [OPTIONS] COMMAND [ARG...]",
}
childCmd.AddCommand(grandchildCmd)
rootCmd.AddCommand(childCmd)
return rootCmd, childCmd, grandchildCmd
}
func TestGetFullCommandName(t *testing.T) {
rootCmd, childCmd, grandchildCmd := setupCobraCommands()
t.Parallel()
for _, tc := range []struct {
testName string
cmd *cobra.Command
expected string
}{
{
testName: "rootCmd",
cmd: rootCmd,
expected: "root",
},
{
testName: "childCmd",
cmd: childCmd,
expected: "root child",
},
{
testName: "grandChild",
cmd: grandchildCmd,
expected: "root child grandchild",
},
} {
tc := tc
t.Run(tc.testName, func(t *testing.T) {
t.Parallel()
actual := getFullCommandName(tc.cmd)
assert.Equal(t, actual, tc.expected)
})
}
}
func TestGetCommandName(t *testing.T) {
rootCmd, childCmd, grandchildCmd := setupCobraCommands()
t.Parallel()
for _, tc := range []struct {
testName string
cmd *cobra.Command
expected string
}{
{
testName: "rootCmd",
cmd: rootCmd,
expected: "",
},
{
testName: "childCmd",
cmd: childCmd,
expected: "child",
},
{
testName: "grandchildCmd",
cmd: grandchildCmd,
expected: "child grandchild",
},
} {
tc := tc
t.Run(tc.testName, func(t *testing.T) {
t.Parallel()
actual := getCommandName(tc.cmd)
assert.Equal(t, actual, tc.expected)
})
}
}
func TestStdioAttributes(t *testing.T) {
outBuffer := new(bytes.Buffer)
errBuffer := new(bytes.Buffer)
t.Parallel()
for _, tc := range []struct {
test string
stdinTty bool
stdoutTty bool
// TODO(laurazard): test stderr
expected []attribute.KeyValue
}{
{
test: "",
expected: []attribute.KeyValue{
attribute.Bool("command.stdin.isatty", false),
attribute.Bool("command.stdout.isatty", false),
attribute.Bool("command.stderr.isatty", false),
},
},
{
test: "",
stdinTty: true,
stdoutTty: true,
expected: []attribute.KeyValue{
attribute.Bool("command.stdin.isatty", true),
attribute.Bool("command.stdout.isatty", true),
attribute.Bool("command.stderr.isatty", false),
},
},
} {
tc := tc
t.Run(tc.test, func(t *testing.T) {
t.Parallel()
cli := &DockerCli{
in: streams.NewIn(io.NopCloser(strings.NewReader(""))),
out: streams.NewOut(outBuffer),
err: errBuffer,
}
cli.In().SetIsTerminal(tc.stdinTty)
cli.Out().SetIsTerminal(tc.stdoutTty)
actual := stdioAttributes(cli)
assert.Check(t, reflect.DeepEqual(actual, tc.expected))
})
}
}
func TestAttributesFromError(t *testing.T) {
t.Parallel()
for _, tc := range []struct {
testName string
err error
expected []attribute.KeyValue
}{
{
testName: "no error",
err: nil,
expected: []attribute.KeyValue{
attribute.Int("command.status.code", 0),
},
},
{
testName: "non-0 exit code",
err: statusError{StatusCode: 127},
expected: []attribute.KeyValue{
attribute.String("command.error.type", "generic"),
attribute.Int("command.status.code", 127),
},
},
{
testName: "canceled",
err: context.Canceled,
expected: []attribute.KeyValue{
attribute.String("command.error.type", "canceled"),
attribute.Int("command.status.code", 1),
},
},
} {
tc := tc
t.Run(tc.testName, func(t *testing.T) {
t.Parallel()
actual := attributesFromError(tc.err)
assert.Check(t, reflect.DeepEqual(actual, tc.expected))
})
}
}