newrelic_rpm 3.5.2.17 → 3.5.3.24

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of newrelic_rpm might be problematic. Click here for more details.

Files changed (134) hide show
  1. data/.travis.yml +3 -1
  2. data/CHANGELOG +39 -23
  3. data/GUIDELINES_FOR_CONTRIBUTING.md +23 -2
  4. data/Rakefile +32 -0
  5. data/lib/new_relic/agent.rb +1 -0
  6. data/lib/new_relic/agent/agent.rb +45 -6
  7. data/lib/new_relic/agent/browser_monitoring.rb +36 -20
  8. data/lib/new_relic/agent/busy_calculator.rb +12 -4
  9. data/lib/new_relic/agent/configuration/defaults.rb +6 -1
  10. data/lib/new_relic/agent/configuration/environment_source.rb +14 -0
  11. data/lib/new_relic/agent/instrumentation/sinatra.rb +14 -10
  12. data/lib/new_relic/agent/new_relic_service.rb +192 -34
  13. data/lib/new_relic/agent/pipe_channel_manager.rb +1 -2
  14. data/lib/new_relic/agent/pipe_service.rb +5 -1
  15. data/lib/new_relic/agent/samplers/memory_sampler.rb +1 -1
  16. data/lib/new_relic/agent/sql_sampler.rb +29 -10
  17. data/lib/new_relic/agent/stats_engine/metric_stats.rb +40 -0
  18. data/lib/new_relic/agent/stats_engine/samplers.rb +1 -2
  19. data/lib/new_relic/agent/thread.rb +27 -0
  20. data/lib/new_relic/agent/thread_profiler.rb +295 -0
  21. data/lib/new_relic/agent/worker_loop.rb +29 -15
  22. data/lib/new_relic/control/frameworks/rails.rb +4 -4
  23. data/lib/new_relic/control/frameworks/rails3.rb +1 -1
  24. data/lib/new_relic/helper.rb +3 -0
  25. data/lib/new_relic/metric_data.rb +10 -2
  26. data/lib/new_relic/noticed_error.rb +5 -0
  27. data/lib/new_relic/transaction_sample.rb +23 -13
  28. data/lib/new_relic/transaction_sample/segment.rb +13 -15
  29. data/lib/new_relic/version.rb +1 -1
  30. data/lib/tasks/tests.rake +5 -11
  31. data/test/multiverse/.gitignore +10 -0
  32. data/test/multiverse/README.md +90 -0
  33. data/test/multiverse/Rakefile +17 -0
  34. data/test/multiverse/lib/multiverse/color.rb +13 -0
  35. data/test/multiverse/lib/multiverse/envfile.rb +66 -0
  36. data/test/multiverse/lib/multiverse/environment.rb +16 -0
  37. data/test/multiverse/lib/multiverse/output_collector.rb +29 -0
  38. data/test/multiverse/lib/multiverse/runner.rb +44 -0
  39. data/test/multiverse/lib/multiverse/suite.rb +162 -0
  40. data/test/multiverse/script/run_one +3 -0
  41. data/test/multiverse/script/runner +9 -0
  42. data/test/multiverse/suites/active_record/Envfile +13 -0
  43. data/test/multiverse/suites/active_record/ar_method_aliasing.rb +94 -0
  44. data/test/multiverse/suites/active_record/config/newrelic.yml +22 -0
  45. data/test/multiverse/suites/active_record/encoding_test.rb +26 -0
  46. data/test/multiverse/suites/agent_only/Envfile +3 -0
  47. data/test/multiverse/suites/agent_only/config/newrelic.yml +22 -0
  48. data/test/multiverse/suites/agent_only/http_response_code_test.rb +53 -0
  49. data/test/multiverse/suites/agent_only/marshaling_test.rb +109 -0
  50. data/test/multiverse/suites/agent_only/method_visibility_test.rb +98 -0
  51. data/test/multiverse/suites/agent_only/pipe_manager_test.rb +33 -0
  52. data/test/multiverse/suites/agent_only/service_timeout_test.rb +29 -0
  53. data/test/multiverse/suites/agent_only/test_trace_method_with_punctuation.rb +30 -0
  54. data/test/multiverse/suites/agent_only/test_trace_transaction_with_punctuation.rb +32 -0
  55. data/test/multiverse/suites/agent_only/thread_profiling_test.rb +80 -0
  56. data/test/multiverse/suites/datamapper/Envfile +8 -0
  57. data/test/multiverse/suites/datamapper/config/newrelic.yml +22 -0
  58. data/test/multiverse/suites/datamapper/encoding_test.rb +36 -0
  59. data/test/multiverse/suites/monitor_mode_false/Envfile +2 -0
  60. data/test/multiverse/suites/monitor_mode_false/config/newrelic.yml +25 -0
  61. data/test/multiverse/suites/monitor_mode_false/no_dns_resolv.rb +29 -0
  62. data/test/multiverse/suites/no_load/Envfile +2 -0
  63. data/test/multiverse/suites/no_load/config/newrelic.yml +23 -0
  64. data/test/multiverse/suites/no_load/start_up_test.rb +14 -0
  65. data/test/multiverse/suites/rails_3_error_tracing/Envfile +15 -0
  66. data/test/multiverse/suites/rails_3_error_tracing/config/newrelic.yml +165 -0
  67. data/test/multiverse/suites/rails_3_error_tracing/error_tracing_test.rb +236 -0
  68. data/test/multiverse/suites/rails_3_gc/Envfile +8 -0
  69. data/test/multiverse/suites/rails_3_gc/config/newrelic.yml +167 -0
  70. data/test/multiverse/suites/rails_3_gc/instrumentation_test.rb +92 -0
  71. data/test/multiverse/suites/rails_3_queue_time/Envfile +15 -0
  72. data/test/multiverse/suites/rails_3_queue_time/config/newrelic.yml +165 -0
  73. data/test/multiverse/suites/rails_3_queue_time/queue_time_test.rb +75 -0
  74. data/test/multiverse/suites/rails_3_views/.gitignore +3 -0
  75. data/test/multiverse/suites/rails_3_views/Envfile +16 -0
  76. data/test/multiverse/suites/rails_3_views/app/views/foos/_foo.html.haml +1 -0
  77. data/test/multiverse/suites/rails_3_views/app/views/test/_a_partial.html.erb +1 -0
  78. data/test/multiverse/suites/rails_3_views/app/views/test/_mid_partial.html.erb +1 -0
  79. data/test/multiverse/suites/rails_3_views/app/views/test/_top_partial.html.erb +3 -0
  80. data/test/multiverse/suites/rails_3_views/app/views/test/deep_partial.html.erb +3 -0
  81. data/test/multiverse/suites/rails_3_views/app/views/test/haml_view.html.haml +6 -0
  82. data/test/multiverse/suites/rails_3_views/app/views/test/index.html.erb +4 -0
  83. data/test/multiverse/suites/rails_3_views/config/newrelic.yml +164 -0
  84. data/test/multiverse/suites/rails_3_views/view_instrumentation_test.rb +245 -0
  85. data/test/multiverse/suites/resque/Envfile +21 -0
  86. data/test/multiverse/suites/resque/config/newrelic.yml +22 -0
  87. data/test/multiverse/suites/resque/dump.rdb +0 -0
  88. data/test/multiverse/suites/resque/instrumentation_test.rb +73 -0
  89. data/test/multiverse/suites/rum_auto_instrumentation/Envfile +4 -0
  90. data/test/multiverse/suites/rum_auto_instrumentation/config/newrelic.yml +24 -0
  91. data/test/multiverse/suites/rum_auto_instrumentation/problem_response.html +422 -0
  92. data/test/multiverse/suites/rum_auto_instrumentation/responses/worst_case_small.html +5000 -0
  93. data/test/multiverse/suites/rum_auto_instrumentation/sanity_test.rb +115 -0
  94. data/test/multiverse/suites/sinatra/Envfile +13 -0
  95. data/test/multiverse/suites/sinatra/config/newrelic.yml +24 -0
  96. data/test/multiverse/suites/sinatra/sinatra_metric_explosion_test.rb +76 -0
  97. data/test/multiverse/suites/sinatra/sinatra_routes_test.rb +46 -0
  98. data/test/multiverse/test/multiverse_test.rb +55 -0
  99. data/test/multiverse/test/suite_examples/one/a/Envfile +3 -0
  100. data/test/multiverse/test/suite_examples/one/a/a_test.rb +11 -0
  101. data/test/multiverse/test/suite_examples/one/a/config/newrelic.yml +24 -0
  102. data/test/multiverse/test/suite_examples/one/b/Envfile +3 -0
  103. data/test/multiverse/test/suite_examples/one/b/b_test.rb +11 -0
  104. data/test/multiverse/test/suite_examples/one/b/config/newrelic.yml +24 -0
  105. data/test/multiverse/test/suite_examples/three/a/Envfile +2 -0
  106. data/test/multiverse/test/suite_examples/three/a/fail_test.rb +6 -0
  107. data/test/multiverse/test/suite_examples/three/b/Envfile +2 -0
  108. data/test/multiverse/test/suite_examples/three/b/win_test.rb +6 -0
  109. data/test/multiverse/test/suite_examples/two/a/Envfile +1 -0
  110. data/test/multiverse/test/suite_examples/two/a/fail_test.rb +6 -0
  111. data/test/new_relic/agent/agent_test.rb +54 -2
  112. data/test/new_relic/agent/agent_test_controller.rb +1 -1
  113. data/test/new_relic/agent/agent_test_controller_test.rb +35 -5
  114. data/test/new_relic/agent/browser_monitoring_test.rb +8 -8
  115. data/test/new_relic/agent/configuration/environment_source_test.rb +16 -0
  116. data/test/new_relic/agent/method_tracer_test.rb +6 -6
  117. data/test/new_relic/agent/new_relic_service_test.rb +137 -20
  118. data/test/new_relic/agent/sql_sampler_test.rb +26 -0
  119. data/test/new_relic/agent/stats_engine/metric_stats_test.rb +1 -1
  120. data/test/new_relic/agent/stats_engine_test.rb +1 -0
  121. data/test/new_relic/agent/thread_profiler_test.rb +536 -0
  122. data/test/new_relic/agent/thread_test.rb +76 -0
  123. data/test/new_relic/agent/threaded_test.rb +65 -0
  124. data/test/new_relic/agent/transaction_sampler_test.rb +16 -13
  125. data/test/new_relic/agent/worker_loop_test.rb +20 -0
  126. data/test/new_relic/fake_collector.rb +103 -31
  127. data/test/new_relic/fake_service.rb +7 -1
  128. data/test/new_relic/metric_data_test.rb +45 -16
  129. data/test/new_relic/noticed_error_test.rb +14 -0
  130. data/test/new_relic/transaction_sample/segment_test.rb +23 -4
  131. data/test/new_relic/transaction_sample_test.rb +39 -0
  132. data/ui/views/layouts/newrelic_default.rhtml +1 -0
  133. data/ui/views/newrelic/threads.rhtml +2 -10
  134. metadata +88 -2
