liveresource 2.0.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.
Files changed (54) hide show
  1. data/.gitignore +1 -0
  2. data/BSDL +24 -0
  3. data/COPYING +59 -0
  4. data/GPL +339 -0
  5. data/README.md +289 -0
  6. data/Rakefile +47 -0
  7. data/benchmark/benchmark_helper.rb +19 -0
  8. data/benchmark/method_benchmark.rb +94 -0
  9. data/lib/live_resource.rb +66 -0
  10. data/lib/live_resource/attributes.rb +77 -0
  11. data/lib/live_resource/declarations.rb +200 -0
  12. data/lib/live_resource/finders.rb +43 -0
  13. data/lib/live_resource/log_helper.rb +24 -0
  14. data/lib/live_resource/methods.rb +41 -0
  15. data/lib/live_resource/methods/dispatcher.rb +176 -0
  16. data/lib/live_resource/methods/forward.rb +23 -0
  17. data/lib/live_resource/methods/future.rb +27 -0
  18. data/lib/live_resource/methods/method.rb +93 -0
  19. data/lib/live_resource/methods/token.rb +22 -0
  20. data/lib/live_resource/redis_client.rb +100 -0
  21. data/lib/live_resource/redis_client/attributes.rb +40 -0
  22. data/lib/live_resource/redis_client/methods.rb +194 -0
  23. data/lib/live_resource/redis_client/registration.rb +25 -0
  24. data/lib/live_resource/resource.rb +44 -0
  25. data/lib/live_resource/resource_proxy.rb +180 -0
  26. data/old/benchmark/attribute_benchmark.rb +58 -0
  27. data/old/benchmark/thread_benchmark.rb +89 -0
  28. data/old/examples/attribute.rb +22 -0
  29. data/old/examples/attribute_rmw.rb +30 -0
  30. data/old/examples/attribute_subscriber.rb +32 -0
  31. data/old/examples/method_provider_sleep.rb +22 -0
  32. data/old/examples/methods.rb +37 -0
  33. data/old/lib/live_resource/subscriber.rb +98 -0
  34. data/old/redis_test.rb +127 -0
  35. data/old/state_publisher_test.rb +139 -0
  36. data/old/test/attribute_modify_test.rb +52 -0
  37. data/old/test/attribute_options_test.rb +54 -0
  38. data/old/test/attribute_subscriber_test.rb +94 -0
  39. data/old/test/composite_resource_test.rb +61 -0
  40. data/old/test/method_sender_test.rb +41 -0
  41. data/old/test/redis_api_test.rb +185 -0
  42. data/old/test/simple_attribute_test.rb +75 -0
  43. data/test/attribute_test.rb +212 -0
  44. data/test/declarations_test.rb +119 -0
  45. data/test/logger_test.rb +44 -0
  46. data/test/method_call_test.rb +223 -0
  47. data/test/method_forward_continue_test.rb +83 -0
  48. data/test/method_params_test.rb +81 -0
  49. data/test/method_routing_test.rb +59 -0
  50. data/test/multiple_class_test.rb +47 -0
  51. data/test/new_api_DISABLED.rb +127 -0
  52. data/test/test_helper.rb +9 -0
  53. data/test/volume_create_DISABLED.rb +74 -0
  54. metadata +129 -0
