rhoconnect 4.0.4 → 5.1.1
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.
- checksums.yaml +5 -13
- data/CHANGELOG.md +54 -5
- data/CREDITS +219 -219
- data/Gemfile +2 -2
- data/Gemfile.lock +68 -79
- data/Rakefile +1 -2
- data/bench/benchapp/spec/models/ruby/mock_adapter_spec.rb +17 -17
- data/bench/benchapp/spec/models/ruby/queue_mock_adapter_spec.rb +17 -17
- data/bench/benchapp/spec/spec_helper.rb +3 -3
- data/bench/blobapp/spec/models/ruby/blob_adapter_spec.rb +17 -17
- data/bench/blobapp/spec/spec_helper.rb +3 -3
- data/bench/lib/bench/runner.rb +1 -69
- data/bench/lib/bench.rb +18 -18
- data/bench/spec/mock_adapter_spec.rb +54 -55
- data/bench/spec/mock_client_spec.rb +47 -48
- data/bench/spec/result_spec.rb +41 -44
- data/bench/spec/utils_spec.rb +24 -25
- data/commands/generators/app.rb +7 -5
- data/commands/generators/controller.rb +7 -5
- data/commands/generators/model.rb +7 -5
- data/commands/generators/source.rb +7 -5
- data/commands/parser.rb +1 -1
- data/commands/redis/redis_download.rb +1 -1
- data/doc/async-jobs.txt +9 -9
- data/doc/supported-platforms.txt +0 -2
- data/generators/rhoconnect.rb +92 -212
- data/generators/templates/application/rcgemfile +3 -3
- data/generators/templates/application/spec/application_controller_spec.rb +14 -16
- data/generators/templates/application/spec/js_spec.rb +20 -20
- data/generators/templates/application/spec/spec_helper.rb +1 -1
- data/generators/templates/source/controllers/ruby/controller_spec.rb +18 -19
- data/generators/templates/source/models/ruby/model_spec.rb +17 -17
- data/install.sh +10 -21
- data/installer/unix-like/rho_connect_install_constants.rb +5 -5
- data/installer/unix-like/rho_connect_install_installers.rb +4 -4
- data/installer/utils/constants.rb +6 -6
- data/installer/utils/nix_install_test.rb +29 -29
- data/installer/utils/package_upload/repos.rake +16 -26
- data/js-adapters/node.rb +4 -4
- data/js-adapters/node_channel.rb +4 -8
- data/lib/rhoconnect/db_adapter.rb +13 -13
- data/lib/rhoconnect/handler/changes/engine.rb +1 -1
- data/lib/rhoconnect/jobs/bulk_data_job.rb +29 -29
- data/lib/rhoconnect/license.rb +7 -7
- data/lib/rhoconnect/model/helpers/find_duplicates_on_update.rb +13 -13
- data/lib/rhoconnect/ping/apple.rb +4 -4
- data/lib/rhoconnect/server.rb +2 -2
- data/lib/rhoconnect/source.rb +2 -2
- data/lib/rhoconnect/store.rb +12 -6
- data/lib/rhoconnect/utilities.rb +2 -2
- data/lib/rhoconnect/version.rb +1 -1
- data/lib/rhoconnect.rb +6 -4
- data/rhoconnect.gemspec +5 -6
- data/spec/api/api_helper.rb +1 -1
- data/spec/api/app/fast_delete_spec.rb +22 -22
- data/spec/api/app/fast_insert_spec.rb +23 -23
- data/spec/api/app/fast_update_spec.rb +63 -63
- data/spec/api/app/push_deletes_spec.rb +11 -13
- data/spec/api/app/push_objects_spec.rb +39 -39
- data/spec/api/client/client_get_db_doc_spec.rb +29 -29
- data/spec/api/client/client_set_db_doc_spec.rb +11 -11
- data/spec/api/client/get_client_params_spec.rb +29 -29
- data/spec/api/client/list_client_docs_spec.rb +32 -34
- data/spec/api/client/reset_spec.rb +30 -30
- data/spec/api/readstate/set_refresh_time_spec.rb +43 -43
- data/spec/api/source/get_source_params_spec.rb +32 -34
- data/spec/api/source/list_sources_spec.rb +13 -13
- data/spec/api/source/update_source_params_spec.rb +19 -19
- data/spec/api/store/get_db_doc_spec.rb +27 -27
- data/spec/api/store/set_db_doc_spec.rb +38 -38
- data/spec/api/system/adapter_spec.rb +27 -29
- data/spec/api/system/get_license_info_spec.rb +11 -11
- data/spec/api/system/login_spec.rb +37 -37
- data/spec/api/system/reset_spec.rb +15 -15
- data/spec/api/system/stats_spec.rb +70 -71
- data/spec/api/user/create_user_spec.rb +37 -37
- data/spec/api/user/delete_client_spec.rb +7 -7
- data/spec/api/user/delete_user_spec.rb +62 -62
- data/spec/api/user/list_clients_spec.rb +24 -24
- data/spec/api/user/list_source_docs_spec.rb +29 -29
- data/spec/api/user/list_users_spec.rb +22 -22
- data/spec/api/user/ping_spec.rb +18 -18
- data/spec/api/user/show_user_spec.rb +10 -10
- data/spec/api/user/update_user_spec.rb +43 -43
- data/spec/api/user/user_get_db_doc_spec.rb +12 -12
- data/spec/api/user/user_set_db_doc_spec.rb +37 -37
- data/spec/api_token_spec.rb +8 -8
- data/spec/app_spec.rb +18 -17
- data/spec/apps/jstestapp/settings/settings.yml +2 -0
- data/spec/async_spec.rb +9 -11
- data/spec/bulk_data/bulk_data_spec.rb +120 -120
- data/spec/cli/cli_spec.rb +50 -53
- data/spec/client_spec.rb +105 -105
- data/spec/client_sync_spec.rb +529 -528
- data/spec/controllers/js_base_spec.rb +147 -141
- data/spec/doc/doc_spec.rb +51 -52
- data/spec/document_spec.rb +58 -58
- data/spec/dynamic_adapter_spec.rb +33 -36
- data/spec/generator/generator_spec.rb +76 -42
- data/spec/jobs/bulk_data_job_spec.rb +101 -102
- data/spec/jobs/ping_job_spec.rb +176 -177
- data/spec/jobs/source_job_spec.rb +24 -25
- data/spec/license_spec.rb +54 -55
- data/spec/models/js_base_spec.rb +121 -120
- data/spec/perf/bulk_data_perf_spec.rb +23 -24
- data/spec/perf/perf_spec_helper.rb +7 -7
- data/spec/perf/store_perf_spec.rb +139 -140
- data/spec/ping/apple_spec.rb +65 -65
- data/spec/ping/gcm_spec.rb +83 -84
- data/spec/ping/rhoconnect_push_spec.rb +52 -53
- data/spec/predefined_adapters/rho_internal_bench_adapter_controller_js_spec.rb +100 -101
- data/spec/predefined_adapters/rho_internal_js_bench_adapter_js_spec.rb +29 -31
- data/spec/read_state_spec.rb +24 -25
- data/spec/rhoconnect_spec.rb +7 -7
- data/spec/server/server_spec.rb +664 -662
- data/spec/server/stats_spec.rb +12 -12
- data/spec/source_adapter_spec.rb +124 -125
- data/spec/source_spec.rb +148 -149
- data/spec/source_sync_spec.rb +736 -736
- data/spec/spec_helper.rb +4 -5
- data/spec/stats/record_spec.rb +22 -21
- data/spec/store_orm_spec.rb +48 -48
- data/spec/store_spec.rb +428 -426
- data/spec/support/shared_examples.rb +5 -7
- data/spec/sync_states_spec.rb +67 -67
- data/spec/test_methods_spec.rb +121 -123
- data/spec/testdata/10000-data.txt +0 -0
- data/spec/testdata/5000-data.txt +0 -0
- data/spec/user_spec.rb +102 -102
- data/tasks/redis.rake +3 -3
- metadata +154 -195
- data/bench/benchapp/tmp/pids/passenger.9292.pid.lock +0 -0
- data/bench/benchapp/tmp/restart.txt +0 -0
- data/bench/blobapp/settings/license.key.bak +0 -2
- data/bench/blobapp/tmp/restart.txt +0 -0
- data/bench/lib/testdata/1-data.txt +0 -0
- data/bench/lib/testdata/10-data.txt +0 -0
- data/bench/lib/testdata/2-data.txt +0 -0
- data/bench/lib/testdata/250-data.txt +0 -0
- data/bench/lib/testdata/5-blob_data.txt +0 -0
- data/bench/lib/testdata/5-data.txt +0 -0
- data/bench/lib/testdata/50-data.txt +0 -0
- data/bench/lib/testdata/500-data.txt +0 -0
- data/doc/protocol.html +0 -1993
- data/spec/coverage/rcov/assets/0.2.3/jquery-1.3.2.min.js +0 -19
- data/spec/coverage/rcov/assets/0.2.3/jquery.tablesorter.min.js +0 -15
- data/spec/coverage/rcov/assets/0.2.3/print.css +0 -12
- data/spec/coverage/rcov/assets/0.2.3/rcov.js +0 -42
- data/spec/coverage/rcov/assets/0.2.3/screen.css +0 -270
- data/spec/coverage/rcov/index.html +0 -88
- data/spec/generator/generator_spec_helper.rb +0 -9
data/spec/source_sync_spec.rb
CHANGED
|
@@ -1,819 +1,819 @@
|
|
|
1
1
|
require File.join(File.dirname(__FILE__),'spec_helper')
|
|
2
2
|
|
|
3
3
|
describe "SourceSync" do
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
4
|
+
include_examples "SharedRhoconnectHelper", :rhoconnect_data => true
|
|
5
|
+
|
|
6
|
+
before(:each) do
|
|
7
|
+
@s = Source.load(@s_fields[:name],@s_params)
|
|
8
|
+
@model = Rhoconnect::Model::Base.create(@s)
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
let(:mock_schema) { {"property" => { "name" => "string", "brand" => "string" }, "version" => "1.0"} }
|
|
12
|
+
|
|
13
|
+
describe "SourceSync query methods" do
|
|
14
|
+
before (:each) do
|
|
15
|
+
rh = lambda { @model.query(params[:query])}
|
|
7
16
|
@model = Rhoconnect::Model::Base.create(@s)
|
|
17
|
+
@ssq = Rhoconnect::Handler::Query::Engine.new(@model, rh, {})
|
|
8
18
|
end
|
|
9
19
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
before (:each) do
|
|
14
|
-
rh = lambda { @model.query(params[:query])}
|
|
15
|
-
@model = Rhoconnect::Model::Base.create(@s)
|
|
16
|
-
@ssq = Rhoconnect::Handler::Query::Engine.new(@model, rh, {})
|
|
17
|
-
end
|
|
20
|
+
it "should create Rhoconnect::Handler::Query::Engine" do
|
|
21
|
+
@ssq.model.is_a?(SampleAdapter).should == true
|
|
22
|
+
end
|
|
18
23
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
24
|
+
it "should fail to create Rhoconnect::Handler::Query::Engine with InvalidArgumentError without source" do
|
|
25
|
+
lambda { Rhoconnect::Handler::Query::Engine.new(nil, nil, {}) }.should raise_error(ArgumentError, 'Unknown source')
|
|
26
|
+
end
|
|
22
27
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
28
|
+
it "should fail to create Rhoconnect::Handler::Query::Engine with InvalidArgumentError without proc handler" do
|
|
29
|
+
lambda { Rhoconnect::Handler::Query::Engine.new(@model, nil) }.should raise_error(ArgumentError, 'Invalid sync handler')
|
|
30
|
+
end
|
|
26
31
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
32
|
+
it "should raise LoginException if login fails" do
|
|
33
|
+
msg = "Error logging in"
|
|
34
|
+
@u.login = nil
|
|
35
|
+
@ssq.should_receive(:log).with("Model raised login exception: #{msg}")
|
|
36
|
+
@ssq.should_receive(:log).with(anything)
|
|
37
|
+
@ssq.do_sync
|
|
38
|
+
verify_doc_result(@s, :errors => {'login-error'=>{'message'=>msg}})
|
|
39
|
+
end
|
|
30
40
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
41
|
+
it "should raise LogoffException if logoff fails" do
|
|
42
|
+
msg = "Error logging off"
|
|
43
|
+
@ssq.should_receive(:log).with("Model raised logoff exception: #{msg}")
|
|
44
|
+
@ssq.should_receive(:log).with(anything)
|
|
45
|
+
set_test_data('test_db_storage',{},msg,'logoff error')
|
|
46
|
+
@ssq.do_sync
|
|
47
|
+
verify_doc_result(@s, :errors => {'logoff-error'=>{'message'=>msg}})
|
|
48
|
+
end
|
|
39
49
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
50
|
+
it "should hold on read on subsequent call of process if default poll interval is not exprired" do
|
|
51
|
+
expected = {'1'=>@product1}
|
|
52
|
+
set_state('test_db_storage' => expected)
|
|
53
|
+
@ssq.do_sync
|
|
54
|
+
set_state('test_db_storage' => {'2'=>@product2})
|
|
55
|
+
@ssq.do_sync
|
|
56
|
+
verify_doc_result(@s, :md => expected)
|
|
57
|
+
end
|
|
48
58
|
|
|
49
|
-
|
|
50
|
-
|
|
59
|
+
it "should read on every subsequent call of process if poll interval is set to 0" do
|
|
60
|
+
expected = {'2'=>@product2}
|
|
61
|
+
@s.poll_interval = 0
|
|
62
|
+
set_state('test_db_storage' => {'1'=>@product1})
|
|
63
|
+
@ssq.do_sync
|
|
64
|
+
set_state('test_db_storage' => expected)
|
|
65
|
+
@ssq.do_sync
|
|
66
|
+
verify_doc_result(@s, :md => expected)
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
it "should never call read on any call of process if poll interval is set to -1" do
|
|
70
|
+
@s.poll_interval = -1
|
|
71
|
+
set_state('test_db_storage' => {'1'=>@product1})
|
|
72
|
+
@ssq.do_sync
|
|
73
|
+
verify_doc_result(@s, :md => {})
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
it "should process model metadata" do
|
|
78
|
+
mock_metadata_method([SampleAdapter, SimpleAdapter]) do
|
|
79
|
+
expected = {'1'=>@product1,'2'=>@product2}
|
|
51
80
|
set_state('test_db_storage' => expected)
|
|
52
81
|
@ssq.do_sync
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
82
|
+
verify_doc_result(@s, {:md => expected,
|
|
83
|
+
:metadata => "{\"foo\":\"bar\"}",
|
|
84
|
+
:metadata_sha1 => "a5e744d0164540d33b1d7ea616c28f2fa97e754a"})
|
|
56
85
|
end
|
|
86
|
+
end
|
|
57
87
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
set_state('test_db_storage' => {'1'=>@product1})
|
|
62
|
-
@ssq.do_sync
|
|
88
|
+
it "should process model schema" do
|
|
89
|
+
mock_schema_method([SampleAdapter]) do
|
|
90
|
+
expected = {'1'=>@product1,'2'=>@product2}
|
|
63
91
|
set_state('test_db_storage' => expected)
|
|
64
92
|
@ssq.do_sync
|
|
65
|
-
verify_doc_result(@s, :md => expected)
|
|
93
|
+
verify_doc_result(@s, :md => expected)
|
|
94
|
+
JSON.parse(@s.get_value(:schema)).should == mock_schema
|
|
95
|
+
@s.get_value(:schema_sha1).should == get_sha1(mock_schema['version'])
|
|
66
96
|
end
|
|
97
|
+
end
|
|
67
98
|
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
99
|
+
it "should raise exception if model schema has no version key/value pair" do
|
|
100
|
+
mock_schema_no_version_method([SampleAdapter]) do
|
|
101
|
+
expected = {'1'=>@product1,'2'=>@product2}
|
|
102
|
+
set_state('test_db_storage' => expected)
|
|
71
103
|
@ssq.do_sync
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
it "should process model metadata" do
|
|
77
|
-
mock_metadata_method([SampleAdapter, SimpleAdapter]) do
|
|
78
|
-
expected = {'1'=>@product1,'2'=>@product2}
|
|
79
|
-
set_state('test_db_storage' => expected)
|
|
80
|
-
@ssq.do_sync
|
|
81
|
-
verify_doc_result(@s, {:md => expected,
|
|
82
|
-
:metadata => "{\"foo\":\"bar\"}",
|
|
83
|
-
:metadata_sha1 => "a5e744d0164540d33b1d7ea616c28f2fa97e754a"})
|
|
84
|
-
end
|
|
104
|
+
errors = {}
|
|
105
|
+
@s.lock(:errors) { errors = @s.get_data(:errors) }
|
|
106
|
+
errors.empty?().should == false
|
|
107
|
+
errors["query-error"]["message"].should == "Mandatory version key is not defined in model schema method"
|
|
85
108
|
end
|
|
109
|
+
end
|
|
86
110
|
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
end
|
|
111
|
+
it "should process model with stash" do
|
|
112
|
+
expected = {'1'=>@product1,'2'=>@product2}
|
|
113
|
+
set_state('test_db_storage' => expected)
|
|
114
|
+
@ssq.params[:query] = {'stash_result' => true}
|
|
115
|
+
@ssq.do_sync
|
|
116
|
+
#@ssq.model.should_receive(:stash_result).once
|
|
117
|
+
verify_doc_result(@s, {:md => expected,
|
|
118
|
+
:md_size => expected.size.to_s})
|
|
119
|
+
end
|
|
97
120
|
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
end
|
|
108
|
-
end
|
|
121
|
+
it "should process model with pass_through set" do
|
|
122
|
+
expected = {'1'=>@product1,'2'=>@product2}
|
|
123
|
+
set_state('test_db_storage' => expected)
|
|
124
|
+
@s.pass_through = 'true'
|
|
125
|
+
@ssq.do_sync.should == expected
|
|
126
|
+
verify_doc_result(@s, {:md => {},
|
|
127
|
+
:md_size => nil})
|
|
128
|
+
@s.pass_through = nil
|
|
129
|
+
end
|
|
109
130
|
|
|
110
|
-
|
|
131
|
+
it "should call methods in model" do
|
|
132
|
+
mock_metadata_method([SampleAdapter, SimpleAdapter]) do
|
|
111
133
|
expected = {'1'=>@product1,'2'=>@product2}
|
|
112
|
-
|
|
113
|
-
@ssq.
|
|
134
|
+
metadata = "{\"foo\":\"bar\"}"
|
|
135
|
+
@ssq.model.should_receive(:login).once.with(no_args()).and_return(true)
|
|
136
|
+
@ssq.model.should_receive(:metadata).once.with(no_args()).and_return(metadata)
|
|
137
|
+
@ssq.model.should_receive(:query).once.with(nil).and_return(expected)
|
|
138
|
+
@ssq.model.should_receive(:sync).once.with(no_args()).and_return(true)
|
|
139
|
+
@ssq.model.should_receive(:logoff).once.with(no_args()).and_return(nil)
|
|
114
140
|
@ssq.do_sync
|
|
115
|
-
#@ssq.model.should_receive(:stash_result).once
|
|
116
|
-
verify_doc_result(@s, {:md => expected,
|
|
117
|
-
:md_size => expected.size.to_s})
|
|
118
|
-
end
|
|
119
|
-
|
|
120
|
-
it "should process model with pass_through set" do
|
|
121
|
-
expected = {'1'=>@product1,'2'=>@product2}
|
|
122
|
-
set_state('test_db_storage' => expected)
|
|
123
|
-
@s.pass_through = 'true'
|
|
124
|
-
@ssq.do_sync.should == expected
|
|
125
|
-
verify_doc_result(@s, {:md => {},
|
|
126
|
-
:md_size => nil})
|
|
127
|
-
@s.pass_through = nil
|
|
128
141
|
end
|
|
142
|
+
end
|
|
129
143
|
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
metadata = "{\"foo\":\"bar\"}"
|
|
134
|
-
@ssq.model.should_receive(:login).once.with(no_args()).and_return(true)
|
|
135
|
-
@ssq.model.should_receive(:metadata).once.with(no_args()).and_return(metadata)
|
|
136
|
-
@ssq.model.should_receive(:query).once.with(nil).and_return(expected)
|
|
137
|
-
@ssq.model.should_receive(:sync).once.with(no_args()).and_return(true)
|
|
138
|
-
@ssq.model.should_receive(:logoff).once.with(no_args()).and_return(nil)
|
|
139
|
-
@ssq.do_sync
|
|
140
|
-
end
|
|
141
|
-
end
|
|
144
|
+
it "should do query with no exception" do
|
|
145
|
+
verify_read_operation('query')
|
|
146
|
+
end
|
|
142
147
|
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
it "should do query with no exception pass through" do
|
|
148
|
-
verify_read_operation_pass_through('query')
|
|
149
|
-
end
|
|
148
|
+
it "should do query with no exception pass through" do
|
|
149
|
+
verify_read_operation_pass_through('query')
|
|
150
|
+
end
|
|
150
151
|
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
it "should do query with exception raised and update refresh time only after retries limit is exceeded" do
|
|
156
|
-
@s.retry_limit = 1
|
|
157
|
-
msg = "Error during query"
|
|
158
|
-
set_test_data('test_db_storage',{},msg,"query error")
|
|
159
|
-
res = @ssq.do_sync
|
|
160
|
-
verify_doc_result(@s, {:md => {},
|
|
161
|
-
:errors => {'query-error'=>{'message'=>msg}}})
|
|
162
|
-
# 1) if retry_limit is set to N - then, first N retries should not update refresh_time
|
|
163
|
-
@s.read_state.retry_counter.should == 1
|
|
164
|
-
@s.read_state.refresh_time.should <= Time.now.to_i
|
|
165
|
-
|
|
166
|
-
# try once more and fail again
|
|
167
|
-
set_test_data('test_db_storage',{},msg,"query error")
|
|
168
|
-
res = @ssq.do_sync
|
|
169
|
-
verify_doc_result(@s, {:md => {},
|
|
170
|
-
:errors => {'query-error'=>{'message'=>msg}}})
|
|
152
|
+
it "should do query with exception raised" do
|
|
153
|
+
verify_read_operation_with_error('query')
|
|
154
|
+
end
|
|
171
155
|
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
156
|
+
it "should do query with exception raised and update refresh time only after retries limit is exceeded" do
|
|
157
|
+
@s.retry_limit = 1
|
|
158
|
+
msg = "Error during query"
|
|
159
|
+
set_test_data('test_db_storage',{},msg,"query error")
|
|
160
|
+
res = @ssq.do_sync
|
|
161
|
+
verify_doc_result(@s, {:md => {},
|
|
162
|
+
:errors => {'query-error'=>{'message'=>msg}}})
|
|
163
|
+
# 1) if retry_limit is set to N - then, first N retries should not update refresh_time
|
|
164
|
+
@s.read_state.retry_counter.should == 1
|
|
165
|
+
@s.read_state.refresh_time.should <= Time.now.to_i
|
|
166
|
+
|
|
167
|
+
# try once more and fail again
|
|
168
|
+
set_test_data('test_db_storage',{},msg,"query error")
|
|
169
|
+
res = @ssq.do_sync
|
|
170
|
+
verify_doc_result(@s, {:md => {},
|
|
171
|
+
:errors => {'query-error'=>{'message'=>msg}}})
|
|
172
|
+
|
|
173
|
+
# 2) if retry_limit is set to N and number of retries exceeded it - update refresh_time
|
|
174
|
+
@s.read_state.retry_counter.should == 0
|
|
175
|
+
@s.read_state.refresh_time.should > Time.now.to_i
|
|
176
|
+
end
|
|
176
177
|
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
178
|
+
it "should do query with exception raised and restore state with succesfull retry" do
|
|
179
|
+
@s.retry_limit = 1
|
|
180
|
+
msg = "Error during query"
|
|
181
|
+
set_test_data('test_db_storage',{},msg,"query error")
|
|
182
|
+
res = @ssq.do_sync
|
|
183
|
+
verify_doc_result(@s, {:md => {},
|
|
184
|
+
:errors => {'query-error'=>{'message'=>msg}}})
|
|
185
|
+
# 1) if retry_limit is set to N - then, first N retries should not update refresh_time
|
|
186
|
+
@s.read_state.retry_counter.should == 1
|
|
187
|
+
@s.read_state.refresh_time.should <= Time.now.to_i
|
|
188
|
+
|
|
189
|
+
# try once more (with success)
|
|
190
|
+
expected = {'1'=>@product1,'2'=>@product2}
|
|
191
|
+
set_test_data('test_db_storage',expected)
|
|
192
|
+
@ssq.do_sync
|
|
193
|
+
verify_doc_result(@s, {:md => expected,
|
|
194
|
+
:errors => {}})
|
|
195
|
+
@s.read_state.retry_counter.should == 0
|
|
196
|
+
@s.read_state.refresh_time.should > Time.now.to_i
|
|
197
|
+
end
|
|
197
198
|
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
199
|
+
it "should reset the retry counter if prev_refresh_time was set more than poll_interval secs ago" do
|
|
200
|
+
@s.retry_limit = 3
|
|
201
|
+
@s.poll_interval = 2
|
|
202
|
+
msg = "Error during query"
|
|
203
|
+
set_test_data('test_db_storage',{},msg,"query error")
|
|
204
|
+
res = @ssq.do_sync
|
|
205
|
+
verify_doc_result(@s, {:md => {},
|
|
206
|
+
:errors => {'query-error'=>{'message'=>msg}}})
|
|
207
|
+
# 1) if retry_limit is set to N - then, first N retries should not update refresh_time
|
|
208
|
+
@s.read_state.retry_counter.should == 1
|
|
209
|
+
@s.read_state.refresh_time.should <= Time.now.to_i
|
|
210
|
+
|
|
211
|
+
# 2) Make another error - results are the same
|
|
212
|
+
set_test_data('test_db_storage',{},msg,"query error")
|
|
213
|
+
res = @ssq.do_sync
|
|
214
|
+
verify_doc_result(@s, {:md => {},
|
|
215
|
+
:errors => {'query-error'=>{'message'=>msg}}})
|
|
216
|
+
@s.read_state.retry_counter.should == 2
|
|
217
|
+
@s.read_state.refresh_time.should <= Time.now.to_i
|
|
218
|
+
|
|
219
|
+
# wait until time interval exprires and prev_refresh_time is too old -
|
|
220
|
+
# this should reset the counter on next request with error
|
|
221
|
+
# and do not update refresh_time
|
|
222
|
+
sleep(3)
|
|
223
|
+
set_test_data('test_db_storage',{},msg,"query error")
|
|
224
|
+
res = @ssq.do_sync
|
|
225
|
+
verify_doc_result(@s, {:md => {},
|
|
205
226
|
:errors => {'query-error'=>{'message'=>msg}}})
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
# 2) Make another error - results are the same
|
|
211
|
-
set_test_data('test_db_storage',{},msg,"query error")
|
|
212
|
-
res = @ssq.do_sync
|
|
213
|
-
verify_doc_result(@s, {:md => {},
|
|
214
|
-
:errors => {'query-error'=>{'message'=>msg}}})
|
|
215
|
-
@s.read_state.retry_counter.should == 2
|
|
216
|
-
@s.read_state.refresh_time.should <= Time.now.to_i
|
|
217
|
-
|
|
218
|
-
# wait until time interval exprires and prev_refresh_time is too old -
|
|
219
|
-
# this should reset the counter on next request with error
|
|
220
|
-
# and do not update refresh_time
|
|
221
|
-
sleep(3)
|
|
222
|
-
set_test_data('test_db_storage',{},msg,"query error")
|
|
223
|
-
res = @ssq.do_sync
|
|
224
|
-
verify_doc_result(@s, {:md => {},
|
|
225
|
-
:errors => {'query-error'=>{'message'=>msg}}})
|
|
226
|
-
@s.read_state.retry_counter.should == 1
|
|
227
|
-
@s.read_state.refresh_time.should <= Time.now.to_i
|
|
228
|
-
end
|
|
229
|
-
|
|
230
|
-
it "should do query with exception raised and update refresh time if retry_limit is 0" do
|
|
231
|
-
@s.retry_limit = 0
|
|
232
|
-
msg = "Error during query"
|
|
233
|
-
set_test_data('test_db_storage',{},msg,"query error")
|
|
234
|
-
res = @ssq.do_sync
|
|
235
|
-
verify_doc_result(@s, {:md => {},
|
|
236
|
-
:errors => {'query-error'=>{'message'=>msg}}})
|
|
237
|
-
# if poll_interval is set to 0 - refresh time should be updated
|
|
238
|
-
@s.read_state.retry_counter.should == 0
|
|
239
|
-
@s.read_state.refresh_time.should > Time.now.to_i
|
|
240
|
-
end
|
|
227
|
+
@s.read_state.retry_counter.should == 1
|
|
228
|
+
@s.read_state.refresh_time.should <= Time.now.to_i
|
|
229
|
+
end
|
|
241
230
|
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
:errors => {'query-error'=>{'message'=>msg}}})
|
|
253
|
-
# if poll_interval is set to 0 - refresh time should be updated
|
|
254
|
-
@s.read_state.retry_counter.should == 0
|
|
255
|
-
@s.read_state.refresh_time.should > prev_refresh_time
|
|
256
|
-
end
|
|
231
|
+
it "should do query with exception raised and update refresh time if retry_limit is 0" do
|
|
232
|
+
@s.retry_limit = 0
|
|
233
|
+
msg = "Error during query"
|
|
234
|
+
set_test_data('test_db_storage',{},msg,"query error")
|
|
235
|
+
res = @ssq.do_sync
|
|
236
|
+
verify_doc_result(@s, {:md => {},
|
|
237
|
+
:errors => {'query-error'=>{'message'=>msg}}})
|
|
238
|
+
# if poll_interval is set to 0 - refresh time should be updated
|
|
239
|
+
@s.read_state.retry_counter.should == 0
|
|
240
|
+
@s.read_state.refresh_time.should > Time.now.to_i
|
|
257
241
|
end
|
|
258
|
-
|
|
259
|
-
describe "push_notify" do
|
|
260
|
-
it "should do push_notify for source after push_objects if enabled" do
|
|
261
|
-
@s.push_notify = 'true'
|
|
262
|
-
data = {'1' => @product1, '2' => @product2, '3' => @product3}
|
|
263
|
-
ping_params = {'user_id'=>["testuser"], 'sources'=>["SampleAdapter"]}
|
|
264
|
-
PingJob.should_receive(:perform).once.with(ping_params)
|
|
265
|
-
po_handler = lambda { @model.push_objects(params) }
|
|
266
|
-
push_objects_handler = Rhoconnect::Handler::PluginCallbacks::Runner.new(po_handler, @model, {'objects' => data})
|
|
267
|
-
push_objects_handler.run
|
|
268
|
-
end
|
|
269
|
-
|
|
270
|
-
it "should do push_notify for source after push_deletes if enabled" do
|
|
271
|
-
@s.push_notify = 'true'
|
|
272
|
-
u2 = User.create(:login => 'user2')
|
|
273
|
-
@a.users << u2.id
|
|
274
|
-
data = {'1' => @product1, '2' => @product2, '3' => @product3}
|
|
275
|
-
ping_params = {'user_id'=>["testuser"], 'sources'=>["SampleAdapter"]}
|
|
276
|
-
PingJob.should_receive(:perform).once.with(ping_params)
|
|
277
|
-
pd_handler = lambda { @model.push_deletes(params) }
|
|
278
|
-
push_deletes_handler = Rhoconnect::Handler::PluginCallbacks::Runner.new(pd_handler, @model, {'objects' => data})
|
|
279
|
-
push_deletes_handler.run
|
|
280
|
-
end
|
|
281
|
-
|
|
282
|
-
it "should not do push_notify for user source if not enabled (default)" do
|
|
283
|
-
u2 = User.create(:login => 'user2')
|
|
284
|
-
@a.users << u2.id
|
|
285
|
-
data = {'1' => @product1}
|
|
286
|
-
PingJob.should_receive(:perform).never
|
|
287
|
-
po_handler = lambda { @model.push_objects(params) }
|
|
288
|
-
push_objects_handler = Rhoconnect::Handler::PluginCallbacks::Runner.new(po_handler, @model, {'objects' => data})
|
|
289
|
-
push_objects_handler.run
|
|
290
|
-
end
|
|
291
242
|
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
243
|
+
it "should do query with exception raised and update refresh time if poll_interval == 0" do
|
|
244
|
+
@s.retry_limit = 1
|
|
245
|
+
@s.poll_interval = 0
|
|
246
|
+
msg = "Error during query"
|
|
247
|
+
set_test_data('test_db_storage',{},msg,"query error")
|
|
248
|
+
prev_refresh_time = @s.read_state.refresh_time
|
|
249
|
+
# make sure refresh time is expired
|
|
250
|
+
sleep(1)
|
|
251
|
+
res = @ssq.do_sync
|
|
252
|
+
verify_doc_result(@s, {:md => {},
|
|
253
|
+
:errors => {'query-error'=>{'message'=>msg}}})
|
|
254
|
+
# if poll_interval is set to 0 - refresh time should be updated
|
|
255
|
+
@s.read_state.retry_counter.should == 0
|
|
256
|
+
@s.read_state.refresh_time.should > prev_refresh_time
|
|
302
257
|
end
|
|
258
|
+
end
|
|
303
259
|
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
:device_pin => 'efgh',
|
|
315
|
-
:device_port => '4444',
|
|
316
|
-
:user_id => @u2.id,
|
|
317
|
-
:app_id => @a.id
|
|
318
|
-
}
|
|
319
|
-
@c2 = Client.create(@c2_fields,{:source_name => @s_fields[:name]})
|
|
320
|
-
@a.users << @u2.id
|
|
321
|
-
end
|
|
260
|
+
describe "push_notify" do
|
|
261
|
+
it "should do push_notify for source after push_objects if enabled" do
|
|
262
|
+
@s.push_notify = 'true'
|
|
263
|
+
data = {'1' => @product1, '2' => @product2, '3' => @product3}
|
|
264
|
+
ping_params = {'user_id'=>["testuser"], 'sources'=>["SampleAdapter"]}
|
|
265
|
+
PingJob.should_receive(:perform).once.with(ping_params)
|
|
266
|
+
po_handler = lambda { @model.push_objects(params) }
|
|
267
|
+
push_objects_handler = Rhoconnect::Handler::PluginCallbacks::Runner.new(po_handler, @model, {'objects' => data})
|
|
268
|
+
push_objects_handler.run
|
|
269
|
+
end
|
|
322
270
|
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
271
|
+
it "should do push_notify for source after push_deletes if enabled" do
|
|
272
|
+
@s.push_notify = 'true'
|
|
273
|
+
u2 = User.create(:login => 'user2')
|
|
274
|
+
@a.users << u2.id
|
|
275
|
+
data = {'1' => @product1, '2' => @product2, '3' => @product3}
|
|
276
|
+
ping_params = {'user_id'=>["testuser"], 'sources'=>["SampleAdapter"]}
|
|
277
|
+
PingJob.should_receive(:perform).once.with(ping_params)
|
|
278
|
+
pd_handler = lambda { @model.push_deletes(params) }
|
|
279
|
+
push_deletes_handler = Rhoconnect::Handler::PluginCallbacks::Runner.new(pd_handler, @model, {'objects' => data})
|
|
280
|
+
push_deletes_handler.run
|
|
281
|
+
end
|
|
330
282
|
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
283
|
+
it "should not do push_notify for user source if not enabled (default)" do
|
|
284
|
+
u2 = User.create(:login => 'user2')
|
|
285
|
+
@a.users << u2.id
|
|
286
|
+
data = {'1' => @product1}
|
|
287
|
+
PingJob.should_receive(:perform).never
|
|
288
|
+
po_handler = lambda { @model.push_objects(params) }
|
|
289
|
+
push_objects_handler = Rhoconnect::Handler::PluginCallbacks::Runner.new(po_handler, @model, {'objects' => data})
|
|
290
|
+
push_objects_handler.run
|
|
291
|
+
end
|
|
339
292
|
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
end
|
|
293
|
+
it "should not do push_notify for app source" do
|
|
294
|
+
@s.partition = :app
|
|
295
|
+
u2 = User.create(:login => 'user2')
|
|
296
|
+
@a.users << u2.id
|
|
297
|
+
data = {'1' => @product1}
|
|
298
|
+
PingJob.should_receive(:perform).never
|
|
299
|
+
po_handler = lambda { @model.push_objects(params) }
|
|
300
|
+
push_objects_handler = Rhoconnect::Handler::PluginCallbacks::Runner.new(po_handler, @model, {'objects' => data})
|
|
301
|
+
push_objects_handler.run
|
|
302
|
+
end
|
|
303
|
+
end
|
|
352
304
|
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
:create_links => {'temp_id2'=>{'l'=>'backend_id'}}})
|
|
371
|
-
end
|
|
305
|
+
describe "create" do
|
|
306
|
+
before (:each) do
|
|
307
|
+
rh = lambda { @model.create(params[:create_object])}
|
|
308
|
+
@ssc = Rhoconnect::Handler::Changes::Engine.new(['create'], @model, rh, {})
|
|
309
|
+
@queue_name = "create"
|
|
310
|
+
@u2_fields = {:login => 'anotheruser'}
|
|
311
|
+
@u2 = User.create(@u2_fields)
|
|
312
|
+
@u2.password = 'testpass'
|
|
313
|
+
@c2_fields = {
|
|
314
|
+
:device_type => 'Android',
|
|
315
|
+
:device_pin => 'efgh',
|
|
316
|
+
:device_port => '4444',
|
|
317
|
+
:user_id => @u2.id,
|
|
318
|
+
:app_id => @a.id
|
|
319
|
+
}
|
|
320
|
+
@c2 = Client.create(@c2_fields,{:source_name => @s_fields[:name]})
|
|
321
|
+
@a.users << @u2.id
|
|
372
322
|
end
|
|
373
323
|
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
324
|
+
it "should do create where adapter.create returns nil" do
|
|
325
|
+
set_source_queue_state(@s, {@queue_name => [[@s.name, [['2', @product2]]]]}, @c.id, true)
|
|
326
|
+
@ssc.create
|
|
327
|
+
verify_source_queue_data(@s, @queue_name => [])
|
|
328
|
+
verify_doc_result(@c, {:create_errors => {},
|
|
329
|
+
:create_links => {}})
|
|
330
|
+
end
|
|
380
331
|
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
332
|
+
it "should do create where adapter.create returns object link" do
|
|
333
|
+
@product4['link'] = 'test link'
|
|
334
|
+
set_source_queue_state(@s, {@queue_name => [[@s.name, [['4', @product4]]]]},@c.id,true)
|
|
335
|
+
@ssc.create
|
|
336
|
+
verify_source_queue_data(@s, @queue_name => [])
|
|
337
|
+
verify_doc_result(@c, {:create_errors => {},
|
|
338
|
+
:create_links => {'4'=>{'l'=>'backend_id'}}})
|
|
339
|
+
end
|
|
387
340
|
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
)
|
|
400
|
-
@ssu.update
|
|
401
|
-
update_data,client_ids = @s.get_queue(@queue_name)
|
|
402
|
-
update_data.should == [[[@s.name, [['4', { 'price' => '199.99'}]]]]]
|
|
403
|
-
client_ids.should == [@c.id]
|
|
404
|
-
verify_doc_result(@c, {:update_errors =>
|
|
405
|
-
{"#{ERROR}-error"=>{"message"=>msg}, ERROR=>data[ERROR]},
|
|
406
|
-
:update_rollback => {ERROR=>{"price"=>"99.99"}}})
|
|
407
|
-
end
|
|
341
|
+
it "should raise exception on adapter.create" do
|
|
342
|
+
msg = "Error creating record"
|
|
343
|
+
data = add_error_object({'4'=>@product4,'2'=>@product2},msg)
|
|
344
|
+
source_queue_data = []
|
|
345
|
+
data.each do |key, value|
|
|
346
|
+
source_queue_data << [key, value]
|
|
347
|
+
end
|
|
348
|
+
set_source_queue_state(@s, {@queue_name => [[@s.name, source_queue_data]]},@c.id, true)
|
|
349
|
+
@ssc.create
|
|
350
|
+
verify_doc_result(@c, :create_errors =>
|
|
351
|
+
{"#{ERROR}-error"=>{"message"=>msg},ERROR=>data[ERROR]})
|
|
408
352
|
end
|
|
409
353
|
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
354
|
+
it "should properly process creates for 2 users using same queue" do
|
|
355
|
+
@product3['link'] = 'test link'
|
|
356
|
+
@product4['link'] = 'test link'
|
|
357
|
+
set_source_queue_state(@s, {@queue_name => [[@s.name, [['temp_id1', @product3]]]]},@c.id,true)
|
|
358
|
+
set_source_queue_state(@s, {@queue_name => [[@s.name, [['temp_id2', @product4]]]]},@c2.id,true)
|
|
359
|
+
@s.queue_docname(:create).should == "source:application:#{@s.name}:create"
|
|
360
|
+
@ssc.create
|
|
361
|
+
verify_source_queue_data(@s, @queue_name => [])
|
|
362
|
+
creates_source1 = Source.load(@s.name,
|
|
363
|
+
{:user_id => @u.id,:app_id => @a.id})
|
|
364
|
+
creates_source2 = Source.load(@s.name,
|
|
365
|
+
{:user_id => @u2.id,:app_id => @a.id})
|
|
366
|
+
verify_doc_result(creates_source1, {:md => {'backend_id' => @product3}})
|
|
367
|
+
verify_doc_result(creates_source2, {:md => {'backend_id' => @product4}})
|
|
368
|
+
verify_doc_result(@c, {:create_errors => {},
|
|
369
|
+
:create_links => {'temp_id1'=>{'l'=>'backend_id'}}})
|
|
370
|
+
verify_doc_result(@c2, {:create_errors => {},
|
|
371
|
+
:create_links => {'temp_id2'=>{'l'=>'backend_id'}}})
|
|
372
|
+
end
|
|
373
|
+
end
|
|
428
374
|
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
verify_doc_result(@c, :delete_errors => {})
|
|
436
|
-
verify_doc_result(@s, :md => {'3'=>@product3})
|
|
437
|
-
verify_doc_result(@c, :cd => {'3'=>@product3})
|
|
438
|
-
end
|
|
375
|
+
describe "update" do
|
|
376
|
+
before (:each) do
|
|
377
|
+
rh = lambda { @model.update(params[:update_object])}
|
|
378
|
+
@ssu = Rhoconnect::Handler::Changes::Engine.new(['update'], @model, rh, {})
|
|
379
|
+
@queue_name = "update"
|
|
380
|
+
end
|
|
439
381
|
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
end
|
|
447
|
-
# this one will be after the error and should remain in the queue
|
|
448
|
-
source_queue_data << ['2', @product2]
|
|
449
|
-
set_source_queue_state(@s, {@queue_name => [[@s.name, source_queue_data]]}, @c.id, true)
|
|
450
|
-
@ssd.delete
|
|
451
|
-
verify_doc_result(@c, :delete_errors => {"#{ERROR}-error"=>{"message"=>msg}, ERROR=>data[ERROR]})
|
|
452
|
-
verify_source_queue_data(@s, @queue_name => [[[@s.name, [['2', @product2]]]]])
|
|
453
|
-
end
|
|
382
|
+
it "should do update with no errors" do
|
|
383
|
+
set_source_queue_state(@s, {@queue_name => [[@s.name, [['4', { 'price' => '199.99' }]]]]},@c.id,true)
|
|
384
|
+
@ssu.update
|
|
385
|
+
verify_source_queue_data(@s, @queue_name => [])
|
|
386
|
+
verify_doc_result(@c, :update_errors => {})
|
|
387
|
+
end
|
|
454
388
|
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
verify_doc_result(@c, :cd => {'2'=>@product2,'3'=>@product3})
|
|
475
|
-
verify_doc_result(@c2, :cd => {'4'=>@product4, '1'=>@product1})
|
|
476
|
-
end
|
|
389
|
+
it "should do update with errors" do
|
|
390
|
+
msg = "Error updating record"
|
|
391
|
+
data = add_error_object({},msg)
|
|
392
|
+
source_queue_data = []
|
|
393
|
+
data.each do |key, value|
|
|
394
|
+
source_queue_data << [key, value]
|
|
395
|
+
end
|
|
396
|
+
# this one will be after the error record - and should remain in the queue
|
|
397
|
+
source_queue_data << ['4', { 'price' => '199.99' }]
|
|
398
|
+
set_source_queue_state(@s, {@queue_name => [[@s.name, source_queue_data]]},@c.id,true)
|
|
399
|
+
set_doc_state(@c, :cd => { ERROR => { 'price' => '99.99' } }
|
|
400
|
+
)
|
|
401
|
+
@ssu.update
|
|
402
|
+
update_data,client_ids = @s.get_queue(@queue_name)
|
|
403
|
+
update_data.should == [[[@s.name, [['4', { 'price' => '199.99'}]]]]]
|
|
404
|
+
client_ids.should == [@c.id]
|
|
405
|
+
verify_doc_result(@c, {:update_errors =>
|
|
406
|
+
{"#{ERROR}-error"=>{"message"=>msg}, ERROR=>data[ERROR]},
|
|
407
|
+
:update_rollback => {ERROR=>{"price"=>"99.99"}}})
|
|
477
408
|
end
|
|
409
|
+
end
|
|
478
410
|
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
411
|
+
describe "delete" do
|
|
412
|
+
before (:each) do
|
|
413
|
+
rh = lambda { @model.update(params[:delete_object])}
|
|
414
|
+
@ssd = Rhoconnect::Handler::Changes::Engine.new(['delete'], @model, rh, {})
|
|
415
|
+
@queue_name = "delete"
|
|
416
|
+
@u2_fields = {:login => 'anotheruser'}
|
|
417
|
+
@u2 = User.create(@u2_fields)
|
|
418
|
+
@u2.password = 'testpass'
|
|
419
|
+
@c2_fields = {
|
|
420
|
+
:device_type => 'Android',
|
|
421
|
+
:device_pin => 'efgh',
|
|
422
|
+
:device_port => '4444',
|
|
423
|
+
:user_id => @u2.id,
|
|
424
|
+
:app_id => @a.id
|
|
425
|
+
}
|
|
426
|
+
@c2 = Client.create(@c2_fields,{:source_name => @s_fields[:name]})
|
|
427
|
+
@a.users << @u2.id
|
|
428
|
+
end
|
|
484
429
|
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
430
|
+
it "should do delete with no errors" do
|
|
431
|
+
set_source_queue_state(@s, {@queue_name => [[@s.name, [['4', @product4]]]]}, @c.id, true)
|
|
432
|
+
set_doc_state(@s, :md => {'4'=>@product4,'3'=>@product3})
|
|
433
|
+
set_doc_state(@c, :cd => {'4'=>@product4,'3'=>@product3})
|
|
434
|
+
@ssd.delete
|
|
435
|
+
verify_source_queue_data(@s, @queue_name => [])
|
|
436
|
+
verify_doc_result(@c, :delete_errors => {})
|
|
437
|
+
verify_doc_result(@s, :md => {'3'=>@product3})
|
|
438
|
+
verify_doc_result(@c, :cd => {'3'=>@product3})
|
|
439
|
+
end
|
|
488
440
|
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
441
|
+
it "should do delete with errors" do
|
|
442
|
+
msg = "Error delete record"
|
|
443
|
+
data = add_error_object({},msg)
|
|
444
|
+
source_queue_data = []
|
|
445
|
+
data.each do |key, value|
|
|
446
|
+
source_queue_data << [key, value]
|
|
447
|
+
end
|
|
448
|
+
# this one will be after the error and should remain in the queue
|
|
449
|
+
source_queue_data << ['2', @product2]
|
|
450
|
+
set_source_queue_state(@s, {@queue_name => [[@s.name, source_queue_data]]}, @c.id, true)
|
|
451
|
+
@ssd.delete
|
|
452
|
+
verify_doc_result(@c, :delete_errors => {"#{ERROR}-error"=>{"message"=>msg}, ERROR=>data[ERROR]})
|
|
453
|
+
verify_source_queue_data(@s, @queue_name => [[[@s.name, [['2', @product2]]]]])
|
|
454
|
+
end
|
|
492
455
|
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
456
|
+
it "should properly process deletes for 2 users using same queue" do
|
|
457
|
+
deletes_source1 = Source.load(@s.name,
|
|
458
|
+
{:user_id => @u.id,:app_id => @a.id})
|
|
459
|
+
deletes_source2 = Source.load(@s.name,
|
|
460
|
+
{:user_id => @u2.id,:app_id => @a.id})
|
|
461
|
+
set_source_queue_state(deletes_source1, {@queue_name => [[@s.name, [['4', @product4]]]]},@c.id,true)
|
|
462
|
+
set_source_queue_state(deletes_source2, {@queue_name => [[@s.name, [['3', @product3]]]]},@c2.id,true)
|
|
463
|
+
deletes_source1.queue_docname(:delete).should == "source:application:#{@s.name}:delete"
|
|
464
|
+
deletes_source1.queue_docname(:delete).should == deletes_source2.queue_docname(:delete)
|
|
465
|
+
set_doc_state(deletes_source1, :md => {'4'=>@product4,'2'=>@product2,'3'=>@product3})
|
|
466
|
+
set_doc_state(deletes_source2, :md => {'4'=>@product4,'3'=>@product3, '1'=>@product1})
|
|
467
|
+
set_doc_state(@c, :cd => {'4'=>@product4,'2'=>@product2,'3'=>@product3})
|
|
468
|
+
set_doc_state(@c2, :cd => {'4'=>@product4,'3'=>@product3, '1'=>@product1})
|
|
469
|
+
@ssd.delete
|
|
470
|
+
verify_source_queue_data(@s, @queue_name => [])
|
|
471
|
+
verify_doc_result(@c, :delete_errors => {})
|
|
472
|
+
verify_doc_result(@c2, :delete_errors => {})
|
|
473
|
+
verify_doc_result(deletes_source1, :md => {'2'=>@product2,'3'=>@product3})
|
|
474
|
+
verify_doc_result(deletes_source2, :md => {'4'=>@product4, '1'=>@product1})
|
|
475
|
+
verify_doc_result(@c, :cd => {'2'=>@product2,'3'=>@product3})
|
|
476
|
+
verify_doc_result(@c2, :cd => {'4'=>@product4, '1'=>@product1})
|
|
477
|
+
end
|
|
478
|
+
end
|
|
496
479
|
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
@u2 = User.create(@u2_fields)
|
|
502
|
-
@u2.password = 'testpass'
|
|
503
|
-
@c2_fields = {
|
|
504
|
-
:device_type => 'Android',
|
|
505
|
-
:device_pin => 'efgh',
|
|
506
|
-
:device_port => '4444',
|
|
507
|
-
:user_id => @u2.id,
|
|
508
|
-
:app_id => @a.id
|
|
509
|
-
}
|
|
510
|
-
@c2 = Client.create(@c2_fields,{:source_name => @s_fields[:name]})
|
|
511
|
-
@a.users << @u2.id
|
|
512
|
-
create_doc1 = { 'name' => 'abc', 'link' => '1', 'an_attribute' => "My attrib 2" }
|
|
513
|
-
create_doc2 = { 'name' => 'name0', 'link' => '1' }
|
|
514
|
-
create_doc3 = { 'name' => 'name7', 'link' => '7' }
|
|
515
|
-
set_source_queue_state(@s, {@create_queue_name => [[@s.name, [['4', create_doc1]]]]},@c.id,true)
|
|
516
|
-
set_source_queue_state(@s, {@create_queue_name => [[@s.name, [['5', create_doc2]]]]},@c2.id,true)
|
|
517
|
-
set_source_queue_state(@s, {@create_queue_name => [[@s.name, [['6', create_doc3]]]]},@c.id,true)
|
|
518
|
-
set_doc_state(@c, :cd => {'10'=> {'name' => 'Apple'}})
|
|
519
|
-
set_source_queue_state(@s, {@update_queue_name => [[@s.name, [['10', { 'name' => 'Android' }]]]]},@c.id,true)
|
|
520
|
-
# should receive login/logoff pair twice for create and once for update
|
|
521
|
-
@sscud.should_receive(:auth_method).exactly(6).times.and_return(true)
|
|
522
|
-
@sscud.should_receive(:_process_create).exactly(3).times
|
|
523
|
-
@sscud.should_receive(:_process_update).once
|
|
524
|
-
@sscud.should_not_receive(:_process_delete)
|
|
525
|
-
@sscud.do_cud
|
|
526
|
-
end
|
|
480
|
+
describe "cud" do
|
|
481
|
+
before (:each) do
|
|
482
|
+
rh = lambda { @model.send(params[:operation].to_sym, params["#{params[:operation]}_object".to_sym]) }
|
|
483
|
+
@sscud = Rhoconnect::Handler::Changes::Engine.new(['create', 'update', 'delete'], @model, rh, {})
|
|
527
484
|
end
|
|
528
|
-
|
|
529
|
-
describe "cud conflicts" do
|
|
530
|
-
before (:each) do
|
|
531
|
-
@create_queue_name = :create
|
|
532
|
-
@update_queue_name = :update
|
|
533
|
-
@delete_queue_name = :delete
|
|
534
|
-
rh = lambda { @model.send(params[:operation].to_sym, params["#{params[:operation]}_object".to_sym]) }
|
|
535
|
-
@sscud = Rhoconnect::Handler::Changes::Engine.new(['create', 'update', 'delete'], @model, rh, {})
|
|
536
|
-
@u2_fields = {:login => 'anotheruser'}
|
|
537
|
-
@u2 = User.create(@u2_fields)
|
|
538
|
-
@u2.password = 'testpass'
|
|
539
|
-
@c2_fields = {
|
|
540
|
-
:device_type => 'Android',
|
|
541
|
-
:device_pin => 'efgh',
|
|
542
|
-
:device_port => '4444',
|
|
543
|
-
:user_id => @u2.id,
|
|
544
|
-
:app_id => @a.id
|
|
545
|
-
}
|
|
546
|
-
@c2 = Client.create(@c2_fields,{:source_name => @s_fields[:name]})
|
|
547
|
-
@a.users << @u2.id
|
|
548
|
-
end
|
|
549
485
|
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
@sscud.do_cud
|
|
554
|
-
|
|
555
|
-
verify_source_queue_data(@s, @create_queue_name => [])
|
|
556
|
-
verify_doc_result(@c, :create_errors => {})
|
|
557
|
-
verify_doc_result(@c, :create_links => {'4'=> { 'l' => 'backend_id' }, '5' => { 'l' => 'backend_id'}})
|
|
558
|
-
end
|
|
559
|
-
|
|
560
|
-
it "should detect create conflict and skip the duplicate record creation, but properly update the errors page" do
|
|
561
|
-
create_doc1 = { 'name' => 'wrongname', 'link' => '1', 'an_attribute' => "Create Sample Adapter Error" }
|
|
562
|
-
create_doc2 = { 'name' => 'wrongname', 'link' => '1', 'duplicate_of_cid' => @c.id, 'duplicate_of_entry_index' => '0', 'duplicate_of_queue_index' => '0'}
|
|
563
|
-
set_source_queue_state(@s, {@create_queue_name => [[@s.name, [['4', create_doc1]]]]},@c.id,true)
|
|
564
|
-
set_source_queue_state(@s, {@create_queue_name => [[@s.name, [['5', create_doc2]]]]},@c.id,true)
|
|
565
|
-
@sscud.do_cud
|
|
566
|
-
|
|
567
|
-
verify_source_queue_data(@s, @create_queue_name => [])
|
|
568
|
-
verify_doc_result(@c, :create_errors => {"4-error"=>{"message"=>"Create Sample Adapter Error"},
|
|
569
|
-
'4' => create_doc1,
|
|
570
|
-
"5-error"=>{"message"=>"Create Sample Adapter Error"},
|
|
571
|
-
'5' => create_doc2})
|
|
572
|
-
verify_doc_result(@c, :create_links => {})
|
|
573
|
-
end
|
|
574
|
-
|
|
575
|
-
it "should detect create conflict and force and error" do
|
|
576
|
-
set_source_queue_state(@s, {@create_queue_name => [[@s.name, [['4', { 'name' => 'Android', 'link' => true }]]]]},@c.id,true)
|
|
577
|
-
set_source_queue_state(@s, {@create_queue_name => [[@s.name, [['5', { 'name' => 'Android', 'link' => '1', 'force_duplicate_error' => '1' }]]]]},@c.id,true)
|
|
578
|
-
@sscud.do_cud
|
|
579
|
-
verify_source_queue_data(@s, @create_queue_name => [])
|
|
580
|
-
verify_doc_result(@c, :create_errors => {"5-error"=>{"message"=>"Error during create: object confict detected"}, "5"=>{"name"=>"Android", "link"=>"1", 'force_duplicate_error' => '1'}} )
|
|
581
|
-
end
|
|
486
|
+
it "should fail to create Rhoconnect::Handler::Changes::Engine with InvalidArgumentError without source" do
|
|
487
|
+
lambda { Rhoconnect::Handler::Changes::Engine.new(['create', 'update', 'delete'], nil, nil, {}) }.should raise_error(ArgumentError, 'Unknown source')
|
|
488
|
+
end
|
|
582
489
|
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
@sscud.do_cud
|
|
587
|
-
|
|
588
|
-
verify_source_queue_data(@s, @create_queue_name => [])
|
|
589
|
-
verify_doc_result(@c, :create_errors => {})
|
|
590
|
-
verify_doc_result(@c, :create_links => {'4'=> { 'l' => 'backend_id' }, '5'=> { 'l' => 'backend_id' }, '6' => { 'l' => 'backend_id' }, '7'=> { 'l' => 'backend_id' }})
|
|
591
|
-
end
|
|
592
|
-
|
|
593
|
-
it "should detect update conflict and skip the duplicate record update" do
|
|
594
|
-
set_doc_state(@c, :cd => {'4'=> {'name' => 'Apple'}})
|
|
595
|
-
set_source_queue_state(@s, {@update_queue_name => [[@s.name, [['4', { 'name' => 'Android' }]]]]},@c.id,true)
|
|
596
|
-
set_source_queue_state(@s, {@update_queue_name => [[@s.name, [['4', { 'name' => 'InvalidName', 'duplicate_of_cid' => @c.id, 'duplicate_of_entry_index' => '0', 'duplicate_of_queue_index' => '0'}]]]]},@c.id,true)
|
|
597
|
-
@sscud.do_cud
|
|
598
|
-
|
|
599
|
-
verify_source_queue_data(@s, @update_queue_name => [])
|
|
600
|
-
verify_doc_result(@c, :update_errors => {})
|
|
601
|
-
verify_doc_result(@c, :update_rollback => {})
|
|
602
|
-
end
|
|
603
|
-
|
|
604
|
-
it "should detect update conflict and force an error on duplicate record update" do
|
|
605
|
-
set_doc_state(@c, :cd => {'4'=> {'name' => 'Apple'}})
|
|
606
|
-
set_source_queue_state(@s, {@update_queue_name => [[@s.name, [['4', { 'name' => 'Android' }]]]]},@c.id,true)
|
|
607
|
-
set_source_queue_state(@s, {@update_queue_name => [[@s.name, [['4', { 'name' => 'ErrorName', 'force_duplicate_error' => '1' }]]]]},@c.id,true)
|
|
608
|
-
@sscud.do_cud
|
|
609
|
-
|
|
610
|
-
verify_source_queue_data(@s, @update_queue_name => [])
|
|
611
|
-
verify_doc_result(@c, :update_errors => {"4-error"=>{"message"=>"Error during update: object confict detected"}, "4"=>{"name"=>"ErrorName", 'force_duplicate_error' => '1'}})
|
|
612
|
-
verify_doc_result(@c, :update_rollback => {'4'=> {'name' => 'Apple'}})
|
|
613
|
-
end
|
|
490
|
+
it "should fail to create Rhoconnect::Handler::Changes::Engine with InvalidArgumentError without proc handler" do
|
|
491
|
+
lambda { Rhoconnect::Handler::Changes::Engine.new(['create', 'update', 'delete'], @model, nil) }.should raise_error(ArgumentError, 'Invalid CUD handler')
|
|
492
|
+
end
|
|
614
493
|
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
set_doc_state(@c, :cd => {'4'=> {'name' => 'Apple'}})
|
|
618
|
-
set_doc_state(@c2, :cd => {'4'=> {'name' => 'Apple'}})
|
|
619
|
-
update_source1 = Source.load(@s.name,
|
|
620
|
-
{:user_id => @u.id,:app_id => @a.id})
|
|
621
|
-
update_source2 = Source.load(@s.name,
|
|
622
|
-
{:user_id => @u2.id,:app_id => @a.id})
|
|
623
|
-
set_source_queue_state(update_source1, {@update_queue_name => [[@s.name, [['4', { 'name' => 'Android' }]]]]},@c.id,true)
|
|
624
|
-
set_source_queue_state(update_source2, {@update_queue_name => [[@s.name, [['4', { 'name' => 'Android' }]]]]},@c2.id, true)
|
|
625
|
-
operation_data,client_ids = update_source2.get_queue(:update)
|
|
626
|
-
invalid_meta = @sscud.model.run_validators(:update,operation_data,client_ids)
|
|
627
|
-
invalid_meta.should == { 1=> {@s.name => { 0 => { :duplicate_of=>true }}},
|
|
628
|
-
0=>{@s.name => { 0 => { :duplicates=>[{:client_id=>@c2.id, :key=>"4", :value=>{"name"=>"Android"}}]}}}}
|
|
629
|
-
|
|
630
|
-
@sscud.model.should_receive(:find_duplicates_on_update).once.and_return(invalid_meta)
|
|
631
|
-
@sscud.do_cud
|
|
632
|
-
|
|
633
|
-
verify_source_queue_data(@s, @update_queue_name => [])
|
|
634
|
-
verify_doc_result(@c, :update_errors => {})
|
|
635
|
-
verify_doc_result(@c, :update_rollback => {})
|
|
636
|
-
SampleAdapter.validators.delete(:find_duplicates_on_update)
|
|
637
|
-
end
|
|
638
|
-
|
|
639
|
-
it "should detect update conflict and force an error on duplicate record update" do
|
|
640
|
-
set_doc_state(@c, :cd => {'4'=> {'name' => 'Apple'}})
|
|
641
|
-
set_source_queue_state(@s, {@update_queue_name => [[@s.name, [['4', { 'name' => 'Android' }]]]]},@c.id,true)
|
|
642
|
-
set_source_queue_state(@s, {@update_queue_name => [[@s.name, [['4', { 'name' => 'ErrorName', 'force_duplicate_error' => '1' }]]]]},@c.id,true)
|
|
643
|
-
@sscud.do_cud
|
|
644
|
-
|
|
645
|
-
verify_source_queue_data(@s, @update_queue_name => [])
|
|
646
|
-
verify_doc_result(@c, :update_errors => {"4-error"=>{"message"=>"Error during update: object confict detected"}, "4"=>{"name"=>"ErrorName", 'force_duplicate_error' => '1'}})
|
|
647
|
-
verify_doc_result(@c, :update_rollback => {'4'=> {'name' => 'Apple'}})
|
|
648
|
-
end
|
|
649
|
-
|
|
650
|
-
it "should install find_duplicates_on_update , detect equal objects conflict and raise a custom error" do
|
|
651
|
-
SampleAdapter.enable :find_duplicates_on_update, :raise_error => true do |options, invalid_meta, operation, operation_data, client_ids|
|
|
652
|
-
invalid_meta.each do |index, index_data|
|
|
653
|
-
index_data.each do |source_id, objindex_data|
|
|
654
|
-
objindex_data.each do |objindex, objmeta|
|
|
655
|
-
if objmeta.has_key?(:error)
|
|
656
|
-
objmeta[:error] = "My custom error"
|
|
657
|
-
end
|
|
658
|
-
end if objindex_data
|
|
659
|
-
end if index_data
|
|
660
|
-
end if invalid_meta
|
|
661
|
-
invalid_meta
|
|
662
|
-
end
|
|
663
|
-
set_doc_state(@c, :cd => {'4'=> {'name' => 'Apple'}})
|
|
664
|
-
set_doc_state(@c2, :cd => {'4'=> {'name' => 'Apple'}})
|
|
665
|
-
update_source1 = Source.load(@s.name,
|
|
666
|
-
{:user_id => @u.id,:app_id => @a.id})
|
|
667
|
-
update_source2 = Source.load(@s.name,
|
|
668
|
-
{:user_id => @u2.id,:app_id => @a.id})
|
|
669
|
-
set_source_queue_state(update_source1, {@update_queue_name => [[@s.name, [['4', { 'name' => 'Android' }]]]]},@c.id,true)
|
|
670
|
-
set_source_queue_state(update_source2, {@update_queue_name => [[@s.name, [['4', { 'name' => 'Android' }]]]]},@c2.id, true)
|
|
671
|
-
operation_data,client_ids = update_source2.get_queue(:update)
|
|
672
|
-
invalid_meta = @sscud.model.run_validators(:update,operation_data,client_ids)
|
|
673
|
-
invalid_meta.should == {1=>{@s.name=>{0=>{:error=>"My custom error"}}}}
|
|
674
|
-
|
|
675
|
-
@sscud.do_cud
|
|
676
|
-
verify_source_queue_data(@s, @update_queue_name => [])
|
|
677
|
-
verify_doc_result(@c, :update_errors => {})
|
|
678
|
-
verify_doc_result(@c, :update_rollback => {})
|
|
679
|
-
verify_doc_result(@c2, :update_errors => {"4-error"=>{"message"=>"My custom error"}, "4"=>{"name"=>"Android"}})
|
|
680
|
-
verify_doc_result(@c2, :update_rollback => {'4'=> {'name' => 'Apple'}})
|
|
681
|
-
SampleAdapter.validators.delete(:find_duplicates_on_update)
|
|
682
|
-
end
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
it "should detect delete conflict and skip the duplicate record delete" do
|
|
686
|
-
set_doc_state(@c, :cd => {'4'=> {'name' => 'Apple'}})
|
|
687
|
-
set_doc_state(@c, :cd_size => 1)
|
|
688
|
-
set_source_queue_state(@s, {@delete_queue_name => [[@s.name, [['4', { 'name' => 'Apple' }]]]]},@c.id,true)
|
|
689
|
-
set_source_queue_state(@s, {@delete_queue_name => [[@s.name, [['4', { 'name' => 'Apple', 'duplicate_of_cid' => @c.id, 'duplicate_of_entry_index' => '0', 'duplicate_of_queue_index' => '0'}]]]]},@c.id,true)
|
|
690
|
-
@sscud.do_cud
|
|
691
|
-
|
|
692
|
-
verify_source_queue_data(@s, @delete_queue_name => [])
|
|
693
|
-
verify_doc_result(@c, :cd => {})
|
|
694
|
-
verify_doc_result(@c, :cd_size => '0')
|
|
695
|
-
verify_doc_result(@c, :delete_errors => {})
|
|
696
|
-
end
|
|
697
|
-
|
|
698
|
-
it "should detect delete conflict and force an error on duplicate record delete" do
|
|
699
|
-
set_doc_state(@c, :cd => {'4'=> {'name' => 'Apple'}})
|
|
700
|
-
set_doc_state(@c, :cd_size => 1)
|
|
701
|
-
set_source_queue_state(@s, {@delete_queue_name => [[@s.name, [['4', { 'name' => 'Apple' }]]]]},@c.id,true)
|
|
702
|
-
set_source_queue_state(@s, {@delete_queue_name => [[@s.name, [['4', { 'name' => 'Apple', 'force_duplicate_error' => '1'}]]]]},@c.id,true)
|
|
703
|
-
@sscud.do_cud
|
|
704
|
-
|
|
705
|
-
verify_source_queue_data(@s, @delete_queue_name => [])
|
|
706
|
-
verify_doc_result(@c, :delete_errors => {"4-error"=>{"message"=>"Error during delete: object confict detected"}, "4"=>{"name"=>"Apple", 'force_duplicate_error' => '1'}})
|
|
707
|
-
end
|
|
494
|
+
it "should create Rhoconnect::Handler::Changes::Engine" do
|
|
495
|
+
@sscud.model.is_a?(SampleAdapter).should == true
|
|
708
496
|
end
|
|
709
497
|
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
498
|
+
it "should do process_cud" do
|
|
499
|
+
@create_queue_name = :create
|
|
500
|
+
@update_queue_name = :update
|
|
501
|
+
@u2_fields = {:login => 'anotheruser'}
|
|
502
|
+
@u2 = User.create(@u2_fields)
|
|
503
|
+
@u2.password = 'testpass'
|
|
504
|
+
@c2_fields = {
|
|
505
|
+
:device_type => 'Android',
|
|
506
|
+
:device_pin => 'efgh',
|
|
507
|
+
:device_port => '4444',
|
|
508
|
+
:user_id => @u2.id,
|
|
509
|
+
:app_id => @a.id
|
|
510
|
+
}
|
|
511
|
+
@c2 = Client.create(@c2_fields,{:source_name => @s_fields[:name]})
|
|
512
|
+
@a.users << @u2.id
|
|
513
|
+
create_doc1 = { 'name' => 'abc', 'link' => '1', 'an_attribute' => "My attrib 2" }
|
|
514
|
+
create_doc2 = { 'name' => 'name0', 'link' => '1' }
|
|
515
|
+
create_doc3 = { 'name' => 'name7', 'link' => '7' }
|
|
516
|
+
set_source_queue_state(@s, {@create_queue_name => [[@s.name, [['4', create_doc1]]]]},@c.id,true)
|
|
517
|
+
set_source_queue_state(@s, {@create_queue_name => [[@s.name, [['5', create_doc2]]]]},@c2.id,true)
|
|
518
|
+
set_source_queue_state(@s, {@create_queue_name => [[@s.name, [['6', create_doc3]]]]},@c.id,true)
|
|
519
|
+
set_doc_state(@c, :cd => {'10'=> {'name' => 'Apple'}})
|
|
520
|
+
set_source_queue_state(@s, {@update_queue_name => [[@s.name, [['10', { 'name' => 'Android' }]]]]},@c.id,true)
|
|
521
|
+
# should receive login/logoff pair twice for create and once for update
|
|
522
|
+
@sscud.should_receive(:auth_method).exactly(6).times.and_return(true)
|
|
523
|
+
@sscud.should_receive(:_process_create).exactly(3).times
|
|
524
|
+
@sscud.should_receive(:_process_update).once
|
|
525
|
+
@sscud.should_not_receive(:_process_delete)
|
|
526
|
+
@sscud.do_cud
|
|
527
|
+
end
|
|
528
|
+
end
|
|
715
529
|
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
530
|
+
describe "cud conflicts" do
|
|
531
|
+
before (:each) do
|
|
532
|
+
@create_queue_name = :create
|
|
533
|
+
@update_queue_name = :update
|
|
534
|
+
@delete_queue_name = :delete
|
|
535
|
+
rh = lambda { @model.send(params[:operation].to_sym, params["#{params[:operation]}_object".to_sym]) }
|
|
536
|
+
@sscud = Rhoconnect::Handler::Changes::Engine.new(['create', 'update', 'delete'], @model, rh, {})
|
|
537
|
+
@u2_fields = {:login => 'anotheruser'}
|
|
538
|
+
@u2 = User.create(@u2_fields)
|
|
539
|
+
@u2.password = 'testpass'
|
|
540
|
+
@c2_fields = {
|
|
541
|
+
:device_type => 'Android',
|
|
542
|
+
:device_pin => 'efgh',
|
|
543
|
+
:device_port => '4444',
|
|
544
|
+
:user_id => @u2.id,
|
|
545
|
+
:app_id => @a.id
|
|
546
|
+
}
|
|
547
|
+
@c2 = Client.create(@c2_fields,{:source_name => @s_fields[:name]})
|
|
548
|
+
@a.users << @u2.id
|
|
549
|
+
end
|
|
723
550
|
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
551
|
+
it "should detect create conflict and skip the duplicate record creation, but properly update the links" do
|
|
552
|
+
set_source_queue_state(@s, {@create_queue_name => [[@s.name, [['4', { 'name' => 'Android', 'link' => '1' }]]]]},@c.id,true)
|
|
553
|
+
set_source_queue_state(@s, {@create_queue_name => [[@s.name, [['5', { 'name' => 'Android', 'link' => '1', 'duplicate_of_cid' => @c.id, 'duplicate_of_entry_index' => '0', 'duplicate_of_queue_index' => '0' }]]]]},@c.id,true)
|
|
554
|
+
@sscud.do_cud
|
|
555
|
+
|
|
556
|
+
verify_source_queue_data(@s, @create_queue_name => [])
|
|
557
|
+
verify_doc_result(@c, :create_errors => {})
|
|
558
|
+
verify_doc_result(@c, :create_links => {'4'=> { 'l' => 'backend_id' }, '5' => { 'l' => 'backend_id'}})
|
|
727
559
|
end
|
|
728
560
|
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
"read_state:#{test_app_name}:__shared__:SampleAdapter:prev_refresh_time",
|
|
743
|
-
"read_state:#{test_app_name}:__shared__:SampleAdapter:rho__id",
|
|
744
|
-
"read_state:#{test_app_name}:__shared__:SampleAdapter:retry_counter"].sort
|
|
745
|
-
end
|
|
561
|
+
it "should detect create conflict and skip the duplicate record creation, but properly update the errors page" do
|
|
562
|
+
create_doc1 = { 'name' => 'wrongname', 'link' => '1', 'an_attribute' => "Create Sample Adapter Error" }
|
|
563
|
+
create_doc2 = { 'name' => 'wrongname', 'link' => '1', 'duplicate_of_cid' => @c.id, 'duplicate_of_entry_index' => '0', 'duplicate_of_queue_index' => '0'}
|
|
564
|
+
set_source_queue_state(@s, {@create_queue_name => [[@s.name, [['4', create_doc1]]]]},@c.id,true)
|
|
565
|
+
set_source_queue_state(@s, {@create_queue_name => [[@s.name, [['5', create_doc2]]]]},@c.id,true)
|
|
566
|
+
@sscud.do_cud
|
|
567
|
+
|
|
568
|
+
verify_source_queue_data(@s, @create_queue_name => [])
|
|
569
|
+
verify_doc_result(@c, :create_errors => {"4-error"=>{"message"=>"Create Sample Adapter Error"},
|
|
570
|
+
'4' => create_doc1,
|
|
571
|
+
"5-error"=>{"message"=>"Create Sample Adapter Error"},
|
|
572
|
+
'5' => create_doc2})
|
|
573
|
+
verify_doc_result(@c, :create_links => {})
|
|
746
574
|
end
|
|
747
575
|
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
@
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
576
|
+
it "should detect create conflict and force and error" do
|
|
577
|
+
set_source_queue_state(@s, {@create_queue_name => [[@s.name, [['4', { 'name' => 'Android', 'link' => true }]]]]},@c.id,true)
|
|
578
|
+
set_source_queue_state(@s, {@create_queue_name => [[@s.name, [['5', { 'name' => 'Android', 'link' => '1', 'force_duplicate_error' => '1' }]]]]},@c.id,true)
|
|
579
|
+
@sscud.do_cud
|
|
580
|
+
verify_source_queue_data(@s, @create_queue_name => [])
|
|
581
|
+
verify_doc_result(@c, :create_errors => {"5-error"=>{"message"=>"Error during create: object confict detected"}, "5"=>{"name"=>"Android", "link"=>"1", 'force_duplicate_error' => '1'}} )
|
|
582
|
+
end
|
|
583
|
+
|
|
584
|
+
it "should detect create conflict in the intermediate state create and skip the duplicate record create" do
|
|
585
|
+
set_source_queue_state(@s, {@create_queue_name => [[@s.name, [['5', { 'name' => 'InvalidName', 'duplicate_of_cid' => @c.id, 'duplicate_of_entry_index' => '1', 'duplicate_of_queue_index' => '0'}], ['4', { 'name' => 'Android' , 'link' => true}]]]]},@c.id,true)
|
|
586
|
+
set_source_queue_state(@s, {@create_queue_name => [[@s.name, [['6', { 'name' => 'iPhone', 'link' => true }], ['7', { 'name' => 'InvalidName', 'duplicate_of_cid' => @c.id, 'duplicate_of_entry_index' => '1', 'duplicate_of_queue_index' => '0'}]]]]},@c.id,true)
|
|
587
|
+
@sscud.do_cud
|
|
588
|
+
|
|
589
|
+
verify_source_queue_data(@s, @create_queue_name => [])
|
|
590
|
+
verify_doc_result(@c, :create_errors => {})
|
|
591
|
+
verify_doc_result(@c, :create_links => {'4'=> { 'l' => 'backend_id' }, '5'=> { 'l' => 'backend_id' }, '6' => { 'l' => 'backend_id' }, '7'=> { 'l' => 'backend_id' }})
|
|
592
|
+
end
|
|
593
|
+
|
|
594
|
+
it "should detect update conflict and skip the duplicate record update" do
|
|
595
|
+
set_doc_state(@c, :cd => {'4'=> {'name' => 'Apple'}})
|
|
596
|
+
set_source_queue_state(@s, {@update_queue_name => [[@s.name, [['4', { 'name' => 'Android' }]]]]},@c.id,true)
|
|
597
|
+
set_source_queue_state(@s, {@update_queue_name => [[@s.name, [['4', { 'name' => 'InvalidName', 'duplicate_of_cid' => @c.id, 'duplicate_of_entry_index' => '0', 'duplicate_of_queue_index' => '0'}]]]]},@c.id,true)
|
|
598
|
+
@sscud.do_cud
|
|
599
|
+
|
|
600
|
+
verify_source_queue_data(@s, @update_queue_name => [])
|
|
601
|
+
verify_doc_result(@c, :update_errors => {})
|
|
602
|
+
verify_doc_result(@c, :update_rollback => {})
|
|
603
|
+
end
|
|
604
|
+
|
|
605
|
+
it "should detect update conflict and force an error on duplicate record update" do
|
|
606
|
+
set_doc_state(@c, :cd => {'4'=> {'name' => 'Apple'}})
|
|
607
|
+
set_source_queue_state(@s, {@update_queue_name => [[@s.name, [['4', { 'name' => 'Android' }]]]]},@c.id,true)
|
|
608
|
+
set_source_queue_state(@s, {@update_queue_name => [[@s.name, [['4', { 'name' => 'ErrorName', 'force_duplicate_error' => '1' }]]]]},@c.id,true)
|
|
609
|
+
@sscud.do_cud
|
|
610
|
+
|
|
611
|
+
verify_source_queue_data(@s, @update_queue_name => [])
|
|
612
|
+
verify_doc_result(@c, :update_errors => {"4-error"=>{"message"=>"Error during update: object confict detected"}, "4"=>{"name"=>"ErrorName", 'force_duplicate_error' => '1'}})
|
|
613
|
+
verify_doc_result(@c, :update_rollback => {'4'=> {'name' => 'Apple'}})
|
|
614
|
+
end
|
|
615
|
+
|
|
616
|
+
it "should install find_duplicates_on_update , detect equal objects conflict and skip the duplicate record update" do
|
|
617
|
+
SampleAdapter.enable :find_duplicates_on_update
|
|
618
|
+
set_doc_state(@c, :cd => {'4'=> {'name' => 'Apple'}})
|
|
619
|
+
set_doc_state(@c2, :cd => {'4'=> {'name' => 'Apple'}})
|
|
620
|
+
update_source1 = Source.load(@s.name,
|
|
621
|
+
{:user_id => @u.id,:app_id => @a.id})
|
|
622
|
+
update_source2 = Source.load(@s.name,
|
|
623
|
+
{:user_id => @u2.id,:app_id => @a.id})
|
|
624
|
+
set_source_queue_state(update_source1, {@update_queue_name => [[@s.name, [['4', { 'name' => 'Android' }]]]]},@c.id,true)
|
|
625
|
+
set_source_queue_state(update_source2, {@update_queue_name => [[@s.name, [['4', { 'name' => 'Android' }]]]]},@c2.id, true)
|
|
626
|
+
operation_data,client_ids = update_source2.get_queue(:update)
|
|
627
|
+
invalid_meta = @sscud.model.run_validators(:update,operation_data,client_ids)
|
|
628
|
+
invalid_meta.should == { 1=> {@s.name => { 0 => { :duplicate_of=>true }}},
|
|
629
|
+
0=>{@s.name => { 0 => { :duplicates=>[{:client_id=>@c2.id, :key=>"4", :value=>{"name"=>"Android"}}]}}}}
|
|
630
|
+
|
|
631
|
+
@sscud.model.should_receive(:find_duplicates_on_update).once.and_return(invalid_meta)
|
|
632
|
+
@sscud.do_cud
|
|
633
|
+
|
|
634
|
+
verify_source_queue_data(@s, @update_queue_name => [])
|
|
635
|
+
verify_doc_result(@c, :update_errors => {})
|
|
636
|
+
verify_doc_result(@c, :update_rollback => {})
|
|
637
|
+
SampleAdapter.validators.delete(:find_duplicates_on_update)
|
|
638
|
+
end
|
|
639
|
+
|
|
640
|
+
it "should detect update conflict and force an error on duplicate record update" do
|
|
641
|
+
set_doc_state(@c, :cd => {'4'=> {'name' => 'Apple'}})
|
|
642
|
+
set_source_queue_state(@s, {@update_queue_name => [[@s.name, [['4', { 'name' => 'Android' }]]]]},@c.id,true)
|
|
643
|
+
set_source_queue_state(@s, {@update_queue_name => [[@s.name, [['4', { 'name' => 'ErrorName', 'force_duplicate_error' => '1' }]]]]},@c.id,true)
|
|
644
|
+
@sscud.do_cud
|
|
645
|
+
|
|
646
|
+
verify_source_queue_data(@s, @update_queue_name => [])
|
|
647
|
+
verify_doc_result(@c, :update_errors => {"4-error"=>{"message"=>"Error during update: object confict detected"}, "4"=>{"name"=>"ErrorName", 'force_duplicate_error' => '1'}})
|
|
648
|
+
verify_doc_result(@c, :update_rollback => {'4'=> {'name' => 'Apple'}})
|
|
649
|
+
end
|
|
650
|
+
|
|
651
|
+
it "should install find_duplicates_on_update , detect equal objects conflict and raise a custom error" do
|
|
652
|
+
SampleAdapter.enable :find_duplicates_on_update, :raise_error => true do |options, invalid_meta, operation, operation_data, client_ids|
|
|
653
|
+
invalid_meta.each do |index, index_data|
|
|
654
|
+
index_data.each do |source_id, objindex_data|
|
|
655
|
+
objindex_data.each do |objindex, objmeta|
|
|
656
|
+
if objmeta.has_key?(:error)
|
|
657
|
+
objmeta[:error] = "My custom error"
|
|
658
|
+
end
|
|
659
|
+
end if objindex_data
|
|
660
|
+
end if index_data
|
|
661
|
+
end if invalid_meta
|
|
662
|
+
invalid_meta
|
|
663
|
+
end
|
|
664
|
+
set_doc_state(@c, :cd => {'4'=> {'name' => 'Apple'}})
|
|
665
|
+
set_doc_state(@c2, :cd => {'4'=> {'name' => 'Apple'}})
|
|
666
|
+
update_source1 = Source.load(@s.name,
|
|
667
|
+
{:user_id => @u.id,:app_id => @a.id})
|
|
668
|
+
update_source2 = Source.load(@s.name,
|
|
669
|
+
{:user_id => @u2.id,:app_id => @a.id})
|
|
670
|
+
set_source_queue_state(update_source1, {@update_queue_name => [[@s.name, [['4', { 'name' => 'Android' }]]]]},@c.id,true)
|
|
671
|
+
set_source_queue_state(update_source2, {@update_queue_name => [[@s.name, [['4', { 'name' => 'Android' }]]]]},@c2.id, true)
|
|
672
|
+
operation_data,client_ids = update_source2.get_queue(:update)
|
|
673
|
+
invalid_meta = @sscud.model.run_validators(:update,operation_data,client_ids)
|
|
674
|
+
invalid_meta.should == {1=>{@s.name=>{0=>{:error=>"My custom error"}}}}
|
|
675
|
+
|
|
676
|
+
@sscud.do_cud
|
|
677
|
+
verify_source_queue_data(@s, @update_queue_name => [])
|
|
678
|
+
verify_doc_result(@c, :update_errors => {})
|
|
679
|
+
verify_doc_result(@c, :update_rollback => {})
|
|
680
|
+
verify_doc_result(@c2, :update_errors => {"4-error"=>{"message"=>"My custom error"}, "4"=>{"name"=>"Android"}})
|
|
681
|
+
verify_doc_result(@c2, :update_rollback => {'4'=> {'name' => 'Apple'}})
|
|
682
|
+
SampleAdapter.validators.delete(:find_duplicates_on_update)
|
|
683
|
+
end
|
|
684
|
+
|
|
685
|
+
|
|
686
|
+
it "should detect delete conflict and skip the duplicate record delete" do
|
|
687
|
+
set_doc_state(@c, :cd => {'4'=> {'name' => 'Apple'}})
|
|
688
|
+
set_doc_state(@c, :cd_size => 1)
|
|
689
|
+
set_source_queue_state(@s, {@delete_queue_name => [[@s.name, [['4', { 'name' => 'Apple' }]]]]},@c.id,true)
|
|
690
|
+
set_source_queue_state(@s, {@delete_queue_name => [[@s.name, [['4', { 'name' => 'Apple', 'duplicate_of_cid' => @c.id, 'duplicate_of_entry_index' => '0', 'duplicate_of_queue_index' => '0'}]]]]},@c.id,true)
|
|
691
|
+
@sscud.do_cud
|
|
692
|
+
|
|
693
|
+
verify_source_queue_data(@s, @delete_queue_name => [])
|
|
694
|
+
verify_doc_result(@c, :cd => {})
|
|
695
|
+
verify_doc_result(@c, :cd_size => '0')
|
|
696
|
+
verify_doc_result(@c, :delete_errors => {})
|
|
697
|
+
end
|
|
698
|
+
|
|
699
|
+
it "should detect delete conflict and force an error on duplicate record delete" do
|
|
700
|
+
set_doc_state(@c, :cd => {'4'=> {'name' => 'Apple'}})
|
|
701
|
+
set_doc_state(@c, :cd_size => 1)
|
|
702
|
+
set_source_queue_state(@s, {@delete_queue_name => [[@s.name, [['4', { 'name' => 'Apple' }]]]]},@c.id,true)
|
|
703
|
+
set_source_queue_state(@s, {@delete_queue_name => [[@s.name, [['4', { 'name' => 'Apple', 'force_duplicate_error' => '1'}]]]]},@c.id,true)
|
|
704
|
+
@sscud.do_cud
|
|
705
|
+
|
|
706
|
+
verify_source_queue_data(@s, @delete_queue_name => [])
|
|
707
|
+
verify_doc_result(@c, :delete_errors => {"4-error"=>{"message"=>"Error during delete: object confict detected"}, "4"=>{"name"=>"Apple", 'force_duplicate_error' => '1'}})
|
|
708
|
+
end
|
|
709
|
+
end
|
|
710
|
+
|
|
711
|
+
describe "search" do
|
|
712
|
+
before (:each) do
|
|
713
|
+
rh = lambda { @model.search(params[:search]) }
|
|
714
|
+
@sss = Rhoconnect::Handler::Search::Engine.new(@model, @c, rh, {})
|
|
715
|
+
end
|
|
716
|
+
|
|
717
|
+
it "should do search with no exception" do
|
|
718
|
+
verify_read_operation('search')
|
|
719
|
+
end
|
|
720
|
+
|
|
721
|
+
it "should do search with no exception pass through" do
|
|
722
|
+
verify_read_operation_pass_through('search')
|
|
761
723
|
end
|
|
724
|
+
|
|
725
|
+
it "should do search with exception raised" do
|
|
726
|
+
verify_read_operation_with_error('search')
|
|
762
727
|
end
|
|
763
|
-
|
|
764
|
-
|
|
728
|
+
end
|
|
729
|
+
|
|
730
|
+
describe "app-level partitioning" do
|
|
731
|
+
it "should create app-level masterdoc with '__shared__' docname" do
|
|
732
|
+
@s1 = Source.load(@s_fields[:name],@s_params)
|
|
733
|
+
@s1.partition = :app
|
|
734
|
+
rh = lambda { @model.query(params[:query]) }
|
|
735
|
+
@model1 = Rhoconnect::Model::Base.create(@s1)
|
|
736
|
+
@ssq = Rhoconnect::Handler::Query::Engine.new(@model1, rh, {})
|
|
765
737
|
expected = {'1'=>@product1,'2'=>@product2}
|
|
766
|
-
|
|
767
|
-
@
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
738
|
+
set_state('test_db_storage' => expected)
|
|
739
|
+
@ssq.do_sync
|
|
740
|
+
verify_doc_result(@s1, :md => expected)
|
|
741
|
+
Store.get_store(0).keys("read_state:#{test_app_name}:__shared__*").sort.should ==
|
|
742
|
+
[ "read_state:#{test_app_name}:__shared__:SampleAdapter:refresh_time",
|
|
743
|
+
"read_state:#{test_app_name}:__shared__:SampleAdapter:prev_refresh_time",
|
|
744
|
+
"read_state:#{test_app_name}:__shared__:SampleAdapter:rho__id",
|
|
745
|
+
"read_state:#{test_app_name}:__shared__:SampleAdapter:retry_counter"].sort
|
|
746
|
+
end
|
|
747
|
+
end
|
|
748
|
+
|
|
749
|
+
def verify_read_operation(operation)
|
|
750
|
+
expected = {'1'=>@product1,'2'=>@product2}
|
|
751
|
+
set_test_data('test_db_storage',expected)
|
|
752
|
+
@s.put_data(:errors,
|
|
753
|
+
{"#{operation}-error"=>{'message'=>'failed'}},true)
|
|
754
|
+
if operation == 'query'
|
|
755
|
+
@ssq.run_query.should == true
|
|
756
|
+
verify_doc_result(@s, {:md => expected,
|
|
773
757
|
:errors => {}})
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
end
|
|
758
|
+
else
|
|
759
|
+
@sss.run_search.should == true
|
|
760
|
+
verify_doc_result(@c, {:search => expected,
|
|
761
|
+
:search_errors => {}})
|
|
779
762
|
end
|
|
763
|
+
end
|
|
780
764
|
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
:search_errors => {'search-error'=>{'message'=>msg}}})
|
|
796
|
-
end
|
|
765
|
+
def verify_read_operation_pass_through(operation)
|
|
766
|
+
expected = {'1'=>@product1,'2'=>@product2}
|
|
767
|
+
set_test_data('test_db_storage',expected)
|
|
768
|
+
@s.put_data(:errors,
|
|
769
|
+
{"#{operation}-error"=>{'message'=>'failed'}},true)
|
|
770
|
+
@s.pass_through = 'true'
|
|
771
|
+
if operation == 'query'
|
|
772
|
+
@ssq.run_query.should == expected
|
|
773
|
+
verify_doc_result(@s, {:md => {},
|
|
774
|
+
:errors => {}})
|
|
775
|
+
else
|
|
776
|
+
@sss.run_search.should == expected
|
|
777
|
+
verify_doc_result(@c, {:search => {},
|
|
778
|
+
:search_errors => {}})
|
|
797
779
|
end
|
|
780
|
+
end
|
|
798
781
|
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
782
|
+
def verify_read_operation_with_error(operation)
|
|
783
|
+
msg = "Error during #{operation}"
|
|
784
|
+
set_test_data('test_db_storage',{},msg,"#{operation} error")
|
|
785
|
+
if operation == 'query'
|
|
786
|
+
@ssq.should_receive(:log).with("Model raised #{operation} exception: #{msg}")
|
|
787
|
+
@ssq.should_receive(:log).with(anything)
|
|
788
|
+
@ssq.run_query.should == true
|
|
789
|
+
verify_doc_result(@s, {:md => {},
|
|
790
|
+
:errors => {'query-error'=>{'message'=>msg}}})
|
|
791
|
+
else
|
|
792
|
+
@sss.should_receive(:log).with("Model raised #{operation} exception: #{msg}")
|
|
793
|
+
@sss.should_receive(:log).with(anything)
|
|
794
|
+
@sss.run_search.should == true
|
|
795
|
+
verify_doc_result(@c, {:search => {},
|
|
796
|
+
:search_errors => {'search-error'=>{'message'=>msg}}})
|
|
797
|
+
end
|
|
798
|
+
end
|
|
808
799
|
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
800
|
+
describe "Jobs" do
|
|
801
|
+
it "should enqueue process_cud SourceJob" do
|
|
802
|
+
@s.cud_queue = :cud
|
|
803
|
+
rh = lambda { @model.send(params[:operation].to_sym, params["#{params[:operation]}_object".to_sym]) }
|
|
804
|
+
@sscud = Rhoconnect::Handler::Changes::Engine.new(['create', 'update', 'delete'], @model, rh, {})
|
|
805
|
+
@sscud.do_cud
|
|
806
|
+
Resque.peek(:cud).should == {"args"=>
|
|
807
|
+
["cud", @s.name, @a.name, @u.login, nil], "class"=>"Rhoconnect::SourceJob"}
|
|
808
|
+
end
|
|
809
|
+
|
|
810
|
+
it "should enqueue process_query SourceJob" do
|
|
811
|
+
@s.query_queue = :abc
|
|
812
|
+
rh = lambda { @model.query(params[:query]) }
|
|
813
|
+
@ssq = Rhoconnect::Handler::Query::Engine.new(@model, rh, { :query => {'foo'=>'bar'} })
|
|
814
|
+
@ssq.do_sync
|
|
815
|
+
Resque.peek(:abc).should == {"args"=>
|
|
816
|
+
["query", @s.name, @a.name, @u.login, {'foo'=>'bar'}], "class"=>"Rhoconnect::SourceJob"}
|
|
817
817
|
end
|
|
818
818
|
end
|
|
819
819
|
end
|