regurgitator 0.0.0

Sign up to get free protection for your applications and to get access to all the features.
data/t/.gitignore ADDED
@@ -0,0 +1,7 @@
1
+ *.sqlite3
2
+ /test-results-*
3
+ /bin-*
4
+ /random_blob
5
+ /.dep+*
6
+ /trash
7
+ /tmp
data/t/GNUmakefile ADDED
@@ -0,0 +1,65 @@
1
+ # we can run tests in parallel with GNU make
2
+
3
+ all::
4
+
5
+ pid := $(shell echo $$PPID)
6
+
7
+ RUBY = ruby
8
+ my_lib := $(shell cd ../lib && pwd)
9
+ -include ../local.mk
10
+ ifeq ($(RUBY_VERSION),)
11
+ RUBY_VERSION := $(shell $(RUBY) -e 'puts RUBY_VERSION')
12
+ endif
13
+ ifeq ($(RUBY_VERSION),)
14
+ $(error unable to detect RUBY_VERSION)
15
+ endif
16
+
17
+ RUBY_ENGINE := $(shell $(RUBY) -e 'puts((RUBY_ENGINE rescue "ruby"))')
18
+ export RUBY_VERSION RUBY_ENGINE
19
+ ifeq ($(RUBYLIB),)
20
+ RUBYLIB := $(my_lib)
21
+ else
22
+ RUBYLIB := $(my_lib):$(RUBYLIB)
23
+ endif
24
+ export RUBYLIB
25
+
26
+ T = $(wildcard t[0-9][0-9][0-9][0-9]-*.sh)
27
+
28
+ all:: $(T)
29
+
30
+ # can't rely on "set -o pipefail" since we don't require bash or ksh93 :<
31
+ t_pfx = trash/$@-$(RUBY_ENGINE)-$(RUBY_VERSION)
32
+ TEST_OPTS =
33
+ # TRACER = strace -f -o $(t_pfx).strace -s 100000
34
+ # TRACER = /usr/bin/time -o $(t_pfx).time
35
+
36
+ ifdef V
37
+ ifeq ($(V),2)
38
+ TEST_OPTS += --trace
39
+ else
40
+ TEST_OPTS += --verbose
41
+ endif
42
+ endif
43
+
44
+ random_blob:
45
+ dd if=/dev/urandom bs=1M count=1 of=$@.$(pid)
46
+ mv $@.$(pid) $@
47
+
48
+ $(T): random_blob
49
+
50
+ dependencies := curl sqlite3
51
+ deps := $(addprefix .dep+,$(dependencies))
52
+ $(deps): dep_bin = $(lastword $(subst +, ,$@))
53
+ $(deps):
54
+ @which $(dep_bin) > $@.$(pid) 2>/dev/null || :
55
+ @test -s $@.$(pid) || \
56
+ { echo >&2 "E '$(dep_bin)' not found in PATH=$(PATH)"; exit 1; }
57
+ @mv $@.$(pid) $@
58
+
59
+ $(T): $(deps)
60
+ $(TRACER) $(SHELL) $(SH_TEST_OPTS) $@ $(TEST_OPTS)
61
+
62
+ clean:
63
+ $(RM) -r trash/*.log trash/*.code test-bin-$(RUBY_VERSION)
64
+
65
+ .PHONY: $(T) clean
@@ -0,0 +1,40 @@
1
+ #!/usr/bin/env ruby
2
+ # -*- encoding: binary -*-
3
+ # this is to remain compatible with the unused_port function in the
4
+ # Unicorn test/test_helper.rb file
5
+ require 'socket'
6
+ require 'tmpdir'
7
+
8
+ default_port = 8080
9
+ addr = ENV['UNICORN_TEST_ADDR'] || '127.0.0.1'
10
+ retries = 100
11
+ base = 5000
12
+ port = sock = lock_path = nil
13
+
14
+ begin
15
+ begin
16
+ port = base + rand(32768 - base)
17
+ while port == default_port
18
+ port = base + rand(32768 - base)
19
+ end
20
+
21
+ sock = Socket.new(Socket::AF_INET, Socket::SOCK_STREAM, 0)
22
+ sock.bind(Socket.pack_sockaddr_in(port, addr))
23
+ sock.listen(5)
24
+ rescue Errno::EADDRINUSE, Errno::EACCES
25
+ sock.close rescue nil
26
+ retry if (retries -= 1) >= 0
27
+ end
28
+
29
+ # since we'll end up closing the random port we just got, there's a race
30
+ # condition could allow the random port we just chose to reselect itself
31
+ # when running tests in parallel with gmake. Create a lock file while
32
+ # we have the port here to ensure that does not happen.
33
+ lock_path = "#{Dir::tmpdir}/unicorn_test.#{addr}:#{port}.lock"
34
+ lock = File.open(lock_path, File::WRONLY|File::CREAT|File::EXCL, 0600)
35
+ rescue Errno::EEXIST
36
+ sock.close rescue nil
37
+ retry
38
+ end
39
+ sock.close rescue nil
40
+ puts %Q(listen=#{addr}:#{port} T_RM_LIST="$T_RM_LIST #{lock_path}")
data/t/domain_host.ru ADDED
@@ -0,0 +1,8 @@
1
+ require 'regurgitator'
2
+ use Rack::ContentLength
3
+ use Rack::ContentType, 'text/plain'
4
+ o = {
5
+ :db => Sequel.connect(ENV['TEST_SEQUEL']),
6
+ :suffix => '.example.com',
7
+ }
8
+ run Regurgitator::DomainHost.new(lambda { |env| [ 404, [], [] ] }, o)
data/t/domain_path.ru ADDED
@@ -0,0 +1,5 @@
1
+ require 'regurgitator'
2
+ use Rack::ContentLength
3
+ use Rack::ContentType, 'text/plain'
4
+ db = Sequel.connect(ENV['TEST_SEQUEL'])
5
+ run Regurgitator::DomainPath.new(lambda { |env| [ 404, [], [] ] }, db)
data/t/file.ru ADDED
@@ -0,0 +1,2 @@
1
+ use Rack::Head
2
+ run Rack::File.new(ENV['TMPDIR'])
data/t/fixtures.sql ADDED
@@ -0,0 +1,59 @@
1
+ CREATE TABLE domain (
2
+ dmid SMALLINT NOT NULL,
3
+ namespace VARCHAR(255),
4
+ PRIMARY KEY (dmid),
5
+ UNIQUE (namespace)
6
+ );
7
+
8
+ CREATE TABLE file (
9
+ fid INTEGER NOT NULL,
10
+ dmid SMALLINT NOT NULL,
11
+ dkey VARCHAR(255),
12
+ length INTEGER,
13
+ classid TINYINT NOT NULL,
14
+ devcount TINYINT NOT NULL,
15
+ UNIQUE (dmid, dkey),
16
+ PRIMARY KEY (fid)
17
+ );
18
+
19
+ CREATE TABLE host (
20
+ hostid MEDIUMINT NOT NULL PRIMARY KEY,
21
+ status VARCHAR(5),
22
+ http_port MEDIUMINT DEFAULT 7500,
23
+ http_get_port MEDIUMINT,
24
+ hostname VARCHAR(40),
25
+ hostip VARCHAR(15),
26
+ altip VARCHAR(15),
27
+ altmask VARCHAR(18),
28
+ UNIQUE (hostname),
29
+ UNIQUE (hostip),
30
+ UNIQUE (altip)
31
+ );
32
+
33
+ CREATE TABLE server_settings (
34
+ field VARCHAR(50) PRIMARY KEY,
35
+ value VARCHAR(255)
36
+ );
37
+
38
+ CREATE TABLE device (
39
+ devid MEDIUMINT NOT NULL,
40
+ hostid MEDIUMINT NOT NULL,
41
+ status VARCHAR(8),
42
+ weight MEDIUMINT DEFAULT 100,
43
+ mb_total MEDIUMINT,
44
+ mb_used MEDIUMINT,
45
+ mb_asof INTEGER,
46
+ PRIMARY KEY (devid)
47
+ );
48
+
49
+ CREATE TABLE file_on (
50
+ fid INTEGER NOT NULL,
51
+ devid MEDIUMINT NOT NULL,
52
+ PRIMARY KEY (fid, devid)
53
+ );
54
+
55
+ INSERT INTO host VALUES(1,'alive',7500,NULL,'localhost','127.0.0.1',NULL,NULL);
56
+ INSERT INTO device VALUES(1,1,'alive',100,99999,0,1234567890);
57
+ INSERT INTO domain VALUES(1,'d');
58
+ INSERT INTO file VALUES(1,1,'blah',0,0,1);
59
+ INSERT INTO file_on VALUES(1,1);
data/t/my-tap-lib.sh ADDED
@@ -0,0 +1,200 @@
1
+ #!/bin/sh
2
+ # Copyright (c) 2009 Eric Wong <normalperson@yhbt.net>
3
+ #
4
+ # TAP-producing shell library for POSIX-compliant Bourne shells We do
5
+ # not _rely_ on Bourne Again features, though we will use "set -o
6
+ # pipefail" from ksh93 or bash 3 if available
7
+ #
8
+ # Only generic, non-project/non-language-specific stuff goes here. We
9
+ # only have POSIX dependencies for the core tests (without --verbose),
10
+ # though we'll enable useful non-POSIX things if they're available.
11
+ #
12
+ # This test library is intentionally unforgiving, it does not support
13
+ # skipping tests nor continuing after any failure. Any failures
14
+ # immediately halt execution as do any references to undefined
15
+ # variables.
16
+ #
17
+ # When --verbose is specified, we always prefix stdout/stderr
18
+ # output with "#" to avoid confusing TAP consumers. Otherwise
19
+ # the normal stdout/stderr streams are redirected to /dev/null
20
+
21
+ # dup normal stdout(fd=1) and stderr (fd=2) to fd=3 and fd=4 respectively
22
+ # normal TAP output goes to fd=3, nothing should go to fd=4
23
+ exec 3>&1 4>&2
24
+
25
+ # ensure a sane environment
26
+ TZ=UTC LC_ALL=C LANG=C
27
+ export LANG LC_ALL TZ
28
+ unset CDPATH
29
+
30
+ # pipefail is non-POSIX, but very useful in ksh93/bash
31
+ ( set -o pipefail 2>/dev/null ) && set -o pipefail
32
+
33
+ SED=${SED-sed}
34
+
35
+ # Unlike other test frameworks, we are unforgiving and bail immediately
36
+ # on any failures. We do this because we're lazy about error handling
37
+ # and also because we believe anything broken should not be allowed to
38
+ # propagate throughout the rest of the test
39
+ set -e
40
+ set -u
41
+
42
+ # name of our test
43
+ T=${0##*/}
44
+
45
+ t_expect_nr=-1
46
+ t_nr=0
47
+ t_current=
48
+ t_complete=false
49
+
50
+ # list of files to remove unconditionally on exit
51
+ T_RM_LIST=
52
+
53
+ # list of files to remove only on successful exit
54
+ T_OK_RM_LIST=
55
+
56
+ # emit output to stdout, it'll be parsed by the TAP consumer
57
+ # so it must be TAP-compliant output
58
+ t_echo () {
59
+ echo >&3 "$@"
60
+ }
61
+
62
+ # emits non-parsed information to stdout, it will be prefixed with a '#'
63
+ # to not throw off TAP consumers
64
+ t_info () {
65
+ t_echo '#' "$@"
66
+ }
67
+
68
+ # exit with an error and print a diagnostic
69
+ die () {
70
+ echo >&2 "$@"
71
+ exit 1
72
+ }
73
+
74
+ # our at_exit handler, it'll fire for all exits except SIGKILL (unavoidable)
75
+ t_at_exit () {
76
+ code=$?
77
+ set +e
78
+ if test $code -eq 0
79
+ then
80
+ $t_complete || {
81
+ t_info "t_done not called"
82
+ code=1
83
+ }
84
+ elif test -n "$t_current"
85
+ then
86
+ t_echo "not ok $t_nr - $t_current"
87
+ fi
88
+ if test $t_expect_nr -ne -1
89
+ then
90
+ test $t_expect_nr -eq $t_nr || {
91
+ t_info "planned $t_expect_nr tests but ran $t_nr"
92
+ test $code -ne 0 || code=1
93
+ }
94
+ fi
95
+ $t_complete || {
96
+ t_info "unexpected test failure"
97
+ test $code -ne 0 || code=1
98
+ }
99
+ rm -f $T_RM_LIST
100
+ test $code -eq 0 && rm -f $T_OK_RM_LIST
101
+ set +x
102
+ exec >&3 2>&4
103
+ t_close_fds
104
+ exit $code
105
+ }
106
+
107
+ # close test-specific extra file descriptors
108
+ t_close_fds () {
109
+ exec 3>&- 4>&-
110
+ }
111
+
112
+ # call this at the start of your test to specify the number of tests
113
+ # you plan to run
114
+ t_plan () {
115
+ test "$1" -ge 1 || die "must plan at least one test"
116
+ test $t_expect_nr -eq -1 || die "tried to plan twice in one test"
117
+ t_expect_nr=$1
118
+ shift
119
+ t_echo 1..$t_expect_nr "#" "$@"
120
+ trap t_at_exit EXIT
121
+ }
122
+
123
+ _t_checkup () {
124
+ test $t_expect_nr -le 0 && die "no tests planned"
125
+ test -n "$t_current" && t_echo "ok $t_nr - $t_current"
126
+ true
127
+ }
128
+
129
+ # finalizes any previously test and starts a new one
130
+ t_begin () {
131
+ _t_checkup
132
+ t_nr=$(( $t_nr + 1 ))
133
+ t_current="$1"
134
+
135
+ # just in case somebody wanted to cheat us:
136
+ set -e
137
+ }
138
+
139
+ # finalizes the current test without starting a new one
140
+ t_end () {
141
+ _t_checkup
142
+ t_current=
143
+ }
144
+
145
+ # run this to signify the end of your test
146
+ t_done () {
147
+ _t_checkup
148
+ t_current=
149
+ t_complete=true
150
+ test $t_expect_nr -eq $t_nr || exit 1
151
+ exit 0
152
+ }
153
+
154
+ # create and assign named-pipes to variable _names_ passed to this function
155
+ t_fifos () {
156
+ for _id in "$@"
157
+ do
158
+ _name=$_id
159
+ _tmp=$(mktemp -t $T.$$.$_id.XXXXXXXX)
160
+ eval "$_id=$_tmp"
161
+ rm -f $_tmp
162
+ mkfifo $_tmp
163
+ T_RM_LIST="$T_RM_LIST $_tmp"
164
+ done
165
+ }
166
+
167
+ t_verbose=false t_trace=false
168
+
169
+ while test "$#" -ne 0
170
+ do
171
+ arg="$1"
172
+ shift
173
+ case $arg in
174
+ -v|--verbose) t_verbose=true ;;
175
+ --trace) t_trace=true t_verbose=true ;;
176
+ *) die "Unknown option: $arg" ;;
177
+ esac
178
+ done
179
+
180
+ # we always only setup stdout, nothing should end up in the "real" stderr
181
+ if $t_verbose
182
+ then
183
+ if test x"$(which mktemp 2>/dev/null)" = x
184
+ then
185
+ die "mktemp(1) not available for --verbose"
186
+ fi
187
+ t_fifos t_stdout t_stderr
188
+
189
+ (
190
+ # use a subshell so seds are not waitable
191
+ $SED -e 's/^/#: /' $t_stdout &
192
+ $SED -e 's/^/#! /' $t_stderr &
193
+ ) &
194
+ exec > $t_stdout 2> $t_stderr
195
+ else
196
+ exec > /dev/null 2> /dev/null
197
+ fi
198
+
199
+ $t_trace && set -x
200
+ true
data/t/one_domain.ru ADDED
@@ -0,0 +1,8 @@
1
+ require 'regurgitator'
2
+ use Rack::ContentLength
3
+ use Rack::ContentType, 'text/plain'
4
+ o = {
5
+ :db => Sequel.connect(ENV['TEST_SEQUEL']),
6
+ :domain => 'd',
7
+ }
8
+ run Regurgitator::OneDomain.new(lambda { |env| [ 404, [], [] ] }, o)
@@ -0,0 +1,67 @@
1
+ #!/bin/sh
2
+ . ./test-lib.sh
3
+ t_plan 8 "DomainPath tests"
4
+
5
+ t_begin "setup" && {
6
+ setup domain_path.ru
7
+ }
8
+
9
+ t_begin "retrieve empty file" && {
10
+ test 0 -eq $(curl -sSvf 2> $curl_err http://$listen/d/blah | wc -c)
11
+ grep 'E[tT]ag: ' $curl_err && die "ETag not expected"
12
+ grep 'Last-Modified: ' $curl_err && die "Last-Modified not expected"
13
+ }
14
+
15
+ t_begin "retrieve missing file" && {
16
+ sqlite3 $db <<EOF
17
+ UPDATE file SET length = $random_blob_size;
18
+ EOF
19
+ ok=$(curl -sSvf 2> $curl_err http://$listen/d/blah || echo ok)
20
+ test ok = "$ok"
21
+ grep '\<404\>' $curl_err
22
+ }
23
+
24
+ t_begin "retrieve existing file" && {
25
+ dir=$TMPDIR/dev1/0/000/000
26
+ mkdir -p $dir
27
+ ln random_blob $dir/0000000001.fid
28
+ cksum="$(curl -sSvf 2> $curl_err http://$listen/d/blah | cksum)"
29
+ test "$cksum" = "$random_blob_cksum"
30
+ dbgcat curl_err
31
+ grep 'E[tT]ag: "1"' $curl_err
32
+ }
33
+
34
+ t_begin "reproxy existing file" && {
35
+ curl -sSvf -H 'X-Reproxy-Path: /reproxy' 2> $curl_err \
36
+ http://$listen/d/blah >/dev/null
37
+ dbgcat curl_err
38
+ uri=http://$rack_file_listen/dev1/0/000/000/0000000001.fid
39
+ grep '^< X-Accel-Redirect: /reproxy' $curl_err
40
+ grep '^< X-Reproxy-Content-Type: application/octet-stream' $curl_err
41
+ grep "^< Location: $uri" $curl_err
42
+ grep '^< X-Reproxy-Last-Modified: ' $curl_err
43
+ grep '^< Content-Length: 0' $curl_err
44
+ grep '^< Etag: "1"' $curl_err
45
+ }
46
+
47
+ t_begin "HEAD requests work" && {
48
+ curl -vsSfI > $curl_err http://$listen/d/blah
49
+ grep '^E[Tt]ag: "1"' $curl_err
50
+ grep "^Content-Length: $random_blob_size" $curl_err
51
+ }
52
+
53
+ t_begin "HEAD requests work with reproxy" && {
54
+ curl -vsSfI -H X-Reproxy-Path:/z > $curl_err http://$listen/d/blah
55
+ grep '^E[Tt]ag: "1"' $curl_err
56
+ grep "^Content-Length: $random_blob_size" $curl_err
57
+ grep '^X-Accel-Redirect:' $curl_err && die "unexpected reproxy header"
58
+ grep '^X-Reproxy' $curl_err && die "unexpected reproxy header"
59
+ grep '^Location:' $curl_err && die "unexpected reproxy header"
60
+ }
61
+
62
+ t_begin "kill servers" && {
63
+ kill -INT $rack_file_pid
64
+ kill -INT $rack_server_pid
65
+ }
66
+
67
+ t_done