yahns 0.0.0 → 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -12,45 +12,51 @@ class TestConfig < Testcase
12
12
  end
13
13
 
14
14
  def test_multi_conf_example
15
- tmpdir = Dir.mktmpdir
15
+ pid = fork do
16
+ tmpdir = Dir.mktmpdir
16
17
 
17
- # modify the example config file for testing
18
- path = "examples/yahns_multi.conf.rb"
19
- cfgs = File.read(path)
20
- cfgs.gsub!(%r{/path/to/}, "#{tmpdir}/")
21
- conf = File.open("#{tmpdir}/yahns_multi.conf.rb", "w")
22
- conf.sync = true
23
- conf.write(cfgs)
24
- File.open("#{tmpdir}/another.ru", "w") do |fp|
25
- fp.puts("run Rack::Lobster.new\n")
26
- end
27
- FileUtils.mkpath("#{tmpdir}/another")
18
+ # modify the example config file for testing
19
+ path = "examples/yahns_multi.conf.rb"
20
+ cfgs = File.read(path)
21
+ cfgs.gsub!(%r{/path/to/}, "#{tmpdir}/")
22
+ conf = File.open("#{tmpdir}/yahns_multi.conf.rb", "w")
23
+ conf.sync = true
24
+ conf.write(cfgs)
25
+ File.open("#{tmpdir}/another.ru", "w") do |fp|
26
+ fp.puts("run Rack::Lobster.new\n")
27
+ end
28
+ FileUtils.mkpath("#{tmpdir}/another")
28
29
 
29
- cfg = GTL.synchronize { Yahns::Config.new(conf.path) }
30
- assert_instance_of Yahns::Config, cfg
31
- ensure
32
- FileUtils.rm_rf(tmpdir) if tmpdir
30
+ cfg = Yahns::Config.new(conf.path)
31
+ FileUtils.rm_rf(tmpdir)
32
+ exit!(Yahns::Config === cfg)
33
+ end
34
+ _, status = Process.waitpid2(pid)
35
+ assert status.success?
33
36
  end
34
37
 
35
38
  def test_rack_basic_conf_example
36
- tmpdir = Dir.mktmpdir
39
+ pid = fork do
40
+ tmpdir = Dir.mktmpdir
37
41
 
38
- # modify the example config file for testing
39
- path = "examples/yahns_rack_basic.conf.rb"
40
- cfgs = File.read(path)
41
- cfgs.gsub!(%r{/path/to/}, "#{tmpdir}/")
42
- Dir.mkdir("#{tmpdir}/my_app")
43
- Dir.mkdir("#{tmpdir}/my_logs")
44
- Dir.mkdir("#{tmpdir}/my_pids")
45
- conf = File.open("#{tmpdir}/yahns_rack_basic.conf.rb", "w")
46
- conf.sync = true
47
- conf.write(cfgs)
48
- File.open("#{tmpdir}/my_app/config.ru", "w") do |fp|
49
- fp.puts("run Rack::Lobster.new\n")
42
+ # modify the example config file for testing
43
+ path = "examples/yahns_rack_basic.conf.rb"
44
+ cfgs = File.read(path)
45
+ cfgs.gsub!(%r{/path/to/}, "#{tmpdir}/")
46
+ Dir.mkdir("#{tmpdir}/my_app")
47
+ Dir.mkdir("#{tmpdir}/my_logs")
48
+ Dir.mkdir("#{tmpdir}/my_pids")
49
+ conf = File.open("#{tmpdir}/yahns_rack_basic.conf.rb", "w")
50
+ conf.sync = true
51
+ conf.write(cfgs)
52
+ File.open("#{tmpdir}/my_app/config.ru", "w") do |fp|
53
+ fp.puts("run Rack::Lobster.new\n")
54
+ end
55
+ cfg = Yahns::Config.new(conf.path)
56
+ FileUtils.rm_rf(tmpdir) if tmpdir
57
+ exit!(Yahns::Config === cfg)
50
58
  end
