otaku 0.1.0 → 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.
@@ -1,3 +1,18 @@
1
+ === 0.2.0 2010-07-19
2
+
3
+ = Features
4
+ * it is now possible to specify which ruby to run the server in [#ngty]
5
+ * officially support MRI-1.8.7, MRI-1.9.1, JRUBY-1.5.1 & REE-1.8.7 [#ngty]
6
+
7
+ = Maintenance
8
+ * split single file into separate files for readability [#ngty]
9
+ * use RubyParser instead of ParseTree [#ngty]
10
+
11
+ = Issues
12
+ * magic variable __FILE__ works as expected, but not __LINE__, in fact, __LINE__ reflects the
13
+ line no starting from the line where the source code is extracted from (not sure if we wanna
14
+ fix this problem though, unless someone explicitely ask for it)
15
+
1
16
  === 0.1.0 2010-07-18
2
17
 
3
18
  first gem release! [#ngty]
@@ -56,6 +56,7 @@ Otaku ships with the following defaults:
56
56
  Otaku.port # >> 10999
57
57
  Otaku.init_wait_time # >> 2
58
58
  Otaku.log_file # >> '/tmp/otaku.log'
59
+ Otaku.ruby # >> 'ruby' # (the current in-use ruby)
59
60
 
60
61
  Configuring can be done via:
61
62
 
data/Rakefile CHANGED
@@ -5,7 +5,7 @@ begin
5
5
  require 'jeweler'
6
6
  Jeweler::Tasks.new do |gem|
7
7
  gem.name = "otaku"
8
- gem.summary = %Q{Dead simple server/client service built using eventmachine}
8
+ gem.summary = %Q{Dead simple service framework built on eventmachine}
9
9
  gem.description = %Q{}
10
10
  gem.email = "ngty77@gmail.com"
11
11
  gem.homepage = "http://github.com/ngty/otaku"
@@ -13,8 +13,7 @@ begin
13
13
  gem.add_development_dependency "bacon", ">= 0"
14
14
  gem.add_dependency "eventmachine", ">= 0.12.10"
15
15
  gem.add_dependency "ruby2ruby", ">= 1.2.4"
16
- # TODO: Should eventually remove requirement for ParseTree !!
17
- gem.add_dependency "ParseTree", ">= 3.0.5"
16
+ gem.add_dependency "ruby_parser", ">= 2.0.4"
18
17
  # gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
19
18
  end
20
19
  Jeweler::GemcutterTasks.new
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.1.0
1
+ 0.2.0
@@ -3,25 +3,25 @@ require 'eventmachine'
3
3
  require 'logger'
4
4
  require 'base64'
5
5
  require 'ruby2ruby'
6
+ require 'ruby_parser'
6
7
 
7
- # TODO: Preliminary try, should be removed eventually !! Should use RubyParser instead.
8
- require 'parse_tree'
9
- require 'parse_tree_extensions'
8
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
9
+ require 'otaku/encoder'
10
+ require 'otaku/handler'
11
+ require 'otaku/server'
12
+ require 'otaku/client'
10
13
 
11
14
  module Otaku
12
15
 
13
16
  class HandlerNotDefinedError < Exception ; end
14
17
  class DataProcessError < Exception ; end
15
18
 
16
- # //////////////////////////////////////////////////////////////////////////////////////////
17
- # Otaku
18
- # //////////////////////////////////////////////////////////////////////////////////////////
19
-
20
19
  DEFAULTS = {
20
+ :ruby => 'ruby',
21
21
  :address => '127.0.0.1',
22
22
  :port => 10999,
23
23
  :log_file => '/tmp/otaku.log',
24
- :init_wait_time => 2
24
+ :init_wait_time => 2 * (RUBY_PLATFORM =~ /java/i ? 3 : 1)
25
25
  }
26
26
 
27
27
  class << self
@@ -57,167 +57,6 @@ module Otaku
57
57
 
58
58
  end
59
59
 
60
- # //////////////////////////////////////////////////////////////////////////////////////////
61
- # Otaku::Encoder
62
- # //////////////////////////////////////////////////////////////////////////////////////////
63
-
64
- module Encoder
65
- class << self
66
-
67
- def encode(thing)
68
- Base64.encode64(Marshal.dump(thing))
69
- end
70
-
71
- def decode(thing)
72
- Marshal.load(Base64.decode64(thing))
73
- end
74
-
75
- end
76
- end
77
-
78
- # //////////////////////////////////////////////////////////////////////////////////////////
79
- # Otaku::Handler
80
- # //////////////////////////////////////////////////////////////////////////////////////////
81
-
82
- class Handler
83
-
84
- def initialize(context, handler)
85
- @context = __context_as_code__(context)
86
- @proc = __proc_as_code__(handler)
87
- end
88
-
89
- def [](data)
90
- eval(@context).instance_exec(data, &eval(@proc))
91
- end
92
-
93
- private
94
-
95
- def __proc_as_code__(block)
96
- Ruby2Ruby.new.process(block.to_sexp)
97
- end
98
-
99
- def __context_as_code__(methods_hash)
100
- 'Class.new{ %s }.new' %
101
- methods_hash.map do |method, val|
102
- "def #{method}; Encoder.decode(%|#{Encoder.encode(val).gsub('|','\|')}|); end"
103
- end.join('; ')
104
- end
105
-
106
- end
107
-
108
- # //////////////////////////////////////////////////////////////////////////////////////////
109
- # Otaku::Server
110
- # //////////////////////////////////////////////////////////////////////////////////////////
111
-
112
- module Server
113
-
114
- class << self
115
-
116
- attr_accessor :handler
117
-
118
- def start(other_process=false)
119
- other_process ? run_evented_server : (
120
- # print '[Otaku] initializing at %s:%s ... ' % [Otaku.address, Otaku.port] # DBUG
121
- run_server_script
122
- # puts 'done [pid#%s]' % @process.pid # DEBUG
123
- )
124
- end
125
-
126
- def run_evented_server
127
- log 'started with pid #%s' % Process.pid,
128
- 'listening at %s:%s' % [Otaku.address, Otaku.port]
129
- EventMachine::run { EventMachine::start_server(Otaku.address, Otaku.port, EM) }
130
- end
131
-
132
- def run_server_script
133
- args = Encoder.encode({
134
- :config => Otaku.config,
135
- :handler => @handler
136
- })
137
- @process = IO.popen(%|ruby #{__FILE__} "#{args.gsub('"','\"')}"|,'r')
138
- sleep Otaku.init_wait_time
139
- end
140
-
141
- def stop
142
- Process.kill('SIGHUP', @process.pid) if @process
143
- end
144
-
145
- def log(*msgs)
146
- @logger ||= Logger.new(Otaku.log_file)
147
- msgs.each{|msg| @logger << "[Otaku] %s\n" % msg }
148
- end
149
-
150
- def cleanup
151
- @logger.close
152
- end
153
-
154
- end
155
-
156
- private
157
-
158
- module EM #:nodoc:
159
-
160
- def receive_data(data)
161
- log 'receives data: %s' % data.inspect
162
- result = process_data(data)
163
- log 'returning result: %s' % result.inspect
164
- send_data(Encoder.encode(result))
165
- end
166
-
167
- def process_data(data)
168
- begin
169
- Server.handler[data]
170
- rescue
171
- error = DataProcessError.new($!.inspect)
172
- log(error.inspect)
173
- error
174
- end
175
- end
176
-
177
- def log(*msg)
178
- Server.log(*msg)
179
- end
180
-
181
- end
182
-
183
- end
184
-
185
- # //////////////////////////////////////////////////////////////////////////////////////////
186
- # Otaku::Client
187
- # //////////////////////////////////////////////////////////////////////////////////////////
188
-
189
- module Client
190
-
191
- class << self
192
- def get(data)
193
- EventMachine::run do
194
- EventMachine::connect(Otaku.address, Otaku.port, EM).
195
- execute(data) do |data|
196
- @result = Encoder.decode(data)
197
- end
198
- end
199
- @result
200
- end
201
- end
202
-
203
- private
204
-
205
- module EM #:nodoc:
206
-
207
- def receive_data(data)
208
- result = @callback.call(data)
209
- result.is_a?(DataProcessError) ? raise(result) : result
210
- EventMachine::stop_event_loop # ends loop & resumes program flow
211
- end
212
-
213
- def execute(method, &callback)
214
- @callback = callback
215
- send_data(method)
216
- end
217
-
218
- end
219
-
220
- end
221
60
  end
222
61
 
223
62
  if $0 == __FILE__ && (encoded_data = ARGV[0])
@@ -0,0 +1,34 @@
1
+ module Otaku
2
+ module Client
3
+
4
+ class << self
5
+ def get(data)
6
+ EventMachine::run do
7
+ EventMachine::connect(Otaku.address, Otaku.port, EM).
8
+ execute(data) do |data|
9
+ @result = Encoder.decode(data)
10
+ end
11
+ end
12
+ @result
13
+ end
14
+ end
15
+
16
+ private
17
+
18
+ module EM #:nodoc:
19
+
20
+ def receive_data(data)
21
+ result = @callback.call(data)
22
+ result.is_a?(DataProcessError) ? raise(result) : result
23
+ EventMachine::stop_event_loop # ends loop & resumes program flow
24
+ end
25
+
26
+ def execute(method, &callback)
27
+ @callback = callback
28
+ send_data(method)
29
+ end
30
+
31
+ end
32
+
33
+ end
34
+ end
@@ -0,0 +1,15 @@
1
+ module Otaku
2
+ module Encoder
3
+ class << self
4
+
5
+ def encode(thing)
6
+ Base64.encode64(Marshal.dump(thing))
7
+ end
8
+
9
+ def decode(thing)
10
+ Marshal.load(Base64.decode64(thing))
11
+ end
12
+
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,101 @@
1
+ module Otaku
2
+ class Handler
3
+
4
+ def initialize(context, handler)
5
+ @context = __context_as_code__(context)
6
+ @proc = __proc_as_code__(handler)
7
+ end
8
+
9
+ def [](data)
10
+ eval(@context).instance_exec(data, &eval(@proc))
11
+ end
12
+
13
+ private
14
+
15
+ def __context_as_code__(methods_hash)
16
+ 'Class.new{ %s }.new' %
17
+ methods_hash.map do |method, val|
18
+ "def #{method}; Encoder.decode(%|#{Encoder.encode(val).gsub('|','\|')}|); end"
19
+ end.sort.join('; ')
20
+ end
21
+
22
+ def __proc_as_code__(block)
23
+ MagicProc.new(block).to_code
24
+ end
25
+
26
+ class MagicProc
27
+
28
+ RUBY_PARSER = RubyParser.new
29
+ RUBY_2_RUBY = Ruby2Ruby.new
30
+
31
+ def initialize(block)
32
+ @block = block
33
+ end
34
+
35
+ def to_code
36
+ code, remaining = code_fragments
37
+
38
+ while frag = remaining[frag_regexp,1]
39
+ begin
40
+ sexp = RUBY_PARSER.parse(code += frag, File.expand_path(@file))
41
+ return RUBY_2_RUBY.process(sexp) if sexp.inspect =~ sexp_regexp
42
+ rescue SyntaxError, Racc::ParseError, NoMethodError
43
+ remaining.sub!(frag,'')
44
+ end
45
+ end
46
+ end
47
+
48
+ def code_fragments
49
+ ignore, start_marker, arg =
50
+ [:ignore, :start_marker, :arg].map{|key| code_match_args[key] }
51
+ [
52
+ "proc #{start_marker} |#{arg}| ",
53
+ source_code.sub(ignore, '')
54
+ ]
55
+ end
56
+
57
+ def sexp_regexp
58
+ @sexp_regexp ||= (
59
+ Regexp.new([
60
+ Regexp.quote("s(:iter, s(:call, nil, :"),
61
+ "(proc|lambda)",
62
+ Regexp.quote(", s(:arglist)), s(:lasgn, :#{code_match_args[:arg]}), s("),
63
+ ].join)
64
+ )
65
+ end
66
+
67
+ def frag_regexp
68
+ @frag_regexp ||= (
69
+ end_marker = {'do' => 'end', '{' => '\}'}[code_match_args[:start_marker]]
70
+ /^(.*?\W#{end_marker})/m
71
+ )
72
+ end
73
+
74
+ def code_regexp
75
+ @code_regexp ||=
76
+ /^(.*?(Otaku\.start.*?|lambda|proc|Proc\.new)\s*(do|\{)\s*\|(\w+)\|\s*)/m
77
+ end
78
+
79
+ def code_match_args
80
+ @code_match_args ||= (
81
+ args = source_code.match(code_regexp)
82
+ {
83
+ :ignore => args[1],
84
+ :start_marker => args[3],
85
+ :arg => args[4]
86
+ }
87
+ )
88
+ end
89
+
90
+ def source_code
91
+ @source_code ||= (
92
+ @file, line_no = /^#<Proc:0x[0-9A-Fa-f]+@(.+):(\d+).*?>$/.match(@block.inspect)[1..2]
93
+ @line_no = line_no.to_i
94
+ File.readlines(@file)[@line_no.pred .. -1].join
95
+ )
96
+ end
97
+
98
+ end
99
+
100
+ end
101
+ end
@@ -0,0 +1,72 @@
1
+ module Otaku
2
+ module Server
3
+
4
+ class << self
5
+
6
+ attr_accessor :handler
7
+
8
+ def start(other_process=false)
9
+ other_process ? run_evented_server : (
10
+ # print '[Otaku] initializing at %s:%s ... ' % [Otaku.address, Otaku.port] # DEBUG
11
+ run_server_script
12
+ # puts 'done [pid#%s]' % @process.pid # DEBUG
13
+ )
14
+ end
15
+
16
+ def run_evented_server
17
+ log 'started with pid #%s' % Process.pid,
18
+ 'listening at %s:%s' % [Otaku.address, Otaku.port]
19
+ EventMachine::run { EventMachine::start_server(Otaku.address, Otaku.port, EM) }
20
+ end
21
+
22
+ def run_server_script
23
+ script = File.join(File.dirname(__FILE__), '..', 'otaku.rb')
24
+ args = Encoder.encode(:config => Otaku.config, :handler => @handler)
25
+ @process = IO.popen(%|#{Otaku.ruby} #{script} "#{args.gsub('"','\"')}"|,'r')
26
+ sleep Otaku.init_wait_time
27
+ end
28
+
29
+ def stop
30
+ Process.kill('SIGHUP', @process.pid) if @process
31
+ end
32
+
33
+ def log(*msgs)
34
+ @logger ||= Logger.new(Otaku.log_file)
35
+ msgs.each{|msg| @logger << "[Otaku] %s\n" % msg }
36
+ end
37
+
38
+ def cleanup
39
+ @logger.close
40
+ end
41
+
42
+ end
43
+
44
+ private
45
+
46
+ module EM #:nodoc:
47
+
48
+ def receive_data(data)
49
+ log 'receives data: %s' % data.inspect
50
+ result = process_data(data)
51
+ log 'returning result: %s' % result.inspect
52
+ send_data(Encoder.encode(result))
53
+ end
54
+
55
+ def process_data(data)
56
+ begin
57
+ Server.handler[data]
58
+ rescue
59
+ error = DataProcessError.new($!.inspect)
60
+ log(error.inspect)
61
+ error
62
+ end
63
+ end
64
+
65
+ def log(*msg)
66
+ Server.log(*msg)
67
+ end
68
+
69
+ end
70
+
71
+ end
72
+ end
@@ -0,0 +1,70 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = %q{otaku}
8
+ s.version = "0.2.0"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = ["NgTzeYang"]
12
+ s.date = %q{2010-07-19}
13
+ s.description = %q{}
14
+ s.email = %q{ngty77@gmail.com}
15
+ s.extra_rdoc_files = [
16
+ "LICENSE",
17
+ "README.rdoc"
18
+ ]
19
+ s.files = [
20
+ ".document",
21
+ ".gitignore",
22
+ "HISTORY.txt",
23
+ "LICENSE",
24
+ "README.rdoc",
25
+ "Rakefile",
26
+ "VERSION",
27
+ "lib/otaku.rb",
28
+ "lib/otaku/client.rb",
29
+ "lib/otaku/encoder.rb",
30
+ "lib/otaku/handler.rb",
31
+ "lib/otaku/server.rb",
32
+ "otaku.gemspec",
33
+ "spec/handler_spec.rb",
34
+ "spec/integration_spec.rb",
35
+ "spec/spec_helper.rb"
36
+ ]
37
+ s.homepage = %q{http://github.com/ngty/otaku}
38
+ s.rdoc_options = ["--charset=UTF-8"]
39
+ s.require_paths = ["lib"]
40
+ s.rubygems_version = %q{1.3.7}
41
+ s.summary = %q{Dead simple service framework built on eventmachine}
42
+ s.test_files = [
43
+ "spec/integration_spec.rb",
44
+ "spec/handler_spec.rb",
45
+ "spec/spec_helper.rb"
46
+ ]
47
+
48
+ if s.respond_to? :specification_version then
49
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
50
+ s.specification_version = 3
51
+
52
+ if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
53
+ s.add_development_dependency(%q<bacon>, [">= 0"])
54
+ s.add_runtime_dependency(%q<eventmachine>, [">= 0.12.10"])
55
+ s.add_runtime_dependency(%q<ruby2ruby>, [">= 1.2.4"])
56
+ s.add_runtime_dependency(%q<ruby_parser>, [">= 2.0.4"])
57
+ else
58
+ s.add_dependency(%q<bacon>, [">= 0"])
59
+ s.add_dependency(%q<eventmachine>, [">= 0.12.10"])
60
+ s.add_dependency(%q<ruby2ruby>, [">= 1.2.4"])
61
+ s.add_dependency(%q<ruby_parser>, [">= 2.0.4"])
62
+ end
63
+ else
64
+ s.add_dependency(%q<bacon>, [">= 0"])
65
+ s.add_dependency(%q<eventmachine>, [">= 0.12.10"])
66
+ s.add_dependency(%q<ruby2ruby>, [">= 1.2.4"])
67
+ s.add_dependency(%q<ruby_parser>, [">= 2.0.4"])
68
+ end
69
+ end
70
+
@@ -0,0 +1,228 @@
1
+ require File.join(File.dirname(__FILE__), 'spec_helper')
2
+
3
+ Otaku::Handler.class_eval do
4
+ attr_reader :context, :proc
5
+ end
6
+
7
+ Otaku.instance_eval do
8
+ def start(context = {}, &block)
9
+ Otaku::Handler.new({}, block)
10
+ end
11
+ end
12
+
13
+ describe "Otaku Service Handler" do
14
+
15
+ describe '>> initializing context' do
16
+
17
+ should 'assign to empty anoynmous class instance code when given {}' do
18
+ Otaku::Handler.new({}, lambda{}).context.should.equal('Class.new{ }.new')
19
+ end
20
+
21
+ should 'assign to non-empty anoynmous class instance code when given {:m1 => v1, :m2 => v2, ...}' do
22
+ encode = lambda{|val| Otaku::Encoder.encode(val).gsub('|','\|') }
23
+ Otaku::Handler.new({:m1 => 'v|1', :m2 => 'v|2'}, lambda{}).context.should.equal(
24
+ 'Class.new{ %s; %s }.new' % [
25
+ "def m1; Encoder.decode(%|#{encode['v|1']}|); end",
26
+ "def m2; Encoder.decode(%|#{encode['v|2']}|); end"
27
+ ])
28
+ end
29
+
30
+ end
31
+
32
+ describe '>> initializing proc' do
33
+
34
+ expected = "proc { |watever| [\"a\", \"b\"].map { |x| puts(x) } }"
35
+
36
+ {
37
+ # ////////////////////////////////////////////////////////////////////////
38
+ # >> Always newlinling
39
+ # ////////////////////////////////////////////////////////////////////////
40
+ __LINE__ => (
41
+ lambda do |watever|
42
+ %w{a b}.map do |x|
43
+ puts x
44
+ end
45
+ end
46
+ ),
47
+ __LINE__ => (
48
+ lambda { |watever|
49
+ %w{a b}.map{|x|
50
+ puts x
51
+ }
52
+ }
53
+ ),
54
+ __LINE__ => (
55
+ proc do |watever|
56
+ %w{a b}.map do |x|
57
+ puts x
58
+ end
59
+ end
60
+ ),
61
+ __LINE__ => (
62
+ proc { |watever|
63
+ %w{a b}.map{|x|
64
+ puts x
65
+ }
66
+ }
67
+ ),
68
+ __LINE__ => (
69
+ Proc.new do |watever|
70
+ %w{a b}.map do |x|
71
+ puts x
72
+ end
73
+ end
74
+ ),
75
+ __LINE__ => (
76
+ Proc.new { |watever|
77
+ %w{a b}.map{|x|
78
+ puts x
79
+ }
80
+ }
81
+ ),
82
+ # ////////////////////////////////////////////////////////////////////////
83
+ # >> Partial newlining
84
+ # ////////////////////////////////////////////////////////////////////////
85
+ __LINE__ => (
86
+ lambda do |watever|
87
+ %w{a b}.map do |x| puts x end
88
+ end
89
+ ),
90
+ __LINE__ => (
91
+ lambda { |watever|
92
+ %w{a b}.map{|x| puts x }
93
+ }
94
+ ),
95
+ __LINE__ => (
96
+ proc do |watever|
97
+ %w{a b}.map do |x| puts x end
98
+ end
99
+ ),
100
+ __LINE__ => (
101
+ proc { |watever|
102
+ %w{a b}.map{|x| puts x }
103
+ }
104
+ ),
105
+ __LINE__ => (
106
+ Proc.new do |watever|
107
+ %w{a b}.map do |x| puts x end
108
+ end
109
+ ),
110
+ __LINE__ => (
111
+ Proc.new { |watever|
112
+ %w{a b}.map{|x| puts x }
113
+ }
114
+ ),
115
+ # ////////////////////////////////////////////////////////////////////////
116
+ # >> No newlining
117
+ # ////////////////////////////////////////////////////////////////////////
118
+ __LINE__ => (
119
+ lambda do |watever| %w{a b}.map do |x| puts x end end
120
+ ),
121
+ __LINE__ => (
122
+ lambda { |watever| %w{a b}.map{|x| puts x } }
123
+ ),
124
+ __LINE__ => (
125
+ proc do |watever| %w{a b}.map do |x| puts x end end
126
+ ),
127
+ __LINE__ => (
128
+ proc { |watever| %w{a b}.map{|x| puts x } }
129
+ ),
130
+ __LINE__ => (
131
+ Proc.new do |watever| %w{a b}.map do |x| puts x end end
132
+ ),
133
+ __LINE__ => (
134
+ Proc.new { |watever| %w{a b}.map{|x| puts x } }
135
+ ),
136
+ }.each do |debug, block|
137
+ should "handle proc as variable [##{debug}]" do
138
+ Otaku::Handler.new({}, block).proc.should.equal(expected)
139
+ end
140
+ end
141
+
142
+ should "handle block using do ... end [##{__LINE__}]" do
143
+ Otaku.start({}) do |watever|
144
+ %w{a b}.map do |x|
145
+ puts x
146
+ end
147
+ end.proc.should.equal(expected)
148
+ end
149
+
150
+ should "handle block using do ... end [##{__LINE__}]" do
151
+ Otaku.start do |watever|
152
+ %w{a b}.map do |x|
153
+ puts x
154
+ end
155
+ end.proc.should.equal(expected)
156
+ end
157
+
158
+ should "handle block using do ... end [##{__LINE__}]" do
159
+ Otaku.start({}) do |watever|
160
+ %w{a b}.map do |x| puts x end
161
+ end.proc.should.equal(expected)
162
+ end
163
+
164
+ should "handle block using do ... end [##{__LINE__}]" do
165
+ Otaku.start do |watever|
166
+ %w{a b}.map do |x| puts x end
167
+ end.proc.should.equal(expected)
168
+ end
169
+
170
+ should "handle block using do ... end [##{__LINE__}]" do
171
+ Otaku.start({}) do |watever| %w{a b}.map do |x| puts x end end.
172
+ proc.should.equal(expected)
173
+ end
174
+
175
+ should "handle block using do ... end [##{__LINE__}]" do
176
+ Otaku.start do |watever| %w{a b}.map do |x| puts x end end.
177
+ proc.should.equal(expected)
178
+ end
179
+
180
+ should "handle block using { ... } [##{__LINE__}]" do
181
+ Otaku.start({}) { |watever|
182
+ %w{a b}.map do |x|
183
+ puts x
184
+ end
185
+ }.proc.should.equal(expected)
186
+ end
187
+
188
+ should "handle block using { ... } [##{__LINE__}]" do
189
+ Otaku.start { |watever|
190
+ %w{a b}.map do |x|
191
+ puts x
192
+ end
193
+ }.proc.should.equal(expected)
194
+ end
195
+
196
+ should "handle block using { ... } [##{__LINE__}]" do
197
+ Otaku.start({}) { |watever|
198
+ %w{a b}.map { |x| puts x }
199
+ }.proc.should.equal(expected)
200
+ end
201
+
202
+ should "handle block using { ... } [##{__LINE__}]" do
203
+ Otaku.start { |watever|
204
+ %w{a b}.map { |x| puts x }
205
+ }.proc.should.equal(expected)
206
+ end
207
+
208
+ should "handle block using { ... } [##{__LINE__}]" do
209
+ Otaku.start({}) { |watever| %w{a b}.map { |x| puts x } }.proc.should.equal(expected)
210
+ end
211
+
212
+ should "handle block using { ... } [##{__LINE__}]" do
213
+ Otaku.start { |watever| %w{a b}.map { |x| puts x } }.proc.should.equal(expected)
214
+ end
215
+
216
+ should "handle __FILE__ correctly [##{__LINE__}]" do
217
+ Otaku.start { |watever| __FILE__ }.proc.should.
218
+ equal("proc { |watever| \"%s\" }" % File.expand_path('spec/handler_spec.rb'))
219
+ end
220
+
221
+ should "handle __LINE__ incorrectly [##{__LINE__}]" do
222
+ Otaku.start { |watever| __LINE__ }.proc.should.
223
+ equal("proc { |watever| 1 }")
224
+ end
225
+
226
+ end
227
+
228
+ end
@@ -0,0 +1,52 @@
1
+ require File.join(File.dirname(__FILE__), 'spec_helper')
2
+
3
+ describe "Otaku Service" do
4
+
5
+ describe '>> starting' do
6
+
7
+ after do
8
+ Otaku.stop
9
+ end
10
+
11
+ should 'raise Otaku::HandlerNotDefinedError when processing wo specified proc' do
12
+ lambda { Otaku.start }.should.raise(Otaku::HandlerNotDefinedError)
13
+ end
14
+
15
+ end
16
+
17
+ describe '>> processing' do
18
+
19
+ after do
20
+ Otaku.stop
21
+ end
22
+
23
+ should 'succeed w proc that has no contextual reference' do
24
+ Otaku.start{|data| '~ %s ~' % data }
25
+ Otaku.process('hello').should.equal '~ hello ~'
26
+ end
27
+
28
+ should 'raise Otaku::DataProcessError w proc that has contextual reference yet has no specified context' do
29
+ mark = '*'
30
+ Otaku.start{|data| '%s %s %s' % [mark, data, mark] }
31
+ lambda { Otaku.process('hello') }.should.raise(Otaku::DataProcessError).
32
+ message.should.match(/#<NameError: undefined local variable or method `mark' for /)
33
+ end
34
+
35
+ should 'succeed w proc that has contextual reference & has context specified' do
36
+ Otaku.start(:mark => '*') {|data| '%s %s %s' % [mark, data, mark] }
37
+ Otaku.process('hello').should.equal('* hello *')
38
+ end
39
+
40
+ should 'reflect __FILE__ as captured when declaring proc' do
41
+ Otaku.start{|data| __FILE__ }
42
+ Otaku.process(:watever_data).should.equal(File.expand_path(__FILE__))
43
+ end
44
+
45
+ should 'not reflect __LINE__ as captured when declaring proc' do
46
+ Otaku.start{|data| __LINE__ }
47
+ Otaku.process(:watever_data).should.not.equal(__LINE__.pred)
48
+ end
49
+
50
+ end
51
+
52
+ end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: otaku
3
3
  version: !ruby/object:Gem::Version
4
- hash: 27
4
+ hash: 23
5
5
  prerelease: false
6
6
  segments:
7
7
  - 0
8
- - 1
8
+ - 2
9
9
  - 0
10
- version: 0.1.0
10
+ version: 0.2.0
11
11
  platform: ruby
12
12
  authors:
13
13
  - NgTzeYang
@@ -15,7 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2010-07-18 00:00:00 +08:00
18
+ date: 2010-07-19 00:00:00 +08:00
19
19
  default_executable:
20
20
  dependencies:
21
21
  - !ruby/object:Gem::Dependency
@@ -65,19 +65,19 @@ dependencies:
65
65
  type: :runtime
66
66
  version_requirements: *id003
67
67
  - !ruby/object:Gem::Dependency
68
- name: ParseTree
68
+ name: ruby_parser
69
69
  prerelease: false
70
70
  requirement: &id004 !ruby/object:Gem::Requirement
71
71
  none: false
72
72
  requirements:
73
73
  - - ">="
74
74
  - !ruby/object:Gem::Version
75
- hash: 13
75
+ hash: 7
76
76
  segments:
77
- - 3
77
+ - 2
78
78
  - 0
79
- - 5
80
- version: 3.0.5
79
+ - 4
80
+ version: 2.0.4
81
81
  type: :runtime
82
82
  version_requirements: *id004
83
83
  description: ""
@@ -98,7 +98,13 @@ files:
98
98
  - Rakefile
99
99
  - VERSION
100
100
  - lib/otaku.rb
101
- - spec/processing_spec.rb
101
+ - lib/otaku/client.rb
102
+ - lib/otaku/encoder.rb
103
+ - lib/otaku/handler.rb
104
+ - lib/otaku/server.rb
105
+ - otaku.gemspec
106
+ - spec/handler_spec.rb
107
+ - spec/integration_spec.rb
102
108
  - spec/spec_helper.rb
103
109
  has_rdoc: true
104
110
  homepage: http://github.com/ngty/otaku
@@ -133,7 +139,8 @@ rubyforge_project:
133
139
  rubygems_version: 1.3.7
134
140
  signing_key:
135
141
  specification_version: 3
136
- summary: Dead simple server/client service built using eventmachine
142
+ summary: Dead simple service framework built on eventmachine
137
143
  test_files:
138
- - spec/processing_spec.rb
144
+ - spec/integration_spec.rb
145
+ - spec/handler_spec.rb
139
146
  - spec/spec_helper.rb
@@ -1,30 +0,0 @@
1
- require File.join(File.dirname(__FILE__), 'spec_helper')
2
-
3
- describe "Otaku doing processing" do
4
-
5
- after do
6
- Otaku.stop
7
- end
8
-
9
- should 'succeed when using proc that has no contextual reference' do
10
- Otaku.start{|data| '~ %s ~' % data }
11
- Otaku.process('hello').should.equal '~ hello ~'
12
- end
13
-
14
- should 'fail when using proc that has contextual reference yet has no specified context' do
15
- mark = '*'
16
- Otaku.start{|data| '%s %s %s' % [mark, data, mark] }
17
- lambda { Otaku.process('hello') }.should.raise(Otaku::DataProcessError).
18
- message.should.match(/#<NameError: undefined local variable or method `mark' for /)
19
- end
20
-
21
- should 'succeed when using proc that has contextual reference & has context specified' do
22
- Otaku.start(:mark => '*') {|data| '%s %s %s' % [mark, data, mark] }
23
- Otaku.process('hello').should.equal('* hello *')
24
- end
25
-
26
- should 'raise Otaku::HandlerNotDefinedError when processing wo specified proc' do
27
- lambda { Otaku.start }.should.raise(Otaku::HandlerNotDefinedError)
28
- end
29
-
30
- end