wd_newrelic_rpm 3.5.5 → 3.5.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (146) hide show
  1. data/.gitignore +2 -0
  2. data/CHANGELOG +60 -0
  3. data/Rakefile +14 -18
  4. data/gem-public_cert.pem +20 -0
  5. data/lib/new_relic/agent.rb +3 -0
  6. data/lib/new_relic/agent/agent.rb +86 -97
  7. data/lib/new_relic/agent/agent_logger.rb +9 -1
  8. data/lib/new_relic/agent/busy_calculator.rb +5 -0
  9. data/lib/new_relic/agent/configuration/defaults.rb +3 -3
  10. data/lib/new_relic/agent/configuration/manager.rb +12 -0
  11. data/lib/new_relic/agent/configuration/mask_defaults.rb +1 -0
  12. data/lib/new_relic/agent/configuration/yaml_source.rb +5 -1
  13. data/lib/new_relic/agent/cross_process_monitoring.rb +164 -20
  14. data/lib/new_relic/agent/error_collector.rb +13 -2
  15. data/lib/new_relic/agent/event_listener.rb +39 -0
  16. data/lib/new_relic/agent/instrumentation/browser_monitoring_timings.rb +18 -8
  17. data/lib/new_relic/agent/instrumentation/rails3/action_controller.rb +1 -1
  18. data/lib/new_relic/agent/instrumentation/sinatra.rb +8 -1
  19. data/lib/new_relic/agent/new_relic_service.rb +90 -10
  20. data/lib/new_relic/agent/pipe_service.rb +9 -0
  21. data/lib/new_relic/agent/sql_sampler.rb +10 -3
  22. data/lib/new_relic/agent/stats_engine/transactions.rb +1 -0
  23. data/lib/new_relic/agent/thread_profiler.rb +20 -7
  24. data/lib/new_relic/agent/worker_loop.rb +2 -1
  25. data/lib/new_relic/coerce.rb +37 -0
  26. data/lib/new_relic/commands/deployments.rb +1 -1
  27. data/lib/new_relic/control/frameworks/rails.rb +29 -5
  28. data/lib/new_relic/control/frameworks/rails3.rb +2 -11
  29. data/lib/new_relic/control/instance_methods.rb +11 -7
  30. data/lib/new_relic/control/server_methods.rb +5 -37
  31. data/lib/new_relic/latest_changes.rb +31 -0
  32. data/lib/new_relic/local_environment.rb +1 -1
  33. data/lib/new_relic/metric_data.rb +13 -2
  34. data/lib/new_relic/noticed_error.rb +8 -1
  35. data/lib/new_relic/rack/agent_hooks.rb +20 -0
  36. data/lib/new_relic/rack/error_collector.rb +11 -1
  37. data/lib/new_relic/recipes.rb +32 -10
  38. data/lib/new_relic/transaction_sample.rb +12 -3
  39. data/lib/new_relic/transaction_sample/segment.rb +6 -3
  40. data/lib/new_relic/version.rb +10 -15
  41. data/newrelic.yml +12 -19
  42. data/newrelic_rpm.gemspec +22 -464
  43. data/test/multiverse/.gitignore +1 -0
  44. data/test/multiverse/lib/multiverse/environment.rb +1 -1
  45. data/test/multiverse/lib/multiverse/suite.rb +2 -0
  46. data/test/multiverse/suites/active_record/Envfile +3 -3
  47. data/test/multiverse/suites/active_record/ar_method_aliasing.rb +1 -1
  48. data/test/multiverse/suites/active_record/config/newrelic.yml +2 -2
  49. data/test/multiverse/suites/agent_only/Envfile +2 -1
  50. data/test/multiverse/suites/agent_only/config/newrelic.yml +3 -1
  51. data/test/multiverse/suites/agent_only/cross_process_test.rb +56 -0
  52. data/test/multiverse/suites/{logging → agent_only}/logging_test.rb +42 -22
  53. data/test/multiverse/suites/agent_only/no_dns_resolv.rb +17 -0
  54. data/test/multiverse/suites/{rum_auto_instrumentation/sanity_test.rb → agent_only/rum_instrumentation_test.rb} +25 -46
  55. data/test/multiverse/suites/agent_only/service_timeout_test.rb +6 -3
  56. data/test/multiverse/suites/agent_only/ssl_test.rb +22 -0
  57. data/test/multiverse/suites/{no_load → agent_only}/start_up_test.rb +9 -2
  58. data/test/multiverse/suites/agent_only/testing_app.rb +17 -0
  59. data/test/multiverse/suites/agent_only/thread_profiling_test.rb +6 -5
  60. data/test/multiverse/suites/datamapper/config/newrelic.yml +1 -1
  61. data/test/multiverse/suites/{rails_3_queue_time → rails}/Envfile +3 -0
  62. data/test/multiverse/suites/rails/app.rb +49 -0
  63. data/test/multiverse/suites/{rails_3_views → rails}/app/views/foos/_foo.html.haml +0 -0
  64. data/test/multiverse/suites/{rails_3_views/app/views/test → rails/app/views/views}/_a_partial.html.erb +0 -0
  65. data/test/multiverse/suites/{rails_3_views/app/views/test → rails/app/views/views}/_mid_partial.html.erb +0 -0
  66. data/test/multiverse/suites/{rails_3_views/app/views/test → rails/app/views/views}/_top_partial.html.erb +0 -0
  67. data/test/multiverse/suites/{rails_3_views/app/views/test → rails/app/views/views}/deep_partial.html.erb +0 -0
  68. data/test/multiverse/suites/{rails_3_views/app/views/test → rails/app/views/views}/haml_view.html.haml +0 -0
  69. data/test/multiverse/suites/{rails_3_views/app/views/test → rails/app/views/views}/index.html.erb +0 -0
  70. data/test/multiverse/suites/rails/config/newrelic.yml +32 -0
  71. data/test/multiverse/suites/{rails_3_error_tracing → rails}/error_tracing_test.rb +51 -88
  72. data/test/multiverse/suites/rails/gc_instrumentation_test.rb +79 -0
  73. data/test/multiverse/suites/{rails_3_queue_time → rails}/queue_time_test.rb +3 -23
  74. data/test/multiverse/suites/{rails_3_views → rails}/view_instrumentation_test.rb +21 -61
  75. data/test/multiverse/suites/resque/Envfile +7 -4
  76. data/test/multiverse/suites/resque/Rakefile +8 -0
  77. data/test/multiverse/suites/resque/config/newrelic.yml +1 -1
  78. data/test/multiverse/suites/resque/instrumentation_test.rb +118 -41
  79. data/test/multiverse/suites/resque/resque_setup.rb +15 -0
  80. data/test/multiverse/suites/sinatra/config/newrelic.yml +1 -2
  81. data/test/multiverse/suites/sinatra/sinatra_error_tracing_test.rb +38 -0
  82. data/test/multiverse/suites/sinatra/sinatra_test.rb +17 -0
  83. data/test/multiverse/test/suite_examples/one/a/config/newrelic.yml +1 -1
  84. data/test/multiverse/test/suite_examples/one/b/config/newrelic.yml +1 -1
  85. data/test/new_relic/agent/agent/connect_test.rb +24 -100
  86. data/test/new_relic/agent/agent/start_worker_thread_test.rb +3 -3
  87. data/test/new_relic/agent/agent_test.rb +126 -31
  88. data/test/new_relic/agent/browser_monitoring_test.rb +1 -1
  89. data/test/new_relic/agent/busy_calculator_test.rb +8 -0
  90. data/test/new_relic/agent/configuration/manager_test.rb +28 -0
  91. data/test/new_relic/agent/configuration/yaml_source_test.rb +12 -2
  92. data/test/new_relic/agent/cross_process_monitoring_test.rb +144 -31
  93. data/test/new_relic/agent/error_collector_test.rb +16 -0
  94. data/test/new_relic/agent/event_listener_test.rb +46 -0
  95. data/test/new_relic/agent/instrumentation/browser_monitoring_timings_test.rb +57 -30
  96. data/test/new_relic/agent/instrumentation/task_instrumentation_test.rb +1 -0
  97. data/test/new_relic/agent/new_relic_service_test.rb +95 -2
  98. data/test/new_relic/agent/pipe_channel_manager_test.rb +3 -3
  99. data/test/new_relic/agent/pipe_service_test.rb +21 -1
  100. data/test/new_relic/agent/rpm_agent_test.rb +1 -1
  101. data/test/new_relic/agent/sql_sampler_test.rb +20 -0
  102. data/test/new_relic/agent/thread_profiler_test.rb +53 -8
  103. data/test/new_relic/agent/worker_loop_test.rb +19 -16
  104. data/test/new_relic/agent_test.rb +1 -2
  105. data/test/new_relic/coerce_test.rb +65 -0
  106. data/test/new_relic/command/deployments_test.rb +1 -1
  107. data/test/new_relic/control_test.rb +23 -44
  108. data/test/new_relic/fake_collector.rb +34 -6
  109. data/test/new_relic/local_environment_test.rb +1 -1
  110. data/test/new_relic/metric_data_test.rb +29 -0
  111. data/test/new_relic/noticed_error_test.rb +8 -0
  112. data/test/new_relic/rack/agent_hooks_test.rb +30 -0
  113. data/test/new_relic/rack/error_collector_test.rb +16 -0
  114. data/test/new_relic/transaction_sample/segment_test.rb +7 -0
  115. data/test/new_relic/transaction_sample_test.rb +36 -8
  116. data/test/new_relic/version_number_test.rb +6 -30
  117. data/test/script/ci.sh +6 -5
  118. data/test/test_contexts.rb +2 -1
  119. data/test/test_helper.rb +23 -6
  120. data/ui/helpers/google_pie_chart.rb +1 -0
  121. metadata +68 -67
  122. data/newrelic_rpm.gemspec.erb +0 -54
  123. data/test/fixtures/gemspec_no_build.rb +0 -442
  124. data/test/fixtures/gemspec_with_build.rb +0 -442
  125. data/test/fixtures/gemspec_with_build_and_stage.rb +0 -442
  126. data/test/multiverse/suites/logging/Envfile +0 -4
  127. data/test/multiverse/suites/logging/config/newrelic.yml +0 -22
  128. data/test/multiverse/suites/monitor_mode_false/Envfile +0 -2
  129. data/test/multiverse/suites/monitor_mode_false/config/newrelic.yml +0 -25
  130. data/test/multiverse/suites/monitor_mode_false/no_dns_resolv.rb +0 -29
  131. data/test/multiverse/suites/no_load/Envfile +0 -2
  132. data/test/multiverse/suites/no_load/config/newrelic.yml +0 -22
  133. data/test/multiverse/suites/rails_3_error_tracing/Envfile +0 -15
  134. data/test/multiverse/suites/rails_3_error_tracing/config/newrelic.yml +0 -165
  135. data/test/multiverse/suites/rails_3_gc/Envfile +0 -8
  136. data/test/multiverse/suites/rails_3_gc/config/newrelic.yml +0 -167
  137. data/test/multiverse/suites/rails_3_gc/instrumentation_test.rb +0 -92
  138. data/test/multiverse/suites/rails_3_queue_time/config/newrelic.yml +0 -165
  139. data/test/multiverse/suites/rails_3_views/.gitignore +0 -3
  140. data/test/multiverse/suites/rails_3_views/Envfile +0 -16
  141. data/test/multiverse/suites/rails_3_views/config/newrelic.yml +0 -164
  142. data/test/multiverse/suites/resque/dump.rdb +0 -0
  143. data/test/multiverse/suites/rum_auto_instrumentation/Envfile +0 -4
  144. data/test/multiverse/suites/rum_auto_instrumentation/config/newrelic.yml +0 -24
  145. data/test/multiverse/suites/rum_auto_instrumentation/responses/worst_case_small.html +0 -5000
  146. data/test/new_relic/fake_service.rb +0 -53