@@ -0,0 +1,6 @@
1
+ require 'test/unit'
2
+ class ATest < Test::Unit::TestCase
3
+ def test_failure
4
+ fail "This test is failing!!!"
5
+ end
6
+ end
@@ -1,4 +1,6 @@
1
1
  require File.expand_path(File.join(File.dirname(__FILE__),'..','..','test_helper'))
2
+ require 'new_relic/agent/thread_profiler'
3
+
2
4
  module NewRelic
3
5
  module Agent
4
6
  class AgentTest < Test::Unit::TestCase
@@ -53,6 +55,47 @@ module NewRelic
53
55
  end
54
56
  end
55
57
 
58
+ def test_graceful_shutdown_ends_thread_profiling
59
+ @agent.thread_profiler.expects(:stop).once
60
+ @agent.instance_variable_set(:@connected, true)
61
+
62
+ @agent.send(:graceful_disconnect)
63
+ end
64
+
65
+ def test_harvest_and_send_thread_profile
66
+ profile = with_profile(:finished => true)
67
+ @agent.send(:harvest_and_send_thread_profile, false)
68
+
69
+ assert_equal([profile],
70
+ @agent.service.agent_data \
71
+ .find{|data| data.action == :profile_data}.params)
72
+ end
73
+
74
+ def test_harvest_and_send_thread_profile_when_not_finished
75
+ with_profile(:finished => false)
76
+ @agent.send(:harvest_and_send_thread_profile, false)
77
+
78
+ assert_nil @agent.service.agent_data.find{|data| data.action == :profile_data}
79
+ end
80
+
81
+ def test_harvest_and_send_thread_profile_when_not_finished_but_disconnecting
82
+ profile = with_profile(:finished => false)
83
+ @agent.send(:harvest_and_send_thread_profile, true)
84
+
85
+ assert_equal([profile],
86
+ @agent.service.agent_data \
87
+ .find{|data| data.action == :profile_data}.params)
88
+ end
89
+
90
+ def with_profile(opts)
91
+ profile = NewRelic::Agent::ThreadProfile.new(-1, 0, 0, true)
92
+ profile.aggregate(["chunky.rb:42:in `bacon'"], profile.traces[:other])
93
+ profile.instance_variable_set(:@finished, opts[:finished])
94
+
95
+ @agent.thread_profiler.instance_variable_set(:@profile, profile)
96
+ profile
97
+ end
98
+
56
99
  def test_harvest_timeslice_data
