-
Notifications
You must be signed in to change notification settings - Fork 5.3k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
This changes the output format of `compose top` and inlines the service container name into the table. Previously, `compose top` had printed something like: <service name> UID PID ... root 1 ... Now, the output looks more like this: SERVICE UID PID ... <name> root 1 ...
- Loading branch information
Showing
2 changed files
with
347 additions
and
17 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,297 @@ | ||
package compose | ||
|
||
import ( | ||
"bytes" | ||
"strings" | ||
"testing" | ||
|
||
"github.com/docker/compose/v2/pkg/api" | ||
"github.com/stretchr/testify/assert" | ||
"github.com/stretchr/testify/require" | ||
) | ||
|
||
var topTestCases = []struct { | ||
name string | ||
titles []string | ||
procs [][]string | ||
|
||
header topHeader | ||
entries []topEntries | ||
output string | ||
}{ | ||
{ | ||
name: "noprocs", | ||
titles: []string{"UID", "PID", "PPID", "C", "STIME", "TTY", "TIME", "CMD"}, | ||
procs: [][]string{}, | ||
header: topHeader{"SERVICE": 0}, | ||
entries: []topEntries{}, | ||
output: "", | ||
}, | ||
{ | ||
name: "simple", | ||
titles: []string{"UID", "PID", "PPID", "C", "STIME", "TTY", "TIME", "CMD"}, | ||
procs: [][]string{{"root", "1", "1", "0", "12:00", "?", "00:00:01", "/entrypoint"}}, | ||
header: topHeader{ | ||
"SERVICE": 0, | ||
"UID": 1, | ||
"PID": 2, | ||
"PPID": 3, | ||
"C": 4, | ||
"STIME": 5, | ||
"TTY": 6, | ||
"TIME": 7, | ||
"CMD": 8, | ||
}, | ||
entries: []topEntries{ | ||
{ | ||
"SERVICE": "simple", | ||
"UID": "root", | ||
"PID": "1", | ||
"PPID": "1", | ||
"C": "0", | ||
"STIME": "12:00", | ||
"TTY": "?", | ||
"TIME": "00:00:01", | ||
"CMD": "/entrypoint", | ||
}, | ||
}, | ||
output: trim(` | ||
SERVICE UID PID PPID C STIME TTY TIME CMD | ||
simple root 1 1 0 12:00 ? 00:00:01 /entrypoint | ||
`), | ||
}, | ||
{ | ||
name: "noppid", | ||
titles: []string{"UID", "PID", "C", "STIME", "TTY", "TIME", "CMD"}, | ||
procs: [][]string{{"root", "1", "0", "12:00", "?", "00:00:02", "/entrypoint"}}, | ||
header: topHeader{ | ||
"SERVICE": 0, | ||
"UID": 1, | ||
"PID": 2, | ||
"C": 3, | ||
"STIME": 4, | ||
"TTY": 5, | ||
"TIME": 6, | ||
"CMD": 7, | ||
}, | ||
entries: []topEntries{ | ||
{ | ||
"SERVICE": "noppid", | ||
"UID": "root", | ||
"PID": "1", | ||
"C": "0", | ||
"STIME": "12:00", | ||
"TTY": "?", | ||
"TIME": "00:00:02", | ||
"CMD": "/entrypoint", | ||
}, | ||
}, | ||
output: trim(` | ||
SERVICE UID PID C STIME TTY TIME CMD | ||
noppid root 1 0 12:00 ? 00:00:02 /entrypoint | ||
`), | ||
}, | ||
{ | ||
name: "extra-hdr", | ||
titles: []string{"UID", "GID", "PID", "PPID", "C", "STIME", "TTY", "TIME", "CMD"}, | ||
procs: [][]string{{"root", "1", "1", "1", "0", "12:00", "?", "00:00:03", "/entrypoint"}}, | ||
header: topHeader{ | ||
"SERVICE": 0, | ||
"UID": 1, | ||
"GID": 2, | ||
"PID": 3, | ||
"PPID": 4, | ||
"C": 5, | ||
"STIME": 6, | ||
"TTY": 7, | ||
"TIME": 8, | ||
"CMD": 9, | ||
}, | ||
entries: []topEntries{ | ||
{ | ||
"SERVICE": "extra-hdr", | ||
"UID": "root", | ||
"GID": "1", | ||
"PID": "1", | ||
"PPID": "1", | ||
"C": "0", | ||
"STIME": "12:00", | ||
"TTY": "?", | ||
"TIME": "00:00:03", | ||
"CMD": "/entrypoint", | ||
}, | ||
}, | ||
output: trim(` | ||
SERVICE UID GID PID PPID C STIME TTY TIME CMD | ||
extra-hdr root 1 1 1 0 12:00 ? 00:00:03 /entrypoint | ||
`), | ||
}, | ||
{ | ||
name: "multiple", | ||
titles: []string{"UID", "PID", "PPID", "C", "STIME", "TTY", "TIME", "CMD"}, | ||
procs: [][]string{ | ||
{"root", "1", "1", "0", "12:00", "?", "00:00:04", "/entrypoint"}, | ||
{"root", "123", "1", "0", "12:00", "?", "00:00:42", "sleep infinity"}, | ||
}, | ||
header: topHeader{ | ||
"SERVICE": 0, | ||
"UID": 1, | ||
"PID": 2, | ||
"PPID": 3, | ||
"C": 4, | ||
"STIME": 5, | ||
"TTY": 6, | ||
"TIME": 7, | ||
"CMD": 8, | ||
}, | ||
entries: []topEntries{ | ||
{ | ||
"SERVICE": "multiple", | ||
"UID": "root", | ||
"PID": "1", | ||
"PPID": "1", | ||
"C": "0", | ||
"STIME": "12:00", | ||
"TTY": "?", | ||
"TIME": "00:00:04", | ||
"CMD": "/entrypoint", | ||
}, | ||
{ | ||
"SERVICE": "multiple", | ||
"UID": "root", | ||
"PID": "123", | ||
"PPID": "1", | ||
"C": "0", | ||
"STIME": "12:00", | ||
"TTY": "?", | ||
"TIME": "00:00:42", | ||
"CMD": "sleep infinity", | ||
}, | ||
}, | ||
output: trim(` | ||
SERVICE UID PID PPID C STIME TTY TIME CMD | ||
multiple root 1 1 0 12:00 ? 00:00:04 /entrypoint | ||
multiple root 123 1 0 12:00 ? 00:00:42 sleep infinity | ||
`), | ||
}, | ||
} | ||
|
||
// TestRunTopCore only tests the core functionality of runTop: formatting | ||
// and printing of the output of (api.Service).Top(). | ||
func TestRunTopCore(t *testing.T) { | ||
t.Parallel() | ||
|
||
all := []api.ContainerProcSummary{} | ||
|
||
for _, tc := range topTestCases { | ||
summary := api.ContainerProcSummary{ | ||
Name: tc.name, | ||
Titles: tc.titles, | ||
Processes: tc.procs, | ||
} | ||
all = append(all, summary) | ||
|
||
t.Run(tc.name, func(t *testing.T) { | ||
header, entries := collectTop([]api.ContainerProcSummary{summary}) | ||
assert.EqualValues(t, tc.header, header) | ||
assert.EqualValues(t, tc.entries, entries) | ||
|
||
var buf bytes.Buffer | ||
err := topPrint(&buf, header, entries) | ||
|
||
require.NoError(t, err) | ||
assert.Equal(t, tc.output, buf.String()) | ||
}) | ||
} | ||
|
||
t.Run("all", func(t *testing.T) { | ||
header, entries := collectTop(all) | ||
assert.EqualValues(t, topHeader{ | ||
"SERVICE": 0, | ||
"UID": 1, | ||
"PID": 2, | ||
"PPID": 3, | ||
"C": 4, | ||
"STIME": 5, | ||
"TTY": 6, | ||
"TIME": 7, | ||
"CMD": 8, | ||
"GID": 9, | ||
}, header) | ||
assert.EqualValues(t, []topEntries{ | ||
{ | ||
"SERVICE": "simple", | ||
"UID": "root", | ||
"PID": "1", | ||
"PPID": "1", | ||
"C": "0", | ||
"STIME": "12:00", | ||
"TTY": "?", | ||
"TIME": "00:00:01", | ||
"CMD": "/entrypoint", | ||
}, { | ||
"SERVICE": "noppid", | ||
"UID": "root", | ||
"PID": "1", | ||
"C": "0", | ||
"STIME": "12:00", | ||
"TTY": "?", | ||
"TIME": "00:00:02", | ||
"CMD": "/entrypoint", | ||
}, { | ||
"SERVICE": "extra-hdr", | ||
"UID": "root", | ||
"GID": "1", | ||
"PID": "1", | ||
"PPID": "1", | ||
"C": "0", | ||
"STIME": "12:00", | ||
"TTY": "?", | ||
"TIME": "00:00:03", | ||
"CMD": "/entrypoint", | ||
}, { | ||
"SERVICE": "multiple", | ||
"UID": "root", | ||
"PID": "1", | ||
"PPID": "1", | ||
"C": "0", | ||
"STIME": "12:00", | ||
"TTY": "?", | ||
"TIME": "00:00:04", | ||
"CMD": "/entrypoint", | ||
}, { | ||
"SERVICE": "multiple", | ||
"UID": "root", | ||
"PID": "123", | ||
"PPID": "1", | ||
"C": "0", | ||
"STIME": "12:00", | ||
"TTY": "?", | ||
"TIME": "00:00:42", | ||
"CMD": "sleep infinity", | ||
}, | ||
}, entries) | ||
|
||
var buf bytes.Buffer | ||
err := topPrint(&buf, header, entries) | ||
require.NoError(t, err) | ||
assert.Equal(t, trim(` | ||
SERVICE UID PID PPID C STIME TTY TIME CMD GID | ||
simple root 1 1 0 12:00 ? 00:00:01 /entrypoint - | ||
noppid root 1 - 0 12:00 ? 00:00:02 /entrypoint - | ||
extra-hdr root 1 1 0 12:00 ? 00:00:03 /entrypoint 1 | ||
multiple root 1 1 0 12:00 ? 00:00:04 /entrypoint - | ||
multiple root 123 1 0 12:00 ? 00:00:42 sleep infinity - | ||
`), buf.String()) | ||
|
||
}) | ||
} | ||
|
||
func trim(s string) string { | ||
var out bytes.Buffer | ||
for _, line := range strings.Split(strings.TrimSpace(s), "\n") { | ||
out.WriteString(strings.TrimSpace(line)) | ||
out.WriteRune('\n') | ||
} | ||
return out.String() | ||
} |