regurgitator 0.0.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/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