Skip to content

Commit

Permalink
Coverage
Browse files Browse the repository at this point in the history
  • Loading branch information
devemlight committed Apr 10, 2022
1 parent f27f8e9 commit f219449
Show file tree
Hide file tree
Showing 35 changed files with 319 additions and 92 deletions.
11 changes: 7 additions & 4 deletions .github/workflows/go.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,14 @@ jobs:
with:
go-version: 1.18

- name: Lint
uses: golangci/golangci-lint-action@v2

- name: Build
run: make build

- name: Test
run: make test
- name: Run coverage
run: go test -race -coverprofile=coverage.out -covermode=atomic -tags test ./...

- name: Lint
uses: golangci/golangci-lint-action@v2
- name: Upload coverage to Codecov
uses: codecov/codecov-action@v2
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ build:
$(GO) build -o $(BIN)/$(APP) ./cmd/cli

test:
go test -v ./...
go test ./...

clean:
rm -f $(BIN)/$(APP)*
Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

<p align="center">
<a href="https://github.com/devemio/docker-color-output/actions/workflows/go.yml"><img src="https://img.shields.io/github/workflow/status/devemio/docker-color-output/Go"></a>
<a href="https://codecov.io/gh/devemio/docker-color-output"><img src="https://img.shields.io/codecov/c/gh/devemio/docker-color-output" alt="Coverage"></a>
<a href="https://github.com/devemio/docker-color-output/releases"><img src="https://img.shields.io/github/downloads/devemio/docker-color-output/total?color=brightgreen" alt="Downloads"></a>
<a href="https://github.com/devemio/docker-color-output/releases"><img src="https://img.shields.io/github/v/release/devemio/docker-color-output" alt="Release"></a>
<a href="https://opensource.org/licenses/MIT"><img src="https://img.shields.io/badge/license-MIT-green.svg" alt="License"></a>
Expand Down
18 changes: 4 additions & 14 deletions cmd/cli/main.go
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
//go:build !test

package main

import (
"docker-color-output/internal/cli"
"docker-color-output/internal/cmd"
"docker-color-output/internal/lines"
"docker-color-output/internal/lines/fmt"
"docker-color-output/internal/stdin"
"docker-color-output/internal/stdout"
)
Expand All @@ -15,21 +14,12 @@ func main() {
cli.Exit(err)
}

c, err := cmd.ParseCmd(in)
vals, err := cli.Execute(in)
if err != nil {
cli.Exit(err)
}

res := make([]*lines.Line, len(in))

cols, values := cmd.ParseFirstLine(in[0])
res[0] = lines.NewLine(values, cols, fmt.NewFirstLineFmt())

for i, values := range cmd.ParseLines(in[1:], cols) {
res[i+1] = lines.NewLine(values, cols, c.GetFmt())
}

for _, v := range res {
for _, v := range vals {
stdout.Println(v)
}
}
31 changes: 31 additions & 0 deletions internal/cli/app.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package cli

import (
"docker-color-output/internal/cmd"
"docker-color-output/internal/lines"
"docker-color-output/internal/lines/fmt"
)

func Execute(in []string) ([]*lines.Line, error) {
c, err := cmd.ParseCmd(in)
if err != nil {
return nil, err
}

res := make([]*lines.Line, len(in))

cols, vals := cmd.ParseFirstLine(in[0])

res[0] = lines.NewLine(vals, cols, fmt.NewFirstLineFmt())

pl, err := cmd.ParseLines(in[1:], cols)
if err != nil {
return nil, err
}

for i, vals := range pl {
res[i+1] = lines.NewLine(vals, cols, c.GetFmt())
}

return res, nil
}
58 changes: 58 additions & 0 deletions internal/cli/app_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
package cli

import (
"os"
"path/filepath"
"runtime"
"strings"
"testing"

"docker-color-output/internal/lines"
"docker-color-output/pkg/utils/assert"
)

