raindrops 0.4.1 → 0.5.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.
Files changed (49) hide show
  1. data/.document +2 -1
  2. data/.gitignore +4 -0
  3. data/.wrongdoc.yml +4 -0
  4. data/GIT-VERSION-GEN +1 -1
  5. data/GNUmakefile +2 -196
  6. data/Gemfile +7 -0
  7. data/LICENSE +1 -1
  8. data/README +17 -47
  9. data/Rakefile +0 -104
  10. data/examples/linux-listener-stats.rb +123 -0
  11. data/examples/{config.ru → middleware.ru} +1 -1
  12. data/examples/watcher.ru +4 -0
  13. data/examples/watcher_demo.ru +13 -0
  14. data/examples/zbatery.conf.rb +13 -0
  15. data/ext/raindrops/extconf.rb +5 -0
  16. data/ext/raindrops/linux_inet_diag.c +449 -151
  17. data/ext/raindrops/linux_tcp_info.c +170 -0
  18. data/ext/raindrops/my_fileno.h +36 -0
  19. data/ext/raindrops/raindrops.c +232 -20
  20. data/lib/raindrops.rb +20 -7
  21. data/lib/raindrops/aggregate.rb +8 -0
  22. data/lib/raindrops/aggregate/last_data_recv.rb +86 -0
  23. data/lib/raindrops/aggregate/pmq.rb +239 -0
  24. data/lib/raindrops/last_data_recv.rb +100 -0
  25. data/lib/raindrops/linux.rb +26 -16
  26. data/lib/raindrops/middleware.rb +112 -41
  27. data/lib/raindrops/middleware/proxy.rb +34 -0
  28. data/lib/raindrops/struct.rb +15 -0
  29. data/lib/raindrops/watcher.rb +362 -0
  30. data/pkg.mk +171 -0
  31. data/raindrops.gemspec +10 -20
  32. data/test/ipv6_enabled.rb +10 -0
  33. data/test/rack_unicorn.rb +12 -0
  34. data/test/test_aggregate_pmq.rb +65 -0
  35. data/test/test_inet_diag_socket.rb +13 -0
  36. data/test/test_last_data_recv_unicorn.rb +69 -0
  37. data/test/test_linux.rb +55 -57
  38. data/test/test_linux_all_tcp_listen_stats.rb +66 -0
  39. data/test/test_linux_all_tcp_listen_stats_leak.rb +43 -0
  40. data/test/test_linux_ipv6.rb +158 -0
  41. data/test/test_linux_tcp_info.rb +61 -0
  42. data/test/test_middleware.rb +15 -2
  43. data/test/test_middleware_unicorn.rb +37 -0
  44. data/test/test_middleware_unicorn_ipv6.rb +37 -0
  45. data/test/test_raindrops.rb +65 -1
  46. data/test/test_raindrops_gc.rb +23 -1
  47. data/test/test_watcher.rb +85 -0
  48. metadata +69 -22
  49. data/examples/linux-tcp-listener-stats.rb +0 -44