@@ -0,0 +1,119 @@
1
+ require_relative 'test_helper'
2
+
3
+ class TestClass < Test::Unit::TestCase
4
+ class Class1
5
+ include LiveResource::Resource
6
+
7
+ @@class_attr = 42
8
+
9
+ remote_reader :name
10
+ remote_writer :write_only
11
+ remote_accessor :accessor
12
+
13
+ resource_name :name
14
+ resource_class :class_1
15
+
16
+ def initialize(name)
17
+ remote_attribute_write(:name, name)
18
+
19
+ self.write_only = 'not yet written'
20
+ self.accessor = nil
21
+ end
22
+
23
+ def self.class_method1(param1, param2)
24
+ (param1 + param2).upcase
25
+ end
26
+
27
+ def method1(param1, param2)
28
+ name + param1 + param2
29
+ end
30
+
31
+ def self.class_attr
32
+ @@class_attr
33
+ end
34
+
35
+ def self.class_attr=(new_value)
36
+ @@class_attr = new_value
37
+ end
38
+
39
+ def self.private_class_method1
40
+ end
41
+ private_class_method :private_class_method1
42
+
43
+ private
44
+
45
+ def private_method1
46
+ end
47
+ end
48
+
49
+ def setup
50
+ Redis.new.flushall
51
+
52
+ LiveResource::RedisClient.logger.level = Logger::INFO
53
+
54
+ # Class resources
55
+ LiveResource::register Class1
56
+ end
57
+
58
+ def teardown
59
+ LiveResource::stop
60
+ end
61
+
62
+ def test_correct_class_methods
63
+ assert_equal [:new, :ruby_new, :class_method1, :class_attr, :class_attr=].sort,
64
+ Class1.remote_methods.sort
65
+ end
66
+
67
+ # TODO: support class attributes (?)
68
+ # def test_correct_class_attributes
69
+ # assert_equal [:class_attr], Class1.remote_attributes
70
+ # end
71
+
72
+ def test_correct_instance_methods
73
+ assert_equal [:method1], Class1.ruby_new("foo").remote_methods
74
+ end
75
+
76
+ def test_correct_instance_attributes
77
+ assert_equal [:name, :write_only=, :accessor, :accessor=].sort,
78
+ Class1.ruby_new("foo").remote_attributes.sort
79
+ end
80
+
81
+ def test_call_class_method
82
+ class_resource = LiveResource::find(:class_1)
83
+
84
+ assert class_resource.respond_to? :new
85
+ assert class_resource.respond_to? :class_method1
86
+
87
+ assert_equal "FOOBAR", class_resource.class_method1("foo", "bar")
88
+ end
89
+
90
+ def test_create_instances
91
+ class_resource = LiveResource::find(:class_1)
92
+
93
+ assert_equal 0, LiveResource::all(:class_1).length
94
+
95
+ class_resource.new("bob")
96
+ class_resource.new("fred")
97
+ class_resource.new("sue")
98
+
99
+ assert_equal 3, LiveResource::all(:class_1).length
100
+ end
101
+
102
+ def test_new_returns_resource_proxy
103
+ class_resource = LiveResource::find(:class_1)
104
+ bob = class_resource.new("bob")
105
+
106
+ assert_equal "bob jones", bob.method1(" ", "jones")
107
+ end
108
+
109
+ def test_resource_proxy_can_get_attributes
110
+ class_resource = LiveResource::find(:class_1)
111
+ bob = class_resource.new("bob")
112
+
113
+ assert_equal "bob", bob.name
114
+ assert_equal nil, bob.accessor
115
+
116
+ bob.accessor = "new value"
117
+ assert_equal "new value", bob.accessor
118
+ end
119
+ end
@@ -0,0 +1,44 @@
1
+ require File.join(File.dirname(__FILE__), 'test_helper')
2
+
3
+ class C
4
+ include LiveResource::LogHelper
5
+
6
+ def initialize
7
+ @log_backend = StringIO.new("", "r+")
8
+ self.logger = Logger.new(@log_backend)
9
+ end
10
+
11
+ def generate_debug
12
+ debug "my debug message"
13
+ end
14
+
15
+ def generate_fatal
16
+ fatal "my fatal message"
17
+ end
18
+
19
+ def dump
20
+ @log_backend.rewind
21
+ @log_backend.readlines
22
+ end
23
+ end
24
+
25
+ class LoggerTest < Test::Unit::TestCase
26
+ def test_basic_logging
27
+ c = C.new
28
+ c.generate_fatal
29
+
30
+ assert_match "my fatal message", c.dump[0]
31
+ end
32
+
33
+ def test_changing_log_levels
34
+ c = C.new
35
+ c.logger.level = Logger::WARN
36
+
37
+ c.generate_debug
38
+ assert_equal 0, c.dump.length
39
+
40
+ c.logger.level = Logger::DEBUG
41
+ c.generate_debug
42
+ assert_match "my debug message", c.dump[0]
43
+ end
44
+ end
@@ -0,0 +1,223 @@
1
+ require_relative 'test_helper'
2
+
3
+ class MethodTest < Test::Unit::TestCase
4
+ class MyClass
5
+ attr_accessor :a, :b
6
+
7
+ def initialize(a, b)
8
+ @a = a
9
+ @b = b
10
+ end
11
+ end
12
+
13
+ # We slice, we dice, we can cut through tin cans!
14
+ class Server
15
+ include LiveResource::Resource
16
+
17
+ resource_class :server
18
+ resource_name :object_id
19
+
20
+ def meaning
21
+ 42
22
+ end
23
+
24
+ def upcase(str)
25
+ str.upcase
26
+ end
27
+
28
+ def slow_upcase(str)
29
+ 10.times { Thread.pass }
30
+ str.upcase
31
+ end
32
+
33
+ def two_second_upcase(str)
34
+ sleep 2
35
+ str.upcase
36
+ end
37
+
38
+ def add(a, b)
39
+ a + b
40
+ end
41
+
42
+ def reverse(arr)
43
+ arr.reverse
44
+ end
45
+
46
+ def swap_a_b(myclass)
47
+ a, b = myclass.a, myclass.b
48
+ myclass.b = a
49
+ myclass.a = b
50
+ myclass
51
+ end
52
+ end
53
+
54
+ def setup
55
+ Redis.new.flushall
56
+
57
+ Server.new
58
+ end
59
+
60
+ def teardown
61
+ LiveResource::stop
62
+ end
63
+
64
+ # TODO: some test like this
65
+ #
66
+ # def test_method_done
67
+ # rs = LiveResource::RedisSpace.new('test')
68
+ #
69
+ # assert_raise(ArgumentError) do
70
+ # rs.method_done? '1' # Doesn't exist yet
71
+ # end
72
+ #
73
+ # rs.method_push '1'
74
+ # assert_equal false, rs.method_done?('1')
75
+ #
76
+ # rs.method_wait
77
+ # assert_equal false, rs.method_done?('1')
78
+ #
79
+ # rs.result_set '1', 42
80
+ # rs.method_done '1'
81
+ # assert_equal true, rs.method_done?('1')
82
+ # end
83
+
84
+ def test_synchronous_method
85
+ starting_keys = Redis.new.dbsize
86
+ client = LiveResource::any(:server)
87
+
88
+ # Zero parameters
89
+ assert_equal 42, client.meaning
90
+
91
+ # One parameter (simple)
92
+ assert_equal "FOOBAR", client.upcase("foobar")
93
+
94
+ # One parameter (complex)
95
+ assert_equal [3, 2, 1], client.reverse([1, 2, 3])
96
+
97
+ # Two parameters
98
+ assert_equal 3, client.add(1, 2)
99
+
100
+ # Non-native class
101
+ myclass = client.swap_a_b MyClass.new("a", "b")
102
+ assert_equal "b", myclass.a
103
+ assert_equal "a", myclass.b
104
+
105
+ # Should have no junk left over in Redis
106
+ assert_equal starting_keys, Redis.new.dbsize
107
+ end
108
+
109
+ def test_method_with_no_response
110
+ starting_keys = Redis.new.dbsize
111
+ client = LiveResource::any(:server)
112
+
113
+ # Do one async call; dispatcher should auto-clean up
114
+ client.upcase! "foobar"
115
+
116
+ # Do a sync call afterward to make sure the first is done
117
+ client.upcase "foobar"
118
+
119
+ assert_equal starting_keys, Redis.new.dbsize
120
+ end
121
+
122
+ def test_no_matching_method
123
+ client = LiveResource::any(:server)
124
+
125
+ assert_raise(NoMethodError) do
126
+ client.this_is_not_a_valid_method
127
+ end
128
+ end
129
+
130
+ def test_method_stress
131
+ starting_keys = Redis.new.dbsize
132
+ client = LiveResource::any(:server)
133
+
134
+ 100.times do
135
+ client.upcase("foobar")
136
+ end
137
+
138
+ # Should have no junk left over in Redis
139
+ assert_equal starting_keys, Redis.new.dbsize
140
+ end
141
+
142
+ def test_method_call_with_future
143
+ starting_keys = Redis.new.dbsize
144
+ client = LiveResource::any(:server)
145
+
146
+ value = client.slow_upcase? 'foobar'
147
+
148
+ assert_not_nil value
149
+ assert_equal false, value.done?
150
+
151
+ # Wait for valid result.
152
+ assert_equal 'FOOBAR', value.value
153
+
154
+ # Should have no junk left over in Redis, BUT we can still get the
155
+ # future's value as many times as we want.
156
+ assert_equal starting_keys, Redis.new.dbsize
157
+ assert_equal 'FOOBAR', value.value
158
+ end
159
+
160
+ # Similar test to above, but in this case we don't wait for done until
161
+ # after we already know the action is done.
162
+ def test_wait_for_done_after_done
163
+ client = LiveResource::any(:server)
164
+
165
+ # Repeat a bunch of times -- this helps catch a race
166
+ # condition in done_with?
167
+ 100.times do
168
+ value = client.slow_upcase? 'foobar'
169
+
170
+ while !value.done?
171
+ Thread.pass
172
+ end
173
+
174
+ # Result should be ready for us
175
+ assert_equal 'FOOBAR', value.value
176
+ end
177
+ end
178
+
179
+ def test_method_timeout_success
180
+ client = LiveResource::any(:server)
181
+ value = client.upcase? "foobar"
182
+
183
+ assert_equal "FOOBAR", value.value(1)
184
+ end
185
+
186
+ def test_method_timeout_failure
187
+ client = LiveResource::any(:server)
188
+
189
+ LiveResource::stop # No servers
190
+
191
+ starting_keys = Redis.new.dbsize
192
+
193
+ assert_raise(RuntimeError) do
194
+ value = client.upcase? "foobar"
195
+ value.value(1)
196
+ end
197
+
198
+ # Should have no junk left over in Redis
199
+ assert_equal starting_keys, Redis.new.dbsize
200
+ end
201
+
202
+ def test_method_completes_after_timeout
203
+ starting_keys = Redis.new.dbsize
204
+ client = LiveResource::any(:server)
205
+
206
+ # Turn up log level; this test will generate an appropriate warning.
207
+ old_level = LiveResource::RedisClient.logger.level = Logger::ERROR
208
+
209
+ # This will fail (as above) but the server will actually complete it a second
210
+ # later. Need to make sure server cleans up ok.
211
+ assert_raise(RuntimeError) do
212
+ value = client.two_second_upcase? "foobar"
213
+ value.value(1)
214
+ end
215
+
216
+ sleep 2
217
+
218
+ # Should have no junk left over in Redis
219
+ assert_equal starting_keys, Redis.new.dbsize
220
+
221
+ LiveResource::RedisClient.logger.level = old_level
222
+ end
223
+ end
@@ -0,0 +1,83 @@
1
+ require_relative 'test_helper'
2
+
3
+ class ForwardContinueTest < Test::Unit::TestCase
4
+ class Class1
5
+ include LiveResource::Resource
6
+
7
+ resource_name :object_id
8
+ resource_class :class_1
9
+
10
+ def method1(param1, param2)
11
+ c2 = LiveResource::any(:class_2)
12
+ c3 = LiveResource::any(:class_3)
13
+ param3 = "baz"
14
+
15
+ forward(c2, :method2, param1, param2, param3).continue(c3, :method3)
16
+ end
17
+ end
18
+
19
+ class Class2
20
+ include LiveResource::Resource
21
+
22
+ resource_name :object_id
23
+ resource_class :class_2
24
+
25
+ def method2(param1, param2, param3)
26
+ [param1, param2, param3].join('-')
27
+ end
28
+ end
29
+
30
+ class Class3
31
+ include LiveResource::Resource
32
+
33
+ resource_name :object_id
34
+ resource_class :class_3
35
+
36
+ def method3(param1)
37
+ param1.upcase
38
+ end
39
+ end
40
+
41
+ def setup
42
+ Redis.new.flushall
43
+
44
+ Class1.new
45
+ Class2.new
46
+ Class3.new
47
+ end
48
+
49
+ def teardown
50
+ LiveResource::stop
51
+ end
52
+
53
+ def test_instances_have_methods
54
+ i = LiveResource::all(:class_1).first
55
+
56
+ assert i.respond_to?(:method1), "instance does not respond to method1"
57
+ end
58
+
59
+ def test_instances_have_async_methods
60
+ i = LiveResource::all(:class_1).first
61
+
62
+ assert i.respond_to?(:method1!), "instance does not respond to method1!"
63
+ assert i.respond_to?(:method1?), "instance does not respond to method1?"
64
+ end
65
+
66
+ def test_instance_does_not_respond_to_invalid_methods
67
+ i = LiveResource::all(:class_1).first
68
+
69
+ assert !i.respond_to?(:method2), "instance should not respond to method2"
70
+ assert !i.respond_to?(:method2!), "instance should not respond to method2!"
71
+ assert !i.respond_to?(:method2?), "instance should not respond to method2?"
72
+ end
73
+
74
+ def test_message_path
75
+ starting_keys = Redis.new.dbsize
76
+
77
+ # LiveResource::RedisClient::logger.level = Logger::DEBUG
78
+ assert_equal "FOO-BAR-BAZ", LiveResource::any(:class_1).method1("foo", "bar")
79
+
80
+ # Should have no junk left over in Redis
81
+ assert_equal starting_keys, Redis.new.dbsize
82
+ end
83
+ end