einhorn 0.7.4 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (52) hide show
  1. checksums.yaml +7 -0
  2. data/Changes.md +10 -0
  3. data/README.md +36 -30
  4. data/bin/einhorn +17 -2
  5. data/einhorn.gemspec +23 -21
  6. data/example/pool_worker.rb +1 -1
  7. data/example/thin_example +8 -8
  8. data/example/time_server +5 -5
  9. data/lib/einhorn/client.rb +8 -9
  10. data/lib/einhorn/command/interface.rb +100 -95
  11. data/lib/einhorn/command.rb +167 -88
  12. data/lib/einhorn/compat.rb +7 -7
  13. data/lib/einhorn/event/abstract_text_descriptor.rb +31 -35
  14. data/lib/einhorn/event/ack_timer.rb +2 -2
  15. data/lib/einhorn/event/command_server.rb +7 -9
  16. data/lib/einhorn/event/connection.rb +1 -3
  17. data/lib/einhorn/event/loop_breaker.rb +2 -1
  18. data/lib/einhorn/event/persistent.rb +2 -2
  19. data/lib/einhorn/event/timer.rb +4 -4
  20. data/lib/einhorn/event.rb +29 -20
  21. data/lib/einhorn/prctl.rb +26 -0
  22. data/lib/einhorn/prctl_linux.rb +48 -0
  23. data/lib/einhorn/safe_yaml.rb +17 -0
  24. data/lib/einhorn/version.rb +1 -1
  25. data/lib/einhorn/worker.rb +67 -49
  26. data/lib/einhorn/worker_pool.rb +9 -9
  27. data/lib/einhorn.rb +155 -126
  28. metadata +42 -137
  29. data/.gitignore +0 -17
  30. data/.travis.yml +0 -10
  31. data/CONTRIBUTORS +0 -6
  32. data/Gemfile +0 -11
  33. data/History.txt +0 -4
  34. data/README.md.in +0 -76
  35. data/Rakefile +0 -27
  36. data/test/_lib.rb +0 -12
  37. data/test/integration/_lib/fixtures/env_printer/env_printer.rb +0 -26
  38. data/test/integration/_lib/fixtures/exit_during_upgrade/exiting_server.rb +0 -22
  39. data/test/integration/_lib/fixtures/exit_during_upgrade/upgrade_reexec.rb +0 -6
  40. data/test/integration/_lib/fixtures/upgrade_project/upgrading_server.rb +0 -22
  41. data/test/integration/_lib/helpers/einhorn_helpers.rb +0 -143
  42. data/test/integration/_lib/helpers.rb +0 -4
  43. data/test/integration/_lib.rb +0 -6
  44. data/test/integration/startup.rb +0 -31
  45. data/test/integration/upgrading.rb +0 -157
  46. data/test/unit/einhorn/client.rb +0 -88
  47. data/test/unit/einhorn/command/interface.rb +0 -49
  48. data/test/unit/einhorn/command.rb +0 -21
  49. data/test/unit/einhorn/event.rb +0 -89
  50. data/test/unit/einhorn/worker_pool.rb +0 -39
  51. data/test/unit/einhorn.rb +0 -58
  52. /data/{LICENSE → LICENSE.txt} +0 -0
metadata CHANGED
@@ -1,149 +1,88 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: einhorn
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.7.4
5
- prerelease:
4
+ version: 1.0.0
6
5
  platform: ruby
7
6
  authors:
8
- - Greg Brockman
9
- autorequire:
7
+ - Stripe
8
+ - Mike Perham
9
+ autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2016-07-13 00:00:00.000000000 Z
12
+ date: 2022-07-14 00:00:00.000000000 Z
13
13
  dependencies:
14
- - !ruby/object:Gem::Dependency
15
- name: rack
16
- requirement: !ruby/object:Gem::Requirement
17
- none: false
18
- requirements:
19
- - - ~>
20
- - !ruby/object:Gem::Version
21
- version: '1.6'
22
- type: :development
23
- prerelease: false
24
- version_requirements: !ruby/object:Gem::Requirement
25
- none: false
26
- requirements:
27
- - - ~>
28
- - !ruby/object:Gem::Version
29
- version: '1.6'
30
14
  - !ruby/object:Gem::Dependency
