yarn 0.0.1 → 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +1 -0
- data/Gemfile +0 -3
- data/README.md +25 -1
- data/bin/yarn +6 -4
- data/features/concurrency.feature +4 -4
- data/features/dynamic_request.feature +6 -1
- data/features/rack.feature +5 -8
- data/features/static_request.feature +2 -2
- data/features/step_definitions/rack_steps.rb +13 -0
- data/features/step_definitions/server_steps.rb +5 -5
- data/features/step_definitions/web_steps.rb +8 -0
- data/lib/rack/handler/yarn.rb +4 -3
- data/lib/yarn/error_page.rb +2 -1
- data/lib/yarn/logging.rb +1 -1
- data/lib/yarn/parslet_parser.rb +9 -24
- data/lib/yarn/rack_handler.rb +11 -9
- data/lib/yarn/request_handler.rb +21 -12
- data/lib/yarn/server.rb +39 -30
- data/lib/yarn/version.rb +1 -1
- data/spec/helpers.rb +16 -8
- data/spec/rack/handler/yarn_spec.rb +21 -0
- data/spec/spec_helper.rb +1 -4
- data/spec/yarn/directory_lister_spec.rb +0 -5
- data/spec/yarn/logging_spec.rb +3 -2
- data/spec/yarn/parslet_parser_spec.rb +26 -0
- data/spec/yarn/rack_handler_spec.rb +15 -4
- data/spec/yarn/request_handler_spec.rb +17 -7
- data/spec/yarn/server_spec.rb +49 -8
- data/test_objects/.gitignore +1 -0
- data/test_objects/app.rb +0 -2
- data/test_objects/config.ru +1 -49
- data/test_objects/rails_test/.gitignore +5 -0
- data/test_objects/rails_test/Gemfile +34 -0
- data/test_objects/rails_test/README +261 -0
- data/test_objects/rails_test/Rakefile +7 -0
- data/test_objects/rails_test/app/assets/images/rails.png +0 -0
- data/test_objects/rails_test/app/assets/javascripts/application.js +6 -0
- data/test_objects/rails_test/app/assets/stylesheets/application.css +7 -0
- data/test_objects/rails_test/app/assets/stylesheets/scaffolds.css.scss +56 -0
- data/test_objects/rails_test/app/mailers/.gitkeep +0 -0
- data/test_objects/rails_test/app/models/.gitkeep +0 -0
- data/test_objects/rails_test/app/views/layouts/application.html.erb +15 -0
- data/test_objects/rails_test/app/views/posts/_form.html.erb +25 -0
- data/test_objects/rails_test/app/views/posts/edit.html.erb +6 -0
- data/test_objects/rails_test/app/views/posts/index.html.erb +20 -0
- data/test_objects/rails_test/app/views/posts/new.html.erb +5 -0
- data/test_objects/rails_test/app/views/posts/show.html.erb +15 -0
- data/test_objects/rails_test/config.ru +4 -0
- data/test_objects/rails_test/config/database.yml +25 -0
- data/test_objects/rails_test/config/locales/en.yml +5 -0
- data/test_objects/rails_test/doc/README_FOR_APP +2 -0
- data/test_objects/rails_test/lib/assets/.gitkeep +0 -0
- data/test_objects/rails_test/lib/tasks/.gitkeep +0 -0
- data/test_objects/rails_test/log/.gitkeep +0 -0
- data/test_objects/rails_test/public/404.html +26 -0
- data/test_objects/rails_test/public/422.html +26 -0
- data/test_objects/rails_test/public/500.html +26 -0
- data/test_objects/rails_test/public/favicon.ico +0 -0
- data/test_objects/rails_test/public/robots.txt +5 -0
- data/test_objects/rails_test/script/rails +6 -0
- data/test_objects/rails_test/test/fixtures/.gitkeep +0 -0
- data/test_objects/rails_test/test/fixtures/posts.yml +9 -0
- data/test_objects/rails_test/test/functional/.gitkeep +0 -0
- data/test_objects/rails_test/test/integration/.gitkeep +0 -0
- data/test_objects/rails_test/test/unit/.gitkeep +0 -0
- data/test_objects/rails_test/vendor/assets/stylesheets/.gitkeep +0 -0
- data/test_objects/rails_test/vendor/plugins/.gitkeep +0 -0
- data/yarn.gemspec +4 -8
- metadata +59 -59
- data/lib/yarn/worker.rb +0 -19
- data/lib/yarn/worker_pool.rb +0 -36
- data/spec/yarn/worker_pool_spec.rb +0 -23
- data/spec/yarn/worker_spec.rb +0 -26
- data/test_objects/simple_rack.rb +0 -12
data/lib/yarn/version.rb
CHANGED
data/spec/helpers.rb
CHANGED
@@ -12,22 +12,28 @@ module Helpers
|
|
12
12
|
|
13
13
|
def get(url)
|
14
14
|
setup
|
15
|
-
|
15
|
+
if url == ""
|
16
|
+
@connection.get "/"
|
17
|
+
else
|
18
|
+
@connection.get "test_objects#{url}"
|
19
|
+
end
|
16
20
|
end
|
17
21
|
|
18
|
-
def post(url,
|
22
|
+
def post(url, data)
|
19
23
|
setup
|
20
|
-
@connection.post url,
|
24
|
+
@connection.post url, data
|
21
25
|
end
|
22
26
|
|
23
27
|
def stop_server
|
24
28
|
@thread.kill if @thread
|
29
|
+
@server.workers.each { |worker_id| Process.kill("INT", worker_id) } if @server and !@server.workers.empty?
|
25
30
|
@server.stop if @server
|
31
|
+
sleep 0.1 # enable socket to close before next test
|
26
32
|
end
|
27
33
|
|
28
|
-
def start_server(port=3000,
|
29
|
-
$console
|
30
|
-
@server = Yarn::Server.new({ port: port, output: $console })
|
34
|
+
def start_server(port=3000,rack="off")
|
35
|
+
$console ||= MockIO.new
|
36
|
+
@server = Yarn::Server.new({ port: port, output: $console, rack: rack, debug: true })
|
31
37
|
@thread = Thread.new { @server.start }
|
32
38
|
sleep 0.1 until @server.socket # wait for socket to be created
|
33
39
|
end
|
@@ -49,8 +55,10 @@ module Helpers
|
|
49
55
|
private
|
50
56
|
|
51
57
|
def setup
|
52
|
-
host =
|
53
|
-
|
58
|
+
host = "127.0.0.1"
|
59
|
+
port = "3000"
|
60
|
+
uri = URI.parse("http://#{host}:#{port}")
|
61
|
+
@connection = Faraday.new(uri)
|
54
62
|
end
|
55
63
|
end
|
56
64
|
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module Rack
|
4
|
+
module Handler
|
5
|
+
|
6
|
+
include Helpers
|
7
|
+
|
8
|
+
# describe Yarn do
|
9
|
+
# after do
|
10
|
+
# @thread.kill
|
11
|
+
# end
|
12
|
+
|
13
|
+
# it "should start the server" do
|
14
|
+
# @thread = Thread.new { Yarn.run("test_objects/config.ru") }
|
15
|
+
# response = get("/").body
|
16
|
+
# response.gsub(/\n?/,"").should == "Rack works"
|
17
|
+
# end
|
18
|
+
# end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
data/spec/spec_helper.rb
CHANGED
@@ -2,21 +2,18 @@ $LOAD_PATH << File.expand_path('../../../lib', __FILE__)
|
|
2
2
|
|
3
3
|
require 'rubygems'
|
4
4
|
require 'bundler/setup'
|
5
|
-
require 'fakefs'
|
6
5
|
|
7
6
|
# unless /jruby/ =~ `ruby -v`
|
8
7
|
require 'simplecov'
|
9
8
|
SimpleCov.start do
|
10
|
-
FakeFS.deactivate!
|
11
9
|
add_filter "/spec/"
|
12
10
|
add_filter "lib/yarn/http*"
|
13
11
|
end
|
14
12
|
# end
|
15
13
|
|
16
|
-
require 'capybara/rspec'
|
17
|
-
|
18
14
|
require 'yarn'
|
19
15
|
require 'helpers'
|
16
|
+
require 'pry'
|
20
17
|
|
21
18
|
RSpec.configure do |config|
|
22
19
|
config.include Helpers
|
@@ -5,10 +5,6 @@ module Yarn
|
|
5
5
|
|
6
6
|
describe DirectoryLister do
|
7
7
|
|
8
|
-
before(:each) do
|
9
|
-
FakeFS.deactivate!
|
10
|
-
end
|
11
|
-
|
12
8
|
describe "#list" do
|
13
9
|
it "returns valid HTML for a directory" do
|
14
10
|
response = DirectoryLister.list("lib")
|
@@ -17,7 +13,6 @@ module Yarn
|
|
17
13
|
end
|
18
14
|
|
19
15
|
it "returns valid HTML a long path" do
|
20
|
-
FakeFS.deactivate!
|
21
16
|
response = DirectoryLister.list("lib/yarn")
|
22
17
|
response.should_not be_nil
|
23
18
|
valid_html?(response).should be_true
|
data/spec/yarn/logging_spec.rb
CHANGED
@@ -10,10 +10,10 @@ module Yarn
|
|
10
10
|
|
11
11
|
describe "#log" do
|
12
12
|
it "should make the logging methods available" do
|
13
|
-
@server = Server.new(output: $output)
|
13
|
+
@server = Server.new(output: $output, debug: true)
|
14
14
|
@server.should respond_to(:log)
|
15
15
|
@server.should respond_to(:debug)
|
16
|
-
@server.
|
16
|
+
@server.stop
|
17
17
|
end
|
18
18
|
|
19
19
|
it "should be available in the handler classes" do
|
@@ -41,6 +41,7 @@ module Yarn
|
|
41
41
|
|
42
42
|
describe "#debug" do
|
43
43
|
it "should invoke the log method with a message" do
|
44
|
+
$debug = true
|
44
45
|
test_logger = TestLoggging.new
|
45
46
|
test_logger.should_receive(:log).with("DEBUG: testing").once
|
46
47
|
|
@@ -56,6 +56,13 @@ module Yarn
|
|
56
56
|
puts result
|
57
57
|
result[:uri][:query].should == "param1=1¶m2=2"
|
58
58
|
end
|
59
|
+
|
60
|
+
it "should parse query on rails assets" do
|
61
|
+
result = @parser.run("GET assets/application.js?body=0 HTTP/1.1\n")
|
62
|
+
puts result
|
63
|
+
result[:uri][:query].should == "body=0"
|
64
|
+
result[:uri][:path].should == "assets/application.js"
|
65
|
+
end
|
59
66
|
end
|
60
67
|
|
61
68
|
describe "#parse headers" do
|
@@ -95,5 +102,24 @@ module Yarn
|
|
95
102
|
end
|
96
103
|
end
|
97
104
|
|
105
|
+
describe "#parse POST body" do
|
106
|
+
it "should parse POST body" do
|
107
|
+
header = "Cookie: $Version=1; Skin=new;"
|
108
|
+
body = "attr=test"
|
109
|
+
request = "POST /form HTTP/1.1\r\n#{header}\r\n\r\n#{body}"
|
110
|
+
result = @parser.run(request)
|
111
|
+
result[:body].should == body
|
112
|
+
end
|
113
|
+
|
114
|
+
it "should parse POST body with added line ending" do
|
115
|
+
header = "Cookie: $Version=1; Skin=new;"
|
116
|
+
body = "attr=test&attr2=some_other_value&attr3=1231682368125361823"
|
117
|
+
request = "POST /form HTTP/1.1\r\n#{header}\r\n\r\n#{body}"
|
118
|
+
result = @parser.run(request)
|
119
|
+
puts result
|
120
|
+
result[:body].should == body
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
98
124
|
end
|
99
125
|
end
|
@@ -3,15 +3,26 @@ require 'spec_helper'
|
|
3
3
|
module Yarn
|
4
4
|
describe RackHandler do
|
5
5
|
|
6
|
+
before(:each) do
|
7
|
+
@handler = RackHandler.new(nil)
|
8
|
+
@handler.request = @handler.parser.run "GET http://www.hostname.com:8888/some_controller/some_action?param1=1¶m2=2 HTTP/1.1"
|
9
|
+
end
|
10
|
+
|
6
11
|
describe "#prepare_response" do
|
7
|
-
|
12
|
+
it "should call make_env" do
|
13
|
+
@app.stub(:call).and_return([200, {}, []])
|
14
|
+
@handler.prepare_response
|
15
|
+
@handler.env.should_not be_nil
|
16
|
+
end
|
17
|
+
|
18
|
+
it "should call the rack app" do
|
19
|
+
@app.should_receive(:call)
|
20
|
+
@handler.prepare_response
|
21
|
+
end
|
8
22
|
end
|
9
23
|
|
10
24
|
describe "#make_env" do
|
11
|
-
|
12
25
|
before(:each) do
|
13
|
-
@handler = RackHandler.new(nil,{})
|
14
|
-
@handler.request = @handler.parser.run "GET http://www.hostname.com:8888/some_controller/some_action?param1=1¶m2=2 HTTP/1.1"
|
15
26
|
@env = @handler.make_env
|
16
27
|
end
|
17
28
|
|
@@ -25,6 +25,15 @@ module Yarn
|
|
25
25
|
|
26
26
|
@handler.read_request.should == "line1\nline2\nline3"
|
27
27
|
end
|
28
|
+
|
29
|
+
it "should handle POST body" do
|
30
|
+
@req = "POST /app HTTP/1.1\nCookie: $key=value;\nContent-Length: 17;\n\r\nfield1=1&field2=2"
|
31
|
+
@handler.unstub!(:read_request)
|
32
|
+
@handler.session = StringIO.new
|
33
|
+
@handler.session.string = @req
|
34
|
+
|
35
|
+
@handler.read_request.should == @req
|
36
|
+
end
|
28
37
|
end
|
29
38
|
|
30
39
|
describe "#parse_request" do
|
@@ -86,22 +95,23 @@ module Yarn
|
|
86
95
|
@handler = RequestHandler.new
|
87
96
|
@handler.session = @session
|
88
97
|
|
89
|
-
FakeFS.activate!
|
90
98
|
@file_content = "<html><body>success!</body></html>"
|
91
99
|
@file = File.open("index.html", 'w') do |file|
|
92
100
|
file.write @file_content
|
93
101
|
end
|
102
|
+
Dir.mkdir("testdir") unless Dir.exists?("testdir")
|
94
103
|
end
|
95
104
|
|
96
105
|
after(:each) do
|
97
106
|
@handler.close_connection
|
98
|
-
|
107
|
+
File.delete("index.html") if File.exists?("index.html")
|
108
|
+
File.delete("testdir/index.html") if File.exists?("testdir/index.html")
|
109
|
+
Dir.delete("testdir") if Dir.exists?("testdir")
|
99
110
|
end
|
100
111
|
|
101
112
|
describe "#prepare_response" do
|
102
113
|
it "should handle a directory" do
|
103
114
|
File.delete("index.html")
|
104
|
-
Dir.mkdir("testdir")
|
105
115
|
@handler.stub(:extract_path).and_return("testdir")
|
106
116
|
@handler.should_receive(:serve_directory).once
|
107
117
|
@handler.prepare_response
|
@@ -112,6 +122,7 @@ module Yarn
|
|
112
122
|
@handler.stub(:extract_path).and_return("test.html")
|
113
123
|
@handler.should_receive(:serve_file).once
|
114
124
|
@handler.prepare_response
|
125
|
+
File.delete("test.html")
|
115
126
|
end
|
116
127
|
|
117
128
|
it "handles missing files" do
|
@@ -130,10 +141,9 @@ module Yarn
|
|
130
141
|
|
131
142
|
describe "#serve_directory" do
|
132
143
|
it "should read index file if it exists" do
|
133
|
-
|
134
|
-
File.new("test/index.html", "w")
|
144
|
+
File.new("testdir/index.html", "w")
|
135
145
|
@handler.should_receive(:read_file).once
|
136
|
-
@handler.serve_directory("
|
146
|
+
@handler.serve_directory("testdir")
|
137
147
|
end
|
138
148
|
|
139
149
|
it "should list a directory" do
|
@@ -144,7 +154,7 @@ module Yarn
|
|
144
154
|
end
|
145
155
|
|
146
156
|
describe "#read_file" do
|
147
|
-
it "should return the contents of a file
|
157
|
+
it "should return the contents of a file" do
|
148
158
|
@handler.response.body.should be_empty
|
149
159
|
@handler.read_file("index.html").should == [@file_content]
|
150
160
|
end
|
data/spec/yarn/server_spec.rb
CHANGED
@@ -5,25 +5,66 @@ module Yarn
|
|
5
5
|
|
6
6
|
after(:each) do
|
7
7
|
stop_server
|
8
|
-
|
8
|
+
end
|
9
|
+
|
10
|
+
describe "#new" do
|
11
|
+
end
|
12
|
+
|
13
|
+
describe "#load_rack_app" do
|
14
|
+
|
15
|
+
before(:each) do
|
16
|
+
$console = MockIO.new
|
17
|
+
@server = Server.new( output: $console )
|
18
|
+
end
|
19
|
+
|
20
|
+
it "should print a message and exit if the file does not exist" do
|
21
|
+
Kernel.should_receive(:exit)
|
22
|
+
@server.load_rack_app("non-existing-app.ru")
|
23
|
+
$console.should include("non-existing-app.ru does not exist. Exiting.")
|
24
|
+
end
|
25
|
+
|
26
|
+
it "should return a rack app if the file exists" do
|
27
|
+
app = @server.load_rack_app("test_objects/config.ru")
|
28
|
+
app.class.should == Rack::Builder
|
29
|
+
end
|
9
30
|
end
|
10
31
|
|
11
32
|
describe "#start" do
|
12
|
-
it "creates a TCP server" do
|
13
|
-
|
14
|
-
@server.
|
33
|
+
it "should creates a TCP server" do
|
34
|
+
@server = Server.new
|
35
|
+
@server.stub(:init_workers)
|
36
|
+
@server.start
|
37
|
+
|
38
|
+
@server.socket.class.should == TCPServer
|
15
39
|
end
|
16
40
|
|
17
|
-
it "
|
18
|
-
@server = Server.new(
|
41
|
+
it "should listen on the supplied port" do
|
42
|
+
@server = Server.new({ port: 4000 })
|
43
|
+
@server.stub(:init_workers)
|
44
|
+
@server.start
|
19
45
|
|
20
46
|
@server.socket.addr.should include(4000)
|
21
47
|
end
|
22
48
|
end
|
23
49
|
|
50
|
+
# describe "#start" do
|
51
|
+
# it "should start the socket_listener" do
|
52
|
+
# @thread = Thread.new do
|
53
|
+
# @server = Server.new({ output: $console })
|
54
|
+
# @server.start
|
55
|
+
# end
|
56
|
+
# sleep 2
|
57
|
+
# get("/").should be_true
|
58
|
+
# @thread.kill
|
59
|
+
# end
|
60
|
+
# end
|
61
|
+
|
24
62
|
describe "#stop" do
|
25
|
-
it "
|
26
|
-
|
63
|
+
it "should notify the server is stopped" do
|
64
|
+
$console = MockIO.new
|
65
|
+
@server = Server.new({ output: $console })
|
66
|
+
@server.stub(:init_workers)
|
67
|
+
@server.start
|
27
68
|
@server.stop
|
28
69
|
|
29
70
|
$console.should include("Server stopped")
|
data/test_objects/.gitignore
CHANGED
data/test_objects/app.rb
CHANGED
data/test_objects/config.ru
CHANGED
@@ -1,54 +1,6 @@
|
|
1
1
|
require 'rubygems'
|
2
2
|
require 'rack'
|
3
3
|
|
4
|
-
# The root of our app
|
5
|
-
@root = File.expand_path(File.dirname(__FILE__))
|
6
|
-
|
7
4
|
run Proc.new { |env|
|
8
|
-
|
9
|
-
path = Rack::Utils.unescape(env['PATH_INFO'])
|
10
|
-
index_file = @root + "#{path}/index.html"
|
11
|
-
|
12
|
-
if File.exists?(index_file)
|
13
|
-
# Return the index
|
14
|
-
[200, {'Content-Type' => get_mime_type(index_file)}, read_file(index_file)]
|
15
|
-
elsif File.exists?(path) && !File.directory?(path)
|
16
|
-
# Return the file
|
17
|
-
[200, {'Content-Type' => get_mime_type(path)}, read_file(path)]
|
18
|
-
else
|
19
|
-
# Return a directory listing
|
20
|
-
Rack::Directory.new(@root).call(env)
|
21
|
-
end
|
5
|
+
[200, {'Content-Type' => "text/plain"}, ["Rack works"]]
|
22
6
|
}
|
23
|
-
|
24
|
-
def read_file(path)
|
25
|
-
file_contents = []
|
26
|
-
File.open(path, "r") do |file|
|
27
|
-
while (line = file.gets) do
|
28
|
-
file_contents << line
|
29
|
-
end
|
30
|
-
end
|
31
|
-
file_contents
|
32
|
-
end
|
33
|
-
|
34
|
-
|
35
|
-
def get_mime_type(path)
|
36
|
-
return false unless path.include? '.'
|
37
|
-
filetype = path.split('.').last
|
38
|
-
|
39
|
-
return case
|
40
|
-
when ["html", "htm"].include?(filetype)
|
41
|
-
"text/html"
|
42
|
-
when "txt" == filetype
|
43
|
-
"text/plain"
|
44
|
-
when "css" == filetype
|
45
|
-
"text/css"
|
46
|
-
when "js" == filetype
|
47
|
-
"text/javascript"
|
48
|
-
when ["png", "jpg", "jpeg", "gif", "tiff"].include?(filetype)
|
49
|
-
"image/#{filetype}"
|
50
|
-
when ["zip","pdf","postscript","x-tar","x-dvi"].include?(filetype)
|
51
|
-
"application/#{filetype}"
|
52
|
-
else false
|
53
|
-
end
|
54
|
-
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
source 'http://rubygems.org'
|
2
|
+
|
3
|
+
gem 'rails', '3.1.0'
|
4
|
+
|
5
|
+
# Bundle edge Rails instead:
|
6
|
+
# gem 'rails', :git => 'git://github.com/rails/rails.git'
|
7
|
+
|
8
|
+
gem 'sqlite3'
|
9
|
+
gem 'yarn'
|
10
|
+
gem 'pry'
|
11
|
+
|
12
|
+
# Gems used only for assets and not required
|
13
|
+
# in production environments by default.
|
14
|
+
group :assets do
|
15
|
+
gem 'sass-rails', " ~> 3.1.0"
|
16
|
+
gem 'coffee-rails', "~> 3.1.0"
|
17
|
+
gem 'uglifier'
|
18
|
+
end
|
19
|
+
|
20
|
+
gem 'jquery-rails'
|
21
|
+
|
22
|
+
# Use unicorn as the web server
|
23
|
+
# gem 'unicorn'
|
24
|
+
|
25
|
+
# Deploy with Capistrano
|
26
|
+
# gem 'capistrano'
|
27
|
+
|
28
|
+
# To use debugger
|
29
|
+
# gem 'ruby-debug19', :require => 'ruby-debug'
|
30
|
+
|
31
|
+
group :test do
|
32
|
+
# Pretty printed test output
|
33
|
+
gem 'turn', :require => false
|
34
|
+
end
|