vanity 1.8.4 → 1.9.0.beta
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/.travis.yml +3 -2
- data/CHANGELOG +12 -0
- data/Gemfile +6 -3
- data/Gemfile.lock +12 -10
- data/README.rdoc +45 -16
- data/Rakefile +14 -9
- data/doc/_layouts/page.html +4 -6
- data/doc/ab_testing.textile +1 -1
- data/doc/configuring.textile +2 -4
- data/doc/email.textile +1 -3
- data/doc/index.textile +3 -63
- data/doc/rails.textile +34 -8
- data/gemfiles/rails3.gemfile +12 -3
- data/gemfiles/rails3.gemfile.lock +37 -11
- data/gemfiles/rails31.gemfile +12 -3
- data/gemfiles/rails31.gemfile.lock +37 -11
- data/gemfiles/rails32.gemfile +12 -3
- data/gemfiles/rails32.gemfile.lock +37 -11
- data/gemfiles/rails4.gemfile +12 -3
- data/gemfiles/rails4.gemfile.lock +37 -11
- data/lib/vanity/adapters/abstract_adapter.rb +4 -0
- data/lib/vanity/adapters/active_record_adapter.rb +18 -10
- data/lib/vanity/adapters/mock_adapter.rb +8 -4
- data/lib/vanity/adapters/mongodb_adapter.rb +11 -7
- data/lib/vanity/adapters/redis_adapter.rb +88 -37
- data/lib/vanity/commands/report.rb +9 -9
- data/lib/vanity/experiment/ab_test.rb +120 -101
- data/lib/vanity/experiment/alternative.rb +21 -21
- data/lib/vanity/experiment/base.rb +5 -5
- data/lib/vanity/experiment/bayesian_bandit_score.rb +51 -51
- data/lib/vanity/experiment/definition.rb +10 -10
- data/lib/vanity/frameworks/rails.rb +39 -36
- data/lib/vanity/helpers.rb +6 -4
- data/lib/vanity/metric/active_record.rb +1 -1
- data/lib/vanity/metric/base.rb +23 -24
- data/lib/vanity/metric/google_analytics.rb +5 -5
- data/lib/vanity/playground.rb +118 -24
- data/lib/vanity/templates/_report.erb +20 -6
- data/lib/vanity/templates/vanity.css +2 -0
- data/lib/vanity/version.rb +1 -1
- data/test/adapters/redis_adapter_test.rb +106 -1
- data/test/dummy/config/database.yml +21 -4
- data/test/dummy/config/routes.rb +1 -1
- data/test/experiment/ab_test.rb +93 -13
- data/test/metric/active_record_test.rb +9 -4
- data/test/passenger_test.rb +43 -42
- data/test/playground_test.rb +50 -1
- data/test/rails_dashboard_test.rb +38 -1
- data/test/rails_helper_test.rb +5 -0
- data/test/rails_test.rb +66 -15
- data/test/test_helper.rb +24 -2
- data/vanity.gemspec +0 -2
- metadata +45 -57
@@ -24,3 +24,5 @@
|
|
24
24
|
.vanity form#milestones label { margin-right: .5em }
|
25
25
|
.vanity form#milestones input { vertical-align: bottom }
|
26
26
|
.vanity .metric .marking.label { position: absolute; bottom: 2em; color: #c66; font-size: 80% }
|
27
|
+
|
28
|
+
.vanity .alert { padding: 8px 35px 8px 14px; margin-bottom: 20px; text-shadow: 0px 1px 0px rgba(255, 255, 255, 0.5); background-color: rgb(252, 248, 227); border: 1px solid rgb(251, 238, 213); border-radius: 4px 4px 4px 4px; }
|
data/lib/vanity/version.rb
CHANGED
@@ -1,6 +1,12 @@
|
|
1
1
|
require 'test/test_helper'
|
2
2
|
|
3
3
|
class RedisAdapterTest < Test::Unit::TestCase
|
4
|
+
def setup
|
5
|
+
require "vanity/adapters/redis_adapter"
|
6
|
+
require "redis"
|
7
|
+
require "redis/namespace"
|
8
|
+
end
|
9
|
+
|
4
10
|
def test_warn_on_disconnect_error
|
5
11
|
if defined?(Redis)
|
6
12
|
assert_nothing_raised do
|
@@ -8,10 +14,109 @@ class RedisAdapterTest < Test::Unit::TestCase
|
|
8
14
|
mocked_redis = stub("Redis")
|
9
15
|
mocked_redis.expects(:client).raises(RuntimeError)
|
10
16
|
redis_adapter = Vanity::Adapters::RedisAdapter.new({})
|
11
|
-
redis_adapter.expects(:warn).with("Error while disconnecting from redis: RuntimeError")
|
12
17
|
redis_adapter.stubs(:redis).returns(mocked_redis)
|
18
|
+
redis_adapter.expects(:warn).with("Error while disconnecting from redis: RuntimeError")
|
13
19
|
redis_adapter.disconnect!
|
14
20
|
end
|
15
21
|
end
|
16
22
|
end
|
23
|
+
|
24
|
+
def stub_redis
|
25
|
+
Vanity.playground.failover_on_datastore_error!
|
26
|
+
mocked_redis = stub("Redis")
|
27
|
+
redis_adapter = Vanity::Adapters::RedisAdapter.new(:redis => mocked_redis)
|
28
|
+
|
29
|
+
[redis_adapter, mocked_redis]
|
30
|
+
end
|
31
|
+
|
32
|
+
def test_graceful_failure_metric_track
|
33
|
+
redis_adapter, mocked_redis = stub_redis
|
34
|
+
mocked_redis.stubs(:incrby).raises(RuntimeError)
|
35
|
+
|
36
|
+
assert_nothing_raised do
|
37
|
+
redis_adapter.metric_track("metric", Time.now.to_s, "3ff62e2fb51f0b22646a342a2d357aec", [1])
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def test_graceful_failure_set_experiment_created_at
|
42
|
+
redis_adapter, mocked_redis = stub_redis
|
43
|
+
mocked_redis.stubs(:setnx).raises(RuntimeError)
|
44
|
+
|
45
|
+
assert_nothing_raised do
|
46
|
+
redis_adapter.set_experiment_created_at("price_options", Time.now)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def test_graceful_failure_is_experiment_completed?
|
51
|
+
redis_adapter, mocked_redis = stub_redis
|
52
|
+
mocked_redis.stubs(:exists).raises(RuntimeError)
|
53
|
+
|
54
|
+
assert_nothing_raised do
|
55
|
+
redis_adapter.is_experiment_completed?("price_options")
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
def test_graceful_failure_ab_show
|
60
|
+
redis_adapter, mocked_redis = stub_redis
|
61
|
+
mocked_redis.stubs(:[]=).raises(RuntimeError)
|
62
|
+
|
63
|
+
assert_nothing_raised do
|
64
|
+
redis_adapter.ab_show("price_options", "3ff62e2fb51f0b22646a342a2d357aec", 0)
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
def test_graceful_failure_ab_showing
|
69
|
+
redis_adapter, mocked_redis = stub_redis
|
70
|
+
mocked_redis.stubs(:[]).raises(RuntimeError)
|
71
|
+
|
72
|
+
assert_nothing_raised do
|
73
|
+
redis_adapter.ab_showing("price_options", "3ff62e2fb51f0b22646a342a2d357aec")
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
def test_graceful_failure_ab_not_showing
|
78
|
+
redis_adapter, mocked_redis = stub_redis
|
79
|
+
mocked_redis.stubs(:del).raises(RuntimeError)
|
80
|
+
|
81
|
+
assert_nothing_raised do
|
82
|
+
redis_adapter.ab_not_showing("price_options", "3ff62e2fb51f0b22646a342a2d357aec")
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
def test_graceful_failure_ab_add_participant
|
87
|
+
redis_adapter, mocked_redis = stub_redis
|
88
|
+
mocked_redis.stubs(:sadd).raises(RuntimeError)
|
89
|
+
|
90
|
+
assert_nothing_raised do
|
91
|
+
redis_adapter.ab_add_participant("price_options", "3ff62e2fb51f0b22646a342a2d357aec", 0)
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
def test_graceful_failure_ab_seen
|
96
|
+
redis_adapter, mocked_redis = stub_redis
|
97
|
+
mocked_redis.stubs(:sismember).raises(RuntimeError)
|
98
|
+
|
99
|
+
assert_nothing_raised do
|
100
|
+
redis_adapter.ab_seen("price_options", "3ff62e2fb51f0b22646a342a2d357aec", 0)
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
def test_graceful_failure_ab_assigned
|
105
|
+
redis_adapter, mocked_redis = stub_redis
|
106
|
+
mocked_redis.stubs(:sismember).raises(RuntimeError)
|
107
|
+
|
108
|
+
assert_nothing_raised do
|
109
|
+
redis_adapter.ab_assigned("price_options", "3ff62e2fb51f0b22646a342a2d357aec")
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
def test_graceful_failure_ab_add_conversion
|
114
|
+
redis_adapter, mocked_redis = stub_redis
|
115
|
+
mocked_redis.stubs(:sismember).raises(RuntimeError)
|
116
|
+
|
117
|
+
assert_nothing_raised do
|
118
|
+
redis_adapter.ab_add_conversion("price_options", 0, "3ff62e2fb51f0b22646a342a2d357aec")
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
17
122
|
end
|
@@ -1,5 +1,22 @@
|
|
1
|
+
# Based on https://github.com/plataformatec/devise/blob/master/test/rails_app/config/database.yml
|
2
|
+
|
3
|
+
# SQLite version 3.x
|
4
|
+
# gem install sqlite3
|
5
|
+
#
|
6
|
+
# Ensure the SQLite 3 gem is defined in your Gemfile
|
7
|
+
# gem 'sqlite3'
|
8
|
+
|
9
|
+
# Set databases in all environments since we may test loading Rails in non-
|
10
|
+
# test environments
|
11
|
+
|
12
|
+
development:
|
13
|
+
adapter: sqlite3
|
14
|
+
database: ":memory:"
|
15
|
+
|
1
16
|
test:
|
2
|
-
adapter:
|
3
|
-
database:
|
4
|
-
|
5
|
-
|
17
|
+
adapter: sqlite3
|
18
|
+
database: ":memory:"
|
19
|
+
|
20
|
+
production:
|
21
|
+
adapter: sqlite3
|
22
|
+
database: ":memory:"
|
data/test/dummy/config/routes.rb
CHANGED
@@ -54,5 +54,5 @@ Dummy::Application.routes.draw do
|
|
54
54
|
|
55
55
|
# This is a legacy wild controller route that's not recommended for RESTful applications.
|
56
56
|
# Note: This route will make all actions in every controller accessible via GET requests.
|
57
|
-
match ':controller(/:action(/:id(.:format)))', :via => [:get]
|
57
|
+
match ':controller(/:action(/:id(.:format)))', :via => [:get, :post]
|
58
58
|
end
|
data/test/experiment/ab_test.rb
CHANGED
@@ -133,7 +133,7 @@ class AbTestTest < ActionController::TestCase
|
|
133
133
|
|
134
134
|
# -- use_js! --
|
135
135
|
|
136
|
-
def
|
136
|
+
def test_choose_does_not_record_participant_when_using_js
|
137
137
|
Vanity.playground.use_js!
|
138
138
|
ids = (0...10).to_a
|
139
139
|
new_ab_test :foobar do
|
@@ -160,6 +160,44 @@ class AbTestTest < ActionController::TestCase
|
|
160
160
|
assert_equal 1, on_assignment_called_times
|
161
161
|
end
|
162
162
|
|
163
|
+
def test_calls_on_assignment_when_given_valid_request
|
164
|
+
on_assignment_called_times = 0
|
165
|
+
new_ab_test :foobar do
|
166
|
+
alternatives "foo", "bar"
|
167
|
+
identify { "6e98ec" }
|
168
|
+
metrics :coolness
|
169
|
+
on_assignment { on_assignment_called_times = on_assignment_called_times+1 }
|
170
|
+
end
|
171
|
+
experiment(:foobar).choose(dummy_request)
|
172
|
+
assert_equal 1, on_assignment_called_times
|
173
|
+
end
|
174
|
+
|
175
|
+
def test_does_not_call_on_assignment_when_given_invalid_request
|
176
|
+
on_assignment_called_times = 0
|
177
|
+
new_ab_test :foobar do
|
178
|
+
alternatives "foo", "bar"
|
179
|
+
identify { "6e98ec" }
|
180
|
+
metrics :coolness
|
181
|
+
on_assignment { on_assignment_called_times = on_assignment_called_times+1 }
|
182
|
+
end
|
183
|
+
request = dummy_request
|
184
|
+
request.user_agent = "Googlebot/2.1 ( http://www.google.com/bot.html)"
|
185
|
+
experiment(:foobar).choose(request)
|
186
|
+
assert_equal 0, on_assignment_called_times
|
187
|
+
end
|
188
|
+
|
189
|
+
def test_calls_on_assignment_on_new_assignment_via_chooses
|
190
|
+
on_assignment_called_times = 0
|
191
|
+
new_ab_test :foobar do
|
192
|
+
alternatives "foo", "bar"
|
193
|
+
identify { "6e98ec" }
|
194
|
+
metrics :coolness
|
195
|
+
on_assignment { on_assignment_called_times = on_assignment_called_times+1 }
|
196
|
+
end
|
197
|
+
2.times { experiment(:foobar).chooses("foo") }
|
198
|
+
assert_equal 1, on_assignment_called_times
|
199
|
+
end
|
200
|
+
|
163
201
|
def test_returns_the_same_alternative_consistently_when_on_assignment_is_set
|
164
202
|
new_ab_test :foobar do
|
165
203
|
alternatives "foo", "bar"
|
@@ -344,6 +382,27 @@ class AbTestTest < ActionController::TestCase
|
|
344
382
|
assert_equal 100, alts.map(&:converted).sum
|
345
383
|
end
|
346
384
|
|
385
|
+
def test_choose_records_participants_given_a_valid_request
|
386
|
+
new_ab_test :foobar do
|
387
|
+
alternatives "foo", "bar"
|
388
|
+
identify { "me" }
|
389
|
+
metrics :coolness
|
390
|
+
end
|
391
|
+
experiment(:foobar).choose(dummy_request)
|
392
|
+
assert_equal 1, experiment(:foobar).alternatives.map(&:participants).sum
|
393
|
+
end
|
394
|
+
|
395
|
+
def test_choose_ignores_participants_given_an_invalid_request
|
396
|
+
new_ab_test :foobar do
|
397
|
+
alternatives "foo", "bar"
|
398
|
+
identify { "me" }
|
399
|
+
metrics :coolness
|
400
|
+
end
|
401
|
+
request = dummy_request
|
402
|
+
request.user_agent = "Googlebot/2.1 ( http://www.google.com/bot.html)"
|
403
|
+
experiment(:foobar).choose(request)
|
404
|
+
assert_equal 0, experiment(:foobar).alternatives.map(&:participants).sum
|
405
|
+
end
|
347
406
|
|
348
407
|
def test_destroy_experiment
|
349
408
|
new_ab_test :simple do
|
@@ -465,6 +524,7 @@ class AbTestTest < ActionController::TestCase
|
|
465
524
|
|
466
525
|
|
467
526
|
# -- Scoring --
|
527
|
+
|
468
528
|
def test_calculate_score
|
469
529
|
new_ab_test :abcd do
|
470
530
|
alternatives :a, :b, :c, :d
|
@@ -488,10 +548,10 @@ class AbTestTest < ActionController::TestCase
|
|
488
548
|
metrics :coolness
|
489
549
|
end
|
490
550
|
# participating, conversions, rate, z-score
|
491
|
-
# Control: 182
|
492
|
-
# Treatment A: 180
|
493
|
-
# treatment B: 189
|
494
|
-
# treatment C: 188
|
551
|
+
# Control: 182 35 19.23% N/A
|
552
|
+
# Treatment A: 180 45 25.00% 1.33
|
553
|
+
# treatment B: 189 28 14.81% -1.13
|
554
|
+
# treatment C: 188 61 32.45% 2.94
|
495
555
|
fake :abcd, :a=>[182, 35], :b=>[180, 45], :c=>[189,28], :d=>[188, 61]
|
496
556
|
|
497
557
|
z_scores = experiment(:abcd).score.alts.map { |alt| "%.2f" % alt.z_score }
|
@@ -514,10 +574,10 @@ class AbTestTest < ActionController::TestCase
|
|
514
574
|
metrics :coolness
|
515
575
|
end
|
516
576
|
# participating, conversions, rate, z-score
|
517
|
-
# Control: 182
|
518
|
-
# Treatment A: 180
|
519
|
-
# treatment B: 189
|
520
|
-
# treatment C: 188
|
577
|
+
# Control: 182 35 19.23% N/A
|
578
|
+
# Treatment A: 180 45 25.00% 1.33
|
579
|
+
# treatment B: 189 28 14.81% -1.13
|
580
|
+
# treatment C: 188 61 32.45% 2.94
|
521
581
|
fake :abcd, :a=>[182, 35], :b=>[180, 45], :c=>[189,28], :d=>[188, 61]
|
522
582
|
|
523
583
|
score_result = experiment(:abcd).bayes_bandit_score
|
@@ -593,10 +653,10 @@ class AbTestTest < ActionController::TestCase
|
|
593
653
|
metrics :coolness
|
594
654
|
end
|
595
655
|
# participating, conversions, rate, z-score
|
596
|
-
# Control: 182
|
597
|
-
# Treatment A: 180
|
598
|
-
# treatment B: 189
|
599
|
-
# treatment C: 188
|
656
|
+
# Control: 182 35 19.23% N/A
|
657
|
+
# Treatment A: 180 45 25.00% 1.33
|
658
|
+
# treatment B: 189 28 14.81% -1.13
|
659
|
+
# treatment C: 188 61 32.45% 2.94
|
600
660
|
fake :abcd, :a=>[182, 35], :b=>[180, 45], :c=>[189,28], :d=>[188, 61]
|
601
661
|
|
602
662
|
assert_equal <<-TEXT, experiment(:abcd).conclusion.join("\n") << "\n"
|
@@ -919,6 +979,26 @@ This experiment did not run long enough to find a clear winner.
|
|
919
979
|
assert_equal experiment(:simple).alternatives[2].participants, 1
|
920
980
|
end
|
921
981
|
|
982
|
+
def test_chooses_records_participants_given_a_valid_request
|
983
|
+
new_ab_test :simple do
|
984
|
+
alternatives :a, :b, :c
|
985
|
+
metrics :coolness
|
986
|
+
end
|
987
|
+
experiment(:simple).chooses(:a, dummy_request)
|
988
|
+
assert_equal 1, experiment(:simple).alternatives[0].participants
|
989
|
+
end
|
990
|
+
|
991
|
+
def test_chooses_ignores_participants_given_an_invalid_request
|
992
|
+
new_ab_test :simple do
|
993
|
+
alternatives :a, :b, :c
|
994
|
+
metrics :coolness
|
995
|
+
end
|
996
|
+
request = dummy_request
|
997
|
+
request.user_agent = "Googlebot/2.1 ( http://www.google.com/bot.html)"
|
998
|
+
experiment(:simple).chooses(:a, request)
|
999
|
+
assert_equal 0, experiment(:simple).alternatives[0].participants
|
1000
|
+
end
|
1001
|
+
|
922
1002
|
def test_no_collection_and_chooses
|
923
1003
|
not_collecting!
|
924
1004
|
new_ab_test :simple do
|
@@ -1,10 +1,12 @@
|
|
1
1
|
require "test/test_helper"
|
2
2
|
|
3
3
|
class Sky < ActiveRecord::Base
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
4
|
+
if connected?
|
5
|
+
connection.drop_table :skies if table_exists?
|
6
|
+
connection.create_table :skies do |t|
|
7
|
+
t.integer :height
|
8
|
+
t.timestamps
|
9
|
+
end
|
8
10
|
end
|
9
11
|
|
10
12
|
if defined?(Rails::Railtie)
|
@@ -14,6 +16,7 @@ class Sky < ActiveRecord::Base
|
|
14
16
|
end
|
15
17
|
end
|
16
18
|
|
19
|
+
if ActiveRecord::Base.connected?
|
17
20
|
|
18
21
|
context "ActiveRecord Metric" do
|
19
22
|
|
@@ -305,3 +308,5 @@ context "ActiveRecord Metric" do
|
|
305
308
|
end
|
306
309
|
end
|
307
310
|
end
|
311
|
+
|
312
|
+
end
|
data/test/passenger_test.rb
CHANGED
@@ -1,51 +1,52 @@
|
|
1
1
|
require "test/test_helper"
|
2
2
|
|
3
|
-
#
|
4
|
-
|
5
|
-
require "phusion_passenger/spawn_manager"
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
3
|
+
# Not supported for rails3
|
4
|
+
if !defined?(Rails::Railtie) && ActiveRecord::Base.connected?
|
5
|
+
require "phusion_passenger/spawn_manager"
|
6
|
+
|
7
|
+
class PassengerTest < Test::Unit::TestCase
|
8
|
+
def setup
|
9
|
+
super
|
10
|
+
ActiveRecord::Base.connection.disconnect! # Otherwise AR metric tests fail
|
11
|
+
@original = Vanity.playground.connection
|
12
|
+
File.unlink "test/myapp/config/vanity.yml" rescue nil
|
13
|
+
File.open("test/myapp/config/vanity.yml", "w") do |io|
|
14
|
+
io.write YAML.dump({ "production"=>DATABASE })
|
15
|
+
end
|
16
|
+
@server = PhusionPassenger::SpawnManager.new
|
17
|
+
@server.start
|
18
|
+
Thread.pass until @server.started?
|
19
|
+
app_root = File.expand_path("myapp", File.dirname(__FILE__))
|
20
|
+
@app = @server.spawn_application "app_root"=>app_root, "spawn_method"=>"smart"
|
14
21
|
end
|
15
|
-
@server = PhusionPassenger::SpawnManager.new
|
16
|
-
@server.start
|
17
|
-
Thread.pass until @server.started?
|
18
|
-
app_root = File.expand_path("myapp", File.dirname(__FILE__))
|
19
|
-
@app = @server.spawn_application "app_root"=>app_root, "spawn_method"=>"smart"
|
20
|
-
end
|
21
22
|
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
23
|
+
def test_reconnect
|
24
|
+
# When using AR adapter, we're not responsible to reconnect, and we're going
|
25
|
+
# to get the same "connect" (AR connection handler) either way.
|
26
|
+
# return if defined?(Vanity::Adapters::ActiveRecordAdapter) && Vanity::Adapters::ActiveRecordAdapter === Vanity.playground.connection
|
26
27
|
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
28
|
+
sleep 0.1
|
29
|
+
case @app.listen_socket_type
|
30
|
+
when "tcp" ; socket = TCPSocket.new(*@app.listen_socket_name.split(":"))
|
31
|
+
when "unix"; socket = UNIXSocket.new(@app.listen_socket_name)
|
32
|
+
else fail
|
33
|
+
end
|
34
|
+
channel = PhusionPassenger::MessageChannel.new(socket)
|
35
|
+
request = {"REQUEST_PATH"=>"/", "REQUEST_METHOD"=>"GET", "QUERY_STRING"=>" "}
|
36
|
+
channel.write_scalar request.to_a.join("\0")
|
37
|
+
response = socket.read.split("\r\n\r\n").last
|
38
|
+
socket.close
|
39
|
+
conn, obj_id = response.split("\n")
|
40
|
+
assert_equal @original.to_s, conn
|
41
|
+
assert_not_equal @original.object_id.to_s, obj_id
|
32
42
|
end
|
33
|
-
channel = PhusionPassenger::MessageChannel.new(socket)
|
34
|
-
request = {"REQUEST_PATH"=>"/", "REQUEST_METHOD"=>"GET", "QUERY_STRING"=>" "}
|
35
|
-
channel.write_scalar request.to_a.join("\0")
|
36
|
-
response = socket.read.split("\r\n\r\n").last
|
37
|
-
socket.close
|
38
|
-
conn, obj_id = response.split("\n")
|
39
|
-
assert_equal @original.to_s, conn
|
40
|
-
assert_not_equal @original.object_id.to_s, obj_id
|
41
|
-
end
|
42
43
|
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
44
|
+
def teardown
|
45
|
+
super
|
46
|
+
@server.cleanup
|
47
|
+
@server.stop
|
48
|
+
Process.kill('SIGKILL', @app.pid.to_i) # Just in case...KIDS, GET OUT OF THE POOL!
|
49
|
+
File.unlink "test/myapp/config/vanity.yml"
|
50
|
+
end
|
49
51
|
end
|
50
52
|
end
|
51
|
-
end
|