unicorn 0.96.1 → 0.97.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +1 -0
- data/Documentation/unicorn_rails.1.txt +6 -1
- data/FAQ +7 -0
- data/GIT-VERSION-GEN +1 -1
- data/GNUmakefile +6 -8
- data/KNOWN_ISSUES +8 -0
- data/Rakefile +1 -4
- data/TODO +1 -6
- data/bin/unicorn +4 -42
- data/bin/unicorn_rails +65 -68
- data/examples/init.sh +7 -2
- data/examples/logger_mp_safe.rb +25 -0
- data/ext/unicorn_http/CFLAGS +13 -0
- data/ext/unicorn_http/c_util.h +13 -0
- data/ext/unicorn_http/common_field_optimization.h +3 -3
- data/ext/unicorn_http/ext_help.h +2 -2
- data/ext/unicorn_http/global_variables.h +1 -3
- data/ext/unicorn_http/unicorn_http.rl +15 -13
- data/lib/unicorn.rb +64 -12
- data/lib/unicorn/configurator.rb +19 -1
- data/lib/unicorn/const.rb +4 -7
- data/lib/unicorn/http_request.rb +1 -1
- data/lib/unicorn/tee_input.rb +39 -39
- data/lib/unicorn/util.rb +1 -2
- data/t/.gitignore +2 -0
- data/t/GNUmakefile +67 -0
- data/t/README +42 -0
- data/t/bin/content-md5-put +36 -0
- data/t/bin/sha1sum.rb +23 -0
- data/t/bin/unused_listen +40 -0
- data/t/bin/utee +12 -0
- data/t/env.ru +3 -0
- data/t/my-tap-lib.sh +200 -0
- data/t/t0000-http-basic.sh +50 -0
- data/t/t0001-reload-bad-config.sh +52 -0
- data/t/t0002-config-conflict.sh +49 -0
- data/t/test-lib.sh +100 -0
- data/test/rails/test_rails.rb +3 -3
- data/test/test_helper.rb +5 -0
- data/test/unit/test_http_parser_ng.rb +0 -1
- data/test/unit/test_server.rb +1 -0
- data/test/unit/test_signals.rb +5 -1
- data/test/unit/test_tee_input.rb +15 -15
- data/test/unit/test_upload.rb +1 -0
- metadata +17 -2
@@ -0,0 +1,50 @@
|
|
1
|
+
#!/bin/sh
|
2
|
+
. ./test-lib.sh
|
3
|
+
t_plan 8 "simple HTTP connection tests"
|
4
|
+
|
5
|
+
t_begin "setup and start" && {
|
6
|
+
unicorn_setup
|
7
|
+
unicorn -D -c $unicorn_config env.ru
|
8
|
+
unicorn_wait_start
|
9
|
+
}
|
10
|
+
|
11
|
+
t_begin "single request" && {
|
12
|
+
curl -sSfv http://$listen/
|
13
|
+
}
|
14
|
+
|
15
|
+
t_begin "check stderr has no errors" && {
|
16
|
+
check_stderr
|
17
|
+
}
|
18
|
+
|
19
|
+
t_begin "HTTP/0.9 request should not return headers" && {
|
20
|
+
(
|
21
|
+
printf 'GET /\r\n'
|
22
|
+
cat $fifo > $tmp &
|
23
|
+
wait
|
24
|
+
echo ok > $ok
|
25
|
+
) | socat - TCP:$listen > $fifo
|
26
|
+
}
|
27
|
+
|
28
|
+
t_begin "env.inspect should've put everything on one line" && {
|
29
|
+
test 1 -eq $(wc -l < $tmp)
|
30
|
+
}
|
31
|
+
|
32
|
+
t_begin "no headers in output" && {
|
33
|
+
if grep ^Connection: $tmp
|
34
|
+
then
|
35
|
+
die "Connection header found in $tmp"
|
36
|
+
elif grep ^HTTP/ $tmp
|
37
|
+
then
|
38
|
+
die "HTTP/ found in $tmp"
|
39
|
+
fi
|
40
|
+
}
|
41
|
+
|
42
|
+
t_begin "killing succeeds" && {
|
43
|
+
kill $unicorn_pid
|
44
|
+
}
|
45
|
+
|
46
|
+
t_begin "check stderr has no errors" && {
|
47
|
+
check_stderr
|
48
|
+
}
|
49
|
+
|
50
|
+
t_done
|
@@ -0,0 +1,52 @@
|
|
1
|
+
#!/bin/sh
|
2
|
+
. ./test-lib.sh
|
3
|
+
t_plan 7 "reload config.ru error with preload_app true"
|
4
|
+
|
5
|
+
t_begin "setup and start" && {
|
6
|
+
unicorn_setup
|
7
|
+
rtmpfiles ru
|
8
|
+
|
9
|
+
cat > $ru <<\EOF
|
10
|
+
use Rack::ContentLength
|
11
|
+
use Rack::ContentType, "text/plain"
|
12
|
+
x = { "hello" => "world" }
|
13
|
+
run lambda { |env| [ 200, {}, [ x.inspect << "\n" ] ] }
|
14
|
+
EOF
|
15
|
+
echo 'preload_app true' >> $unicorn_config
|
16
|
+
unicorn -D -c $unicorn_config $ru
|
17
|
+
unicorn_wait_start
|
18
|
+
}
|
19
|
+
|
20
|
+
t_begin "hit with curl" && {
|
21
|
+
out=$(curl -sSf http://$listen/)
|
22
|
+
test x"$out" = x'{"hello"=>"world"}'
|
23
|
+
}
|
24
|
+
|
25
|
+
t_begin "introduce syntax error in rackup file" && {
|
26
|
+
echo '...' >> $ru
|
27
|
+
}
|
28
|
+
|
29
|
+
t_begin "reload signal succeeds" && {
|
30
|
+
kill -HUP $unicorn_pid
|
31
|
+
while ! egrep '(done|error) reloading' $r_err >/dev/null
|
32
|
+
do
|
33
|
+
sleep 1
|
34
|
+
done
|
35
|
+
|
36
|
+
grep 'error reloading' $r_err >/dev/null
|
37
|
+
}
|
38
|
+
|
39
|
+
t_begin "hit with curl" && {
|
40
|
+
out=$(curl -sSf http://$listen/)
|
41
|
+
test x"$out" = x'{"hello"=>"world"}'
|
42
|
+
}
|
43
|
+
|
44
|
+
t_begin "killing succeeds" && {
|
45
|
+
kill $unicorn_pid
|
46
|
+
}
|
47
|
+
|
48
|
+
t_begin "check stderr" && {
|
49
|
+
check_stderr
|
50
|
+
}
|
51
|
+
|
52
|
+
t_done
|
@@ -0,0 +1,49 @@
|
|
1
|
+
#!/bin/sh
|
2
|
+
. ./test-lib.sh
|
3
|
+
t_plan 6 "config variables conflict with preload_app"
|
4
|
+
|
5
|
+
t_begin "setup and start" && {
|
6
|
+
unicorn_setup
|
7
|
+
rtmpfiles ru rutmp
|
8
|
+
|
9
|
+
cat > $ru <<\EOF
|
10
|
+
use Rack::ContentLength
|
11
|
+
use Rack::ContentType, "text/plain"
|
12
|
+
config = ru = { "hello" => "world" }
|
13
|
+
run lambda { |env| [ 200, {}, [ ru.inspect << "\n" ] ] }
|
14
|
+
EOF
|
15
|
+
echo 'preload_app true' >> $unicorn_config
|
16
|
+
unicorn -D -c $unicorn_config $ru
|
17
|
+
unicorn_wait_start
|
18
|
+
}
|
19
|
+
|
20
|
+
t_begin "hit with curl" && {
|
21
|
+
out=$(curl -sSf http://$listen/)
|
22
|
+
test x"$out" = x'{"hello"=>"world"}'
|
23
|
+
}
|
24
|
+
|
25
|
+
t_begin "modify rackup file" && {
|
26
|
+
sed -e 's/world/WORLD/' < $ru > $rutmp
|
27
|
+
mv $rutmp $ru
|
28
|
+
}
|
29
|
+
|
30
|
+
t_begin "reload signal succeeds" && {
|
31
|
+
kill -HUP $unicorn_pid
|
32
|
+
while ! egrep '(done|error) reloading' < $r_err >/dev/null
|
33
|
+
do
|
34
|
+
sleep 1
|
35
|
+
done
|
36
|
+
|
37
|
+
grep 'done reloading' $r_err >/dev/null
|
38
|
+
}
|
39
|
+
|
40
|
+
t_begin "hit with curl" && {
|
41
|
+
out=$(curl -sSf http://$listen/)
|
42
|
+
test x"$out" = x'{"hello"=>"WORLD"}'
|
43
|
+
}
|
44
|
+
|
45
|
+
t_begin "killing succeeds" && {
|
46
|
+
kill $unicorn_pid
|
47
|
+
}
|
48
|
+
|
49
|
+
t_done
|
data/t/test-lib.sh
ADDED
@@ -0,0 +1,100 @@
|
|
1
|
+
#!/bin/sh
|
2
|
+
# Copyright (c) 2009 Rainbows! hackers
|
3
|
+
# Copyright (c) 2010 Unicorn hackers
|
4
|
+
. ./my-tap-lib.sh
|
5
|
+
|
6
|
+
set +u
|
7
|
+
set -e
|
8
|
+
RUBY="${RUBY-ruby}"
|
9
|
+
RUBY_VERSION=${RUBY_VERSION-$($RUBY -e 'puts RUBY_VERSION')}
|
10
|
+
t_pfx=$PWD/trash/$T-$RUBY_VERSION
|
11
|
+
set -u
|
12
|
+
|
13
|
+
PATH=$PWD/bin:$PATH
|
14
|
+
export PATH
|
15
|
+
|
16
|
+
test -x $PWD/bin/unused_listen || die "must be run in 't' directory"
|
17
|
+
|
18
|
+
wait_for_pid () {
|
19
|
+
path="$1"
|
20
|
+
nr=30
|
21
|
+
while ! test -s "$path" && test $nr -gt 0
|
22
|
+
do
|
23
|
+
nr=$(($nr - 1))
|
24
|
+
sleep 1
|
25
|
+
done
|
26
|
+
}
|
27
|
+
|
28
|
+
# given a list of variable names, create temporary files and assign
|
29
|
+
# the pathnames to those variables
|
30
|
+
rtmpfiles () {
|
31
|
+
for id in "$@"
|
32
|
+
do
|
33
|
+
name=$id
|
34
|
+
_tmp=$t_pfx.$id
|
35
|
+
eval "$id=$_tmp"
|
36
|
+
|
37
|
+
case $name in
|
38
|
+
*fifo)
|
39
|
+
rm -f $_tmp
|
40
|
+
mkfifo $_tmp
|
41
|
+
T_RM_LIST="$T_RM_LIST $_tmp"
|
42
|
+
;;
|
43
|
+
*socket)
|
44
|
+
rm -f $_tmp
|
45
|
+
T_RM_LIST="$T_RM_LIST $_tmp"
|
46
|
+
;;
|
47
|
+
*)
|
48
|
+
> $_tmp
|
49
|
+
T_OK_RM_LIST="$T_OK_RM_LIST $_tmp"
|
50
|
+
;;
|
51
|
+
esac
|
52
|
+
done
|
53
|
+
}
|
54
|
+
|
55
|
+
dbgcat () {
|
56
|
+
id=$1
|
57
|
+
eval '_file=$'$id
|
58
|
+
echo "==> $id <=="
|
59
|
+
sed -e "s/^/$id:/" < $_file
|
60
|
+
}
|
61
|
+
|
62
|
+
check_stderr () {
|
63
|
+
set +u
|
64
|
+
_r_err=${1-${r_err}}
|
65
|
+
set -u
|
66
|
+
if grep -v $T $_r_err | grep -i Error
|
67
|
+
then
|
68
|
+
die "Errors found in $_r_err"
|
69
|
+
elif grep SIGKILL $_r_err
|
70
|
+
then
|
71
|
+
die "SIGKILL found in $_r_err"
|
72
|
+
fi
|
73
|
+
}
|
74
|
+
|
75
|
+
# unicorn_setup
|
76
|
+
unicorn_setup () {
|
77
|
+
eval $(unused_listen)
|
78
|
+
rtmpfiles unicorn_config pid r_err r_out fifo tmp ok
|
79
|
+
cat > $unicorn_config <<EOF
|
80
|
+
listen "$listen"
|
81
|
+
pid "$pid"
|
82
|
+
stderr_path "$r_err"
|
83
|
+
stdout_path "$r_out"
|
84
|
+
EOF
|
85
|
+
}
|
86
|
+
|
87
|
+
unicorn_wait_start () {
|
88
|
+
# no need to play tricks with FIFOs since we got "ready_pipe" now
|
89
|
+
unicorn_pid=$(cat $pid)
|
90
|
+
}
|
91
|
+
|
92
|
+
rsha1 () {
|
93
|
+
_cmd="$(which sha1sum 2>/dev/null || :)"
|
94
|
+
test -n "$_cmd" || _cmd="$(which openssl 2>/dev/null || :) sha1"
|
95
|
+
test "$_cmd" != " sha1" || _cmd="$(which gsha1sum 2>/dev/null || :)"
|
96
|
+
|
97
|
+
# last resort, see comments in sha1sum.rb for reasoning
|
98
|
+
test -n "$_cmd" || _cmd=sha1sum.rb
|
99
|
+
expr "$($_cmd < random_blob)" : '\([a-f0-9]\{40\}\)'
|
100
|
+
}
|
data/test/rails/test_rails.rb
CHANGED
@@ -92,9 +92,6 @@ logger Logger.new('#{COMMON_TMP.path}')
|
|
92
92
|
redirect_test_io { @pid = fork { exec 'unicorn_rails', "-l#@addr:#@port" } }
|
93
93
|
wait_master_ready("test_stderr.#$$.log")
|
94
94
|
|
95
|
-
# temp dirs exist
|
96
|
-
tmp_dirs.each { |dir| assert(File.directory?("tmp/#{dir}")) }
|
97
|
-
|
98
95
|
# basic GET
|
99
96
|
res = Net::HTTP.get_response(URI.parse("http://#@addr:#@port/foo"))
|
100
97
|
assert_equal "FOO\n", res.body
|
@@ -102,6 +99,9 @@ logger Logger.new('#{COMMON_TMP.path}')
|
|
102
99
|
assert_equal "4", res['Content-Length']
|
103
100
|
assert_equal "200 OK", res['Status']
|
104
101
|
|
102
|
+
# temp dirs exist
|
103
|
+
tmp_dirs.each { |dir| assert(File.directory?("tmp/#{dir}")) }
|
104
|
+
|
105
105
|
# can we set cookies?
|
106
106
|
res = Net::HTTP.get_response(URI.parse("http://#@addr:#@port/foo/xcookie"))
|
107
107
|
assert_equal "200", res.code
|
data/test/test_helper.rb
CHANGED
data/test/unit/test_server.rb
CHANGED
data/test/unit/test_signals.rb
CHANGED
@@ -40,6 +40,10 @@ class SignalsTest < Test::Unit::TestCase
|
|
40
40
|
@server = nil
|
41
41
|
end
|
42
42
|
|
43
|
+
def teardown
|
44
|
+
reset_sig_handlers
|
45
|
+
end
|
46
|
+
|
43
47
|
def test_worker_dies_on_dead_master
|
44
48
|
pid = fork {
|
45
49
|
app = lambda { |env| [ 200, {'X-Pid' => "#$$" }, [] ] }
|
@@ -190,7 +194,7 @@ class SignalsTest < Test::Unit::TestCase
|
|
190
194
|
killer = fork { loop { Process.kill(:HUP, pid); sleep(0.0001) } }
|
191
195
|
buf = ' ' * @bs
|
192
196
|
@count.times { sock.syswrite(buf) }
|
193
|
-
Process.kill(:
|
197
|
+
Process.kill(:KILL, killer)
|
194
198
|
Process.waitpid2(killer)
|
195
199
|
redirect_test_io { @server.stop(true) }
|
196
200
|
# can't check for == since pending signals get merged
|
data/test/unit/test_tee_input.rb
CHANGED
@@ -71,8 +71,8 @@ class TestTeeInput < Test::Unit::TestCase
|
|
71
71
|
ti = Unicorn::TeeInput.new(@rd, @env, @parser, @buf)
|
72
72
|
assert_equal 0, @parser.content_length
|
73
73
|
assert @parser.body_eof?
|
74
|
-
assert_equal StringIO, ti.
|
75
|
-
assert_equal 0, ti.
|
74
|
+
assert_equal StringIO, ti.tmp.class
|
75
|
+
assert_equal 0, ti.tmp.pos
|
76
76
|
assert_equal 5, ti.size
|
77
77
|
assert_equal 'hello', ti.read
|
78
78
|
assert_equal '', ti.read
|
@@ -99,8 +99,8 @@ class TestTeeInput < Test::Unit::TestCase
|
|
99
99
|
ti = Unicorn::TeeInput.new(@rd, @env, @parser, @buf)
|
100
100
|
assert_equal 0, @parser.content_length
|
101
101
|
assert @parser.body_eof?
|
102
|
-
assert_kind_of File, ti.
|
103
|
-
assert_equal 0, ti.
|
102
|
+
assert_kind_of File, ti.tmp
|
103
|
+
assert_equal 0, ti.tmp.pos
|
104
104
|
assert_equal Unicorn::Const::MAX_BODY + 1, ti.size
|
105
105
|
end
|
106
106
|
|
@@ -125,9 +125,9 @@ class TestTeeInput < Test::Unit::TestCase
|
|
125
125
|
ti = Unicorn::TeeInput.new(@rd, @env, @parser, @buf)
|
126
126
|
assert_equal Unicorn::Const::MAX_BODY, @parser.content_length
|
127
127
|
assert ! @parser.body_eof?
|
128
|
-
assert_kind_of File, ti.
|
129
|
-
assert_equal 0, ti.
|
130
|
-
assert_equal 1, ti.
|
128
|
+
assert_kind_of File, ti.tmp
|
129
|
+
assert_equal 0, ti.tmp.pos
|
130
|
+
assert_equal 1, ti.tmp.size
|
131
131
|
assert_equal Unicorn::Const::MAX_BODY + 1, ti.size
|
132
132
|
nr = Unicorn::Const::MAX_BODY / 4
|
133
133
|
pid = fork {
|
@@ -165,19 +165,19 @@ class TestTeeInput < Test::Unit::TestCase
|
|
165
165
|
@wr.close
|
166
166
|
ti = Unicorn::TeeInput.new(@rd, @env, @parser, @buf)
|
167
167
|
assert_nil @parser.content_length
|
168
|
-
assert_nil ti.
|
168
|
+
assert_nil ti.len
|
169
169
|
assert ! @parser.body_eof?
|
170
170
|
assert_equal 25, ti.size
|
171
171
|
assert @parser.body_eof?
|
172
|
-
assert_equal 25, ti.
|
173
|
-
assert_equal 0, ti.
|
172
|
+
assert_equal 25, ti.len
|
173
|
+
assert_equal 0, ti.tmp.pos
|
174
174
|
assert_nothing_raised { ti.rewind }
|
175
|
-
assert_equal 0, ti.
|
175
|
+
assert_equal 0, ti.tmp.pos
|
176
176
|
assert_equal 'abcdeabcdeabcdeabcde', ti.read(20)
|
177
|
-
assert_equal 20, ti.
|
177
|
+
assert_equal 20, ti.tmp.pos
|
178
178
|
assert_nothing_raised { ti.rewind }
|
179
|
-
assert_equal 0, ti.
|
180
|
-
assert_kind_of File, ti.
|
179
|
+
assert_equal 0, ti.tmp.pos
|
180
|
+
assert_kind_of File, ti.tmp
|
181
181
|
status = nil
|
182
182
|
assert_nothing_raised { pid, status = Process.waitpid2(pid) }
|
183
183
|
assert status.success?
|
@@ -203,7 +203,7 @@ class TestTeeInput < Test::Unit::TestCase
|
|
203
203
|
}
|
204
204
|
ti = Unicorn::TeeInput.new(@rd, @env, @parser, @buf)
|
205
205
|
assert_nil @parser.content_length
|
206
|
-
assert_nil ti.
|
206
|
+
assert_nil ti.len
|
207
207
|
assert ! @parser.body_eof?
|
208
208
|
chunks.each do |chunk|
|
209
209
|
wr.write('.')
|
data/test/unit/test_upload.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: unicorn
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.97.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Unicorn hackers
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2010-
|
12
|
+
date: 2010-03-01 00:00:00 +00:00
|
13
13
|
default_executable:
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
@@ -98,8 +98,10 @@ files:
|
|
98
98
|
- examples/echo.ru
|
99
99
|
- examples/git.ru
|
100
100
|
- examples/init.sh
|
101
|
+
- examples/logger_mp_safe.rb
|
101
102
|
- examples/nginx.conf
|
102
103
|
- examples/unicorn.conf.rb
|
104
|
+
- ext/unicorn_http/CFLAGS
|
103
105
|
- ext/unicorn_http/c_util.h
|
104
106
|
- ext/unicorn_http/common_field_optimization.h
|
105
107
|
- ext/unicorn_http/ext_help.h
|
@@ -126,6 +128,19 @@ files:
|
|
126
128
|
- man/man1/unicorn.1
|
127
129
|
- man/man1/unicorn_rails.1
|
128
130
|
- setup.rb
|
131
|
+
- t/.gitignore
|
132
|
+
- t/GNUmakefile
|
133
|
+
- t/README
|
134
|
+
- t/bin/content-md5-put
|
135
|
+
- t/bin/sha1sum.rb
|
136
|
+
- t/bin/unused_listen
|
137
|
+
- t/bin/utee
|
138
|
+
- t/env.ru
|
139
|
+
- t/my-tap-lib.sh
|
140
|
+
- t/t0000-http-basic.sh
|
141
|
+
- t/t0001-reload-bad-config.sh
|
142
|
+
- t/t0002-config-conflict.sh
|
143
|
+
- t/test-lib.sh
|
129
144
|
- test/aggregate.rb
|
130
145
|
- test/benchmark/README
|
131
146
|
- test/benchmark/dd.ru
|