github.1git.de/docker/cli@v26.1.3+incompatible/cli/command/telemetry_utils_test.go (about) 1 package command 2 3 import ( 4 "bytes" 5 "context" 6 "io" 7 "reflect" 8 "strings" 9 "testing" 10 11 "github.com/docker/cli/cli/streams" 12 "github.com/spf13/cobra" 13 "go.opentelemetry.io/otel/attribute" 14 "gotest.tools/v3/assert" 15 ) 16 17 func setupCobraCommands() (*cobra.Command, *cobra.Command, *cobra.Command) { 18 rootCmd := &cobra.Command{ 19 Use: "root [OPTIONS] COMMAND [ARG...]", 20 } 21 childCmd := &cobra.Command{ 22 Use: "child [OPTIONS] COMMAND [ARG...]", 23 } 24 grandchildCmd := &cobra.Command{ 25 Use: "grandchild [OPTIONS] COMMAND [ARG...]", 26 } 27 childCmd.AddCommand(grandchildCmd) 28 rootCmd.AddCommand(childCmd) 29 30 return rootCmd, childCmd, grandchildCmd 31 } 32 33 func TestGetFullCommandName(t *testing.T) { 34 rootCmd, childCmd, grandchildCmd := setupCobraCommands() 35 36 t.Parallel() 37 38 for _, tc := range []struct { 39 testName string 40 cmd *cobra.Command 41 expected string 42 }{ 43 { 44 testName: "rootCmd", 45 cmd: rootCmd, 46 expected: "root", 47 }, 48 { 49 testName: "childCmd", 50 cmd: childCmd, 51 expected: "root child", 52 }, 53 { 54 testName: "grandChild", 55 cmd: grandchildCmd, 56 expected: "root child grandchild", 57 }, 58 } { 59 tc := tc 60 t.Run(tc.testName, func(t *testing.T) { 61 t.Parallel() 62 actual := getFullCommandName(tc.cmd) 63 assert.Equal(t, actual, tc.expected) 64 }) 65 } 66 } 67 68 func TestGetCommandName(t *testing.T) { 69 rootCmd, childCmd, grandchildCmd := setupCobraCommands() 70 71 t.Parallel() 72 73 for _, tc := range []struct { 74 testName string 75 cmd *cobra.Command 76 expected string 77 }{ 78 { 79 testName: "rootCmd", 80 cmd: rootCmd, 81 expected: "", 82 }, 83 { 84 testName: "childCmd", 85 cmd: childCmd, 86 expected: "child", 87 }, 88 { 89 testName: "grandchildCmd", 90 cmd: grandchildCmd, 91 expected: "child grandchild", 92 }, 93 } { 94 tc := tc 95 t.Run(tc.testName, func(t *testing.T) { 96 t.Parallel() 97 actual := getCommandName(tc.cmd) 98 assert.Equal(t, actual, tc.expected) 99 }) 100 } 101 } 102 103 func TestStdioAttributes(t *testing.T) { 104 outBuffer := new(bytes.Buffer) 105 errBuffer := new(bytes.Buffer) 106 t.Parallel() 107 for _, tc := range []struct { 108 test string 109 stdinTty bool 110 stdoutTty bool 111 // TODO(laurazard): test stderr 112 expected []attribute.KeyValue 113 }{ 114 { 115 test: "", 116 expected: []attribute.KeyValue{ 117 attribute.Bool("command.stdin.isatty", false), 118 attribute.Bool("command.stdout.isatty", false), 119 attribute.Bool("command.stderr.isatty", false), 120 }, 121 }, 122 { 123 test: "", 124 stdinTty: true, 125 stdoutTty: true, 126 expected: []attribute.KeyValue{ 127 attribute.Bool("command.stdin.isatty", true), 128 attribute.Bool("command.stdout.isatty", true), 129 attribute.Bool("command.stderr.isatty", false), 130 }, 131 }, 132 } { 133 tc := tc 134 t.Run(tc.test, func(t *testing.T) { 135 t.Parallel() 136 cli := &DockerCli{ 137 in: streams.NewIn(io.NopCloser(strings.NewReader(""))), 138 out: streams.NewOut(outBuffer), 139 err: errBuffer, 140 } 141 cli.In().SetIsTerminal(tc.stdinTty) 142 cli.Out().SetIsTerminal(tc.stdoutTty) 143 actual := stdioAttributes(cli) 144 145 assert.Check(t, reflect.DeepEqual(actual, tc.expected)) 146 }) 147 } 148 } 149 150 func TestAttributesFromError(t *testing.T) { 151 t.Parallel() 152 153 for _, tc := range []struct { 154 testName string 155 err error 156 expected []attribute.KeyValue 157 }{ 158 { 159 testName: "no error", 160 err: nil, 161 expected: []attribute.KeyValue{ 162 attribute.Int("command.status.code", 0), 163 }, 164 }, 165 { 166 testName: "non-0 exit code", 167 err: statusError{StatusCode: 127}, 168 expected: []attribute.KeyValue{ 169 attribute.String("command.error.type", "generic"), 170 attribute.Int("command.status.code", 127), 171 }, 172 }, 173 { 174 testName: "canceled", 175 err: context.Canceled, 176 expected: []attribute.KeyValue{ 177 attribute.String("command.error.type", "canceled"), 178 attribute.Int("command.status.code", 1), 179 }, 180 }, 181 } { 182 tc := tc 183 t.Run(tc.testName, func(t *testing.T) { 184 t.Parallel() 185 actual := attributesFromError(tc.err) 186 assert.Check(t, reflect.DeepEqual(actual, tc.expected)) 187 }) 188 } 189 }