@@ -1,4 +1,5 @@
1
1
  require File.expand_path(File.join(File.dirname(__FILE__), '..', '..', '..', 'test_helper'))
2
+ require File.expand_path(File.join(File.dirname(__FILE__), '..', '..', '..', 'test_contexts'))
2
3
 
3
4
  class NewRelic::Agent::Instrumentation::TaskInstrumentationTest < Test::Unit::TestCase
4
5
  include NewRelic::Agent::Instrumentation::ControllerInstrumentation
@@ -1,6 +1,62 @@
1
1
  require File.expand_path(File.join(File.dirname(__FILE__), '..', '..', 'test_helper'))
2
2
  require 'new_relic/agent/thread_profiler'
3
3
 
4
+ # Tests of HTTP Keep Alive implementation that require a different setup and
5
+ # set of mocks.
6
+ class NewRelicServiceKeepAliveTest < Test::Unit::TestCase
7
+ def setup
8
+ @server = NewRelic::Control::Server.new('somewhere.example.com',
9
+ 30303, '10.10.10.10')
10
+ @service = NewRelic::Agent::NewRelicService.new('license-key', @server)
11
+ end
12
+
13
+ def stub_net_http_handle(overrides = {})
14
+ stub('http_handle', :start => true, :finish => true, :address => '10.10.10.10', :port => 30303)
15
+ end
16
+
17
+ def test_session_block_reuses_http_handle
18
+ handle1 = stub_net_http_handle
19
+ handle2 = stub_net_http_handle
20
+ @service.stubs(:create_http_connection).returns(handle1, handle2)
21
+
22
+ block_ran = false
23
+ @service.session do
24
+ block_ran = true
25
+ assert(@service.http_connection)
26
+
27
+ # check we get the same object back each time we call http_connection in the block
28
+ assert_equal(@service.http_connection.object_id, handle1.object_id)
29
+ assert_equal(@service.http_connection.object_id, handle1.object_id)
30
+ end
31
+ assert(block_ran)
32
+ end
33
+
34
+ def test_multiple_http_handles_are_used_outside_session_block
35
+ handle1 = stub_net_http_handle
36
+ handle2 = stub_net_http_handle
37
+ @service.stubs(:create_http_connection).returns(handle1, handle2)
38
+ assert_equal(@service.http_connection.object_id, handle1.object_id)
39
+ assert_equal(@service.http_connection.object_id, handle2.object_id)
40
+ end
41
+
42
+
43
+ def test_session_starts_and_finishes_http_session
44
+ handle1 = stub_net_http_handle
45
+ handle1.expects(:start).once
46
+ handle1.expects(:finish).once
47
+ @service.stubs(:create_http_connection).returns(handle1)
48
+
49
+ block_ran = false
50
+ @service.session do
51
+ block_ran = true
52
+ # mocks expect #start and #finish to be called. This is how Net::HTTP
53
+ # implements keep alive
54
+ end
55
+ assert(block_ran)
56
+ end
57
+
58
+ end
59
+
4
60
  class NewRelicServiceTest < Test::Unit::TestCase
