github.com/pwn-term/docker@v0.0.0-20210616085119-6e977cce2565/cli/e2e/cli-plugins/help_test.go (about)

     1  package cliplugins
     2  
     3  import (
     4  	"bufio"
     5  	"regexp"
     6  	"strings"
     7  	"testing"
     8  
     9  	"gotest.tools/v3/assert"
    10  	is "gotest.tools/v3/assert/cmp"
    11  	"gotest.tools/v3/icmd"
    12  )
    13  
    14  // TestGlobalHelp ensures correct behaviour when running `docker help`
    15  func TestGlobalHelp(t *testing.T) {
    16  	run, _, cleanup := prepare(t)
    17  	defer cleanup()
    18  
    19  	res := icmd.RunCmd(run("help"))
    20  	res.Assert(t, icmd.Expected{
    21  		ExitCode: 0,
    22  	})
    23  	assert.Assert(t, is.Equal(res.Stderr(), ""))
    24  	scanner := bufio.NewScanner(strings.NewReader(res.Stdout()))
    25  
    26  	// Instead of baking in the full current output of `docker
    27  	// help`, which can be expected to change regularly, bake in
    28  	// some checkpoints. Key things we are looking for:
    29  	//
    30  	//  - The top-level description
    31  	//  - Each of the main headings
    32  	//  - Some builtin commands under the main headings
    33  	//  - The `helloworld` plugin in the appropriate place
    34  	//  - The `badmeta` plugin under the "Invalid Plugins" heading.
    35  	//
    36  	// Regexps are needed because the width depends on `unix.TIOCGWINSZ` or similar.
    37  	helloworldre := regexp.MustCompile(`^  helloworld\*\s+A basic Hello World plugin for tests \(Docker Inc\., testing\)$`)
    38  	badmetare := regexp.MustCompile(`^  badmeta\s+invalid metadata: invalid character 'i' looking for beginning of object key string$`)
    39  	var helloworldcount, badmetacount int
    40  	for _, expected := range []*regexp.Regexp{
    41  		regexp.MustCompile(`^A self-sufficient runtime for containers$`),
    42  		regexp.MustCompile(`^Management Commands:$`),
    43  		regexp.MustCompile(`^  container\s+Manage containers$`),
    44  		helloworldre,
    45  		regexp.MustCompile(`^  image\s+Manage images$`),
    46  		regexp.MustCompile(`^Commands:$`),
    47  		regexp.MustCompile(`^  create\s+Create a new container$`),
    48  		regexp.MustCompile(`^Invalid Plugins:$`),
    49  		badmetare,
    50  		nil, // scan to end of input rather than stopping at badmetare
    51  	} {
    52  		var found bool
    53  		for scanner.Scan() {
    54  			text := scanner.Text()
    55  			if helloworldre.MatchString(text) {
    56  				helloworldcount++
    57  			}
    58  			if badmetare.MatchString(text) {
    59  				badmetacount++
    60  			}
    61  
    62  			if expected != nil && expected.MatchString(text) {
    63  				found = true
    64  				break
    65  			}
    66  		}
    67  		assert.Assert(t, expected == nil || found, "Did not find match for %q in `docker help` output", expected)
    68  	}
    69  	// We successfully scanned all the input
    70  	assert.Assert(t, !scanner.Scan())
    71  	assert.NilError(t, scanner.Err())
    72  	// Plugins should only be listed once.
    73  	assert.Assert(t, is.Equal(helloworldcount, 1))
    74  	assert.Assert(t, is.Equal(badmetacount, 1))
    75  
    76  	// Running with `--help` should produce the same.
    77  	t.Run("help_flag", func(t *testing.T) {
    78  		res2 := icmd.RunCmd(run("--help"))
    79  		res2.Assert(t, icmd.Expected{
    80  			ExitCode: 0,
    81  		})
    82  		assert.Assert(t, is.Equal(res2.Stdout(), res.Stdout()))
    83  		assert.Assert(t, is.Equal(res2.Stderr(), ""))
    84  	})
    85  
    86  	// Running just `docker` (without `help` nor `--help`) should produce the same thing, except on Stderr.
    87  	t.Run("bare", func(t *testing.T) {
    88  		res2 := icmd.RunCmd(run())
    89  		res2.Assert(t, icmd.Expected{
    90  			ExitCode: 0,
    91  		})
    92  		assert.Assert(t, is.Equal(res2.Stdout(), ""))
    93  		assert.Assert(t, is.Equal(res2.Stderr(), res.Stdout()))
    94  	})
    95  
    96  	t.Run("badopt", func(t *testing.T) {
    97  		// Running `docker --badopt` should also produce the
    98  		// same thing, give or take the leading error message
    99  		// and a trailing carriage return (due to main() using
   100  		// Println in the error case).
   101  		res2 := icmd.RunCmd(run("--badopt"))
   102  		res2.Assert(t, icmd.Expected{
   103  			ExitCode: 125,
   104  		})
   105  		assert.Assert(t, is.Equal(res2.Stdout(), ""))
   106  		exp := "unknown flag: --badopt\nSee 'docker --help'.\n" + res.Stdout() + "\n"
   107  		assert.Assert(t, is.Equal(res2.Stderr(), exp))
   108  	})
   109  }