51
- cfg = GTL.synchronize { Yahns::Config.new(conf.path) }
52
- assert_instance_of Yahns::Config, cfg
53
- ensure
54
- FileUtils.rm_rf(tmpdir) if tmpdir
59
+ _, status = Process.waitpid2(pid)
60
+ assert status.success?
55
61
  end
56
62
  end
@@ -0,0 +1,74 @@
1
+ # Copyright (C) 2013, Eric Wong <normalperson@yhbt.net> and all contributors
2
+ # License: GPLv3 or later (https://www.gnu.org/licenses/gpl-3.0.txt)
3
+ require_relative 'server_helper'
4
+
5
+ class TestRackHijack < Testcase
6
+ parallelize_me!
7
+ include ServerHelper
8
+ alias setup server_helper_setup
9
+ alias teardown server_helper_teardown
10
+
11
+ class DieIfUsed
12
+ def each
13
+ abort "body.each called after response hijack\n"
14
+ end
15
+
16
+ def close
17
+ abort "body.close called after response hijack\n"
18
+ end
19
+ end
20
+
21
+ HIJACK_APP = lambda { |env|
22
+ case env["PATH_INFO"]
23
+ when "/hijack_req"
24
+ io = env["rack.hijack"].call
25
+ if io.respond_to?(:read_nonblock) &&
26
+ env["rack.hijack_io"].respond_to?(:read_nonblock)
27
+
28
+ # exercise both, since we Rack::Lint may use different objects
29
+ env["rack.hijack_io"].write("HTTP/1.0 200 OK\r\n\r\n")
30
+ io.write("request.hijacked")
31
+ io.close
32
+ return [ 500, {}, DieIfUsed.new ]
33
+ end
34
+ [ 500, {}, [ "hijack BAD\n" ] ]
35
+ when "/hijack_res"
36
+ r = "response.hijacked"
37
+ [ 200,
38
+ {
39
+ "X-Test" => "zzz",
40
+ "Content-Length" => r.bytesize.to_s,
41
+ "rack.hijack" => proc { |x| x.write(r); x.close }
42
+ },
43
+ DieIfUsed.new
44
+ ]
45
+ end
46
+ }
47
+
48
+ def test_hijack
49
+ err = @err
50
+ cfg = Yahns::Config.new
51
+ host, port = @srv.addr[3], @srv.addr[1]
52
+ cfg.instance_eval do
53
+ GTL.synchronize { app(:rack, HIJACK_APP) { listen "#{host}:#{port}" } }
54
+ logger(Logger.new(err.path))
55
+ end
56
+ srv = Yahns::Server.new(cfg)
57
+ pid = fork do
58
+ ENV["YAHNS_FD"] = @srv.fileno.to_s
59
+ srv.start.join
60
+ end
61
+ res = Net::HTTP.start(host, port) { |h| h.get("/hijack_req") }
62
+ assert_equal "request.hijacked", res.body
63
+ assert_equal 200, res.code.to_i
64
+ assert_equal "1.0", res.http_version
65
+
66
+ res = Net::HTTP.start(host, port) { |h| h.get("/hijack_res") }
67
+ assert_equal "response.hijacked", res.body
68
+ assert_equal 200, res.code.to_i
69
+ assert_equal "zzz", res["X-Test"]
70
+ assert_equal "1.1", res.http_version
71
+ ensure
72
+ quit_wait(pid)
73
+ end
74
+ end
@@ -0,0 +1,64 @@
1
+ # Copyright (C) 2013, Eric Wong <normalperson@yhbt.net> and all contributors
2
+ # License: GPLv3 or later (https://www.gnu.org/licenses/gpl-3.0.txt)
3
+ require_relative 'server_helper'
4
+ require 'rack/commonlogger'
5
+
6
+ class TestReopenLogs < Testcase
7
+ parallelize_me!
8
+ include ServerHelper
9
+ alias setup server_helper_setup
10
+ alias teardown server_helper_teardown
11
+
12
+ def test_reopen_logs_noworker; reopen(false); end
13
+ def test_reopen_logs_worker; reopen(true); end
14
+
15
+ def reopen(worker)
16
+ err = @err
17
+ out = tmpfile(%w(log .out))
18
+ opath = out.path
19
+ cfg = Yahns::Config.new
20
+ host, port = @srv.addr[3], @srv.addr[1]
21
+ cfg.instance_eval do
22
+ stderr_path err.path
23
+ stdout_path opath
24
+ GTL.synchronize do
25
+ app = Rack::Builder.new do
26
+ use Rack::CommonLogger, $stdout
27
+ use Rack::ContentLength
28
+ use Rack::ContentType, "text/plain"
29
+ run lambda { |_| [ 200, {}, [ "#$$" ] ] }
30
+ end
31
+ app(:rack, app.to_app) { listen "#{host}:#{port}" }
32
+ end
33
+ worker_processes 1 if worker
34
+ end
35
+ pid = fork do
36
+ ENV["YAHNS_FD"] = @srv.fileno.to_s
37
+ Yahns::Server.new(cfg).start.join
38
+ end
39
+ Net::HTTP.start(host, port) do |http|
40
+ res = http.request(Net::HTTP::Get.new("/aaa"))
41
+ assert_equal 200, res.code.to_i
42
+ orig = res.body
43
+ Timeout.timeout(10) { Thread.pass until File.read(opath) =~ /aaa/ }
44
+ File.unlink(opath)
45
+ Process.kill(:USR1, pid)
46
+ Timeout.timeout(10) { sleep(0.01) until File.exist?(opath) }
47
+
48
+ # we need to repeat the HTTP request since the worker_processes
49
+ # may not have switched to the new file, yet.
50
+ Timeout.timeout(10) do
51
+ begin
52
+ res = http.request(Net::HTTP::Get.new("/bbb"))
53
+ assert_equal 200, res.code.to_i
54
+ assert_equal orig, res.body
55
+ end until File.read(opath) =~ /bbb/
56
+ end
57
+ end
58
+ rescue => e
59
+ Yahns::Log.exception(Logger.new($stderr), "test", e)
60
+ raise
61
+ ensure
62
+ quit_wait(pid)
63
+ end
64
+ end
@@ -51,8 +51,11 @@ class TestServer < Testcase
51
51
  end