5
61
  def initialize(*_)
6
62
  [ :HTTPSuccess,
@@ -27,7 +83,7 @@ class NewRelicServiceTest < Test::Unit::TestCase
27
83
  30303, '10.10.10.10')
28
84
  @service = NewRelic::Agent::NewRelicService.new('license-key', @server)
29
85
  @http_handle = HTTPHandle.new
30
- NewRelic::Control.instance.stubs(:http_connection).returns(@http_handle)
86
+ @service.stubs(:create_http_connection).returns(@http_handle)
31
87
 
32
88
  @http_handle.respond_to(:get_redirect_host, 'localhost')
33
89
  connect_response = {
@@ -43,6 +99,43 @@ class NewRelicServiceTest < Test::Unit::TestCase
43
99
  end
44
100
  end
45
101
 
102
+ def test_cert_file_path
103
+ assert @service.cert_file_path
104
+ assert_equal File.expand_path(File.join(File.dirname(__FILE__), '..', '..', '..', 'cert', 'cacert.pem')), @service.cert_file_path
105
+ end
106
+
107
+ # This test does not actually use the ruby agent in any way - it's
108
+ # testing that the CA file we ship actually validates our server's
109
+ # certificate. It's used for customers who enable verify_certificate
110
+ def test_cert_file
111
+ require 'socket'
112
+ require 'openssl'
113
+
114
+ s = TCPSocket.new 'collector.newrelic.com', 443
115
+ ctx = OpenSSL::SSL::SSLContext.new
116
+ ctx.ca_file = @service.cert_file_path
117
+ ctx.verify_mode = OpenSSL::SSL::VERIFY_PEER
118
+ s = OpenSSL::SSL::SSLSocket.new s, ctx
119
+ s.connect
120
+ # should not raise an error
121
+ end
122
+
123
+ # see above, but for staging, as well. This allows us to test new
124
+ # certificates in a non-customer-facing place before setting them
125
+ # live.
126
+ def test_staging_cert_file
127
+ require 'socket'
128
+ require 'openssl'
129
+
130
+ s = TCPSocket.new 'staging-collector.newrelic.com', 443
131
+ ctx = OpenSSL::SSL::SSLContext.new
132
+ ctx.ca_file = @service.cert_file_path
133
+ ctx.verify_mode = OpenSSL::SSL::VERIFY_PEER
134
+ s = OpenSSL::SSL::SSLSocket.new s, ctx
135
+ s.connect
136
+ # should not raise an error
137
+ end
138
+
46
139
  def test_initialize_uses_correct_license_key_settings
47
140
  with_config(:license_key => 'abcde') do
48
141
  service = NewRelic::Agent::NewRelicService.new
@@ -65,7 +158,7 @@ class NewRelicServiceTest < Test::Unit::TestCase
65
158
  def test_connect_resets_cached_ip_address
66
159
  assert_equal '10.10.10.10', @service.collector.ip
67
160
  @service.connect
68
- assert_nil @service.collector.ip # 'localhost' resolves to nil
161
+ assert_equal 'localhost', @service.collector.ip # 'localhost' resolves to nil
69
162
  end
70
163
 
71
164
  def test_connect_uses_proxy_collector_if_no_redirect_host
@@ -77,9 +77,9 @@ class NewRelic::Agent::PipeChannelManagerTest < Test::Unit::TestCase
77
77
  sampler.notice_error(Exception.new("message"), :uri => '/myurl/',
78
78
  :metric => 'path', :referer => 'test_referer',
79
79
  :request_params => {:x => 'y'})
80
- NewRelic::Agent.agent.merge_data_from([nil, nil, [sampler.errors]])
80
+ NewRelic::Agent.agent.merge_data_from([nil, nil, sampler.errors])
81
81
 
82
- assert_equal(1, NewRelic::Agent.agent.unsent_errors_size)
82
+ assert_equal(1, NewRelic::Agent.agent.error_collector.errors.size)
83
83
 
84
84
  listener = start_listener_with_pipe(668)
85
85
 
@@ -94,7 +94,7 @@ class NewRelic::Agent::PipeChannelManagerTest < Test::Unit::TestCase
94
94
  Process.wait(pid)
95
95
  listener.stop
96
96
 
97
- assert_equal(2, NewRelic::Agent.agent.unsent_errors_size)
97
+ assert_equal(2, NewRelic::Agent.agent.error_collector.errors.size)
98
98
  end
99
99
 
100
100
  def test_close_pipe_on_EOF_string
@@ -14,7 +14,27 @@ class PipeServiceTest < Test::Unit::TestCase
14
14
  def test_connect_returns_nil
15
15
  assert_nil @service.connect({})
16
16
  end
17
-
17
+
18
+ # a #session method is required of services, though in the case of the
19
+ # PipeService all it does is invoke the block it's passed.
20
+ def test_session_invokes_block
21
+ block_ran = false
22
+ @service.session do
23
+ block_ran = true
24
+ end
25
+ assert(block_ran)
26
+ end
27
+
28
+ def test_write_to_missing_pipe_logs_error
29
+ service = NewRelic::Agent::PipeService.new(:non_existant)
30
+ ::NewRelic::Agent.logger.expects(:error) \
31
+ .with(regexp_matches(/Unable to send data to parent process/)).once
32
+
33
+ assert_nothing_raised do
34
+ service.metric_data(Time.now, Time.now, {})
35
+ end
36
+ end
37
+
18
38
  if NewRelic::LanguageSupport.can_fork? &&
19
39
  !NewRelic::LanguageSupport.using_version?('1.9.1')
20
40
 
@@ -1,5 +1,6 @@
1
1
  ENV['SKIP_RAILS'] = 'true'
2
2
  require File.expand_path('../../../test_helper', __FILE__)
3
+ require File.expand_path('../../../test_contexts', __FILE__)
3
4
 
4
5
  class NewRelic::Agent::RpmAgentTest < Test::Unit::TestCase # ActiveSupport::TestCase
5
6
  extend TestContexts
@@ -85,7 +86,6 @@ class NewRelic::Agent::RpmAgentTest < Test::Unit::TestCase # ActiveSupport::Test
85
86
  should "send_timeslice_data" do
86
87
  # this test fails due to a rubinius bug
87
88
  return if NewRelic::LanguageSupport.using_engine?('rbx')
88
- @agent.service = NewRelic::FakeService.new
89
89
  @agent.service.expects(:metric_data).returns([ [{'name' => '/A/b/c'}, 1],
90
90
  [{'name' => '/A/b/c', 'scope' => '/X'}, 2],
91
91
  [{'name' => '/A/b/d'}, 3] ])
@@ -214,4 +214,24 @@ class NewRelic::Agent::SqlSamplerTest < Test::Unit::TestCase
214
214
  assert_equal expected, sql_traces[0].to_collector_array(marshaller.default_encoder)
215
215
  end
216
216
  end
217
+
218
+ def test_to_collector_array_with_bad_values
219
+ slow = NewRelic::Agent::SlowSql.new("query", "transaction", {}, Rational(12, 1))
220
+ trace = NewRelic::Agent::SqlTrace.new("query", slow, "path", "uri")
221
+ trace.call_count = Rational(10, 1)
222
+ trace.instance_variable_set(:@sql_id, "1234")
223
+
224
+ if NewRelic::Agent::NewRelicService::JsonMarshaller.is_supported?
225
+ marshaller = NewRelic::Agent::NewRelicService::JsonMarshaller.new
226
+ else
227
+ marshaller = NewRelic::Agent::NewRelicService::PrubyMarshaller.new
228
+ end
229
+
230
+ params = RUBY_VERSION >= '1.9.2' ? "eJyrrgUAAXUA+Q==\n" : {}
231
+ expected = [ "path", "uri", 1234, "query", "transaction",
232
+ 10, 12000, 12000, 12000, params]
233
+
234
+ assert_equal expected, trace.to_collector_array(marshaller.default_encoder)
235
+ end
236
+
217
237
  end
@@ -210,7 +210,11 @@ class ThreadProfileTest < ThreadedTest
210
210
  "irb:12:in `<main>'"
211
211
  ]
