cross-stub 0.1.4 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (39) hide show
  1. data/HISTORY.txt +12 -0
  2. data/README.rdoc +85 -29
  3. data/Rakefile +8 -1
  4. data/VERSION +1 -1
  5. data/cross-stub.gemspec +37 -19
  6. data/lib/cross-stub.rb +63 -24
  7. data/lib/cross-stub/arguments.rb +21 -0
  8. data/lib/cross-stub/arguments/array.rb +16 -0
  9. data/lib/cross-stub/arguments/hash.rb +17 -0
  10. data/lib/cross-stub/arguments/proc.rb +73 -0
  11. data/lib/cross-stub/cache.rb +36 -0
  12. data/lib/cross-stub/stores.rb +4 -0
  13. data/lib/cross-stub/stores/base.rb +38 -0
  14. data/lib/cross-stub/stores/file.rb +39 -0
  15. data/lib/cross-stub/stores/memcache.rb +40 -0
  16. data/lib/cross-stub/stores/redis.rb +41 -0
  17. data/lib/cross-stub/stubber.rb +132 -0
  18. data/rails_generators/cross_stub/cross_stub_generator.rb +1 -1
  19. data/rails_generators/cross_stub/templates/config/initializers/cross-stub.rb +9 -1
  20. data/rails_generators/cross_stub/templates/features/support/cross-stub.rb +16 -2
  21. data/spec/arguments/proc_spec.rb +689 -0
  22. data/spec/includes.rb +103 -0
  23. data/spec/integration/clearing_instance_stubs_spec.rb +119 -0
  24. data/spec/integration/clearing_stubs_spec.rb +118 -0
  25. data/spec/integration/creating_instance_stubs_spec.rb +91 -0
  26. data/spec/integration/creating_stubs_spec.rb +95 -0
  27. data/spec/integration/shared_spec.rb +35 -0
  28. data/spec/integration/stubbing_error_spec.rb +69 -0
  29. data/spec/service.rb +114 -0
  30. data/spec/spec_helper.rb +1 -41
  31. metadata +58 -26
  32. data/lib/cross-stub/cache_helpers.rb +0 -48
  33. data/lib/cross-stub/pseudo_class.rb +0 -82
  34. data/lib/cross-stub/setup_helpers.rb +0 -13
  35. data/lib/cross-stub/stub_helpers.rb +0 -64
  36. data/spec/cross-stub/clearing_stubs_spec.rb +0 -112
  37. data/spec/cross-stub/creating_stubs_spec.rb +0 -110
  38. data/spec/cross-stub/stubbing_error_spec.rb +0 -38
  39. data/spec/helpers.rb +0 -125
