github.1git.de/docker/cli@v26.1.3+incompatible/cli/command/volume/prune_test.go (about)

     1  package volume
     2  
     3  import (
     4  	"context"
     5  	"fmt"
     6  	"io"
     7  	"runtime"
     8  	"strings"
     9  	"testing"
    10  
    11  	"github.com/docker/cli/cli/streams"
    12  	"github.com/docker/cli/internal/test"
    13  	"github.com/docker/docker/api/types"
    14  	"github.com/docker/docker/api/types/filters"
    15  	"github.com/pkg/errors"
    16  	"gotest.tools/v3/assert"
    17  	is "gotest.tools/v3/assert/cmp"
    18  	"gotest.tools/v3/golden"
    19  	"gotest.tools/v3/skip"
    20  )
    21  
    22  func TestVolumePruneErrors(t *testing.T) {
    23  	testCases := []struct {
    24  		name            string
    25  		args            []string
    26  		flags           map[string]string
    27  		volumePruneFunc func(args filters.Args) (types.VolumesPruneReport, error)
    28  		expectedError   string
    29  	}{
    30  		{
    31  			name:          "accepts no arguments",
    32  			args:          []string{"foo"},
    33  			expectedError: "accepts no argument",
    34  		},
    35  		{
    36  			name: "forced but other error",
    37  			flags: map[string]string{
    38  				"force": "true",
    39  			},
    40  			volumePruneFunc: func(args filters.Args) (types.VolumesPruneReport, error) {
    41  				return types.VolumesPruneReport{}, errors.Errorf("error pruning volumes")
    42  			},
    43  			expectedError: "error pruning volumes",
    44  		},
    45  		{
    46  			name: "conflicting options",
    47  			flags: map[string]string{
    48  				"all":    "true",
    49  				"filter": "all=1",
    50  			},
    51  			expectedError: "conflicting options: cannot specify both --all and --filter all=1",
    52  		},
    53  	}
    54  	for _, tc := range testCases {
    55  		tc := tc
    56  		t.Run(tc.name, func(t *testing.T) {
    57  			cmd := NewPruneCommand(
    58  				test.NewFakeCli(&fakeClient{
    59  					volumePruneFunc: tc.volumePruneFunc,
    60  				}),
    61  			)
    62  			cmd.SetArgs(tc.args)
    63  			for key, value := range tc.flags {
    64  				cmd.Flags().Set(key, value)
    65  			}
    66  			cmd.SetOut(io.Discard)
    67  			cmd.SetErr(io.Discard)
    68  			assert.ErrorContains(t, cmd.Execute(), tc.expectedError)
    69  		})
    70  	}
    71  }
    72  
    73  func TestVolumePruneSuccess(t *testing.T) {
    74  	testCases := []struct {
    75  		name            string
    76  		args            []string
    77  		input           string
    78  		volumePruneFunc func(args filters.Args) (types.VolumesPruneReport, error)
    79  	}{
    80  		{
    81  			name:  "all",
    82  			args:  []string{"--all"},
    83  			input: "y",
    84  			volumePruneFunc: func(pruneFilter filters.Args) (types.VolumesPruneReport, error) {
    85  				assert.Check(t, is.DeepEqual([]string{"true"}, pruneFilter.Get("all")))
    86  				return types.VolumesPruneReport{}, nil
    87  			},
    88  		},
    89  		{
    90  			name: "all-forced",
    91  			args: []string{"--all", "--force"},
    92  			volumePruneFunc: func(pruneFilter filters.Args) (types.VolumesPruneReport, error) {
    93  				return types.VolumesPruneReport{}, nil
    94  			},
    95  		},
    96  		{
    97  			name:  "label-filter",
    98  			args:  []string{"--filter", "label=foobar"},
    99  			input: "y",
   100  			volumePruneFunc: func(pruneFilter filters.Args) (types.VolumesPruneReport, error) {
   101  				assert.Check(t, is.DeepEqual([]string{"foobar"}, pruneFilter.Get("label")))
   102  				return types.VolumesPruneReport{}, nil
   103  			},
   104  		},
   105  	}
   106  	for _, tc := range testCases {
   107  		tc := tc
   108  		t.Run(tc.name, func(t *testing.T) {
   109  			cli := test.NewFakeCli(&fakeClient{volumePruneFunc: tc.volumePruneFunc})
   110  			cmd := NewPruneCommand(cli)
   111  			if tc.input != "" {
   112  				cli.SetIn(streams.NewIn(io.NopCloser(strings.NewReader(tc.input))))
   113  			}
   114  			cmd.SetOut(io.Discard)
   115  			cmd.SetArgs(tc.args)
   116  			err := cmd.Execute()
   117  			assert.NilError(t, err)
   118  			golden.Assert(t, cli.OutBuffer().String(), fmt.Sprintf("volume-prune-success.%s.golden", tc.name))
   119  		})
   120  	}
   121  }
   122  
   123  func TestVolumePruneForce(t *testing.T) {
   124  	testCases := []struct {
   125  		name            string
   126  		volumePruneFunc func(args filters.Args) (types.VolumesPruneReport, error)
   127  	}{
   128  		{
   129  			name: "empty",
   130  		},
   131  		{
   132  			name:            "deletedVolumes",
   133  			volumePruneFunc: simplePruneFunc,
   134  		},
   135  	}
   136  	for _, tc := range testCases {
   137  		cli := test.NewFakeCli(&fakeClient{
   138  			volumePruneFunc: tc.volumePruneFunc,
   139  		})
   140  		cmd := NewPruneCommand(cli)
   141  		cmd.Flags().Set("force", "true")
   142  		assert.NilError(t, cmd.Execute())
   143  		golden.Assert(t, cli.OutBuffer().String(), fmt.Sprintf("volume-prune.%s.golden", tc.name))
   144  	}
   145  }
   146  
   147  func TestVolumePrunePromptYes(t *testing.T) {
   148  	// FIXME(vdemeester) make it work..
   149  	skip.If(t, runtime.GOOS == "windows", "TODO: fix test on windows")
   150  
   151  	for _, input := range []string{"y", "Y"} {
   152  		cli := test.NewFakeCli(&fakeClient{
   153  			volumePruneFunc: simplePruneFunc,
   154  		})
   155  
   156  		cli.SetIn(streams.NewIn(io.NopCloser(strings.NewReader(input))))
   157  		cmd := NewPruneCommand(cli)
   158  		cmd.SetArgs([]string{})
   159  		assert.NilError(t, cmd.Execute())
   160  		golden.Assert(t, cli.OutBuffer().String(), "volume-prune-yes.golden")
   161  	}
   162  }
   163  
   164  func TestVolumePrunePromptNo(t *testing.T) {
   165  	// FIXME(vdemeester) make it work..
   166  	skip.If(t, runtime.GOOS == "windows", "TODO: fix test on windows")
   167  
   168  	for _, input := range []string{"n", "N", "no", "anything", "really"} {
   169  		cli := test.NewFakeCli(&fakeClient{
   170  			volumePruneFunc: simplePruneFunc,
   171  		})
   172  
   173  		cli.SetIn(streams.NewIn(io.NopCloser(strings.NewReader(input))))
   174  		cmd := NewPruneCommand(cli)
   175  		cmd.SetArgs([]string{})
   176  		assert.ErrorContains(t, cmd.Execute(), "volume prune has been cancelled")
   177  		golden.Assert(t, cli.OutBuffer().String(), "volume-prune-no.golden")
   178  	}
   179  }
   180  
   181  func simplePruneFunc(filters.Args) (types.VolumesPruneReport, error) {
   182  	return types.VolumesPruneReport{
   183  		VolumesDeleted: []string{
   184  			"foo", "bar", "baz",
   185  		},
   186  		SpaceReclaimed: 2000,
   187  	}, nil
   188  }
   189  
   190  func TestVolumePrunePromptTerminate(t *testing.T) {
   191  	ctx, cancel := context.WithCancel(context.Background())
   192  	t.Cleanup(cancel)
   193  
   194  	cli := test.NewFakeCli(&fakeClient{
   195  		volumePruneFunc: func(filter filters.Args) (types.VolumesPruneReport, error) {
   196  			return types.VolumesPruneReport{}, errors.New("fakeClient volumePruneFunc should not be called")
   197  		},
   198  	})
   199  
   200  	cmd := NewPruneCommand(cli)
   201  	cmd.SetArgs([]string{})
   202  	test.TerminatePrompt(ctx, t, cmd, cli)
   203  	golden.Assert(t, cli.OutBuffer().String(), "volume-prune-terminate.golden")
   204  }