wd_newrelic_rpm 3.5.5 → 3.5.6

Sign up to get free protection for your applications and to get access to all the features.
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