52
52
  end
53
53
  Process.kill(:QUIT, pid)
54
- "GET / HTTP/1.1\r\n\r\n".each_byte { |x| Thread.pass; c.write(x.chr) }
55
- buf = Timeout.timeout(10) { c.read }
54
+ "GET / HTTP/1.1\r\nHost: example.com\r\n\r\n".each_byte do |x|
55
+ sleep(0.01)
56
+ c.write(x.chr)
57
+ end
58
+ buf = Timeout.timeout(30) { c.read }
56
59
  assert_match(/Connection: close/, buf)
57
60
  _, status = Timeout.timeout(10) { Process.waitpid2(pid) }
58
61
  assert status.success?, status.inspect
@@ -287,6 +290,7 @@ class TestServer < Testcase
287
290
 
288
291
  # Linux blocking accept() has fair behavior between multiple tasks
289
292
  def test_mp_balance
293
+ skip("this fails occasionally on Linux, still...")
290
294
  skip("linux-only test") unless RUBY_PLATFORM =~ /linux/
291
295
  pid, host, port = new_mp_server(2)
292
296
  seen = {}
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: yahns
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.0
4
+ version: 0.0.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - yahns hackers
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2013-10-18 00:00:00.000000000 Z
11
+ date: 2013-10-20 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: kgio
@@ -96,6 +96,7 @@ files:
96
96
  - examples/yahns_rack_basic.conf.rb
