github.com/cloudfoundry/cli@v7.1.0+incompatible/util/ui/request_logger_terminal_display_test.go (about) 1 package ui_test 2 3 import ( 4 "errors" 5 "regexp" 6 "time" 7 8 . "code.cloudfoundry.org/cli/util/ui" 9 10 . "github.com/onsi/ginkgo" 11 . "github.com/onsi/gomega" 12 . "github.com/onsi/gomega/gbytes" 13 ) 14 15 var _ = Describe("Request Logger Terminal Display", func() { 16 var ( 17 out *Buffer 18 testUI *UI 19 display *RequestLoggerTerminalDisplay 20 ) 21 22 BeforeEach(func() { 23 out = NewBuffer() 24 testUI = NewTestUI(nil, out, NewBuffer()) 25 display = testUI.RequestLoggerTerminalDisplay() 26 Expect(display.Start()).ToNot(HaveOccurred()) 27 }) 28 29 Describe("DisplayBody", func() { 30 It("displays the redacted value", func() { 31 err := display.DisplayBody([]byte("some-string body")) 32 Expect(err).ToNot(HaveOccurred()) 33 34 err = display.Stop() 35 Expect(err).ToNot(HaveOccurred()) 36 37 Expect(testUI.Out).To(Say(`\[PRIVATE DATA HIDDEN\]`)) 38 }) 39 }) 40 41 Describe("DisplayDump", func() { 42 It("displays the passed in string", func() { 43 err := display.DisplayDump("some-dump-of-string") 44 Expect(err).ToNot(HaveOccurred()) 45 46 err = display.Stop() 47 Expect(err).ToNot(HaveOccurred()) 48 49 Expect(testUI.Out).To(Say("some-dump-of-string")) 50 }) 51 52 It("redacts auth tokens and cookies", func() { 53 dump := `GET /apps/ce03a2e2-95c0-4f3b-abb9-32718d408c8b/stream HTTP/1.1 54 Host: wss://doppler.bosh-lite.com:443 55 Upgrade: websocket 56 Connection: Upgrade 57 Sec-WebSocket-Version: 13 58 Sec-WebSocket-Key: [HIDDEN] 59 Set-Cookie: please-redact-this 60 Authorization: bearer eyJhbGciOiJSUzI1NiIsImtpZCI6ImtleS0xIiwidHlwIjoiSldUIn0.eyJqdGkiOiI3YzRmYWEyZjI5MmQ0MTQ5ODM5NGE3OTU0Y2E3ZWNlMCIsInN1YiI6IjIyMjNiM2IzLTE3ZTktNDJkNi1iNzQzLThjZjcyZWIwOWRlNSIsInNjb3BlIjpbInJvdXRpbmcucm91dGVyX2dyb3Vwcy5yZWFkIiwiY2xvdWRfY29udHJvbGxlci5yZWFkIiwicGFzc3dvcmQud3JpdGUiLCJjbG91ZF9jb250cm9sbGVyLndyaXRlIiwib3BlbmlkIiwicm91dGluZy5yb3V0ZXJfZ3JvdXBzLndyaXRlIiwiZG9wcGxlci5maXJlaG9zZSIsInNjaW0ud3JpdGUiLCJzY2ltLnJlYWQiLCJjbG91ZF9jb250cm9sbGVyLmFkbWluIiwidWFhLnVzZXIiXSwiY2xpZW50X2lkIjoiY2YiLCJjaWQiOiJjZiIsImF6cCI6ImNmIiwiZ3JhbnRfdHlwZSI6InBhc3N3b3JkIiwidXNlcl9pZCI6IjIyMjNiM2IzLTE3ZTktNDJkNi1iNzQzLThjZjcyZWIwOWRlNSIsIm9yaWdpbiI6InVhYSIsInVzZXJfbmFtZSI6ImFkbWluIiwiZW1haWwiOiJhZG1pbiIsInJldl9zaWciOiI4NDBiMDBhMyIsImlhdCI6MTQ5NjQyNTU5NiwiZXhwIjoxNDk2NDI2MTk2LCJpc3MiOiJodHRwczovL3VhYS5ib3NoLWxpdGUuY29tL29hdXRoL3Rva2VuIiwiemlkIjoidWFhIiwiYXVkIjpbInNjaW0iLCJjbG91ZF9jb250cm9sbGVyIiwicGFzc3dvcmQiLCJjZiIsInVhYSIsIm9wZW5pZCIsImRvcHBsZXIiLCJyb3V0aW5nLnJvdXRlcl9ncm91cHMiXX0.TFDmHviKcs-eeNoz79dVwOl-k_dHTdqHkyztont2qnBDchNSpWvR5Yba54MMG8uTUHM72YbCopxdyaLY-g8s5wJFGLaBocrDgqswUh3mQRvynQG6_zne1h_0oHXnm0U-ZPnTyV8qjtHUoLvks4GOuktXc6ZE3NriWODpKIU5WdMgEbvyhuTnUEn88rQnmGJbKvHOIilulb6avSkZfTEq1o8w4VLCeRDlVLNh5JzCUtGzLfImNb31ks_Wv6HuI8kFjQZ5PQiTYjlhkuDQOcNSaAyWxQ_7425hiA7x8omBgEr-uST7GsxLvgoHqQaDH0JSTgMmO_GaN_QD52JVuru9og 61 Origin: wss://doppler.bosh-lite.com:443` 62 err := display.DisplayDump(dump) 63 Expect(err).ToNot(HaveOccurred()) 64 65 err = display.Stop() 66 Expect(err).ToNot(HaveOccurred()) 67 68 Expect(testUI.Out).To(Say("Connection: Upgrade")) 69 Expect(testUI.Out).To(Say(`Set-Cookie: \[PRIVATE DATA HIDDEN\]`)) 70 Expect(testUI.Out).To(Say(`Authorization: \[PRIVATE DATA HIDDEN\]`)) 71 Expect(testUI.Out).To(Say("Origin: wss://doppler.bosh-lite.com:443")) 72 }) 73 }) 74 75 Describe("DisplayHeader", func() { 76 It("displays the header key and value", func() { 77 err := display.DisplayHeader("Header", "Value") 78 Expect(err).ToNot(HaveOccurred()) 79 80 err = display.Stop() 81 Expect(err).ToNot(HaveOccurred()) 82 83 Expect(testUI.Out).To(Say("Header: Value")) 84 }) 85 }) 86 87 Describe("DisplayHost", func() { 88 It("displays the host", func() { 89 err := display.DisplayHost("banana") 90 Expect(err).ToNot(HaveOccurred()) 91 92 err = display.Stop() 93 Expect(err).ToNot(HaveOccurred()) 94 95 Expect(testUI.Out).To(Say("Host: banana")) 96 }) 97 }) 98 99 Describe("DisplayJSONBody", func() { 100 When("provided well formed JSON", func() { 101 It("displayed a formated output", func() { 102 raw := `{"a":"b", "c":"d", "don't html escape":"<&>"}` 103 formatted := `{ 104 "a": "b", 105 "c": "d", 106 "don't html escape": "<&>" 107 }` 108 err := display.DisplayJSONBody([]byte(raw)) 109 Expect(err).ToNot(HaveOccurred()) 110 111 err = display.Stop() 112 Expect(err).ToNot(HaveOccurred()) 113 114 Expect(testUI.Out).To(Say(formatted)) 115 }) 116 }) 117 118 When("the body is empty", func() { 119 It("does not display the body", func() { 120 err := display.DisplayJSONBody(nil) 121 Expect(err).ToNot(HaveOccurred()) 122 123 err = display.Stop() 124 Expect(err).ToNot(HaveOccurred()) 125 126 Expect(string(out.Contents())).To(Equal("\n")) 127 }) 128 }) 129 130 When("provided malformed JSON", func() { 131 It("displays the raw body", func() { 132 raw := `[{"data":1, "banana": 2}` 133 err := display.DisplayJSONBody([]byte(raw)) 134 Expect(err).ToNot(HaveOccurred()) 135 136 err = display.Stop() 137 Expect(err).ToNot(HaveOccurred()) 138 139 buff, ok := testUI.Out.(*Buffer) 140 Expect(ok).To(BeTrue()) 141 Expect(string(buff.Contents())).To(Equal(raw + "\n\n")) 142 }) 143 }) 144 }) 145 146 Describe("DisplayMessage", func() { 147 It("writes the message", func() { 148 msg := "i am a message!!!!" 149 err := display.DisplayMessage(msg) 150 Expect(err).ToNot(HaveOccurred()) 151 152 err = display.Stop() 153 Expect(err).ToNot(HaveOccurred()) 154 155 Expect(testUI.Out).To(Say(msg)) 156 }) 157 }) 158 159 Describe("DisplayRequestHeader", func() { 160 It("displays the method, uri and http protocol", func() { 161 err := display.DisplayRequestHeader("GET", "/v2/spaces/guid/summary", "HTTP/1.1") 162 Expect(err).ToNot(HaveOccurred()) 163 164 err = display.Stop() 165 Expect(err).ToNot(HaveOccurred()) 166 167 Expect(testUI.Out).To(Say("GET /v2/spaces/guid/summary HTTP/1.1")) 168 }) 169 }) 170 171 Describe("DisplayResponseHeader", func() { 172 It("displays the method, uri and http protocol", func() { 173 err := display.DisplayResponseHeader("HTTP/1.1", "200 OK") 174 Expect(err).ToNot(HaveOccurred()) 175 176 err = display.Stop() 177 Expect(err).ToNot(HaveOccurred()) 178 179 Expect(testUI.Out).To(Say("HTTP/1.1 200 OK")) 180 }) 181 }) 182 183 Describe("DisplayType", func() { 184 It("displays the passed type and time in localized ISO 8601", func() { 185 passedTime := time.Now() 186 err := display.DisplayType("banana", passedTime) 187 Expect(err).ToNot(HaveOccurred()) 188 189 err = display.Stop() 190 Expect(err).ToNot(HaveOccurred()) 191 192 Expect(testUI.Out).To(Say(`banana: \[%s\]`, regexp.QuoteMeta(passedTime.Format(time.RFC3339)))) 193 }) 194 }) 195 196 Describe("HandleInternalError", func() { 197 It("sends error to standard error", func() { 198 err := errors.New("foobar") 199 display.HandleInternalError(err) 200 201 err = display.Stop() 202 Expect(err).ToNot(HaveOccurred()) 203 204 Expect(testUI.Err).To(Say("foobar")) 205 }) 206 }) 207 208 Describe("Start and Stop", func() { 209 It("locks and then unlocks the mutex properly", func() { 210 c := make(chan bool) 211 go func() { 212 Expect(display.Start()).NotTo(HaveOccurred()) 213 c <- true 214 }() 215 Consistently(c).ShouldNot(Receive()) 216 Expect(display.Stop()).NotTo(HaveOccurred()) 217 Eventually(c).Should(Receive()) 218 Expect(display.Stop()).NotTo(HaveOccurred()) 219 }) 220 }) 221 222 Describe("UI", func() { 223 Describe("RequestLoggerTerminalDisplay", func() { 224 BeforeEach(func() { 225 Expect(display.Stop()).ToNot(HaveOccurred()) 226 }) 227 228 It("returns a RequestLoggerTerminalDisplay with the consistent display mutex", func() { 229 logger1 := testUI.RequestLoggerTerminalDisplay() 230 logger2 := testUI.RequestLoggerTerminalDisplay() 231 232 c := make(chan bool) 233 err := logger1.Start() 234 Expect(err).ToNot(HaveOccurred()) 235 go func() { 236 Expect(logger2.Start()).ToNot(HaveOccurred()) 237 c <- true 238 }() 239 Consistently(c).ShouldNot(Receive()) 240 Expect(logger1.Stop()).ToNot(HaveOccurred()) 241 Eventually(c).Should(Receive()) 242 }) 243 }) 244 }) 245 })