57
100
  assert_equal({}, @agent.send(:harvest_timeslice_data),
58
101
  'should return timeslice data')
@@ -63,11 +106,11 @@ module NewRelic
63
106
  @agent.stats_engine.stats_hash[i.to_s] = NewRelic::StatsBase.new
64
107
  end
65
108
 
66
- harvest = Thread.new do
109
+ harvest = Thread.new("Harvesting Test run timeslices") do
67
110
  @agent.send(:harvest_timeslice_data)
68
111
  end
69
112
 
70
- app = Thread.new do
113
+ app = Thread.new("Harvesting Test Modify stats_hash") do
71
114
  200.times do |i|
72
115
  @agent.stats_engine.stats_hash["a#{i}"] = NewRelic::StatsBase.new
73
116
  end
@@ -82,6 +125,15 @@ module NewRelic
82
125
  assert_equal([], @agent.send(:harvest_errors), 'should return errors')
83
126
  end
84
127
 
128
+ def test_check_for_agent_commands
129
+ @agent.send :check_for_agent_commands
130
+
131
+ expected = RUBY_VERSION >= "1.9.2" ? 1 : 0
132
+ assert_equal(expected,
133
+ @agent.service.agent_data \
134
+ .select {|data| data.action == :get_agent_commands }.size)
135
+ end
136
+
85
137
  def test_merge_data_from_empty
