ww 0.2.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/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
+