github.com/newrelic/go-agent@v3.26.0+incompatible/internal/connect_reply_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 "testing" 9 "time" 10 ) 11 12 func TestCreateFullTxnNameBasic(t *testing.T) { 13 emptyReply := ConnectReplyDefaults() 14 15 tcs := []struct { 16 input string 17 background bool 18 expect string 19 }{ 20 {"", true, "WebTransaction/Go/"}, 21 {"/", true, "WebTransaction/Go/"}, 22 {"hello", true, "WebTransaction/Go/hello"}, 23 {"/hello", true, "WebTransaction/Go/hello"}, 24 25 {"", false, "OtherTransaction/Go/"}, 26 {"/", false, "OtherTransaction/Go/"}, 27 {"hello", false, "OtherTransaction/Go/hello"}, 28 {"/hello", false, "OtherTransaction/Go/hello"}, 29 } 30 31 for _, tc := range tcs { 32 if out := CreateFullTxnName(tc.input, emptyReply, tc.background); out != tc.expect { 33 t.Error(tc.input, tc.background, out, tc.expect) 34 } 35 } 36 } 37 38 func TestCreateFullTxnNameURLRulesIgnore(t *testing.T) { 39 js := `[{ 40 "match_expression":".*zip.*$", 41 "ignore":true 42 }]` 43 reply := ConnectReplyDefaults() 44 err := json.Unmarshal([]byte(js), &reply.URLRules) 45 if nil != err { 46 t.Fatal(err) 47 } 48 if out := CreateFullTxnName("/zap/zip/zep", reply, true); out != "" { 49 t.Error(out) 50 } 51 } 52 53 func TestCreateFullTxnNameTxnRulesIgnore(t *testing.T) { 54 js := `[{ 55 "match_expression":"^WebTransaction/Go/zap/zip/zep$", 56 "ignore":true 57 }]` 58 reply := ConnectReplyDefaults() 59 err := json.Unmarshal([]byte(js), &reply.TxnNameRules) 60 if nil != err { 61 t.Fatal(err) 62 } 63 if out := CreateFullTxnName("/zap/zip/zep", reply, true); out != "" { 64 t.Error(out) 65 } 66 } 67 68 func TestCreateFullTxnNameAllRulesWithCache(t *testing.T) { 69 js := `{ 70 "url_rules":[ 71 {"match_expression":"zip","each_segment":true,"replacement":"zoop"} 72 ], 73 "transaction_name_rules":[ 74 {"match_expression":"WebTransaction/Go/zap/zoop/zep", 75 "replacement":"WebTransaction/Go/zap/zoop/zep/zup/zyp"} 76 ], 77 "transaction_segment_terms":[ 78 {"prefix": "WebTransaction/Go/", 79 "terms": ["zyp", "zoop", "zap"]} 80 ] 81 }` 82 reply := ConnectReplyDefaults() 83 reply.rulesCache = newRulesCache(3) 84 err := json.Unmarshal([]byte(js), &reply) 85 if nil != err { 86 t.Fatal(err) 87 } 88 want := "WebTransaction/Go/zap/zoop/*/zyp" 89 if out := CreateFullTxnName("/zap/zip/zep", reply, true); out != want { 90 t.Error("wanted:", want, "got:", out) 91 } 92 // Check that the cache was populated as expected. 93 if out := reply.rulesCache.find("/zap/zip/zep", true); out != want { 94 t.Error("wanted:", want, "got:", out) 95 } 96 // Check that the next CreateFullTxnName returns the same output. 97 if out := CreateFullTxnName("/zap/zip/zep", reply, true); out != want { 98 t.Error("wanted:", want, "got:", out) 99 } 100 } 101 102 func TestCalculateApdexThreshold(t *testing.T) { 103 reply := ConnectReplyDefaults() 104 threshold := CalculateApdexThreshold(reply, "WebTransaction/Go/hello") 105 if threshold != 500*time.Millisecond { 106 t.Error("default apdex threshold", threshold) 107 } 108 109 reply = ConnectReplyDefaults() 110 reply.ApdexThresholdSeconds = 1.3 111 reply.KeyTxnApdex = map[string]float64{ 112 "WebTransaction/Go/zip": 2.2, 113 "WebTransaction/Go/zap": 2.3, 114 } 115 threshold = CalculateApdexThreshold(reply, "WebTransaction/Go/hello") 116 if threshold != 1300*time.Millisecond { 117 t.Error(threshold) 118 } 119 threshold = CalculateApdexThreshold(reply, "WebTransaction/Go/zip") 120 if threshold != 2200*time.Millisecond { 121 t.Error(threshold) 122 } 123 } 124 125 func TestIsTrusted(t *testing.T) { 126 for _, test := range []struct { 127 id int 128 trusted string 129 expected bool 130 }{ 131 {1, `[]`, false}, 132 {1, `[2, 3]`, false}, 133 {1, `[1]`, true}, 134 {1, `[1, 2, 3]`, true}, 135 } { 136 trustedAccounts := make(trustedAccountSet) 137 if err := json.Unmarshal([]byte(test.trusted), &trustedAccounts); err != nil { 138 t.Fatal(err) 139 } 140 141 if actual := trustedAccounts.IsTrusted(test.id); test.expected != actual { 142 t.Errorf("failed asserting whether %d is trusted by %v: expected %v; got %v", test.id, test.trusted, test.expected, actual) 143 } 144 } 145 } 146 147 func BenchmarkDefaultRules(b *testing.B) { 148 js := `{"url_rules":[ 149 { 150 "match_expression":".*\\.(ace|arj|ini|txt|udl|plist|css|gif|ico|jpe?g|js|png|swf|woff|caf|aiff|m4v|mpe?g|mp3|mp4|mov)$", 151 "replacement":"/*.\\1", 152 "ignore":false, 153 "eval_order":1000, 154 "terminate_chain":true, 155 "replace_all":false, 156 "each_segment":false 157 }, 158 { 159 "match_expression":"^[0-9][0-9a-f_,.-]*$", 160 "replacement":"*", 161 "ignore":false, 162 "eval_order":1001, 163 "terminate_chain":false, 164 "replace_all":false, 165 "each_segment":true 166 }, 167 { 168 "match_expression":"^(.*)/[0-9][0-9a-f_,-]*\\.([0-9a-z][0-9a-z]*)$", 169 "replacement":"\\1/.*\\2", 170 "ignore":false, 171 "eval_order":1002, 172 "terminate_chain":false, 173 "replace_all":false, 174 "each_segment":false 175 } 176 ]}` 177 reply := ConnectReplyDefaults() 178 reply.rulesCache = newRulesCache(1) 179 err := json.Unmarshal([]byte(js), &reply) 180 if nil != err { 181 b.Fatal(err) 182 } 183 184 b.ResetTimer() 185 b.ReportAllocs() 186 187 for i := 0; i < b.N; i++ { 188 if out := CreateFullTxnName("/myEndpoint", reply, true); out != "WebTransaction/Go/myEndpoint" { 189 b.Error(out) 190 } 191 } 192 } 193 194 func TestNegativeHarvestLimits(t *testing.T) { 195 // Test that negative harvest event limits will cause a connect error. 196 // Harvest event limits are never expected to be negative: This is just 197 // extra defensiveness. 198 _, err := ConstructConnectReply([]byte(`{"return_value":{ 199 "event_harvest_config": { 200 "harvest_limits": { 201 "error_event_data": -1 202 } 203 } 204 }}`), PreconnectReply{}) 205 if err == nil { 206 t.Fatal("expected error missing") 207 } 208 } 209 210 type dfltMaxTxnEvents struct{} 211 212 func (dfltMaxTxnEvents) MaxTxnEvents() int { 213 return MaxTxnEvents 214 } 215 216 func TestDefaultEventHarvestConfigJSON(t *testing.T) { 217 js, err := json.Marshal(DefaultEventHarvestConfig(dfltMaxTxnEvents{})) 218 if err != nil { 219 t.Error(err) 220 } 221 if string(js) != `{"report_period_ms":60000,"harvest_limits":{"analytic_event_data":10000,"custom_event_data":10000,"error_event_data":100}}` { 222 t.Error(string(js)) 223 } 224 }