File: spec_test.go

package info (click to toggle)
golang-sourcehut-rjarry-go-opt 2.0.1-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 148 kB
  • sloc: makefile: 2
file content (112 lines) | stat: -rw-r--r-- 2,495 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
package opt_test

import (
	"fmt"
	"testing"

	"git.sr.ht/~rjarry/go-opt/v2"
	"github.com/stretchr/testify/assert"
)

type OptionStruct struct {
	Jobs    int     `opt:"-j,--jobs" required:"true"`
	Delay   float64 `opt:"--delay" default:"0.5"`
	Zero    bool    `opt:"-z" aliases:"baz"`
	Backoff bool    `opt:"-B,--backoff"`
	Name    string  `opt:"name" aliases:"bar" action:"ParseName"`
}

func (o *OptionStruct) ParseName(arg string) error {
	if arg == "invalid" {
		return fmt.Errorf("%q invalid value", arg)
	}
	o.Name = arg
	return nil
}

func TestArgsToStructErrors(t *testing.T) {
	vectors := []struct {
		cmdline string
		err     string
	}{
		{"foo", "-j is required"},
		{"foo -j", "-j takes a value"},
		{"foo --delay -B", "--delay takes a value"},
		{"bar -j4", "<name> is required"},
		{"foo -j f", `strconv.ParseInt: parsing "f": invalid syntax.`},
		{"foo --delay=m", `strconv.ParseFloat: parsing "m": invalid syntax.`},
		{"foo --jobs 8 baz", `"baz" unexpected argument`},
		{"foo -u8 hop", `"-u8" unexpected argument`},
		{"foo -z", `"-z" unexpected argument`},
		{"bar -j4 foo baz", `"baz" unexpected argument`},
		{"bar -j4 invalid", `invalid value`},
	}

	for _, v := range vectors {
		t.Run(v.cmdline, func(t *testing.T) {
			err := opt.CmdlineToStruct(v.cmdline, new(OptionStruct))
			assert.ErrorContains(t, err, v.err)
		})
	}

	spec := opt.NewCmdSpec("bar", new(OptionStruct))
	assert.Equal(t, spec.Usage(), "bar -j <jobs> [--delay <delay>] [-B] <name>")
}

func TestArgsToStruct(t *testing.T) {
	vectors := []struct {
		cmdline  string
		expected OptionStruct
	}{
		{
			cmdline: `bar -j4 'f o o \(°</ f o o'`,
			expected: OptionStruct{
				Jobs:  4,
				Delay: 0.5,
				Name:  `f o o \(°</ f o o`,
			},
		},
		{
			cmdline: "foo --delay 0.1 -Bj 8",
			expected: OptionStruct{
				Jobs:    8,
				Delay:   0.1,
				Backoff: true,
			},
		},
		{
			cmdline: `baz -Bz --delay=0.1 -j8`,
			expected: OptionStruct{
				Jobs:    8,
				Delay:   0.1,
				Zero:    true,
				Backoff: true,
			},
		},
		{
			cmdline: `bar 'n a m e' -j7 --backoff`,
			expected: OptionStruct{
				Jobs:    7,
				Delay:   0.5,
				Backoff: true,
				Name:    "n a m e",
			},
		},
		{
			cmdline: `bar -j3 -- -j7`,
			expected: OptionStruct{
				Jobs:  3,
				Delay: 0.5,
				Name:  "-j7",
			},
		},
	}

	for _, v := range vectors {
		t.Run(v.cmdline, func(t *testing.T) {
			var s OptionStruct
			assert.Nil(t, opt.CmdlineToStruct(v.cmdline, &s))
			assert.Equal(t, v.expected, s)
		})
	}
}