@@ -0,0 +1,35 @@
1
+ require File.join(File.dirname(__FILE__), '..', 'spec_helper')
2
+ require File.join(File.dirname(__FILE__), '..', 'includes')
3
+ require File.join(File.dirname(__FILE__), '..', 'service')
4
+
5
+ shared 'has standard setup' do
6
+ before { CrossStub.setup(cache_store(@store_type)) }
7
+ after { CrossStub.clear }
8
+ end
9
+
10
+ shared 'has current process setup' do
11
+ behaves_like 'has standard setup'
12
+ before { @call = Object.method(:do_local_method_call) }
13
+ end
14
+
15
+ shared 'has other process setup' do
16
+
17
+ behaves_like 'has standard setup'
18
+
19
+ before do
20
+ @call = lambda do |klass_and_method_and_args|
21
+ do_remote_method_call("%s/%s" % [@store_type, klass_and_method_and_args])
22
+ end
23
+ $service_started ||= (
24
+ EchoServer.start if ENV['ECHO_SERVER'] != 'false'
25
+ true
26
+ )
27
+ end
28
+
29
+ end
30
+
31
+ at_exit do
32
+ $service_started && (
33
+ EchoServer.stop unless ENV['ECHO_SERVER'] == 'false'
34
+ )
35
+ end
@@ -0,0 +1,69 @@
1
+ require File.join(File.dirname(__FILE__), 'shared_spec')
2
+
3
+ describe 'Stubbing Error' do
4
+
5
+ describe ">> xstub (class/module)" do
6
+
7
+ before do
8
+ @store_type = :file
9
+ end
10
+
11
+ behaves_like 'has standard setup'
12
+
13
+ should 'not be raised when stubbing module' do
14
+ lambda { AnyModule.send(:xstub, :bang => 'OOPS') }.
15
+ should.not.raise(CrossStub::Error)
16
+ end
17
+
18
+ should 'not be raised when stubbing nested module' do
19
+ lambda { AnyModule::Inner.send(:xstub, :bang => 'OOPS') }.
20
+ should.not.raise(CrossStub::Error)
21
+ end
22
+
23
+ should 'not be raised when stubbing class' do
24
+ lambda { AnyClass.send(:xstub, :bang => 'OOPS') }.
25
+ should.not.raise(CrossStub::Error)
26
+ end
27
+
28
+ should 'not be raised when stubbing nested class' do
29
+ lambda { AnyClass::Inner.send(:xstub, :bang => 'OOPS') }.
30
+ should.not.raise(CrossStub::Error)
31
+ end
32
+
33
+ should 'be raised when stubbing instance' do
34
+ lambda { AnyInstance.new.send(:xstub, :bang => 'OOPS') }.
35
+ should.raise(CrossStub::CannotStubInstanceError)
36
+ end
37
+
38
+ end
39
+
40
+ describe ">> xstub (instance)" do
41
+
42
+ should 'not be raised when stubbing class' do
43
+ lambda { AnyClass.xstub({:bang => 'OOPS'}, :instance => true) }.
44
+ should.not.raise(CrossStub::Error)
45
+ end
46
+
47
+ should 'not be raised when stubbing nested class' do
48
+ lambda { AnyClass::Inner.xstub({:bang => 'OOPS'}, :instance => true) }.
49
+ should.not.raise(CrossStub::Error)
50
+ end
51
+
52
+ should 'be raised when stubbing module' do
53
+ lambda { AnyModule.xstub({:bang => 'OOPS'}, :instance => true) }.
54
+ should.raise(CrossStub::ModuleCannotBeInstantiatedError)
55
+ end
56
+
57
+ should 'be raised when stubbing nested module' do
58
+ lambda { AnyModule::Inner.xstub({:bang => 'OOPS'}, :instance => true) }.
59
+ should.raise(CrossStub::ModuleCannotBeInstantiatedError)
60
+ end
61
+
62
+ should 'be raised when stubbing instance' do
63
+ lambda { AnyInstance.new.xstub({:bang => 'OOPS'}, :instance => true) }.
64
+ should.raise(CrossStub::CannotStubInstanceError)
65
+ end
66
+
67
+ end
68
+
69
+ end
data/spec/service.rb ADDED
@@ -0,0 +1,114 @@
1
+ require 'rubygems'
2
+ require 'eventmachine'
3
+ require File.join(File.dirname(__FILE__), 'includes')
4
+
5
+ module EchoClient
6
+
7
+ ADDRESS = ECHO_SERVER_HOST
8
+ PORT = ECHO_SERVER_PORT
9
+
10
+ class << self
11
+ def get(klass_and_method)
12
+ EventMachine::run do
13
+ (EventMachine::connect(ADDRESS, PORT, EM)).
14
+ execute(klass_and_method){|data| @result = Marshal.load(Base64.decode64(data)) }
15
+ end
16
+ @result
17
+ end
18
+ end
19
+
20
+ private
21
+
22
+ module EM
23
+ def receive_data(data)
24
+ @callback.call(data)
25
+ EventMachine::stop_event_loop
26
+ end
27
+ def execute(method, &blk)
28
+ @callback = blk
29
+ send_data(method)
30
+ end
31
+ end
32
+
33
+ end
34
+
35
+ module EchoServer
36
+
37
+ ADDRESS = ECHO_SERVER_HOST
38
+ PORT = ECHO_SERVER_PORT
39
+ LOG = ECHO_SERVER_LOG
40
+ WAIT_TIME = ECHO_SERVER_INIT_WAIT_TIME
41
+
42
+ class << self
43
+
44
+ def log(*msg)
45
+ (@logger ||= (
46
+ require 'logger'
47
+ Logger.new(LOG)
48
+ )) << [msg, ""].flatten.join("\n")
49
+ end
50
+
51
+ def cleanup
52
+ @logger.close
53
+ end
54
+
55
+ def start(other_process=false)
56
+ unless other_process
57
+ @process = IO.popen("ruby #{__FILE__}",'r')
58
+ sleep WAIT_TIME
59
+ else
60
+ log 'Starting echo service at %s:%s (#%s)' % [ADDRESS, PORT, Process.pid]
61
+ EventMachine::run { EventMachine::start_server(ADDRESS, PORT, EM) }
62
+ end
63
+ end
64
+
65
+ def stop
66
+ Process.kill('SIGHUP', @process.pid) if @process
67
+ end
68
+
69
+ end
70
+
71
+ private
72
+
73
+ module EM
74
+
75
+ def receive_data(store_type_and_klass_and_method_and_args)
76
+ log "\n"
77
+ log "(1) EchoServer::EM#receive_data ... receives: #{store_type_and_klass_and_method_and_args}"
78
+
79
+ store_type, klass_and_method_and_args =
80
+ store_type_and_klass_and_method_and_args.match(/^(.*?)\/(.*)$/)[1..2]
81
+
82
+ CrossStub.refresh(cache_store($prev_store_type)) if $prev_store_type
83
+ CrossStub.refresh(cache_store($prev_store_type = store_type))
84
+ log "(2) EchoServer::EM#receive_data ... completes stubs refresh"
85
+
86
+ klass, is_instance, method, args = parse_call_args(klass_and_method_and_args)
87
+ log "(3) EchoServer::EM#receive_data ... parses arguments to:",
88
+ " * receiver ... #{klass}%s" % (is_instance ? "#new" : nil),
89
+ " * method ... #{method}",
90
+ " * args ... #{args.inspect}"
91
+ value = do_local_method_call(klass_and_method_and_args) rescue $!.message
92
+
93
+ log "(4) EchoServer::EM#receive_data ... returns: #{value.inspect}"
94
+ send_data(Base64.encode64(Marshal.dump(value)))
95
+ log "(5) EchoServer::EM#receive_data ... end"
96
+ end
97
+
98
+ def log(*msg)
99
+ EchoServer.log(*msg)
100
+ end
101
+
102
+ end
103
+
104
+ end
105
+
106
+ if $0 == __FILE__
107
+ begin
108
+ EchoServer.start(true)
109
+ rescue
110
+ EchoServer.log "#{$!.inspect}\n"
111
+ ensure
112
+ EchoServer.cleanup
113
+ end
114
+ end
data/spec/spec_helper.rb CHANGED
@@ -1,45 +1,5 @@
1
1
  require 'rubygems'