86
138
  unsent_timeslice_data = mock('unsent timeslice data')
87
139
  unsent_errors = mock('unsent errors')
@@ -12,7 +12,7 @@ class NewRelic::Agent::AgentTestController < NewRelic::Agent::SuperclassControll
12
12
  @@headers_to_add = nil
13
13
 
14
14
  def index
15
- sleep params['wait'].to_i if params['wait']
15
+ sleep params['wait'].to_f if params['wait']
16
16
  render :text => params.inspect
17
17
  end
18
18
  def _filter_parameters(params)
@@ -289,19 +289,49 @@ class NewRelic::Agent::AgentTestControllerTest < ActionController::TestCase
289
289
  end
290
290
 
291
291
 
292
- def test_busycalculation
292
+ def test_busy_calculation_correctly_calculates_based_acccumlator
293
+
294
+ # woah it's 1970
295
+ now = Time.at 0
296
+
297
+ # We'll record two seconds of transactions
298
+ later = Time.at(now + 2)
299
+ NewRelic::Agent::BusyCalculator.stubs(:time_now).
300
+ returns(now).then.returns(later)
301
+
302
+ # reset harvest time to epoch (based on stub)
303
+ NewRelic::Agent::BusyCalculator.reset
304
+
305
+ # We record 1 second of busy time in our two seconds of wall clock
306
+ NewRelic::Agent::BusyCalculator.instance_variable_set(:@accumulator, 1.0)
307
+
308
+
309
+ NewRelic::Agent::BusyCalculator.harvest_busy
310
+
311
+ # smooth out floating point math
312
+ stat_int = (stats('Instance/Busy').total_call_time * 10).to_i
313
+
314
+ # Despite your expectations, #total_call_time is a percentage here.
315
+ assert_equal(stat_int, 5,
316
+ "#{stats('Instance/Busy').total_call_time} != 0.5")
317
+ end
318
+
319
+ def test_busy_calculation_generates_a_positive_value
293
320
  engine.clear_stats
294
- assert_equal 0, NewRelic::Agent::BusyCalculator.busy_count
295
321
  get :index, 'social_security_number' => "001-555-1212", 'wait' => '0.05'
296
322
  NewRelic::Agent::BusyCalculator.harvest_busy
297
323
 
298
324
  assert_equal 1, stats('Instance/Busy').call_count
299
325
  assert_equal 1, stats('HttpDispatcher').call_count
300
- # We are probably busy about 99% of the time, but lets make sure it's at least 50
301
- assert stats('Instance/Busy').total_call_time > (0.5 * 0.05), stats('Instance/Busy').inspect
326
+
327
+ # Timing is too non-deterministic, so we just assert a positive, non-zero
328
+ # value here. See
329
+ # #test_busy_calculation_correctly_calculates_based_acccumlator for
330
+ # assertions that the formula is correct.
331
+ assert(stats('Instance/Busy').total_call_time > 0,
332
+ "#{stats('Instance/Busy').total_call_time} !> 0")
302
333
  assert_equal 0, stats('WebFrontend/Mongrel/Average Queue Time').call_count
303
334
  end
304
-
305
335
  def test_queue_headers_no_header
306
336
  engine.clear_stats
307
337
  queue_length_stat = stats('Mongrel/Queue Length')