data/pkg.mk ADDED
@@ -0,0 +1,171 @@
1
+ RUBY = ruby
2
+ RAKE = rake
3
+ RSYNC = rsync
4
+ WRONGDOC = wrongdoc
5
+
6
+ GIT-VERSION-FILE: .FORCE-GIT-VERSION-FILE
7
+ @./GIT-VERSION-GEN
8
+ -include GIT-VERSION-FILE
9
+ -include local.mk
10
+ DLEXT := $(shell $(RUBY) -rrbconfig -e 'puts RbConfig::CONFIG["DLEXT"]')
11
+ RUBY_VERSION := $(shell $(RUBY) -e 'puts RUBY_VERSION')
12
+ RUBY_ENGINE := $(shell $(RUBY) -e 'puts((RUBY_ENGINE rescue "ruby"))')
13
+ lib := lib
14
+
15
+ ifeq ($(shell test -f script/isolate_for_tests && echo t),t)
16
+ isolate_libs := tmp/isolate/$(RUBY_ENGINE)-$(RUBY_VERSION)/isolate.mk
17
+ $(isolate_libs): script/isolate_for_tests
18
+ @$(RUBY) script/isolate_for_tests
19
+ -include $(isolate_libs)
20
+ lib := $(lib):$(ISOLATE_LIBS)
21
+ endif
22
+
23
+ ext := $(firstword $(wildcard ext/*))
24
+ ifneq ($(ext),)
25
+ ext_pfx := tmp/ext/$(RUBY_ENGINE)-$(RUBY_VERSION)
26
+ ext_h := $(wildcard $(ext)/*/*.h $(ext)/*.h)
27
+ ext_src := $(wildcard $(ext)/*.c $(ext_h))
28
+ ext_pfx_src := $(addprefix $(ext_pfx)/,$(ext_src))
29
+ ext_d := $(ext_pfx)/$(ext)/.d
30
+ $(ext)/extconf.rb: $(wildcard $(ext)/*.h)
31
+ @>> $@
32
+ $(ext_d):
33
+ @mkdir -p $(@D)
34
+ @> $@
35
+ $(ext_pfx)/$(ext)/%: $(ext)/% $(ext_d)
36
+ install -m 644 $< $@
37
+ $(ext_pfx)/$(ext)/Makefile: $(ext)/extconf.rb $(ext_d) $(ext_h)
38
+ $(RM) -f $(@D)/*.o
39
+ cd $(@D) && $(RUBY) $(CURDIR)/$(ext)/extconf.rb
40
+ ext_sfx := _ext.$(DLEXT)
41
+ ext_dl := $(ext_pfx)/$(ext)/$(notdir $(ext)_ext.$(DLEXT))
42
+ $(ext_dl): $(ext_src) $(ext_pfx_src) $(ext_pfx)/$(ext)/Makefile
43
+ @echo $^ == $@
44
+ $(MAKE) -C $(@D)
45
+ lib := $(lib):$(ext_pfx)/$(ext)
46
+ build: $(ext_dl)
47
+ else
48
+ build:
49
+ endif
50
+
51
+ pkg_extra += GIT-VERSION-FILE NEWS ChangeLog LATEST
52
+ ChangeLog: GIT-VERSION-FILE .wrongdoc.yml
53
+ $(WRONGDOC) prepare
54
+ NEWS LATEST: ChangeLog
55
+
56
+ manifest:
57
+ $(RM) .manifest
58
+ $(MAKE) .manifest
59
+
60
+ .manifest: $(pkg_extra)
61
+ (git ls-files && for i in $@ $(pkg_extra); do echo $$i; done) | \
62
+ LC_ALL=C sort > $@+
63
+ cmp $@+ $@ || mv $@+ $@
64
+ $(RM) $@+
65
+
66
+ doc:: .document .wrongdoc.yml $(pkg_extra)
67
+ -find lib -type f -name '*.rbc' -exec rm -f '{}' ';'
68
+ -find ext -type f -name '*.rbc' -exec rm -f '{}' ';'
69
+ $(RM) -r doc
70
+ $(WRONGDOC) all
71
+ install -m644 COPYING doc/COPYING
72
+ install -m644 $(shell grep '^[A-Z]' .document) doc/
73
+
74
+ ifneq ($(VERSION),)
75
+ pkggem := pkg/$(rfpackage)-$(VERSION).gem
76
+ pkgtgz := pkg/$(rfpackage)-$(VERSION).tgz
77
+ release_notes := release_notes-$(VERSION)
78
+ release_changes := release_changes-$(VERSION)
79
+
80
+ release-notes: $(release_notes)
81
+ release-changes: $(release_changes)
82
+ $(release_changes):
83
+ $(WRONGDOC) release_changes > $@+
84
+ $(VISUAL) $@+ && test -s $@+ && mv $@+ $@
85
+ $(release_notes):
86
+ $(WRONGDOC) release_notes > $@+
87
+ $(VISUAL) $@+ && test -s $@+ && mv $@+ $@
88
+
89
+ # ensures we're actually on the tagged $(VERSION), only used for release
90
+ verify:
91
+ test x"$(shell umask)" = x0022
92
+ git rev-parse --verify refs/tags/v$(VERSION)^{}
93
+ git diff-index --quiet HEAD^0
94
+ test $$(git rev-parse --verify HEAD^0) = \
95
+ $$(git rev-parse --verify refs/tags/v$(VERSION)^{})
96
+
97
+ fix-perms:
98
+ -git ls-tree -r HEAD | awk '/^100644 / {print $$NF}' | xargs chmod 644
99
+ -git ls-tree -r HEAD | awk '/^100755 / {print $$NF}' | xargs chmod 755
100
+
101
+ gem: $(pkggem)
102
+
103
+ install-gem: $(pkggem)
104
+ gem install $(CURDIR)/$<
105
+
106
+ $(pkggem): manifest fix-perms
107
+ gem build $(rfpackage).gemspec
108
+ mkdir -p pkg
109
+ mv $(@F) $@
110
+
111
+ $(pkgtgz): distdir = $(basename $@)
112
+ $(pkgtgz): HEAD = v$(VERSION)
113
+ $(pkgtgz): manifest fix-perms
114
+ @test -n "$(distdir)"
115
+ $(RM) -r $(distdir)
116
+ mkdir -p $(distdir)
117
+ tar cf - $$(cat .manifest) | (cd $(distdir) && tar xf -)
118
+ cd pkg && tar cf - $(basename $(@F)) | gzip -9 > $(@F)+
119
+ mv $@+ $@
120
+
121
+ package: $(pkgtgz) $(pkggem)
122
+
123
+ test-release:: verify package $(release_notes) $(release_changes)
124
+ # make tgz release on RubyForge
125
+ @echo rubyforge add_release -f \
126
+ -n $(release_notes) -a $(release_changes) \
127
+ $(rfproject) $(rfpackage) $(VERSION) $(pkgtgz)
128
+ @echo gem push $(pkggem)
129
+ @echo rubyforge add_file \
130
+ $(rfproject) $(rfpackage) $(VERSION) $(pkggem)
131
+ release:: verify package $(release_notes) $(release_changes)
132
+ # make tgz release on RubyForge
133
+ rubyforge add_release -f -n $(release_notes) -a $(release_changes) \
134
+ $(rfproject) $(rfpackage) $(VERSION) $(pkgtgz)
135
+ # push gem to RubyGems.org
136
+ gem push $(pkggem)
137
+ # in case of gem downloads from RubyForge releases page
138
+ rubyforge add_file \
139
+ $(rfproject) $(rfpackage) $(VERSION) $(pkggem)
140
+ else
141
+ gem install-gem: GIT-VERSION-FILE
142
+ $(MAKE) $@ VERSION=$(GIT_VERSION)
143
+ endif
144
+
145
+ all:: test
146
+ test_units := $(wildcard test/test_*.rb)
147
+ test: test-unit
148
+ test-unit: $(test_units)
149
+ $(test_units): build
150
+ $(RUBY) -I $(lib) $@ $(RUBY_TEST_OPTS)
151
+
152
+ # this requires GNU coreutils variants
153
+ ifneq ($(RSYNC_DEST),)
154
+ publish_doc:
155
+ -git set-file-times
156
+ $(MAKE) doc
157
+ find doc/images -type f | \
158
+ TZ=UTC xargs touch -d '1970-01-01 00:00:06' doc/rdoc.css
159
+ $(MAKE) doc_gz
160
+ $(RSYNC) -av doc/ $(RSYNC_DEST)/
161
+ git ls-files | xargs touch
162
+ endif
163
+
164
+ # Create gzip variants of the same timestamp as the original so nginx
165
+ # "gzip_static on" can serve the gzipped versions directly.
166
+ doc_gz: docs = $(shell find doc -type f ! -regex '^.*\.\(gif\|jpg\|png\|gz\)$$')
167
+ doc_gz:
168
+ for i in $(docs); do \
169
+ gzip --rsyncable -9 < $$i > $$i.gz; touch -r $$i $$i.gz; done
170
+
171
+ .PHONY: all .FORCE-GIT-VERSION-FILE doc test $(test_units) manifest
data/raindrops.gemspec CHANGED
@@ -1,38 +1,28 @@
1
1
  # -*- encoding: binary -*-
2
-
3
2
  ENV["VERSION"] or abort "VERSION= must be specified"
4
3
  manifest = File.readlines('.manifest').map! { |x| x.chomp! }
5
4
  test_files = manifest.grep(%r{\Atest/test_.*\.rb\z})
5
+ require 'wrongdoc'
6
+ extend Wrongdoc::Gemspec
7
+ name, summary, title = readme_metadata
6
8
 
7
9
  Gem::Specification.new do |s|
8
10
  s.name = %q{raindrops}
9
- s.version = ENV["VERSION"]
11
+ s.version = ENV["VERSION"].dup
10
12
 
11
13
  s.authors = ["raindrops hackers"]
12
14
  s.date = Time.now.utc.strftime('%Y-%m-%d')
13
- s.description = File.read("README").split(/\n\n/)[1]
15
+ s.description = readme_description
14
16
  s.email = %q{raindrops@librelist.com}
15
17
  s.extensions = %w(ext/raindrops/extconf.rb)
16
-
17
- s.extra_rdoc_files = File.readlines('.document').map! do |x|
18
- x.chomp!
19
- if File.directory?(x)
20
- manifest.grep(%r{\A#{x}/})
21
- elsif File.file?(x)
22
- x
23
- else
24
- nil
25
- end
26
- end.flatten.compact
27
-
18
+ s.extra_rdoc_files = extra_rdoc_files(manifest)
28
19
  s.files = manifest
29
- s.homepage = %q{http://raindrops.bogomips.org/}
30
- s.summary = %q{real-time stats for preforking Rack servers}
31
- s.rdoc_options = [ "-Na", "-t", "raindrops - #{s.summary}" ]
32
- s.require_paths = %w(lib)
20
+ s.homepage = Wrongdoc.config[:rdoc_url]
21
+ s.summary = summary
22
+ s.rdoc_options = rdoc_options
33
23
  s.rubyforge_project = %q{rainbows}
34
-
35
24
  s.test_files = test_files
25
+ s.add_development_dependency('bundler', '~> 1.0.10')
36
26
 
37
27
  # s.licenses = %w(LGPLv3) # accessor not compatible with older RubyGems
38
28
  end
@@ -0,0 +1,10 @@
1
+ def ipv6_enabled?
2
+ tmp = TCPServer.new(ENV["TEST_HOST6"] || '::1', 0)
3
+ tmp.close
4
+ true
5
+ rescue => e
6
+ warn "skipping IPv6 tests, host does not seem to be IPv6 enabled:"
7
+ warn " #{e.class}: #{e}"
8
+ return false
9
+ ipv6_enabled = false
10
+ end
@@ -0,0 +1,12 @@
1
+ # -*- encoding: binary -*-
2
+ require "test/unit"
3
+ require "raindrops"
4
+ require "rack"
5
+ require "rack/lobster"
6
+ require "open-uri"
7
+ begin
8
+ require "unicorn"
9
+ require "rack/lobster"
10
+ rescue LoadError => e
11
+ warn "W: #{e} skipping test since Rack or Unicorn was not found"
12
+ end
@@ -0,0 +1,65 @@
1
+ require "test/unit"
2
+ require "raindrops"
3
+ pmq = begin
4
+ Raindrops::Aggregate::PMQ
5
+ rescue => LoadError
6
+ warn "W: #{e} skipping test"
7
+ false
8
+ end
9
+ if RUBY_VERSION.to_f < 1.9
10
+ pmq = false
11
+ warn "W: skipping #{__FILE__}, only Ruby 1.9 supported for now"
12
+ end
13
+
14
+ Thread.abort_on_exception = true
15
+
16
+ class TestAggregatePMQ < Test::Unit::TestCase
17
+
18
+ def setup
19
+ @queue = "/test.#{rand}"
20
+ end
21
+
22
+ def teardown
23
+ POSIX_MQ.unlink @queue
24
+ end
25
+
26
+ def test_run
27
+ pmq = Raindrops::Aggregate::PMQ.new :queue => @queue
28
+ thr = Thread.new { pmq.master_loop }
29
+ agg = Aggregate.new
30
+ (1..10).each { |i| pmq << i; agg << i }
31
+ pmq.stop_master_loop
32
+ assert thr.join
33
+ assert_equal agg.count, pmq.count
34
+ assert_equal agg.mean, pmq.mean
35
+ assert_equal agg.std_dev, pmq.std_dev
36
+ assert_equal agg.min, pmq.min
37
+ assert_equal agg.max, pmq.max
38
+ assert_equal agg.to_s, pmq.to_s
39
+ end
40
+
41
+ def test_multi_process
42
+ nr_workers = 4
43
+ nr = 100
44
+ pmq = Raindrops::Aggregate::PMQ.new :queue => @queue
45
+ pid = fork { pmq.master_loop }
46
+ workers = (1..nr_workers).map {
47
+ fork {
48
+ (1..nr).each { |i| pmq << i }
49
+ pmq.flush
50
+ }
51
+ }
52
+ workers.each { |pid| assert Process.waitpid2(pid).last.success? }
53
+ pmq.stop_master_loop
54
+ assert Process.waitpid2(pid).last.success?
55
+ assert_equal 400, pmq.count
56
+ agg = Aggregate.new
57
+ (1..nr_workers).map { (1..nr).each { |i| agg << i } }
58
+ assert_equal agg.to_s, pmq.to_s
59
+ assert_equal agg.mean, pmq.mean
60
+ assert_equal agg.std_dev, pmq.std_dev
61
+ assert_equal agg.min, pmq.min
62
+ assert_equal agg.max, pmq.max
63
+ assert_equal agg.to_s, pmq.to_s
64
+ end
65
+ end if pmq
@@ -0,0 +1,13 @@
1
+ # -*- encoding: binary -*-
2
+ require 'test/unit'
3
+ require 'raindrops'
4
+ $stderr.sync = $stdout.sync = true
5
+
6
+ class TestInetDiagSocket < Test::Unit::TestCase
7
+ def test_new
8
+ sock = Raindrops::InetDiagSocket.new
9
+ assert_kind_of Socket, sock
10
+ assert_kind_of Fixnum, sock.fileno
11
+ assert_nil sock.close
12
+ end
13
+ end if RUBY_PLATFORM =~ /linux/
@@ -0,0 +1,69 @@
1
+ # -*- encoding: binary -*-
2
+ require "./test/rack_unicorn"
3
+ require "tempfile"
4
+ require "net/http"
5
+
6
+ $stderr.sync = $stdout.sync = true
7
+ pmq = begin
8
+ Raindrops::Aggregate::PMQ
9
+ rescue => LoadError
10
+ warn "W: #{e} skipping test"
11
+ false
12
+ end
13
+ if RUBY_VERSION.to_f < 1.9
14
+ pmq = false
15
+ warn "W: skipping test=#{__FILE__}, only Ruby 1.9 supported for now"
16
+ end
17
+
18
+ class TestLastDataRecvUnicorn < Test::Unit::TestCase
19
+ def setup
20
+ @queue = "/test.#{rand}"
21
+ @host = ENV["UNICORN_TEST_ADDR"] || "127.0.0.1"
22
+ @sock = TCPServer.new @host, 0
23
+ @port = @sock.addr[1]
24
+ ENV["UNICORN_FD"] = @sock.fileno.to_s
25
+ @host_with_port = "#@host:#@port"
26
+ @cfg = Tempfile.new 'unicorn_config_file'
27
+ @cfg.puts "require 'raindrops'"
28
+ @cfg.puts "preload_app true"
29
+ ENV['RAINDROPS_MQUEUE'] = @queue
30
+ # @cfg.puts "worker_processes 4"
31
+ @opts = { :listeners => [ @host_with_port ], :config_file => @cfg.path }
32
+ end
33
+
34
+ def test_auto_listener
35
+ @srv = fork {
36
+ Thread.abort_on_exception = true
37
+ app = %q!Rack::Builder.new do
38
+ map("/ldr") { run Raindrops::LastDataRecv.new }
39
+ map("/") { run Rack::Lobster.new }
40
+ end.to_app!
41
+ def app.arity; 0; end
42
+ def app.call; eval self; end
43
+ Unicorn.run(app, @opts)
44
+ }
45
+ 400.times { assert_kind_of Net::HTTPSuccess, get("/") }
46
+ resp = get("/ldr")
47
+ # # p(resp.methods - Object.methods)
48
+ # resp.each_header { |k,v| p [k, "=" , v] }
49
+ assert resp.header["x-count"]
50
+ assert resp.header["x-min"]
51
+ assert resp.header["x-max"]
52
+ assert resp.header["x-mean"]
53
+ assert resp.header["x-std-dev"]
54
+ assert resp.header["x-outliers-low"]
55
+ assert resp.header["x-outliers-high"]
56
+ assert resp.body.size > 0
57
+ end
58
+
59
+ def get(path)
60
+ Net::HTTP.start(@host, @port) { |http| http.get path }
61
+ end
62
+
63
+ def teardown
64
+ Process.kill :QUIT, @srv
65
+ _, status = Process.waitpid2 @srv
66
+ assert status.success?
67
+ POSIX_MQ.unlink @queue
68
+ end
69
+ end if defined?(Unicorn) && RUBY_PLATFORM =~ /linux/ && pmq
data/test/test_linux.rb CHANGED
@@ -39,9 +39,29 @@ class TestLinux < Test::Unit::TestCase
39
39
  assert_equal 1, stats[tmp.path].queued
40
40
  end
41
41
 
42
+ def test_unix_all
43
+ tmp = Tempfile.new("\xde\xad\xbe\xef") # valid path, really :)
44
+ File.unlink(tmp.path)
45
+ us = UNIXServer.new(tmp.path)
46
+ uc0 = UNIXSocket.new(tmp.path)
47
+ stats = unix_listener_stats
48
+ assert_equal 0, stats[tmp.path].active
49
+ assert_equal 1, stats[tmp.path].queued
50
+
51
+ uc1 = UNIXSocket.new(tmp.path)
52
+ stats = unix_listener_stats
53
+ assert_equal 0, stats[tmp.path].active
54
+ assert_equal 2, stats[tmp.path].queued
55
+
56
+ ua0 = us.accept
57
+ stats = unix_listener_stats
58
+ assert_equal 1, stats[tmp.path].active
59
+ assert_equal 1, stats[tmp.path].queued
60
+ end
61
+
42
62
  def test_tcp
43
- port = unused_port
44
- s = TCPServer.new(TEST_ADDR, port)
63
+ s = TCPServer.new(TEST_ADDR, 0)
64
+ port = s.addr[1]
45
65
  addr = "#{TEST_ADDR}:#{port}"
46
66
  addrs = [ addr ]
47
67
  stats = tcp_listener_stats(addrs)
@@ -62,10 +82,36 @@ class TestLinux < Test::Unit::TestCase
62
82
  assert_equal 1, stats[addr].active
63
83
  end
64
84
 
85
+ def test_tcp_reuse_sock
86
+ nlsock = Raindrops::InetDiagSocket.new
87
+ s = TCPServer.new(TEST_ADDR, 0)
88
+ port = s.addr[1]
89
+ addr = "#{TEST_ADDR}:#{port}"
90
+ addrs = [ addr ]
91
+ stats = tcp_listener_stats(addrs, nlsock)
92
+ assert_equal 1, stats.size
93
+ assert_equal 0, stats[addr].queued
94
+ assert_equal 0, stats[addr].active
95
+
96
+ c = TCPSocket.new(TEST_ADDR, port)
97
+ stats = tcp_listener_stats(addrs, nlsock)
98
+ assert_equal 1, stats.size
99
+ assert_equal 1, stats[addr].queued
100
+ assert_equal 0, stats[addr].active
101
+
102
+ sc = s.accept
103
+ stats = tcp_listener_stats(addrs, nlsock)
104
+ assert_equal 1, stats.size
105
+ assert_equal 0, stats[addr].queued
106
+ assert_equal 1, stats[addr].active
107
+ ensure
108
+ nlsock.close
109
+ end
110
+
65
111
  def test_tcp_multi
66
- port1, port2 = unused_port, unused_port
67
- s1 = TCPServer.new(TEST_ADDR, port1)
68
- s2 = TCPServer.new(TEST_ADDR, port2)
112
+ s1 = TCPServer.new(TEST_ADDR, 0)
113
+ s2 = TCPServer.new(TEST_ADDR, 0)
114
+ port1, port2 = s1.addr[1], s2.addr[1]
69
115
  addr1, addr2 = "#{TEST_ADDR}:#{port1}", "#{TEST_ADDR}:#{port2}"
70
116
  addrs = [ addr1, addr2 ]
71
117
  stats = tcp_listener_stats(addrs)
@@ -127,10 +173,10 @@ class TestLinux < Test::Unit::TestCase
127
173
  def test_tcp_stress_test
128
174
  nr_proc = 32
129
175
  nr_sock = 500
130
- port = unused_port
176
+ s = TCPServer.new(TEST_ADDR, 0)
177
+ port = s.addr[1]
131
178
  addr = "#{TEST_ADDR}:#{port}"
132
179
  addrs = [ addr ]
133
- s = TCPServer.new(TEST_ADDR, port)
134
180
  rda, wra = IO.pipe
135
181
  rdb, wrb = IO.pipe
136
182
 
@@ -138,7 +184,7 @@ class TestLinux < Test::Unit::TestCase
138
184
  fork do
139
185
  rda.close
140
186
  wrb.close
141
- socks = (1..nr_sock).times.map { s.accept }
187
+ socks = (1..nr_sock).map { s.accept }
142
188
  wra.syswrite('.')
143
189
  wra.close
144
190
  rdb.sysread(1) # wait for parent to nuke us
@@ -149,7 +195,7 @@ class TestLinux < Test::Unit::TestCase
149
195
  fork do
150
196
  rda.close
151
197
  wrb.close
152
- socks = (1..nr_sock).times.map { TCPSocket.new(TEST_ADDR, port) }
198
+ socks = (1..nr_sock).map { TCPSocket.new(TEST_ADDR, port) }
153
199
  wra.syswrite('.')
154
200
  wra.close
155
201
  rdb.sysread(1) # wait for parent to nuke us
@@ -177,52 +223,4 @@ class TestLinux < Test::Unit::TestCase
177
223
  statuses = Process.waitall
178
224
  statuses.each { |(pid,status)| assert status.success?, status.inspect }
179
225
  end if ENV["STRESS"].to_i != 0
180
-
181
- private
182
-
183
- # Stolen from Unicorn, also a version of this is used by the Rainbows!
184
- # test suite.
185
- # unused_port provides an unused port on +addr+ usable for TCP that is
186
- # guaranteed to be unused across all compatible tests on that system. It
187
- # prevents race conditions by using a lock file other tests
188
- # will see. This is required if you perform several builds in parallel
189
- # with a continuous integration system or run tests in parallel via
190
- # gmake. This is NOT guaranteed to be race-free if you run other
191
- # systems that bind to random ports for testing (but the window
192
- # for a race condition is very small). You may also set UNICORN_TEST_ADDR
193
- # to override the default test address (127.0.0.1).
194
- def unused_port(addr = TEST_ADDR)
195
- retries = 100
196
- base = 5000
197
- port = sock = nil
198
- begin
199
- begin
200
- port = base + rand(32768 - base)
201
- while port == 8080
202
- port = base + rand(32768 - base)
203
- end
204
-
205
- sock = Socket.new(Socket::AF_INET, Socket::SOCK_STREAM, 0)
206
- sock.bind(Socket.pack_sockaddr_in(port, addr))
207
- sock.listen(5)
208
- rescue Errno::EADDRINUSE, Errno::EACCES
209
- sock.close rescue nil
210
- retry if (retries -= 1) >= 0
211
- end
212
-
213
- # since we'll end up closing the random port we just got, there's a race
214
- # condition could allow the random port we just chose to reselect itself
215
- # when running tests in parallel with gmake. Create a lock file while
216
- # we have the port here to ensure that does not happen .
217
- lock_path = "#{Dir::tmpdir}/unicorn_test.#{addr}:#{port}.lock"
218
- lock = File.open(lock_path, File::WRONLY|File::CREAT|File::EXCL, 0600)
219
- at_exit { File.unlink(lock_path) rescue nil }
220
- rescue Errno::EEXIST
221
- sock.close rescue nil
222
- retry
223
- end
224
- sock.close rescue nil
225
- port
226
- end
227
-
228
226
  end if RUBY_PLATFORM =~ /linux/