func TestExecute(t *testing.T) {
read := func(filename string) []string {
_, b, _, _ := runtime.Caller(0)
path := filepath.Dir(b)
bytes, _ := os.ReadFile(path + "/../../test/data/" + filename)
vals := strings.Split(string(bytes), "\n")
vals = vals[:len(vals)-1]
if len(vals) == 0 {
return nil
}
return vals
}

build := func(in []*lines.Line) []string {
var vals []string
for _, v := range in {
vals = append(vals, v.Build())
}
return vals
}

tests := map[string]struct {
in string
want string
wantErr bool
}{
"no_stdin": {wantErr: true},
"no_first_line": {in: "in/no_first_line.out", wantErr: true},
"invalid_cols": {in: "in/invalid_cols.out", wantErr: true},
"docker_ps": {in: "in/docker_ps.out", want: "out/docker_ps.out"},
"docker_ps:custom_cols": {in: "in/docker_ps_custom_cols.out", want: "out/docker_ps_custom_cols.out"},
"docker_ps:nullable_col": {in: "in/docker_ps_nullable_col.out", want: "out/docker_ps_nullable_col.out"},
"docker_ps:nullable_cols": {in: "in/docker_ps_nullable_cols.out", wantErr: true},
"docker_images": {in: "in/docker_images.out", want: "out/docker_images.out"},
"docker_compose_ps": {in: "in/docker_compose_ps.out", want: "out/docker_compose_ps.out"},
}

for name, tt := range tests {
t.Run(name, func(t *testing.T) {
vals, err := Execute(read(tt.in))
assert.Equal(t, tt.wantErr, err != nil)
assert.Equal(t, read(tt.want), build(vals))
})
}
}
2 changes: 1 addition & 1 deletion internal/cli/constants.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package cli

const (
Ver = "2.2.0"
Ver = "2.2.0-rc.1"
App = "docker-color-output"
)
6 changes: 4 additions & 2 deletions internal/cli/cli.go → internal/cli/shutdown.go
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
//go:build !test

package cli

