Skip to content

Commit

Permalink
adding list tests, reworked erroring to be testable
Browse files Browse the repository at this point in the history
  • Loading branch information
luthermonson committed Dec 25, 2023
1 parent 26733a7 commit 692eb81
Show file tree
Hide file tree
Showing 8 changed files with 166 additions and 74 deletions.
60 changes: 58 additions & 2 deletions cmd/main.go → cmd/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,61 @@ import (
"github.com/goodhosts/hostsfile"
"github.com/olekukonko/tablewriter"
"github.com/sirupsen/logrus"
easy "github.com/t-tomalak/logrus-easy-formatter"
"github.com/urfave/cli/v2"
)

var (
version string
App = &cli.App{
Name: "goodhosts",
Usage: "manage your hosts file goodly",
Action: DefaultAction,
Commands: append(Commands(), &cli.Command{
Name: "version",
Usage: "",
Aliases: []string{"v", "ver"},
Action: func(c *cli.Context) error {
logrus.Infof(version)
return nil
},
}),
Before: func(ctx *cli.Context) error {
if ctx.Bool("debug") {
logrus.SetLevel(logrus.DebugLevel)
logrus.SetFormatter(&logrus.TextFormatter{})
} else {
// treat logrus like fmt.Print
logrus.SetFormatter(&easy.Formatter{
LogFormat: "%msg%",
})
}
if ctx.Bool("quiet") {
logrus.SetOutput(io.Discard)
}
return nil
},
Flags: []cli.Flag{
&cli.StringFlag{
Name: "file",
Aliases: []string{"f"},
Value: "",
Usage: fmt.Sprintf("override the default hosts: %s", hostsfile.HostsFilePath),
},
&cli.BoolFlag{
Name: "debug",
Aliases: []string{"d"},
Usage: "Turn on verbose debug logging",
},
&cli.BoolFlag{
Name: "quiet",
Aliases: []string{"q"},
Usage: "Turn on off all logging",
},
},
}
)

