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  }