123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280 |
- package jsonmessage
- import (
- "bytes"
- "fmt"
- "os"
- "strings"
- "testing"
- "time"
- "github.com/docker/docker/pkg/jsonlog"
- "github.com/docker/docker/pkg/term"
- "github.com/stretchr/testify/assert"
- )
- func TestError(t *testing.T) {
- je := JSONError{404, "Not found"}
- if je.Error() != "Not found" {
- t.Fatalf("Expected 'Not found' got '%s'", je.Error())
- }
- }
- 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())
- }
- expected := " 1B"
- jp2 := JSONProgress{Current: 1}
- if jp2.String() != expected {
- t.Fatalf("Expected %q, got %q", expected, jp2.String())
- }
- 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())
- }
- 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())
- }
- // 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())
- }
- 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())
- }
- }
- func TestJSONMessageDisplay(t *testing.T) {
- now := time.Now()
- messages := map[JSONMessage][]string{
- // Empty
- {}: {"\n", "\n"},
- // Status
- {
- Status: "status",
- }: {
- "status\n",
- "status\n",
- },
- // General
- {
- Time: now.Unix(),
- ID: "ID",
- From: "From",
- Status: "status",
- }: {
- fmt.Sprintf("%v ID: (from From) status\n", time.Unix(now.Unix(), 0).Format(jsonlog.RFC3339NanoFixed)),
- fmt.Sprintf("%v ID: (from From) status\n", time.Unix(now.Unix(), 0).Format(jsonlog.RFC3339NanoFixed)),
- },
- // General, with nano precision time
- {
- TimeNano: now.UnixNano(),
- ID: "ID",
- From: "From",
- Status: "status",
- }: {
- fmt.Sprintf("%v ID: (from From) status\n", time.Unix(0, now.UnixNano()).Format(jsonlog.RFC3339NanoFixed)),
- fmt.Sprintf("%v ID: (from From) status\n", time.Unix(0, now.UnixNano()).Format(jsonlog.RFC3339NanoFixed)),
- },
- // General, with both times Nano is preferred
- {
- Time: now.Unix(),
- TimeNano: now.UnixNano(),
- ID: "ID",
- From: "From",
- Status: "status",
- }: {
- fmt.Sprintf("%v ID: (from From) status\n", time.Unix(0, now.UnixNano()).Format(jsonlog.RFC3339NanoFixed)),
- fmt.Sprintf("%v ID: (from From) status\n", time.Unix(0, now.UnixNano()).Format(jsonlog.RFC3339NanoFixed)),
- },
- // Stream over status
- {
- Status: "status",
- Stream: "stream",
- }: {
- "stream",
- "stream",
- },
- // With progress message
- {
- Status: "status",
- ProgressMessage: "progressMessage",
- }: {
- "status progressMessage",
- "status progressMessage",
- },
- // With progress, stream empty
- {
- Status: "status",
- Stream: "",
- Progress: &JSONProgress{Current: 1},
- }: {
- "",
- fmt.Sprintf("%c[1K%c[K\rstatus 1B\r", 27, 27),
- },
- }
- // The tests :)
- for jsonMessage, expectedMessages := range messages {
- // Without terminal
- data := bytes.NewBuffer([]byte{})
- if err := jsonMessage.Display(data, nil); err != nil {
- t.Fatal(err)
- }
- if data.String() != expectedMessages[0] {
- t.Fatalf("Expected %q,got %q", expectedMessages[0], data.String())
- }
- // With terminal
- data = bytes.NewBuffer([]byte{})
- if err := jsonMessage.Display(data, &noTermInfo{}); err != nil {
- t.Fatal(err)
- }
- if data.String() != expectedMessages[1] {
- t.Fatalf("\nExpected %q\n got %q", expectedMessages[1], data.String())
- }
- }
- }
- // Test JSONMessage with an Error. It will return an error with the text as error, not the meaning of the HTTP code.
- func TestJSONMessageDisplayWithJSONError(t *testing.T) {
- data := bytes.NewBuffer([]byte{})
- jsonMessage := JSONMessage{Error: &JSONError{404, "Can't find it"}}
- err := jsonMessage.Display(data, &noTermInfo{})
- if err == nil || err.Error() != "Can't find it" {
- t.Fatalf("Expected a JSONError 404, got %q", err)
- }
- jsonMessage = JSONMessage{Error: &JSONError{401, "Anything"}}
- err = jsonMessage.Display(data, &noTermInfo{})
- assert.EqualError(t, err, "authentication is required")
- }
- func TestDisplayJSONMessagesStreamInvalidJSON(t *testing.T) {
- var (
- inFd uintptr
- )
- data := bytes.NewBuffer([]byte{})
- reader := strings.NewReader("This is not a 'valid' JSON []")
- inFd, _ = term.GetFdInfo(reader)
- if err := DisplayJSONMessagesStream(reader, data, inFd, false, nil); err == nil && err.Error()[:17] != "invalid character" {
- t.Fatalf("Should have thrown an error (invalid character in ..), got %q", err)
- }
- }
- func TestDisplayJSONMessagesStream(t *testing.T) {
- var (
- inFd uintptr
- )
- messages := map[string][]string{
- // empty string
- "": {
- "",
- ""},
- // Without progress & ID
- "{ \"status\": \"status\" }": {
- "status\n",
- "status\n",
- },
- // Without progress, with ID
- "{ \"id\": \"ID\",\"status\": \"status\" }": {
- "ID: status\n",
- fmt.Sprintf("ID: status\n"),
- },
- // With progress
- "{ \"id\": \"ID\", \"status\": \"status\", \"progress\": \"ProgressMessage\" }": {
- "ID: status ProgressMessage",
- fmt.Sprintf("\n%c[%dAID: status ProgressMessage%c[%dB", 27, 1, 27, 1),
- },
- // With progressDetail
- "{ \"id\": \"ID\", \"status\": \"status\", \"progressDetail\": { \"Current\": 1} }": {
- "", // progressbar is disabled in non-terminal
- fmt.Sprintf("\n%c[%dA%c[1K%c[K\rID: status 1B\r%c[%dB", 27, 1, 27, 27, 27, 1),
- },
- }
- // Use $TERM which is unlikely to exist, forcing DisplayJSONMessageStream to
- // (hopefully) use &noTermInfo.
- origTerm := os.Getenv("TERM")
- os.Setenv("TERM", "xyzzy-non-existent-terminfo")
- for jsonMessage, expectedMessages := range messages {
- data := bytes.NewBuffer([]byte{})
- reader := strings.NewReader(jsonMessage)
- inFd, _ = term.GetFdInfo(reader)
- // Without terminal
- if err := DisplayJSONMessagesStream(reader, data, inFd, false, nil); err != nil {
- t.Fatal(err)
- }
- if data.String() != expectedMessages[0] {
- t.Fatalf("Expected an %q, got %q", expectedMessages[0], data.String())
- }
- // With terminal
- data = bytes.NewBuffer([]byte{})
- reader = strings.NewReader(jsonMessage)
- if err := DisplayJSONMessagesStream(reader, data, inFd, true, nil); err != nil {
- t.Fatal(err)
- }
- if data.String() != expectedMessages[1] {
- t.Fatalf("\nExpected %q\n got %q", expectedMessages[1], data.String())
- }
- }
- os.Setenv("TERM", origTerm)
- }
|