31
15
  name: rake
32
16
  requirement: !ruby/object:Gem::Requirement
33
- none: false
34
- requirements:
35
- - - ! '>='
36
- - !ruby/object:Gem::Version
37
- version: '0'
38
- type: :development
39
- prerelease: false
40
- version_requirements: !ruby/object:Gem::Requirement
41
- none: false
42
- requirements:
43
- - - ! '>='
44
- - !ruby/object:Gem::Version
45
- version: '0'
46
- - !ruby/object:Gem::Dependency
47
- name: pry
48
- requirement: !ruby/object:Gem::Requirement
49
- none: false
50
17
  requirements:
51
- - - ! '>='
18
+ - - "~>"
52
19
  - !ruby/object:Gem::Version
53
- version: '0'
20
+ version: '13'
54
21
  type: :development
55
22
  prerelease: false
56
23
  version_requirements: !ruby/object:Gem::Requirement
57
- none: false
58
24
  requirements:
59
- - - ! '>='
25
+ - - "~>"
60
26
  - !ruby/object:Gem::Version
61
- version: '0'
27
+ version: '13'
62
28
  - !ruby/object:Gem::Dependency
63
29
  name: minitest
64
30
  requirement: !ruby/object:Gem::Requirement
65
- none: false
66
31
  requirements:
67
- - - <
32
+ - - "~>"
68
33
  - !ruby/object:Gem::Version
69
- version: '5.0'
34
+ version: '5'
70
35
  type: :development
71
36
  prerelease: false
72
37
  version_requirements: !ruby/object:Gem::Requirement
73
- none: false
74
38
  requirements:
75
- - - <
39
+ - - "~>"
76
40
  - !ruby/object:Gem::Version
77
- version: '5.0'
41
+ version: '5'
78
42
  - !ruby/object:Gem::Dependency
79
43
  name: mocha
80
44
  requirement: !ruby/object:Gem::Requirement
81
- none: false
82
- requirements:
83
- - - ~>
84
- - !ruby/object:Gem::Version
85
- version: '0.13'
86
- type: :development
87
- prerelease: false
88
- version_requirements: !ruby/object:Gem::Requirement
89
- none: false
90
- requirements:
91
- - - ~>
92
- - !ruby/object:Gem::Version
93
- version: '0.13'
94
- - !ruby/object:Gem::Dependency
95
- name: chalk-rake
96
- requirement: !ruby/object:Gem::Requirement
97
- none: false
98
45
  requirements:
99
- - - ! '>='
46
+ - - "~>"
100
47
  - !ruby/object:Gem::Version
101
- version: '0'
48
+ version: '1'
102
49
  type: :development
103
50
  prerelease: false
104
51
  version_requirements: !ruby/object:Gem::Requirement
105
- none: false
106
52
  requirements:
107
- - - ! '>='
53
+ - - "~>"
108
54
  - !ruby/object:Gem::Version
109
- version: '0'
55
+ version: '1'
110
56
  - !ruby/object:Gem::Dependency
111
57
  name: subprocess
112
58
  requirement: !ruby/object:Gem::Requirement
113
- none: false
114
59
  requirements:
115
- - - ! '>='
60
+ - - "~>"
116
61
  - !ruby/object:Gem::Version
117
- version: '0'
62
+ version: '1'
118
63
  type: :development
119
64
  prerelease: false
120
65
  version_requirements: !ruby/object:Gem::Requirement
121
- none: false
122
66
  requirements:
123
- - - ! '>='
67
+ - - "~>"
124
68
  - !ruby/object:Gem::Version
125
- version: '0'
69
+ version: '1'
126
70
  description: Einhorn makes it easy to run multiple instances of an application server,