2
2
  require 'bacon'
3
- require 'mocha'
4
-
5
- $LOAD_PATH.unshift(File.dirname(__FILE__))
6
- require 'helpers'
3
+ require File.join(File.dirname(__FILE__), 'includes')
7
4
 
8
5
  Bacon.summary_on_exit
9
-
10
- shared 'has standard setup' do
11
- before do
12
- CrossStub.setup(:file => $cache_file)
13
- @get_context = lambda do |klass_or_module|
14
- klass_or_module.split(/::/).inject(Object) { |context, name| context.const_get(name) }
15
- end
16
- end
17
- after do
18
- CrossStub.clear
19
- end
20
- end
21
-
22
- shared 'has current process setup' do
23
- before do
24
- @get_value = lambda do |klass_and_method_and_args|
25
- klass, method, *args = klass_and_method_and_args.split('.')
26
- konst = klass.split(/::/).inject(Object) { |const_train, const| const_train.const_get(const) }
27
- args.empty? ? konst.send(method) :
28
- konst.send(method, *args)
29
- end
30
- end
31
- end
32
-
33
- shared 'has other process setup' do
34
- before do
35
- EchoServer.start unless ENV['ECHO_SERVER'] == 'false'
36
- @get_value = lambda do |klass_and_method_and_args|
37
- (value = EchoClient.get(klass_and_method_and_args)) !~ /^undefined method/ ? value :
38
- Object.we_just_wanna_trigger_a_no_method_error_with_this_very_long_and_weird_method!
39
- end
40
- end
41
- after do
42
- EchoServer.stop unless ENV['ECHO_SERVER'] == 'false'
43
- end
44
- end
45
-
metadata CHANGED
@@ -1,12 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cross-stub
3
3
  version: !ruby/object:Gem::Version