212
212
 
213
- @profile = NewRelic::Agent::ThreadProfile.new(-1, 0.029, 0.01, true)
213
+ # Run the worker_loop for the thread profile based on two iterations
214
+ # This takes time fussiness out of the equation and keeps the tests stable
215
+ ignored_duration = 666
216
+ @profile = NewRelic::Agent::ThreadProfile.new(-1, ignored_duration, 0.01, true)
217
+ @profile.instance_variable_set(:@worker_loop, NewRelic::Agent::WorkerLoop.new(:limit => 2))
214
218
  end
215
219
 
216
220
  # Running Tests
@@ -426,12 +430,7 @@ class ThreadProfileTest < ThreadedTest
426
430
  assert_equal [], @profile.traces[:other][0].children
427
431
  end
428
432
 
429
- def test_to_collector_array
430
- @profile.instance_variable_set(:@start_time, 1350403938892.524)
431
- @profile.instance_variable_set(:@stop_time, 1350403939904.375)
432
- @profile.instance_variable_set(:@poll_count, 10)
433
- @profile.instance_variable_set(:@sample_count, 2)
434
-
433
+ def build_well_known_trace
435
434
  trace = ["thread_profiler.py:1:in `<module>'"]
436
435
  10.times { @profile.aggregate(trace, @profile.traces[:other]) }
