github.com/Aoi-hosizora/ahlib-more@v1.5.1-0.20230404072844-256112befaf6/xpflag/xpflag_test.go (about)

     1  package xpflag
     2  
     3  import (
     4  	"errors"
     5  	"fmt"
     6  	"github.com/Aoi-hosizora/ahlib/xtesting"
     7  	"github.com/spf13/pflag"
     8  	"log"
     9  	"os"
    10  	"strings"
    11  	"testing"
    12  )
    13  
    14  func TestParse(t *testing.T) {
    15  	saved := _cmd
    16  	defer func() { _cmd = saved }()
    17  	saved2 := os.Args
    18  	defer func() { os.Args = saved2 }()
    19  	saved3 := _osStderr
    20  	defer func() { _osStderr = saved3 }()
    21  	saved4 := _osExit
    22  	defer func() { _osExit = saved4 }()
    23  
    24  	var pHelp *bool
    25  	var pConfig *string
    26  	define := func(includeError bool) {
    27  		_cmd = pflag.NewFlagSet("application", pflag.ContinueOnError) // avoid to influence global _cmd
    28  		_cmd.Usage = func() { DefaultUsage(_cmd) }
    29  		if includeError {
    30  			pHelp = Cmd().BoolP("help", "h", false, "show help message")
    31  		}
    32  		pConfig = Cmd().StringP("config", "c", "./config.json", "config file path")
    33  	}
    34  	sb := &strings.Builder{}
    35  	_osStderr = sb
    36  	exitCode := -1
    37  	_osExit = func(code int) {
    38  		exitCode = code
    39  	}
    40  
    41  	// 1. PrintUsage
    42  	xtesting.EmptyCollection(t, strings.TrimSpace(Cmd().FlagUsages()))
    43  	PrintUsage()
    44  	define(false)
    45  	xtesting.Equal(t, len(strings.Split(strings.TrimSpace(Cmd().FlagUsages()), "\n")), 1)
    46  	PrintUsage()
    47  	define(true)
    48  	xtesting.Equal(t, len(strings.Split(strings.TrimSpace(Cmd().FlagUsages()), "\n")), 2)
    49  	PrintUsage()
    50  
    51  	// => test normal parse
    52  	for _, tc := range []struct {
    53  		giveArgs  []string
    54  		wantError bool
    55  		checkFn   func()
    56  	}{
    57  		{[]string{}, false, func() {
    58  			xtesting.Equal(t, *pHelp, false)
    59  			xtesting.Equal(t, *pConfig, "./config.json")
    60  		}},
    61  		{[]string{"-x"}, true, nil},
    62  		{[]string{"-xxx"}, true, nil},
    63  		{[]string{"--xxx"}, true, nil},
    64  		{[]string{"-h", "-1"}, true, nil},
    65  		{[]string{"-x", "-c"}, true, nil},
    66  		{[]string{"-h", "123"}, false, func() {
    67  			xtesting.Equal(t, *pHelp, true)
    68  			xtesting.Equal(t, *pConfig, "./config.json")
    69  		}},
    70  		{[]string{"--help", "-h", "-c", "xxx"}, false, func() {
    71  			xtesting.Equal(t, *pHelp, true)
    72  			xtesting.Equal(t, *pConfig, "xxx")
    73  		}},
    74  		{[]string{"-c", "--help"}, false, func() {
    75  			xtesting.Equal(t, *pHelp, false)
    76  			xtesting.Equal(t, *pConfig, "--help")
    77  		}},
    78  	} {
    79  		t.Run(strings.Join(tc.giveArgs, " "), func(t *testing.T) {
    80  			os.Args = append([]string{"application"}, tc.giveArgs...)
    81  			define(true)
    82  
    83  			// 2. Parse
    84  			err := Parse()
    85  			xtesting.Equal(t, err != nil, tc.wantError)
    86  			if err == nil && tc.checkFn != nil {
    87  				tc.checkFn()
    88  			}
    89  
    90  			// 3. MustParse
    91  			sb.Reset()
    92  			exitCode = -1
    93  			MustParse()
    94  			if !tc.wantError {
    95  				xtesting.Equal(t, sb.String(), "")
    96  				xtesting.Equal(t, exitCode, -1) // success
    97  			} else {
    98  				log.Println(err)
    99  				firstLine := strings.Split(sb.String(), "\n")[0]
   100  				xtesting.Equal(t, firstLine, fmt.Sprintf("Error: %v", err))
   101  				xtesting.Equal(t, exitCode, 2)
   102  			}
   103  		})
   104  	}
   105  
   106  	// => test parse without help flag
   107  	for _, tc := range []struct {
   108  		giveArgs      []string
   109  		wantHelpError bool
   110  	}{
   111  		{[]string{""}, false},
   112  		{[]string{"-h"}, true},
   113  		{[]string{"--help"}, true},
   114  		{[]string{"-c -h"}, false},
   115  		{[]string{"-h -c"}, true},
   116  	} {
   117  		t.Run(strings.Join(tc.giveArgs, " "), func(t *testing.T) {
   118  			os.Args = append([]string{"application"}, tc.giveArgs...)
   119  			define(false)
   120  
   121  			// 4. Parse (for help)
   122  			err := Parse()
   123  			xtesting.Equal(t, errors.Is(err, pflag.ErrHelp), tc.wantHelpError)
   124  			log.Println(err) // may be "pflag: help requested"
   125  
   126  			// 5. MustParse (for help)
   127  			sb.Reset()
   128  			exitCode = -1
   129  			MustParse()
   130  			if !tc.wantHelpError {
   131  				xtesting.Equal(t, exitCode, -1) // success
   132  			} else {
   133  				xtesting.Equal(t, exitCode, 0)
   134  				xtesting.Equal(t, strings.Contains(sb.String(), pflag.ErrHelp.Error()), false)
   135  			}
   136  		})
   137  	}
   138  }