realweb 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/LICENSE +20 -0
- data/README.rdoc +24 -0
- data/lib/realweb.rb +24 -0
- data/lib/realweb/forking_server.rb +32 -0
- data/lib/realweb/in_thread_server.rb +22 -0
- data/lib/realweb/server.rb +109 -0
- metadata +90 -0
data/LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2009 geemus (Wesley Beary)
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.rdoc
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
= RealWeb
|
2
|
+
|
3
|
+
Boot a rack app in a thread or process to use as a real test endpoint.
|
4
|
+
|
5
|
+
=== Usage
|
6
|
+
|
7
|
+
before(:each) do
|
8
|
+
@server = RealWeb.start_server("path/to/config.ru")
|
9
|
+
end
|
10
|
+
|
11
|
+
after(:each) do
|
12
|
+
@server.stop
|
13
|
+
end
|
14
|
+
|
15
|
+
it "runs some action that would normally hit the api" do
|
16
|
+
MyLibrary.get_list_of_things(@server.base_uri)
|
17
|
+
end
|
18
|
+
|
19
|
+
|
20
|
+
RealWeb.start_server boots the given config.ru in a thread. When you call stop on the server object, the server is killed.
|
21
|
+
|
22
|
+
You can specifically use a Process.fork server with start_server_in_fork.
|
23
|
+
|
24
|
+
RealWeb uses WEBrick for its pure ruby server. No extra dependencies or C extensions.
|
data/lib/realweb.rb
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
require 'realweb/in_thread_server'
|
2
|
+
require 'realweb/forking_server'
|
3
|
+
|
4
|
+
module RealWeb
|
5
|
+
class << self
|
6
|
+
def start_server_in_thread(*args)
|
7
|
+
InThreadServer.new(*args) { |server| server.start }
|
8
|
+
end
|
9
|
+
alias start_server start_server_in_thread
|
10
|
+
|
11
|
+
def start_server_in_fork(*args)
|
12
|
+
ForkingServer.new(*args) { |server| server.start }
|
13
|
+
end
|
14
|
+
|
15
|
+
def with_server_in_thread(*args, &block)
|
16
|
+
InThreadServer.with_rackup(*args, &block)
|
17
|
+
end
|
18
|
+
alias with_server with_server_in_thread
|
19
|
+
|
20
|
+
def with_server_in_fork(*args, &block)
|
21
|
+
ForkingServer.with_rackup(*args, &block)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
require 'realweb/server'
|
2
|
+
|
3
|
+
module RealWeb
|
4
|
+
class ForkingServer < Server
|
5
|
+
|
6
|
+
def stop
|
7
|
+
kill_pid
|
8
|
+
super
|
9
|
+
end
|
10
|
+
|
11
|
+
protected
|
12
|
+
|
13
|
+
def kill_pid
|
14
|
+
return unless @pid
|
15
|
+
Process.kill 'INT', @pid
|
16
|
+
Process.kill 'TERM', @pid
|
17
|
+
Process.wait @pid
|
18
|
+
rescue
|
19
|
+
# noop
|
20
|
+
ensure
|
21
|
+
@pid = nil
|
22
|
+
end
|
23
|
+
|
24
|
+
def spawn_server
|
25
|
+
@pid ||= Process.fork do
|
26
|
+
boot_rack_server do |webrick_server|
|
27
|
+
trap(:TERM) { webrick_server.shutdown; exit!(0) }
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
require 'realweb/server'
|
2
|
+
|
3
|
+
module RealWeb
|
4
|
+
class InThreadServer < Server
|
5
|
+
|
6
|
+
def stop
|
7
|
+
@thread[:kill_server].call
|
8
|
+
@thread.kill
|
9
|
+
super
|
10
|
+
end
|
11
|
+
|
12
|
+
protected
|
13
|
+
|
14
|
+
def spawn_server
|
15
|
+
@thread ||= Thread.new do
|
16
|
+
boot_rack_server do |webrick_server|
|
17
|
+
Thread.current[:kill_server] = lambda { webrick_server.shutdown }
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,109 @@
|
|
1
|
+
require 'rack'
|
2
|
+
require 'webrick'
|
3
|
+
require 'stringio'
|
4
|
+
require 'logger'
|
5
|
+
require 'open-uri'
|
6
|
+
|
7
|
+
module RealWeb
|
8
|
+
class Server
|
9
|
+
DEFAULT_PORT_RANGE = 8000..10000
|
10
|
+
|
11
|
+
def self.with_rackup(*args)
|
12
|
+
new(*args) do |server|
|
13
|
+
server.start
|
14
|
+
yield server if block_given?
|
15
|
+
server.stop
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
attr_reader :port
|
20
|
+
|
21
|
+
def initialize(config_ru, pre_spawn_callback = nil, port_range = DEFAULT_PORT_RANGE)
|
22
|
+
@config_ru, @pre_spawn_callback, @port_range = config_ru, pre_spawn_callback, port_range
|
23
|
+
@running = false
|
24
|
+
yield self if block_given?
|
25
|
+
end
|
26
|
+
|
27
|
+
def running?
|
28
|
+
@running
|
29
|
+
end
|
30
|
+
|
31
|
+
def start
|
32
|
+
return if running?
|
33
|
+
find_port
|
34
|
+
run_pre_spawn
|
35
|
+
spawn_server
|
36
|
+
at_exit { stop }
|
37
|
+
wait_for_server
|
38
|
+
@running = true
|
39
|
+
end
|
40
|
+
|
41
|
+
def stop
|
42
|
+
@running = false
|
43
|
+
end
|
44
|
+
|
45
|
+
def host
|
46
|
+
"127.0.0.1"
|
47
|
+
end
|
48
|
+
|
49
|
+
def base_uri
|
50
|
+
URI.parse("http://#{host}:#{@port}/")
|
51
|
+
end
|
52
|
+
|
53
|
+
protected
|
54
|
+
|
55
|
+
def find_port
|
56
|
+
return if @port
|
57
|
+
begin
|
58
|
+
@port = random_port
|
59
|
+
end while system("lsof -i tcp:#{@port} > /dev/null")
|
60
|
+
end
|
61
|
+
|
62
|
+
def random_port
|
63
|
+
@port_range.to_a[rand(@port_range.to_a.size)]
|
64
|
+
end
|
65
|
+
|
66
|
+
def run_pre_spawn
|
67
|
+
@pre_spawn_callback.call(self) if @pre_spawn_callback
|
68
|
+
end
|
69
|
+
|
70
|
+
def spawn_server
|
71
|
+
raise "Not implemented"
|
72
|
+
end
|
73
|
+
|
74
|
+
# hack around Rack::Server not yielding the real server
|
75
|
+
def boot_rack_server(&block)
|
76
|
+
begin
|
77
|
+
rack_server = Rack::Server.new(
|
78
|
+
:Port => @port,
|
79
|
+
:config => @config_ru,
|
80
|
+
:server => 'webrick',
|
81
|
+
:Logger => Logger.new(StringIO.new), # quiet webrick
|
82
|
+
:AccessLog => [ StringIO.new, WEBrick::AccessLog::COMMON_LOG_FORMAT ]
|
83
|
+
)
|
84
|
+
webrick_handler = rack_server.server
|
85
|
+
wrapped_app = rack_server.send(:wrapped_app)
|
86
|
+
webrick_handler.run(wrapped_app, rack_server.options, &block)
|
87
|
+
rescue
|
88
|
+
$stderr.puts "Failed to start server"
|
89
|
+
$stderr.puts $!.inspect
|
90
|
+
$stderr.puts $!.backtrace
|
91
|
+
abort
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
def wait_for_server
|
96
|
+
10.times do
|
97
|
+
begin
|
98
|
+
sleep 0.5
|
99
|
+
open(base_uri)
|
100
|
+
return
|
101
|
+
rescue Errno::ECONNREFUSED
|
102
|
+
puts "Connection refused; retrying..."
|
103
|
+
sleep 0.5
|
104
|
+
end
|
105
|
+
end
|
106
|
+
abort "Unable to reach RealWeb server: Problem booting #{@config_ru}"
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
metadata
ADDED
@@ -0,0 +1,90 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: realweb
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
hash: 27
|
5
|
+
prerelease: false
|
6
|
+
segments:
|
7
|
+
- 0
|
8
|
+
- 1
|
9
|
+
- 0
|
10
|
+
version: 0.1.0
|
11
|
+
platform: ruby
|
12
|
+
authors:
|
13
|
+
- Ben Burkert
|
14
|
+
- Martin Emde
|
15
|
+
- Sam Merritt
|
16
|
+
autorequire:
|
17
|
+
bindir: bin
|
18
|
+
cert_chain: []
|
19
|
+
|
20
|
+
date: 2010-05-28 00:00:00 -07:00
|
21
|
+
default_executable:
|
22
|
+
dependencies:
|
23
|
+
- !ruby/object:Gem::Dependency
|
24
|
+
prerelease: false
|
25
|
+
version_requirements: &id001 !ruby/object:Gem::Requirement
|
26
|
+
none: false
|
27
|
+
requirements:
|
28
|
+
- - ">="
|
29
|
+
- !ruby/object:Gem::Version
|
30
|
+
hash: 19
|
31
|
+
segments:
|
32
|
+
- 1
|
33
|
+
- 1
|
34
|
+
- 0
|
35
|
+
version: 1.1.0
|
36
|
+
requirement: *id001
|
37
|
+
type: :runtime
|
38
|
+
name: rack
|
39
|
+
description: Easily runs a rack app for tests that hit web APIs
|
40
|
+
email: cloud-engineering@engineyard.com
|
41
|
+
executables: []
|
42
|
+
|
43
|
+
extensions: []
|
44
|
+
|
45
|
+
extra_rdoc_files:
|
46
|
+
- README.rdoc
|
47
|
+
- LICENSE
|
48
|
+
files:
|
49
|
+
- lib/realweb/forking_server.rb
|
50
|
+
- lib/realweb/in_thread_server.rb
|
51
|
+
- lib/realweb/server.rb
|
52
|
+
- lib/realweb.rb
|
53
|
+
- README.rdoc
|
54
|
+
- LICENSE
|
55
|
+
has_rdoc: true
|
56
|
+
homepage: http://github.com/engineyard/realweb
|
57
|
+
licenses: []
|
58
|
+
|
59
|
+
post_install_message:
|
60
|
+
rdoc_options: []
|
61
|
+
|
62
|
+
require_paths:
|
63
|
+
- lib
|
64
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
65
|
+
none: false
|
66
|
+
requirements:
|
67
|
+
- - ">="
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
hash: 3
|
70
|
+
segments:
|
71
|
+
- 0
|
72
|
+
version: "0"
|
73
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
74
|
+
none: false
|
75
|
+
requirements:
|
76
|
+
- - ">="
|
77
|
+
- !ruby/object:Gem::Version
|
78
|
+
hash: 3
|
79
|
+
segments:
|
80
|
+
- 0
|
81
|
+
version: "0"
|
82
|
+
requirements: []
|
83
|
+
|
84
|
+
rubyforge_project:
|
85
|
+
rubygems_version: 1.3.7
|
86
|
+
signing_key:
|
87
|
+
specification_version: 3
|
88
|
+
summary: Easily runs a rack app for tests that hit web APIs
|
89
|
+
test_files: []
|
90
|
+
|