realweb 0.1.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.
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
+