func Commands() []*cli.Command {
return []*cli.Command{
Add(),
Expand All @@ -25,6 +77,10 @@ func Commands() []*cli.Command {
}
}

func Version(v string) {
version = v
}

func DefaultAction(c *cli.Context) error {
return list(c)
}
Expand All @@ -43,11 +99,11 @@ func loadHostsfile(c *cli.Context, readOnly bool) (*hostsfile.Hosts, error) {
}

if err != nil {
return hf, cli.Exit(err, 1)
return hf, err
}

if !readOnly && !hf.IsWritable() {
return hf, cli.Exit("Host file not writable. Try running with elevated privileges.", 1)
return hf, fmt.Errorf("Hostsfile %s not writable. Try running with elevated privileges.", hf.Path)
}

return hf, nil
Expand Down
36 changes: 36 additions & 0 deletions cmd/app_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package cmd

import (
"bytes"
"os"
"testing"

"github.com/stretchr/testify/assert"

"github.com/sirupsen/logrus"
)

// Setup takes args slice and resets logrus and returns args to pass to App.Run
func setup(args ...string) ([]string, *bytes.Buffer) {
out := &bytes.Buffer{}
logrus.SetOutput(out)
a := os.Args[0:1]
a = append(a, args...)
return a, out
}

func read(t *testing.T, name, file string) func() {
err := os.WriteFile(name, []byte(file), 0440)
assert.Nil(t, err)
return func() {
assert.Nil(t, os.Remove(name))
}
}

func write(t *testing.T, name, file string) func() {

Check failure on line 30 in cmd/app_test.go

View workflow job for this annotation

GitHub Actions / ci

func `write` is unused (unused)

Check failure on line 30 in cmd/app_test.go

View workflow job for this annotation

GitHub Actions / ci

func `write` is unused (unused)
err := os.WriteFile(name, []byte(file), 0770)
assert.Nil(t, err)
return func() {
assert.Nil(t, os.Remove(name))
}
}
2 changes: 1 addition & 1 deletion cmd/list.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ func List() *cli.Command {
}

func list(c *cli.Context) error {
hf, err := loadHostsfile(c, false)
hf, err := loadHostsfile(c, true)
if err != nil {
return err
}
Expand Down
24 changes: 24 additions & 0 deletions cmd/list_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package cmd

import (
"testing"

"github.com/stretchr/testify/assert"
)

func TestList(t *testing.T) {
args, out := setup("-f", "no-existy", "list")

Check failure on line 10 in cmd/list_test.go

View workflow job for this annotation

GitHub Actions / ci

ineffectual assignment to out (ineffassign)

Check failure on line 10 in cmd/list_test.go

View workflow job for this annotation

GitHub Actions / ci

ineffectual assignment to out (ineffassign)
err := App.Run(args)
assert.NotEmpty(t, err)
assert.Equal(t, "open no-existy: The system cannot find the file specified.", err.Error())

file := "list"
content := "127.0.0.1 localhost"

cleanup := read(t, file, content)
defer cleanup()

args, out = setup("-f", file, "list")
assert.Empty(t, App.Run(args))
assert.Equal(t, content+"\n", out.String())
}
2 changes: 1 addition & 1 deletion mage/test/test.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ func Build() error {
// Coverage run all unit tests and output coverage
func Coverage() error {
fmt.Println("Running Tests with Coverage...")
return sh.RunV("go", "test", "-v", "-coverprofile=coverage.txt", ".")
return sh.RunV("go", "test", "-v", "-coverprofile=coverage.txt", "./...")
}

// HTML display the html coverage report from the cover tool
Expand Down
14 changes: 13 additions & 1 deletion magefile.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"fmt"
"os"
"path/filepath"
"runtime"

"github.com/magefile/mage/mg"
"github.com/magefile/mage/sh"
Expand All @@ -33,11 +34,22 @@ func Ci() error {
return nil
}

// build goodhosts cli locally
func Build() error {
fmt.Println("Building goodhosts...")
out := "goodhosts"
if runtime.GOOS == "windows" {
out = "goodhosts.exe"
}
sh.RunV("go", "build", "-o", out, "main.go")
return nil
}

// run the linter
func Lint() error {
mg.Deps(install.Golangcilint)
fmt.Println("Running Linter...")
return sh.RunV("./bin/golangci-lint", "run")
return sh.RunV("golangci-lint", "run")
}

// delete files and paths made by mage
Expand Down
62 changes: 8 additions & 54 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,11 @@ package main

import (
"fmt"
"io"
"os"

"github.com/goodhosts/cli/cmd"
"github.com/goodhosts/hostsfile"
"github.com/sirupsen/logrus"
easy "github.com/t-tomalak/logrus-easy-formatter"
"github.com/urfave/cli/v2"

"github.com/goodhosts/cli/cmd"
)

var (
Expand All @@ -18,60 +15,17 @@ var (
date = "unknown"
)

var app = &cli.App{
Name: "goodhosts",
Usage: "manage your hosts file goodly",
Action: cmd.DefaultAction,
Commands: append(cmd.Commands(), &cli.Command{
Name: "version",
Usage: "",
Aliases: []string{"v", "ver"},
Action: func(c *cli.Context) error {
logrus.Infof("goodhosts %s@%s built on %s", version, commit, date)
return nil
},
}),
Before: func(ctx *cli.Context) error {
if ctx.Bool("debug") {
logrus.SetLevel(logrus.DebugLevel)
logrus.SetFormatter(&logrus.TextFormatter{})
} else {
// treat logrus like fmt.Print
logrus.SetFormatter(&easy.Formatter{
LogFormat: "%msg%",
})
}
if ctx.Bool("quiet") {
logrus.SetOutput(io.Discard)
}
return nil
},
Flags: []cli.Flag{
&cli.StringFlag{
Name: "file",
Aliases: []string{"f"},
Value: "",
Usage: fmt.Sprintf("override the default hosts: %s", hostsfile.HostsFilePath),
},
&cli.BoolFlag{
Name: "debug",
Aliases: []string{"d"},
Usage: "Turn on verbose debug logging",
},
&cli.BoolFlag{
Name: "quiet",
Aliases: []string{"q"},
Usage: "Turn on off all logging",
},
},
}

func main() {
if err := run(os.Args); err != nil {
logrus.Fatal(err)
}
}

func formatVersion(version, commit, date string) string {
return fmt.Sprintf("goodhosts %s@%s built on %s", version, commit, date)
}

func run(args []string) error {
return app.Run(args)
cmd.Version(formatVersion(version, commit, date))
return cmd.App.Run(args)
}
40 changes: 25 additions & 15 deletions main_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,36 +6,46 @@ import (
"strings"
"testing"

"github.com/goodhosts/cli/cmd"

"github.com/sirupsen/logrus"
"github.com/stretchr/testify/assert"
)

func TestVersion(t *testing.T) {
// Run exported in tests to let subcommands call the main run
// Setup takes args slice and resets logrus and returns args to pass to App.Run
func setup(args ...string) ([]string, *bytes.Buffer) {
out := &bytes.Buffer{}
logrus.SetOutput(out)
a := os.Args[0:1]
a = append(a, args...)
return a, out
}

args := os.Args[0:1]
args = append(args, "version")
func TestVersion(t *testing.T) {
// test version passed in run()
args, out := setup("version")
assert.Nil(t, run(args))
assert.Equal(t, "goodhosts dev@none built on unknown", out.String())

// test that version@commit + date work
args, out = setup("version")
cmd.Version(formatVersion("test-version", "test-commit", "test-date"))
assert.Nil(t, cmd.App.Run(args))
assert.Equal(t, "goodhosts test-version@test-commit built on test-date", out.String())

// reset for future tests
cmd.Version(formatVersion("dev", "none", "unknown"))
}

func TestDebug(t *testing.T) {
out := &bytes.Buffer{}
logrus.SetOutput(out)

args := os.Args[0:1]
args = append(args, "--debug", "version")
assert.Nil(t, run(args))
args, out := setup("--debug", "version")
assert.Nil(t, cmd.App.Run(args))
assert.True(t, strings.Contains(out.String(), "level=info msg=\"goodhosts dev@none built on unknown\""))
}

func TestQuiet(t *testing.T) {
out := &bytes.Buffer{}
logrus.SetOutput(out)

args := os.Args[0:1]
args = append(args, "--quiet", "version")
assert.Nil(t, run(args))
args, out := setup("--quiet", "version")
assert.Nil(t, cmd.App.Run(args))
assert.Empty(t, out.String())
}

0 comments on commit 692eb81

Please sign in to comment.