rhosync 2.0.0.beta1

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 (200) hide show
  1. data/CHANGELOG +5 -0
  2. data/LICENSE +674 -0
  3. data/README.md +26 -0
  4. data/Rakefile +109 -0
  5. data/bench/bench +6 -0
  6. data/bench/benchapp/Rakefile +14 -0
  7. data/bench/benchapp/application.rb +13 -0
  8. data/bench/benchapp/config.ru +32 -0
  9. data/bench/benchapp/settings/license.key +1 -0
  10. data/bench/benchapp/settings/settings.yml +18 -0
  11. data/bench/benchapp/sources/mock_adapter.rb +55 -0
  12. data/bench/benchapp/sources/queue_mock_adapter.rb +2 -0
  13. data/bench/benchapp/vendor/rhosync/lib/rhosync.rb +7 -0
  14. data/bench/lib/bench/cli.rb +16 -0
  15. data/bench/lib/bench/logging.rb +18 -0
  16. data/bench/lib/bench/mock_client.rb +41 -0
  17. data/bench/lib/bench/result.rb +50 -0
  18. data/bench/lib/bench/runner.rb +44 -0
  19. data/bench/lib/bench/session.rb +65 -0
  20. data/bench/lib/bench/statistics.rb +56 -0
  21. data/bench/lib/bench/test_data.rb +55 -0
  22. data/bench/lib/bench/timer.rb +10 -0
  23. data/bench/lib/bench/utils.rb +49 -0
  24. data/bench/lib/bench.rb +128 -0
  25. data/bench/lib/testdata/100-data.txt +148 -0
  26. data/bench/lib/testdata/5-data.txt +11 -0
  27. data/bench/scripts/cud_script.rb +77 -0
  28. data/bench/scripts/helpers.rb +101 -0
  29. data/bench/scripts/query_md_script.rb +46 -0
  30. data/bench/scripts/query_script.rb +46 -0
  31. data/bench/spec/bench_spec_helper.rb +65 -0
  32. data/bench/spec/logging_spec.rb +19 -0
  33. data/bench/spec/mock_adapter_spec.rb +61 -0
  34. data/bench/spec/mock_client_spec.rb +64 -0
  35. data/bench/spec/result_spec.rb +59 -0
  36. data/bench/spec/utils_spec.rb +35 -0
  37. data/bin/rhosync +34 -0
  38. data/doc/protocol.html +1901 -0
  39. data/doc/public/css/print.css +29 -0
  40. data/doc/public/css/screen.css +257 -0
  41. data/doc/public/css/style.css +20 -0
  42. data/examples/simple/application.rb +13 -0
  43. data/examples/simple/sources/sample_adapter.rb +5 -0
  44. data/examples/simple/sources/simple_adapter.rb +5 -0
  45. data/examples/simple/vendor/rhosync/lib/rhosync.rb +7 -0
  46. data/generators/rhosync.rb +98 -0
  47. data/generators/templates/application/Rakefile +19 -0
  48. data/generators/templates/application/application.rb +27 -0
  49. data/generators/templates/application/config.ru +33 -0
  50. data/generators/templates/application/settings/license.key +1 -0
  51. data/generators/templates/application/settings/settings.yml +14 -0
  52. data/generators/templates/source/source_adapter.rb +49 -0
  53. data/lib/rhosync/api/create_client.rb +3 -0
  54. data/lib/rhosync/api/create_user.rb +7 -0
  55. data/lib/rhosync/api/delete_client.rb +5 -0
  56. data/lib/rhosync/api/delete_user.rb +5 -0
  57. data/lib/rhosync/api/get_api_token.rb +7 -0
  58. data/lib/rhosync/api/get_client_params.rb +3 -0
  59. data/lib/rhosync/api/get_db_doc.rb +7 -0
  60. data/lib/rhosync/api/get_license_info.rb +7 -0
  61. data/lib/rhosync/api/get_source_params.rb +3 -0
  62. data/lib/rhosync/api/list_client_docs.rb +12 -0
  63. data/lib/rhosync/api/list_clients.rb +3 -0
  64. data/lib/rhosync/api/list_source_docs.rb +10 -0
  65. data/lib/rhosync/api/list_sources.rb +15 -0
  66. data/lib/rhosync/api/list_users.rb +3 -0
  67. data/lib/rhosync/api/ping.rb +7 -0
  68. data/lib/rhosync/api/push_deletes.rb +6 -0
  69. data/lib/rhosync/api/push_objects.rb +6 -0
  70. data/lib/rhosync/api/reset.rb +10 -0
  71. data/lib/rhosync/api/set_db_doc.rb +8 -0
  72. data/lib/rhosync/api/set_refresh_time.rb +8 -0
  73. data/lib/rhosync/api/update_user.rb +4 -0
  74. data/lib/rhosync/api/upload_file.rb +4 -0
  75. data/lib/rhosync/api_token.rb +19 -0
  76. data/lib/rhosync/app.rb +69 -0
  77. data/lib/rhosync/bulk_data/bulk_data.rb +75 -0
  78. data/lib/rhosync/bulk_data/syncdb.index.schema +3 -0
  79. data/lib/rhosync/bulk_data/syncdb.schema +37 -0
  80. data/lib/rhosync/bulk_data.rb +2 -0
  81. data/lib/rhosync/client.rb +74 -0
  82. data/lib/rhosync/client_sync.rb +296 -0
  83. data/lib/rhosync/console/app/helpers/auth_helper.rb +18 -0
  84. data/lib/rhosync/console/app/helpers/extensions.rb +19 -0
  85. data/lib/rhosync/console/app/helpers/helpers.rb +52 -0
  86. data/lib/rhosync/console/app/public/main.css +7 -0
  87. data/lib/rhosync/console/app/public/text.txt +0 -0
  88. data/lib/rhosync/console/app/routes/auth.rb +29 -0
  89. data/lib/rhosync/console/app/routes/client.rb +32 -0
  90. data/lib/rhosync/console/app/routes/docs.rb +84 -0
  91. data/lib/rhosync/console/app/routes/home.rb +22 -0
  92. data/lib/rhosync/console/app/routes/user.rb +63 -0
  93. data/lib/rhosync/console/app/views/client.erb +30 -0
  94. data/lib/rhosync/console/app/views/doc.erb +56 -0
  95. data/lib/rhosync/console/app/views/docs.erb +29 -0
  96. data/lib/rhosync/console/app/views/index.erb +50 -0
  97. data/lib/rhosync/console/app/views/layout.erb +12 -0
  98. data/lib/rhosync/console/app/views/newuser.erb +17 -0
  99. data/lib/rhosync/console/app/views/ping.erb +28 -0
  100. data/lib/rhosync/console/app/views/result.erb +11 -0
  101. data/lib/rhosync/console/app/views/user.erb +32 -0
  102. data/lib/rhosync/console/app/views/users.erb +14 -0
  103. data/lib/rhosync/console/rhosync_api.rb +102 -0
  104. data/lib/rhosync/console/server.rb +27 -0
  105. data/lib/rhosync/credential.rb +9 -0
  106. data/lib/rhosync/document.rb +43 -0
  107. data/lib/rhosync/indifferent_access.rb +132 -0
  108. data/lib/rhosync/jobs/bulk_data_job.rb +104 -0
  109. data/lib/rhosync/jobs/ping_job.rb +19 -0
  110. data/lib/rhosync/jobs/source_job.rb +16 -0
  111. data/lib/rhosync/license.rb +79 -0
  112. data/lib/rhosync/lock_ops.rb +11 -0
  113. data/lib/rhosync/model.rb +410 -0
  114. data/lib/rhosync/ping/blackberry.rb +55 -0
  115. data/lib/rhosync/ping/iphone.rb +44 -0
  116. data/lib/rhosync/ping.rb +2 -0
  117. data/lib/rhosync/read_state.rb +27 -0
  118. data/lib/rhosync/server/views/index.erb +12 -0
  119. data/lib/rhosync/server.rb +242 -0
  120. data/lib/rhosync/source.rb +112 -0
  121. data/lib/rhosync/source_adapter.rb +95 -0
  122. data/lib/rhosync/source_sync.rb +245 -0
  123. data/lib/rhosync/store.rb +199 -0
  124. data/lib/rhosync/tasks.rb +151 -0
  125. data/lib/rhosync/user.rb +83 -0
  126. data/lib/rhosync/version.rb +3 -0
  127. data/lib/rhosync.rb +251 -0
  128. data/spec/api/api_helper.rb +44 -0
  129. data/spec/api/create_client_spec.rb +13 -0
  130. data/spec/api/create_user_spec.rb +16 -0
  131. data/spec/api/delete_client_spec.rb +13 -0
  132. data/spec/api/delete_user_spec.rb +18 -0
  133. data/spec/api/get_api_token_spec.rb +25 -0
  134. data/spec/api/get_client_params_spec.rb +18 -0
  135. data/spec/api/get_db_doc_spec.rb +21 -0
  136. data/spec/api/get_license_info_spec.rb +16 -0
  137. data/spec/api/get_source_params_spec.rb +26 -0
  138. data/spec/api/list_client_docs_spec.rb +33 -0
  139. data/spec/api/list_clients_spec.rb +23 -0
  140. data/spec/api/list_source_docs_spec.rb +26 -0
  141. data/spec/api/list_sources_spec.rb +27 -0
  142. data/spec/api/list_users_spec.rb +21 -0
  143. data/spec/api/ping_spec.rb +24 -0
  144. data/spec/api/push_deletes_spec.rb +16 -0
  145. data/spec/api/push_objects_spec.rb +27 -0
  146. data/spec/api/reset_spec.rb +22 -0
  147. data/spec/api/set_db_doc_spec.rb +20 -0
  148. data/spec/api/set_refresh_time_spec.rb +43 -0
  149. data/spec/api/update_user_spec.rb +31 -0
  150. data/spec/api/upload_file_spec.rb +26 -0
  151. data/spec/api_token_spec.rb +13 -0
  152. data/spec/app_spec.rb +20 -0
  153. data/spec/apps/rhotestapp/Rakefile +1 -0
  154. data/spec/apps/rhotestapp/application.rb +16 -0
  155. data/spec/apps/rhotestapp/config.ru +1 -0
  156. data/spec/apps/rhotestapp/settings/apple_fake_cert.pem +1 -0
  157. data/spec/apps/rhotestapp/settings/license.key +1 -0
  158. data/spec/apps/rhotestapp/settings/settings.yml +23 -0
  159. data/spec/apps/rhotestapp/sources/base_adapter.rb +9 -0
  160. data/spec/apps/rhotestapp/sources/sample_adapter.rb +66 -0
  161. data/spec/apps/rhotestapp/sources/simple_adapter.rb +39 -0
  162. data/spec/apps/rhotestapp/sources/sub_adapter.rb +7 -0
  163. data/spec/apps/rhotestapp/vendor/mygem-0.1.0/lib/mygem/mygem.rb +8 -0
  164. data/spec/apps/rhotestapp/vendor/mygem-0.1.0/lib/mygem.rb +1 -0
  165. data/spec/bulk_data/bulk_data_spec.rb +79 -0
  166. data/spec/client_spec.rb +58 -0
  167. data/spec/client_sync_spec.rb +377 -0
  168. data/spec/doc/base.html +72 -0
  169. data/spec/doc/doc_spec.rb +303 -0
  170. data/spec/doc/footer.html +4 -0
  171. data/spec/doc/header.html +30 -0
  172. data/spec/document_spec.rb +27 -0
  173. data/spec/generator/generator_spec.rb +53 -0
  174. data/spec/generator/generator_spec_helper.rb +8 -0
  175. data/spec/jobs/bulk_data_job_spec.rb +76 -0
  176. data/spec/jobs/ping_job_spec.rb +26 -0
  177. data/spec/jobs/source_job_spec.rb +25 -0
  178. data/spec/license_spec.rb +48 -0
  179. data/spec/model_spec.rb +269 -0
  180. data/spec/perf/bulk_data_perf_spec.rb +33 -0
  181. data/spec/perf/perf_spec_helper.rb +51 -0
  182. data/spec/perf/store_perf_spec.rb +28 -0
  183. data/spec/ping/blackberry_spec.rb +62 -0
  184. data/spec/ping/iphone_spec.rb +50 -0
  185. data/spec/read_state_spec.rb +25 -0
  186. data/spec/rhosync_spec.rb +43 -0
  187. data/spec/server/server_spec.rb +341 -0
  188. data/spec/source_adapter_spec.rb +114 -0
  189. data/spec/source_spec.rb +77 -0
  190. data/spec/source_sync_spec.rb +248 -0
  191. data/spec/spec_helper.rb +240 -0
  192. data/spec/store_spec.rb +149 -0
  193. data/spec/sync_states_spec.rb +101 -0
  194. data/spec/testdata/1000-data.txt +1414 -0
  195. data/spec/testdata/compressed/compress-data.txt +1 -0
  196. data/spec/testdata/upload1.txt +1 -0
  197. data/spec/testdata/upload2.txt +1 -0
  198. data/spec/user_spec.rb +79 -0
  199. data/tasks/redis.rake +134 -0
  200. metadata +545 -0
