Cleanup pkg/jsonmessage progress tests
Signed-off-by: Daniel Nephin <dnephin@docker.com>
This commit is contained in:
parent
c9e52bd0da
commit
7d8815ea70
3 changed files with 132 additions and 93 deletions
|
@ -40,21 +40,17 @@ type JSONProgress struct {
|
|||
// If true, don't show xB/yB
|
||||
HideCounts bool `json:"hidecounts,omitempty"`
|
||||
Units string `json:"units,omitempty"`
|
||||
nowFunc func() time.Time
|
||||
winSize int
|
||||
}
|
||||
|
||||
func (p *JSONProgress) String() string {
|
||||
var (
|
||||
width = 200
|
||||
width = p.width()
|
||||
pbBox string
|
||||
numbersBox string
|
||||
timeLeftBox string
|
||||
)
|
||||
|
||||
ws, err := term.GetWinsize(p.terminalFd)
|
||||
if err == nil {
|
||||
width = int(ws.Width)
|
||||
}
|
||||
|
||||
if p.Current <= 0 && p.Total <= 0 {
|
||||
return ""
|
||||
}
|
||||
|
@ -103,7 +99,7 @@ func (p *JSONProgress) String() string {
|
|||
}
|
||||
|
||||
if p.Current > 0 && p.Start > 0 && percentage < 50 {
|
||||
fromStart := time.Now().UTC().Sub(time.Unix(p.Start, 0))
|
||||
fromStart := p.now().Sub(time.Unix(p.Start, 0))
|
||||
perEntry := fromStart / time.Duration(p.Current)
|
||||
left := time.Duration(p.Total-p.Current) * perEntry
|
||||
left = (left / time.Second) * time.Second
|
||||
|
@ -115,6 +111,28 @@ func (p *JSONProgress) String() string {
|
|||
return pbBox + numbersBox + timeLeftBox
|
||||
}
|
||||
|
||||
// shim for testing
|
||||
func (p *JSONProgress) now() time.Time {
|
||||
if p.nowFunc == nil {
|
||||
p.nowFunc = func() time.Time {
|
||||
return time.Now().UTC()
|
||||
}
|
||||
}
|
||||
return p.nowFunc()
|
||||
}
|
||||
|
||||
// shim for testing
|
||||
func (p *JSONProgress) width() int {
|
||||
if p.winSize != 0 {
|
||||
return p.winSize
|
||||
}
|
||||
ws, err := term.GetWinsize(p.terminalFd)
|
||||
if err == nil {
|
||||
return int(ws.Width)
|
||||
}
|
||||
return 200
|
||||
}
|
||||
|
||||
// JSONMessage defines a message struct. It describes
|
||||
// the created time, where it from, status, ID of the
|
||||
// message. It's used for docker events.
|
||||
|
|
|
@ -15,84 +15,102 @@ import (
|
|||
|
||||
func TestError(t *testing.T) {
|
||||
je := JSONError{404, "Not found"}
|
||||
if je.Error() != "Not found" {
|
||||
t.Fatalf("Expected 'Not found' got '%s'", je.Error())
|
||||
}
|
||||
assert.Assert(t, is.Error(&je, "Not found"))
|
||||
}
|
||||
|
||||
func TestProgress(t *testing.T) {
|
||||
termsz, err := term.GetWinsize(0)
|
||||
if err != nil {
|
||||
// we can safely ignore the err here
|
||||
termsz = nil
|
||||
}
|
||||
jp := JSONProgress{}
|
||||
if jp.String() != "" {
|
||||
t.Fatalf("Expected empty string, got '%s'", jp.String())
|
||||
func TestProgressString(t *testing.T) {
|
||||
type expected struct {
|
||||
short string
|
||||
long string
|
||||
}
|
||||
|
||||
expected := " 1B"
|
||||
jp2 := JSONProgress{Current: 1}
|
||||
if jp2.String() != expected {
|
||||
t.Fatalf("Expected %q, got %q", expected, jp2.String())
|
||||
shortAndLong := func(short, long string) expected {
|
||||
return expected{short: short, long: long}
|
||||
}
|
||||
|
||||
expectedStart := "[==========> ] 20B/100B"
|
||||
if termsz != nil && termsz.Width <= 110 {
|
||||
expectedStart = " 20B/100B"
|
||||
}
|
||||
jp3 := JSONProgress{Current: 20, Total: 100, Start: time.Now().Unix()}
|
||||
// Just look at the start of the string
|
||||
// (the remaining time is really hard to test -_-)
|
||||
if jp3.String()[:len(expectedStart)] != expectedStart {
|
||||
t.Fatalf("Expected to start with %q, got %q", expectedStart, jp3.String())
|
||||
start := time.Date(2017, 12, 3, 15, 10, 1, 0, time.UTC)
|
||||
timeAfter := func(delta time.Duration) func() time.Time {
|
||||
return func() time.Time {
|
||||
return start.Add(delta)
|
||||
}
|
||||
}
|
||||
|
||||
expected = "[=========================> ] 50B/100B"
|
||||
if termsz != nil && termsz.Width <= 110 {
|
||||
expected = " 50B/100B"
|
||||
}
|
||||
jp4 := JSONProgress{Current: 50, Total: 100}
|
||||
if jp4.String() != expected {
|
||||
t.Fatalf("Expected %q, got %q", expected, jp4.String())
|
||||
var testcases = []struct {
|
||||
name string
|
||||
progress JSONProgress
|
||||
expected expected
|
||||
}{
|
||||
{
|
||||
name: "no progress",
|
||||
},
|
||||
{
|
||||
name: "progress 1",
|
||||
progress: JSONProgress{Current: 1},
|
||||
expected: shortAndLong(" 1B", " 1B"),
|
||||
},
|
||||
{
|
||||
name: "some progress with a start time",
|
||||
progress: JSONProgress{
|
||||
Current: 20,
|
||||
Total: 100,
|
||||
Start: start.Unix(),
|
||||
nowFunc: timeAfter(time.Second),
|
||||
},
|
||||
expected: shortAndLong(
|
||||
" 20B/100B 4s",
|
||||
"[==========> ] 20B/100B 4s",
|
||||
),
|
||||
},
|
||||
{
|
||||
name: "some progress without a start time",
|
||||
progress: JSONProgress{Current: 50, Total: 100},
|
||||
expected: shortAndLong(
|
||||
" 50B/100B",
|
||||
"[=========================> ] 50B/100B",
|
||||
),
|
||||
},
|
||||
{
|
||||
name: "current more than total is not negative gh#7136",
|
||||
progress: JSONProgress{Current: 50, Total: 40},
|
||||
expected: shortAndLong(
|
||||
" 50B",
|
||||
"[==================================================>] 50B",
|
||||
),
|
||||
},
|
||||
{
|
||||
name: "with units",
|
||||
progress: JSONProgress{Current: 50, Total: 100, Units: "units"},
|
||||
expected: shortAndLong(
|
||||
"50/100 units",
|
||||
"[=========================> ] 50/100 units",
|
||||
),
|
||||
},
|
||||
{
|
||||
name: "current more than total with units is not negative ",
|
||||
progress: JSONProgress{Current: 50, Total: 40, Units: "units"},
|
||||
expected: shortAndLong(
|
||||
"50 units",
|
||||
"[==================================================>] 50 units",
|
||||
),
|
||||
},
|
||||
{
|
||||
name: "hide counts",
|
||||
progress: JSONProgress{Current: 50, Total: 100, HideCounts: true},
|
||||
expected: shortAndLong(
|
||||
"",
|
||||
"[=========================> ] ",
|
||||
),
|
||||
},
|
||||
}
|
||||
|
||||
// this number can't be negative gh#7136
|
||||
expected = "[==================================================>] 50B"
|
||||
if termsz != nil && termsz.Width <= 110 {
|
||||
expected = " 50B"
|
||||
}
|
||||
jp5 := JSONProgress{Current: 50, Total: 40}
|
||||
if jp5.String() != expected {
|
||||
t.Fatalf("Expected %q, got %q", expected, jp5.String())
|
||||
}
|
||||
for _, testcase := range testcases {
|
||||
t.Run(testcase.name, func(t *testing.T) {
|
||||
testcase.progress.winSize = 100
|
||||
assert.Equal(t, testcase.progress.String(), testcase.expected.short)
|
||||
|
||||
expected = "[=========================> ] 50/100 units"
|
||||
if termsz != nil && termsz.Width <= 110 {
|
||||
expected = " 50/100 units"
|
||||
}
|
||||
jp6 := JSONProgress{Current: 50, Total: 100, Units: "units"}
|
||||
if jp6.String() != expected {
|
||||
t.Fatalf("Expected %q, got %q", expected, jp6.String())
|
||||
}
|
||||
|
||||
// this number can't be negative
|
||||
expected = "[==================================================>] 50 units"
|
||||
if termsz != nil && termsz.Width <= 110 {
|
||||
expected = " 50 units"
|
||||
}
|
||||
jp7 := JSONProgress{Current: 50, Total: 40, Units: "units"}
|
||||
if jp7.String() != expected {
|
||||
t.Fatalf("Expected %q, got %q", expected, jp7.String())
|
||||
}
|
||||
|
||||
expected = "[=========================> ] "
|
||||
if termsz != nil && termsz.Width <= 110 {
|
||||
expected = ""
|
||||
}
|
||||
jp8 := JSONProgress{Current: 50, Total: 100, HideCounts: true}
|
||||
if jp8.String() != expected {
|
||||
t.Fatalf("Expected %q, got %q", expected, jp8.String())
|
||||
testcase.progress.winSize = 200
|
||||
assert.Equal(t, testcase.progress.String(), testcase.expected.long)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -8,6 +8,8 @@ import (
|
|||
"testing"
|
||||
|
||||
"github.com/docker/docker/pkg/jsonmessage"
|
||||
"github.com/google/go-cmp/cmp"
|
||||
"github.com/google/go-cmp/cmp/cmpopts"
|
||||
"github.com/gotestyourself/gotestyourself/assert"
|
||||
is "github.com/gotestyourself/gotestyourself/assert/cmp"
|
||||
)
|
||||
|
@ -58,30 +60,31 @@ func TestJsonProgressFormatterFormatProgress(t *testing.T) {
|
|||
Total: 30,
|
||||
Start: 1,
|
||||
}
|
||||
res := sf.formatProgress("id", "action", jsonProgress, &AuxFormatter{Writer: &bytes.Buffer{}})
|
||||
aux := "aux message"
|
||||
res := sf.formatProgress("id", "action", jsonProgress, aux)
|
||||
msg := &jsonmessage.JSONMessage{}
|
||||
|
||||
assert.NilError(t, json.Unmarshal(res, msg))
|
||||
assert.Check(t, is.Equal("id", msg.ID))
|
||||
assert.Check(t, is.Equal("action", msg.Status))
|
||||
|
||||
// jsonProgress will always be in the format of:
|
||||
// [=========================> ] 15B/30B 412910h51m30s
|
||||
// The last entry '404933h7m11s' is the timeLeftBox.
|
||||
// However, the timeLeftBox field may change as jsonProgress.String() depends on time.Now().
|
||||
// Therefore, we have to strip the timeLeftBox from the strings to do the comparison.
|
||||
|
||||
// Compare the jsonProgress strings before the timeLeftBox
|
||||
expectedProgress := "[=========================> ] 15B/30B"
|
||||
// if terminal column is <= 110, expectedProgressShort is expected.
|
||||
expectedProgressShort := " 15B/30B"
|
||||
if !(strings.HasPrefix(msg.ProgressMessage, expectedProgress) ||
|
||||
strings.HasPrefix(msg.ProgressMessage, expectedProgressShort)) {
|
||||
t.Fatalf("ProgressMessage without the timeLeftBox must be %s or %s, got: %s",
|
||||
expectedProgress, expectedProgressShort, msg.ProgressMessage)
|
||||
rawAux := json.RawMessage(`"` + aux + `"`)
|
||||
expected := &jsonmessage.JSONMessage{
|
||||
ID: "id",
|
||||
Status: "action",
|
||||
Aux: &rawAux,
|
||||
Progress: jsonProgress,
|
||||
}
|
||||
assert.DeepEqual(t, msg, expected, cmpJSONMessageOpt())
|
||||
}
|
||||
|
||||
assert.Check(t, is.DeepEqual(jsonProgress, msg.Progress))
|
||||
func cmpJSONMessageOpt() cmp.Option {
|
||||
progressMessagePath := func(path cmp.Path) bool {
|
||||
return path.String() == "ProgressMessage"
|
||||
}
|
||||
return cmp.Options{
|
||||
cmpopts.IgnoreUnexported(jsonmessage.JSONProgress{}),
|
||||
// Ignore deprecated property that is a derivative of Progress
|
||||
cmp.FilterPath(progressMessagePath, cmp.Ignore()),
|
||||
}
|
||||
}
|
||||
|
||||
func TestJsonProgressFormatterFormatStatus(t *testing.T) {
|
||||
|
|
Loading…
Reference in a new issue