437
436
 
@@ -443,13 +442,24 @@ class ThreadProfileTest < ThreadedTest
443
442
  "thread_profiler.py:103:in `_run_profiler'",
444
443
  "thread_profiler.py:165:in `collect_thread_stacks'"]
445
444
  10.times { @profile.aggregate(trace, @profile.traces[:agent]) }
445
+ end
446
+
447
+ WELL_KNOWN_TRACE_ENCODED = "eJy9klFPwjAUhf/LfW7WDQTUGBPUiYkGdAxelqXZRpGGrm1uS8xi/O924JQX\n9Un7dm77ndN7c19hlt7FCZxnWQZug7xYMYN6LSTHwDRA4KLWq53kl0CinEQh\nCUmW5zmBJH5axPPUk16MJ/E0/cGk0lLyyrGPS+uKamu943DQeX5HMtypz5In\nwv6vRCeZ1NoAGQ2PCDpvrOM1fRAlFtjQWyxq/qJxa+lj4zZaBeuuQpccrdDK\n0l4wolKU1OxftOoQLNTzIdL/EcjJafjnQYyVWjvrsDBMKNVOZBD1/jO27fPs\naBG+DoGr8fX9JJktpjftVry9A9unzGo=\n"
448
+
449
+ def test_to_collector_array
450
+ @profile.instance_variable_set(:@start_time, 1350403938892.524)
451
+ @profile.instance_variable_set(:@stop_time, 1350403939904.375)
452
+ @profile.instance_variable_set(:@poll_count, 10)
453
+ @profile.instance_variable_set(:@sample_count, 2)
454
+
455
+ build_well_known_trace
446
456
 