4
+ hash: 23
4
5
  prerelease: false
5
6
  segments:
6
7
  - 0
7
- - 1
8
- - 4
9
- version: 0.1.4
8
+ - 2
9
+ - 0
10
+ version: 0.2.0
10
11
  platform: ruby
11
12
  authors:
12
13
  - NgTzeYang
@@ -14,16 +15,18 @@ autorequire:
14
15
  bindir: bin
15
16
  cert_chain: []
16
17
 
17
- date: 2010-04-03 00:00:00 +08:00
18
+ date: 2010-07-16 00:00:00 +08:00
18
19
  default_executable:
19
20
  dependencies:
20
21
  - !ruby/object:Gem::Dependency
21
22
  name: bacon
22
23
  prerelease: false
23
24
  requirement: &id001 !ruby/object:Gem::Requirement
25
+ none: false
24
26
  requirements:
25
27
  - - ">="
26
28
  - !ruby/object:Gem::Version
29
+ hash: 31
27
30
  segments:
28
31
  - 0
29
32
  - 0
@@ -35,9 +38,11 @@ dependencies:
35
38
  name: eventmachine
36
39
  prerelease: false
37
40
  requirement: &id002 !ruby/object:Gem::Requirement
41
+ none: false
38
42
  requirements:
39
43
  - - ">="
40
44
  - !ruby/object:Gem::Version
45
+ hash: 31
41
46
  segments:
42
47
  - 0
43
48
  - 0
@@ -46,31 +51,35 @@ dependencies:
46
51
  type: :development
47
52
  version_requirements: *id002
48
53
  - !ruby/object:Gem::Dependency
49
- name: ParseTree
54
+ name: ruby2ruby
50
55
  prerelease: false
51
56
  requirement: &id003 !ruby/object:Gem::Requirement
57
+ none: false
52
58
  requirements:
53
59
  - - "="
54
60
  - !ruby/object:Gem::Version
61
+ hash: 23
55
62
  segments:
56
- - 3
57
- - 0
63
+ - 1
64
+ - 2
58
65
  - 4
59
- version: 3.0.4
66
+ version: 1.2.4
60
67
  type: :runtime
61
68
  version_requirements: *id003
62
69
  - !ruby/object:Gem::Dependency
63
- name: ruby2ruby
70
+ name: ruby_parser
64
71
  prerelease: false
65
72
  requirement: &id004 !ruby/object:Gem::Requirement
73
+ none: false
66
74
  requirements:
67
75
  - - "="
68
76
  - !ruby/object:Gem::Version
77
+ hash: 7
69
78
  segments:
70
- - 1
71
79
  - 2
80
+ - 0
72
81
  - 4
73
- version: 1.2.4
82
+ version: 2.0.4
74
83
  type: :runtime
75
84
  version_requirements: *id004
76
85
  description: ""
@@ -92,18 +101,30 @@ files:
92
101
  - VERSION
93
102
  - cross-stub.gemspec
94
103
  - lib/cross-stub.rb
95
- - lib/cross-stub/cache_helpers.rb
96
- - lib/cross-stub/pseudo_class.rb
97
- - lib/cross-stub/setup_helpers.rb
98
- - lib/cross-stub/stub_helpers.rb
104
+ - lib/cross-stub/arguments.rb
105
+ - lib/cross-stub/arguments/array.rb
106
+ - lib/cross-stub/arguments/hash.rb
107
+ - lib/cross-stub/arguments/proc.rb
108
+ - lib/cross-stub/cache.rb
109
+ - lib/cross-stub/stores.rb
110
+ - lib/cross-stub/stores/base.rb
111
+ - lib/cross-stub/stores/file.rb
112
+ - lib/cross-stub/stores/memcache.rb
113
+ - lib/cross-stub/stores/redis.rb
114
+ - lib/cross-stub/stubber.rb
99
115
  - rails_generators/cross_stub/cross_stub_generator.rb
100
116
  - rails_generators/cross_stub/templates/config/initializers/cross-stub.rb
