|
1 | 1 | package manager |
2 | 2 |
|
3 | 3 | import ( |
| 4 | + "context" |
4 | 5 | "testing" |
5 | 6 |
|
| 7 | + "github.com/docker/cli/cli/config/configfile" |
| 8 | + "github.com/spf13/cobra" |
6 | 9 | "gotest.tools/v3/assert" |
7 | 10 | is "gotest.tools/v3/assert/cmp" |
8 | 11 | ) |
9 | 12 |
|
| 13 | +type fakeConfigProvider struct { |
| 14 | + cfg *configfile.ConfigFile |
| 15 | +} |
| 16 | + |
| 17 | +func (f *fakeConfigProvider) ConfigFile() *configfile.ConfigFile { |
| 18 | + return f.cfg |
| 19 | +} |
| 20 | + |
10 | 21 | func TestGetNaiveFlags(t *testing.T) { |
11 | 22 | testCases := []struct { |
12 | 23 | args []string |
@@ -141,3 +152,71 @@ func TestAppendNextSteps(t *testing.T) { |
141 | 152 | }) |
142 | 153 | } |
143 | 154 | } |
| 155 | + |
| 156 | +func TestRunPluginHooksPassesErrorMessage(t *testing.T) { |
| 157 | + cfg := configfile.New("") |
| 158 | + cfg.Plugins = map[string]map[string]string{ |
| 159 | + "test-plugin": {"hooks": "build"}, |
| 160 | + } |
| 161 | + provider := &fakeConfigProvider{cfg: cfg} |
| 162 | + root := &cobra.Command{Use: "docker"} |
| 163 | + sub := &cobra.Command{Use: "build"} |
| 164 | + root.AddCommand(sub) |
| 165 | + |
| 166 | + // Should not panic with empty error message (success case) |
| 167 | + RunPluginHooks(context.Background(), provider, root, sub, []string{"build"}, "") |
| 168 | + |
| 169 | + // Should not panic with non-empty error message (failure case) |
| 170 | + RunPluginHooks(context.Background(), provider, root, sub, []string{"build"}, "exit status 1") |
| 171 | +} |
| 172 | + |
| 173 | +func TestInvokeAndCollectHooksForwardsErrorMessage(t *testing.T) { |
| 174 | + cfg := configfile.New("") |
| 175 | + cfg.Plugins = map[string]map[string]string{ |
| 176 | + "nonexistent": {"hooks": "build"}, |
| 177 | + } |
| 178 | + root := &cobra.Command{Use: "docker"} |
| 179 | + sub := &cobra.Command{Use: "build"} |
| 180 | + root.AddCommand(sub) |
| 181 | + |
| 182 | + // Plugin binary doesn't exist — invokeAndCollectHooks skips it |
| 183 | + // gracefully and returns empty. Verifies the error message path |
| 184 | + // doesn't cause issues when forwarded through the call chain. |
| 185 | + result := invokeAndCollectHooks( |
| 186 | + context.Background(), cfg, root, sub, |
| 187 | + "build", map[string]string{}, "exit status 1", |
| 188 | + ) |
| 189 | + assert.Check(t, is.Len(result, 0)) |
| 190 | +} |
| 191 | + |
| 192 | +func TestInvokeAndCollectHooksNoPlugins(t *testing.T) { |
| 193 | + cfg := configfile.New("") |
| 194 | + root := &cobra.Command{Use: "docker"} |
| 195 | + sub := &cobra.Command{Use: "build"} |
| 196 | + root.AddCommand(sub) |
| 197 | + |
| 198 | + result := invokeAndCollectHooks( |
| 199 | + context.Background(), cfg, root, sub, |
| 200 | + "build", map[string]string{}, "some error", |
| 201 | + ) |
| 202 | + assert.Check(t, is.Len(result, 0)) |
| 203 | +} |
| 204 | + |
| 205 | +func TestInvokeAndCollectHooksCancelledContext(t *testing.T) { |
| 206 | + cfg := configfile.New("") |
| 207 | + cfg.Plugins = map[string]map[string]string{ |
| 208 | + "test-plugin": {"hooks": "build"}, |
| 209 | + } |
| 210 | + root := &cobra.Command{Use: "docker"} |
| 211 | + sub := &cobra.Command{Use: "build"} |
| 212 | + root.AddCommand(sub) |
| 213 | + |
| 214 | + ctx, cancel := context.WithCancel(context.Background()) |
| 215 | + cancel() // cancel immediately |
| 216 | + |
| 217 | + result := invokeAndCollectHooks( |
| 218 | + ctx, cfg, root, sub, |
| 219 | + "build", map[string]string{}, "exit status 1", |
| 220 | + ) |
| 221 | + assert.Check(t, is.Nil(result)) |
| 222 | +} |
0 commit comments