447
457
  expected = [[
448
458
  -1,
449
459
  1350403938892.524,
450
460
  1350403939904.375,
451
461
  10,
452
- "eJy9klFPwjAUhf/LfW7WDQTUGBPUiYkGdAxelqXZRpGGrm1uS8xi/O924JQX\n9Un7dm77ndN7c19hlt7FCZxnWQZug7xYMYN6LSTHwDRA4KLWq53kl0CinEQh\nCUmW5zmBJH5axPPUk16MJ/E0/cGk0lLyyrGPS+uKamu943DQeX5HMtypz5In\nwv6vRCeZ1NoAGQ2PCDpvrOM1fRAlFtjQWyxq/qJxa+lj4zZaBeuuQpccrdDK\n0l4wolKU1OxftOoQLNTzIdL/EcjJafjnQYyVWjvrsDBMKNVOZBD1/jO27fPs\naBG+DoGr8fX9JJktpjftVry9A9unzGo=\n",
462
+ WELL_KNOWN_TRACE_ENCODED,
453
463
  2,
454
464
  0
455
465
  ]]
@@ -457,6 +467,29 @@ class ThreadProfileTest < ThreadedTest
457
467
  marshaller = NewRelic::Agent::NewRelicService::JsonMarshaller.new
458
468
  assert_equal expected, @profile.to_collector_array(marshaller.default_encoder)
