github.com/ruphin/docker@v1.10.1/pkg/jsonmessage/jsonmessage_test.go (about) 1 package jsonmessage 2 3 import ( 4 "bytes" 5 "fmt" 6 "strings" 7 "testing" 8 "time" 9 10 "github.com/docker/docker/pkg/jsonlog" 11 "github.com/docker/docker/pkg/term" 12 ) 13 14 func TestError(t *testing.T) { 15 je := JSONError{404, "Not found"} 16 if je.Error() != "Not found" { 17 t.Fatalf("Expected 'Not found' got '%s'", je.Error()) 18 } 19 } 20 21 func TestProgress(t *testing.T) { 22 jp := JSONProgress{} 23 if jp.String() != "" { 24 t.Fatalf("Expected empty string, got '%s'", jp.String()) 25 } 26 27 expected := " 1 B" 28 jp2 := JSONProgress{Current: 1} 29 if jp2.String() != expected { 30 t.Fatalf("Expected %q, got %q", expected, jp2.String()) 31 } 32 33 expectedStart := "[==========> ] 20 B/100 B" 34 jp3 := JSONProgress{Current: 20, Total: 100, Start: time.Now().Unix()} 35 // Just look at the start of the string 36 // (the remaining time is really hard to test -_-) 37 if jp3.String()[:len(expectedStart)] != expectedStart { 38 t.Fatalf("Expected to start with %q, got %q", expectedStart, jp3.String()) 39 } 40 41 expected = "[=========================> ] 50 B/100 B" 42 jp4 := JSONProgress{Current: 50, Total: 100} 43 if jp4.String() != expected { 44 t.Fatalf("Expected %q, got %q", expected, jp4.String()) 45 } 46 47 // this number can't be negative gh#7136 48 expected = "[==================================================>] 50 B" 49 jp5 := JSONProgress{Current: 50, Total: 40} 50 if jp5.String() != expected { 51 t.Fatalf("Expected %q, got %q", expected, jp5.String()) 52 } 53 } 54 55 func TestJSONMessageDisplay(t *testing.T) { 56 now := time.Now() 57 messages := map[JSONMessage][]string{ 58 // Empty 59 JSONMessage{}: {"\n", "\n"}, 60 // Status 61 JSONMessage{ 62 Status: "status", 63 }: { 64 "status\n", 65 "status\n", 66 }, 67 // General 68 JSONMessage{ 69 Time: now.Unix(), 70 ID: "ID", 71 From: "From", 72 Status: "status", 73 }: { 74 fmt.Sprintf("%v ID: (from From) status\n", time.Unix(now.Unix(), 0).Format(jsonlog.RFC3339NanoFixed)), 75 fmt.Sprintf("%v ID: (from From) status\n", time.Unix(now.Unix(), 0).Format(jsonlog.RFC3339NanoFixed)), 76 }, 77 // General, with nano precision time 78 JSONMessage{ 79 TimeNano: now.UnixNano(), 80 ID: "ID", 81 From: "From", 82 Status: "status", 83 }: { 84 fmt.Sprintf("%v ID: (from From) status\n", time.Unix(0, now.UnixNano()).Format(jsonlog.RFC3339NanoFixed)), 85 fmt.Sprintf("%v ID: (from From) status\n", time.Unix(0, now.UnixNano()).Format(jsonlog.RFC3339NanoFixed)), 86 }, 87 // General, with both times Nano is preferred 88 JSONMessage{ 89 Time: now.Unix(), 90 TimeNano: now.UnixNano(), 91 ID: "ID", 92 From: "From", 93 Status: "status", 94 }: { 95 fmt.Sprintf("%v ID: (from From) status\n", time.Unix(0, now.UnixNano()).Format(jsonlog.RFC3339NanoFixed)), 96 fmt.Sprintf("%v ID: (from From) status\n", time.Unix(0, now.UnixNano()).Format(jsonlog.RFC3339NanoFixed)), 97 }, 98 // Stream over status 99 JSONMessage{ 100 Status: "status", 101 Stream: "stream", 102 }: { 103 "stream", 104 "stream", 105 }, 106 // With progress message 107 JSONMessage{ 108 Status: "status", 109 ProgressMessage: "progressMessage", 110 }: { 111 "status progressMessage", 112 "status progressMessage", 113 }, 114 // With progress, stream empty 115 JSONMessage{ 116 Status: "status", 117 Stream: "", 118 Progress: &JSONProgress{Current: 1}, 119 }: { 120 "", 121 fmt.Sprintf("%c[2K\rstatus 1 B\r", 27), 122 }, 123 } 124 125 // The tests :) 126 for jsonMessage, expectedMessages := range messages { 127 // Without terminal 128 data := bytes.NewBuffer([]byte{}) 129 if err := jsonMessage.Display(data, false); err != nil { 130 t.Fatal(err) 131 } 132 if data.String() != expectedMessages[0] { 133 t.Fatalf("Expected [%v], got [%v]", expectedMessages[0], data.String()) 134 } 135 // With terminal 136 data = bytes.NewBuffer([]byte{}) 137 if err := jsonMessage.Display(data, true); err != nil { 138 t.Fatal(err) 139 } 140 if data.String() != expectedMessages[1] { 141 t.Fatalf("Expected [%v], got [%v]", expectedMessages[1], data.String()) 142 } 143 } 144 } 145 146 // Test JSONMessage with an Error. It will return an error with the text as error, not the meaning of the HTTP code. 147 func TestJSONMessageDisplayWithJSONError(t *testing.T) { 148 data := bytes.NewBuffer([]byte{}) 149 jsonMessage := JSONMessage{Error: &JSONError{404, "Can't find it"}} 150 151 err := jsonMessage.Display(data, true) 152 if err == nil || err.Error() != "Can't find it" { 153 t.Fatalf("Expected a JSONError 404, got [%v]", err) 154 } 155 156 jsonMessage = JSONMessage{Error: &JSONError{401, "Anything"}} 157 err = jsonMessage.Display(data, true) 158 if err == nil || err.Error() != "Authentication is required." { 159 t.Fatalf("Expected an error [Authentication is required.], got [%v]", err) 160 } 161 } 162 163 func TestDisplayJSONMessagesStreamInvalidJSON(t *testing.T) { 164 var ( 165 inFd uintptr 166 ) 167 data := bytes.NewBuffer([]byte{}) 168 reader := strings.NewReader("This is not a 'valid' JSON []") 169 inFd, _ = term.GetFdInfo(reader) 170 171 if err := DisplayJSONMessagesStream(reader, data, inFd, false, nil); err == nil && err.Error()[:17] != "invalid character" { 172 t.Fatalf("Should have thrown an error (invalid character in ..), got [%v]", err) 173 } 174 } 175 176 func TestDisplayJSONMessagesStream(t *testing.T) { 177 var ( 178 inFd uintptr 179 ) 180 181 messages := map[string][]string{ 182 // empty string 183 "": { 184 "", 185 ""}, 186 // Without progress & ID 187 "{ \"status\": \"status\" }": { 188 "status\n", 189 "status\n", 190 }, 191 // Without progress, with ID 192 "{ \"id\": \"ID\",\"status\": \"status\" }": { 193 "ID: status\n", 194 fmt.Sprintf("ID: status\n%c[%dB", 27, 0), 195 }, 196 // With progress 197 "{ \"id\": \"ID\", \"status\": \"status\", \"progress\": \"ProgressMessage\" }": { 198 "ID: status ProgressMessage", 199 fmt.Sprintf("\n%c[%dAID: status ProgressMessage%c[%dB", 27, 0, 27, 0), 200 }, 201 // With progressDetail 202 "{ \"id\": \"ID\", \"status\": \"status\", \"progressDetail\": { \"Current\": 1} }": { 203 "", // progressbar is disabled in non-terminal 204 fmt.Sprintf("\n%c[%dA%c[2K\rID: status 1 B\r%c[%dB", 27, 0, 27, 27, 0), 205 }, 206 } 207 for jsonMessage, expectedMessages := range messages { 208 data := bytes.NewBuffer([]byte{}) 209 reader := strings.NewReader(jsonMessage) 210 inFd, _ = term.GetFdInfo(reader) 211 212 // Without terminal 213 if err := DisplayJSONMessagesStream(reader, data, inFd, false, nil); err != nil { 214 t.Fatal(err) 215 } 216 if data.String() != expectedMessages[0] { 217 t.Fatalf("Expected an [%v], got [%v]", expectedMessages[0], data.String()) 218 } 219 220 // With terminal 221 data = bytes.NewBuffer([]byte{}) 222 reader = strings.NewReader(jsonMessage) 223 if err := DisplayJSONMessagesStream(reader, data, inFd, true, nil); err != nil { 224 t.Fatal(err) 225 } 226 if data.String() != expectedMessages[1] { 227 t.Fatalf("Expected an [%v], got [%v]", expectedMessages[1], data.String()) 228 } 229 } 230 231 }