97
97
  - lib/yahns.rb
98
98
  - lib/yahns/acceptor.rb
99
+ - lib/yahns/cap_input.rb
99
100
  - lib/yahns/client_expire.rb
100
101
  - lib/yahns/client_expire_portable.rb
101
102
  - lib/yahns/config.rb
@@ -105,6 +106,9 @@ files:
105
106
  - lib/yahns/http_context.rb
106
107
  - lib/yahns/http_response.rb
107
108
  - lib/yahns/log.rb
109
+ - lib/yahns/max_body.rb
110
+ - lib/yahns/max_body/rewindable_wrapper.rb
111
+ - lib/yahns/max_body/wrapper.rb
108
112
  - lib/yahns/queue.rb
109
113
  - lib/yahns/queue_egg.rb
110
114
  - lib/yahns/queue_epoll.rb
@@ -128,11 +132,13 @@ files:
128
132
  - test/server_helper.rb
129
133
  - test/test_bin.rb
130
134
  - test/test_client_expire.rb
135
+ - test/test_client_max_body_size.rb
131
136
  - test/test_config.rb
132
137
  - test/test_fdmap.rb
133
138
  - test/test_output_buffering.rb
134
- - test/test_queue.rb
135
139
  - test/test_rack.rb
140
+ - test/test_rack_hijack.rb
141
+ - test/test_reopen_logs.rb
136
142
  - test/test_serve_static.rb
137
143
  - test/test_server.rb
138
144
  - test/test_stream_file.rb
@@ -158,7 +164,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
158
164
  version: '0'
159
165
  requirements: []
160
166
  rubyforge_project:
161
- rubygems_version: 2.1.9
167
+ rubygems_version: 2.1.3
162
168
  signing_key:
163
169
  specification_version: 4
164
170
  summary: sleepy, multi-threaded, non-blocking application server
@@ -1,59 +0,0 @@
1
- # Copyright (C) 2013, Eric Wong <normalperson@yhbt.net> and all contributors
2
- # License: GPLv3 or later (https://www.gnu.org/licenses/gpl-3.0.txt)
3
- require_relative 'helper'
4
- require 'timeout'
5
- require 'stringio'
6
-
7
- class TestQueue < Testcase
8
- parallelize_me!
9
-
10
- def setup
11
- @q = Yahns::Queue.new
12
- @err = StringIO.new
13
- @logger = Logger.new(@err)
14
- @q.fdmap = @fdmap = Yahns::Fdmap.new(@logger, 0.5)
15
- assert @q.close_on_exec?
16
- end
17
-
18
- def test_queue
19
- r, w = IO.pipe
20
- assert_equal 0, @fdmap.size
21
- @q.queue_add(r, Yahns::Queue::QEV_RD)
22
- assert_equal 1, @fdmap.size
23
- def r.yahns_step
24
- begin
25
- case read_nonblock(11)
26
- when "delete"
27
- return :delete
28
- end
29
- rescue Errno::EAGAIN
30
- return :wait_readable
31
- rescue EOFError
32
- return nil
33
- end while true
34
- end
35
- w.write('.')
36
- Timeout.timeout(10) do
37
- Thread.pass until r.nread > 0
38
- @q.spawn_worker_threads(@logger, 1, 1)
39
- Thread.pass until r.nread == 0
40
-
41
- w.write("delete")
42
- Thread.pass until r.nread == 0
43
- Thread.pass until @fdmap.size == 0
44
-
45
- # should not raise
46
- @q.queue_add(r, Yahns::Queue::QEV_RD)
47
- assert_equal 1, @fdmap.size
48
- w.close
49
- Thread.pass until @fdmap.size == 0
50
- end
51
- assert r.closed?
52
- ensure
53
- [ r, w ].each { |io| io.close unless io.closed? }
54
- end
55
-
56
- def teardown
57
- @q.close
58
- end
59
- end