459
469
  end
470
+
471
+ def test_to_collector_array_with_bad_values
472
+ @profile.instance_variable_set(:@profile_id, "-1")
473
+ @profile.instance_variable_set(:@start_time, "")
474
+ @profile.instance_variable_set(:@stop_time, nil)
475
+ @profile.instance_variable_set(:@poll_count, Rational(10, 1))
476
+ @profile.instance_variable_set(:@sample_count, nil)
477
+
478
+ build_well_known_trace
479
+
480
+ expected = [[
481
+ -1,
482
+ 0.0,
483
+ 0.0,
484
+ 10,
485
+ WELL_KNOWN_TRACE_ENCODED,
486
+ 0,
487
+ 0
488
+ ]]
489
+
490
+ marshaller = NewRelic::Agent::NewRelicService::JsonMarshaller.new
491
+ assert_equal expected, @profile.to_collector_array(marshaller.default_encoder)
492
+ end
460
493
  end
461
494
 
462
495
  class ThreadProfileNodeTest < Test::Unit::TestCase
@@ -492,6 +525,18 @@ class ThreadProfileNodeTest < Test::Unit::TestCase
492
525
  node.to_array)
493
526
  end
494
527
 
528
+ def test_gracefully_handle_bad_values_in_to_array
529
+ node = NewRelic::Agent::ThreadProfile::Node.new(SINGLE_LINE)
530
+ node.instance_variable_set(:@line_no, "blarg")
531
+ node.runnable_count = Rational(10, 1)
532
+
533
+ assert_equal([
534
+ ["irb.rb", "catch", 0],
535
+ 10, 0,
536
+ []],
537
+ node.to_array)
538
+ end
539
+
495
540
  def test_add_child_twice
496
541
  parent = NewRelic::Agent::ThreadProfile::Node.new(SINGLE_LINE)
497
542
  child = NewRelic::Agent::ThreadProfile::Node.new(SINGLE_LINE)
@@ -18,6 +18,11 @@ class NewRelic::Agent::WorkerLoopTest < Test::Unit::TestCase
18
18
 
19
19
  def test_with_duration
20
20
  worker_loop = NewRelic::Agent::WorkerLoop.new(:duration => 0.1)
21
+
22
+ # Advance in small increments vs our period so time will pass over the
23
+ # nasty multiple calls to Time.now that WorkerLoop makes
24
+ Time.stubs(:now).returns(*ticks(0, 0.12, 0.005))
25
+
21
26
  count = 0
22
27
  worker_loop.run(0.04) do
23
28
  count += 1
@@ -26,6 +31,15 @@ class NewRelic::Agent::WorkerLoopTest < Test::Unit::TestCase
26
31
  assert_equal 2, count
27
32
  end
28
33
 
34
+ def test_duration_clock_starts_with_run
35
+ # This test is a little on the nose, but any timing based test WILL fail in CI
36
+ worker_loop = NewRelic::Agent::WorkerLoop.new(:duration => 0.01)
37
+ assert_nil worker_loop.instance_variable_get(:@deadline)
38
+
39
+ worker_loop.run(0.001) {}
40
+ assert !worker_loop.instance_variable_get(:@deadline).nil?
41
+ end
42
+
29
43
  def test_loop_limit
30
44
  worker_loop = NewRelic::Agent::WorkerLoop.new(:limit => 2)
31
45
  iterations = 0
@@ -33,21 +47,6 @@ class NewRelic::Agent::WorkerLoopTest < Test::Unit::TestCase
33
47
  assert_equal 2, iterations
34
48
  end
35
49
 
36
- def test_density
37
- # This shows how the tasks stay aligned with the period and don't drift.
38
- count = 0
39
- start = Time.now
40
- @worker_loop.run(0.03) do
41
- count +=1
42
- if count == 3
43
- @worker_loop.stop
44
- next
45
- end
46
- end
47
- elapsed = Time.now - start
48
- assert_in_delta 0.09, elapsed, 0.03
49
- end
50
-
51
50
  def test_task_error__standard
52
51
  expects_logging(:error, any_parameters)
53
52
  # This loop task will run twice
@@ -71,11 +70,15 @@ class NewRelic::Agent::WorkerLoopTest < Test::Unit::TestCase
71
70
  end
