Browse Source

cmd/fdroidcl: add first negative match tests

Also rework how sub-command flags work. If we use global flagsets, the
tests run into trouble as flagsets cannot be reused or reset.
pull/32/head
Daniel Martí 8 years ago
parent
commit
de9786478d
  1. 68
      cmd/fdroidcl/endtoend_test.go
  2. 14
      cmd/fdroidcl/main.go
  3. 25
      cmd/fdroidcl/search.go

68
cmd/fdroidcl/endtoend_test.go

@ -37,50 +37,50 @@ func TestCommands(t *testing.T) {
defer os.RemoveAll(dir)
testBasedir = dir
mustSucceed := func(t *testing.T, want string, cmd *Command, args ...string) {
mustRun(t, true, want, cmd, args...)
mustSucceed := func(t *testing.T, wantRe, negRe string, cmd *Command, args ...string) {
mustRun(t, true, wantRe, negRe, cmd, args...)
}
mustFail := func(t *testing.T, want string, cmd *Command, args ...string) {
mustRun(t, false, want, cmd, args...)
mustFail := func(t *testing.T, wantRe, negRe string, cmd *Command, args ...string) {
mustRun(t, false, wantRe, negRe, cmd, args...)
}
t.Run("Version", func(t *testing.T) {
mustSucceed(t, `^v`, cmdVersion)
mustSucceed(t, `^v`, ``, cmdVersion)
})
t.Run("SearchBeforeUpdate", func(t *testing.T) {
mustFail(t, `could not open index`, cmdSearch)
mustFail(t, `could not open index`, ``, cmdSearch)
})
t.Run("UpdateFirst", func(t *testing.T) {
mustSucceed(t, `done`, cmdUpdate)
mustSucceed(t, `done`, ``, cmdUpdate)
})
t.Run("UpdateCached", func(t *testing.T) {
mustSucceed(t, `not modified`, cmdUpdate)
mustSucceed(t, `not modified`, ``, cmdUpdate)
})
t.Run("SearchNoArgs", func(t *testing.T) {
mustSucceed(t, `F-Droid`, cmdSearch)
mustSucceed(t, `F-Droid`, ``, cmdSearch)
})
t.Run("SearchWithArgs", func(t *testing.T) {
mustSucceed(t, `F-Droid`, cmdSearch, "fdroid.fdroid")
mustSucceed(t, `F-Droid`, ``, cmdSearch, "fdroid.fdroid")
})
t.Run("SearchWithArgsNone", func(t *testing.T) {
mustSucceed(t, `^$`, cmdSearch, "nomatches")
mustSucceed(t, `^$`, ``, cmdSearch, "nomatches")
})
t.Run("SearchOnlyPackageNames", func(t *testing.T) {
mustSucceed(t, `^[^ ]*$`, cmdSearch, "-q", "fdroid.fdroid")
mustSucceed(t, `^[^ ]*$`, ``, cmdSearch, "-q", "fdroid.fdroid")
})
t.Run("ShowOne", func(t *testing.T) {
mustSucceed(t, `fdroid/fdroidclient`, cmdShow, "org.fdroid.fdroid")
mustSucceed(t, `fdroid/fdroidclient`, ``, cmdShow, "org.fdroid.fdroid")
})
t.Run("ShowMany", func(t *testing.T) {
mustSucceed(t, `fdroid/fdroidclient.*fdroid/privileged-extension`,
mustSucceed(t, `fdroid/fdroidclient.*fdroid/privileged-extension`, ``,
cmdShow, "org.fdroid.fdroid", "org.fdroid.fdroid.privileged")
})
t.Run("ListCategories", func(t *testing.T) {
mustSucceed(t, `Development`, cmdList, "categories")
mustSucceed(t, `Development`, ``, cmdList, "categories")
})
if err := startAdbIfNeeded(); err != nil {
@ -99,29 +99,49 @@ func TestCommands(t *testing.T) {
t.Log("skipping the device tests as too many were found via ADB")
}
t.Run("DevicesOne", func(t *testing.T) {
mustSucceed(t, `\n`, ``, cmdDevices)
})
// try to uninstall the app first
devices[0].Uninstall(chosenApp)
t.Run("UninstallMissing", func(t *testing.T) {
mustFail(t, `not installed$`, cmdUninstall, chosenApp)
mustFail(t, `not installed$`, ``, cmdUninstall, chosenApp)
})
t.Run("SearchInstalledMissing", func(t *testing.T) {
mustSucceed(t, ``, regexp.QuoteMeta(chosenApp), cmdSearch, "-i", "-q")
})
t.Run("SearchUpgradableMissing", func(t *testing.T) {
mustSucceed(t, ``, regexp.QuoteMeta(chosenApp), cmdSearch, "-u", "-q")
})
t.Run("InstallVersioned", func(t *testing.T) {
mustSucceed(t, `Installing `+regexp.QuoteMeta(chosenApp),
mustSucceed(t, `Installing `+regexp.QuoteMeta(chosenApp), ``,
cmdInstall, chosenApp+":1")
})
t.Run("SearchInstalled", func(t *testing.T) {
time.Sleep(3 * time.Second)
mustSucceed(t, regexp.QuoteMeta(chosenApp), ``, cmdSearch, "-i", "-q")
})
t.Run("SearchUpgradable", func(t *testing.T) {
mustSucceed(t, regexp.QuoteMeta(chosenApp), ``, cmdSearch, "-u", "-q")
})
t.Run("Upgrade", func(t *testing.T) {
mustSucceed(t, `Upgrading `+regexp.QuoteMeta(chosenApp),
mustSucceed(t, `Upgrading `+regexp.QuoteMeta(chosenApp), ``,
cmdUpgrade, chosenApp)
})
t.Run("SearchUpgradableUpToDate", func(t *testing.T) {
mustSucceed(t, ``, regexp.QuoteMeta(chosenApp), cmdSearch, "-u", "-q")
})
t.Run("UpgradeAlreadyInstalled", func(t *testing.T) {
mustFail(t, `is up to date$`, cmdUpgrade, chosenApp)
mustFail(t, `is up to date$`, ``, cmdUpgrade, chosenApp)
})
t.Run("UninstallExisting", func(t *testing.T) {
mustSucceed(t, `Uninstalling `+regexp.QuoteMeta(chosenApp),
mustSucceed(t, `Uninstalling `+regexp.QuoteMeta(chosenApp), ``,
cmdUninstall, chosenApp)
})
}
func mustRun(t *testing.T, success bool, wantRe string, cmd *Command, args ...string) {
func mustRun(t *testing.T, success bool, wantRe, negRe string, cmd *Command, args ...string) {
var buf bytes.Buffer
stdout, stderr = &buf, &buf
err := cmd.Run(args)
@ -139,4 +159,10 @@ func mustRun(t *testing.T, success bool, wantRe string, cmd *Command, args ...st
if !regexp.MustCompile(wantRe).MatchString(out) {
t.Fatalf("output does not match %#q:\n%s", wantRe, out)
}
if negRe != "" {
negRe = "(?sm)" + negRe
if regexp.MustCompile(negRe).MatchString(out) {
t.Fatalf("output does match %#q:\n%s", negRe, out)
}
}
}

14
cmd/fdroidcl/main.go

@ -115,9 +115,6 @@ type Command struct {
// Short is the short description.
Short string
// Flag is a set of flags specific to this command.
Flag flag.FlagSet
}
// Name returns the command's name: the first word in the usage line.
@ -130,13 +127,13 @@ func (c *Command) Name() string {
return name
}
func (c *Command) Usage() {
func (c *Command) usage(flagSet *flag.FlagSet) {
fmt.Fprintf(stderr, "Usage: %s %s [-h]\n", cmdName, c.UsageLine)
anyFlags := false
c.Flag.VisitAll(func(f *flag.Flag) { anyFlags = true })
flagSet.VisitAll(func(f *flag.Flag) { anyFlags = true })
if anyFlags {
fmt.Fprintf(stderr, "\nAvailable options:\n")
c.Flag.PrintDefaults()
flagSet.PrintDefaults()
}
os.Exit(2)
}
@ -202,10 +199,7 @@ func main() {
continue
}
readConfig()
cmd.Flag.Usage = func() { cmd.Usage() }
cmd.Flag.Parse(args[1:])
args = cmd.Flag.Args()
if err := cmd.Run(args); err != nil {
if err := cmd.Run(args[1:]); err != nil {
errExit("%s: %v\n", cmdName, err)
}
return

25
cmd/fdroidcl/search.go

@ -4,6 +4,7 @@
package main
import (
"flag"
"fmt"
"regexp"
"sort"
@ -19,20 +20,22 @@ var cmdSearch = &Command{
Short: "Search available apps",
}
var (
quiet = cmdSearch.Flag.Bool("q", false, "Print package names only")
installed = cmdSearch.Flag.Bool("i", false, "Filter installed apps")
updates = cmdSearch.Flag.Bool("u", false, "Filter apps with updates")
days = cmdSearch.Flag.Int("d", 0, "Select apps last updated in the last <n> days; a negative value drops them instead")
category = cmdSearch.Flag.String("c", "", "Filter apps by category")
sortBy = cmdSearch.Flag.String("o", "", "Sort order (added, updated)")
)
func init() {
cmdSearch.Run = runSearch
}
func runSearch(args []string) error {
var fset flag.FlagSet
var (
quiet = fset.Bool("q", false, "Print package names only")
installed = fset.Bool("i", false, "Filter installed apps")
updates = fset.Bool("u", false, "Filter apps with updates")
days = fset.Int("d", 0, "Select apps last updated in the last <n> days; a negative value drops them instead")
category = fset.String("c", "", "Filter apps by category")
sortBy = fset.String("o", "", "Sort order (added, updated)")
)
fset.Parse(args)
args = fset.Args()
if *installed && *updates {
return fmt.Errorf("-i is redundant if -u is specified")
}
@ -137,8 +140,7 @@ func printApps(apps []fdroidcl.App, inst map[string]adb.Package, device *adb.Dev
}
func descVersion(app fdroidcl.App, inst *adb.Package, device *adb.Device) string {
// With "-u" or "-i" option there must be a connected device
if *updates || *installed {
if inst != nil {
suggested := app.SuggestedApk(device)
if suggested != nil && inst.VCode < suggested.VCode {
return fmt.Sprintf("%s (%d) -> %s (%d)", inst.VName, inst.VCode,
@ -146,7 +148,6 @@ func descVersion(app fdroidcl.App, inst *adb.Package, device *adb.Device) string
}
return fmt.Sprintf("%s (%d)", inst.VName, inst.VCode)
}
// Without "-u" or "-i" we only have repositories indices
return fmt.Sprintf("%s (%d)", app.CVName, app.CVCode)
}

Loading…
Cancel
Save