PageRenderTime 58ms CodeModel.GetById 26ms RepoModel.GetById 0ms app.codeStats 0ms

/test/new_relic/agent/browser_monitoring_test.rb

http://github.com/newrelic/rpm
Ruby | 323 lines | 261 code | 53 blank | 9 comment | 0 complexity | 4f053b0605ca4babd60df93841f84f52 MD5 | raw file
Possible License(s): Apache-2.0
  1. ENV['SKIP_RAILS'] = 'true'
  2. require File.expand_path(File.join(File.dirname(__FILE__),'..','..','test_helper'))
  3. require "new_relic/agent/browser_monitoring"
  4. class NewRelic::Agent::BrowserMonitoringTest < Test::Unit::TestCase
  5. include NewRelic::Agent::BrowserMonitoring
  6. include NewRelic::Agent::Instrumentation::ControllerInstrumentation
  7. def setup
  8. NewRelic::Agent.manual_start
  9. @browser_monitoring_key = "fred"
  10. @episodes_file = "this_is_my_file"
  11. NewRelic::Agent.instance.instance_eval do
  12. @beacon_configuration = NewRelic::Agent::BeaconConfiguration.new({"rum.enabled" => true, "browser_key" => "browserKey", "application_id" => "apId", "beacon"=>"beacon", "episodes_url"=>"this_is_my_file", 'rum.jsonp' => true})
  13. end
  14. Thread.current[:last_metric_frame] = nil
  15. NewRelic::Agent::TransactionInfo.clear
  16. end
  17. def teardown
  18. mocha_teardown
  19. end
  20. def test_browser_monitoring_start_time_is_reset_each_request_when_auto_instrument_is_disabled
  21. controller = Object.new
  22. def controller.perform_action_without_newrelic_trace(method, options={});
  23. # noop; instrument me
  24. end
  25. def controller.newrelic_metric_path; "foo"; end
  26. controller.extend ::NewRelic::Agent::Instrumentation::ControllerInstrumentation
  27. controller.extend ::NewRelic::Agent::BrowserMonitoring
  28. NewRelic::Control.instance['browser_monitoring'] = { 'auto_instrument' => false }
  29. controller.perform_action_with_newrelic_trace(:index)
  30. first_request_start_time = controller.send(:browser_monitoring_start_time)
  31. controller.perform_action_with_newrelic_trace(:index)
  32. second_request_start_time = controller.send(:browser_monitoring_start_time)
  33. # assert that these aren't the same time object
  34. # the start time should be reinitialized each request to the controller
  35. assert !(first_request_start_time.equal? second_request_start_time)
  36. end
  37. def test_browser_timing_header_with_no_beacon_configuration
  38. NewRelic::Agent.instance.expects(:beacon_configuration).returns( nil)
  39. header = browser_timing_header
  40. assert_equal "", header
  41. end
  42. def test_browser_timing_header
  43. header = browser_timing_header
  44. assert_equal "<script type=\"text/javascript\">var NREUMQ=NREUMQ||[];NREUMQ.push([\"mark\",\"firstbyte\",new Date().getTime()]);</script>", header
  45. end
  46. def test_browser_timing_header_with_rum_enabled_not_specified
  47. NewRelic::Agent.instance.expects(:beacon_configuration).at_least_once.returns( NewRelic::Agent::BeaconConfiguration.new({"browser_key" => "browserKey", "application_id" => "apId", "beacon"=>"beacon", "episodes_url"=>"this_is_my_file"}))
  48. header = browser_timing_header
  49. assert_equal "<script type=\"text/javascript\">var NREUMQ=NREUMQ||[];NREUMQ.push([\"mark\",\"firstbyte\",new Date().getTime()]);</script>", header
  50. end
  51. def test_browser_timing_header_with_rum_enabled_false
  52. NewRelic::Agent.instance.expects(:beacon_configuration).twice.returns( NewRelic::Agent::BeaconConfiguration.new({"rum.enabled" => false, "browser_key" => "browserKey", "application_id" => "apId", "beacon"=>"beacon", "episodes_url"=>"this_is_my_file"}))
  53. header = browser_timing_header
  54. assert_equal "", header
  55. end
  56. def test_browser_timing_header_disable_all_tracing
  57. header = nil
  58. NewRelic::Agent.disable_all_tracing do
  59. header = browser_timing_header
  60. end
  61. assert_equal "", header
  62. end
  63. def test_browser_timing_header_disable_transaction_tracing
  64. header = nil
  65. NewRelic::Agent.disable_transaction_tracing do
  66. header = browser_timing_header
  67. end
  68. assert_equal "", header
  69. end
  70. def test_browser_timing_footer
  71. browser_timing_header
  72. NewRelic::Control.instance.expects(:license_key).returns("a" * 13)
  73. footer = browser_timing_footer
  74. snippet = '<script type="text/javascript">if (!NREUMQ.f) { NREUMQ.f=function() {
  75. NREUMQ.push(["load",new Date().getTime()]);
  76. var e=document.createElement("script");'
  77. assert footer.include?(snippet), "Expected footer to include snippet: #{snippet}, but instead was #{footer}"
  78. end
  79. def test_browser_timing_footer_with_no_browser_key_rum_enabled
  80. browser_timing_header
  81. NewRelic::Agent.instance.expects(:beacon_configuration).returns( NewRelic::Agent::BeaconConfiguration.new({"rum.enabled" => true, "application_id" => "apId", "beacon"=>"beacon", "episodes_url"=>"this_is_my_file"}))
  82. footer = browser_timing_footer
  83. assert_equal "", footer
  84. end
  85. def test_browser_timing_footer_with_no_browser_key_rum_disabled
  86. browser_timing_header
  87. NewRelic::Agent.instance.expects(:beacon_configuration).returns( NewRelic::Agent::BeaconConfiguration.new({"rum.enabled" => false, "application_id" => "apId", "beacon"=>"beacon", "episodes_url"=>"this_is_my_file"}))
  88. footer = browser_timing_footer
  89. assert_equal "", footer
  90. end
  91. def test_browser_timing_footer_with_rum_enabled_not_specified
  92. browser_timing_header
  93. license_bytes = [];
  94. ("a" * 13).each_byte {|byte| license_bytes << byte}
  95. config = NewRelic::Agent::BeaconConfiguration.new({"browser_key" => "browserKey", "application_id" => "apId", "beacon"=>"beacon", "episodes_url"=>"this_is_my_file", "license_bytes" => license_bytes})
  96. config.expects(:license_bytes).returns(license_bytes).at_least_once
  97. NewRelic::Agent.instance.expects(:beacon_configuration).returns(config).at_least_once
  98. footer = browser_timing_footer
  99. beginning_snippet = '<script type="text/javascript">if (!NREUMQ.f) { NREUMQ.f=function() {
  100. NREUMQ.push(["load",new Date().getTime()]);
  101. var e=document.createElement("script");'
  102. ending_snippet = "])</script>"
  103. assert(footer.include?(beginning_snippet), "expected footer to include beginning snippet: #{beginning_snippet}, but was #{footer}")
  104. assert(footer.include?(ending_snippet), "expected footer to include ending snippet: #{ending_snippet}, but was #{footer}")
  105. end
  106. def test_browser_timing_footer_with_no_beacon_configuration
  107. browser_timing_header
  108. NewRelic::Agent.instance.expects(:beacon_configuration).returns( nil)
  109. footer = browser_timing_footer
  110. assert_equal "", footer
  111. end
  112. def test_browser_timing_footer_disable_all_tracing
  113. browser_timing_header
  114. footer = nil
  115. NewRelic::Agent.disable_all_tracing do
  116. footer = browser_timing_footer
  117. end
  118. assert_equal "", footer
  119. end
  120. def test_browser_timing_footer_disable_transaction_tracing
  121. browser_timing_header
  122. footer = nil
  123. NewRelic::Agent.disable_transaction_tracing do
  124. footer = browser_timing_footer
  125. end
  126. assert_equal "", footer
  127. end
  128. def test_browser_timing_footer_browser_monitoring_key_missing
  129. fake_config = mock('beacon configuration')
  130. NewRelic::Agent.instance.expects(:beacon_configuration).returns(fake_config)
  131. fake_config.expects(:nil?).returns(false)
  132. fake_config.expects(:rum_enabled).returns(true)
  133. fake_config.expects(:browser_monitoring_key).returns(nil)
  134. self.expects(:generate_footer_js).never
  135. assert_equal('', browser_timing_footer, "should not return a footer when there is no key")
  136. end
  137. def test_generate_footer_js_null_case
  138. self.expects(:browser_monitoring_start_time).returns(nil)
  139. assert_equal('', generate_footer_js(NewRelic::Agent.instance.beacon_configuration), "should not send javascript when there is no start time")
  140. end
  141. def test_generate_footer_js_with_start_time
  142. self.expects(:browser_monitoring_start_time).returns(Time.at(100))
  143. fake_bc = mock('beacon configuration')
  144. fake_bc.expects(:application_id).returns(1)
  145. fake_bc.expects(:beacon).returns('beacon')
  146. fake_bc.expects(:browser_monitoring_key).returns('a' * 40)
  147. NewRelic::Agent.instance.stubs(:beacon_configuration).returns(fake_bc)
  148. self.expects(:footer_js_string).with(NewRelic::Agent.instance.beacon_configuration, 'beacon', 'a' * 40, 1).returns('footer js')
  149. assert_equal('footer js', generate_footer_js(NewRelic::Agent.instance.beacon_configuration), 'should generate and return the footer JS when there is a start time')
  150. end
  151. def test_browser_monitoring_transaction_name_basic
  152. mock = mock('transaction sample')
  153. NewRelic::Agent::TransactionInfo.set(mock)
  154. mock.stubs(:transaction_name).returns('a transaction name')
  155. assert_equal('a transaction name', browser_monitoring_transaction_name, "should take the value from the thread local")
  156. end
  157. def test_browser_monitoring_transaction_name_empty
  158. mock = mock('transaction sample')
  159. NewRelic::Agent::TransactionInfo.set(mock)
  160. mock.stubs(:transaction_name).returns('')
  161. assert_equal('', browser_monitoring_transaction_name, "should take the value even when it is empty")
  162. end
  163. def test_browser_monitoring_transaction_name_nil
  164. assert_equal('(unknown)', browser_monitoring_transaction_name, "should fill in a default when it is nil")
  165. end
  166. def test_browser_monitoring_transaction_name_when_tt_disabled
  167. @sampler = NewRelic::Agent.instance.transaction_sampler
  168. @sampler.disable
  169. perform_action_with_newrelic_trace(:name => 'disabled_transactions') do
  170. self.class.inspect
  171. end
  172. assert_match(/disabled_transactions/, browser_monitoring_transaction_name,
  173. "should name transaction when transaction tracing disabled")
  174. ensure
  175. @sampler.enable
  176. end
  177. def test_browser_monitoring_start_time
  178. mock = mock('transaction info')
  179. NewRelic::Agent::TransactionInfo.set(mock)
  180. mock.stubs(:start_time).returns(Time.at(100))
  181. mock.stubs(:guid).returns('ABC')
  182. assert_equal(Time.at(100), browser_monitoring_start_time, "should take the value from the thread local")
  183. end
  184. def test_clamp_to_positive
  185. assert_equal(0.0, clamp_to_positive(-1), "should clamp a negative value to zero")
  186. assert_equal(1232, clamp_to_positive(1232), "should pass through the value when it is positive")
  187. assert_equal(0, clamp_to_positive(0), "should not mess with zero when passing it through")
  188. end
  189. def test_browser_monitoring_app_time_nonzero
  190. start = Time.now
  191. self.expects(:browser_monitoring_start_time).returns(start - 1)
  192. Time.expects(:now).returns(start)
  193. assert_equal(1000, browser_monitoring_app_time, 'should return a rounded time')
  194. end
  195. def test_browser_monitoring_queue_time_nil
  196. assert_equal(0.0, browser_monitoring_queue_time, 'should return zero when there is no queue time')
  197. end
  198. def test_browser_monitoring_queue_time_zero
  199. frame = Thread.current[:last_metric_frame] = mock('metric frame')
  200. frame.expects(:queue_time).returns(0.0)
  201. assert_equal(0.0, browser_monitoring_queue_time, 'should return zero when there is zero queue time')
  202. end
  203. def test_browser_monitoring_queue_time_ducks
  204. frame = Thread.current[:last_metric_frame] = mock('metric frame')
  205. frame.expects(:queue_time).returns('a duck')
  206. assert_equal(0.0, browser_monitoring_queue_time, 'should return zero when there is an incorrect queue time')
  207. end
  208. def test_browser_monitoring_queue_time_nonzero
  209. frame = Thread.current[:last_metric_frame] = mock('metric frame')
  210. frame.expects(:queue_time).returns(3.00002)
  211. assert_equal(3000, browser_monitoring_queue_time, 'should return a rounded time')
  212. end
  213. def test_footer_js_string_basic
  214. beacon = ''
  215. license_key = ''
  216. application_id = 1
  217. # mocking this because JRuby thinks that Time.now - Time.now
  218. # always takes at least 1ms
  219. self.expects(:browser_monitoring_app_time).returns(0)
  220. frame = Thread.current[:last_metric_frame] = mock('metric frame')
  221. user_attributes = {:user => "user", :account => "account", :product => "product"}
  222. frame.expects(:user_attributes).returns(user_attributes).at_least_once
  223. frame.expects(:queue_time).returns(0)
  224. sample = mock('transaction info')
  225. NewRelic::Agent::TransactionInfo.set(sample)
  226. sample.stubs(:start_time).returns(Time.at(100))
  227. sample.stubs(:guid).returns('ABC')
  228. sample.stubs(:transaction_name).returns('most recent transaction')
  229. sample.stubs(:include_guid?).returns(true)
  230. sample.stubs(:duration).returns(12.0)
  231. sample.stubs(:token).returns('0123456789ABCDEF')
  232. self.expects(:obfuscate).with(NewRelic::Agent.instance.beacon_configuration, 'most recent transaction').returns('most recent transaction')
  233. self.expects(:obfuscate).with(NewRelic::Agent.instance.beacon_configuration, 'user').returns('user')
  234. self.expects(:obfuscate).with(NewRelic::Agent.instance.beacon_configuration, 'account').returns('account')
  235. self.expects(:obfuscate).with(NewRelic::Agent.instance.beacon_configuration, 'product').returns('product')
  236. value = footer_js_string(NewRelic::Agent.instance.beacon_configuration, beacon, license_key, application_id)
  237. assert_equal("<script type=\"text/javascript\">if (!NREUMQ.f) { NREUMQ.f=function() {\nNREUMQ.push([\"load\",new Date().getTime()]);\nvar e=document.createElement(\"script\");\ne.type=\"text/javascript\";e.async=true;e.src=\"this_is_my_file\";\ndocument.body.appendChild(e);\nif(NREUMQ.a)NREUMQ.a();\n};\nNREUMQ.a=window.onload;window.onload=NREUMQ.f;\n};\nNREUMQ.push([\"nrfj\",\"\",\"\",1,\"most recent transaction\",0,0,new Date().getTime(),\"ABC\",\"0123456789ABCDEF\",\"user\",\"account\",\"product\"])</script>", value, "should return the javascript given some default values")
  238. end
  239. def test_html_safe_if_needed_unsafed
  240. string = mock('string')
  241. # here to handle 1.9 encoding - we stub this out because it should
  242. # be handled automatically and is outside the scope of this test
  243. string.stubs(:respond_to?).with(:encoding).returns(false)
  244. string.expects(:respond_to?).with(:html_safe).returns(false)
  245. assert_equal(string, html_safe_if_needed(string))
  246. end
  247. def test_html_safe_if_needed_safed
  248. string = mock('string')
  249. string.expects(:respond_to?).with(:html_safe).returns(true)
  250. string.expects(:html_safe).returns(string)
  251. # here to handle 1.9 encoding - we stub this out because it should
  252. # be handled automatically and is outside the scope of this test
  253. string.stubs(:respond_to?).with(:encoding).returns(false)
  254. assert_equal(string, html_safe_if_needed(string))
  255. end
  256. def test_obfuscate_basic
  257. text = 'a happy piece of small text'
  258. key = (1..40).to_a
  259. NewRelic::Agent.instance.beacon_configuration.expects(:license_bytes).returns(key)
  260. output = obfuscate(NewRelic::Agent.instance.beacon_configuration, text)
  261. assert_equal('YCJrZXV2fih5Y25vaCFtZSR2a2ZkZSp/aXV1', output, "should output obfuscated text")
  262. end
  263. def test_obfuscate_long_string
  264. text = 'a happy piece of small text' * 5
  265. key = (1..40).to_a
  266. NewRelic::Agent.instance.beacon_configuration.expects(:license_bytes).returns(key)
  267. output = obfuscate(NewRelic::Agent.instance.beacon_configuration, text)
  268. assert_equal('YCJrZXV2fih5Y25vaCFtZSR2a2ZkZSp/aXV1YyNsZHZ3cSl6YmluZCJsYiV1amllZit4aHl2YiRtZ3d4cCp7ZWhiZyNrYyZ0ZWhmZyx5ZHp3ZSVuZnh5cyt8ZGRhZiRqYCd7ZGtnYC11Z3twZCZvaXl6cix9aGdgYSVpYSh6Z2pgYSF2Znxx', output, "should output obfuscated text")
  269. end
  270. end