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