72
71
 
73
72
  def test_task_error__server
74
- expects_no_logging(:error, any_parameters)
73
+ expects_no_logging(:error)
75
74
  expects_logging(:debug, any_parameters)
76
75
  @worker_loop.run(0) do
77
76
  @worker_loop.stop
78
77
  raise NewRelic::Agent::ServerError, "Runtime Error Test"
79
78
  end
80
79
  end
80
+
81
+ def ticks(start, finish, step)
82
+ (start..finish).step(step).to_a
83
+ end
81
84
  end
@@ -31,6 +31,7 @@ module NewRelic
31
31
 
32
32
  def test_shutdown_removes_server_config
33
33
  NewRelic::Agent.manual_start
34
+ NewRelic::Agent.instance.service = default_service
34
35
  NewRelic::Agent.instance.finish_setup('agent_config' =>
35
36
  { :some_absurd_setting => true })
36
37
  assert NewRelic::Agent.config[:some_absurd_setting]
@@ -70,7 +71,6 @@ module NewRelic
70
71
  def test_timeslice_harvest_with_after_fork_report_to_channel
71
72
  with_config(:agent_enabled => true, :monitor_mode => true) do
72
73
  NewRelic::Agent.shutdown # make sure the agent is not already started
73
- NewRelic::Agent::Agent.instance.service = NewRelic::FakeService.new
74
74
  NewRelic::Agent.manual_start(:license_key => ('1234567890' * 4),
75
75
  :start_channel_listener => true)
76
76
 
@@ -120,7 +120,6 @@ module NewRelic
120
120
 
121
121
  def test_manual_start_starts_channel_listener
122
122
  NewRelic::Agent::PipeChannelManager.listener.stop
123
- NewRelic::Agent.agent.service = NewRelic::FakeService.new
124
123
  NewRelic::Agent.manual_start(:start_channel_listener => true)
125
124
  assert NewRelic::Agent::PipeChannelManager.listener.started?
126
125
  NewRelic::Agent::PipeChannelManager.listener.stop
@@ -0,0 +1,65 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__),'..','test_helper'))
2
+ require 'new_relic/coerce'
3
+
4
+ class CoerceTest < Test::Unit::TestCase
5
+
6
+ include NewRelic::Coerce
7
+
8
+ def test_int_coerce
9
+ assert_equal 1, int(1)
10
+ assert_equal 1, int("1")
11
+ assert_equal 1, int(1.0)
12
+ assert_equal 1, int(Rational(1, 1))
13
+ assert_equal 0, int("invalid")
14
+ assert_equal 0, int(nil)
15
+
16
+ # http://ruby-doc.org/core-1.8.7/Symbol.html#method-i-to_i
17
+ assert_equal 0, int(:wat) unless RUBY_VERSION < '1.9'
18
+ end
19
+
20
+ def test_int_coerce_logs
21
+ expects_logging(:warn, Not(includes("context")), any_parameters)
22
+ int("not valid")
23
+ end
24
+
25
+ def test_int_coerce_logs_with_context
26
+ expects_logging(:warn, all_of(includes("HERE"), includes("Integer")), anything)
27
+ int("not valid", "HERE")
28
+ end
29
+
30
+
31
+ def test_float_coerce
32
+ assert_equal 1.0, float(1.0)
33
+ assert_equal 1.0, float("1.0")
34
+ assert_equal 1.0, float(1)
35
+ assert_equal 1.0, float(Rational(1, 1))
36
+ assert_equal 0.0, float("invalid")
37
+ assert_equal 0.0, float(nil)
38
+ assert_equal 0.0, float(:symbols_are_fun)
39
+ end
40
+
41
+ def test_float_coerce_logs_with_context
42
+ expects_logging(:warn, all_of(includes("HERE"), includes("Float")), anything)
43
+ float("not valid", "HERE")
44
+ end
45
+
46
+
47
+ def test_string_coerce
48
+ assert_equal "1", string(1)
49
+ assert_equal "1.0", string(1.0)
50
+ assert_equal "string", string("string")
51
+ assert_equal "1/100", string(Rational(1, 100))
52
+ assert_equal "yeah", string(:yeah)
53
+ assert_equal nil, string(nil)
54
+ assert_equal "", string(Unstringable.new)
55
+ end
56
+
57
+ def test_string_coerce_logs_with_context
58
+ expects_logging(:warn, all_of(includes("HERE"), includes("String")), anything)
59
+ string(Unstringable.new, "HERE")
60
+ end
61
+
62
+ class Unstringable
63
+ undef :to_s
64
+ end
65
+ end