127
71
  all listening on the same port. You can also seamlessly restart your workers without
128
72
  dropping any requests. Einhorn requires minimal application-level support, making
129
73
  it easy to use with an existing project.
130
74
  email:
131
- - gdb@stripe.com
75
+ - support+github@stripe.com
76
+ - mperham@gmail.com
132
77
  executables:
133
78
  - einhorn
134
79
  - einhornsh
135
80
  extensions: []
136
81
  extra_rdoc_files: []
137
82
  files:
138
- - .gitignore
139
- - .travis.yml
140
- - CONTRIBUTORS
141
- - Gemfile
142
- - History.txt
143
- - LICENSE
83
+ - Changes.md
84
+ - LICENSE.txt
144
85
  - README.md
145
- - README.md.in
146
- - Rakefile
147
86
  - bin/einhorn
148
87
  - bin/einhornsh
149
88
  - einhorn.gemspec
@@ -163,71 +102,37 @@ files:
163
102
  - lib/einhorn/event/loop_breaker.rb
164
103
  - lib/einhorn/event/persistent.rb
165
104
  - lib/einhorn/event/timer.rb
105
+ - lib/einhorn/prctl.rb
106
+ - lib/einhorn/prctl_linux.rb
107
+ - lib/einhorn/safe_yaml.rb
166
108
  - lib/einhorn/third.rb
167
109
  - lib/einhorn/version.rb
168
110
  - lib/einhorn/worker.rb
169
111
  - lib/einhorn/worker_pool.rb
170
- - test/_lib.rb
171
- - test/integration/_lib.rb
172
- - test/integration/_lib/fixtures/env_printer/env_printer.rb
173
- - test/integration/_lib/fixtures/exit_during_upgrade/exiting_server.rb
174
- - test/integration/_lib/fixtures/exit_during_upgrade/upgrade_reexec.rb
175
- - test/integration/_lib/fixtures/upgrade_project/upgrading_server.rb
176
- - test/integration/_lib/helpers.rb
177
- - test/integration/_lib/helpers/einhorn_helpers.rb
178
- - test/integration/startup.rb
179
- - test/integration/upgrading.rb
180
- - test/unit/einhorn.rb
181
- - test/unit/einhorn/client.rb
182
- - test/unit/einhorn/command.rb
183
- - test/unit/einhorn/command/interface.rb
184
- - test/unit/einhorn/event.rb
185
- - test/unit/einhorn/worker_pool.rb
186
- homepage: https://github.com/stripe/einhorn
112
+ homepage: https://github.com/contribsys/einhorn
187
113
  licenses:
188
114
  - MIT
189
- post_install_message:
115
+ metadata:
116
+ bug_tracker_uri: https://github.com/contribsys/einhorn/issues
117
+ documentation_uri: https://github.com/contribsys/einhorn/wiki
118
+ changelog_uri: https://github.com/contribsys/einhorn/blob/main/Changes.md
119
+ post_install_message:
190
120
  rdoc_options: []
191
121
  require_paths:
192
122
  - lib
193
123
  required_ruby_version: !ruby/object:Gem::Requirement
194
- none: false
195
124
  requirements:
196
- - - ! '>='
125
+ - - ">="
197
126
  - !ruby/object:Gem::Version
198
- version: '0'
199
- segments:
200
- - 0
201
- hash: 4291999791412545660
127
+ version: 2.5.0
202
128
  required_rubygems_version: !ruby/object:Gem::Requirement
203
- none: false
204
129
  requirements:
205
- - - ! '>='
130
+ - - ">="
206
131
  - !ruby/object:Gem::Version
207
132
  version: '0'
208
- segments:
209
- - 0
210
- hash: 4291999791412545660
211
133
  requirements: []