101
117
  - rails_generators/cross_stub/templates/features/support/cross-stub.rb
102
118
  - spec/.bacon
103
- - spec/cross-stub/clearing_stubs_spec.rb
104
- - spec/cross-stub/creating_stubs_spec.rb
105
- - spec/cross-stub/stubbing_error_spec.rb
106
- - spec/helpers.rb
119
+ - spec/arguments/proc_spec.rb
120
+ - spec/includes.rb
121
+ - spec/integration/clearing_instance_stubs_spec.rb
122
+ - spec/integration/clearing_stubs_spec.rb
123
+ - spec/integration/creating_instance_stubs_spec.rb
124
+ - spec/integration/creating_stubs_spec.rb
125
+ - spec/integration/shared_spec.rb
126
+ - spec/integration/stubbing_error_spec.rb
127
+ - spec/service.rb
107
128
  - spec/spec_helper.rb
108
129
  - tmp/.dummy
109
130
  has_rdoc: true
@@ -116,29 +137,40 @@ rdoc_options:
116
137
  require_paths:
117
138
  - lib
118
139
  required_ruby_version: !ruby/object:Gem::Requirement
140
+ none: false
119
141
  requirements:
120
142
  - - ">="
121
143
  - !ruby/object:Gem::Version
144
+ hash: 57
122
145
  segments:
123
- - 0
124
- version: "0"
146
+ - 1
147
+ - 8
148
+ - 7
149
+ version: 1.8.7
125
150
  required_rubygems_version: !ruby/object:Gem::Requirement
151
+ none: false
126
152
  requirements:
127
153
  - - ">="
128
154
  - !ruby/object:Gem::Version
155
+ hash: 3
129
156
  segments:
130
157
  - 0
131
158
  version: "0"
132
159
  requirements: []
133
160
 
134
161
  rubyforge_project:
135
- rubygems_version: 1.3.6
162
+ rubygems_version: 1.3.7
136
163
  signing_key:
137
164
  specification_version: 3
138
165
  summary: Simple cross process stubbing
139
166
  test_files:
140
- - spec/helpers.rb
141
- - spec/cross-stub/stubbing_error_spec.rb
142
- - spec/cross-stub/clearing_stubs_spec.rb
143
- - spec/cross-stub/creating_stubs_spec.rb
167
+ - spec/includes.rb
168
+ - spec/arguments/proc_spec.rb
169
+ - spec/service.rb
170
+ - spec/integration/stubbing_error_spec.rb
171
+ - spec/integration/creating_instance_stubs_spec.rb
172
+ - spec/integration/shared_spec.rb
173
+ - spec/integration/clearing_stubs_spec.rb
174
+ - spec/integration/creating_stubs_spec.rb
175
+ - spec/integration/clearing_instance_stubs_spec.rb
144
176
  - spec/spec_helper.rb
@@ -1,48 +0,0 @@
1
- module CrossStub
2
-
3
- private
4
-
5
- module CacheHelpers
6
-
7
- def setup_cache
8
- File.open(cache_file, 'w') {|f| Marshal.dump({}, f) }
9
- end
10
-
11
- def update_cache(&blk)
12
- dump_cache(yield(load_cache))
13
- end
14
-
15
- def delete_cache
16
- if File.exists?(cache_file)
17
- File.exists?(backup_cache_file) ?
18
- File.delete(cache_file) : File.rename(cache_file, backup_cache_file)
19
- end
20
- end
21
-
22
- def load_cache
23
- File.open(cache_file,'r') {|f| Marshal.load(f) }
24
- end
25
-
26
- def load_backup_cache
27
- cache = {}
28
- if File.exists?(backup_cache_file)
29
- cache = File.open(backup_cache_file, 'r') {|f| Marshal.load(f) }
30
- File.delete(backup_cache_file)
31
- end
32
- cache
33
- end
34
-
35
- def dump_cache(data)
36
- File.open(cache_file,'w') {|f| Marshal.dump(data, f) }
37
- end
38
-
39
- def backup_cache_file
40
- %\#{options[:file]}.bak\
41
- end
42
-
43
- def cache_file
44
- options[:file]
45
- end
46
-
47
- end
48
- end