yarn 0.0.1 → 0.0.2
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/.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
|