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.
- data/CHANGELOG +5 -0
- data/LICENSE +674 -0
- data/README.md +26 -0
- data/Rakefile +109 -0
- data/bench/bench +6 -0
- data/bench/benchapp/Rakefile +14 -0
- data/bench/benchapp/application.rb +13 -0
- data/bench/benchapp/config.ru +32 -0
- data/bench/benchapp/settings/license.key +1 -0
- data/bench/benchapp/settings/settings.yml +18 -0
- data/bench/benchapp/sources/mock_adapter.rb +55 -0
- data/bench/benchapp/sources/queue_mock_adapter.rb +2 -0
- data/bench/benchapp/vendor/rhosync/lib/rhosync.rb +7 -0
- data/bench/lib/bench/cli.rb +16 -0
- data/bench/lib/bench/logging.rb +18 -0
- data/bench/lib/bench/mock_client.rb +41 -0
- data/bench/lib/bench/result.rb +50 -0
- data/bench/lib/bench/runner.rb +44 -0
- data/bench/lib/bench/session.rb +65 -0
- data/bench/lib/bench/statistics.rb +56 -0
- data/bench/lib/bench/test_data.rb +55 -0
- data/bench/lib/bench/timer.rb +10 -0
- data/bench/lib/bench/utils.rb +49 -0
- data/bench/lib/bench.rb +128 -0
- data/bench/lib/testdata/100-data.txt +148 -0
- data/bench/lib/testdata/5-data.txt +11 -0
- data/bench/scripts/cud_script.rb +77 -0
- data/bench/scripts/helpers.rb +101 -0
- data/bench/scripts/query_md_script.rb +46 -0
- data/bench/scripts/query_script.rb +46 -0
- data/bench/spec/bench_spec_helper.rb +65 -0
- data/bench/spec/logging_spec.rb +19 -0
- data/bench/spec/mock_adapter_spec.rb +61 -0
- data/bench/spec/mock_client_spec.rb +64 -0
- data/bench/spec/result_spec.rb +59 -0
- data/bench/spec/utils_spec.rb +35 -0
- data/bin/rhosync +34 -0
- data/doc/protocol.html +1901 -0
- data/doc/public/css/print.css +29 -0
- data/doc/public/css/screen.css +257 -0
- data/doc/public/css/style.css +20 -0
- data/examples/simple/application.rb +13 -0
- data/examples/simple/sources/sample_adapter.rb +5 -0
- data/examples/simple/sources/simple_adapter.rb +5 -0
- data/examples/simple/vendor/rhosync/lib/rhosync.rb +7 -0
- data/generators/rhosync.rb +98 -0
- data/generators/templates/application/Rakefile +19 -0
- data/generators/templates/application/application.rb +27 -0
- data/generators/templates/application/config.ru +33 -0
- data/generators/templates/application/settings/license.key +1 -0
- data/generators/templates/application/settings/settings.yml +14 -0
- data/generators/templates/source/source_adapter.rb +49 -0
- data/lib/rhosync/api/create_client.rb +3 -0
- data/lib/rhosync/api/create_user.rb +7 -0
- data/lib/rhosync/api/delete_client.rb +5 -0
- data/lib/rhosync/api/delete_user.rb +5 -0
- data/lib/rhosync/api/get_api_token.rb +7 -0
- data/lib/rhosync/api/get_client_params.rb +3 -0
- data/lib/rhosync/api/get_db_doc.rb +7 -0
- data/lib/rhosync/api/get_license_info.rb +7 -0
- data/lib/rhosync/api/get_source_params.rb +3 -0
- data/lib/rhosync/api/list_client_docs.rb +12 -0
- data/lib/rhosync/api/list_clients.rb +3 -0
- data/lib/rhosync/api/list_source_docs.rb +10 -0
- data/lib/rhosync/api/list_sources.rb +15 -0
- data/lib/rhosync/api/list_users.rb +3 -0
- data/lib/rhosync/api/ping.rb +7 -0
- data/lib/rhosync/api/push_deletes.rb +6 -0
- data/lib/rhosync/api/push_objects.rb +6 -0
- data/lib/rhosync/api/reset.rb +10 -0
- data/lib/rhosync/api/set_db_doc.rb +8 -0
- data/lib/rhosync/api/set_refresh_time.rb +8 -0
- data/lib/rhosync/api/update_user.rb +4 -0
- data/lib/rhosync/api/upload_file.rb +4 -0
- data/lib/rhosync/api_token.rb +19 -0
- data/lib/rhosync/app.rb +69 -0
- data/lib/rhosync/bulk_data/bulk_data.rb +75 -0
- data/lib/rhosync/bulk_data/syncdb.index.schema +3 -0
- data/lib/rhosync/bulk_data/syncdb.schema +37 -0
- data/lib/rhosync/bulk_data.rb +2 -0
- data/lib/rhosync/client.rb +74 -0
- data/lib/rhosync/client_sync.rb +296 -0
- data/lib/rhosync/console/app/helpers/auth_helper.rb +18 -0
- data/lib/rhosync/console/app/helpers/extensions.rb +19 -0
- data/lib/rhosync/console/app/helpers/helpers.rb +52 -0
- data/lib/rhosync/console/app/public/main.css +7 -0
- data/lib/rhosync/console/app/public/text.txt +0 -0
- data/lib/rhosync/console/app/routes/auth.rb +29 -0
- data/lib/rhosync/console/app/routes/client.rb +32 -0
- data/lib/rhosync/console/app/routes/docs.rb +84 -0
- data/lib/rhosync/console/app/routes/home.rb +22 -0
- data/lib/rhosync/console/app/routes/user.rb +63 -0
- data/lib/rhosync/console/app/views/client.erb +30 -0
- data/lib/rhosync/console/app/views/doc.erb +56 -0
- data/lib/rhosync/console/app/views/docs.erb +29 -0
- data/lib/rhosync/console/app/views/index.erb +50 -0
- data/lib/rhosync/console/app/views/layout.erb +12 -0
- data/lib/rhosync/console/app/views/newuser.erb +17 -0
- data/lib/rhosync/console/app/views/ping.erb +28 -0
- data/lib/rhosync/console/app/views/result.erb +11 -0
- data/lib/rhosync/console/app/views/user.erb +32 -0
- data/lib/rhosync/console/app/views/users.erb +14 -0
- data/lib/rhosync/console/rhosync_api.rb +102 -0
- data/lib/rhosync/console/server.rb +27 -0
- data/lib/rhosync/credential.rb +9 -0
- data/lib/rhosync/document.rb +43 -0
- data/lib/rhosync/indifferent_access.rb +132 -0
- data/lib/rhosync/jobs/bulk_data_job.rb +104 -0
- data/lib/rhosync/jobs/ping_job.rb +19 -0
- data/lib/rhosync/jobs/source_job.rb +16 -0
- data/lib/rhosync/license.rb +79 -0
- data/lib/rhosync/lock_ops.rb +11 -0
- data/lib/rhosync/model.rb +410 -0
- data/lib/rhosync/ping/blackberry.rb +55 -0
- data/lib/rhosync/ping/iphone.rb +44 -0
- data/lib/rhosync/ping.rb +2 -0
- data/lib/rhosync/read_state.rb +27 -0
- data/lib/rhosync/server/views/index.erb +12 -0
- data/lib/rhosync/server.rb +242 -0
- data/lib/rhosync/source.rb +112 -0
- data/lib/rhosync/source_adapter.rb +95 -0
- data/lib/rhosync/source_sync.rb +245 -0
- data/lib/rhosync/store.rb +199 -0
- data/lib/rhosync/tasks.rb +151 -0
- data/lib/rhosync/user.rb +83 -0
- data/lib/rhosync/version.rb +3 -0
- data/lib/rhosync.rb +251 -0
- data/spec/api/api_helper.rb +44 -0
- data/spec/api/create_client_spec.rb +13 -0
- data/spec/api/create_user_spec.rb +16 -0
- data/spec/api/delete_client_spec.rb +13 -0
- data/spec/api/delete_user_spec.rb +18 -0
- data/spec/api/get_api_token_spec.rb +25 -0
- data/spec/api/get_client_params_spec.rb +18 -0
- data/spec/api/get_db_doc_spec.rb +21 -0
- data/spec/api/get_license_info_spec.rb +16 -0
- data/spec/api/get_source_params_spec.rb +26 -0
- data/spec/api/list_client_docs_spec.rb +33 -0
- data/spec/api/list_clients_spec.rb +23 -0
- data/spec/api/list_source_docs_spec.rb +26 -0
- data/spec/api/list_sources_spec.rb +27 -0
- data/spec/api/list_users_spec.rb +21 -0
- data/spec/api/ping_spec.rb +24 -0
- data/spec/api/push_deletes_spec.rb +16 -0
- data/spec/api/push_objects_spec.rb +27 -0
- data/spec/api/reset_spec.rb +22 -0
- data/spec/api/set_db_doc_spec.rb +20 -0
- data/spec/api/set_refresh_time_spec.rb +43 -0
- data/spec/api/update_user_spec.rb +31 -0
- data/spec/api/upload_file_spec.rb +26 -0
- data/spec/api_token_spec.rb +13 -0
- data/spec/app_spec.rb +20 -0
- data/spec/apps/rhotestapp/Rakefile +1 -0
- data/spec/apps/rhotestapp/application.rb +16 -0
- data/spec/apps/rhotestapp/config.ru +1 -0
- data/spec/apps/rhotestapp/settings/apple_fake_cert.pem +1 -0
- data/spec/apps/rhotestapp/settings/license.key +1 -0
- data/spec/apps/rhotestapp/settings/settings.yml +23 -0
- data/spec/apps/rhotestapp/sources/base_adapter.rb +9 -0
- data/spec/apps/rhotestapp/sources/sample_adapter.rb +66 -0
- data/spec/apps/rhotestapp/sources/simple_adapter.rb +39 -0
- data/spec/apps/rhotestapp/sources/sub_adapter.rb +7 -0
- data/spec/apps/rhotestapp/vendor/mygem-0.1.0/lib/mygem/mygem.rb +8 -0
- data/spec/apps/rhotestapp/vendor/mygem-0.1.0/lib/mygem.rb +1 -0
- data/spec/bulk_data/bulk_data_spec.rb +79 -0
- data/spec/client_spec.rb +58 -0
- data/spec/client_sync_spec.rb +377 -0
- data/spec/doc/base.html +72 -0
- data/spec/doc/doc_spec.rb +303 -0
- data/spec/doc/footer.html +4 -0
- data/spec/doc/header.html +30 -0
- data/spec/document_spec.rb +27 -0
- data/spec/generator/generator_spec.rb +53 -0
- data/spec/generator/generator_spec_helper.rb +8 -0
- data/spec/jobs/bulk_data_job_spec.rb +76 -0
- data/spec/jobs/ping_job_spec.rb +26 -0
- data/spec/jobs/source_job_spec.rb +25 -0
- data/spec/license_spec.rb +48 -0
- data/spec/model_spec.rb +269 -0
- data/spec/perf/bulk_data_perf_spec.rb +33 -0
- data/spec/perf/perf_spec_helper.rb +51 -0
- data/spec/perf/store_perf_spec.rb +28 -0
- data/spec/ping/blackberry_spec.rb +62 -0
- data/spec/ping/iphone_spec.rb +50 -0
- data/spec/read_state_spec.rb +25 -0
- data/spec/rhosync_spec.rb +43 -0
- data/spec/server/server_spec.rb +341 -0
- data/spec/source_adapter_spec.rb +114 -0
- data/spec/source_spec.rb +77 -0
- data/spec/source_sync_spec.rb +248 -0
- data/spec/spec_helper.rb +240 -0
- data/spec/store_spec.rb +149 -0
- data/spec/sync_states_spec.rb +101 -0
- data/spec/testdata/1000-data.txt +1414 -0
- data/spec/testdata/compressed/compress-data.txt +1 -0
- data/spec/testdata/upload1.txt +1 -0
- data/spec/testdata/upload2.txt +1 -0
- data/spec/user_spec.rb +79 -0
- data/tasks/redis.rake +134 -0
- metadata +545 -0
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
:sources:
|
|
2
|
+
SampleAdapter:
|
|
3
|
+
poll_interval: 300
|
|
4
|
+
SimpleAdapter:
|
|
5
|
+
poll_interval: 600
|
|
6
|
+
partition_type: app
|
|
7
|
+
|
|
8
|
+
:development:
|
|
9
|
+
:licensefile: settings/license.key
|
|
10
|
+
:iphonecertfile: settings/apple_fake_cert.pem
|
|
11
|
+
:iphonepassphrase: certpassword
|
|
12
|
+
:iphoneserver: gateway.sandbox.push.apple.com
|
|
13
|
+
:iphoneport: 2195
|
|
14
|
+
:redis: localhost:6379
|
|
15
|
+
:syncserver: http://localhost:9292/application/
|
|
16
|
+
:test:
|
|
17
|
+
:licensefile: settings/license.key
|
|
18
|
+
:redis: localhost:6379
|
|
19
|
+
:syncserver: http://localhost:9292/application/
|
|
20
|
+
:production:
|
|
21
|
+
:licensefile: settings/license.key
|
|
22
|
+
:redis: localhost:6379
|
|
23
|
+
:syncserver: http://localhost:9292/application/
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
class SampleAdapter < SourceAdapter
|
|
2
|
+
def initialize(source,credential)
|
|
3
|
+
super(source,credential)
|
|
4
|
+
end
|
|
5
|
+
|
|
6
|
+
def login
|
|
7
|
+
raise SourceAdapterLoginException.new('Error logging in') if _is_empty?(current_user.login)
|
|
8
|
+
true
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def query(params=nil)
|
|
12
|
+
_read('query',params)
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def search(params=nil)
|
|
16
|
+
_read('search',params)
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def sync
|
|
20
|
+
super
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def create(name_value_list,blob=nil)
|
|
24
|
+
Store.put_data('test_create_storage',{name_value_list['_id']=>name_value_list},true)
|
|
25
|
+
raise SourceAdapterException.new("ID provided in name_value_list") if name_value_list['id']
|
|
26
|
+
_raise_exception(name_value_list)
|
|
27
|
+
'backend_id' if name_value_list and name_value_list['link']
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def update(name_value_list)
|
|
31
|
+
raise SourceAdapterException.new("No id provided in name_value_list") unless name_value_list['id']
|
|
32
|
+
Store.put_data('test_update_storage',{name_value_list['id']=>name_value_list},true)
|
|
33
|
+
_raise_exception(name_value_list)
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def delete(name_value_list)
|
|
37
|
+
raise SourceAdapterException.new("No id provided in name_value_list") unless name_value_list['id']
|
|
38
|
+
raise SourceAdapterServerErrorException.new("Error delete record") if name_value_list['id'] == ERROR
|
|
39
|
+
Store.put_data('test_delete_storage',{name_value_list['id']=>name_value_list},true)
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def logoff
|
|
43
|
+
@result = Store.get_data('test_db_storage')
|
|
44
|
+
raise SourceAdapterLogoffException.new(@result[ERROR]['an_attribute']) if @result[ERROR] and
|
|
45
|
+
@result[ERROR]['name'] == 'logoff error'
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
private
|
|
49
|
+
def _is_empty?(str)
|
|
50
|
+
str.length <= 0
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def _raise_exception(name_value_list)
|
|
54
|
+
if name_value_list and name_value_list['name'] == 'wrongname' or name_value_list['id'] == 'error'
|
|
55
|
+
raise SourceAdapterServerErrorException.new(name_value_list['an_attribute'])
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def _read(operation,params)
|
|
60
|
+
@result = Store.get_data('test_db_storage')
|
|
61
|
+
raise SourceAdapterServerErrorException.new(@result[ERROR]['an_attribute']) if @result[ERROR] and
|
|
62
|
+
@result[ERROR]['name'] == "#{operation} error"
|
|
63
|
+
@result.reject! {|key,value| value['name'] != params['name']} if params
|
|
64
|
+
@result
|
|
65
|
+
end
|
|
66
|
+
end
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
class SimpleAdapter < SourceAdapter
|
|
2
|
+
def initialize(source,credential)
|
|
3
|
+
super(source,credential)
|
|
4
|
+
end
|
|
5
|
+
|
|
6
|
+
def login
|
|
7
|
+
unless _is_empty?(current_user.login)
|
|
8
|
+
true
|
|
9
|
+
else
|
|
10
|
+
raise SourceAdapterLoginException.new('Error logging in')
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def query(params=nil)
|
|
15
|
+
@result
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def search(params=nil,txt='')
|
|
19
|
+
params[:foo] = 'bar'
|
|
20
|
+
if params['search'] == 'bar'
|
|
21
|
+
@result = {'obj'=>{'foo'=>'bar'}}
|
|
22
|
+
params['name'] = 'iPhone'
|
|
23
|
+
end
|
|
24
|
+
@result
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def sync
|
|
28
|
+
super
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def create(name_value_list,blob=nil)
|
|
32
|
+
'obj4'
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
private
|
|
36
|
+
def _is_empty?(str)
|
|
37
|
+
str.length <= 0
|
|
38
|
+
end
|
|
39
|
+
end
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
require 'mygem/mygem'
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
require File.join(File.dirname(__FILE__),'..','spec_helper')
|
|
2
|
+
|
|
3
|
+
describe "BulkData" do
|
|
4
|
+
it_should_behave_like "SpecBootstrapHelper"
|
|
5
|
+
it_should_behave_like "SourceAdapterHelper"
|
|
6
|
+
|
|
7
|
+
after(:each) do
|
|
8
|
+
delete_data_directory
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
it "should return true if bulk data is completed" do
|
|
12
|
+
dbfile = create_datafile(File.join(@a.name,@u.id.to_s),@u.id.to_s)
|
|
13
|
+
data = BulkData.create(:name => bulk_data_docname(@a.id,@u.id),
|
|
14
|
+
:state => :completed,
|
|
15
|
+
:app_id => @a.id,
|
|
16
|
+
:user_id => @u.id,
|
|
17
|
+
:sources => [@s_fields[:name]])
|
|
18
|
+
data.dbfile = dbfile
|
|
19
|
+
data.completed?.should == true
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
it "should return false if bulk data isn't completed" do
|
|
23
|
+
data = BulkData.create(:name => bulk_data_docname(@a.id,@u.id),
|
|
24
|
+
:state => :inprogress,
|
|
25
|
+
:app_id => @a.id,
|
|
26
|
+
:user_id => @u.id,
|
|
27
|
+
:sources => [@s_fields[:name]])
|
|
28
|
+
data.completed?.should == false
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
it "should enqueue sqlite db type" do
|
|
32
|
+
BulkData.enqueue
|
|
33
|
+
Resque.peek(:bulk_data).should == {"args"=>[{}],
|
|
34
|
+
"class"=>"Rhosync::BulkDataJob"}
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
it "should generate correct bulk data name for user partition" do
|
|
38
|
+
BulkData.get_name(:user,@c).should == File.join(@a_fields[:name],@u_fields[:login],@u_fields[:login])
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
it "should generate correct bulk data name for app partition" do
|
|
42
|
+
BulkData.get_name(:app,@c).should ==
|
|
43
|
+
File.join(@a_fields[:name],@a_fields[:name])
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
it "should process_sources for bulk data" do
|
|
47
|
+
current = Time.now.to_i
|
|
48
|
+
@s.read_state.refresh_time = current
|
|
49
|
+
data = BulkData.create(:name => bulk_data_docname(@a.id,@u.id),
|
|
50
|
+
:state => :inprogress,
|
|
51
|
+
:app_id => @a.id,
|
|
52
|
+
:user_id => @u.id,
|
|
53
|
+
:sources => [@s_fields[:name]])
|
|
54
|
+
data.process_sources
|
|
55
|
+
@s.read_state.refresh_time.should >= current + @s_fields[:poll_interval].to_i
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
it "should delete source masterdoc copy on delete" do
|
|
59
|
+
set_state('test_db_storage' => @data)
|
|
60
|
+
data = BulkData.create(:name => bulk_data_docname(@a.id,@u.id),
|
|
61
|
+
:state => :inprogress,
|
|
62
|
+
:app_id => @a.id,
|
|
63
|
+
:user_id => @u.id,
|
|
64
|
+
:sources => [@s_fields[:name]])
|
|
65
|
+
data.process_sources
|
|
66
|
+
verify_result(@s.docname(:md_copy) => @data)
|
|
67
|
+
data.delete
|
|
68
|
+
verify_result(@s.docname(:md_copy) => {},
|
|
69
|
+
@s.docname(:md) => @data)
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
def create_datafile(dir,name)
|
|
74
|
+
dir = File.join(Rhosync.data_directory,dir)
|
|
75
|
+
FileUtils.mkdir_p(dir)
|
|
76
|
+
fname = File.join(dir,name+'.data')
|
|
77
|
+
File.open(fname,'wb') {|f| f.puts ''}
|
|
78
|
+
fname
|
|
79
|
+
end
|
data/spec/client_spec.rb
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
require File.join(File.dirname(__FILE__),'spec_helper')
|
|
2
|
+
|
|
3
|
+
describe "Client" do
|
|
4
|
+
it_should_behave_like "SpecBootstrapHelper"
|
|
5
|
+
it_should_behave_like "SourceAdapterHelper"
|
|
6
|
+
|
|
7
|
+
it "should create client with fields" do
|
|
8
|
+
@c.id.length.should == 32
|
|
9
|
+
@c.device_type.should == @c_fields[:device_type]
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
it "should update_fields for a client" do
|
|
13
|
+
@c.update_fields({:device_type => 'android',:device_port => 100})
|
|
14
|
+
@c.device_type.should == 'android'
|
|
15
|
+
@c.device_port.should == '100'
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
it "should create client with user_id" do
|
|
19
|
+
@c.id.length.should == 32
|
|
20
|
+
@c.user_id.should == @c_fields[:user_id]
|
|
21
|
+
@u.clients.members.should == [@c.id]
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
it "should raise exception if source_name is nil" do
|
|
25
|
+
@c.source_name = nil
|
|
26
|
+
lambda {
|
|
27
|
+
@c.doc_suffix('foo')
|
|
28
|
+
}.should raise_error(InvalidSourceNameError, 'Invalid Source Name For Client')
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
it "should raise exception if license seats exceeded" do
|
|
32
|
+
Store.put_value(License::CLIENT_DOCKEY,100)
|
|
33
|
+
lambda { Client.create(@c_fields,{}) }.should raise_error(
|
|
34
|
+
LicenseSeatsExceededException, "WARNING: Maximum # of clients exceeded for this license."
|
|
35
|
+
)
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
it "should free seat when client is deleted" do
|
|
39
|
+
current = Store.get_value(License::CLIENT_DOCKEY).to_i
|
|
40
|
+
@c.delete
|
|
41
|
+
Store.get_value(License::CLIENT_DOCKEY).to_i.should == current - 1
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
it "should delete client and all associated documents" do
|
|
45
|
+
docname = @c.docname(:cd)
|
|
46
|
+
set_state(docname => @data)
|
|
47
|
+
@c.delete
|
|
48
|
+
verify_result(docname => {})
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
it "should create cd as masterdoc clone" do
|
|
52
|
+
set_state(@s.docname(:md_copy) => @data,
|
|
53
|
+
@c.docname(:cd) => {'foo' => {'bar' => 'abc'}})
|
|
54
|
+
@c.update_clientdoc([@s_fields[:name]])
|
|
55
|
+
verify_result(@c.docname(:cd) => @data,
|
|
56
|
+
@s.docname(:md_copy) => @data)
|
|
57
|
+
end
|
|
58
|
+
end
|
|
@@ -0,0 +1,377 @@
|
|
|
1
|
+
require File.join(File.dirname(__FILE__),'spec_helper')
|
|
2
|
+
|
|
3
|
+
describe "ClientSync" do
|
|
4
|
+
it_should_behave_like "SpecBootstrapHelper"
|
|
5
|
+
it_should_behave_like "SourceAdapterHelper"
|
|
6
|
+
|
|
7
|
+
it "should raise Argument error if no client or source is provided" do
|
|
8
|
+
lambda { ClientSync.new(@s,nil,2) }.should raise_error(ArgumentError,'Missing required attribute client')
|
|
9
|
+
lambda { ClientSync.new(nil,@c,2) }.should raise_error(ArgumentError,'Missing required attribute source')
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
before(:each) do
|
|
13
|
+
@cs = ClientSync.new(@s,@c,2)
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
describe "cud methods" do
|
|
17
|
+
it "should handle receive cud" do
|
|
18
|
+
params = {'create'=>{'1'=>@product1},'update'=>{'2'=>@product2},'delete'=>{'3'=>@product3}}
|
|
19
|
+
@cs.receive_cud(params)
|
|
20
|
+
verify_result(@cs.client.docname(:create) => {},
|
|
21
|
+
@cs.client.docname(:update) => {},
|
|
22
|
+
@cs.client.docname(:delete) => {})
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
it "should handle send cud" do
|
|
26
|
+
data = {'1'=>@product1,'2'=>@product2}
|
|
27
|
+
expected = {'insert'=>data}
|
|
28
|
+
set_test_data('test_db_storage',data)
|
|
29
|
+
@cs.send_cud.should == [{'version'=>ClientSync::VERSION},
|
|
30
|
+
{'token'=>@c.get_value(:page_token)},
|
|
31
|
+
{'count'=>data.size},{'progress_count'=>0},
|
|
32
|
+
{'total_count'=>data.size},expected]
|
|
33
|
+
verify_result(@cs.client.docname(:page) => data,
|
|
34
|
+
@cs.client.docname(:delete_page) => {},
|
|
35
|
+
@cs.client.docname(:cd) => data)
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
it "should return read errors in send cud" do
|
|
39
|
+
msg = "Error during query"
|
|
40
|
+
data = {'1'=>@product1,'2'=>@product2}
|
|
41
|
+
set_test_data('test_db_storage',data,msg,'query error')
|
|
42
|
+
@cs.send_cud.should == [{"version"=>ClientSync::VERSION},
|
|
43
|
+
{"token"=>""}, {"count"=>0}, {"progress_count"=>0},{"total_count"=>0},
|
|
44
|
+
{"source-error"=>{"query-error"=>{"message"=>msg}}}]
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
it "should return login errors in send cud" do
|
|
48
|
+
@u.login = nil
|
|
49
|
+
@cs.send_cud.should == [{"version"=>ClientSync::VERSION},{"token"=>""},
|
|
50
|
+
{"count"=>0}, {"progress_count"=>0}, {"total_count"=>0},
|
|
51
|
+
{'source-error'=>{"login-error"=>{"message"=>"Error logging in"}}}]
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
it "should return logoff errors in send cud" do
|
|
55
|
+
msg = "Error logging off"
|
|
56
|
+
set_test_data('test_db_storage',{},msg,'logoff error')
|
|
57
|
+
@cs.send_cud.should == [{"version"=>ClientSync::VERSION},
|
|
58
|
+
{"token"=>@c.get_value(:page_token)},
|
|
59
|
+
{"count"=>1}, {"progress_count"=>0}, {"total_count"=>1},
|
|
60
|
+
{"source-error"=>{"logoff-error"=>{"message"=>msg}},
|
|
61
|
+
"insert"=>{ERROR=>{"name"=>"logoff error", "an_attribute"=>msg}}}]
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
describe "send errors in send_cud" do
|
|
65
|
+
it "should handle create errors" do
|
|
66
|
+
receive_and_send_cud('create')
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
it "should handle update errors" do
|
|
70
|
+
receive_and_send_cud('update')
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
it "should handle delete errors" do
|
|
74
|
+
msg = "Error delete record"
|
|
75
|
+
error_objs = add_error_object({},"Error delete record")
|
|
76
|
+
op_data = {'delete'=>error_objs}
|
|
77
|
+
@cs.receive_cud(op_data)
|
|
78
|
+
@cs.send_cud.should == [{"version"=>ClientSync::VERSION},
|
|
79
|
+
{"token"=>""}, {"count"=>0}, {"progress_count"=>0}, {"total_count"=>0},
|
|
80
|
+
{"delete-error"=>{"#{ERROR}-error"=>{"message"=>msg},ERROR=>error_objs[ERROR]}}]
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
it "should send cud errors only once" do
|
|
84
|
+
msg = "Error delete record"
|
|
85
|
+
error_objs = add_error_object({},"Error delete record")
|
|
86
|
+
op_data = {'delete'=>error_objs}
|
|
87
|
+
@cs.receive_cud(op_data)
|
|
88
|
+
@cs.send_cud.should == [{"version"=>ClientSync::VERSION},
|
|
89
|
+
{"token"=>""}, {"count"=>0}, {"progress_count"=>0}, {"total_count"=>0},
|
|
90
|
+
{"delete-error"=>{"#{ERROR}-error"=>{"message"=>msg},ERROR=>error_objs[ERROR]}}]
|
|
91
|
+
verify_result(@c.docname(:delete_errors) => {})
|
|
92
|
+
@cs.send_cud.should == [{"version"=>ClientSync::VERSION},
|
|
93
|
+
{"token"=>""}, {"count"=>0}, {"progress_count"=>0}, {"total_count"=>0},{}]
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
def receive_and_send_cud(operation)
|
|
97
|
+
msg = "Error #{operation} record"
|
|
98
|
+
op_data = {operation=>{ERROR=>{'an_attribute'=>msg,'name'=>'wrongname'}}}
|
|
99
|
+
@cs.receive_cud(op_data)
|
|
100
|
+
@cs.send_cud.should == [{"version"=>ClientSync::VERSION},
|
|
101
|
+
{"token"=>""}, {"count"=>0}, {"progress_count"=>0}, {"total_count"=>0},
|
|
102
|
+
{"#{operation}-error"=>{"#{ERROR}-error"=>{"message"=>msg},ERROR=>op_data[operation][ERROR]}}]
|
|
103
|
+
end
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
it "should handle receive_cud" do
|
|
107
|
+
set_state(@s.docname(:md) => {'3'=>@product3},
|
|
108
|
+
@c.docname(:cd) => {'3'=>@product3})
|
|
109
|
+
params = {'create'=>{'1'=>@product1},
|
|
110
|
+
'update'=>{'2'=>@product2},'delete'=>{'3'=>@product3}}
|
|
111
|
+
@cs.receive_cud(params)
|
|
112
|
+
verify_result(@cs.client.docname(:create) => {},
|
|
113
|
+
@cs.client.docname(:update) => {},
|
|
114
|
+
@cs.client.docname(:delete) => {},
|
|
115
|
+
@s.docname(:md) => {},
|
|
116
|
+
@c.docname(:cd) => {})
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
it "should handle blob upload in receive_cud" do
|
|
120
|
+
pending
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
it "should handle send_cud with query_params" do
|
|
124
|
+
expected = {'1'=>@product1}
|
|
125
|
+
set_state('test_db_storage' => {'1'=>@product1,'2'=>@product2,'4'=>@product4})
|
|
126
|
+
params = {'name' => 'iPhone'}
|
|
127
|
+
@cs.send_cud(nil,params)
|
|
128
|
+
verify_result(@s.docname(:md) => expected,
|
|
129
|
+
@cs.client.docname(:page) => expected)
|
|
130
|
+
end
|
|
131
|
+
end
|
|
132
|
+
|
|
133
|
+
describe "reset" do
|
|
134
|
+
it "should handle reset" do
|
|
135
|
+
set_state(@c.docname(:cd) => @data)
|
|
136
|
+
ClientSync.reset(@c)
|
|
137
|
+
verify_result(@c.docname(:cd) => {})
|
|
138
|
+
Client.load(@c.id,{:source_name => @s.name}).should_not be_nil
|
|
139
|
+
end
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
describe "search" do
|
|
143
|
+
before(:each) do
|
|
144
|
+
@s_fields[:name] = 'SimpleAdapter'
|
|
145
|
+
@c1 = Client.create(@c_fields,{:source_name => @s_fields[:name]})
|
|
146
|
+
@s1 = Source.create(@s_fields,@s_params)
|
|
147
|
+
@cs1 = ClientSync.new(@s1,@c1,2)
|
|
148
|
+
end
|
|
149
|
+
|
|
150
|
+
it "should handle search" do
|
|
151
|
+
params = {:search => {'name' => 'iPhone'}}
|
|
152
|
+
set_state('test_db_storage' => @data)
|
|
153
|
+
res = @cs.search(params)
|
|
154
|
+
token = @c.get_value(:search_token)
|
|
155
|
+
res.should == [{'version'=>ClientSync::VERSION},{'search_token'=>token},
|
|
156
|
+
{'source'=>@s.name},{'count'=>1},{'insert'=>{'1'=>@product1}}]
|
|
157
|
+
verify_result(@c.docname(:search) => {'1'=>@product1},
|
|
158
|
+
@c.docname(:search_errors) => {})
|
|
159
|
+
end
|
|
160
|
+
|
|
161
|
+
it "should handle search with nil result" do
|
|
162
|
+
params = {:search => {'name' => 'foo'}}
|
|
163
|
+
set_state('test_db_storage' => @data)
|
|
164
|
+
@cs.search(params).should == []
|
|
165
|
+
verify_result(@c.docname(:search) => {},
|
|
166
|
+
@c.docname(:search_errors) => {})
|
|
167
|
+
end
|
|
168
|
+
|
|
169
|
+
it "should resend search by search_token" do
|
|
170
|
+
@source = @s
|
|
171
|
+
set_state({@c.docname(:search) => {'1'=>@product1}})
|
|
172
|
+
token = compute_token @cs.client.docname(:search_token)
|
|
173
|
+
@cs.search({:resend => true,:search_token => token}).should == [{'version'=>ClientSync::VERSION},
|
|
174
|
+
{'search_token'=>token},{'source'=>@s.name},{'count'=>1},{'insert'=>{'1'=>@product1}}]
|
|
175
|
+
verify_result(@c.docname(:search) => {'1'=>@product1},
|
|
176
|
+
@c.docname(:search_errors) => {},
|
|
177
|
+
@cs.client.docname(:search_token) => token)
|
|
178
|
+
end
|
|
179
|
+
|
|
180
|
+
it "should handle search ack" do
|
|
181
|
+
@source = @s
|
|
182
|
+
set_state({@c.docname(:search) => {'1'=>@product1}})
|
|
183
|
+
token = compute_token @cs.client.docname(:search_token)
|
|
184
|
+
@cs.search({:search_token => token}).should == []
|
|
185
|
+
verify_result(@c.docname(:search) => {},
|
|
186
|
+
@c.docname(:search_errors) => {},
|
|
187
|
+
@cs.client.docname(:search_token) => nil)
|
|
188
|
+
end
|
|
189
|
+
|
|
190
|
+
it "should handle search all" do
|
|
191
|
+
sources = ['SampleAdapter']
|
|
192
|
+
set_state('test_db_storage' => @data)
|
|
193
|
+
res = ClientSync.search_all(@c,{:sources => sources,:search => {'name' => 'iPhone'}})
|
|
194
|
+
token = Store.get_value(@cs.client.docname(:search_token))
|
|
195
|
+
res.should == [[{'version'=>ClientSync::VERSION},{'search_token'=>token},
|
|
196
|
+
{'source'=>sources[0]},{'count'=>1},{'insert'=>{'1'=>@product1}}]]
|
|
197
|
+
verify_result(@c.docname(:search) => {'1'=>@product1},
|
|
198
|
+
@c.docname(:search_errors) => {})
|
|
199
|
+
end
|
|
200
|
+
|
|
201
|
+
it "should handle search all error" do
|
|
202
|
+
sources = ['SampleAdapter']
|
|
203
|
+
msg = "Error during search"
|
|
204
|
+
error = set_test_data('test_db_storage',@data,msg,'search error')
|
|
205
|
+
res = ClientSync.search_all(@c,{:sources => sources,:search => {'name' => 'iPhone'}})
|
|
206
|
+
token = Store.get_value(@cs.client.docname(:search_token))
|
|
207
|
+
res.should == [[{'version'=>ClientSync::VERSION},
|
|
208
|
+
{'source'=>sources[0]},{'search-error'=>{'search-error'=>{'message'=>msg}}}]]
|
|
209
|
+
verify_result(@c.docname(:search) => {},
|
|
210
|
+
@c.docname(:search_errors) => {'search-error'=>{'message'=>msg}})
|
|
211
|
+
end
|
|
212
|
+
|
|
213
|
+
it "should handle search all login error" do
|
|
214
|
+
@u.login = nil
|
|
215
|
+
sources = ['SampleAdapter']
|
|
216
|
+
msg = "Error logging in"
|
|
217
|
+
error = set_test_data('test_db_storage',@data,msg,'search error')
|
|
218
|
+
ClientSync.search_all(@c,{:sources => sources,:search => {'name' => 'iPhone'}}).should == [
|
|
219
|
+
[{'version'=>ClientSync::VERSION},{'source'=>sources[0]},
|
|
220
|
+
{'search-error'=>{'login-error'=>{'message'=>msg}}}]]
|
|
221
|
+
verify_result(@c.docname(:search) => {},
|
|
222
|
+
@c.docname(:search_errors) => {'login-error'=>{'message'=>msg}},
|
|
223
|
+
@c.docname(:search_token) => nil)
|
|
224
|
+
end
|
|
225
|
+
|
|
226
|
+
it "should handle multiple source search all" do
|
|
227
|
+
set_test_data('test_db_storage',@data)
|
|
228
|
+
sources = ['SampleAdapter','SimpleAdapter']
|
|
229
|
+
res = ClientSync.search_all(@c,{:sources => sources,:search => {'name' => 'iPhone'}})
|
|
230
|
+
@c.source_name = 'SampleAdapter'
|
|
231
|
+
token = Store.get_value(@c.docname(:search_token))
|
|
232
|
+
res.should == [[{"version"=>ClientSync::VERSION},{'search_token'=>token},
|
|
233
|
+
{"source"=>"SampleAdapter"},{"count"=>1},{"insert"=>{'1'=>@product1}}],[]]
|
|
234
|
+
end
|
|
235
|
+
|
|
236
|
+
it "should handle search and accumulate params" do
|
|
237
|
+
set_test_data('test_db_storage',@data)
|
|
238
|
+
sources = ['SimpleAdapter','SampleAdapter']
|
|
239
|
+
res = ClientSync.search_all(@c,{:sources => sources,:search => {'search'=>'bar'}})
|
|
240
|
+
@c.source_name = 'SimpleAdapter'
|
|
241
|
+
token = Store.get_value(@c.docname(:search_token))
|
|
242
|
+
@c.source_name = 'SampleAdapter'
|
|
243
|
+
token1 = Store.get_value(@c.docname(:search_token))
|
|
244
|
+
res.should == [[{"version"=>ClientSync::VERSION}, {'search_token'=>token},
|
|
245
|
+
{"source"=>"SimpleAdapter"},{"count"=>1},{"insert"=>{'obj'=>{'foo'=>'bar'}}}],
|
|
246
|
+
[{"version"=>ClientSync::VERSION},{'search_token'=>token1},{"source"=>"SampleAdapter"},
|
|
247
|
+
{"count"=>1}, {"insert"=>{'1'=>@product1}}]]
|
|
248
|
+
end
|
|
249
|
+
end
|
|
250
|
+
|
|
251
|
+
describe "page methods" do
|
|
252
|
+
it "should return diffs between master documents and client documents limited by page size" do
|
|
253
|
+
Store.put_data(@s.docname(:md),@data).should == true
|
|
254
|
+
Store.get_data(@s.docname(:md)).should == @data
|
|
255
|
+
Store.put_value(@s.docname(:md_size),@data.size)
|
|
256
|
+
@expected = {'1'=>@product1,'2'=>@product2}
|
|
257
|
+
@cs.compute_page.should == [0,3,@expected]
|
|
258
|
+
Store.get_value(@cs.client.docname(:cd_size)).to_i.should == 0
|
|
259
|
+
Store.get_data(@cs.client.docname(:page)).should == @expected
|
|
260
|
+
end
|
|
261
|
+
|
|
262
|
+
it "appends diff to the client document" do
|
|
263
|
+
@cd = {'3'=>@product3}
|
|
264
|
+
Store.put_data(@c.docname(:cd),@cd)
|
|
265
|
+
Store.get_data(@c.docname(:cd)).should == @cd
|
|
266
|
+
|
|
267
|
+
@page = {'1'=>@product1,'2'=>@product2}
|
|
268
|
+
@expected = {'1'=>@product1,'2'=>@product2,'3'=>@product3}
|
|
269
|
+
|
|
270
|
+
Store.put_data(@c.docname(:cd),@page,true).should == true
|
|
271
|
+
Store.get_data(@c.docname(:cd)).should == @expected
|
|
272
|
+
end
|
|
273
|
+
|
|
274
|
+
it "should return deleted objects in the client document" do
|
|
275
|
+
Store.put_data(@s.docname(:md),@data).should == true
|
|
276
|
+
Store.get_data(@s.docname(:md)).should == @data
|
|
277
|
+
|
|
278
|
+
@cd = {'1'=>@product1,'2'=>@product2,'3'=>@product3,'4'=>@product4}
|
|
279
|
+
Store.put_data(@cs.client.docname(:cd),@cd)
|
|
280
|
+
Store.get_data(@cs.client.docname(:cd)).should == @cd
|
|
281
|
+
|
|
282
|
+
@expected = {'4'=>@product4}
|
|
283
|
+
@cs.compute_deleted_page.should == @expected
|
|
284
|
+
Store.get_data(@cs.client.docname(:delete_page)).should == @expected
|
|
285
|
+
end
|
|
286
|
+
|
|
287
|
+
it "should delete objects from client document" do
|
|
288
|
+
Store.put_data(@s.docname(:md),@data).should == true
|
|
289
|
+
Store.get_data(@s.docname(:md)).should == @data
|
|
290
|
+
|
|
291
|
+
@cd = {'1'=>@product1,'2'=>@product2,'3'=>@product3,'4'=>@product4}
|
|
292
|
+
Store.put_data(@cs.client.docname(:cd),@cd)
|
|
293
|
+
Store.get_data(@cs.client.docname(:cd)).should == @cd
|
|
294
|
+
|
|
295
|
+
Store.delete_data(@cs.client.docname(:cd),@cs.compute_deleted_page).should == true
|
|
296
|
+
Store.get_data(@cs.client.docname(:cd)).should == @data
|
|
297
|
+
end
|
|
298
|
+
|
|
299
|
+
it "should resend page if page exists and no token provided" do
|
|
300
|
+
expected = {'1'=>@product1}
|
|
301
|
+
set_test_data('test_db_storage',{'1'=>@product1,'2'=>@product2,'4'=>@product4})
|
|
302
|
+
params = {'name' => 'iPhone'}
|
|
303
|
+
@cs.send_cud(nil,params)
|
|
304
|
+
token = @c.get_value(:page_token)
|
|
305
|
+
@cs.send_cud.should == [{"version"=>ClientSync::VERSION},{"token"=>token},
|
|
306
|
+
{"count"=>1}, {"progress_count"=>0},{"total_count"=>1},{'insert' => expected}]
|
|
307
|
+
@cs.send_cud(token).should == [{"version"=>ClientSync::VERSION},{"token"=>""},
|
|
308
|
+
{"count"=>0}, {"progress_count"=>1}, {"total_count"=>1}, {}]
|
|
309
|
+
Store.get_data(@cs.client.docname(:page)).should == {}
|
|
310
|
+
@c.get_value(:page_token).should be_nil
|
|
311
|
+
end
|
|
312
|
+
end
|
|
313
|
+
|
|
314
|
+
describe "bulk data" do
|
|
315
|
+
after(:each) do
|
|
316
|
+
delete_data_directory
|
|
317
|
+
end
|
|
318
|
+
|
|
319
|
+
it "should create bulk data job user parition if none exists" do
|
|
320
|
+
ClientSync.bulk_data(:user,@c).should == {:result => :wait}
|
|
321
|
+
Resque.peek(:bulk_data).should == {"args"=>
|
|
322
|
+
[{"data_name"=>File.join(@a_fields[:name],@u_fields[:login],@u_fields[:login])}],
|
|
323
|
+
"class"=>"Rhosync::BulkDataJob"}
|
|
324
|
+
end
|
|
325
|
+
|
|
326
|
+
it "should create bulk data job app partition if none exists and no parition sources" do
|
|
327
|
+
ClientSync.bulk_data(:app,@c).should == {:result => :nop}
|
|
328
|
+
Resque.peek(:bulk_data).should == nil
|
|
329
|
+
end
|
|
330
|
+
|
|
331
|
+
it "should create bulk data job app partition with partition sources" do
|
|
332
|
+
@s.partition = :app
|
|
333
|
+
ClientSync.bulk_data(:app,@c).should == {:result => :wait}
|
|
334
|
+
Resque.peek(:bulk_data).should == {"args"=>
|
|
335
|
+
[{"data_name"=>File.join(@a_fields[:name],@a_fields[:name])}],
|
|
336
|
+
"class"=>"Rhosync::BulkDataJob"}
|
|
337
|
+
end
|
|
338
|
+
|
|
339
|
+
it "should return bulk data url for completed bulk data user partition" do
|
|
340
|
+
set_state('test_db_storage' => @data)
|
|
341
|
+
ClientSync.bulk_data(:user,@c)
|
|
342
|
+
BulkDataJob.perform("data_name" => bulk_data_docname(@a.id,@u.id))
|
|
343
|
+
ClientSync.bulk_data(:user,@c).should == {:result => :url,
|
|
344
|
+
:url => BulkData.load(bulk_data_docname(@a.id,@u.id)).dbfile}
|
|
345
|
+
verify_result(
|
|
346
|
+
"client:#{@a_fields[:name]}:#{@u_fields[:login]}:#{@c.id}:#{@s_fields[:name]}:cd" => @data,
|
|
347
|
+
"source:#{@a_fields[:name]}:#{@u_fields[:login]}:#{@s_fields[:name]}:md" => @data,
|
|
348
|
+
"source:#{@a_fields[:name]}:#{@u_fields[:login]}:#{@s_fields[:name]}:md_copy" => @data)
|
|
349
|
+
end
|
|
350
|
+
|
|
351
|
+
it "should return bulk data url for completed bulk data app partition" do
|
|
352
|
+
set_state('test_db_storage' => @data)
|
|
353
|
+
@s.partition = :app
|
|
354
|
+
ClientSync.bulk_data(:app,@c)
|
|
355
|
+
BulkDataJob.perform("data_name" => bulk_data_docname(@a.id,"*"))
|
|
356
|
+
ClientSync.bulk_data(:app,@c).should == {:result => :url,
|
|
357
|
+
:url => BulkData.load(bulk_data_docname(@a.id,"*")).dbfile}
|
|
358
|
+
verify_result(
|
|
359
|
+
"client:#{@a_fields[:name]}:#{@u_fields[:login]}:#{@c.id}:#{@s_fields[:name]}:cd" => @data,
|
|
360
|
+
"source:#{@a_fields[:name]}:__shared__:#{@s_fields[:name]}:md" => @data,
|
|
361
|
+
"source:#{@a_fields[:name]}:__shared__:#{@s_fields[:name]}:md_copy" => @data)
|
|
362
|
+
end
|
|
363
|
+
|
|
364
|
+
it "should return bulk data url for completed bulk data with bulk_sync_only source" do
|
|
365
|
+
set_state('test_db_storage' => @data)
|
|
366
|
+
@s.sync_type = :bulk_sync_only
|
|
367
|
+
ClientSync.bulk_data(:user,@c)
|
|
368
|
+
BulkDataJob.perform("data_name" => bulk_data_docname(@a.id,@u.id))
|
|
369
|
+
ClientSync.bulk_data(:user,@c).should == {:result => :url,
|
|
370
|
+
:url => BulkData.load(bulk_data_docname(@a.id,@u.id)).dbfile}
|
|
371
|
+
verify_result(
|
|
372
|
+
"client:#{@a_fields[:name]}:#{@u_fields[:login]}:#{@c.id}:#{@s_fields[:name]}:cd" => {},
|
|
373
|
+
"source:#{@a_fields[:name]}:#{@u_fields[:login]}:#{@s_fields[:name]}:md" => @data,
|
|
374
|
+
"source:#{@a_fields[:name]}:#{@u_fields[:login]}:#{@s_fields[:name]}:md_copy" => {})
|
|
375
|
+
end
|
|
376
|
+
end
|
|
377
|
+
end
|