@@ -60,7 +60,7 @@ class NewRelic::Agent::BrowserMonitoringTest < Test::Unit::TestCase
60
60
  end
61
61
 
62
62
  def test_browser_timing_header_with_no_beacon_configuration
63
- NewRelic::Agent.instance.expects(:beacon_configuration).returns( nil)
63
+ NewRelic::Agent.instance.stubs(:beacon_configuration).returns( nil)
64
64
  header = browser_timing_header
65
65
  assert_equal "", header
66
66
  end
@@ -71,14 +71,14 @@ class NewRelic::Agent::BrowserMonitoringTest < Test::Unit::TestCase
71
71
  end
72
72
 
73
73
  def test_browser_timing_header_with_rum_enabled_not_specified
74
- NewRelic::Agent.instance.expects(:beacon_configuration).at_least_once.returns( NewRelic::Agent::BeaconConfiguration.new)
74
+ NewRelic::Agent.instance.stubs(:beacon_configuration).returns( NewRelic::Agent::BeaconConfiguration.new)
75
75
  header = browser_timing_header
76
76
  assert_equal "<script type=\"text/javascript\">var NREUMQ=NREUMQ||[];NREUMQ.push([\"mark\",\"firstbyte\",new Date().getTime()]);</script>", header
77
77
  end
78
78
 
79
79
  def test_browser_timing_header_with_rum_enabled_false
80
80
  with_config(:'rum.enabled' => false) do
81
- NewRelic::Agent.instance.expects(:beacon_configuration).twice.returns( NewRelic::Agent::BeaconConfiguration.new)
81
+ NewRelic::Agent.instance.stubs(:beacon_configuration).returns( NewRelic::Agent::BeaconConfiguration.new)
82
82
  header = browser_timing_header
83
83
  assert_equal "", header
84
84
  end
@@ -115,7 +115,7 @@ var e=document.createElement("script");'
115
115
  def test_browser_timing_footer_with_no_browser_key_rum_enabled
116
116
  with_config(:browser_key => '') do
117
117
  browser_timing_header
118
- NewRelic::Agent.instance.expects(:beacon_configuration).returns(NewRelic::Agent::BeaconConfiguration.new)
118
+ NewRelic::Agent.instance.stubs(:beacon_configuration).returns(NewRelic::Agent::BeaconConfiguration.new)
119
119
  footer = browser_timing_footer
120
120
  assert_equal "", footer
121
121
  end
@@ -124,7 +124,7 @@ var e=document.createElement("script");'
124
124
  def test_browser_timing_footer_with_no_browser_key_rum_disabled
125
125
  with_config(:'rum.enabled' => false) do
126
126
  browser_timing_header
127
- NewRelic::Agent.instance.expects(:beacon_configuration) \
127
+ NewRelic::Agent.instance.stubs(:beacon_configuration) \
128
128
  .returns(NewRelic::Agent::BeaconConfiguration.new)
129
129
  footer = browser_timing_footer
130
130
  assert_equal "", footer
@@ -138,7 +138,7 @@ var e=document.createElement("script");'
138
138
  ("a" * 13).each_byte {|byte| license_bytes << byte}
139
139
  config = NewRelic::Agent::BeaconConfiguration.new
140
140
  config.expects(:license_bytes).returns(license_bytes).at_least_once
141
- NewRelic::Agent.instance.expects(:beacon_configuration).returns(config).at_least_once
141
+ NewRelic::Agent.instance.stubs(:beacon_configuration).returns(config).at_least_once
142
142
  footer = browser_timing_footer
143
143
  beginning_snippet = '<script type="text/javascript">if (!NREUMQ.f) { NREUMQ.f=function() {
144
144
  NREUMQ.push(["load",new Date().getTime()]);
@@ -152,7 +152,7 @@ var e=document.createElement("script");'
152
152
 
153
153
  def test_browser_timing_footer_with_no_beacon_configuration
154
154
  browser_timing_header
155
- NewRelic::Agent.instance.expects(:beacon_configuration).returns( nil)
155
+ NewRelic::Agent.instance.stubs(:beacon_configuration).returns( nil)
156
156
  footer = browser_timing_footer
157
157
  assert_equal "", footer
158
158
  end
@@ -178,7 +178,7 @@ var e=document.createElement("script");'
178
178
  def test_browser_timing_footer_browser_key_missing
179
179
  with_config(:browser_key => '') do
180
180
  fake_config = mock('beacon configuration')
181
- NewRelic::Agent.instance.expects(:beacon_configuration).returns(fake_config)
181
+ NewRelic::Agent.instance.stubs(:beacon_configuration).returns(fake_config)
182
182
  fake_config.expects(:nil?).returns(false)
