github.com/newrelic/go-agent@v3.26.0+incompatible/internal/custom_event_test.go (about)

     1  // Copyright 2020 New Relic Corporation. All rights reserved.
     2  // SPDX-License-Identifier: Apache-2.0
     3  
     4  package internal
     5  
     6  import (
     7  	"encoding/json"
     8  	"strconv"
     9  	"testing"
    10  	"time"
    11  )
    12  
    13  var (
    14  	now       = time.Date(2014, time.November, 28, 1, 1, 0, 0, time.UTC)
    15  	strLen512 = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" +
    16  		"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" +
    17  		"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" +
    18  		"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" +
    19  		"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" +
    20  		"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" +
    21  		"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" +
    22  		"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
    23  	strLen255 = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" +
    24  		"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" +
    25  		"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" +
    26  		"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
    27  )
    28  
    29  // Tests use a single key-value pair in params to ensure deterministic JSON
    30  // ordering.
    31  
    32  func TestCreateCustomEventSuccess(t *testing.T) {
    33  	event, err := CreateCustomEvent("myEvent", map[string]interface{}{"alpha": 1}, now)
    34  	if nil != err {
    35  		t.Fatal(err)
    36  	}
    37  	js, err := json.Marshal(event)
    38  	if nil != err {
    39  		t.Fatal(err)
    40  	}
    41  	if string(js) != `[{"type":"myEvent","timestamp":1.41713646e+09},{"alpha":1},{}]` {
    42  		t.Fatal(string(js))
    43  	}
    44  }
    45  
    46  func TestInvalidEventTypeCharacter(t *testing.T) {
    47  	event, err := CreateCustomEvent("myEvent!", map[string]interface{}{"alpha": 1}, now)
    48  	if err != ErrEventTypeRegex {
    49  		t.Fatal(err)
    50  	}
    51  	if nil != event {
    52  		t.Fatal(event)
    53  	}
    54  }
    55  
    56  func TestLongEventType(t *testing.T) {
    57  	event, err := CreateCustomEvent(strLen512, map[string]interface{}{"alpha": 1}, now)
    58  	if err != errEventTypeLength {
    59  		t.Fatal(err)
    60  	}
    61  	if nil != event {
    62  		t.Fatal(event)
    63  	}
    64  }
    65  
    66  func TestNilParams(t *testing.T) {
    67  	event, err := CreateCustomEvent("myEvent", nil, now)
    68  	if nil != err {
    69  		t.Fatal(err)
    70  	}
    71  	js, err := json.Marshal(event)
    72  	if nil != err {
    73  		t.Fatal(err)
    74  	}
    75  	if string(js) != `[{"type":"myEvent","timestamp":1.41713646e+09},{},{}]` {
    76  		t.Fatal(string(js))
    77  	}
    78  }
    79  
    80  func TestMissingEventType(t *testing.T) {
    81  	event, err := CreateCustomEvent("", map[string]interface{}{"alpha": 1}, now)
    82  	if err != ErrEventTypeRegex {
    83  		t.Fatal(err)
    84  	}
    85  	if nil != event {
    86  		t.Fatal(event)
    87  	}
    88  }
    89  
    90  func TestEmptyParams(t *testing.T) {
    91  	event, err := CreateCustomEvent("myEvent", map[string]interface{}{}, now)
    92  	if nil != err {
    93  		t.Fatal(err)
    94  	}
    95  	js, err := json.Marshal(event)
    96  	if nil != err {
    97  		t.Fatal(err)
    98  	}
    99  	if string(js) != `[{"type":"myEvent","timestamp":1.41713646e+09},{},{}]` {
   100  		t.Fatal(string(js))
   101  	}
   102  }
   103  
   104  func TestTruncatedStringValue(t *testing.T) {
   105  	event, err := CreateCustomEvent("myEvent", map[string]interface{}{"alpha": strLen512}, now)
   106  	if nil != err {
   107  		t.Fatal(err)
   108  	}
   109  	js, err := json.Marshal(event)
   110  	if nil != err {
   111  		t.Fatal(err)
   112  	}
   113  	if string(js) != `[{"type":"myEvent","timestamp":1.41713646e+09},{"alpha":"`+strLen255+`"},{}]` {
   114  		t.Fatal(string(js))
   115  	}
   116  }
   117  
   118  func TestInvalidValueType(t *testing.T) {
   119  	event, err := CreateCustomEvent("myEvent", map[string]interface{}{"alpha": []string{}}, now)
   120  	if _, ok := err.(ErrInvalidAttributeType); !ok {
   121  		t.Fatal(err)
   122  	}
   123  	if nil != event {
   124  		t.Fatal(event)
   125  	}
   126  }
   127  
   128  func TestInvalidCustomAttributeKey(t *testing.T) {
   129  	event, err := CreateCustomEvent("myEvent", map[string]interface{}{strLen512: 1}, now)
   130  	if nil == err {
   131  		t.Fatal(err)
   132  	}
   133  	if _, ok := err.(invalidAttributeKeyErr); !ok {
   134  		t.Fatal(err)
   135  	}
   136  	if nil != event {
   137  		t.Fatal(event)
   138  	}
   139  }
   140  
   141  func TestTooManyAttributes(t *testing.T) {
   142  	params := make(map[string]interface{})
   143  	for i := 0; i < customEventAttributeLimit+1; i++ {
   144  		params[strconv.Itoa(i)] = i
   145  	}
   146  	event, err := CreateCustomEvent("myEvent", params, now)
   147  	if errNumAttributes != err {
   148  		t.Fatal(err)
   149  	}
   150  	if nil != event {
   151  		t.Fatal(event)
   152  	}
   153  }
   154  
   155  func TestCustomEventAttributeTypes(t *testing.T) {
   156  	testcases := []struct {
   157  		val interface{}
   158  		js  string
   159  	}{
   160  		{"string", `"string"`},
   161  		{true, `true`},
   162  		{false, `false`},
   163  		{uint8(1), `1`},
   164  		{uint16(1), `1`},
   165  		{uint32(1), `1`},
   166  		{uint64(1), `1`},
   167  		{int8(1), `1`},
   168  		{int16(1), `1`},
   169  		{int32(1), `1`},
   170  		{int64(1), `1`},
   171  		{float32(1), `1`},
   172  		{float64(1), `1`},
   173  		{uint(1), `1`},
   174  		{int(1), `1`},
   175  		{uintptr(1), `1`},
   176  	}
   177  
   178  	for _, tc := range testcases {
   179  		event, err := CreateCustomEvent("myEvent", map[string]interface{}{"key": tc.val}, now)
   180  		if nil != err {
   181  			t.Fatal(err)
   182  		}
   183  		js, err := json.Marshal(event)
   184  		if nil != err {
   185  			t.Fatal(err)
   186  		}
   187  		if string(js) != `[{"type":"myEvent","timestamp":1.41713646e+09},{"key":`+tc.js+`},{}]` {
   188  			t.Fatal(string(js))
   189  		}
   190  	}
   191  }
   192  
   193  func TestCustomParamsCopied(t *testing.T) {
   194  	params := map[string]interface{}{"alpha": 1}
   195  	event, err := CreateCustomEvent("myEvent", params, now)
   196  	if nil != err {
   197  		t.Fatal(err)
   198  	}
   199  	// Attempt to change the params after the event created:
   200  	params["zip"] = "zap"
   201  	js, err := json.Marshal(event)
   202  	if nil != err {
   203  		t.Fatal(err)
   204  	}
   205  	if string(js) != `[{"type":"myEvent","timestamp":1.41713646e+09},{"alpha":1},{}]` {
   206  		t.Fatal(string(js))
   207  	}
   208  }
   209  
   210  func TestMultipleAttributeJSON(t *testing.T) {
   211  	params := map[string]interface{}{"alpha": 1, "beta": 2}
   212  	event, err := CreateCustomEvent("myEvent", params, now)
   213  	if nil != err {
   214  		t.Fatal(err)
   215  	}
   216  	js, err := json.Marshal(event)
   217  	if nil != err {
   218  		t.Fatal(err)
   219  	}
   220  	// Params order may not be deterministic, so we simply test that the
   221  	// JSON created is valid.
   222  	var valid interface{}
   223  	if err := json.Unmarshal(js, &valid); nil != err {
   224  		t.Error(string(js))
   225  	}
   226  }