212
- rubyforge_project:
213
- rubygems_version: 1.8.23
214
- signing_key:
215
- specification_version: 3
216
- summary: ! 'Einhorn: the language-independent shared socket manager'
217
- test_files:
218
- - test/_lib.rb
219
- - test/integration/_lib.rb
220
- - test/integration/_lib/fixtures/env_printer/env_printer.rb
221
- - test/integration/_lib/fixtures/exit_during_upgrade/exiting_server.rb
222
- - test/integration/_lib/fixtures/exit_during_upgrade/upgrade_reexec.rb
223
- - test/integration/_lib/fixtures/upgrade_project/upgrading_server.rb
224
- - test/integration/_lib/helpers.rb
225
- - test/integration/_lib/helpers/einhorn_helpers.rb
226
- - test/integration/startup.rb
227
- - test/integration/upgrading.rb
228
- - test/unit/einhorn.rb
229
- - test/unit/einhorn/client.rb
230
- - test/unit/einhorn/command.rb
231
- - test/unit/einhorn/command/interface.rb
232
- - test/unit/einhorn/event.rb
233
- - test/unit/einhorn/worker_pool.rb
134
+ rubygems_version: 3.2.32
135
+ signing_key:
136
+ specification_version: 4
137
+ summary: 'Einhorn: the language-independent shared socket manager'
138
+ test_files: []
data/.gitignore DELETED
@@ -1,17 +0,0 @@
1
- *.gem
2
- *.rbc
3
- .bundle
4
- .config
5
- .yardoc
6
- Gemfile.lock
7
- InstalledFiles
8
- _yardoc
9
- coverage
10
- doc/
11
- lib/bundler/man
12
- pkg
13
- rdoc
14
- spec/reports
15
- test/tmp
16
- test/version_tmp
17
- tmp
data/.travis.yml DELETED
@@ -1,10 +0,0 @@
1
- language: ruby
2
- rvm:
3
- - 2.0.0
4
- - 2.1
5
- - 2.2
6
-
7
- # This is to work around the version of bundler installed in Travis and
8
- # https://github.com/bundler/bundler/issues/3558
9
- before_install:
10
- - gem update bundler
data/CONTRIBUTORS DELETED
@@ -1,6 +0,0 @@
1
- Greg Brockman <gdb@stripe.com>
2
- Evan Broder <evan@stripe.com>
3
- Nelson Elhage <nelhage@stripe.com>
4
- Paul Hammond <paul@paulhammond.org>
5
- Conrad Irwin <conrad.irwin@gmail.com>
6
- Max Wang <max@stripe.com>
data/Gemfile DELETED
@@ -1,11 +0,0 @@
1
- # Execute bundler hook if present
2
- ['~/.', '/etc/'].any? do |file|
3
- File.lstat(path = File.expand_path(file + 'bundle-gemfile-hook')) rescue next
4
- eval(File.read(path), binding, path); break true
5
- end || source('https://rubygems.org/')
6
-
7
- # Only needed for examples
8
- gem 'thin-attach_socket'
9
-
10
- # Specify your gem's dependencies in einhorn.gemspec
11
- gemspec
data/History.txt DELETED
@@ -1,4 +0,0 @@
1
- === 0.5.0 2013-07-11
2
-
3
- * 1 major enhancement:
4
- * Improve Einhorn protocol to allow multiplexing of commands on a single socket
data/README.md.in DELETED
@@ -1,76 +0,0 @@
1
- # Einhorn: the language-independent shared socket manager
2
-
3
- ![Einhorn](https://stripe.com/img/blog/posts/meet-einhorn/einhorn.png)
4
-
5
- Let's say you have a server process which processes one request at a
6
- time. Your site is becoming increasingly popular, and this one process
7
- is no longer able to handle all of your inbound connections. However,
8
- you notice that your box's load number is low.
9
-
10
- So you start thinking about how to handle more requests. You could
11
- rewrite your server to use threads, but threads are a pain to program
12
- against (and maybe you're writing in Python or Ruby where you don't
13
- have true threads anyway). You could rewrite your server to be
14
- event-driven, but that'd require a ton of effort, and it wouldn't help
15
- you go beyond one core. So instead, you decide to just run multiple
16
- copies of your server process.
17
-
18
- Enter Einhorn. Einhorn makes it easy to run (and keep alive) multiple
19
- copies of a single long-lived process. If that process is a server
20
- listening on some socket, Einhorn will open the socket in the master
21
- process so that it's shared among the workers.
22
-
23
- Einhorn is designed to be compatible with arbitrary languages and
24
- frameworks, requiring minimal modification of your
25
- application. Einhorn is simple to configure and run.
26
-
27
- ## Installation
28
-
29
- Install from Rubygems as:
30
-
31
- $ gem install einhorn
32
-
33
- Or build from source by:
34
-
35
- $ gem build einhorn.gemspec
36
-
37
- And then install the built gem.
38
-
39
- [[usage]]
40
-
41
- ## Contributing
42
-
43
- Contributions are definitely welcome. To contribute, just follow the
44
- usual workflow:
45
-
46
- 1. Fork Einhorn
47
- 2. Create your feature branch (`git checkout -b my-new-feature`)
48
- 3. Commit your changes (`git commit -am 'Added some feature'`)
49
- 4. Push to the branch (`git push origin my-new-feature`)
50
- 5. Create new Github pull request
51
-
52
- ## History
53
-
54
- Einhorn came about when Stripe was investigating seamless code
55
- upgrading solutions for our API worker processes. We really liked the
56
- process model of [Unicorn](http://unicorn.bogomips.org/), but didn't
57
- want to use its HTTP functionality. So Einhorn was born, providing the
58
- master process functionality of Unicorn (and similar preforking
59
- servers) to a wider array of applications.
60
-
61
- See https://stripe.com/blog/meet-einhorn for more background.
62
-
63
- Stripe currently uses Einhorn in production for a number of
64
- services. You can use Conrad Irwin's thin-attach_socket gem along with
65
- EventMachine-LE to support file-descriptor passing. Check out
66
- `example/thin_example` for an example of running Thin under Einhorn.
67
-
68
- ## Compatibility
69
-
70
- Einhorn was developed and tested under Ruby 1.8.7.
71
-
72
- ## About
73
-
74
- Einhorn is a project of [Stripe](https://stripe.com), led by [Greg
75
- Brockman](https://twitter.com/thegdb). Feel free to get in touch at
76
- info@stripe.com.
data/Rakefile DELETED
@@ -1,27 +0,0 @@
1
- #!/usr/bin/env rake
2
- require 'bundler/gem_tasks'
3
- require 'rake/testtask'
4
-
5
- desc 'Rebuild the README with the latest usage from einhorn'
6
- task :readme do
7
- Dir.chdir(File.dirname(__FILE__))
8
- readme = File.read('README.md.in')
9
- usage = `bin/einhorn -h`
10
- readme.gsub!('[[usage]]', usage)
11
- File.open('README.md', 'w') {|f| f.write(readme)}
12
- end
13
-
14
- task :default => :test do
15
- end
16
- require 'bundler/setup'
17
- require 'chalk-rake/gem_tasks'
18
- require 'rake/testtask'
19
-
20
- Rake::TestTask.new do |t|
21
- t.libs = ['lib']
22
- # t.warning = true
23
- t.verbose = true
24
- t.test_files = FileList['test/**/*.rb'].reject do |file|
25
- file.end_with?('_lib.rb') || file.include?('/_lib/')
26
- end
27
- end
data/test/_lib.rb DELETED
@@ -1,12 +0,0 @@
1
- require 'rubygems'
2
- require 'bundler/setup'
3
-
4
- require 'minitest/autorun'
5
- require 'minitest/spec'
6
- require 'mocha/setup'
7
-
8
- class EinhornTestCase < ::MiniTest::Spec
9
- def setup
10
- # Put global stubs here
11
- end
12
- end
@@ -1,26 +0,0 @@
1
- require 'bundler/setup'
2
- require 'socket'
3
- require 'einhorn/worker'
4
-
5
- def einhorn_main
6
- $stderr.puts "Worker starting up!"
7
- serv = Socket.for_fd(ENV['EINHORN_FD_0'].to_i)
8
- $stderr.puts "Worker has a socket"
9
- Einhorn::Worker.ack!
10
- $stderr.puts "Worker sent ack to einhorn"
11
- $stdout.puts "Environment from #{Process.pid} is: #{ENV.inspect}"
12
- while true
13
- s, addrinfo = serv.accept
14
- $stderr.puts "Worker got a socket!"
15
- output = ""
16
- ARGV.each do |variable_to_write|
17
- output += ENV[variable_to_write].to_s
18
- end
19
- s.write(output)
20
- s.flush
21
- s.close
22
- $stderr.puts "Worker closed its socket"
23
- end
24
- end
25
-
26
- einhorn_main if $0 == __FILE__
@@ -1,22 +0,0 @@
1
- require 'bundler/setup'
2
- require 'socket'
3
- require 'einhorn/worker'
4
-
5
- def einhorn_main
6
- serv = Socket.for_fd(Einhorn::Worker.socket!)
7
- Einhorn::Worker.ack!
8
-
9
- Signal.trap('USR2') do
10
- sleep 3
11
- exit!
12
- end
13
-
14
- while true
15
- s, _ = serv.accept
16
- s.write($$)
17
- s.flush
18
- s.close
19
- end
20
- end
21
-
22
- einhorn_main if $0 == __FILE__
@@ -1,6 +0,0 @@
1
- #!/bin/sh
2
-
3
- if [ "$1" = "--with-state-fd" ]; then
4
- sleep 6
5
- fi
6
- exec bundle exec --keep-file-descriptors einhorn "$@"
@@ -1,22 +0,0 @@
1
- require 'bundler/setup'
2
- require 'socket'
3
- require 'einhorn/worker'
4
-
5
- def einhorn_main
6
- version = File.read(File.join(File.dirname(__FILE__), "version"))
7
- $stderr.puts "Worker starting up!"
8
- serv = Socket.for_fd(ENV['EINHORN_FD_0'].to_i)
9
- $stderr.puts "Worker has a socket"
10
- Einhorn::Worker.ack!
11
- $stderr.puts "Worker sent ack to einhorn"
12
- while true
13
- s, addrinfo = serv.accept
14
- $stderr.puts "Worker got a socket!"
15
- s.write(version)
16
- s.flush
17
- s.close
18
- $stderr.puts "Worker closed its socket"
19
- end
20
- end
21
-
22
- einhorn_main if $0 == __FILE__
@@ -1,143 +0,0 @@
1
- require 'subprocess'
2
- require 'timeout'
3
- require 'tmpdir'
4
-
5
- module Helpers
6
- module EinhornHelpers
7
- def einhorn_code_dir
8
- File.expand_path('../../../../', File.dirname(__FILE__))
9
- end
10
-
11
- def default_einhorn_command
12
- cmd = ['bundle', 'exec']
13
- cmd << '--keep-file-descriptors' if RUBY_VERSION >= '2.0'
14
- cmd << File.expand_path('bin/einhorn', einhorn_code_dir)
15
-
16
- cmd
17
- end
18
-
19
- def with_running_einhorn(cmdline, options = {})
20
- options = options.dup
21
- einhorn_command = options.delete(:einhorn_command) { default_einhorn_command }
22
- expected_exit_code = options.delete(:expected_exit_code) { nil }
23
- output_callback = options.delete(:output_callback) { nil }
24
-
25
- stdout, stderr = "", ""
26
- communicator = nil
27
- process = Bundler.with_clean_env do
28
- default_options = {
29
- :stdout => Subprocess::PIPE,
30
- :stderr => Subprocess::PIPE,
31
- :stdin => '/dev/null',
32
- :cwd => einhorn_code_dir
33
- }
34
- Subprocess::Process.new(Array(einhorn_command) + cmdline, default_options.merge(options))
35
- end
36
-
37
- status = nil
38
- begin
39
- communicator = Thread.new do
40
- begin
41
- stdout, stderr = process.communicate
42
- rescue Errno::ECHILD
43
- # It's dead, and we're not getting anything. This is peaceful.
44
- end
45
- end
46
- yield(process) if block_given?
47
- rescue
48
- unless (status = process.poll) && status.exited?
49
- process.terminate
50
- end
51
- raise
52
- ensure
53
- unless (status = process.poll) && status.exited?
54
- for i in 1..10 do
55
- status = process.poll
56
- if status && status.exited?
57
- break
58
- end
59
- sleep(1)
60
- end
61
- unless status && status.exited?
62
- $stderr.puts "Could not get Einhorn to quit within 10 seconds, killing it forcefully..."
63
- process.send_signal("KILL")
64
- status = process.wait
65
- end
66
- end
67
- communicator.join
68
- output_callback.call(stdout, stderr) if output_callback
69
- end
70
- end
71
-
72
- def einhornsh(commandline, options = {})
73
- Subprocess.check_call(%W{bundle exec #{File.expand_path('bin/einhornsh')}} + commandline,
74
- {
75
- :stdin => '/dev/null',
76
- :stdout => '/dev/null',
77
- :stderr => '/dev/null'
78
- }.merge(options))
79
- end
80
-
81
- def fixture_path(name)
82
- File.expand_path(File.join('../fixtures', name), File.dirname(__FILE__))
83
- end
84
-
85
- # Creates a new temporary directory with the initial contents from
86
- # test/integration/_lib/fixtures/{name} and returns the path to
87
- # it. The contents of this directory are temporary and can be
88
- # safely overwritten.
89
- def prepare_fixture_directory(name)
90
- @fixtured_dirs ||= Set.new
91
- new_dir = Dir.mktmpdir(name)
92
- @fixtured_dirs << new_dir
93
- FileUtils.cp_r(File.join(fixture_path(name), '.'), new_dir, :preserve => true)
94
-
95
- new_dir
96
- end
97
-
98
- def cleanup_fixtured_directories
99
- (@fixtured_dirs || []).each { |dir| FileUtils.rm_rf(dir) }
100
- end
101
-
102
- def find_free_port(host='127.0.0.1')
103
- open_port = TCPServer.new(host, 0)
104
- open_port.addr[1]
105
- ensure
106
- open_port.close
107
- end
108
-
109
- def wait_for_open_port
110
- max_retries = 50
111
- begin
112
- read_from_port
113
- rescue Errno::ECONNREFUSED
114
- max_retries -= 1
115
- if max_retries <= 0
116
- raise
117
- else
118
- sleep 0.1
119
- retry
120
- end
121
- end
122
- end
123
-
124
-
125
- def read_from_port
126
- ewouldblock = RUBY_VERSION >= '1.9.0' ? IO::WaitWritable : Errno::EINPROGRESS
127
- socket = Socket.new(Socket::PF_INET, Socket::SOCK_STREAM, 0)
128
- sockaddr = Socket.pack_sockaddr_in(@port, '127.0.0.1')
129
- begin
130
- socket.connect_nonblock(sockaddr)
131
- rescue ewouldblock
132
- IO.select(nil, [socket], [], 5)
133
- begin
134
- socket.connect_nonblock(sockaddr)
135
- rescue Errno::EISCONN
136
- end
137
- end
138
- socket.read.chomp
139
- ensure
140
- socket.close if socket
141
- end
142
- end
143
- end
@@ -1,4 +0,0 @@
1
- module Helpers
2
- end
3
-
4
- require(File.expand_path('helpers/einhorn_helpers', File.dirname(__FILE__)))
@@ -1,6 +0,0 @@
1
- require(File.expand_path('../_lib', File.dirname(__FILE__)))
2
- require(File.expand_path('_lib/helpers', File.dirname(__FILE__)))
3
-
4
- class EinhornIntegrationTestCase < EinhornTestCase
5
-
6
- end