183
183
  fake_config.expects(:enabled?).returns(true)
184
184
  self.expects(:generate_footer_js).never
@@ -49,6 +49,22 @@ module NewRelic::Agent::Configuration
49
49
  assert_equal 'STDOUT', source[:log_file_path]
50
50
  end
51
51
 
52
+ def test_thread_profiler_is_supported
53
+ source = EnvironmentSource.new
54
+
55
+ assert_equal(
56
+ NewRelic::Agent::ThreadProfiler.is_supported?,
57
+ source[:'thread_profiler.is_supported'])
58
+ end
59
+
60
+ def test_thread_profiler_enabled_depending_on_support
61
+ source = EnvironmentSource.new
62
+
63
+ expected = false unless NewRelic::Agent::ThreadProfiler.is_supported?
64
+
65
+ assert_equal expected, source[:'thread_profiler.enabled']
66
+ end
67
+
52
68
  def assert_applied_string(env_var, config_var)
53
69
  ENV[env_var] = 'test value'
54
70
  assert_equal 'test value', EnvironmentSource.new[config_var.to_sym]
@@ -324,14 +324,14 @@ class NewRelic::Agent::MethodTracerTest < Test::Unit::TestCase
324
324
  end
325
325
 
326
326
  def test_add_multiple_tracers
327
- self.class.add_method_tracer :method_to_be_traced, 'X', :push_scope => false
327
+ self.class.add_method_tracer :method_to_be_traced, 'XX', :push_scope => false
328
328
  method_to_be_traced 1,2,3,true,nil
329
- self.class.add_method_tracer :method_to_be_traced, 'Y'
330
- method_to_be_traced 1,2,3,true,'Y'
331
- self.class.remove_method_tracer :method_to_be_traced, 'Y'
329
+ self.class.add_method_tracer :method_to_be_traced, 'YY'
330
+ method_to_be_traced 1,2,3,true,'YY'
331
+ self.class.remove_method_tracer :method_to_be_traced, 'YY'
332
332
  method_to_be_traced 1,2,3,true,nil
333
- self.class.remove_method_tracer :method_to_be_traced, 'X'
334
- method_to_be_traced 1,2,3,false,'X'
333
+ self.class.remove_method_tracer :method_to_be_traced, 'XX'
334
+ method_to_be_traced 1,2,3,false,'XX'
335
335
  end
336
336
 
337
337
  def trace_no_push_scope
@@ -1,8 +1,10 @@
1
1
  require File.expand_path(File.join(File.dirname(__FILE__), '..', '..', 'test_helper'))
2
+ require 'new_relic/agent/thread_profiler'
2
3
 
3
4
  class NewRelicServiceTest < Test::Unit::TestCase
4
5
  def initialize(*_)
5
6
  [ :HTTPSuccess,
7
+ :HTTPUnauthorized,
6
8
  :HTTPNotFound,
7
9
  :HTTPRequestEntityTooLarge,
8
10
  :HTTPUnsupportedMediaType ].each do |class_name|
@@ -26,6 +28,7 @@ class NewRelicServiceTest < Test::Unit::TestCase
26
28
  @service = NewRelic::Agent::NewRelicService.new('license-key', @server)
27
29
  @http_handle = HTTPHandle.new
28
30
  NewRelic::Control.instance.stubs(:http_connection).returns(@http_handle)
31
+
29
32
  @http_handle.respond_to(:get_redirect_host, 'localhost')
