statsd-ruby-tcp 0.0.0

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.
@@ -0,0 +1,35 @@
1
+ class Statsd
2
+ # = MonotonicTime: a helper for getting monotonic time
3
+ #
4
+ # @example
5
+ # MonotonicTime.time_in_ms #=> 287138801.144576
6
+
7
+ # MonotonicTime guarantees that the time is strictly linearly
8
+ # increasing (unlike realtime).
9
+ # @see http://pubs.opengroup.org/onlinepubs/9699919799/functions/clock_getres.html
10
+ module MonotonicTime
11
+ class << self
12
+ # @return [Integer] current monotonic time in milliseconds
13
+ def time_in_ms
14
+ time_in_nanoseconds / (10.0 ** 6)
15
+ end
16
+
17
+ private
18
+
19
+ if defined?(Process::CLOCK_MONOTONIC)
20
+ def time_in_nanoseconds
21
+ Process.clock_gettime(Process::CLOCK_MONOTONIC, :nanosecond)
22
+ end
23
+ elsif RUBY_ENGINE == 'jruby'
24
+ def time_in_nanoseconds
25
+ java.lang.System.nanoTime
26
+ end
27
+ else
28
+ def time_in_nanoseconds
29
+ t = Time.now
30
+ t.to_i * (10 ** 9) + t.nsec
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,43 @@
1
+ require 'bundler/setup'
2
+
3
+ require 'simplecov'
4
+ SimpleCov.start
5
+
6
+ require 'minitest/autorun'
7
+ require 'statsd'
8
+ require 'logger'
9
+ require 'timeout'
10
+
11
+ class FakeUDPSocket
12
+ def initialize
13
+ @buffer = []
14
+ end
15
+
16
+ def write(message)
17
+ @buffer.push [message]
18
+ message.length
19
+ end
20
+
21
+ def recv
22
+ @buffer.shift
23
+ end
24
+
25
+ def clear
26
+ @buffer = []
27
+ end
28
+
29
+ def to_s
30
+ inspect
31
+ end
32
+
33
+ def inspect
34
+ "<#{self.class.name}: #{@buffer.inspect}>"
35
+ end
36
+ end
37
+
38
+ class FakeTCPSocket < FakeUDPSocket
39
+ alias_method :readline, :recv
40
+ def write(message)
41
+ @buffer.push message
42
+ end
43
+ end
@@ -0,0 +1,117 @@
1
+ require 'helper'
2
+
3
+ describe Statsd::Admin do
4
+
5
+ before do
6
+ class Statsd::Admin
7
+ o, $VERBOSE = $VERBOSE, nil
8
+ alias connect_old connect
9
+ def connect
10
+ $connect_count ||= 0
11
+ $connect_count += 1
12
+ end
13
+ $VERBOSE = o
14
+ end
15
+ @admin = Statsd::Admin.new('localhost', 1234)
16
+ @socket = @admin.instance_variable_set(:@socket, FakeTCPSocket.new)
17
+ end
18
+
19
+ after do
20
+ class Statsd::Admin
21
+ o, $VERBOSE = $VERBOSE, nil
22
+ alias connect connect_old
23
+ $VERBOSE = o
24
+ end
25
+ end
26
+
27
+ describe "#initialize" do
28
+ it "should set the host and port" do
29
+ @admin.host.must_equal 'localhost'
30
+ @admin.port.must_equal 1234
31
+ end
32
+
33
+ it "should default the host to 127.0.0.1 and port to 8126" do
34
+ statsd = Statsd::Admin.new
35
+ statsd.host.must_equal '127.0.0.1'
36
+ statsd.port.must_equal 8126
37
+ end
38
+ end
39
+
40
+ describe "#host and #port" do
41
+ it "should set host and port" do
42
+ @admin.host = '1.2.3.4'
43
+ @admin.port = 5678
44
+ @admin.host.must_equal '1.2.3.4'
45
+ @admin.port.must_equal 5678
46
+ end
47
+
48
+ it "should not resolve hostnames to IPs" do
49
+ @admin.host = 'localhost'
50
+ @admin.host.must_equal 'localhost'
51
+ end
52
+
53
+ it "should set nil host to default" do
54
+ @admin.host = nil
55
+ @admin.host.must_equal '127.0.0.1'
56
+ end
57
+
58
+ it "should set nil port to default" do
59
+ @admin.port = nil
60
+ @admin.port.must_equal 8126
61
+ end
62
+ end
63
+
64
+ %w(gauges counters timers).each do |action|
65
+ describe "##{action}" do
66
+ it "should send a command and return a Hash" do
67
+ ["{'foo.bar': 0,\n",
68
+ "'foo.baz': 1,\n",
69
+ "'foo.quux': 2 }\n",
70
+ "END\n","\n"].each do |line|
71
+ @socket.write line
72
+ end
73
+ result = @admin.send action.to_sym
74
+ result.must_be_kind_of Hash
75
+ result.size.must_equal 3
76
+ @socket.readline.must_equal "#{action}\n"
77
+ end
78
+ end
79
+
80
+ describe "#del#{action}" do
81
+ it "should send a command and return an Array" do
82
+ ["deleted: foo.bar\n",
83
+ "deleted: foo.baz\n",
84
+ "deleted: foo.quux\n",
85
+ "END\n", "\n"].each do |line|
86
+ @socket.write line
87
+ end
88
+ result = @admin.send "del#{action}", "foo.*"
89
+ result.must_be_kind_of Array
90
+ result.size.must_equal 3
91
+ @socket.readline.must_equal "del#{action} foo.*\n"
92
+ end
93
+ end
94
+ end
95
+
96
+ describe "#stats" do
97
+ it "should send a command and return a Hash" do
98
+ ["whatever: 0\n", "END\n", "\n"].each do |line|
99
+ @socket.write line
100
+ end
101
+ result = @admin.stats
102
+ result.must_be_kind_of Hash
103
+ result["whatever"].must_equal 0
104
+ @socket.readline.must_equal "stats\n"
105
+ end
106
+ end
107
+
108
+ describe "#connect" do
109
+ it "should reconnect" do
110
+ c = $connect_count
111
+ @admin.connect
112
+ ($connect_count - c).must_equal 1
113
+ end
114
+ end
115
+ end
116
+
117
+
@@ -0,0 +1,593 @@
1
+ require 'helper'
2
+
3
+ describe Statsd do
4
+ before do
5
+ class Statsd
6
+ o, $VERBOSE = $VERBOSE, nil
7
+ alias connect_old connect
8
+ def connect
9
+ $connect_count ||= 1
10
+ $connect_count += 1
11
+ end
12
+ $VERBOSE = o
13
+ end
14
+
15
+ @statsd = Statsd.new('localhost', 1234)
16
+ @socket = @statsd.instance_variable_set(:@socket, FakeUDPSocket.new)
17
+ end
18
+
19
+ after do
20
+ class Statsd
21
+ o, $VERBOSE = $VERBOSE, nil
22
+ alias connect connect_old
23
+ $VERBOSE = o
24
+ end
25
+ end
26
+
27
+ describe "#initialize" do
28
+ it "should set the host and port" do
29
+ @statsd.host.must_equal 'localhost'
30
+ @statsd.port.must_equal 1234
31
+ end
32
+
33
+ it "should default the host to 127.0.0.1 and port to 8125" do
34
+ statsd = Statsd.new
35
+ statsd.host.must_equal '127.0.0.1'
36
+ statsd.port.must_equal 8125
37
+ end
38
+
39
+ it "should set delimiter to period by default" do
40
+ @statsd.delimiter.must_equal "."
41
+ end
42
+ end
43
+
44
+ describe "#host and #port" do
45
+ it "should set host and port" do
46
+ @statsd.host = '1.2.3.4'
47
+ @statsd.port = 5678
48
+ @statsd.host.must_equal '1.2.3.4'
49
+ @statsd.port.must_equal 5678
50
+ end
51
+
52
+ it "should not resolve hostnames to IPs" do
53
+ @statsd.host = 'localhost'
54
+ @statsd.host.must_equal 'localhost'
55
+ end
56
+
57
+ it "should set nil host to default" do
58
+ @statsd.host = nil
59
+ @statsd.host.must_equal '127.0.0.1'
60
+ end
61
+
62
+ it "should set nil port to default" do
63
+ @statsd.port = nil
64
+ @statsd.port.must_equal 8125
65
+ end
66
+
67
+ it "should allow an IPv6 address" do
68
+ @statsd.host = '::1'
69
+ @statsd.host.must_equal '::1'
70
+ end
71
+ end
72
+
73
+ describe "#delimiter" do
74
+ it "should set delimiter" do
75
+ @statsd.delimiter = "-"
76
+ @statsd.delimiter.must_equal "-"
77
+ end
78
+
79
+ it "should set default to period if not given a value" do
80
+ @statsd.delimiter = nil
81
+ @statsd.delimiter.must_equal "."
82
+ end
83
+ end
84
+
85
+ describe "#increment" do
86
+ it "should format the message according to the statsd spec" do
87
+ @statsd.increment('foobar')
88
+ @socket.recv.must_equal ['foobar:1|c']
89
+ end
90
+
91
+ describe "with a sample rate" do
92
+ before { class << @statsd; def rand; 0; end; end } # ensure delivery
93
+ it "should format the message according to the statsd spec" do
94
+ @statsd.increment('foobar', 0.5)
95
+ @socket.recv.must_equal ['foobar:1|c|@0.5']
96
+ end
97
+ end
98
+ end
99
+
100
+ describe "#decrement" do
101
+ it "should format the message according to the statsd spec" do
102
+ @statsd.decrement('foobar')
103
+ @socket.recv.must_equal ['foobar:-1|c']
104
+ end
105
+
106
+ describe "with a sample rate" do
107
+ before { class << @statsd; def rand; 0; end; end } # ensure delivery
108
+ it "should format the message according to the statsd spec" do
109
+ @statsd.decrement('foobar', 0.5)
110
+ @socket.recv.must_equal ['foobar:-1|c|@0.5']
111
+ end
112
+ end
113
+ end
114
+
115
+ describe "#gauge" do
116
+ it "should send a message with a 'g' type, per the nearbuy fork" do
117
+ @statsd.gauge('begrutten-suffusion', 536)
118
+ @socket.recv.must_equal ['begrutten-suffusion:536|g']
119
+ @statsd.gauge('begrutten-suffusion', -107.3)
120
+ @socket.recv.must_equal ['begrutten-suffusion:-107.3|g']
121
+ end
122
+
123
+ describe "with a sample rate" do
124
+ before { class << @statsd; def rand; 0; end; end } # ensure delivery
125
+ it "should format the message according to the statsd spec" do
126
+ @statsd.gauge('begrutten-suffusion', 536, 0.1)
127
+ @socket.recv.must_equal ['begrutten-suffusion:536|g|@0.1']
128
+ end
129
+ end
130
+ end
131
+
132
+ describe "#timing" do
133
+ it "should format the message according to the statsd spec" do
134
+ @statsd.timing('foobar', 500)
135
+ @socket.recv.must_equal ['foobar:500|ms']
136
+ end
137
+
138
+ describe "with a sample rate" do
139
+ before { class << @statsd; def rand; 0; end; end } # ensure delivery
140
+ it "should format the message according to the statsd spec" do
141
+ @statsd.timing('foobar', 500, 0.5)
142
+ @socket.recv.must_equal ['foobar:500|ms|@0.5']
143
+ end
144
+ end
145
+ end
146
+
147
+ describe "#set" do
148
+ it "should format the message according to the statsd spec" do
149
+ @statsd.set('foobar', 765)
150
+ @socket.recv.must_equal ['foobar:765|s']
151
+ end
152
+
153
+ describe "with a sample rate" do
154
+ before { class << @statsd; def rand; 0; end; end } # ensure delivery
155
+ it "should format the message according to the statsd spec" do
156
+ @statsd.set('foobar', 500, 0.5)
157
+ @socket.recv.must_equal ['foobar:500|s|@0.5']
158
+ end
159
+ end
160
+ end
161
+
162
+ describe "#time" do
163
+ it "should format the message according to the statsd spec" do
164
+ @statsd.time('foobar') { 'test' }
165
+ @socket.recv.must_equal ['foobar:0|ms']
166
+ end
167
+
168
+ it "should return the result of the block" do
169
+ result = @statsd.time('foobar') { 'test' }
170
+ result.must_equal 'test'
171
+ end
172
+
173
+ describe "when given a block with an explicit return" do
174
+ it "should format the message according to the statsd spec" do
175
+ lambda { @statsd.time('foobar') { return 'test' } }.call
176
+ @socket.recv.must_equal ['foobar:0|ms']
177
+ end
178
+
179
+ it "should return the result of the block" do
180
+ result = lambda { @statsd.time('foobar') { return 'test' } }.call
181
+ result.must_equal 'test'
182
+ end
183
+ end
184
+
185
+ describe "with a sample rate" do
186
+ before { class << @statsd; def rand; 0; end; end } # ensure delivery
187
+
188
+ it "should format the message according to the statsd spec" do
189
+ @statsd.time('foobar', 0.5) { 'test' }
190
+ @socket.recv.must_equal ['foobar:0|ms|@0.5']
191
+ end
192
+ end
193
+ end
194
+
195
+ describe "#sampled" do
196
+ describe "when the sample rate is 1" do
197
+ before { class << @statsd; def rand; raise end; end }
198
+ it "should send" do
199
+ @statsd.timing('foobar', 500, 1)
200
+ @socket.recv.must_equal ['foobar:500|ms']
201
+ end
202
+ end
203
+
204
+ describe "when the sample rate is greater than a random value [0,1]" do
205
+ before { class << @statsd; def rand; 0; end; end } # ensure delivery
206
+ it "should send" do
207
+ @statsd.timing('foobar', 500, 0.5)
208
+ @socket.recv.must_equal ['foobar:500|ms|@0.5']
209
+ end
210
+ end
211
+
212
+ describe "when the sample rate is less than a random value [0,1]" do
213
+ before { class << @statsd; def rand; 1; end; end } # ensure no delivery
214
+ it "should not send" do
215
+ assert_nil @statsd.timing('foobar', 500, 0.5)
216
+ end
217
+ end
218
+
219
+ describe "when the sample rate is equal to a random value [0,1]" do
220
+ before { class << @statsd; def rand; 0; end; end } # ensure delivery
221
+ it "should send" do
222
+ @statsd.timing('foobar', 500, 0.5)
223
+ @socket.recv.must_equal ['foobar:500|ms|@0.5']
224
+ end
225
+ end
226
+ end
227
+
228
+ describe "with namespace" do
229
+ before { @statsd.namespace = 'service' }
230
+
231
+ it "should add namespace to increment" do
232
+ @statsd.increment('foobar')
233
+ @socket.recv.must_equal ['service.foobar:1|c']
234
+ end
235
+
236
+ it "should add namespace to decrement" do
237
+ @statsd.decrement('foobar')
238
+ @socket.recv.must_equal ['service.foobar:-1|c']
239
+ end
240
+
241
+ it "should add namespace to timing" do
242
+ @statsd.timing('foobar', 500)
243
+ @socket.recv.must_equal ['service.foobar:500|ms']
244
+ end
245
+
246
+ it "should add namespace to gauge" do
247
+ @statsd.gauge('foobar', 500)
248
+ @socket.recv.must_equal ['service.foobar:500|g']
249
+ end
250
+ end
251
+
252
+ describe "with postfix" do
253
+ before { @statsd.postfix = 'ip-23-45-56-78' }
254
+
255
+ it "should add postfix to increment" do
256
+ @statsd.increment('foobar')
257
+ @socket.recv.must_equal ['foobar.ip-23-45-56-78:1|c']
258
+ end
259
+
260
+ it "should add postfix to decrement" do
261
+ @statsd.decrement('foobar')
262
+ @socket.recv.must_equal ['foobar.ip-23-45-56-78:-1|c']
263
+ end
264
+
265
+ it "should add namespace to timing" do
266
+ @statsd.timing('foobar', 500)
267
+ @socket.recv.must_equal ['foobar.ip-23-45-56-78:500|ms']
268
+ end
269
+
270
+ it "should add namespace to gauge" do
271
+ @statsd.gauge('foobar', 500)
272
+ @socket.recv.must_equal ['foobar.ip-23-45-56-78:500|g']
273
+ end
274
+ end
275
+
276
+ describe '#postfix=' do
277
+ describe "when nil, false, or empty" do
278
+ it "should set postfix to nil" do
279
+ [nil, false, ''].each do |value|
280
+ @statsd.postfix = 'a postfix'
281
+ @statsd.postfix = value
282
+ assert_nil @statsd.postfix
283
+ end
284
+ end
285
+ end
286
+ end
287
+
288
+ describe "with logging" do
289
+ require 'stringio'
290
+ before { Statsd.logger = Logger.new(@log = StringIO.new)}
291
+
292
+ it "should write to the log in debug" do
293
+ Statsd.logger.level = Logger::DEBUG
294
+
295
+ @statsd.increment('foobar')
296
+
297
+ @log.string.must_match "Statsd: foobar:1|c"
298
+ end
299
+
300
+ it "should not write to the log unless debug" do
301
+ Statsd.logger.level = Logger::INFO
302
+
303
+ @statsd.increment('foobar')
304
+
305
+ @log.string.must_be_empty
306
+ end
307
+ end
308
+
309
+ describe "stat names" do
310
+ it "should accept anything as stat" do
311
+ @statsd.increment(Object, 1)
312
+ end
313
+
314
+ it "should replace ruby constant delimeter with graphite package name" do
315
+ class Statsd::SomeClass; end
316
+ @statsd.increment(Statsd::SomeClass, 1)
317
+
318
+ @socket.recv.must_equal ['Statsd.SomeClass:1|c']
319
+ end
320
+
321
+ describe "custom delimiter" do
322
+ before do
323
+ @statsd.delimiter = "-"
324
+ end
325
+
326
+ it "should replace ruby constant delimiter with custom delimiter" do
327
+ class Statsd::SomeOtherClass; end
328
+ @statsd.increment(Statsd::SomeOtherClass, 1)
329
+
330
+ @socket.recv.must_equal ['Statsd-SomeOtherClass:1|c']
331
+ end
332
+ end
333
+
334
+ it "should replace statsd reserved chars in the stat name" do
335
+ @statsd.increment('ray@hostname.blah|blah.blah:blah', 1)
336
+ @socket.recv.must_equal ['ray_hostname.blah_blah.blah_blah:1|c']
337
+ end
338
+ end
339
+
340
+ describe "handling socket errors" do
341
+ before do
342
+ require 'stringio'
343
+ Statsd.logger = Logger.new(@log = StringIO.new)
344
+ @socket.instance_eval { def write(*) raise SocketError end }
345
+ end
346
+
347
+ it "should ignore socket errors" do
348
+ assert_nil @statsd.increment('foobar')
349
+ end
350
+
351
+ it "should log socket errors" do
352
+ @statsd.increment('foobar')
353
+ @log.string.must_match 'Statsd: SocketError'
354
+ end
355
+ end
356
+
357
+ describe "batching" do
358
+ it "should have a default batch size of 10" do
359
+ @statsd.batch_size.must_equal 10
360
+ end
361
+
362
+ it "should have a default batch byte size of nil" do
363
+ assert_nil @statsd.batch_byte_size
364
+ end
365
+
366
+ it "should have a default flush interval of nil" do
367
+ assert_nil @statsd.flush_interval
368
+ end
369
+
370
+ it "should have a modifiable batch size" do
371
+ @statsd.batch_size = 7
372
+ @statsd.batch_size.must_equal 7
373
+ @statsd.batch do |b|
374
+ b.batch_size.must_equal 7
375
+ end
376
+
377
+ @statsd.batch_size = nil
378
+ @statsd.batch_byte_size = 1472
379
+ @statsd.batch do |b|
380
+ assert_nil b.batch_size
381
+ b.batch_byte_size.must_equal 1472
382
+ end
383
+
384
+ end
385
+
386
+ it 'should have a modifiable flush interval' do
387
+ @statsd.flush_interval = 1
388
+ @statsd.flush_interval.must_equal 1
389
+ @statsd.batch do |b|
390
+ b.flush_interval.must_equal 1
391
+ end
392
+ end
393
+
394
+ it "should flush the batch at the batch size or at the end of the block" do
395
+ @statsd.batch do |b|
396
+ b.batch_size = 3
397
+
398
+ # The first three should flush, the next two will be flushed when the
399
+ # block is done.
400
+ 5.times { b.increment('foobar') }
401
+
402
+ @socket.recv.must_equal [(["foobar:1|c"] * 3).join("\n")]
403
+ end
404
+
405
+ @socket.recv.must_equal [(["foobar:1|c"] * 2).join("\n")]
406
+ end
407
+
408
+ it "should flush based on batch byte size" do
409
+ @statsd.batch do |b|
410
+ b.batch_size = nil
411
+ b.batch_byte_size = 22
412
+
413
+ # The first two should flush, the last will be flushed when the
414
+ # block is done.
415
+ 3.times { b.increment('foobar') }
416
+
417
+ @socket.recv.must_equal [(["foobar:1|c"] * 2).join("\n")]
418
+ end
419
+
420
+ @socket.recv.must_equal ["foobar:1|c"]
421
+ end
422
+
423
+ it "should flush immediately when the queue is exactly a batch size" do
424
+ @statsd.batch do |b|
425
+ b.batch_size = nil
426
+ b.batch_byte_size = 21
427
+
428
+ # The first two should flush together
429
+ 2.times { b.increment('foobar') }
430
+
431
+ @socket.recv.must_equal [(["foobar:1|c"] * 2).join("\n")]
432
+ end
433
+ end
434
+
435
+ it "should flush when the interval has passed" do
436
+ @statsd.batch do |b|
437
+ b.batch_size = nil
438
+ b.flush_interval = 0.01
439
+
440
+ # The first two should flush, the last will be flushed when the
441
+ # block is done.
442
+ 2.times { b.increment('foobar') }
443
+ sleep(0.03)
444
+ b.increment('foobar')
445
+
446
+ @socket.recv.must_equal [(["foobar:1|c"] * 2).join("\n")]
447
+ end
448
+
449
+ @socket.recv.must_equal ["foobar:1|c"]
450
+ end
451
+
452
+ it "should not flush to the socket if the backlog is empty" do
453
+ batch = Statsd::Batch.new(@statsd)
454
+ batch.flush
455
+ @socket.recv.must_be :nil?
456
+
457
+ batch.increment 'foobar'
458
+ batch.flush
459
+ @socket.recv.must_equal %w[foobar:1|c]
460
+ end
461
+
462
+ it "should support setting namespace for the underlying instance" do
463
+ batch = Statsd::Batch.new(@statsd)
464
+ batch.namespace = 'ns'
465
+ @statsd.namespace.must_equal 'ns'
466
+ end
467
+
468
+ it "should support setting host for the underlying instance" do
469
+ batch = Statsd::Batch.new(@statsd)
470
+ batch.host = '1.2.3.4'
471
+ @statsd.host.must_equal '1.2.3.4'
472
+ end
473
+
474
+ it "should support setting port for the underlying instance" do
475
+ batch = Statsd::Batch.new(@statsd)
476
+ batch.port = 42
477
+ @statsd.port.must_equal 42
478
+ end
479
+
480
+ end
481
+
482
+ describe "#connect" do
483
+ it "should reconnect" do
484
+ c = $connect_count
485
+ @statsd.connect
486
+ ($connect_count - c).must_equal 1
487
+ end
488
+ end
489
+
490
+ end
491
+
492
+ describe Statsd do
493
+ describe "with a real UDP socket" do
494
+ it "should actually send stuff over the socket" do
495
+ family = Addrinfo.udp(UDPSocket.getaddress('localhost'), 0).afamily
496
+ begin
497
+ socket = UDPSocket.new family
498
+ host, port = 'localhost', 0
499
+ socket.bind(host, port)
500
+ port = socket.addr[1]
501
+
502
+ statsd = Statsd.new(host, port)
503
+ statsd.increment('foobar')
504
+ message = socket.recvfrom(16).first
505
+ message.must_equal 'foobar:1|c'
506
+ ensure
507
+ socket.close
508
+ end
509
+ end
510
+
511
+ it "should send stuff over an IPv4 socket" do
512
+ begin
513
+ socket = UDPSocket.new Socket::AF_INET
514
+ host, port = '127.0.0.1', 0
515
+ socket.bind(host, port)
516
+ port = socket.addr[1]
517
+
518
+ statsd = Statsd.new(host, port)
519
+ statsd.increment('foobar')
520
+ message = socket.recvfrom(16).first
521
+ message.must_equal 'foobar:1|c'
522
+ ensure
523
+ socket.close
524
+ end
525
+ end
526
+
527
+ it "should send stuff over an IPv6 socket" do
528
+ begin
529
+ socket = UDPSocket.new Socket::AF_INET6
530
+ host, port = '::1', 0
531
+ socket.bind(host, port)
532
+ port = socket.addr[1]
533
+
534
+ statsd = Statsd.new(host, port)
535
+ statsd.increment('foobar')
536
+ message = socket.recvfrom(16).first
537
+ message.must_equal 'foobar:1|c'
538
+ ensure
539
+ socket.close
540
+ end
541
+ end
542
+ end
543
+
544
+ describe "supports TCP sockets" do
545
+ it "should connect to and send stats over TCPv4" do
546
+ begin
547
+ host, port = '127.0.0.1', 0
548
+ server = TCPServer.new host, port
549
+ port = server.addr[1]
550
+
551
+ socket = nil
552
+ Thread.new { socket = server.accept }
553
+
554
+ statsd = Statsd.new(host, port, :tcp)
555
+ statsd.increment('foobar')
556
+
557
+ Timeout.timeout(5) do
558
+ Thread.pass while socket == nil
559
+ end
560
+
561
+ message = socket.recvfrom(16).first
562
+ message.must_equal "foobar:1|c\n"
563
+ ensure
564
+ socket.close if socket
565
+ server.close
566
+ end
567
+ end
568
+
569
+ it "should connect to and send stats over TCPv6" do
570
+ begin
571
+ host, port = '::1', 0
572
+ server = TCPServer.new host, port
573
+ port = server.addr[1]
574
+
575
+ socket = nil
576
+ Thread.new { socket = server.accept }
577
+
578
+ statsd = Statsd.new(host, port, :tcp)
579
+ statsd.increment('foobar')
580
+
581
+ Timeout.timeout(5) do
582
+ Thread.pass while socket == nil
583
+ end
584
+
585
+ message = socket.recvfrom(16).first
586
+ message.must_equal "foobar:1|c\n"
587
+ ensure
588
+ socket.close if socket
589
+ server.close
590
+ end
591
+ end
592
+ end
593
+ end