import (
Expand All @@ -12,8 +14,8 @@ func Exit(err error) {
fmt.Println(color.LightRed("💡 Error: " + err.Error()))
fmt.Println("💥 Docker color output " + color.Green(Ver))
fmt.Println("⚡️ Usage:")
fmt.Println(" " + color.Green(cmd.DockerImages.String()) + " | " + color.Brown(App))
fmt.Println(" " + color.Green(cmd.DockerPs.String()) + " [-a] | " + color.Brown(App))
fmt.Println(" " + color.Green(cmd.DockerComposePs.String()) + " [-a] | " + color.Brown(App))
fmt.Println(" " + color.Green(cmd.DockerImages.String()) + " [--format] | " + color.Brown(App))
fmt.Println(" " + color.Green(cmd.DockerPs.String()) + " [-a] [--format] | " + color.Brown(App))
os.Exit(1)
}
49 changes: 28 additions & 21 deletions internal/cmd/cmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,24 +2,19 @@ package cmd

import (
"errors"
"log"
"strings"

"docker-color-output/internal/lines"
"docker-color-output/internal/utils"
"docker-color-output/internal/utils/pointer"
"docker-color-output/pkg/color"
)

func ParseCmd(in []string) (Cmd, error) {
if len(in) == 0 {
if len(in) == 0 || len(in[0]) == 0 {
return "", errors.New("no first line")
}

parts := utils.Split(in[0])
if len(parts) == 0 {
return "", errors.New("no first line")
}

if utils.Intersect(parts, DockerPs.Columns()) {
return DockerPs, nil
Expand All @@ -36,41 +31,42 @@ func ParseCmd(in []string) (Cmd, error) {
return "", errors.New("invalid first line")
}

func ParseFirstLine(in string) ([]lines.Column, []string) {
func ParseFirstLine(in string) ([]lines.Column, lines.Values) {
parts := utils.Split(in)

cols := make([]lines.Column, len(parts))
values := make([]string, len(parts))
vals := make(lines.Values, len(parts))

for i, part := range parts {
cols[i] = lines.Column{
Name: part,
Len: pointer.ToInt(len(part)),
}

values[i] = part
vals[part] = part
}

return cols, values
return cols, vals
}

func ParseLines(ins []string, cols []lines.Column) [][]string {
rows := make([][]string, len(ins))
func ParseLines(ins []string, cols []lines.Column) ([]lines.Values, error) {
if calculateNullableCols(cols) > 1 {
return nil, errors.New("nullable columns more than one")
}

rows := make([]lines.Values, len(ins))

for i, in := range ins {
rows[i] = make([]string, len(cols))
rows[i] = make(lines.Values, len(cols))

parts := utils.Split(in)

offset := 0
mismatches := len(cols) - len(parts)
if mismatches > 1 {
log.Fatal(color.Red("nullable columns more than two")) // panic
}
mismatch := len(parts) < len(cols)

for j, col := range cols {
if mismatches > 0 && (col.Name == "PORTS" || col.Name == "MOUNTS") {
offset += 1
if mismatch && col.IsNullable() {
offset++
continue
}

Expand All @@ -85,9 +81,20 @@ func ParseLines(ins []string, cols []lines.Column) [][]string {
*col.Len = l
}

rows[i][j] = v
rows[i][col.Name] = v
}
}

return rows, nil
}

func calculateNullableCols(cols []lines.Column) byte {
var total byte = 0
for _, col := range cols {
if col.IsNullable() {
total++
}
}

return rows
return total
}
16 changes: 8 additions & 8 deletions internal/cmd/constants.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,17 +24,17 @@ func (c Cmd) Columns() []string {
"NAMES", //
"LABELS", // opt
"MOUNTS", // opt | nullable
"NETWORKS", // opt
"NETWORKS", // opt | nullable
}
case DockerImages:
return []string{
"IMAGE ID",
"REPOSITORY",
"TAG",
"DIGEST",
"CREATED",
"CREATED AT",
"SIZE",
"IMAGE ID", //
"REPOSITORY", //
"TAG", //
"DIGEST", // opt
"CREATED", //
"CREATED AT", // opt
"SIZE", //
}
case DockerComposePs:
return []string{
Expand Down
11 changes: 11 additions & 0 deletions internal/lines/contracts.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,14 @@ package lines
type Buildable interface {
Build() string
}

type Values map[string]string

type Column struct {
Name string
Len *int
}

func (c *Column) IsNullable() bool {
return c.Name == "PORTS" || c.Name == "MOUNTS" || c.Name == "NETWORKS"
}
2 changes: 1 addition & 1 deletion internal/lines/fmt/contracts.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
package fmt

type Formatable interface {
Format(col string, v string) string
Format(vals map[string]string, col string) string
}
15 changes: 8 additions & 7 deletions internal/lines/fmt/docker_compose_ps_line_fmt.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ func NewDockerComposePsLineFmt() *DockerComposePsLineFmt {
return &DockerComposePsLineFmt{}
}

func (*DockerComposePsLineFmt) Name(v string) string {
if strings.Contains(v, "exited") { // @fixme status
func (*DockerComposePsLineFmt) Name(v, status string) string {
if strings.Contains(status, "exited") {
return color.DarkGray(v)
}
return color.White(v)
Expand All @@ -23,8 +23,8 @@ func (*DockerComposePsLineFmt) Command(v string) string {
return color.DarkGray(v)
}

func (*DockerComposePsLineFmt) Service(v string) string {
if strings.Contains(v, "exited") { // @fixme status
func (*DockerComposePsLineFmt) Service(v, status string) string {
if strings.Contains(status, "exited") {
return color.DarkGray(v)
}
return color.Yellow(v)
Expand All @@ -49,14 +49,15 @@ func (*DockerComposePsLineFmt) Ports(v string) string {
return strings.Join(ports, ", ")
}

func (f *DockerComposePsLineFmt) Format(col string, v string) string {
func (f *DockerComposePsLineFmt) Format(vals map[string]string, col string) string {
v := vals[col]
switch col {
case "NAME":
return f.Name(v)
return f.Name(v, vals["STATUS"])
case "COMMAND":
return f.Command(v)
case "SERVICE":
return f.Service(v)
return f.Service(v, vals["STATUS"])
case "STATUS":
return f.Status(v)
case "PORTS":
Expand Down
Loading

0 comments on commit f219449

Please sign in to comment.