github.com/mundipagg/tracer-splunk-writer@v1.0.6/splunk_test.go (about) 1 package splunk 2 3 import ( 4 "errors" 5 "net/http" 6 "os" 7 "sync" 8 "testing" 9 "time" 10 11 "github.com/icrowley/fake" 12 "github.com/jarcoal/httpmock" 13 "github.com/mralves/tracer" 14 "github.com/mundipagg/tracer-splunk-writer/buffer" 15 "github.com/mundipagg/tracer-splunk-writer/json" 16 "github.com/stretchr/testify/assert" 17 ) 18 19 type event struct { 20 Level string 21 MessageTemplate string 22 Properties Entry 23 Timestamp string 24 } 25 26 func TestWriter_Write(t *testing.T) { 27 os.Stderr, _ = os.Open(os.DevNull) 28 t.Parallel() 29 t.Run("when the minimum level is higher than the log level received", func(t *testing.T) { 30 t.Parallel() 31 buf := &buffer.Mock{} 32 ref := time.Now() 33 stackTrace := tracer.GetStackTrace(3) 34 subject := &Writer{ 35 buffer: buf, 36 minimumLevel: tracer.Error, 37 } 38 39 entry := tracer.Entry{ 40 Level: tracer.Debug, 41 Message: "Message", 42 StackTrace: stackTrace, 43 Time: ref, 44 Owner: "owner", 45 TransactionId: "Transaction", 46 Args: []interface{}{ 47 "Arg", 48 Entry{ 49 "Nested": "value", 50 }, 51 }, 52 } 53 subject.Write(entry) 54 time.Sleep(30 * time.Millisecond) 55 buf.AssertExpectations(t) 56 }) 57 t.Run("when the minimum level is lower than the log level received", func(t *testing.T) { 58 t.Parallel() 59 buf := &buffer.Mock{} 60 ref := time.Now() 61 stackTrace := tracer.GetStackTrace(3) 62 event := event{ 63 Level: Error, 64 MessageTemplate: "Before Message After", 65 Properties: Entry{ 66 "string": "Arg", 67 "Nested": "value", 68 "Caller": stackTrace[0].String(), 69 "RequestKey": "Transaction", 70 "Name": "Default", 71 }, 72 Timestamp: ref.UTC().Format(time.RFC3339Nano), 73 } 74 buf.On("Write", event).Return() 75 subject := &Writer{ 76 buffer: buf, 77 minimumLevel: tracer.Debug, 78 messageEnvelop: "Before %v After", 79 defaultPropertiesApp: Entry{ 80 "Name": "Default", 81 }, 82 } 83 84 entry := tracer.Entry{ 85 Level: tracer.Critical, 86 Message: "Message", 87 StackTrace: stackTrace, 88 Time: ref, 89 Owner: "owner", 90 TransactionId: "Transaction", 91 Args: []interface{}{ 92 "Arg", 93 Entry{ 94 "Nested": "value", 95 }, 96 }, 97 } 98 subject.Write(entry) 99 buf.AssertNumberOfCalls(t, "Write", 0) 100 }) 101 } 102 103 func TestWriter_Send(t *testing.T) { 104 t.Parallel() 105 t.Run("when there is an invalid field value in event", func(t *testing.T) { 106 t.Parallel() 107 is := assert.New(t) 108 c := &http.Client{} 109 activateNonDefault(c) 110 subject := &Writer{ 111 address: "http://log.io/", 112 client: c, 113 marshaller: json.New(), 114 } 115 err := subject.send([]interface{}{ 116 event{ 117 Properties: Entry{ 118 "C": make(chan int), 119 }, 120 }, 121 }) 122 is.NotNil(err, "it should return an error") 123 }) 124 t.Run("when the request fails", func(t *testing.T) { 125 t.Parallel() 126 is := assert.New(t) 127 c := &http.Client{} 128 activateNonDefault(c) 129 url := "http://log.io/" + fake.Password(8, 8, false, false, false) 130 httpmock.RegisterResponder("POST", url, func(request *http.Request) (response *http.Response, err error) { 131 return nil, errors.New("failed") 132 }) 133 subject := &Writer{ 134 address: url, 135 client: c, 136 marshaller: json.New(), 137 } 138 err := subject.send([]interface{}{ 139 event{ 140 Properties: Entry{ 141 "C": 15, 142 }, 143 }, 144 }) 145 is.NotNil(err, "it should return an error") 146 }) 147 t.Run("when the request fails", func(t *testing.T) { 148 t.Parallel() 149 is := assert.New(t) 150 c := &http.Client{} 151 activateNonDefault(c) 152 url := "http://log.io/" + fake.Password(8, 8, false, false, false) 153 httpmock.RegisterResponder("POST", url, func(request *http.Request) (response *http.Response, err error) { 154 is.Equal(http.Header{ 155 "Authorization": []string{"Splunk key"}, 156 "Content-Type": []string{"application/json"}, 157 }, request.Header, "it should return the expected header") 158 return nil, errors.New("failed") 159 }) 160 subject := &Writer{ 161 address: url, 162 client: c, 163 marshaller: json.New(), 164 key: "key", 165 } 166 err := subject.send([]interface{}{ 167 event{ 168 Properties: Entry{ 169 "C": 15, 170 }, 171 }, 172 }) 173 is.NotNil(err, "it should return an error") 174 }) 175 t.Run("when the request return an status unexpected", func(t *testing.T) { 176 t.Parallel() 177 is := assert.New(t) 178 c := &http.Client{} 179 activateNonDefault(c) 180 url := "http://log.io/" + fake.Password(8, 8, false, false, false) 181 httpmock.RegisterResponder("POST", url, func(request *http.Request) (response *http.Response, err error) { 182 is.Equal(http.Header{ 183 "Authorization": []string{"Splunk key"}, 184 "Content-Type": []string{"application/json"}, 185 }, request.Header, "it should return the expected header") 186 return httpmock.NewBytesResponse(502, nil), nil 187 }) 188 subject := &Writer{ 189 address: url, 190 client: c, 191 marshaller: json.New(), 192 key: "key", 193 } 194 err := subject.send([]interface{}{ 195 event{ 196 Properties: Entry{ 197 "C": 15, 198 }, 199 }, 200 }) 201 is.NotNil(err, "it should return an error") 202 }) 203 t.Run("when the request return 201", func(t *testing.T) { 204 t.Parallel() 205 is := assert.New(t) 206 c := &http.Client{} 207 activateNonDefault(c) 208 url := "http://log.io/" + fake.Password(8, 8, false, false, false) 209 httpmock.RegisterResponder("POST", url, func(request *http.Request) (response *http.Response, err error) { 210 is.Equal(http.Header{ 211 "Authorization": []string{"Splunk key"}, 212 "Content-Type": []string{"application/json"}, 213 }, request.Header, "it should return the expected header") 214 return httpmock.NewBytesResponse(200, nil), nil 215 }) 216 subject := &Writer{ 217 address: url, 218 client: c, 219 marshaller: json.New(), 220 key: "key", 221 } 222 err := subject.send([]interface{}{ 223 event{ 224 Properties: Entry{ 225 "C": 15, 226 }, 227 }, 228 }) 229 is.Nil(err, "it should return no error") 230 }) 231 } 232 233 var lock sync.Mutex 234 235 func activateNonDefault(c *http.Client) { 236 lock.Lock() 237 defer lock.Unlock() 238 httpmock.ActivateNonDefault(c) 239 }