rhosync 2.0.0.beta1

Sign up to get free protection for your applications and to get access to all the features.
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,72 @@
1
+ <h2 id='<%=data[:rand_id].to_s%>'><%="#{data[:rand_id].to_s}. #{data[:title]} - #{data[:description]}"%></h2>
2
+
3
+ <h3>Request: <%=data[:req_method]%> <%=data[:req_url]+data[:req_query_string]%></h3>
4
+ <table>
5
+ <thead>
6
+ <tr>
7
+ <th>Header</th>
8
+ <th>Value</th>
9
+ </tr>
10
+ </thead>
11
+ <tbody>
12
+ <tr>
13
+ <td style='text-align: left;'>Content-Type</td>
14
+ <td style='text-align: left;'><%=data[:req_content_type]%></td>
15
+ </tr>
16
+ <tr>
17
+ <td style='text-align: left;'>Content-Length</td>
18
+ <td style='text-align: left;'><%=data[:req_content_length]%></td>
19
+ </tr>
20
+ <tr>
21
+ <td style='text-align: left;'>Cookie</td>
22
+ <td style='text-align: left;'><%=data[:req_cookie]%></td>
23
+ </tr>
24
+ </tbody>
25
+ </table>
26
+ <table>
27
+ <thead>
28
+ <tr>
29
+ <th>Body</th>
30
+ </tr>
31
+ </thead>
32
+ <tbody>
33
+ <tr>
34
+ <td><%=data[:req_body]%></td>
35
+ </tr>
36
+ </tbody>
37
+ </table>
38
+ <h3>Response: <%=data[:res_status]%></h3>
39
+ <table>
40
+ <thead>
41
+ <tr>
42
+ <th>Header</th>
43
+ <th>Value</th>
44
+ </tr>
45
+ </thead>
46
+ <tbody>
47
+ <tr>
48
+ <td style='text-align: left;'>Content-Type</td>
49
+ <td style='text-align: left;'><%=data[:res_content_type]%></td>
50
+ </tr>
51
+ <tr>
52
+ <td style='text-align: left;'>Content-Length</td>
53
+ <td style='text-align: left;'><%=data[:res_content_length]%></td>
54
+ </tr>
55
+ <tr>
56
+ <td style='text-align: left;'>Set-Cookie</td>
57
+ <td style='text-align: left;'><%=data[:res_cookie]%></td>
58
+ </tr>
59
+ </tbody>
60
+ </table>
61
+ <table>
62
+ <thead>
63
+ <tr>
64
+ <th>Body</th>
65
+ </tr>
66
+ </thead>
67
+ <tbody>
68
+ <tr>
69
+ <td style='text-align: left;'><%=data[:res_body]%></td>
70
+ </tr>
71
+ </tbody>
72
+ </table>
@@ -0,0 +1,303 @@
1
+ require File.join(File.dirname(__FILE__),'..','spec_helper')
2
+ require 'rack/test'
3
+ require 'spec'
4
+ require 'spec/autorun'
5
+ require 'spec/interop/test'
6
+
7
+ require File.join(File.dirname(__FILE__),'..','..','lib','rhosync','server.rb')
8
+
9
+ describe "Protocol" do
10
+ it_should_behave_like "SourceAdapterHelper"
11
+ it_should_behave_like "TestappHelper"
12
+
13
+ include Rack::Test::Methods
14
+ include Rhosync
15
+
16
+ Rhosync.log_disabled = true
17
+ it_should_behave_like "SourceAdapterHelper"
18
+
19
+ before(:each) do
20
+ $rand_id ||= 0
21
+ $content_table ||= []
22
+ $content ||= []
23
+ require File.join(get_testapp_path,@test_app_name)
24
+ Rhosync.bootstrap(get_testapp_path) do |rhosync|
25
+ rhosync.vendor_directory = File.join(rhosync.base_directory,'..','..','..','vendor')
26
+ end
27
+ Server.set(
28
+ :environment => :test,
29
+ :run => false,
30
+ :secret => "secure!"
31
+ )
32
+ Server.use Rack::Static, :urls => ["/data"],
33
+ :root => File.join(File.dirname(__FILE__),'..','apps',@test_app_name)
34
+ end
35
+
36
+ before(:each) do
37
+ do_post "/#{@a.name}/clientlogin", "login" => @u.login, "password" => 'testpass'
38
+ @title,@description = nil,nil
39
+ $rand_id += 1
40
+ end
41
+
42
+ def app
43
+ @app ||= Server.new
44
+ end
45
+
46
+ after(:each) do
47
+ #_print_messages
48
+ _print_markdown if @title and @description
49
+ end
50
+
51
+ after(:all) do
52
+ _write_doc if $content and $content.length > 0
53
+ end
54
+
55
+ it "clientlogin" do
56
+ do_post "/#{@a.name}/clientlogin", "login" => @u.login, "password" => 'testpass'
57
+ @title,@description = 'clientlogin', 'authenticate client'
58
+ end
59
+
60
+ it "wrong login or password clientlogin" do
61
+ do_post "/#{@a.name}/clientlogin", "login" => @u.login, "password" => 'wrongpass'
62
+ @title,@description = 'clientlogin', 'login failure'
63
+ end
64
+
65
+ it "clientcreate" do
66
+ get "/#{@a.name}/clientcreate"
67
+ @title,@description = 'clientcreate', 'create client id'
68
+ end
69
+
70
+ it "clientcreate" do
71
+ get "/#{@a.name}/clientcreate?device_type=iPhone&device_pin=abcd&device_port=3333"
72
+ @title,@description = 'clientcreate-and-register', 'create client id with register params'
73
+ end
74
+
75
+ it "clientregister" do
76
+ do_post "/#{@a.name}/clientregister",
77
+ "device_type" => "iPhone", "device_pin" => "abcd",
78
+ "device_port" => "3333", "client_id" => @c.id
79
+ @title,@description = 'clientregister', 'register client with params'
80
+ end
81
+
82
+ it "clientreset" do
83
+ get "/#{@a.name}/clientreset", :client_id => @c.id
84
+ @title,@description = 'clientreset', 'reset client database'
85
+ end
86
+
87
+ ['create','update','delete'].each do |operation|
88
+ it "client #{operation} object(s)" do
89
+ params = {operation=>{'1'=>@product1},
90
+ :client_id => @c.id,
91
+ :source_name => @s.name}
92
+ do_post "/#{@a.name}", params
93
+ @title,@description = operation, "#{operation} object(s)"
94
+ end
95
+ end
96
+
97
+ it "client creates blobs" do
98
+ body = <<eol
99
+ <pre>------------XnJLe9ZIbbGUYtzPQJ16u1
100
+ Content-Disposition: form-data; name="txtfile-rhoblob-1"; filename="upload1.txt"
101
+ Content-Type: application/octet-stream
102
+ Content-Length: 5
103
+
104
+ hello
105
+ ------------XnJLe9ZIbbGUYtzPQJ16u1
106
+ Content-Disposition: form-data; name="txtfile-rhoblob-2"; filename="upload2.txt"
107
+ Content-Type: application/octet-stream
108
+ Content-Length: 5
109
+
110
+ world
111
+ ------------XnJLe9ZIbbGUYtzPQJ16u1
112
+ Content-Disposition: form-data; name="cud"
113
+
114
+ {"client_id":"278c76a7ab2a4f64ba804c1aa22504f3","source_name":"SampleAdapter","version":3,"create":{"1":{"price":"199.99","brand":"Apple","name":"iPhone","txtfile-rhoblob":"upload1.txt","_id":"tempobj1"},"2":{"price":"99.99","brand":"Android","name":"G2","txtfile-rhoblob":"upload2.txt","_id":"tempobj2"}},"blob_fields":["txtfile-rhoblob"]}
115
+ ------------XnJLe9ZIbbGUYtzPQJ16u1--</pre>
116
+ eol
117
+ @title,@description = 'create', 'client creates blobs'
118
+ $content_table << {$rand_id => "#{@title} - #{@description}"}
119
+ data = {
120
+ :title => @title,
121
+ :description => @description,
122
+ :rand_id => $rand_id,
123
+ :req_method => 'POST',
124
+ :req_url => '/application',
125
+ :req_query_string => '',
126
+ :req_content_type => "multipart/form-data; boundary=----------XnJLe9ZIbbGUYtzPQJ16u1",
127
+ :req_content_length => 833,
128
+ :req_cookie => "rhosync_session=BAh7CDoNYXBwX25hbWUiEGFwcGxpY2F0aW9uOglhdXRoIg5kZWxlZ2F0ZWQ6\nCmxvZ2luIg10ZXN0dXNlcg==\n--87659670a0625baf4cdd81bdb9bf829b4567eb35",
129
+ :req_body => body,
130
+ :res_status => 200,
131
+ :res_content_type => 'text/html',
132
+ :res_content_length => 0,
133
+ :res_cookie => "rhosync_session=BAh7CDoKbG9naW4iDXRlc3R1c2VyOg1hcHBfbmFtZSIPcmhvdGVzdGFwcDoJ%0AYXV0aCIOZGVsZWdhdGVk%0A--788449811455529433e658e1c486c622f47ee0d8; path=/; expires=Mon, 04-Apr-2011 19:29:32",
134
+ :res_body => ''
135
+ }
136
+ $content << data
137
+ @title,@description = nil,nil
138
+ end
139
+
140
+ it "client create,update,delete objects" do
141
+ params = {'create'=>{'1'=>@product1},
142
+ 'update'=>{'2'=>@product2},
143
+ 'delete'=>{'3'=>@product3},
144
+ :client_id => @c.id,
145
+ :source_name => @s.name}
146
+ do_post "/#{@a.name}", params
147
+ @title,@description = 'create-update-delete', 'create,update,delete object(s)'
148
+ end
149
+
150
+ it "server sends link created object" do
151
+ @product4['link'] = 'test link'
152
+ params = {'create'=>{'4'=>@product4},
153
+ :client_id => @c.id,
154
+ :source_name => @s.name}
155
+ do_post "/#{@a.name}", params
156
+ get "/#{@a.name}",:client_id => @c.id,:source_name => @s.name,
157
+ :version => ClientSync::VERSION
158
+ @title,@description = 'create-with-link', 'send link for created object'
159
+ end
160
+
161
+ it "server send source query error to client" do
162
+ set_test_data('test_db_storage',{},"Error during query",'query error')
163
+ get "/#{@a.name}",:client_id => @c.id,:source_name => @s.name,:version => ClientSync::VERSION
164
+ @title,@description = 'query-error', 'send query error'
165
+ end
166
+
167
+ it "server send source login error to client" do
168
+ @u.login = nil
169
+ get "/#{@a.name}",:client_id => @c.id,:source_name => @s.name,:version => ClientSync::VERSION
170
+ @title,@description = 'login-error', 'send login error'
171
+ end
172
+
173
+ it "server send source logoff error to client" do
174
+ set_test_data('test_db_storage',{},"Error logging off",'logoff error')
175
+ get "/#{@a.name}",:client_id => @c.id,:source_name => @s.name,:version => ClientSync::VERSION
176
+ @title,@description = 'logoff-error', 'send logoff error'
177
+ end
178
+
179
+ ['create','update','delete'].each do |operation|
180
+ it "client #{operation} object(s) with error" do
181
+ params = {operation=>{ERROR=>{'an_attribute'=>"error #{operation}",'name'=>'wrongname'}},
182
+ :client_id => @c.id,
183
+ :source_name => @s.name}
184
+ do_post "/#{@a.name}", params
185
+ get "/#{@a.name}",:client_id => @c.id,:source_name => @s.name,:version => ClientSync::VERSION
186
+ @title,@description = "#{operation}-error", "send #{operation} error"
187
+ end
188
+ end
189
+
190
+ it "server send insert objects to client" do
191
+ cs = ClientSync.new(@s,@c,1)
192
+ data = {'1'=>@product1,'2'=>@product2}
193
+ set_test_data('test_db_storage',data)
194
+ get "/#{@a.name}",:client_id => @c.id,:source_name => @s.name,:version => ClientSync::VERSION
195
+ @title,@description = 'insert objects', 'send insert objects'
196
+ end
197
+
198
+ it "server send metadata to client" do
199
+ mock_metadata_method([SampleAdapter]) do
200
+ cs = ClientSync.new(@s,@c,1)
201
+ set_test_data('test_db_storage',@data)
202
+ get "/#{@a.name}",:client_id => @c.id,:source_name => @s.name,:version => ClientSync::VERSION
203
+ end
204
+ @title,@description = 'metadata', 'send metadata'
205
+ end
206
+
207
+ it "server send delete objects to client" do
208
+ cs = ClientSync.new(@s,@c,1)
209
+ data = {'1'=>@product1,'2'=>@product2}
210
+ set_test_data('test_db_storage',data)
211
+ get "/#{@a.name}",:client_id => @c.id,:source_name => @s.name,:version => ClientSync::VERSION
212
+ token = Store.get_value(@c.docname(:page_token))
213
+ Store.flash_data('test_db_storage')
214
+ @s.read_state.refresh_time = Time.now.to_i
215
+ get "/#{@a.name}",:client_id => @c.id,:source_name => @s.name,:token => token,
216
+ :version => ClientSync::VERSION
217
+ @title,@description = 'delete objects', 'send delete objects'
218
+ end
219
+
220
+ it "server send insert,delete objects to client" do
221
+ cs = ClientSync.new(@s,@c,1)
222
+ data = {'1'=>@product1,'2'=>@product2}
223
+ set_test_data('test_db_storage',data)
224
+ get "/#{@a.name}",:client_id => @c.id,:source_name => @s.name,:version => ClientSync::VERSION
225
+ token = Store.get_value(@c.docname(:page_token))
226
+ set_test_data('test_db_storage',{'1'=>@product1,'3'=>@product3})
227
+ @s.read_state.refresh_time = Time.now.to_i
228
+ get "/#{@a.name}",:client_id => @c.id,:source_name => @s.name,:token => token,
229
+ :version => ClientSync::VERSION
230
+ @title,@description = 'insert-delete objects', 'send insert and delete objects'
231
+ end
232
+
233
+ it "server send search results" do
234
+ sources = ['SampleAdapter']
235
+ Store.put_data('test_db_storage',@data)
236
+ params = {:client_id => @c.id,:sources => sources,:search => {'name' => 'iPhone'},
237
+ :version => ClientSync::VERSION}
238
+ get "/#{@a.name}/search",params
239
+ @title,@description = 'search result', 'send search results'
240
+ end
241
+
242
+ it "should get search results with error" do
243
+ sources = ['SampleAdapter']
244
+ msg = "Error during search"
245
+ error = set_test_data('test_db_storage',@data,msg,'search error')
246
+ params = {:client_id => @c.id,:sources => sources,:search => {'name' => 'iPhone'},
247
+ :version => ClientSync::VERSION}
248
+ get "/#{@a.name}/search",params
249
+ @title,@description = 'search error', 'send search error'
250
+ end
251
+
252
+ it "should get multiple source search results" do
253
+ @s_fields[:name] = 'SimpleAdapter'
254
+ @s1 = Source.load(@s_fields,@s_params)
255
+ Store.put_data('test_db_storage',@data)
256
+ sources = ['SimpleAdapter','SampleAdapter']
257
+ params = {:client_id => @c.id,:sources => sources,:search => {'search' => 'bar'},
258
+ :version => ClientSync::VERSION}
259
+ get "/#{@a.name}/search",params
260
+ @title,@description = 'multi source search', 'send multiple sources in search results'
261
+ end
262
+
263
+ private
264
+ def _print_markdown
265
+ $content_table << {$rand_id => "#{@title} - #{@description}"}
266
+ data = {
267
+ :title => @title,
268
+ :description => @description,
269
+ :rand_id => $rand_id,
270
+ :req_method => last_request.env['REQUEST_METHOD'],
271
+ :req_url => last_request.env['PATH_INFO'],
272
+ :req_query_string => last_request.env['QUERY_STRING'].empty? ? '' : "?#{last_request.env['QUERY_STRING']}",
273
+ :req_content_type => _get_header_text(last_request.env['CONTENT_TYPE']),
274
+ :req_content_length => _get_header_text(last_request.env['CONTENT_LENGTH']),
275
+ :req_cookie => _get_header_text(last_request.env['HTTP_COOKIE']),
276
+ :req_body => last_request.body.read,
277
+ :res_status => last_response.status.to_s,
278
+ :res_content_type => _get_header_text(last_response.headers['Content-Type']),
279
+ :res_content_length => _get_header_text(last_response.headers['Content-Length']),
280
+ :res_cookie => _get_header_text(last_response.headers['Set-Cookie']),
281
+ :res_body => last_response.body
282
+ }
283
+ last_request.body.rewind
284
+ $content << data
285
+ end
286
+
287
+ def _write_doc
288
+ File.open(File.join('doc','protocol.html'),'w') do |file|
289
+ header = ERB.new(File.read(File.join(File.dirname(__FILE__),'header.html'))).result(binding)
290
+ file.write(header)
291
+ page = ERB.new(File.read(File.join(File.dirname(__FILE__),'base.html')))
292
+ $content.each do |data|
293
+ file.write(page.result(binding))
294
+ end
295
+ footer = ERB.new(File.read(File.join(File.dirname(__FILE__),'footer.html'))).result(binding)
296
+ file.write(footer)
297
+ end
298
+ end
299
+
300
+ def _get_header_text(header)
301
+ header ? header : '&nbsp;'
302
+ end
303
+ end
@@ -0,0 +1,4 @@
1
+ </div>
2
+ </div>
3
+ </body>
4
+ </html>
@@ -0,0 +1,30 @@
1
+ <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
2
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
3
+ <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
4
+ <head>
5
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
6
+ <title>Rhosync API</title>
7
+
8
+ <link rel="stylesheet" href="./public/css/screen.css" type="text/css" media="screen, projection">
9
+ <link rel="stylesheet" href="./public/css/print.css" type="text/css" media="print">
10
+ <!--[if lt IE 8]>
11
+ <link rel="stylesheet" href="./public/css/ie.css" type="text/css" media="screen, projection">
12
+ <![endif]-->
13
+ <link rel="stylesheet" href="./public/css/style.css" type="text/css" media="screen" charset="utf-8"/>
14
+ </head>
15
+
16
+ <body>
17
+ <br/><br/>
18
+ <div class="container">
19
+ <div id="wrapper">
20
+ <h1>Table of Contents</h1>
21
+ <ul id="toc">
22
+ <%$content_table.each do |toc|%>
23
+ <li><span><%=toc.keys[0]%>.</span> <a href="#<%=toc.keys[0]%>"><%=toc.values[0]%></a><br/></li>
24
+ <%end%>
25
+ </ul>
26
+ </div>
27
+ </div>
28
+ <br/><br/>
29
+ <div class="container">
30
+ <div class="span-24 content">
@@ -0,0 +1,27 @@
1
+ require File.join(File.dirname(__FILE__),'spec_helper')
2
+
3
+ describe "Document" do
4
+ it_should_behave_like "SpecBootstrapHelper"
5
+ it_should_behave_like "SourceAdapterHelper"
6
+
7
+ it "should generate client docname" do
8
+ @c.docname(:foo).should == "client:#{@a.id}:#{@u.id}:#{@c.id}:#{@s_fields[:name]}:foo"
9
+ end
10
+
11
+ it "should generate source docname" do
12
+ @s.docname(:foo).should == "source:#{@a.id}:#{@u.id}:#{@s_fields[:name]}:foo"
13
+ end
14
+
15
+ it "should flash_data for docname" do
16
+ @c.put_data(:foo1,{'1'=>@product1})
17
+ Store.db.keys(@c.docname('*')).should == [@c.docname(:foo1)]
18
+ @c.flash_data('*')
19
+ Store.db.keys(@c.docname(:foo)).should == []
20
+ end
21
+
22
+ it "should rename doc" do
23
+ set_state(@c.docname(:key1) => @data)
24
+ @c.rename(:key1,:key2)
25
+ verify_result(@c.docname(:key1) => {}, @c.docname(:key2) => @data)
26
+ end
27
+ end
@@ -0,0 +1,53 @@
1
+ require File.join(File.dirname(__FILE__),'generator_spec_helper')
2
+
3
+ describe "Generator" do
4
+ appname = 'mynewapp'
5
+ source = 'mysource'
6
+ path = File.expand_path(File.join(File.dirname(__FILE__)))
7
+
8
+ after(:each) do
9
+ #FileUtils.rm_rf path
10
+ end
11
+
12
+ describe "AppGenerator" do
13
+ it "should complain if no name is specified" do
14
+ lambda {
15
+ Rhosync::AppGenerator.new('/tmp',{})
16
+ }.should raise_error(Templater::TooFewArgumentsError)
17
+ end
18
+
19
+ before(:each) do
20
+ @generator = Rhosync::AppGenerator.new('/tmp',{},appname)
21
+ end
22
+
23
+ it "should create new application files" do
24
+ [
25
+ 'config.ru',
26
+ "application.rb",
27
+ 'settings/settings.yml',
28
+ 'settings/license.key',
29
+ 'Rakefile'
30
+ ].each do |template|
31
+ @generator.should create("/tmp/#{appname}/#{template}")
32
+ end
33
+ end
34
+ end
35
+
36
+ describe "SourceGenerator" do
37
+ it "should complain if no name is specified" do
38
+ lambda {
39
+ Rhosync::SourceGenerator.new('/tmp',{})
40
+ }.should raise_error(Templater::TooFewArgumentsError)
41
+ end
42
+
43
+ before(:each) do
44
+ @generator = Rhosync::SourceGenerator.new('/tmp',{},source)
45
+ end
46
+
47
+ it "should create new source adapter" do
48
+ pending
49
+ @generator.should create("/tmp/sources/#{source}.rb")
50
+ end
51
+ end
52
+
53
+ end
@@ -0,0 +1,8 @@
1
+ require 'rubygems'
2
+ require 'templater/spec/helpers'
3
+ require 'rhosync'
4
+ require File.join(File.dirname(__FILE__),'..','..','generators','rhosync')
5
+
6
+ Spec::Runner.configure do |config|
7
+ config.include Templater::Spec::Helpers
8
+ end
@@ -0,0 +1,76 @@
1
+ require File.join(File.dirname(__FILE__),'..','spec_helper')
2
+ require 'sqlite3'
3
+
4
+ describe "BulkDataJob" do
5
+ it_should_behave_like "SpecBootstrapHelper"
6
+ it_should_behave_like "SourceAdapterHelper"
7
+
8
+ before(:each) do
9
+ Rhosync.blackberry_bulk_sync = true
10
+ end
11
+
12
+ after(:each) do
13
+ delete_data_directory
14
+ end
15
+
16
+ it "should create sqlite data file from master document" do
17
+ set_state('test_db_storage' => @data)
18
+ docname = bulk_data_docname(@a.id,@u.id)
19
+ data = BulkData.create(:name => docname,
20
+ :state => :inprogress,
21
+ :app_id => @a.id,
22
+ :user_id => @u.id,
23
+ :sources => [@s_fields[:name]])
24
+ BulkDataJob.perform("data_name" => data.name)
25
+ data = BulkData.load(docname)
26
+ data.completed?.should == true
27
+ verify_result(@s.docname(:md) => @data,@s.docname(:md_copy) => @data)
28
+ validate_db(data,@data).should == true
29
+ File.exists?(data.dbfile+'.hsqldb.data').should == true
30
+ File.exists?(data.dbfile+'.hsqldb.script').should == true
31
+ File.exists?(data.dbfile+'.hsqldb.properties').should == true
32
+ end
33
+
34
+ it "should not create hsql db files if blackberry_bulk_sync is disabled" do
35
+ Rhosync.blackberry_bulk_sync = false
36
+ set_state('test_db_storage' => @data)
37
+ docname = bulk_data_docname(@a.id,@u.id)
38
+ data = BulkData.create(:name => docname,
39
+ :state => :inprogress,
40
+ :app_id => @a.id,
41
+ :user_id => @u.id,
42
+ :sources => [@s_fields[:name]])
43
+ BulkDataJob.perform("data_name" => data.name)
44
+ data = BulkData.load(docname)
45
+ data.completed?.should == true
46
+ verify_result(@s.docname(:md) => @data,@s.docname(:md_copy) => @data)
47
+ validate_db(data,@data).should == true
48
+ File.exists?(data.dbfile+'.hsqldb.script').should == false
49
+ File.exists?(data.dbfile+'.hsqldb.properties').should == false
50
+ end
51
+
52
+ it "should raise exception if hsqldata fails" do
53
+ data = BulkData.create(:name => bulk_data_docname(@a.id,@u.id),
54
+ :state => :inprogress,
55
+ :app_id => @a.id,
56
+ :user_id => @u.id,
57
+ :sources => [@s_fields[:name]])
58
+ lambda { BulkDataJob.create_hsql_data_file(data,Time.now.to_i.to_s)
59
+ }.should raise_error(Exception,"Error running hsqldata")
60
+ end
61
+
62
+ it "should delete bulk data if exception is raised" do
63
+ lambda { BulkDataJob.perform("data_name" => 'broken') }.should raise_error(Exception)
64
+ Store.db.keys('bulk_data*').should == []
65
+ end
66
+
67
+ it "should delete bulk data if exception is raised" do
68
+ data = BulkData.create(:name => bulk_data_docname('broken',@u.id),
69
+ :state => :inprogress,
70
+ :app_id => 'broken',
71
+ :user_id => @u.id,
72
+ :sources => [@s_fields[:name]])
73
+ lambda { BulkDataJob.perform("data_name" => data.name) }.should raise_error(Exception)
74
+ Store.db.keys('bulk_data*').should == []
75
+ end
76
+ end
@@ -0,0 +1,26 @@
1
+ require File.join(File.dirname(__FILE__),'..','spec_helper')
2
+
3
+ describe "PingJob" do
4
+ it_should_behave_like "SpecBootstrapHelper"
5
+ it_should_behave_like "SourceAdapterHelper"
6
+
7
+ it "should perform iphone ping" do
8
+ params = {"user_id" => @u.id, "api_token" => @api_token,
9
+ "sources" => [@s.name], "message" => 'hello world',
10
+ "vibrate" => '5', "badge" => '5', "sound" => 'hello.mp3'}
11
+ Iphone.should_receive(:ping).once.with({'device_pin' => @c.device_pin,
12
+ 'device_port' => @c.device_port}.merge!(params))
13
+ PingJob.perform(params)
14
+ end
15
+
16
+ it "should perform blackberry ping" do
17
+ params = {"user_id" => @u.id, "api_token" => @api_token,
18
+ "sources" => [@s.name], "message" => 'hello world',
19
+ "vibrate" => '5', "badge" => '5', "sound" => 'hello.mp3'}
20
+ @c.device_type = 'blackberry'
21
+ Blackberry.should_receive(:ping).once.with({'device_pin' => @c.device_pin,
22
+ 'device_port' => @c.device_port}.merge!(params))
23
+ PingJob.perform(params)
24
+ end
25
+
26
+ end
@@ -0,0 +1,25 @@
1
+ require File.join(File.dirname(__FILE__),'..','spec_helper')
2
+
3
+ describe "SourceJob" do
4
+ it_should_behave_like "SpecBootstrapHelper"
5
+ it_should_behave_like "SourceAdapterHelper"
6
+
7
+ it "should perform process_query" do
8
+ set_state('test_db_storage' => @data)
9
+ SourceJob.perform('query',@s.id,@s.app_id,@s.user_id,nil,nil)
10
+ verify_result(@s.docname(:md) => @data,
11
+ @s.docname(:md_size) => @data.size.to_s)
12
+ end
13
+
14
+ it "should perform process_cud" do
15
+ expected = {'backend_id'=>@product1}
16
+ @product1['link'] = 'abc'
17
+ set_state(@c.docname(:create) => {'1'=>@product1})
18
+ SourceJob.perform('cud',@s.id,@s.app_id,@s.user_id,@c.id,nil)
19
+ verify_result(@s.docname(:md) => expected,
20
+ @s.docname(:md_size) => expected.size.to_s,
21
+ @c.docname(:cd) => expected,
22
+ @c.docname(:cd_size) => expected.size.to_s,
23
+ @c.docname(:create) => {})
24
+ end
25
+ end
@@ -0,0 +1,48 @@
1
+ require File.join(File.dirname(__FILE__),'spec_helper')
2
+
3
+ describe "License" do
4
+ it_should_behave_like "SpecBootstrapHelper"
5
+ it_should_behave_like "SourceAdapterHelper"
6
+
7
+ before(:each) do
8
+ Store.put_value(License::CLIENT_DOCKEY,nil)
9
+ end
10
+
11
+ it "should decrypt license" do
12
+ license = License.new
13
+ license.rhosync_version.should == 'Version 1'
14
+ license.licensee.should == 'Rhomobile'
15
+ license.seats.should == 10
16
+ license.issued.should == 'Fri Apr 23 17:20:13 -0700 2010'
17
+ end
18
+
19
+ it "should raise exception on license load error" do
20
+ Rhosync.stub!(:get_config).and_return({Rhosync.environment.to_sym => {}})
21
+ lambda { License.new }.should raise_error(LicenseException, "Error verifying license.")
22
+ end
23
+
24
+ it "should verify # of seats before adding" do
25
+ License.new.check_and_use_seat
26
+ Store.get_value(License::CLIENT_DOCKEY).to_i.should == 1
27
+ end
28
+
29
+ it "should raise exception when seats are exceeded" do
30
+ Store.put_value(License::CLIENT_DOCKEY,10)
31
+ lambda { License.new.check_and_use_seat }.should raise_error(
32
+ LicenseSeatsExceededException, "WARNING: Maximum # of clients exceeded for this license."
33
+ )
34
+ end
35
+
36
+ it "should free license seat" do
37
+ Store.put_value(License::CLIENT_DOCKEY,5)
38
+ License.new.free_seat
39
+ Store.get_value(License::CLIENT_DOCKEY).to_i.should == 4
40
+ end
41
+
42
+ it "should get # of available seats" do
43
+ license = License.new
44
+ license.check_and_use_seat
45
+ license.available.should == 9
46
+ end
47
+
48
+ end