Skip to content

Commit d25630f

Browse files
authored
Merge pull request #17 from zmap/phillip/validate-after-defaults
Validate flags after setting defaults
2 parents c5e486f + eaeb12e commit d25630f

File tree

2 files changed

+89
-4
lines changed

2 files changed

+89
-4
lines changed

ini.go

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -605,10 +605,7 @@ func (i *IniParser) parse(ini *ini) ([]string, []interface{}, error) {
605605
if name != "" && name != "Application Options" {
606606
c := i.parser.Find(name)
607607
if c != nil {
608-
if cmd, ok := c.data.(ZCommander); ok {
609-
if err := cmd.Validate([]string{}); err != nil { //validate
610-
log.Fatal(err)
611-
}
608+
if _, ok := c.data.(ZCommander); ok {
612609
modTypes = append(modTypes, name)
613610
returnFlags = append(returnFlags, c.data)
614611
par, _ := c.parent.(*Command)
@@ -629,6 +626,15 @@ func (i *IniParser) parse(ini *ini) ([]string, []interface{}, error) {
629626

630627
option.clearDefault()
631628
})
629+
// Validate the options after all default settings set
630+
631+
p.eachCommand(func(c *Command) {
632+
if cmd, ok := c.data.(ZCommander); ok {
633+
if err := cmd.Validate([]string{}); err != nil { //validate
634+
log.Fatal(err)
635+
}
636+
}
637+
}, true)
632638
// TODO: checkRequired?
633639

634640
for opt, quoted := range quotesLookup {

ini_test.go

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -451,6 +451,85 @@ int-map = b:3
451451
}
452452
}
453453

454+
type testCmd struct{}
455+
type testCmdFlags struct {
456+
Senders int `long:"senders" description:"Number of parallel senders" default:"10"`
457+
Destination string `long:"destination" description:"Destination address to send messages" default:"localhost:8080"`
458+
SrcPort uint `long:"source-port" description:"Source port for msgs" default:"24"`
459+
}
460+
461+
func (opt *testCmdFlags) Validate(_ []string) error {
462+
// Ensures default was used
463+
if opt.Senders <= 0 {
464+
return fmt.Errorf("senders must be positive")
465+
}
466+
if len(opt.Destination) == 0 {
467+
return fmt.Errorf("destination must be specified")
468+
}
469+
if opt.SrcPort == 0 {
470+
return fmt.Errorf("source port must be specified")
471+
}
472+
return nil
473+
}
474+
func (opt *testCmdFlags) Help() string {
475+
return "Help for testCmdFlags"
476+
}
477+
func (opt *testCmd) NewFlags() any {
478+
return new(testCmdFlags)
479+
}
480+
func TestZCommanderIni(t *testing.T) {
481+
type applicationOptions struct {
482+
Verbose []bool `long:"verbose" description:"Show verbose debug information"`
483+
}
484+
var appOpts applicationOptions
485+
var module testCmd
486+
487+
p := NewNamedParser("TestIni", Default)
488+
p.AddGroup("Application Options", "The application options", &appOpts)
489+
p.AddCommand("scan", "scan module", "A mock scanner module", &module)
490+
491+
inip := NewIniParser(p)
492+
493+
inic := `
494+
; Show verbose debug information
495+
[Application Options]
496+
verbose = true
497+
verbose = true
498+
499+
500+
[scan]
501+
senders = 20
502+
destination = example.com:9090
503+
504+
`
505+
b := strings.NewReader(inic)
506+
registeredCmds, registeredFlags, err := inip.Parse(b)
507+
508+
if err != nil {
509+
t.Fatalf("Unexpected error: %s", err)
510+
}
511+
512+
assertBoolArray(t, appOpts.Verbose, []bool{true, true})
513+
if registeredCmds[0] != "scan" {
514+
t.Fatalf("Expected registered command = scan, but got %s", registeredCmds[0])
515+
}
516+
flags, ok := registeredFlags[0].(*testCmdFlags)
517+
if !ok {
518+
t.Fatalf("Expected registered flags to be of type *testCmdFlags")
519+
}
520+
if flags.Senders != 20 {
521+
t.Fatalf("Expected senders = 20, but got %d", flags.Senders)
522+
}
523+
if flags.Destination != "example.com:9090" {
524+
t.Fatalf("Expected destination = example.com:9090, but got %s", flags.Destination)
525+
}
526+
527+
// We didn't set this, so just checking that default was preserved
528+
if flags.SrcPort != 24 {
529+
t.Fatalf("Expected source-port = 24, but got %d", flags.SrcPort)
530+
}
531+
}
532+
454533
func TestReadAndWriteIni(t *testing.T) {
455534
var tests = []struct {
456535
options IniOptions

0 commit comments

Comments
 (0)