@@ -0,0 +1,65 @@
1
+ require 'rubygems'
2
+ require 'log4r'
3
+ $:.unshift File.join(File.dirname(__FILE__),'..')
4
+ $:.unshift File.join(File.dirname(__FILE__),'..','lib')
5
+ require 'bench/logging'
6
+ require 'bench/mock_client'
7
+ require 'bench/utils'
8
+ require 'bench/result'
9
+ include Bench
10
+
11
+ describe "BenchSpecHelper", :shared => true do
12
+ before(:each) do
13
+ Store.create
14
+ Store.db.flushdb
15
+
16
+ @product1 = {
17
+ 'name' => 'iPhone',
18
+ 'brand' => 'Apple',
19
+ 'price' => '199.99'
20
+ }
21
+
22
+ @product2 = {
23
+ 'name' => 'G2',
24
+ 'brand' => 'Android',
25
+ 'price' => '99.99'
26
+ }
27
+
28
+ @product3 = {
29
+ 'name' => 'Fuze',
30
+ 'brand' => 'HTC',
31
+ 'price' => '299.99'
32
+ }
33
+
34
+ @product4 = {
35
+ 'name' => 'Droid',
36
+ 'brand' => 'Android',
37
+ 'price' => '249.99'
38
+ }
39
+
40
+ @data = {'1'=>@product1,'2'=>@product2,'3'=>@product3}
41
+ end
42
+
43
+ def set_state(state)
44
+ state.each do |dockey,data|
45
+ if data.is_a?(Hash) or data.is_a?(Array)
46
+ Store.put_data(dockey,data)
47
+ else
48
+ Store.put_value(dockey,data)
49
+ end
50
+ end
51
+ end
52
+
53
+ def verify_result(result)
54
+ result.each do |dockey,expected|
55
+ if expected.is_a?(Hash)
56
+ Store.get_data(dockey).should == expected
57
+ elsif expected.is_a?(Array)
58
+ Store.get_data(dockey,Array).should == expected
59
+ else
60
+ Store.get_value(dockey).should == expected
61
+ end
62
+ end
63
+ end
64
+
65
+ end
@@ -0,0 +1,19 @@
1
+ $:.unshift File.join(File.dirname(__FILE__))
2
+ require 'bench_spec_helper'
3
+
4
+ describe "Logging" do
5
+
6
+ before(:each) do
7
+ @mc = MockClient.new(1,2,123)
8
+ end
9
+
10
+ it "should get logger" do
11
+ @mc.logger.class.should == Log4r::Logger
12
+ end
13
+
14
+ it "should get prefix" do
15
+ @mc.log_prefix.should == "[T:001|I:002]"
16
+ end
17
+
18
+ end
19
+
@@ -0,0 +1,61 @@
1
+ $:.unshift File.join(File.dirname(__FILE__))
2
+ require 'bench_spec_helper'
3
+ require 'benchapp/sources/mock_adapter'
4
+
5
+ describe "MockAdapter" do
6
+ it_should_behave_like "BenchSpecHelper"
7
+
8
+ before(:each) do
9
+ @s_fields = {
10
+ :source_id => 1,
11
+ :name => 'SampleAdapter',
12
+ :url => 'http://example.com',
13
+ :login => 'testuser',
14
+ :password => 'testpass',
15
+ }
16
+ @s_params = {
17
+ :user_id => 'mock_user_id',
18
+ :app_id => 'mock_app_id'
19
+ }
20
+ @s = Source.create(@s_fields,@s_params)
21
+ @ma = MockAdapter.new(@s,nil)
22
+ end
23
+
24
+ it "should return db name" do
25
+ @ma.db_name.should == "test_db_storage:mock_app_id:mock_user_id"
26
+ end
27
+
28
+ it "should return db lock name" do
29
+ @ma.lock_name.should == "test_db_storage:mock_app_id:mock_user_id:lock"
30
+ end
31
+
32
+ it "should login" do
33
+ @ma.login.should == true
34
+ end
35
+
36
+ it "should query data from db" do
37
+ set_state(@ma.db_name => @data)
38
+ @ma.query.should == @data
39
+ end
40
+
41
+ it "should create object in the db" do
42
+ @product1.merge!('mock_id'=>'1')
43
+ @ma.create(@product1).should == '1'
44
+ verify_result(@ma.db_name => {'1' => @product1})
45
+ end
46
+
47
+ it "should update object in db" do
48
+ set_state(@ma.db_name => @data)
49
+ @ma.update('id' => '3','price' => '99.99')
50
+ @product3['price'] = '99.99'
51
+ verify_result(@ma.db_name => @data)
52
+ end
53
+
54
+ it "should delete object in db" do
55
+ set_state(@ma.db_name => @data)
56
+ del_object = {}.merge!(@product2).merge!('id'=>'2')
57
+ @ma.delete(del_object)
58
+ verify_result(@ma.db_name => {'1' => @product1, '3' => @product3})
59
+ end
60
+
61
+ end
@@ -0,0 +1,64 @@
1
+ $:.unshift File.join(File.dirname(__FILE__))
2
+ require 'bench_spec_helper'
3
+
4
+ describe "MockClient" do
5
+ it_should_behave_like "BenchSpecHelper"
6
+
7
+ before(:each) do
8
+ @mc = MockClient.new(1,2,123)
9
+ end
10
+
11
+ it "should return document type" do
12
+ @mc.doc_type.should == "123:mock:cd"
13
+ end
14
+
15
+ it "should insert objects into the client document" do
16
+ @mc.insert(@data)
17
+ verify_result(@mc.doc_type => @data)
18
+ end
19
+
20
+ it "should delete objects from the client document" do
21
+ set_state(@mc.doc_type => @data)
22
+ @mc.delete('1' => @product1,'3' => @product3)
23
+ verify_result(@mc.doc_type => {'2' => @product2})
24
+ end
25
+
26
+ it "should verify state of the client document" do
27
+ set_state(@mc.doc_type => @data)
28
+ @mc.verify(@data).should == true
29
+ @mc.verify('1' => @product1,'3' => @product3).should == false
30
+ end
31
+
32
+ it "should parse server message and insert objects into the client document" do
33
+ message = [{:version => 3},{:token=>'123'},{:count=>3},{:progress_count=>0},{:total_count=>3},{:insert=>@data}].to_json
34
+ @mc.parse message
35
+ verify_result(@mc.doc_type => @data)
36
+ end
37
+
38
+ it "should parse server message and delete objects for the client document" do
39
+ set_state(@mc.doc_type => @data)
40
+ message = [{:version => 3},{:token=>'123'},{:count=>3},{:progress_count=>0},{:total_count=>3},{:delete=>{'2'=>@product2}}].to_json
41
+ @mc.parse message
42
+ verify_result(@mc.doc_type => {'1' => @product1,'3' => @product3})
43
+ end
44
+
45
+ it "should parse server message and insert/delete objects to/from client document" do
46
+ set_state(@mc.doc_type => {'1' => @product1,'2' => @product2})
47
+ message = [{:version => 3},{:token=>'123'},{:count=>3},{:progress_count=>0},{:total_count=>3},
48
+ {:insert=>{'3'=>@product3}},{:delete=>{'2'=>@product2}}].to_json
49
+ @mc.parse message
50
+ verify_result(@mc.doc_type => {'1' => @product1,'3' => @product3})
51
+ end
52
+
53
+ it "should raise exception on wrong message format" do
54
+ message = [{:version => 3},{:token=>'123'},{:count=>3},{:progress_count=>0}].to_json
55
+ lambda { @mc.parse message }.should raise_error(Exception,
56
+ '[T:001|I:002] Wrong message format. Message: "[{\"version\":3},{\"token\":\"123\"},{\"count\":3},{\"progress_count\":0}]"')
57
+ end
58
+
59
+ it "should raise exception on wrong protocol version" do
60
+ message = [{:version => 1},{:token=>'123'},{:count=>3},{:progress_count=>0},{:total_count=>0},{}].to_json
61
+ lambda { @mc.parse message }.should raise_error(Exception,
62
+ '[T:001|I:002] Wrong protocol version. Message: "[{\"version\":1},{\"token\":\"123\"},{\"count\":3},{\"progress_count\":0},{\"total_count\":0},{}]"')
63
+ end
64
+ end
@@ -0,0 +1,59 @@
1
+ $:.unshift File.join(File.dirname(__FILE__))
2
+ require 'bench_spec_helper'
3
+ require 'rest_client'
4
+
5
+ describe "ResultSpec" do
6
+ it_should_behave_like "BenchSpecHelper"
7
+ include Utils
8
+
9
+ before(:each) do
10
+ @s1 = [{"foo" => {"bar" => "cake"}}]
11
+ @s2 = [{"foo" => {"bar" => "cake1"}},{"hello" => "world"}]
12
+ @result = Result.new("marker",:get,"some/url",0,1)
13
+ client = mock("RestClient")
14
+ client.stub!(:headers).and_return({'header1'=>'headervalue1'})
15
+ client.stub!(:cookies).and_return({'session1'=>'sessval1'})
16
+ client.stub!(:code).and_return(200)
17
+ client.stub!(:to_s).and_return(@s1.to_json)
18
+ @result.last_response = client
19
+ end
20
+
21
+ describe "test @last_response wrapper" do
22
+
23
+ it "shold return 'code'" do
24
+ @result.code.should == 200
25
+ end
26
+
27
+ it "shold return 'body'" do
28
+ JSON.parse(@result.body).should == @s1
29
+ end
30
+
31
+ it "shold return 'cookies'" do
32
+ @result.cookies.should == {'session1'=>'sessval1'}
33
+ end
34
+
35
+ it "shhould return 'headers'" do
36
+ @result.headers.should == {'header1'=>'headervalue1'}
37
+ end
38
+
39
+ end
40
+
41
+ it "should compare two array/hash structures" do
42
+ compare(:expected,@s1,:actual,@s2).should == [{:expected=>"cake",
43
+ :path=>[0, "foo", "bar"], :actual=>"cake1"},
44
+ {:expected=>nil, :path=>[1], :actual=>{"hello"=>"world"}}]
45
+ end
46
+
47
+ it "should verify body" do
48
+ @result.logger.should_receive(:error).exactly(8).times
49
+ @result.verify_body(@s2.to_json)
50
+ @result.verification_error.should == 1
51
+ end
52
+
53
+ it "should verify code" do
54
+ @result.logger.should_receive(:error).exactly(4).times
55
+ @result.verify_code(500)
56
+ @result.verification_error.should == 1
57
+ end
58
+
59
+ end
@@ -0,0 +1,35 @@
1
+ $:.unshift File.join(File.dirname(__FILE__))
2
+ require 'bench_spec_helper'
3
+
4
+ describe "UtilsSpec" do
5
+ it_should_behave_like "BenchSpecHelper"
6
+ include Utils
7
+ include Logging
8
+
9
+ it "should compare two identical hashes" do
10
+ h1 = {'key1' => {'key2' => 'value2'}}
11
+ h2 = {'key1' => {'key2' => 'value2'}}
12
+ compare(:expected,h1,:actual,h2).should == []
13
+ end
14
+
15
+ it "should compare two different hashes" do
16
+ h1 = {'key1' => {'key2' => 'value2'}}
17
+ h2 = {'key1' => {'key2' => 'value3'}}
18
+ compare(:expected,h1,:actual,h2).should ==
19
+ [{:actual=>"value3", :path=>["key1", "key2"], :expected=>"value2"}]
20
+ end
21
+
22
+ it "should compare_and_log two identical hashes" do
23
+ h1 = {'key1' => {'key2' => 'value2'}}
24
+ h2 = {'key1' => {'key2' => 'value2'}}
25
+ logger.should_not_receive(:error)
26
+ compare_and_log(h1,h2,'the caller').should == 0
27
+ end
28
+
29
+ it "should compare_and_log two different hashes" do
30
+ h1 = {'key1' => {'key2' => 'value2'}}
31
+ h2 = {'key1' => {'key2' => 'value3'}}
32
+ logger.should_receive(:error).exactly(5).times
33
+ compare_and_log(h1,h2,'the caller').should == 1
34
+ end
35
+ end
data/bin/rhosync ADDED
@@ -0,0 +1,34 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'rubygems'
4
+ require 'templater'
5
+ require File.join(File.dirname(__FILE__), '..','generators','rhosync')
6
+ $:.unshift File.join(File.dirname(__FILE__),'..','lib')
7
+ require File.join(File.dirname(__FILE__), '..','lib','rhosync')
8
+
9
+ # Stub this method to force 1.8 compatibility (come on templater!)
10
+ class Encoding
11
+ def find
12
+ "utf-8"
13
+ end
14
+
15
+ def dummy?
16
+ false
17
+ end
18
+ end
19
+
20
+ class String
21
+ def force_encoding(enc)
22
+ return self
23
+ end
24
+ def encoding
25
+ if RUBY_VERSION =~ /1\.8/ and Encoding.responds_to?('new')
26
+ Encoding.new
27
+ else
28
+ Encoding.default_external
29
+ end
30
+ end
31
+ end
32
+
33
+
34
+ Rhosync.run_cli(Dir.pwd, 'rhosync', Rhosync::VERSION, ARGV)