rhoconnect 3.4.5 → 4.0.0.beta.10
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.md +57 -3
- data/Gemfile +9 -7
- data/Gemfile.lock +37 -37
- data/Rakefile +18 -7
- data/bench/benchapp/Gemfile +1 -1
- data/bench/benchapp/config.ru +0 -3
- data/bench/benchapp/controllers/ruby/application.rb +17 -0
- data/bench/benchapp/controllers/ruby/application_controller.rb +17 -0
- data/bench/benchapp/controllers/ruby/mock_adapter_controller.rb +8 -0
- data/bench/benchapp/controllers/ruby/queue_mock_adapter_controller.rb +8 -0
- data/bench/benchapp/{sources → models/ruby}/mock_adapter.rb +1 -1
- data/bench/benchapp/{sources → models/ruby}/queue_mock_adapter.rb +0 -0
- data/bench/benchapp/spec/{sources → models/ruby}/mock_adapter_spec.rb +1 -1
- data/bench/benchapp/spec/{sources → models/ruby}/queue_mock_adapter_spec.rb +1 -1
- data/bench/benchapp/spec/spec_helper.rb +2 -2
- data/bench/blobapp/Gemfile +1 -1
- data/bench/blobapp/config.ru +0 -3
- data/bench/blobapp/controllers/ruby/application_controller.rb +17 -0
- data/bench/blobapp/controllers/ruby/blob_adapter_controller.rb +8 -0
- data/bench/blobapp/{sources → models/ruby}/blob_adapter.rb +9 -2
- data/bench/blobapp/spec/{sources → models/ruby}/blob_adapter_spec.rb +1 -1
- data/bench/blobapp/spec/spec_helper.rb +1 -1
- data/bench/lib/bench/cli.rb +1 -1
- data/bench/scripts/blob_cud_script.rb +1 -1
- data/bench/scripts/query_md_script.rb +1 -1
- data/bench/scripts/query_only_script.rb +1 -1
- data/bench/scripts/query_script.rb +1 -1
- data/bench/scripts/test_query_script.rb +7 -1
- data/bench/spec/mock_adapter_spec.rb +1 -1
- data/bench/spec/result_spec.rb +3 -3
- data/bin/rhoconnect +5 -3
- data/commands/dtach/dtach_install.rb +2 -2
- data/commands/execute.rb +8 -3
- data/commands/generators/app.rb +3 -3
- data/commands/generators/controller.rb +6 -0
- data/commands/generators/model.rb +6 -0
- data/commands/generators/source.rb +3 -3
- data/commands/generators/update.rb +1 -1
- data/commands/redis/redis_about.rb +2 -2
- data/commands/redis/redis_download.rb +1 -1
- data/commands/redis/redis_install.rb +4 -3
- data/commands/redis/redis_restart.rb +4 -4
- data/commands/redis/redis_start.rb +5 -4
- data/commands/redis/redis_startbg.rb +5 -4
- data/commands/redis/redis_status.rb +13 -0
- data/commands/redis/redis_stop.rb +3 -3
- data/commands/rhoconnect/config.rb +28 -16
- data/commands/rhoconnect/flushdb.rb +1 -2
- data/commands/rhoconnect/get_token.rb +15 -11
- data/commands/rhoconnect/restart.rb +13 -5
- data/commands/rhoconnect/set_admin_password.rb +8 -8
- data/commands/rhoconnect/start.rb +74 -16
- data/commands/rhoconnect/startbg.rb +1 -1
- data/commands/rhoconnect/startdebug.rb +1 -1
- data/commands/rhoconnect/stop.rb +13 -1
- data/commands/rhoconnect/web.rb +5 -5
- data/commands/rhoconnect_console/console.rb +7 -5
- data/commands/{rhoconnect → rhoconnect_spec}/spec.rb +0 -0
- data/commands/rhoconnect_war/war.rb +9 -9
- data/commands/utilities/blank_app.ru +56 -0
- data/commands/utilities/redis_runner.rb +54 -19
- data/doc/authentication.txt +80 -6
- data/doc/blob-sync.txt +104 -97
- data/doc/bulk-sync.txt +1 -1
- data/doc/client-java.txt +3 -3
- data/doc/client-objc.txt +2 -2
- data/doc/client.txt +4 -4
- data/doc/command-line.txt +105 -200
- data/doc/data-partitioning.txt +40 -0
- data/doc/deploying.txt +249 -77
- data/doc/extending-rhoconnect-server.txt +40 -57
- data/doc/heroku-addon.txt +2 -0
- data/doc/install.txt +45 -95
- data/doc/introduction.txt +1 -1
- data/doc/java-plugin.txt +365 -190
- data/doc/metadata.txt +1 -1
- data/doc/migration.txt +108 -142
- data/doc/preparing-production.txt +1 -1
- data/doc/push-backend-setup.txt +2 -0
- data/doc/push-client-setup-android.txt +78 -0
- data/doc/push-client-setup-bb.txt +81 -0
- data/doc/push-client-setup-ios.txt +70 -0
- data/doc/push-client-setup-rps.txt +200 -0
- data/doc/push-client-setup.txt +63 -66
- data/doc/push-server-setup.txt +67 -40
- data/doc/push-testing.txt +29 -0
- data/doc/push.txt +21 -6
- data/doc/rest-api.txt +128 -55
- data/doc/rhoconnect-redis-stack.txt +120 -0
- data/doc/settings.txt +4 -12
- data/doc/source-adapters-intro.txt +28 -0
- data/doc/source-adapters.txt +235 -272
- data/doc/stats-middleware.txt +9 -29
- data/doc/supported-platforms.txt +21 -30
- data/doc/testing.txt +40 -42
- data/doc/tutorial.txt +72 -57
- data/examples/simple/Gemfile +1 -1
- data/examples/simple/application.rb +4 -5
- data/examples/simple/my_server.rb +2 -2
- data/examples/simple/settings/settings.yml +1 -1
- data/generators/rhoconnect.rb +151 -50
- data/generators/templates/application/Gemfile +1 -1
- data/generators/templates/application/Rakefile +3 -3
- data/generators/templates/application/config.ru +1 -4
- data/generators/templates/application/controllers/application_controller.rb +17 -0
- data/generators/templates/application/controllers/js/application_controller.js +14 -0
- data/generators/templates/application/controllers/ruby/application_controller.rb +17 -0
- data/generators/templates/application/package.json +8 -0
- data/generators/templates/application/rcgemfile +2 -5
- data/generators/templates/application/settings/settings.yml +3 -3
- data/generators/templates/application/spec/application_controller_spec.rb +23 -0
- data/generators/templates/application/spec/js_spec.rb +25 -0
- data/generators/templates/application/spec/spec_helper.rb +21 -7
- data/generators/templates/source/controllers/js/controller.js +7 -0
- data/generators/templates/source/controllers/ruby/controller.rb +8 -0
- data/generators/templates/source/controllers/ruby/controller_spec.rb +27 -0
- data/generators/templates/source/models/js/model.js +46 -0
- data/generators/templates/source/{source_adapter.rb → models/ruby/model.rb} +15 -10
- data/generators/templates/source/{source_spec.rb → models/ruby/model_spec.rb} +1 -1
- data/install.sh +5 -5
- data/installer/unix-like/create_texts.rb +2 -2
- data/installer/unix-like/rho_connect_install_constants.rb +2 -2
- data/installer/unix-like/rho_connect_install_utilities.rb +1 -1
- data/installer/utils/constants.rb +4 -4
- data/js-adapters/ballroom.js +216 -0
- data/js-adapters/node.rb +52 -0
- data/js-adapters/node_channel.rb +181 -0
- data/js-adapters/request.js +27 -0
- data/js-adapters/response.js +57 -0
- data/js-adapters/rhoconnect_helpers.js +60 -0
- data/js-adapters/router.js +60 -0
- data/js-adapters/server.js +5 -0
- data/lib/rhoconnect/api/app/ans_login.rb +3 -3
- data/lib/rhoconnect/api/app/bulk_data.rb +10 -10
- data/lib/rhoconnect/api/app/fast_delete.rb +11 -10
- data/lib/rhoconnect/api/app/fast_insert.rb +11 -10
- data/lib/rhoconnect/api/app/fast_update.rb +11 -10
- data/lib/rhoconnect/api/app/login.rb +5 -5
- data/lib/rhoconnect/api/app/push_deletes.rb +12 -11
- data/lib/rhoconnect/api/app/push_objects.rb +12 -11
- data/lib/rhoconnect/api/app/query.rb +8 -7
- data/lib/rhoconnect/api/app/queue_updates.rb +98 -94
- data/lib/rhoconnect/api/app/search.rb +8 -7
- data/lib/rhoconnect/api/client/client_get_db_doc.rb +5 -5
- data/lib/rhoconnect/api/client/client_set_db_doc.rb +8 -8
- data/lib/rhoconnect/api/client/create.rb +7 -7
- data/lib/rhoconnect/api/client/get_client_params.rb +4 -4
- data/lib/rhoconnect/api/client/list_client_docs.rb +17 -17
- data/lib/rhoconnect/api/client/register.rb +12 -12
- data/lib/rhoconnect/api/client/reset.rb +5 -5
- data/lib/rhoconnect/api/readstate/set_refresh_time.rb +9 -9
- data/lib/rhoconnect/api/source/get_source_params.rb +4 -4
- data/lib/rhoconnect/api/source/list_sources.rb +16 -16
- data/lib/rhoconnect/api/source/update_source_params.rb +6 -6
- data/lib/rhoconnect/api/store/get_db_doc.rb +4 -4
- data/lib/rhoconnect/api/store/set_db_doc.rb +7 -7
- data/lib/rhoconnect/api/system/get_adapter.rb +4 -4
- data/lib/rhoconnect/api/system/get_license_info.rb +8 -8
- data/lib/rhoconnect/api/system/login.rb +15 -15
- data/lib/rhoconnect/api/system/reset.rb +11 -11
- data/lib/rhoconnect/api/system/save_adapter.rb +4 -4
- data/lib/rhoconnect/api/system/stats.rb +22 -22
- data/lib/rhoconnect/api/user/create_user.rb +7 -7
- data/lib/rhoconnect/api/user/delete_client.rb +6 -6
- data/lib/rhoconnect/api/user/delete_user.rb +11 -10
- data/lib/rhoconnect/api/user/list_clients.rb +4 -4
- data/lib/rhoconnect/api/user/list_source_docs.rb +10 -10
- data/lib/rhoconnect/api/user/list_users.rb +3 -3
- data/lib/rhoconnect/api/user/ping.rb +3 -3
- data/lib/rhoconnect/api/user/show_user.rb +3 -3
- data/lib/rhoconnect/api/user/update_user.rb +5 -5
- data/lib/rhoconnect/api/user/user_get_db_doc.rb +5 -5
- data/lib/rhoconnect/api/user/user_set_db_doc.rb +10 -10
- data/lib/rhoconnect/api_token.rb +5 -6
- data/lib/rhoconnect/app.rb +6 -46
- data/lib/rhoconnect/application/init.rb +5 -2
- data/lib/rhoconnect/async.rb +76 -39
- data/lib/rhoconnect/bulk_data/bulk_data.rb +6 -4
- data/lib/rhoconnect/client.rb +59 -9
- data/lib/rhoconnect/condition/admin_required.rb +27 -0
- data/lib/rhoconnect/condition/client_required.rb +50 -0
- data/lib/rhoconnect/condition/login_required.rb +22 -0
- data/lib/rhoconnect/condition/source_required.rb +49 -0
- data/lib/rhoconnect/condition/verbs.rb +17 -0
- data/lib/rhoconnect/condition/verify_success.rb +19 -0
- data/lib/rhoconnect/controller/app_base.rb +74 -0
- data/lib/rhoconnect/controller/base.rb +68 -0
- data/lib/rhoconnect/controller/clients_controller.rb +79 -0
- data/lib/rhoconnect/controller/dynamic_adapter_controller.rb +93 -0
- data/lib/rhoconnect/controller/js_base.rb +124 -0
- data/lib/rhoconnect/controller/read_state_controller.rb +22 -0
- data/lib/rhoconnect/controller/source_adapter_base.rb +14 -0
- data/lib/rhoconnect/controller/sources_controller.rb +44 -0
- data/lib/rhoconnect/controller/store_controller.rb +25 -0
- data/lib/rhoconnect/controller/system_controller.rb +67 -0
- data/lib/rhoconnect/controller/users_controller.rb +99 -0
- data/lib/rhoconnect/db_adapter.rb +1 -3
- data/lib/rhoconnect/document.rb +159 -50
- data/lib/rhoconnect/handler/authenticate/execute_methods.rb +77 -0
- data/lib/rhoconnect/handler/authenticate/runner.rb +49 -0
- data/lib/rhoconnect/handler/authenticate.rb +3 -0
- data/lib/rhoconnect/handler/bulk_data.rb +28 -0
- data/lib/rhoconnect/handler/changes/engine.rb +271 -0
- data/lib/rhoconnect/handler/changes/execute_methods.rb +88 -0
- data/lib/rhoconnect/handler/changes/pass_through_runner.rb +11 -0
- data/lib/rhoconnect/handler/changes/runner.rb +53 -0
- data/lib/rhoconnect/handler/changes.rb +31 -0
- data/lib/rhoconnect/handler/helpers/auth_method.rb +29 -0
- data/lib/rhoconnect/handler/helpers/binding.rb +18 -0
- data/lib/rhoconnect/handler/helpers/bulk_data.rb +53 -0
- data/lib/rhoconnect/handler/helpers/source_job.rb +14 -0
- data/lib/rhoconnect/handler/helpers.rb +4 -0
- data/lib/rhoconnect/handler/plugin_callbacks/execute_methods.rb +99 -0
- data/lib/rhoconnect/handler/plugin_callbacks/runner.rb +28 -0
- data/lib/rhoconnect/handler/plugin_callbacks.rb +67 -0
- data/lib/rhoconnect/handler/query/engine.rb +93 -0
- data/lib/rhoconnect/handler/query/execute_methods.rb +21 -0
- data/lib/rhoconnect/handler/query/pass_through_runner.rb +35 -0
- data/lib/rhoconnect/handler/query/runner.rb +270 -0
- data/lib/rhoconnect/handler/query.rb +19 -0
- data/lib/rhoconnect/handler/search/engine.rb +60 -0
- data/lib/rhoconnect/handler/search/execute_methods.rb +32 -0
- data/lib/rhoconnect/handler/search/pass_through_runner.rb +18 -0
- data/lib/rhoconnect/handler/search/runner.rb +104 -0
- data/lib/rhoconnect/handler/search.rb +26 -0
- data/lib/rhoconnect/handler/sync.rb +29 -0
- data/lib/rhoconnect/jobs/source_job.rb +13 -4
- data/lib/rhoconnect/js_adapter.rb +79 -0
- data/lib/rhoconnect/license.rb +10 -2
- data/lib/rhoconnect/middleware/current_user.rb +14 -1
- data/lib/rhoconnect/middleware/helpers.rb +10 -93
- data/lib/rhoconnect/middleware/x_domain_session_wrapper.rb +1 -1
- data/lib/rhoconnect/model/base.rb +229 -0
- data/lib/rhoconnect/model/dynamic_adapter_model.rb +90 -0
- data/lib/rhoconnect/model/js_base.rb +121 -0
- data/lib/rhoconnect/ping/android.rb +1 -1
- data/lib/rhoconnect/predefined_adapters/bench_adapter.rb +7 -4
- data/lib/rhoconnect/read_state.rb +3 -3
- data/lib/rhoconnect/server.rb +159 -190
- data/lib/rhoconnect/source.rb +100 -11
- data/lib/rhoconnect/stats/record.rb +10 -10
- data/lib/rhoconnect/store.rb +905 -591
- data/lib/rhoconnect/{model.rb → store_orm.rb} +53 -115
- data/lib/rhoconnect/tasks.rb +18 -4
- data/lib/rhoconnect/test_methods.rb +30 -17
- data/lib/rhoconnect/user.rb +35 -17
- data/lib/rhoconnect/utilities.rb +1 -1
- data/lib/rhoconnect/version.rb +2 -2
- data/lib/rhoconnect/web-console/server.rb +29 -14
- data/lib/rhoconnect/web-console/views/home.js +10 -10
- data/lib/rhoconnect/web-console/views/new_ping.js +1 -1
- data/lib/rhoconnect.rb +120 -51
- data/rhoconnect.gemspec +4 -3
- data/spec/api/api_helper.rb +1 -6
- data/spec/api/app/fast_delete_spec.rb +4 -4
- data/spec/api/app/fast_insert_spec.rb +4 -4
- data/spec/api/app/fast_update_spec.rb +8 -8
- data/spec/api/app/push_deletes_spec.rb +2 -2
- data/spec/api/app/push_objects_spec.rb +5 -5
- data/spec/api/client/client_get_db_doc_spec.rb +6 -4
- data/spec/api/client/client_set_db_doc_spec.rb +3 -2
- data/spec/api/client/get_client_params_spec.rb +14 -0
- data/spec/api/client/list_client_docs_spec.rb +30 -20
- data/spec/api/client/reset_spec.rb +36 -0
- data/spec/api/source/get_source_params_spec.rb +23 -17
- data/spec/api/system/get_license_info_spec.rb +0 -20
- data/spec/api/system/login_spec.rb +8 -0
- data/spec/api/system/reset_spec.rb +0 -1
- data/spec/api/system/stats_spec.rb +5 -5
- data/spec/api/user/create_user_spec.rb +14 -6
- data/spec/api/user/delete_user_spec.rb +20 -18
- data/spec/api/user/list_users_spec.rb +5 -6
- data/spec/api/user/update_user_spec.rb +5 -4
- data/spec/apps/rhotestapp/config.ru +16 -1
- data/spec/apps/rhotestapp/controllers/js/js_sample_controller.js +23 -0
- data/spec/apps/rhotestapp/controllers/js/sample2_controller.js +32 -0
- data/spec/apps/rhotestapp/controllers/ruby/application_controller.rb +21 -0
- data/spec/apps/rhotestapp/controllers/ruby/sample_adapter_controller.rb +8 -0
- data/spec/apps/rhotestapp/models/js/js_sample.js +55 -0
- data/spec/apps/rhotestapp/models/js/sample2.js +25 -0
- data/spec/apps/rhotestapp/{sources → models/ruby}/base_adapter.rb +0 -0
- data/spec/apps/rhotestapp/{sources → models/ruby}/fixed_schema_adapter.rb +0 -0
- data/spec/apps/rhotestapp/{sources → models/ruby}/other_adapter.rb +0 -0
- data/spec/apps/rhotestapp/{sources → models/ruby}/sample_adapter.rb +0 -0
- data/spec/apps/rhotestapp/{sources → models/ruby}/simple_adapter.rb +2 -2
- data/spec/apps/rhotestapp/{sources → models/ruby}/sub_adapter.rb +0 -0
- data/spec/apps/rhotestapp/settings/settings.yml +0 -1
- data/spec/bulk_data/bulk_data_spec.rb +20 -5
- data/spec/cli/cli_spec.rb +83 -0
- data/spec/client_spec.rb +20 -17
- data/spec/client_sync_spec.rb +244 -406
- data/spec/controllers/js_base_spec.rb +89 -0
- data/spec/doc/doc_spec.rb +18 -18
- data/spec/document_spec.rb +29 -13
- data/spec/dynamic_adapter_spec.rb +6 -6
- data/spec/generator/generator_spec.rb +7 -4
- data/spec/jobs/bulk_data_job_spec.rb +14 -10
- data/spec/jobs/source_job_spec.rb +8 -8
- data/spec/license_spec.rb +5 -2
- data/spec/models/js_model_spec.rb +39 -0
- data/spec/node_spec.rb +42 -0
- data/spec/perf/store_perf_spec.rb +67 -12
- data/spec/ping/android_spec.rb +1 -1
- data/spec/read_state_spec.rb +1 -1
- data/spec/rhoconnect_spec.rb +1 -1
- data/spec/server/cors_spec.rb +14 -18
- data/spec/server/server_spec.rb +265 -88
- data/spec/server/stats_spec.rb +1 -1
- data/spec/source_adapter_spec.rb +54 -27
- data/spec/source_spec.rb +8 -3
- data/spec/source_sync_spec.rb +538 -468
- data/spec/spec_helper.rb +35 -4
- data/spec/stats/record_spec.rb +10 -10
- data/spec/{model_spec.rb → store_orm_spec.rb} +56 -54
- data/spec/store_spec.rb +159 -179
- data/spec/support/shared_examples.rb +36 -27
- data/spec/sync_states_spec.rb +40 -33
- data/spec/test_methods_spec.rb +18 -14
- data/spec/user_spec.rb +17 -30
- metadata +156 -52
- data/bench/benchapp/application.rb +0 -39
- data/bench/blobapp/application.rb +0 -44
- data/commands/rhoconnect/clean_start.rb +0 -9
- data/commands/rhoconnect/create_user.rb +0 -18
- data/commands/rhoconnect/delete_device.rb +0 -9
- data/commands/rhoconnect/delete_user.rb +0 -8
- data/commands/rhoconnect/reset.rb +0 -16
- data/commands/rhoconnect/reset_refresh.rb +0 -11
- data/generators/templates/application/application.rb +0 -43
- data/lib/rhoconnect/client_sync.rb +0 -434
- data/lib/rhoconnect/dynamic_adapter.rb +0 -91
- data/lib/rhoconnect/middleware/admin_user.rb +0 -23
- data/lib/rhoconnect/middleware/current_request.rb +0 -16
- data/lib/rhoconnect/middleware/login_required.rb +0 -22
- data/lib/rhoconnect/source_adapter.rb +0 -132
- data/lib/rhoconnect/source_sync.rb +0 -464
- data/spec/apps/rhotestapp/application.rb +0 -23
data/spec/source_sync_spec.rb
CHANGED
|
@@ -4,558 +4,628 @@ describe "SourceSync" do
|
|
|
4
4
|
it_behaves_like "SharedRhoconnectHelper", :rhoconnect_data => true do
|
|
5
5
|
before(:each) do
|
|
6
6
|
@s = Source.load(@s_fields[:name],@s_params)
|
|
7
|
-
@
|
|
7
|
+
@model = Rhoconnect::Model::Base.create(@s)
|
|
8
8
|
end
|
|
9
9
|
|
|
10
10
|
let(:mock_schema) { {"property" => { "name" => "string", "brand" => "string" }, "version" => "1.0"} }
|
|
11
11
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
12
|
+
describe "SourceSync query methods" do
|
|
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
|
|
15
18
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
+
it "should create Rhoconnect::Handler::Query::Engine" do
|
|
20
|
+
@ssq.model.is_a?(SampleAdapter).should == true
|
|
21
|
+
end
|
|
19
22
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
@ss = SourceSync.new(@s)
|
|
24
|
-
@ss.should_receive(:log).with("SourceAdapter raised login exception: #{msg}")
|
|
25
|
-
@ss.should_receive(:log).with(anything)
|
|
26
|
-
@ss.process_query
|
|
27
|
-
verify_result(@s.docname(:errors) => {'login-error'=>{'message'=>msg}})
|
|
28
|
-
end
|
|
23
|
+
it "should fail to create Rhoconnect::Handler::Query::Engine with InvalidArgumentError without source" do
|
|
24
|
+
lambda { Rhoconnect::Handler::Query::Engine.new(nil, nil, {}) }.should raise_error(ArgumentError, 'Unknown source')
|
|
25
|
+
end
|
|
29
26
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
@ss.should_receive(:log).with(anything)
|
|
34
|
-
set_test_data('test_db_storage',{},msg,'logoff error')
|
|
35
|
-
@ss.process_query
|
|
36
|
-
verify_result(@s.docname(:errors) => {'logoff-error'=>{'message'=>msg}})
|
|
37
|
-
end
|
|
27
|
+
it "should fail to create Rhoconnect::Handler::Query::Engine with InvalidArgumentError without proc handler" do
|
|
28
|
+
lambda { Rhoconnect::Handler::Query::Engine.new(@model, nil) }.should raise_error(ArgumentError, 'Invalid sync handler')
|
|
29
|
+
end
|
|
38
30
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
31
|
+
it "should raise LoginException if login fails" do
|
|
32
|
+
msg = "Error logging in"
|
|
33
|
+
@u.login = nil
|
|
34
|
+
@ssq.should_receive(:log).with("Model raised login exception: #{msg}")
|
|
35
|
+
@ssq.should_receive(:log).with(anything)
|
|
36
|
+
@ssq.do_sync
|
|
37
|
+
verify_doc_result(@s, :errors => {'login-error'=>{'message'=>msg}})
|
|
38
|
+
end
|
|
47
39
|
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
end
|
|
40
|
+
it "should raise LogoffException if logoff fails" do
|
|
41
|
+
msg = "Error logging off"
|
|
42
|
+
@ssq.should_receive(:log).with("Model raised logoff exception: #{msg}")
|
|
43
|
+
@ssq.should_receive(:log).with(anything)
|
|
44
|
+
set_test_data('test_db_storage',{},msg,'logoff error')
|
|
45
|
+
@ssq.do_sync
|
|
46
|
+
verify_doc_result(@s, :errors => {'logoff-error'=>{'message'=>msg}})
|
|
47
|
+
end
|
|
57
48
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
49
|
+
it "should hold on read on subsequent call of process if default poll interval is not exprired" do
|
|
50
|
+
expected = {'1'=>@product1}
|
|
51
|
+
set_state('test_db_storage' => expected)
|
|
52
|
+
@ssq.do_sync
|
|
53
|
+
set_state('test_db_storage' => {'2'=>@product2})
|
|
54
|
+
@ssq.do_sync
|
|
55
|
+
verify_doc_result(@s, :md => expected)
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
it "should read on every subsequent call of process if poll interval is set to 0" do
|
|
59
|
+
expected = {'2'=>@product2}
|
|
60
|
+
@s.poll_interval = 0
|
|
61
|
+
set_state('test_db_storage' => {'1'=>@product1})
|
|
62
|
+
@ssq.do_sync
|
|
63
|
+
set_state('test_db_storage' => expected)
|
|
64
|
+
@ssq.do_sync
|
|
65
|
+
verify_doc_result(@s, :md => expected)
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
it "should never call read on any call of process if poll interval is set to -1" do
|
|
69
|
+
@s.poll_interval = -1
|
|
70
|
+
set_state('test_db_storage' => {'1'=>@product1})
|
|
71
|
+
@ssq.do_sync
|
|
72
|
+
verify_doc_result(@s, :md => {})
|
|
73
|
+
end
|
|
64
74
|
|
|
65
|
-
describe "methods" do
|
|
66
75
|
|
|
67
|
-
it "should process
|
|
76
|
+
it "should process model metadata" do
|
|
68
77
|
mock_metadata_method([SampleAdapter, SimpleAdapter]) do
|
|
69
78
|
expected = {'1'=>@product1,'2'=>@product2}
|
|
70
79
|
set_state('test_db_storage' => expected)
|
|
71
|
-
@
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
80
|
+
@ssq.do_sync
|
|
81
|
+
verify_doc_result(@s, {:md => expected,
|
|
82
|
+
:metadata => "{\"foo\":\"bar\"}",
|
|
83
|
+
:metadata_sha1 => "a5e744d0164540d33b1d7ea616c28f2fa97e754a"})
|
|
75
84
|
end
|
|
76
85
|
end
|
|
77
86
|
|
|
78
|
-
it "should process
|
|
87
|
+
it "should process model schema" do
|
|
79
88
|
mock_schema_method([SampleAdapter]) do
|
|
80
89
|
expected = {'1'=>@product1,'2'=>@product2}
|
|
81
90
|
set_state('test_db_storage' => expected)
|
|
82
|
-
@
|
|
83
|
-
|
|
84
|
-
JSON.parse(
|
|
85
|
-
|
|
91
|
+
@ssq.do_sync
|
|
92
|
+
verify_doc_result(@s, :md => expected)
|
|
93
|
+
JSON.parse(@s.get_value(:schema)).should == mock_schema
|
|
94
|
+
@s.get_value(:schema_sha1).should == get_sha1(mock_schema['version'])
|
|
86
95
|
end
|
|
87
96
|
end
|
|
88
97
|
|
|
89
|
-
it "should raise exception if
|
|
98
|
+
it "should raise exception if model schema has no version key/value pair" do
|
|
90
99
|
mock_schema_no_version_method([SampleAdapter]) do
|
|
91
100
|
expected = {'1'=>@product1,'2'=>@product2}
|
|
92
101
|
set_state('test_db_storage' => expected)
|
|
93
|
-
@
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
errors["query-error"]["message"].should == "Mandatory version key is not defined in source adapter schema method"
|
|
102
|
+
@ssq.do_sync
|
|
103
|
+
errors = {}
|
|
104
|
+
@s.lock(:errors) { errors = @s.get_data(:errors) }
|
|
105
|
+
errors.empty?().should == false
|
|
106
|
+
errors["query-error"]["message"].should == "Mandatory version key is not defined in model schema method"
|
|
99
107
|
end
|
|
100
108
|
end
|
|
101
109
|
|
|
102
|
-
it "should process
|
|
110
|
+
it "should process model with stash" do
|
|
103
111
|
expected = {'1'=>@product1,'2'=>@product2}
|
|
104
112
|
set_state('test_db_storage' => expected)
|
|
105
|
-
|
|
106
|
-
@
|
|
107
|
-
|
|
108
|
-
|
|
113
|
+
@ssq.params[:query] = {'stash_result' => true}
|
|
114
|
+
@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})
|
|
109
118
|
end
|
|
110
119
|
|
|
111
|
-
it "should process
|
|
120
|
+
it "should process model with pass_through set" do
|
|
112
121
|
expected = {'1'=>@product1,'2'=>@product2}
|
|
113
122
|
set_state('test_db_storage' => expected)
|
|
114
123
|
@s.pass_through = 'true'
|
|
115
|
-
@
|
|
116
|
-
|
|
117
|
-
|
|
124
|
+
@ssq.do_sync.should == expected
|
|
125
|
+
verify_doc_result(@s, {:md => {},
|
|
126
|
+
:md_size => nil})
|
|
118
127
|
@s.pass_through = nil
|
|
119
128
|
end
|
|
120
129
|
|
|
121
|
-
it "should call methods in
|
|
130
|
+
it "should call methods in model" do
|
|
122
131
|
mock_metadata_method([SampleAdapter, SimpleAdapter]) do
|
|
123
132
|
expected = {'1'=>@product1,'2'=>@product2}
|
|
124
133
|
metadata = "{\"foo\":\"bar\"}"
|
|
125
|
-
@
|
|
126
|
-
@
|
|
127
|
-
@
|
|
128
|
-
@
|
|
129
|
-
@
|
|
130
|
-
@
|
|
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
|
|
131
140
|
end
|
|
132
141
|
end
|
|
142
|
+
|
|
143
|
+
it "should do query with no exception" do
|
|
144
|
+
verify_read_operation('query')
|
|
145
|
+
end
|
|
133
146
|
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
@s.push_notify = 'true'
|
|
137
|
-
data = {'1' => @product1, '2' => @product2, '3' => @product3}
|
|
138
|
-
params = {'user_id'=>["testuser"], 'sources'=>["SampleAdapter"]}
|
|
139
|
-
PingJob.should_receive(:perform).once.with(params)
|
|
140
|
-
@ss.push_objects(data)
|
|
141
|
-
end
|
|
142
|
-
|
|
143
|
-
it "should do push_notify for source after push_deletes if enabled" do
|
|
144
|
-
@s.push_notify = 'true'
|
|
145
|
-
u2 = User.create(:login => 'user2')
|
|
146
|
-
@a.users << u2.id
|
|
147
|
-
data = {'1' => @product1, '2' => @product2, '3' => @product3}
|
|
148
|
-
params = {'user_id'=>["testuser"], 'sources'=>["SampleAdapter"]}
|
|
149
|
-
PingJob.should_receive(:perform).once.with(params)
|
|
150
|
-
@ss.push_deletes(data)
|
|
151
|
-
end
|
|
152
|
-
|
|
153
|
-
it "should not do push_notify for source by default" do
|
|
154
|
-
@s.partition = :app
|
|
155
|
-
u2 = User.create(:login => 'user2')
|
|
156
|
-
@a.users << u2.id
|
|
157
|
-
data = {'1' => @product1}
|
|
158
|
-
PingJob.should_receive(:perform).never
|
|
159
|
-
@ss.fast_delete(data)
|
|
160
|
-
end
|
|
147
|
+
it "should do query with no exception pass through" do
|
|
148
|
+
verify_read_operation_pass_through('query')
|
|
161
149
|
end
|
|
162
150
|
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
151
|
+
it "should do query with exception raised" do
|
|
152
|
+
verify_read_operation_with_error('query')
|
|
153
|
+
end
|
|
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}}})
|
|
171
|
+
|
|
172
|
+
# 2) if retry_limit is set to N and number of retries exceeded it - update refresh_time
|
|
173
|
+
@s.read_state.retry_counter.should == 0
|
|
174
|
+
@s.read_state.refresh_time.should > Time.now.to_i
|
|
175
|
+
end
|
|
171
176
|
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
177
|
+
it "should do query with exception raised and restore state with succesfull retry" do
|
|
178
|
+
@s.retry_limit = 1
|
|
179
|
+
msg = "Error during query"
|
|
180
|
+
set_test_data('test_db_storage',{},msg,"query error")
|
|
181
|
+
res = @ssq.do_sync
|
|
182
|
+
verify_doc_result(@s, {:md => {},
|
|
183
|
+
:errors => {'query-error'=>{'message'=>msg}}})
|
|
184
|
+
# 1) if retry_limit is set to N - then, first N retries should not update refresh_time
|
|
185
|
+
@s.read_state.retry_counter.should == 1
|
|
186
|
+
@s.read_state.refresh_time.should <= Time.now.to_i
|
|
187
|
+
|
|
188
|
+
# try once more (with success)
|
|
189
|
+
expected = {'1'=>@product1,'2'=>@product2}
|
|
190
|
+
set_test_data('test_db_storage',expected)
|
|
191
|
+
@ssq.do_sync
|
|
192
|
+
verify_doc_result(@s, {:md => expected,
|
|
193
|
+
:errors => {}})
|
|
194
|
+
@s.read_state.retry_counter.should == 0
|
|
195
|
+
@s.read_state.refresh_time.should > Time.now.to_i
|
|
196
|
+
end
|
|
180
197
|
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
198
|
+
it "should reset the retry counter if prev_refresh_time was set more than poll_interval secs ago" do
|
|
199
|
+
@s.retry_limit = 3
|
|
200
|
+
@s.poll_interval = 2
|
|
201
|
+
msg = "Error during query"
|
|
202
|
+
set_test_data('test_db_storage',{},msg,"query error")
|
|
203
|
+
res = @ssq.do_sync
|
|
204
|
+
verify_doc_result(@s, {:md => {},
|
|
205
|
+
:errors => {'query-error'=>{'message'=>msg}}})
|
|
206
|
+
# 1) if retry_limit is set to N - then, first N retries should not update refresh_time
|
|
207
|
+
@s.read_state.retry_counter.should == 1
|
|
208
|
+
@s.read_state.refresh_time.should <= Time.now.to_i
|
|
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
|
|
189
240
|
end
|
|
190
241
|
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
242
|
+
it "should do query with exception raised and update refresh time if poll_interval == 0" do
|
|
243
|
+
@s.retry_limit = 1
|
|
244
|
+
@s.poll_interval = 0
|
|
245
|
+
msg = "Error during query"
|
|
246
|
+
set_test_data('test_db_storage',{},msg,"query error")
|
|
247
|
+
prev_refresh_time = @s.read_state.refresh_time
|
|
248
|
+
# make sure refresh time is expired
|
|
249
|
+
sleep(1)
|
|
250
|
+
res = @ssq.do_sync
|
|
251
|
+
verify_doc_result(@s, {:md => {},
|
|
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
|
|
257
|
+
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
|
|
198
291
|
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
# Should we disable tesing of them then?
|
|
209
|
-
unless client_ids.empty?
|
|
210
|
-
update_data.should == [{'4'=> { 'price' => '199.99'}}]
|
|
211
|
-
client_ids.should == [@c.id]
|
|
212
|
-
end
|
|
213
|
-
verify_result(
|
|
214
|
-
@c.docname(:update_errors) =>
|
|
215
|
-
{"#{ERROR}-error"=>{"message"=>msg}, ERROR=>data[ERROR]},
|
|
216
|
-
@c.docname(:update_rollback) => {ERROR=>{"price"=>"99.99"}})
|
|
217
|
-
end
|
|
292
|
+
it "should not do push_notify for app source" do
|
|
293
|
+
@s.partition = :app
|
|
294
|
+
u2 = User.create(:login => 'user2')
|
|
295
|
+
@a.users << u2.id
|
|
296
|
+
data = {'1' => @product1}
|
|
297
|
+
PingJob.should_receive(:perform).never
|
|
298
|
+
po_handler = lambda { @model.push_objects(params) }
|
|
299
|
+
push_objects_handler = Rhoconnect::Handler::PluginCallbacks::Runner.new(po_handler, @model, {'objects' => data})
|
|
300
|
+
push_objects_handler.run
|
|
218
301
|
end
|
|
302
|
+
end
|
|
219
303
|
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
@ss.delete
|
|
226
|
-
verify_zresult(@s.docname(:delete) => [])
|
|
227
|
-
verify_result(@c.docname(:delete_errors) => {},
|
|
228
|
-
@s.docname(:md) => {'3'=>@product3},
|
|
229
|
-
@c.docname(:cd) => {'3'=>@product3})
|
|
230
|
-
end
|
|
304
|
+
describe "create" do
|
|
305
|
+
before (:each) do
|
|
306
|
+
rh = lambda { @model.create(params[:create_object])}
|
|
307
|
+
@ssc = Rhoconnect::Handler::Changes::Engine.new(['create'], @model, rh, {})
|
|
308
|
+
end
|
|
231
309
|
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
# FIXME: Failed for jruby, ruby 1.9.2
|
|
239
|
-
# verify_result(@c.docname(:delete_errors) =>
|
|
240
|
-
# {"#{ERROR}-error"=>{"message"=>msg}, ERROR=>data[ERROR]},
|
|
241
|
-
# @c.docname(:delete) => {'2'=>@product2})
|
|
242
|
-
|
|
243
|
-
# Failure/Error: {"#{ERROR}-error"=>{"message"=>msg}, ERROR=>data[ERROR]},
|
|
244
|
-
# Verifying `client:application:testuser:b020a633ac2c43f7b0d30ef92dd43886:SampleAdapter:delete`
|
|
245
|
-
# expected: {"2"=>{"name"=>"G2", "brand"=>"Android", "price"=>"99.99"}}
|
|
246
|
-
# got: {} (using ==)
|
|
247
|
-
|
|
248
|
-
# Failure/Error: @c.docname(:delete) => {'2'=>@product2})
|
|
249
|
-
# Verifying `client:application:testuser:26a072a1da0d4bc18f69376e3229ab30:SampleAdapter:delete`
|
|
250
|
-
# expected: {"2"=>{"name"=>"G2", "brand"=>"Android", "price"=>"99.99"}}
|
|
251
|
-
# got: {} (using ==)
|
|
252
|
-
|
|
253
|
-
# But this one works everywhere !!!
|
|
254
|
-
verify_result(@c.docname(:delete_errors) => {"#{ERROR}-error"=>{"message"=>msg}, ERROR=>data[ERROR]})
|
|
255
|
-
end
|
|
310
|
+
it "should do create where adapter.create returns nil" do
|
|
311
|
+
set_source_queue_state(@s, {:create => {'2'=>@product2}}, @c.id, true)
|
|
312
|
+
@ssc.create
|
|
313
|
+
verify_source_queue_data(@s, :create => [])
|
|
314
|
+
verify_doc_result(@c, {:create_errors => {},
|
|
315
|
+
:create_links => {}})
|
|
256
316
|
end
|
|
257
317
|
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
end
|
|
318
|
+
it "should do create where adapter.create returns object link" do
|
|
319
|
+
@product4['link'] = 'test link'
|
|
320
|
+
set_source_queue_state(@s, {:create => {'4'=>@product4}},@c.id,true)
|
|
321
|
+
@ssc.create
|
|
322
|
+
verify_source_queue_data(@s, :create => [])
|
|
323
|
+
verify_doc_result(@c, {:create_errors => {},
|
|
324
|
+
:create_links => {'4'=>{'l'=>'backend_id'}}})
|
|
266
325
|
end
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
326
|
+
|
|
327
|
+
it "should raise exception on adapter.create" do
|
|
328
|
+
msg = "Error creating record"
|
|
329
|
+
data = add_error_object({'4'=>@product4,'2'=>@product2},msg)
|
|
330
|
+
set_source_queue_state(@s, {:create => data},@c.id, true)
|
|
331
|
+
@ssc.create
|
|
332
|
+
verify_doc_result(@c, :create_errors =>
|
|
333
|
+
{"#{ERROR}-error"=>{"message"=>msg},ERROR=>data[ERROR]})
|
|
334
|
+
end
|
|
335
|
+
end
|
|
336
|
+
|
|
337
|
+
describe "update" do
|
|
338
|
+
before (:each) do
|
|
339
|
+
rh = lambda { @model.update(params[:update_object])}
|
|
340
|
+
@ssu = Rhoconnect::Handler::Changes::Engine.new(['update'], @model, rh, {})
|
|
341
|
+
end
|
|
342
|
+
|
|
343
|
+
it "should do update with no errors" do
|
|
344
|
+
set_source_queue_state(@s, {:update => {'4'=> { 'price' => '199.99' }}},@c.id,true)
|
|
345
|
+
@ssu.update
|
|
346
|
+
verify_source_queue_data(@s, :update => [])
|
|
347
|
+
verify_doc_result(@c, :update_errors => {})
|
|
348
|
+
end
|
|
349
|
+
|
|
350
|
+
it "should do update with errors" do
|
|
351
|
+
msg = "Error updating record"
|
|
352
|
+
data = add_error_object({'4'=> { 'price' => '199.99' }},msg)
|
|
353
|
+
set_source_queue_state(@s, {:update => data},@c.id,true)
|
|
354
|
+
set_doc_state(@c, :cd => { ERROR => { 'price' => '99.99' } }
|
|
355
|
+
)
|
|
356
|
+
@ssu.update
|
|
357
|
+
update_data,client_ids = @s.get_queue(:update)
|
|
358
|
+
update_data.should == [{'4'=> { 'price' => '199.99'}}]
|
|
359
|
+
client_ids.should == [@c.id]
|
|
360
|
+
verify_doc_result(@c, {:update_errors =>
|
|
361
|
+
{"#{ERROR}-error"=>{"message"=>msg}, ERROR=>data[ERROR]},
|
|
362
|
+
:update_rollback => {ERROR=>{"price"=>"99.99"}}})
|
|
363
|
+
end
|
|
364
|
+
end
|
|
365
|
+
|
|
366
|
+
describe "delete" do
|
|
367
|
+
before (:each) do
|
|
368
|
+
rh = lambda { @model.update(params[:delete_object])}
|
|
369
|
+
@ssd = Rhoconnect::Handler::Changes::Engine.new(['delete'], @model, rh, {})
|
|
370
|
+
end
|
|
371
|
+
|
|
372
|
+
it "should do delete with no errors" do
|
|
373
|
+
set_source_queue_state(@s, {:delete => {'4'=>@product4}}, @c.id, true)
|
|
374
|
+
set_doc_state(@s, :md => {'4'=>@product4,'3'=>@product3})
|
|
375
|
+
set_doc_state(@c, :cd => {'4'=>@product4,'3'=>@product3})
|
|
376
|
+
@ssd.delete
|
|
377
|
+
verify_source_queue_data(@s, :delete => [])
|
|
378
|
+
verify_doc_result(@c, :delete_errors => {})
|
|
379
|
+
verify_doc_result(@s, :md => {'3'=>@product3})
|
|
380
|
+
verify_doc_result(@c, :cd => {'3'=>@product3})
|
|
381
|
+
end
|
|
382
|
+
|
|
383
|
+
it "should do delete with errors" do
|
|
384
|
+
msg = "Error delete record"
|
|
385
|
+
data = add_error_object({'2'=>@product2},msg)
|
|
386
|
+
set_source_queue_state(@s, {:delete => data}, @c.id, true)
|
|
387
|
+
@ssd.delete
|
|
388
|
+
|
|
389
|
+
# FIXME: Failed for jruby, ruby 1.9.2
|
|
390
|
+
# verify_result(@c.docname(:delete_errors) =>
|
|
391
|
+
# {"#{ERROR}-error"=>{"message"=>msg}, ERROR=>data[ERROR]},
|
|
392
|
+
# @c.docname(:delete) => {'2'=>@product2})
|
|
293
393
|
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
394
|
+
# Failure/Error: {"#{ERROR}-error"=>{"message"=>msg}, ERROR=>data[ERROR]},
|
|
395
|
+
# Verifying `client:application:testuser:b020a633ac2c43f7b0d30ef92dd43886:SampleAdapter:delete`
|
|
396
|
+
# expected: {"2"=>{"name"=>"G2", "brand"=>"Android", "price"=>"99.99"}}
|
|
397
|
+
# got: {} (using ==)
|
|
398
|
+
|
|
399
|
+
# Failure/Error: @c.docname(:delete) => {'2'=>@product2})
|
|
400
|
+
# Verifying `client:application:testuser:26a072a1da0d4bc18f69376e3229ab30:SampleAdapter:delete`
|
|
401
|
+
# expected: {"2"=>{"name"=>"G2", "brand"=>"Android", "price"=>"99.99"}}
|
|
402
|
+
# got: {} (using ==)
|
|
403
|
+
|
|
404
|
+
# But this one works everywhere !!!
|
|
405
|
+
verify_doc_result(@c, :delete_errors => {"#{ERROR}-error"=>{"message"=>msg}, ERROR=>data[ERROR]})
|
|
406
|
+
end
|
|
407
|
+
end
|
|
408
|
+
|
|
409
|
+
describe "cud" do
|
|
410
|
+
before (:each) do
|
|
411
|
+
rh = lambda { @model.send(params[:operation].to_sym, params["#{params[:operation]}_object".to_sym]) }
|
|
412
|
+
@sscud = Rhoconnect::Handler::Changes::Engine.new(['create', 'update', 'delete'], @model, rh, {})
|
|
413
|
+
end
|
|
414
|
+
|
|
415
|
+
it "should fail to create Rhoconnect::Handler::Changes::Engine with InvalidArgumentError without source" do
|
|
416
|
+
lambda { Rhoconnect::Handler::Changes::Engine.new(['create', 'update', 'delete'], nil, nil, {}) }.should raise_error(ArgumentError, 'Unknown source')
|
|
417
|
+
end
|
|
418
|
+
|
|
419
|
+
it "should fail to create Rhoconnect::Handler::Changes::Engine with InvalidArgumentError without proc handler" do
|
|
420
|
+
lambda { Rhoconnect::Handler::Changes::Engine.new(['create', 'update', 'delete'], @model, nil) }.should raise_error(ArgumentError, 'Invalid CUD handler')
|
|
421
|
+
end
|
|
422
|
+
|
|
423
|
+
it "should create Rhoconnect::Handler::Changes::Engine" do
|
|
424
|
+
@sscud.model.is_a?(SampleAdapter).should == true
|
|
425
|
+
end
|
|
426
|
+
|
|
427
|
+
it "should do process_cud" do
|
|
428
|
+
@sscud.should_receive(:auth_method).twice.and_return(true)
|
|
429
|
+
@sscud.should_receive(:create).once
|
|
430
|
+
@sscud.should_receive(:update).once
|
|
431
|
+
@sscud.should_receive(:delete).once
|
|
432
|
+
@sscud.do_cud
|
|
433
|
+
end
|
|
434
|
+
end
|
|
435
|
+
|
|
436
|
+
describe "cud conflicts" do
|
|
437
|
+
before (:each) do
|
|
438
|
+
rh = lambda { @model.send(params[:operation].to_sym, params["#{params[:operation]}_object".to_sym]) }
|
|
439
|
+
@sscud = Rhoconnect::Handler::Changes::Engine.new(['create', 'update', 'delete'], @model, rh, {})
|
|
440
|
+
end
|
|
441
|
+
|
|
442
|
+
it "should detect create conflict and skip the duplicate record creation, but properly update the links" do
|
|
443
|
+
set_source_queue_state(@s, {:create => {'4'=> { 'name' => 'Android', 'link' => '1' }}},@c.id,true)
|
|
444
|
+
set_source_queue_state(@s, {:create => {'5'=> { 'name' => 'Android', 'link' => '1', 'duplicate_of_cid' => @c.id, 'duplicate_of_key' => '4', 'duplicate_of_queue_index' => '0' }}},@c.id,true)
|
|
445
|
+
@sscud.do_cud
|
|
301
446
|
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
447
|
+
verify_source_queue_data(@s, :create => [])
|
|
448
|
+
verify_doc_result(@c, :create_errors => {})
|
|
449
|
+
verify_doc_result(@c, :create_links => {'4'=> { 'l' => 'backend_id' }, '5' => { 'l' => 'backend_id'}})
|
|
450
|
+
end
|
|
451
|
+
|
|
452
|
+
it "should detect create conflict and skip the duplicate record creation, but properly update the errors page" do
|
|
453
|
+
create_doc1 = { 'name' => 'wrongname', 'link' => '1', 'an_attribute' => "Create Sample Adapter Error" }
|
|
454
|
+
create_doc2 = { 'name' => 'wrongname', 'link' => '1', 'duplicate_of_cid' => @c.id, 'duplicate_of_key' => '4', 'duplicate_of_queue_index' => '0'}
|
|
455
|
+
set_source_queue_state(@s, {:create => {'4' => create_doc1}},@c.id,true)
|
|
456
|
+
set_source_queue_state(@s, {:create => {'5' => create_doc2}},@c.id,true)
|
|
457
|
+
@sscud.do_cud
|
|
312
458
|
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
459
|
+
verify_source_queue_data(@s, :create => [])
|
|
460
|
+
verify_doc_result(@c, :create_errors => {"4-error"=>{"message"=>"Create Sample Adapter Error"},
|
|
461
|
+
'4' => create_doc1,
|
|
462
|
+
"5-error"=>{"message"=>"Create Sample Adapter Error"},
|
|
463
|
+
'5' => create_doc2})
|
|
464
|
+
verify_doc_result(@c, :create_links => {})
|
|
465
|
+
end
|
|
466
|
+
|
|
467
|
+
it "should detect create conflict and force and error" do
|
|
468
|
+
set_source_queue_state(@s, {:create => {'4'=> { 'name' => 'Android', 'link' => true }}},@c.id,true)
|
|
469
|
+
set_source_queue_state(@s, {:create => {'5'=> { 'name' => 'Android', 'link' => '1', 'force_duplicate_error' => '1' }}},@c.id,true)
|
|
470
|
+
@sscud.do_cud
|
|
471
|
+
verify_source_queue_data(@s, :create => [])
|
|
472
|
+
verify_doc_result(@c, :create_errors => {"5-error"=>{"message"=>"Error during create: object confict detected"}, "5"=>{"name"=>"Android", "link"=>"1", 'force_duplicate_error' => '1'}} )
|
|
473
|
+
end
|
|
474
|
+
|
|
475
|
+
it "should detect update conflict and skip the duplicate record update" do
|
|
476
|
+
set_doc_state(@c, :cd => {'4'=> {'name' => 'Apple'}})
|
|
477
|
+
set_source_queue_state(@s, {:update => {'4'=> { 'name' => 'Android' }}},@c.id,true)
|
|
478
|
+
set_source_queue_state(@s, {:update => {'4'=> { 'name' => 'InvalidName', 'duplicate_of_cid' => @c.id, 'duplicate_of_key' => '4', 'duplicate_of_queue_index' => '0'}}},@c.id,true)
|
|
479
|
+
@sscud.do_cud
|
|
323
480
|
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
verify_result(@c.docname(:delete_errors) => {})
|
|
335
|
-
end
|
|
481
|
+
verify_source_queue_data(@s, :update => [])
|
|
482
|
+
verify_doc_result(@c, :update_errors => {})
|
|
483
|
+
verify_doc_result(@c, :update_rollback => {})
|
|
484
|
+
end
|
|
485
|
+
|
|
486
|
+
it "should detect update conflict and force an error on duplicate record update" do
|
|
487
|
+
set_doc_state(@c, :cd => {'4'=> {'name' => 'Apple'}})
|
|
488
|
+
set_source_queue_state(@s, {:update => {'4'=> { 'name' => 'Android' }}},@c.id,true)
|
|
489
|
+
set_source_queue_state(@s, {:update => {'4'=> { 'name' => 'ErrorName', 'force_duplicate_error' => '1' }}},@c.id,true)
|
|
490
|
+
@sscud.do_cud
|
|
336
491
|
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
set_zstate({@s.docname(:delete) => {'4'=> { 'name' => 'Apple' }}},@c.id,true)
|
|
341
|
-
set_zstate({@s.docname(:delete) => {'4'=> { 'name' => 'Apple', 'force_duplicate_error' => '1'}}},@c.id,true)
|
|
342
|
-
@ss.process_cud
|
|
343
|
-
|
|
344
|
-
verify_zresult(@s.docname(:delete) => [])
|
|
345
|
-
verify_result(@c.docname(:delete_errors) => {"4-error"=>{"message"=>"Error during delete: object confict detected"}, "4"=>{"name"=>"Apple", 'force_duplicate_error' => '1'}})
|
|
346
|
-
end
|
|
492
|
+
verify_source_queue_data(@s, :update => [])
|
|
493
|
+
verify_doc_result(@c, :update_errors => {"4-error"=>{"message"=>"Error during update: object confict detected"}, "4"=>{"name"=>"ErrorName", 'force_duplicate_error' => '1'}})
|
|
494
|
+
verify_doc_result(@c, :update_rollback => {'4'=> {'name' => 'Apple'}})
|
|
347
495
|
end
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
496
|
+
|
|
497
|
+
it "should detect delete conflict and skip the duplicate record delete" do
|
|
498
|
+
set_doc_state(@c, :cd => {'4'=> {'name' => 'Apple'}})
|
|
499
|
+
set_doc_state(@c, :cd_size => 1)
|
|
500
|
+
set_source_queue_state(@s, {:delete => {'4'=> { 'name' => 'Apple' }}},@c.id,true)
|
|
501
|
+
set_source_queue_state(@s, {:delete => {'4'=> { 'name' => 'Apple', 'duplicate_of_cid' => @c.id, 'duplicate_of_key' => '4', 'duplicate_of_queue_index' => '0'}}},@c.id,true)
|
|
502
|
+
@sscud.do_cud
|
|
353
503
|
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
504
|
+
verify_source_queue_data(@s, :delete => [])
|
|
505
|
+
verify_doc_result(@c, :cd => {})
|
|
506
|
+
verify_doc_result(@c, :cd_size => '0')
|
|
507
|
+
verify_doc_result(@c, :delete_errors => {})
|
|
508
|
+
end
|
|
509
|
+
|
|
510
|
+
it "should detect delete conflict and force an error on duplicate record delete" do
|
|
511
|
+
set_doc_state(@c, :cd => {'4'=> {'name' => 'Apple'}})
|
|
512
|
+
set_doc_state(@c, :cd_size => 1)
|
|
513
|
+
set_source_queue_state(@s, {:delete => {'4'=> { 'name' => 'Apple' }}},@c.id,true)
|
|
514
|
+
set_source_queue_state(@s, {:delete => {'4'=> { 'name' => 'Apple', 'force_duplicate_error' => '1'}}},@c.id,true)
|
|
515
|
+
@sscud.do_cud
|
|
361
516
|
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
res = @ss.do_query
|
|
367
|
-
verify_result(@s.docname(:md) => {},
|
|
368
|
-
@s.docname(:errors) => {'query-error'=>{'message'=>msg}})
|
|
369
|
-
# 1) if retry_limit is set to N - then, first N retries should not update refresh_time
|
|
370
|
-
@s.read_state.retry_counter.should == 1
|
|
371
|
-
@s.read_state.refresh_time.should <= Time.now.to_i
|
|
372
|
-
|
|
373
|
-
# try once more and fail again
|
|
374
|
-
set_test_data('test_db_storage',{},msg,"query error")
|
|
375
|
-
res = @ss.do_query
|
|
376
|
-
verify_result(@s.docname(:md) => {},
|
|
377
|
-
@s.docname(:errors) => {'query-error'=>{'message'=>msg}})
|
|
378
|
-
|
|
379
|
-
# 2) if retry_limit is set to N and number of retries exceeded it - update refresh_time
|
|
380
|
-
@s.read_state.retry_counter.should == 0
|
|
381
|
-
@s.read_state.refresh_time.should > Time.now.to_i
|
|
382
|
-
end
|
|
383
|
-
|
|
384
|
-
it "should do query with exception raised and restore state with succesfull retry" do
|
|
385
|
-
@s.retry_limit = 1
|
|
386
|
-
msg = "Error during query"
|
|
387
|
-
set_test_data('test_db_storage',{},msg,"query error")
|
|
388
|
-
res = @ss.do_query
|
|
389
|
-
verify_result(@s.docname(:md) => {},
|
|
390
|
-
@s.docname(:errors) => {'query-error'=>{'message'=>msg}})
|
|
391
|
-
# 1) if retry_limit is set to N - then, first N retries should not update refresh_time
|
|
392
|
-
@s.read_state.retry_counter.should == 1
|
|
393
|
-
@s.read_state.refresh_time.should <= Time.now.to_i
|
|
394
|
-
|
|
395
|
-
# try once more (with success)
|
|
396
|
-
expected = {'1'=>@product1,'2'=>@product2}
|
|
397
|
-
set_test_data('test_db_storage',expected)
|
|
398
|
-
@ss.do_query
|
|
399
|
-
verify_result(@s.docname(:md) => expected,
|
|
400
|
-
@s.docname(:errors) => {})
|
|
401
|
-
@s.read_state.retry_counter.should == 0
|
|
402
|
-
@s.read_state.refresh_time.should > Time.now.to_i
|
|
403
|
-
end
|
|
517
|
+
verify_source_queue_data(@s, :delete => [])
|
|
518
|
+
verify_doc_result(@c, :delete_errors => {"4-error"=>{"message"=>"Error during delete: object confict detected"}, "4"=>{"name"=>"Apple", 'force_duplicate_error' => '1'}})
|
|
519
|
+
end
|
|
520
|
+
end
|
|
404
521
|
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
res = @ss.do_query
|
|
411
|
-
verify_result(@s.docname(:md) => {},
|
|
412
|
-
@s.docname(:errors) => {'query-error'=>{'message'=>msg}})
|
|
413
|
-
# 1) if retry_limit is set to N - then, first N retries should not update refresh_time
|
|
414
|
-
@s.read_state.retry_counter.should == 1
|
|
415
|
-
@s.read_state.refresh_time.should <= Time.now.to_i
|
|
416
|
-
|
|
417
|
-
# 2) Make another error - results are the same
|
|
418
|
-
set_test_data('test_db_storage',{},msg,"query error")
|
|
419
|
-
res = @ss.do_query
|
|
420
|
-
verify_result(@s.docname(:md) => {},
|
|
421
|
-
@s.docname(:errors) => {'query-error'=>{'message'=>msg}})
|
|
422
|
-
@s.read_state.retry_counter.should == 2
|
|
423
|
-
@s.read_state.refresh_time.should <= Time.now.to_i
|
|
424
|
-
|
|
425
|
-
# wait until time interval exprires and prev_refresh_time is too old -
|
|
426
|
-
# this should reset the counter on next request with error
|
|
427
|
-
# and do not update refresh_time
|
|
428
|
-
sleep(3)
|
|
429
|
-
set_test_data('test_db_storage',{},msg,"query error")
|
|
430
|
-
res = @ss.do_query
|
|
431
|
-
verify_result(@s.docname(:md) => {},
|
|
432
|
-
@s.docname(:errors) => {'query-error'=>{'message'=>msg}})
|
|
433
|
-
@s.read_state.retry_counter.should == 1
|
|
434
|
-
@s.read_state.refresh_time.should <= Time.now.to_i
|
|
435
|
-
end
|
|
436
|
-
|
|
437
|
-
it "should do query with exception raised and update refresh time if retry_limit is 0" do
|
|
438
|
-
@s.retry_limit = 0
|
|
439
|
-
msg = "Error during query"
|
|
440
|
-
set_test_data('test_db_storage',{},msg,"query error")
|
|
441
|
-
res = @ss.do_query
|
|
442
|
-
verify_result(@s.docname(:md) => {},
|
|
443
|
-
@s.docname(:errors) => {'query-error'=>{'message'=>msg}})
|
|
444
|
-
# if poll_interval is set to 0 - refresh time should be updated
|
|
445
|
-
@s.read_state.retry_counter.should == 0
|
|
446
|
-
@s.read_state.refresh_time.should > Time.now.to_i
|
|
447
|
-
end
|
|
522
|
+
describe "search" do
|
|
523
|
+
before (:each) do
|
|
524
|
+
rh = lambda { @model.search(params[:search]) }
|
|
525
|
+
@sss = Rhoconnect::Handler::Search::Engine.new(@model, @c, rh, {})
|
|
526
|
+
end
|
|
448
527
|
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
@s.poll_interval = 0
|
|
452
|
-
msg = "Error during query"
|
|
453
|
-
set_test_data('test_db_storage',{},msg,"query error")
|
|
454
|
-
prev_refresh_time = @s.read_state.refresh_time
|
|
455
|
-
# make sure refresh time is expired
|
|
456
|
-
sleep(1)
|
|
457
|
-
res = @ss.do_query
|
|
458
|
-
verify_result(@s.docname(:md) => {},
|
|
459
|
-
@s.docname(:errors) => {'query-error'=>{'message'=>msg}})
|
|
460
|
-
# if poll_interval is set to 0 - refresh time should be updated
|
|
461
|
-
@s.read_state.retry_counter.should == 0
|
|
462
|
-
@s.read_state.refresh_time.should > prev_refresh_time
|
|
463
|
-
end
|
|
528
|
+
it "should do search with no exception" do
|
|
529
|
+
verify_read_operation('search')
|
|
464
530
|
end
|
|
465
531
|
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
verify_read_operation('search')
|
|
532
|
+
it "should do search with no exception pass through" do
|
|
533
|
+
verify_read_operation_pass_through('search')
|
|
469
534
|
end
|
|
470
|
-
|
|
471
|
-
it "should do search with no exception pass through" do
|
|
472
|
-
verify_read_operation_pass_through('search')
|
|
473
|
-
end
|
|
474
535
|
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
end
|
|
536
|
+
it "should do search with exception raised" do
|
|
537
|
+
verify_read_operation_with_error('search')
|
|
478
538
|
end
|
|
539
|
+
end
|
|
479
540
|
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
541
|
+
describe "app-level partitioning" do
|
|
542
|
+
it "should create app-level masterdoc with '__shared__' docname" do
|
|
543
|
+
@s1 = Source.load(@s_fields[:name],@s_params)
|
|
544
|
+
@s1.partition = :app
|
|
545
|
+
rh = lambda { @model.query(params[:query]) }
|
|
546
|
+
@model1 = Rhoconnect::Model::Base.create(@s1)
|
|
547
|
+
@ssq = Rhoconnect::Handler::Query::Engine.new(@model1, rh, {})
|
|
548
|
+
expected = {'1'=>@product1,'2'=>@product2}
|
|
549
|
+
set_state('test_db_storage' => expected)
|
|
550
|
+
@ssq.do_sync
|
|
551
|
+
verify_doc_result(@s1, :md => expected)
|
|
552
|
+
Store.get_store(0).keys("read_state:#{test_app_name}:__shared__*").sort.should ==
|
|
553
|
+
[ "read_state:#{test_app_name}:__shared__:SampleAdapter:refresh_time",
|
|
554
|
+
"read_state:#{test_app_name}:__shared__:SampleAdapter:prev_refresh_time",
|
|
555
|
+
"read_state:#{test_app_name}:__shared__:SampleAdapter:rho__id",
|
|
556
|
+
"read_state:#{test_app_name}:__shared__:SampleAdapter:retry_counter"].sort
|
|
495
557
|
end
|
|
558
|
+
end
|
|
496
559
|
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
end
|
|
560
|
+
def verify_read_operation(operation)
|
|
561
|
+
expected = {'1'=>@product1,'2'=>@product2}
|
|
562
|
+
set_test_data('test_db_storage',expected)
|
|
563
|
+
@s.put_data(:errors,
|
|
564
|
+
{"#{operation}-error"=>{'message'=>'failed'}},true)
|
|
565
|
+
if operation == 'query'
|
|
566
|
+
@ssq.run_query.should == true
|
|
567
|
+
verify_doc_result(@s, {:md => expected,
|
|
568
|
+
:errors => {}})
|
|
569
|
+
else
|
|
570
|
+
@sss.run_search.should == true
|
|
571
|
+
verify_doc_result(@c, {:search => expected,
|
|
572
|
+
:search_errors => {}})
|
|
511
573
|
end
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
574
|
+
end
|
|
575
|
+
|
|
576
|
+
def verify_read_operation_pass_through(operation)
|
|
577
|
+
expected = {'1'=>@product1,'2'=>@product2}
|
|
578
|
+
set_test_data('test_db_storage',expected)
|
|
579
|
+
@s.put_data(:errors,
|
|
580
|
+
{"#{operation}-error"=>{'message'=>'failed'}},true)
|
|
581
|
+
@s.pass_through = 'true'
|
|
582
|
+
if operation == 'query'
|
|
583
|
+
@ssq.run_query.should == expected
|
|
584
|
+
verify_doc_result(@s, {:md => {},
|
|
585
|
+
:errors => {}})
|
|
586
|
+
else
|
|
587
|
+
@sss.run_search.should == expected
|
|
588
|
+
verify_doc_result(@c, {:search => {},
|
|
589
|
+
:search_errors => {}})
|
|
528
590
|
end
|
|
591
|
+
end
|
|
529
592
|
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
593
|
+
def verify_read_operation_with_error(operation)
|
|
594
|
+
msg = "Error during #{operation}"
|
|
595
|
+
set_test_data('test_db_storage',{},msg,"#{operation} error")
|
|
596
|
+
if operation == 'query'
|
|
597
|
+
@ssq.should_receive(:log).with("Model raised #{operation} exception: #{msg}")
|
|
598
|
+
@ssq.should_receive(:log).with(anything)
|
|
599
|
+
@ssq.run_query.should == true
|
|
600
|
+
verify_doc_result(@s, {:md => {},
|
|
601
|
+
:errors => {'query-error'=>{'message'=>msg}}})
|
|
602
|
+
else
|
|
603
|
+
@sss.should_receive(:log).with("Model raised #{operation} exception: #{msg}")
|
|
604
|
+
@sss.should_receive(:log).with(anything)
|
|
605
|
+
@sss.run_search.should == true
|
|
606
|
+
verify_doc_result(@c, {:search => {},
|
|
607
|
+
:search_errors => {'search-error'=>{'message'=>msg}}})
|
|
544
608
|
end
|
|
545
609
|
end
|
|
546
610
|
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
[
|
|
552
|
-
|
|
611
|
+
describe "Jobs" do
|
|
612
|
+
it "should enqueue process_cud SourceJob" do
|
|
613
|
+
@s.cud_queue = :cud
|
|
614
|
+
rh = lambda { @model.send(params[:operation].to_sym, params["#{params[:operation]}_object".to_sym]) }
|
|
615
|
+
@sscud = Rhoconnect::Handler::Changes::Engine.new(['create', 'update', 'delete'], @model, rh, {})
|
|
616
|
+
@sscud.do_cud
|
|
617
|
+
Resque.peek(:cud).should == {"args"=>
|
|
618
|
+
["cud", @s.name, @a.name, @u.login, nil], "class"=>"Rhoconnect::SourceJob"}
|
|
619
|
+
end
|
|
553
620
|
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
621
|
+
it "should enqueue process_query SourceJob" do
|
|
622
|
+
@s.query_queue = :abc
|
|
623
|
+
rh = lambda { @model.query(params[:query]) }
|
|
624
|
+
@ssq = Rhoconnect::Handler::Query::Engine.new(@model, rh, { :query => {'foo'=>'bar'} })
|
|
625
|
+
@ssq.do_sync
|
|
626
|
+
Resque.peek(:abc).should == {"args"=>
|
|
627
|
+
["query", @s.name, @a.name, @u.login, {'foo'=>'bar'}], "class"=>"Rhoconnect::SourceJob"}
|
|
628
|
+
end
|
|
559
629
|
end
|
|
560
630
|
end
|
|
561
631
|
end
|