ww 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
data/Rakefile ADDED
@@ -0,0 +1,112 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+ require 'rake/clean'
4
+ require 'rake/testtask'
5
+ require 'rake/packagetask'
6
+ require 'rake/gempackagetask'
7
+ require 'rake/rdoctask'
8
+ require 'fileutils'
9
+ require 'spec/rake/spectask'
10
+ require 'lib/ww'
11
+ include FileUtils
12
+
13
+ NAME = "ww"
14
+ AUTHOR = "moro"
15
+ EMAIL = "moronatural@gmail.com"
16
+ DESCRIPTION = "Double Web, framework to build double Web server."
17
+ HOMEPAGE = "http://github.com/moro/#{NAME}/"
18
+ BIN_FILES = %w( )
19
+
20
+ VERS = Ww::Version
21
+ REV = File.read(".svn/entries")[/committed-rev="(d+)"/, 1] rescue nil
22
+ CLEAN.include ['**/.*.sw?', '*.gem', '.config']
23
+ RDOC_OPTS = [
24
+ '--title', "#{NAME} documentation",
25
+ "--charset", "utf-8",
26
+ "--opname", "index.html",
27
+ "--line-numbers",
28
+ "--main", "README.rdoc",
29
+ "--inline-source",
30
+ ]
31
+
32
+ task :default => [:spec]
33
+ task :package => [:clean]
34
+
35
+ desc "Run all specs in spec directory"
36
+ Spec::Rake::SpecTask.new(:spec) do |t|
37
+ t.spec_opts = %w[--colour --format progress --loadby --reverse]
38
+ t.spec_files = FileList['spec/**/*_spec.rb']
39
+ end
40
+
41
+ spec = Gem::Specification.new do |s|
42
+ s.name = NAME
43
+ s.version = VERS
44
+ s.platform = Gem::Platform::RUBY
45
+ s.has_rdoc = true
46
+ # s.extra_rdoc_files = ["README.rdoc", "ChangeLog"]
47
+ s.rdoc_options += RDOC_OPTS + ['--exclude', '^(examples|extras)/']
48
+ s.summary = DESCRIPTION
49
+ s.description = DESCRIPTION
50
+ s.author = AUTHOR
51
+ s.email = EMAIL
52
+ s.homepage = HOMEPAGE
53
+ s.executables = BIN_FILES
54
+ s.bindir = "bin"
55
+ s.require_path = "lib"
56
+ s.test_files = Dir["test/*_test.rb"]
57
+
58
+ s.add_dependency('sinatra', '>=0.9.4')
59
+ s.add_dependency('rack', '>=1.0.1')
60
+ s.add_dependency('json')
61
+ #s.required_ruby_version = '>= 1.8.2'
62
+
63
+ s.files = %w(Rakefile) +
64
+ Dir.glob("{bin,doc,test,lib,templates,generator,extras,website,script}/**/*") +
65
+ Dir.glob("ext/**/*.{h,c,rb}") +
66
+ Dir.glob("examples/**/*.rb") +
67
+ Dir.glob("tools/*.rb") +
68
+ Dir.glob("rails/*.rb")
69
+
70
+ s.extensions = FileList["ext/**/extconf.rb"].to_a
71
+ end
72
+
73
+ Rake::GemPackageTask.new(spec) do |p|
74
+ p.need_tar = true
75
+ p.gem_spec = spec
76
+ end
77
+
78
+ task :install do
79
+ name = "#{NAME}-#{VERS}.gem"
80
+ sh %{rake package}
81
+ sh %{gem install pkg/#{name}}
82
+ end
83
+
84
+ task :uninstall => [:clean] do
85
+ sh %{gem uninstall #{NAME}}
86
+ end
87
+
88
+ desc 'Show information about the gem.'
89
+ task :debug_gem do
90
+ puts spec.to_ruby
91
+ end
92
+
93
+ desc 'Update gem spec'
94
+ task :gemspec do
95
+ open("#{NAME}.gemspec", 'w').write spec.to_ruby
96
+ end
97
+
98
+
99
+ Rake::RDocTask.new do |rdoc|
100
+ rdoc.rdoc_dir = 'html'
101
+ rdoc.options += RDOC_OPTS
102
+ rdoc.template = "resh"
103
+ #rdoc.template = "#{ENV['template']}.rb" if ENV['template']
104
+ if ENV['DOC_FILES']
105
+ rdoc.rdoc_files.include(ENV['DOC_FILES'].split(/,\s*/))
106
+ else
107
+ rdoc.rdoc_files.include('README.rdoc', 'ChangeLog')
108
+ rdoc.rdoc_files.include('lib/**/*.rb')
109
+ rdoc.rdoc_files.include('ext/**/*.c')
110
+ end
111
+ end
112
+
data/lib/ww.rb ADDED
@@ -0,0 +1,23 @@
1
+ require 'rubygems'
2
+ require 'rack'
3
+
4
+ module Ww
5
+ autoload :Servlet, 'ww/servlet'
6
+ autoload :SpyEye, 'ww/spy_eye'
7
+
8
+ Version = '0.2.0'
9
+
10
+ def to_app(spy_eye_path = "/spy", &block)
11
+ Rack::Builder.new {
12
+ use Rack::ShowExceptions
13
+
14
+ servlet = Servlet.base(&block)
15
+ spy = SpyEye.new(servlet)
16
+
17
+ map(spy_eye_path) { run spy }
18
+ map("/") { run servlet }
19
+ }
20
+ end
21
+ module_function :to_app
22
+ end
23
+
data/lib/ww/double.rb ADDED
@@ -0,0 +1,34 @@
1
+ require 'ww/double/stub'
2
+ require 'ww/double/mock'
3
+ require 'ww/double/spy'
4
+
5
+ module Ww
6
+ module Double
7
+ class Error < RuntimeError; end
8
+ class MockError < Error ; end
9
+
10
+ MODULES = [Stub, Mock, Spy].each do |mod|
11
+ include mod
12
+ end
13
+
14
+ def self.extended(base)
15
+ MODULES.each do |mod|
16
+ base.send(:include, mod::InstanceMethods) if mod.const_defined?("InstanceMethods")
17
+ end
18
+ end
19
+
20
+ def unbound_action(klass, mname, block)
21
+ ret = nil
22
+ klass.module_eval do
23
+ begin
24
+ define_method(mname, &block)
25
+ ret = instance_method(mname)
26
+ ensure
27
+ remove_method(mname) if instance_methods.include?(mname)
28
+ end
29
+ end
30
+ return ret
31
+ end
32
+ module_function :unbound_action
33
+ end
34
+ end
@@ -0,0 +1,33 @@
1
+ module Ww
2
+ module Double
3
+ module Mock
4
+ class Expectation
5
+ def executed!; @e = true; end
6
+ def executed?; !!@e; end
7
+ attr_reader :identifier
8
+ def initialize(verb, path)
9
+ @identifier = "_mock_ #{verb.to_s.upcase} #{path}"
10
+ end
11
+ end
12
+
13
+ def mock(verb, path, &block)
14
+ expectations << (expect = Expectation.new(verb, path))
15
+ action = Double.unbound_action(self, expect.identifier, block)
16
+
17
+ stub(verb, path) do |*args|
18
+ expect.executed!
19
+ action.bind(self).call(*args)
20
+ end
21
+ end
22
+
23
+ def verify
24
+ raise MockError unless expectations.all? {|mock| mock.executed? }
25
+ end
26
+
27
+ private
28
+ def expectations
29
+ @expectations ||= []
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,32 @@
1
+ require 'ww/store'
2
+ require 'ww/double/spy/request'
3
+
4
+ module Ww
5
+ module Double
6
+ module Spy
7
+ def spy(verb, path, &block)
8
+ action = Double.unbound_action(self, "_spy_ #{verb.to_s.upcase} #{path}", block)
9
+
10
+ stub(verb, path) do |*args|
11
+ spy!
12
+ action.bind(self).call(*args)
13
+ end
14
+ end
15
+
16
+ def requests
17
+ @requests ||= Store.new
18
+ end
19
+
20
+ def store(req)
21
+ requests.store(Request.new(req))
22
+ end
23
+
24
+ module InstanceMethods
25
+ def spy!
26
+ self.class.store(@request)
27
+ end
28
+ alias stump! spy!
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,48 @@
1
+ require 'rack/request'
2
+
3
+ autoload :JSON, 'json'
4
+ autoload :YAML, 'yaml'
5
+
6
+ module Ww::Double::Spy
7
+ class Request < ::Rack::Request
8
+ attr_reader :time
9
+ @@req_parsers = []
10
+
11
+ def self.regist_request_parser(pattern, &block)
12
+ @@req_parsers << [pattern, block]
13
+ end
14
+
15
+ regist_request_parser %r{[application|text]/json} do |body|
16
+ JSON.parse(body)
17
+ end
18
+
19
+ regist_request_parser %r{[application|text]/json} do |body|
20
+ JSON.parse(body)
21
+ end
22
+
23
+ regist_request_parser %r{[application|text]/yaml} do |body|
24
+ YAML.load(body)
25
+ end
26
+
27
+ def initialize(req_or_env)
28
+ env = req_or_env.is_a?(Rack::Request) ? req_or_env.env : req_or_env
29
+ super(env.dup)
30
+ @time = Time.now
31
+ end
32
+
33
+ def parsed_body
34
+ return "" if get?
35
+ return self.POST if form_data?
36
+
37
+ @body ||=
38
+ begin
39
+ body.read
40
+ ensure
41
+ body.rewind
42
+ end
43
+
44
+ _, processor = @@req_parsers.detect{|re, ignore| re =~ media_type }
45
+ processor ? processor.call(@body) : @body
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,14 @@
1
+ module Ww
2
+ module Double
3
+ module Stub
4
+ def stub(verb, path, &block)
5
+ v = verb.to_s.upcase
6
+
7
+ synchronize do
8
+ send(verb, path, &block)
9
+ routes[v].unshift(routes[v].pop)
10
+ end
11
+ end
12
+ end
13
+ end
14
+ end
data/lib/ww/servlet.rb ADDED
@@ -0,0 +1,19 @@
1
+ require 'sinatra/base'
2
+ require 'monitor'
3
+
4
+ module Ww
5
+ autoload :Double, 'ww/double'
6
+
7
+ class Servlet < Sinatra::Base
8
+ class << self
9
+ def base(&block)
10
+ Class.new(self).tap do |k|
11
+ k.extend Double
12
+ k.extend MonitorMixin
13
+ k.class_eval(&block)
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end
19
+
@@ -0,0 +1,95 @@
1
+ :ruby
2
+ require 'pp'
3
+ title = "#{requests.size} requests - Double Web"
4
+ !!!
5
+ %html
6
+ %head
7
+ %title&= title
8
+ %script{:src=>"http://ajax.googleapis.com/ajax/libs/jquery/1.3.1/jquery.min.js"}
9
+ %style{:type=>"text/css"}
10
+ :sass
11
+ body
12
+ width: 80%
13
+ margin: auto
14
+
15
+ h1
16
+ font-size: 10px
17
+
18
+ div.stump
19
+ font-size: 10px
20
+ border: 1px solid silver
21
+ padding: 0 1em
22
+
23
+ h2
24
+ font-size: 10px
25
+ color: gray
26
+
27
+ span.method, span.path
28
+ font-size: 16px
29
+ font-weight: normal
30
+ font-family: 'Courier', monospace
31
+
32
+ span.method
33
+ color: #090
34
+
35
+ span.path
36
+ color: black
37
+
38
+ span.time, span.source
39
+ color: blue
40
+
41
+ h3
42
+ font-size: small
43
+ border-bottom: 1px solid green
44
+ background: #cfb
45
+ padding: 2px 0 0 2px
46
+
47
+ span.media_type
48
+ color: blue
49
+ font-size: small
50
+ font-weight: normal
51
+ font-family: 'Courier', monospace
52
+
53
+ .headers table, div.body pre
54
+ border: 1px dashed green
55
+ margin: 1em
56
+ padding: 1em
57
+
58
+ div.body pre
59
+ overflow: auto
60
+ font-size: 12px
61
+ %body
62
+ %h1&= title
63
+ - requests.each do |wreq|
64
+ %div.stump{:id => wreq.object_id}
65
+ %h2
66
+ %span.method&= wreq.request_method
67
+ %span.path&= wreq.fullpath
68
+ on
69
+ %span.time&= wreq.time.iso8601
70
+ from
71
+ %span.source&= wreq.ip
72
+ %div
73
+ .headers
74
+ %h3 Headers
75
+ %table
76
+ - wreq.env.each do |k,v|
77
+ - next if k =~ /\A[a-z]/
78
+ %tr
79
+ %th&= k
80
+ %td&= v
81
+
82
+ - unless wreq.get?
83
+ .body
84
+ %h3
85
+ Body
86
+ %span.media_type= wreq.media_type
87
+ %pre&= wreq.parsed_body.pretty_inspect
88
+
89
+ :javascript
90
+ jQuery(function(){
91
+ $("div.stump .headers h3").click(function(){ $(this).next("table").toggle() });
92
+ $("div.stump .body h3").click(function(){ $(this).next("pre").toggle() });
93
+ $("div.stump .headers table").hide();
94
+ $("div.stump .body pre").hide();
95
+ });
data/lib/ww/spy_eye.rb ADDED
@@ -0,0 +1,25 @@
1
+ require 'forwardable'
2
+ require 'time'
3
+ require 'haml'
4
+
5
+ module Ww
6
+ class SpyEye
7
+ extend Forwardable
8
+ def_delegator :@servlet, :requests
9
+
10
+ def initialize(servlet)
11
+ @servlet = servlet
12
+ end
13
+
14
+ def call(env)
15
+ [200, {"Content-Type" => "text/html"}, template.render(self)]
16
+ end
17
+
18
+ private
19
+ def template
20
+ path = ::File.expand_path("spy_eye.html.haml", ::File.dirname(__FILE__))
21
+ Haml::Engine.new(::File.read(path))
22
+ end
23
+ end
24
+ end
25
+
data/lib/ww/store.rb ADDED
@@ -0,0 +1,33 @@
1
+ require 'monitor'
2
+ require 'forwardable'
3
+
4
+ module Ww
5
+ class Store
6
+ include Enumerable
7
+ include MonitorMixin
8
+ extend Forwardable
9
+
10
+ def_delegators :storage, *[:size, :first, :last, :[], :empty?]
11
+
12
+ def initialize
13
+ super()
14
+ @store = []
15
+ end
16
+
17
+ def storage
18
+ synchronize { @store.dup }
19
+ end
20
+
21
+ def store(obj)
22
+ synchronize{ @store << obj }
23
+ end
24
+
25
+ def each(descendant = true, &block)
26
+ (descendant ? storage.reverse : storage).each(&block)
27
+ end
28
+
29
+ def clear!
30
+ synchronize{ @store.clear }
31
+ end
32
+ end
33
+ end
metadata ADDED
@@ -0,0 +1,105 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: ww
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.2.0
5
+ platform: ruby
6
+ authors:
7
+ - moro
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2010-01-14 00:00:00 +09:00
13
+ default_executable:
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: sinatra
17
+ type: :runtime
18
+ version_requirement:
19
+ version_requirements: !ruby/object:Gem::Requirement
20
+ requirements:
21
+ - - ">="
22
+ - !ruby/object:Gem::Version
23
+ version: 0.9.4
24
+ version:
25
+ - !ruby/object:Gem::Dependency
26
+ name: rack
27
+ type: :runtime
28
+ version_requirement:
29
+ version_requirements: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: 1.0.1
34
+ version:
35
+ - !ruby/object:Gem::Dependency
36
+ name: json
37
+ type: :runtime
38
+ version_requirement:
39
+ version_requirements: !ruby/object:Gem::Requirement
40
+ requirements:
41
+ - - ">="
42
+ - !ruby/object:Gem::Version
43
+ version: "0"
44
+ version:
45
+ description: Double Web, framework to build double Web server.
46
+ email: moronatural@gmail.com
47
+ executables: []
48
+
49
+ extensions: []
50
+
51
+ extra_rdoc_files: []
52
+
53
+ files:
54
+ - Rakefile
55
+ - lib/ww/double/mock.rb
56
+ - lib/ww/double/spy/request.rb
57
+ - lib/ww/double/spy.rb
58
+ - lib/ww/double/stub.rb
59
+ - lib/ww/double.rb
60
+ - lib/ww/servlet.rb
61
+ - lib/ww/spy_eye.html.haml
62
+ - lib/ww/spy_eye.rb
63
+ - lib/ww/store.rb
64
+ - lib/ww.rb
65
+ has_rdoc: true
66
+ homepage: http://github.com/moro/ww/
67
+ licenses: []
68
+
69
+ post_install_message:
70
+ rdoc_options:
71
+ - --title
72
+ - ww documentation
73
+ - --charset
74
+ - utf-8
75
+ - --opname
76
+ - index.html
77
+ - --line-numbers
78
+ - --main
79
+ - README.rdoc
80
+ - --inline-source
81
+ - --exclude
82
+ - ^(examples|extras)/
83
+ require_paths:
84
+ - lib
85
+ required_ruby_version: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: "0"
90
+ version:
91
+ required_rubygems_version: !ruby/object:Gem::Requirement
92
+ requirements:
93
+ - - ">="
94
+ - !ruby/object:Gem::Version
95
+ version: "0"
96
+ version:
97
+ requirements: []
98
+
99
+ rubyforge_project:
100
+ rubygems_version: 1.3.5
101
+ signing_key:
102
+ specification_version: 3
103
+ summary: Double Web, framework to build double Web server.
104
+ test_files: []
105
+