30
33
  connect_response = {
31
34
  'config' => 'some config directives',
@@ -62,7 +65,7 @@ class NewRelicServiceTest < Test::Unit::TestCase
62
65
  def test_connect_uses_proxy_collector_if_no_redirect_host
63
66
  @http_handle.reset
64
67
  @http_handle.respond_to(:get_redirect_host, nil)
65
- @http_handle.respond_to(:connect, {'agent_run_id' => 1})
68
+ @http_handle.respond_to(:connect, 'agent_run_id' => 1)
66
69
 
67
70
  @service.connect
68
71
  assert_equal 'somewhere.example.com', @service.collector.name
@@ -71,15 +74,14 @@ class NewRelicServiceTest < Test::Unit::TestCase
71
74
  def test_connect_sets_agent_id
72
75
  @http_handle.reset
73
76
  @http_handle.respond_to(:get_redirect_host, 'localhost')
74
- @http_handle.respond_to(:connect, {'agent_run_id' => 666})
77
+ @http_handle.respond_to(:connect, 'agent_run_id' => 666)
75
78
 
76
79
  @service.connect
77
80
  assert_equal 666, @service.agent_id
78
81
  end
79
82
 
80
83
  def test_get_redirect_host
81
- host = @service.get_redirect_host
82
- assert_equal 'localhost', host
84
+ assert_equal 'localhost', @service.get_redirect_host
83
85
  end
84
86
 
85
87
  def test_shutdown
@@ -97,7 +99,7 @@ class NewRelicServiceTest < Test::Unit::TestCase
97
99
 
98
100
  def test_metric_data
99
101
  @http_handle.respond_to(:metric_data, 'met rick date uhhh')
100
- response = @service.metric_data(Time.now - 60, Time.now, {})
102
+ response = @service.metric_data((Time.now - 60).to_f, Time.now.to_f, {})
101
103
  assert_equal 'met rick date uhhh', response
102
104
  end
103
105
 
@@ -119,6 +121,44 @@ class NewRelicServiceTest < Test::Unit::TestCase
119
121
  assert_equal 'explain this', response
120
122
  end
121
123
 
124
+
125
+ # Thread profiling only available in 1.9.2 and above
126
+ if RUBY_VERSION >= '1.9.2'
127
+ def test_profile_data
128
+ @http_handle.respond_to(:profile_data, 'profile' => 123)
129
+ response = @service.profile_data(NewRelic::Agent::ThreadProfile.new(0, 0, 0, true))
130
+ assert_equal({ "profile" => 123 }, response)
131
+ end
132
+
133
+ def test_get_agent_commands
134
+ @service.agent_id = 666
135
+ @http_handle.respond_to(:get_agent_commands, [1,2,3])
136
+
137
+ response = @service.get_agent_commands
138
+ assert_equal [1,2,3], response
139
+ end
140
+
141
+ def test_get_agent_commands_with_no_response
142
+ @service.agent_id = 666
143
+ @http_handle.respond_to(:get_agent_commands, nil)
144
+
145
+ response = @service.get_agent_commands
146
+ assert_equal nil, response
147
+ end
148
+
149
+ def test_agent_command_results
150
+ @http_handle.respond_to(:agent_command_results, {})
151
+ response = @service.agent_command_results(4200)
152
+ assert_equal({}, response)
153
+ end
154
+
155
+ def test_agent_command_results_with_errors
156
+ @http_handle.respond_to(:agent_command_results, [123])
157
+ response = @service.agent_command_results(4200, 'Boo!')
158
+ assert_equal [123], response
159
+ end
160
+ end
161
+
122
162
  def test_request_timeout
123
163
  with_config(:timeout => 600) do
124
164
  service = NewRelic::Agent::NewRelicService.new('abcdef', @server)
@@ -136,32 +176,89 @@ class NewRelicServiceTest < Test::Unit::TestCase
136
176
  @service.expects(:get_redirect_host).once
137
177
 
138
178
  @service.connect
139
- @http_handle.respond_to(:metric_data, '0')
140
- @service.metric_data(Time.now - 60, Time.now, {})
179
+ @http_handle.respond_to(:metric_data, 0)
180
+ @service.metric_data((Time.now - 60).to_f, Time.now.to_f, {})
141
181
 
142
- @http_handle.respond_to(:transaction_sample_data, '1')
182
+ @http_handle.respond_to(:transaction_sample_data, 1)
143
183
  @service.transaction_sample_data([])
144
184
 
145
- @http_handle.respond_to(:sql_trace_data, '2')
185
+ @http_handle.respond_to(:sql_trace_data, 2)
146
186
  @service.sql_trace_data([])
147
187
  end
148
188
 
189
+ # for PRUBY proxy compatibility
190
+ def test_should_raise_exception_on_401
191
+ @http_handle.reset
192
+ @http_handle.respond_to(:get_redirect_host, 'bad license', :code => 401)
193
+ assert_raise NewRelic::Agent::LicenseException do
194
+ @service.get_redirect_host
195
+ end
196
+ end
197
+
149
198
  # protocol 9
150
199
  def test_should_raise_exception_on_413
151
- @http_handle.respond_to(:metric_data, 'too big', 413)
200
+ @http_handle.respond_to(:metric_data, 'too big', :code => 413)
152
201
  assert_raise NewRelic::Agent::UnrecoverableServerException do
153
- @service.metric_data(Time.now - 60, Time.now, {})
202
+ @service.metric_data((Time.now - 60).to_f, Time.now.to_f, {})
154
203
  end
155
204
  end
156
205
 
157
206
  # protocol 9
158
207
  def test_should_raise_exception_on_415
159
- @http_handle.respond_to(:metric_data, 'too big', 415)
208
+ @http_handle.respond_to(:metric_data, 'too big', :code => 415)
160
209
  assert_raise NewRelic::Agent::UnrecoverableServerException do
161
- @service.metric_data(Time.now - 60, Time.now, {})
210
+ @service.metric_data((Time.now - 60).to_f, Time.now.to_f, {})
162
211
  end
163
212
  end
164
213
 
214
+ if NewRelic::LanguageSupport.using_version?('1.9')
215
+ def test_json_marshaller_handles_responses_from_collector
216
+ marshaller = NewRelic::Agent::NewRelicService::JsonMarshaller.new
217
+ assert_equal ['beep', 'boop'], marshaller.load('{"return_value": ["beep","boop"]}')
218
+ end
219
+
220
+ def test_json_marshaller_handles_errors_from_collector
221
+ marshaller = NewRelic::Agent::NewRelicService::JsonMarshaller.new
222
+ assert_raise(NewRelic::Agent::NewRelicService::CollectorError,
223
+ 'JavaCrash: error message') do
224
+ marshaller.load('{"exception": {"message": "error message", "error_type": "JavaCrash"}}')
225
+ end
226
+ end
227
+ end
228
+
229
+ def test_pruby_marshaller_handles_errors_from_collector
230
+ marshaller = NewRelic::Agent::NewRelicService::PrubyMarshaller.new
231
+ assert_raise(NewRelic::Agent::NewRelicService::CollectorError, 'error message') do
232
+ marshaller.load(Marshal.dump({"exception" => {"message" => "error message",
233
+ "error_type" => "JavaCrash"}}))
234
+ end
235
+ end
236
+
237
+ def test_pruby_marshaller_compresses_large_payloads
238
+ marshaller = NewRelic::Agent::NewRelicService::PrubyMarshaller.new
239
+ large_payload = 'a' * 64 * 1024
240
+ result = marshaller.dump(large_payload)
241
+ assert_equal 'deflate', marshaller.encoding
242
+ assert_equal large_payload, Marshal.load(Zlib::Inflate.inflate(result))
243
+ end
244
+
245
+ def test_marshaller_handles_known_errors
246
+ error_data = {
247
+ 'error_type' => 'NewRelic::Agent::ForceRestartException',
248
+ 'message' => 'test'
249
+ }
250
+ error = @service.marshaller.parsed_error(error_data)
251
+ assert_equal NewRelic::Agent::ForceRestartException, error.class
252
+ assert_equal 'test', error.message
253
+ end
254
+
255
+ def test_marshaller_handles_unknown_errors
256
+ error = @service.marshaller.parsed_error('error_type' => 'OogBooga',
257
+ 'message' => 'test')
258
+ assert_equal NewRelic::Agent::NewRelicService::CollectorError, error.class
259
+ assert_equal 'OogBooga: test', error.message
260
+ end
261
+
165
262
  class HTTPHandle
166
263
  attr_accessor :read_timeout, :route_table
167
264
 
@@ -169,18 +266,38 @@ class NewRelicServiceTest < Test::Unit::TestCase
169
266
  reset
170
267
  end
171
268
 
172
- def respond_to(method, payload, code=200)
173
- klass = HTTPSuccess
174
- if code == 413
269
+ def respond_to(method, payload, opts={})
270
+ if NewRelic::Agent::NewRelicService::JsonMarshaller.is_supported?
271
+ format = :json
272
+ else
273
+ format = :pruby
274
+ end
275
+
276
+ opts = {
277
+ :code => 200,
278
+ :format => format
279
+ }.merge(opts)
280
+
281
+ if opts[:code] == 401
282
+ klass = HTTPUnauthorized
283
+ elsif opts[:code] == 413
175
284
  klass = HTTPRequestEntityTooLarge
176
- elsif code == 415
285
+ elsif opts[:code] == 415
177
286
  klass = HTTPUnsupportedMediaType
178
- elsif code >= 400
287
+ elsif opts[:code] >= 400
179
288
  klass = HTTPServerError
289
+ else
290
+ klass = HTTPSuccess
180
291
  end
181
292
 
182
- register(klass.new(Marshal.dump(payload), code)) do |request|
183
- request.path.include?(method.to_s)
293
+ if opts[:format] == :json
294
+ register(klass.new(JSON.dump('return_value' => payload), opts[:code])) do |request|
295
+ request.path.include?(method.to_s)
296
+ end
297
+ else
298
+ register(klass.new(Marshal.dump('return_value' => payload), opts[:code])) do |request|
299
+ request.path.include?(method.to_s)
300
+ end
184
301
  end
185
302
  end
186
303