rhoconnect 3.3.6 → 3.4.2
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 +40 -4
- data/Gemfile +2 -2
- data/Gemfile.lock +27 -25
- data/bench/benchapp/Gemfile +7 -27
- data/bench/benchapp/config.ru +9 -31
- data/bench/blobapp/Gemfile +7 -27
- data/bench/blobapp/config.ru +9 -29
- data/bench/lib/bench.rb +8 -1
- data/bench/lib/bench/test_data.rb +4 -1
- data/bench/scripts/blob_cud_script.rb +4 -0
- data/bench/scripts/cud_script.rb +7 -1
- data/bench/scripts/helpers.rb +1 -1
- data/bench/scripts/test_query_script.rb +20 -7
- data/bench/spec/bench_spec_helper.rb +3 -1
- data/bin/rhoconnect +22 -12
- data/commands/{commands/dtach_commands → dtach}/dtach_about.rb +0 -0
- data/commands/{commands/dtach_commands → dtach}/dtach_install.rb +0 -0
- data/commands/{commands/redis_commands → dtach}/redis_attach.rb +0 -0
- data/commands/execute.rb +14 -15
- data/commands/generators/update.rb +26 -0
- data/commands/{commands/redis_commands → redis}/redis_about.rb +0 -0
- data/commands/redis/redis_download.rb +13 -0
- data/commands/redis/redis_install.rb +26 -0
- data/commands/{commands/redis_commands → redis}/redis_make.rb +0 -0
- data/commands/{commands/redis_commands → redis}/redis_restart.rb +3 -2
- data/commands/{commands/redis_commands → redis}/redis_start.rb +0 -0
- data/commands/{commands/redis_commands → redis}/redis_startbg.rb +0 -0
- data/commands/{commands/redis_commands → redis}/redis_stop.rb +3 -2
- data/commands/{commands/rhoconnect → rhoconnect}/clean_start.rb +0 -0
- data/commands/{commands/rhoconnect → rhoconnect}/config.rb +7 -2
- data/commands/{commands/rhoconnect → rhoconnect}/create_user.rb +0 -0
- data/commands/{commands/rhoconnect → rhoconnect}/delete_device.rb +0 -0
- data/commands/{commands/rhoconnect → rhoconnect}/delete_user.rb +0 -0
- data/commands/{commands/rhoconnect → rhoconnect}/flushdb.rb +4 -4
- data/commands/{commands/rhoconnect → rhoconnect}/get_token.rb +0 -0
- data/commands/{commands/rhoconnect → rhoconnect}/reset.rb +0 -0
- data/commands/{commands/rhoconnect → rhoconnect}/reset_refresh.rb +0 -0
- data/commands/{commands/rhoconnect → rhoconnect}/restart.rb +0 -0
- data/commands/{commands/rhoconnect → rhoconnect}/secret.rb +0 -0
- data/commands/{commands/rhoconnect → rhoconnect}/set_admin_password.rb +0 -0
- data/commands/{commands/rhoconnect → rhoconnect}/spec.rb +0 -0
- data/commands/rhoconnect/start.rb +27 -0
- data/commands/{commands/rhoconnect → rhoconnect}/startbg.rb +0 -0
- data/commands/{commands/rhoconnect → rhoconnect}/startdebug.rb +2 -2
- data/commands/{commands/rhoconnect → rhoconnect}/stop.rb +3 -4
- data/commands/{commands/rhoconnect → rhoconnect}/version.rb +0 -0
- data/commands/{commands/rhoconnect → rhoconnect}/web.rb +0 -0
- data/commands/rhoconnect_attach/attach.rb +10 -0
- data/commands/rhoconnect_console/console.rb +16 -0
- data/commands/{commands/rhoconnect → rhoconnect_console}/console_helper.rb +0 -0
- data/commands/{commands/rhoconnect → rhoconnect_war}/war.rb +0 -0
- data/commands/{commands/redis_commands → utilities}/redis_runner.rb +22 -19
- data/commands/utilities/utilities.rb +6 -0
- data/doc/benchmarks.txt +2 -2
- data/doc/bulk-sync.txt +12 -1
- data/doc/client-java.txt +3 -3
- data/doc/client-objc.txt +1 -1
- data/doc/client.txt +5 -5
- data/doc/command-line.txt +80 -135
- data/doc/deploying.txt +119 -12
- data/doc/extending-rhoconnect-server.txt +1 -1
- data/doc/heroku-addon.txt +119 -23
- data/doc/install.txt +101 -39
- data/doc/java-plugin.txt +2 -2
- data/doc/licensing.txt +1 -1
- data/doc/plugin-intro.txt +3 -1
- data/doc/preparing-production.txt +4 -4
- data/doc/public/cli.txt +2 -2
- data/doc/push-backend-setup.txt +11 -1
- data/doc/push-client-setup.txt +72 -2
- data/doc/push-server-setup.txt +129 -8
- data/doc/rails-plugin.txt +245 -40
- data/doc/rest-api.txt +10 -6
- data/doc/rhoconnect-calculator.txt +237 -0
- data/doc/rhoconnect-redis-stack.txt +35 -0
- data/doc/session-and-configuration.txt +24 -0
- data/doc/settings.txt +51 -41
- data/doc/source-adapters.txt +45 -45
- data/doc/stats-middleware.txt +2 -2
- data/doc/supported-platforms.txt +6 -6
- data/doc/testing.txt +2 -2
- data/doc/tutorial.txt +63 -63
- data/examples/simple/Gemfile +7 -35
- data/examples/simple/config.ru +8 -26
- data/examples/simple/sources/product.rb +6 -6
- data/generators/rhoconnect.rb +5 -0
- data/generators/templates/application/Gemfile +7 -37
- data/generators/templates/application/Rakefile +8 -0
- data/generators/templates/application/config.ru +12 -31
- data/generators/templates/application/rcgemfile +44 -0
- data/generators/templates/application/settings/settings.yml +7 -5
- data/install.sh +4 -4
- data/installer/unix-like/create_texts.rb +7 -2
- data/installer/unix-like/rho_connect_install_constants.rb +2 -2
- data/installer/unix-like/rho_connect_install_installers.rb +1 -16
- data/lib/rhoconnect.rb +51 -38
- data/lib/rhoconnect/api/app/query.rb +4 -1
- data/lib/rhoconnect/api/app/search.rb +4 -1
- data/lib/rhoconnect/api/client/list_client_docs.rb +3 -1
- data/lib/rhoconnect/api/user/ping.rb +1 -5
- data/lib/rhoconnect/application/init.rb +43 -0
- data/lib/rhoconnect/async.rb +11 -6
- data/lib/rhoconnect/client_sync.rb +30 -37
- data/lib/rhoconnect/document.rb +4 -0
- data/lib/rhoconnect/graph_helper.rb +74 -56
- data/lib/rhoconnect/middleware/helpers.rb +4 -0
- data/lib/rhoconnect/ping.rb +1 -0
- data/lib/rhoconnect/ping/gcm.rb +58 -0
- data/lib/rhoconnect/predefined_adapters/bench_adapter.rb +7 -1
- data/lib/rhoconnect/source.rb +70 -56
- data/lib/rhoconnect/source_sync.rb +33 -5
- data/lib/rhoconnect/store.rb +358 -110
- data/lib/rhoconnect/user.rb +8 -0
- data/lib/rhoconnect/utilities.rb +16 -14
- data/lib/rhoconnect/version.rb +1 -1
- data/lib/rhoconnect/web-console/models/client.js +1 -1
- data/lib/rhoconnect/web-console/public/UNVR67bold.ttf +0 -0
- data/lib/rhoconnect/web-console/public/bootstrap.css +6 -0
- data/lib/rhoconnect/web-console/public/logo.png +0 -0
- data/lib/rhoconnect/web-console/server.rb +13 -11
- data/lib/rhoconnect/web-console/templates/index.erb +5 -5
- data/lib/rhoconnect/web-console/templates/jqplot.erb +1 -0
- data/lib/rhoconnect/web-console/views/doc.js +0 -4
- data/lib/rhoconnect/web-console/views/home.js +2 -1
- data/lib/rhoconnect/web-console/views/new_ping.js +11 -6
- data/lib/rhoconnect/web-console/views/stats.js +9 -5
- data/rhoconnect.gemspec +6 -4
- data/spec/api/app/fast_update_spec.rb +2 -2
- data/spec/api/source/get_source_params_spec.rb +1 -0
- data/spec/apps/rhotestapp/settings/settings.yml +5 -5
- data/spec/client_sync_spec.rb +3 -14
- data/spec/perf/perf_spec_helper.rb +11 -7
- data/spec/perf/store_perf_spec.rb +88 -11
- data/spec/ping/gcm_spec.rb +99 -0
- data/spec/server/server_spec.rb +7 -0
- data/spec/server/stats_spec.rb +9 -2
- data/spec/source_sync_spec.rb +29 -0
- data/spec/spec_helper.rb +40 -38
- data/spec/stats/record_spec.rb +18 -9
- data/spec/store_spec.rb +128 -19
- data/spec/testdata/10000-data.txt +0 -0
- data/spec/testdata/5-data.txt +0 -0
- data/spec/testdata/5000-data.txt +0 -0
- data/tasks/jasmine.rake +1 -0
- data/tasks/redis.rake +16 -13
- metadata +71 -39
- data/commands/commands/redis_commands/redis_download.rb +0 -33
- data/commands/commands/redis_commands/redis_install.rb +0 -26
- data/commands/commands/rhoconnect/attach.rb +0 -8
- data/commands/commands/rhoconnect/console.rb +0 -15
- data/commands/commands/rhoconnect/start.rb +0 -18
- data/commands/utilities/dtach_installed.rb +0 -10
|
@@ -33,16 +33,20 @@ def title
|
|
|
33
33
|
"#{prefix} #{suffix}"
|
|
34
34
|
end
|
|
35
35
|
|
|
36
|
-
def generate_fake_data(num=1000)
|
|
36
|
+
def generate_fake_data(num=1000,unique=false)
|
|
37
37
|
res = {}
|
|
38
38
|
num.times do |n|
|
|
39
|
+
unique_prefix = ""
|
|
40
|
+
if unique
|
|
41
|
+
unique_prefix = "#{n}-#{Time.now.to_s}"
|
|
42
|
+
end
|
|
39
43
|
res[n.to_s] = {
|
|
40
|
-
"FirstName" => Faker::Name.first_name,
|
|
41
|
-
"LastName" => Faker::Name.last_name,
|
|
42
|
-
"Email" => Faker::Internet.free_email,
|
|
43
|
-
"Company" => Faker::Company.name,
|
|
44
|
-
"JobTitle" => title,
|
|
45
|
-
"Phone1" => Faker::PhoneNumber.phone_number
|
|
44
|
+
"FirstName" => Faker::Name.first_name + unique_prefix,
|
|
45
|
+
"LastName" => Faker::Name.last_name + unique_prefix,
|
|
46
|
+
"Email" => Faker::Internet.free_email + unique_prefix,
|
|
47
|
+
"Company" => Faker::Company.name + unique_prefix,
|
|
48
|
+
"JobTitle" => title + unique_prefix,
|
|
49
|
+
"Phone1" => Faker::PhoneNumber.phone_number + unique_prefix
|
|
46
50
|
}
|
|
47
51
|
end
|
|
48
52
|
res
|
|
@@ -2,25 +2,102 @@ require File.join(File.dirname(__FILE__),'perf_spec_helper')
|
|
|
2
2
|
|
|
3
3
|
describe "Rhoconnect Performance" do
|
|
4
4
|
it_behaves_like "SharedRhoconnectHelper", :rhoconnect_data => false do
|
|
5
|
-
it "should process get/put for
|
|
6
|
-
@data = get_test_data(
|
|
5
|
+
it "should process get/put/delete for 10000 records (60000 elements)" do
|
|
6
|
+
@data = get_test_data(10000)
|
|
7
7
|
start = start_timer
|
|
8
8
|
Store.put_data('mdoc',@data).should == true
|
|
9
9
|
start = lap_timer('put_data duration',start)
|
|
10
10
|
Store.get_data('mdoc').should == @data
|
|
11
|
-
lap_timer('get_data duration',start)
|
|
11
|
+
start = lap_timer('get_data duration',start)
|
|
12
|
+
Store.rename('mdoc','mdoc_copy')
|
|
13
|
+
start = lap_timer("rename doc duration", start)
|
|
14
|
+
Store.clone('mdoc_copy','mdoc_copy1')
|
|
15
|
+
start = lap_timer("clone doc duration", start)
|
|
16
|
+
Store.delete_objects('mdoc_copy',@data.keys[0,2])
|
|
17
|
+
start = lap_timer("delete_objects duration", start)
|
|
18
|
+
Store.delete_data('mdoc_copy1',@data)
|
|
19
|
+
start = lap_timer("delete_data duration", start)
|
|
12
20
|
end
|
|
13
|
-
|
|
14
|
-
it "should process
|
|
15
|
-
@data = get_test_data(
|
|
16
|
-
|
|
21
|
+
|
|
22
|
+
it "should process update_objects in a set of 10000 records (60000 elements)" do
|
|
23
|
+
@data = get_test_data(10000)
|
|
24
|
+
updated_key = @data.keys[21]
|
|
25
|
+
@update_data = {}
|
|
26
|
+
@update_data[updated_key] = @data[updated_key].clone
|
|
27
|
+
@update_data[updated_key]['Phone'] = 'updated phone SADD'
|
|
28
|
+
@update_data[updated_key]['Phone1'] = 'updated phone SREM and SADD'
|
|
29
|
+
expected = @data.clone
|
|
30
|
+
expected.merge!(@update_data)
|
|
31
|
+
|
|
32
|
+
Store.put_data('mdoc',@data).should == true
|
|
33
|
+
start = start_timer
|
|
34
|
+
Store.update_objects('mdoc', @update_data)
|
|
35
|
+
lap_timer("update_objects duration", start)
|
|
36
|
+
Store.get_data('mdoc').should == expected
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
it "should process 1000 update_objects in a set of 10000 records (60000 elements)" do
|
|
40
|
+
@data = get_test_data(10000)
|
|
41
|
+
updated_keys = @data.keys[2001..3000]
|
|
42
|
+
@update_data = {}
|
|
43
|
+
updated_keys.each do |updated_key|
|
|
44
|
+
@update_data[updated_key] = @data[updated_key].clone
|
|
45
|
+
@update_data[updated_key]['Phone'] = 'updated phone SADD'
|
|
46
|
+
@update_data[updated_key]['Phone1'] = 'updated phone SREM and SADD'
|
|
47
|
+
end
|
|
48
|
+
expected = @data.dup
|
|
49
|
+
expected.merge!(@update_data)
|
|
50
|
+
|
|
51
|
+
Store.put_data('mdoc',@data).should == true
|
|
52
|
+
start = start_timer
|
|
53
|
+
Store.update_objects('mdoc', @update_data)
|
|
54
|
+
lap_timer("update_objects duration", start)
|
|
55
|
+
|
|
56
|
+
Store.get_data('mdoc').should == expected
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
it "should process single attribute diff for 10000-record doc" do
|
|
60
|
+
@data = get_test_data(10000)
|
|
61
|
+
@data1 = get_test_data(10000)
|
|
17
62
|
@data1['950']['Phone1'] = 'This is changed'
|
|
18
63
|
expected = {'950' => {'Phone1' => 'This is changed'}}
|
|
19
|
-
Store.put_data(
|
|
20
|
-
Store.put_data(
|
|
64
|
+
Store.put_data(@s.docname(:md),@data1).should == true
|
|
65
|
+
Store.put_data(@c.docname(:cd),@data).should == true
|
|
66
|
+
start = start_timer
|
|
67
|
+
cs = ClientSync.new(@s,@c)
|
|
68
|
+
token,progress_count,total_count,res = cs.send_new_page
|
|
69
|
+
lap_timer('compute_page duration', start)
|
|
70
|
+
Store.get_data(@c.docname(:page)).should == expected
|
|
71
|
+
res['insert'].should == expected
|
|
72
|
+
res['delete'].should == {'950' => {'Phone1' => @data['950']['Phone1']}}
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
it "should process full-sync for 5000-record doc" do
|
|
76
|
+
@data = get_test_data(5000)
|
|
77
|
+
Store.put_data(@s.docname(:md),@data).should == true
|
|
78
|
+
start = start_timer
|
|
79
|
+
cs = ClientSync.new(@s,@c,5000)
|
|
80
|
+
token,progress_count,total_count,res = cs.send_new_page
|
|
81
|
+
lap_timer('compute_page duration', start)
|
|
82
|
+
Store.get_data(@c.docname(:page)).should == @data
|
|
83
|
+
res['insert'].should == @data
|
|
84
|
+
res['delete'].should == nil
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
it "should process worst-case sync scenario there every attrib of every object is changed for 5000-record doc" do
|
|
88
|
+
@data = generate_fake_data(5000,true)
|
|
89
|
+
sleep(1.5)
|
|
90
|
+
@data1 = generate_fake_data(5000,true)
|
|
91
|
+
Store.put_data(@s.docname(:md),@data).should == true
|
|
92
|
+
Store.put_data(@c.docname(:cd),@data1).should == true
|
|
21
93
|
start = start_timer
|
|
22
|
-
|
|
23
|
-
|
|
94
|
+
cs = ClientSync.new(@s,@c,5000)
|
|
95
|
+
token,progress_count,total_count,res = cs.send_new_page
|
|
96
|
+
lap_timer('compute_page duration', start)
|
|
97
|
+
Store.get_data(@c.docname(:page)).should == @data
|
|
98
|
+
Store.get_data(@c.docname(:cd)).should == Store.get_data(@s.docname(:md))
|
|
99
|
+
res['insert'].should == @data
|
|
100
|
+
res['delete'].should == @data1
|
|
24
101
|
end
|
|
25
102
|
end
|
|
26
103
|
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
require File.join(File.dirname(__FILE__),'..','spec_helper')
|
|
2
|
+
|
|
3
|
+
describe "Ping Android GCM" do
|
|
4
|
+
it_behaves_like "SharedRhoconnectHelper", :rhoconnect_data => false do
|
|
5
|
+
|
|
6
|
+
before(:each) do
|
|
7
|
+
@params = {"device_pin" => @c.device_pin,
|
|
8
|
+
"sources" => [@s.name], "message" => 'hello world',
|
|
9
|
+
"vibrate" => '5', "badge" => '5', "sound" => 'hello.mp3'}
|
|
10
|
+
@response = mock('response')
|
|
11
|
+
Rhoconnect.settings[:gcm_api_key] = 'validkey'
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
it "should ping gcm successfully" do
|
|
15
|
+
result = 'id=0:34234234134254%abc123\n'
|
|
16
|
+
@response.stub!(:code).and_return(200)
|
|
17
|
+
@response.stub!(:body).and_return(result)
|
|
18
|
+
@response.stub!(:headers).and_return({})
|
|
19
|
+
@response.stub!(:return!).and_return(@response)
|
|
20
|
+
setup_post_yield(@response)
|
|
21
|
+
Gcm.ping(@params).body.should == result
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
it "should raise error on missing gcm_api_key setting" do
|
|
25
|
+
key = Rhoconnect.settings[:gcm_api_key].dup
|
|
26
|
+
Rhoconnect.settings[:gcm_api_key] = nil
|
|
27
|
+
lambda { Gcm.ping(@params) }.should raise_error(
|
|
28
|
+
Gcm::InvalidApiKey, 'Missing `:gcm_api_key:` option in settings/settings.yml'
|
|
29
|
+
)
|
|
30
|
+
Rhoconnect.settings[:gcm_api_key] = key
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
it "should ping gcm with 503 connection error" do
|
|
34
|
+
error = 'Connection refused'
|
|
35
|
+
@response.stub!(:body).and_return(error)
|
|
36
|
+
RestClient.stub!(:post).and_return { raise RestClient::Exception.new(@response,503) }
|
|
37
|
+
Gcm.should_receive(:log).twice
|
|
38
|
+
lambda { Gcm.ping(@params) }.should raise_error(RestClient::Exception)
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
it "should ping gcm with 200 error message" do
|
|
42
|
+
error = 'Error=QuotaExceeded'
|
|
43
|
+
@response.stub!(:code).and_return(200)
|
|
44
|
+
@response.stub!(:body).and_return(error)
|
|
45
|
+
@response.stub!(:headers).and_return(nil)
|
|
46
|
+
setup_post_yield(@response)
|
|
47
|
+
Gcm.should_receive(:log).twice
|
|
48
|
+
lambda { Gcm.ping(@params) }.should raise_error(Gcm::GCMPingError, "GCM ping error: QuotaExceeded")
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
it "should fail to ping with bad authentication" do
|
|
52
|
+
error = 'Error=BadAuthentication'
|
|
53
|
+
@response.stub!(:code).and_return(403)
|
|
54
|
+
@response.stub!(:body).and_return(error)
|
|
55
|
+
@response.stub!(:headers).and_return({})
|
|
56
|
+
setup_post_yield(@response)
|
|
57
|
+
Gcm.should_receive(:log).twice
|
|
58
|
+
lambda { Gcm.ping(@params) }.should raise_error(
|
|
59
|
+
Gcm::InvalidApiKey, "Invalid GCM api key. Obtain new api key from GCM service."
|
|
60
|
+
)
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
it "should ping gcm with 401 error message" do
|
|
64
|
+
@response.stub!(:code).and_return(401)
|
|
65
|
+
@response.stub!(:body).and_return('')
|
|
66
|
+
setup_post_yield(@response)
|
|
67
|
+
Gcm.should_receive(:log).twice
|
|
68
|
+
lambda { Gcm.ping(@params) }.should raise_error(
|
|
69
|
+
Gcm::InvalidApiKey, "Invalid GCM api key. Obtain new api key from GCM service."
|
|
70
|
+
)
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
it "should compute gcm_message" do
|
|
74
|
+
expected = {
|
|
75
|
+
'registration_ids' => [@c.device_pin],
|
|
76
|
+
'collapse_key' => "RAND_KEY",
|
|
77
|
+
'data' => {
|
|
78
|
+
'do_sync' => @s.name,
|
|
79
|
+
'alert' => "hello world",
|
|
80
|
+
'vibrate' => '5',
|
|
81
|
+
'sound' => "hello.mp3"
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
actual = Gcm.gcm_message(@params)
|
|
85
|
+
actual['collapse_key'] = "RAND_KEY" unless actual['collapse_key'].nil?
|
|
86
|
+
actual.should == expected
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
it "should trim empty or nil params from gcm_message" do
|
|
90
|
+
expected = {'registration_ids' => [@c.device_pin], 'collapse_key' => "RAND_KEY",
|
|
91
|
+
'data' => {'vibrate' => '5', 'do_sync' => '', 'sound' => "hello.mp3"} }
|
|
92
|
+
params = {"device_pin" => @c.device_pin,
|
|
93
|
+
"sources" => [], "message" => '', "vibrate" => '5', "sound" => 'hello.mp3'}
|
|
94
|
+
actual = Gcm.gcm_message(params)
|
|
95
|
+
actual['collapse_key'] = "RAND_KEY" unless actual['collapse_key'].nil?
|
|
96
|
+
actual.should == expected
|
|
97
|
+
end
|
|
98
|
+
end
|
|
99
|
+
end
|
data/spec/server/server_spec.rb
CHANGED
|
@@ -382,6 +382,8 @@ describe "Server" do
|
|
|
382
382
|
get "/app/#{Rhoconnect::API_VERSION}/#{@s.name}", {}, {Rhoconnect::CLIENT_ID_HEADER => @c.id}
|
|
383
383
|
last_response.should be_ok
|
|
384
384
|
token = @c.get_value(:page_token)
|
|
385
|
+
last_response.headers[Rhoconnect::PAGE_TOKEN_HEADER].should == token
|
|
386
|
+
last_response.headers[Rhoconnect::PAGE_OBJECT_COUNT_HEADER].should == 2.to_s
|
|
385
387
|
JSON.parse(last_response.body).should == [{'version'=>ClientSync::SYNC_VERSION},{"token"=>token},
|
|
386
388
|
{"count"=>2}, {"progress_count"=>0}, {"total_count"=>2},{'insert'=>data}]
|
|
387
389
|
|
|
@@ -391,6 +393,8 @@ describe "Server" do
|
|
|
391
393
|
get "/app/#{Rhoconnect::API_VERSION}/#{@s.name}",{:token => token}, {Rhoconnect::CLIENT_ID_HEADER => @c.id}
|
|
392
394
|
last_response.should be_ok
|
|
393
395
|
token = @c.get_value(:page_token)
|
|
396
|
+
last_response.headers[Rhoconnect::PAGE_TOKEN_HEADER].should == token
|
|
397
|
+
last_response.headers[Rhoconnect::PAGE_OBJECT_COUNT_HEADER].should == 2.to_s
|
|
394
398
|
JSON.parse(last_response.body).should == [{'version'=>ClientSync::SYNC_VERSION},{"token"=>token},
|
|
395
399
|
{"count"=>2}, {"progress_count"=>0}, {"total_count"=>0},{'delete'=>data}]
|
|
396
400
|
end
|
|
@@ -402,8 +406,11 @@ describe "Server" do
|
|
|
402
406
|
params = {:client_id => @c.id,:sources => sources,:search => {'name' => 'iPhone'},
|
|
403
407
|
:version => ClientSync::VERSION}
|
|
404
408
|
get "/api/application/search",params
|
|
409
|
+
last_response.headers['Warning'].index('deprecated').should_not == nil
|
|
405
410
|
last_response.content_type.should =~ /application\/json/
|
|
406
411
|
token = @c.get_value(:search_token)
|
|
412
|
+
last_response.headers[Rhoconnect::PAGE_TOKEN_HEADER].should == token
|
|
413
|
+
last_response.headers[Rhoconnect::PAGE_OBJECT_COUNT_HEADER].should == 1.to_s
|
|
407
414
|
JSON.parse(last_response.body).should == [[{'version'=>ClientSync::SYNC_VERSION},{'token'=>token},
|
|
408
415
|
{'source'=>sources[0][:name]},{'count'=>1},{'insert'=>{'1'=>@product1}}]]
|
|
409
416
|
end
|
data/spec/server/stats_spec.rb
CHANGED
|
@@ -26,7 +26,14 @@ describe "Middleware" do
|
|
|
26
26
|
end
|
|
27
27
|
|
|
28
28
|
it "should compute http average" do
|
|
29
|
-
|
|
29
|
+
@incr = 0
|
|
30
|
+
Time.stub!(:now).and_return do
|
|
31
|
+
if @incr > 0
|
|
32
|
+
@now += 0.3
|
|
33
|
+
@incr -= 1
|
|
34
|
+
end
|
|
35
|
+
@now
|
|
36
|
+
end
|
|
30
37
|
env = {
|
|
31
38
|
'rack.request.query_hash' => {
|
|
32
39
|
'source_name' => 'SampleAdapter'
|
|
@@ -34,7 +41,7 @@ describe "Middleware" do
|
|
|
34
41
|
'REQUEST_METHOD' => 'GET',
|
|
35
42
|
'PATH_INFO' => '/api/application/query'
|
|
36
43
|
}
|
|
37
|
-
10.times { @middleware_new_routes.call(env) }
|
|
44
|
+
10.times { @incr = 3; @middleware_new_routes.call(env) }
|
|
38
45
|
metric = 'http:GET:/api/application/query:SampleAdapter'
|
|
39
46
|
Rhoconnect::Stats::Record.key(metric).should == "stat:#{metric}"
|
|
40
47
|
|
data/spec/source_sync_spec.rb
CHANGED
|
@@ -130,6 +130,35 @@ describe "SourceSync" do
|
|
|
130
130
|
@ss.process_query
|
|
131
131
|
end
|
|
132
132
|
end
|
|
133
|
+
|
|
134
|
+
describe "push_notify" do
|
|
135
|
+
it "should do push_notify for source after push_objects if enabled" do
|
|
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
|
|
161
|
+
end
|
|
133
162
|
|
|
134
163
|
describe "create" do
|
|
135
164
|
it "should do create where adapter.create returns nil" do
|
data/spec/spec_helper.rb
CHANGED
|
@@ -4,23 +4,25 @@ require 'webmock/rspec'
|
|
|
4
4
|
require 'rspec/autorun' # Required for Rcov to run with rspec '~> 2.8.0'
|
|
5
5
|
if RUBY_VERSION =~ /1.9/ || defined?(JRUBY_VERSION)
|
|
6
6
|
require 'simplecov'
|
|
7
|
-
SimpleCov.start
|
|
7
|
+
SimpleCov.start do
|
|
8
|
+
add_filter '/spec/'
|
|
9
|
+
end
|
|
8
10
|
end
|
|
9
11
|
|
|
10
12
|
# all specs are Async'd in new ruby
|
|
11
13
|
if RUBY_VERSION =~ /1.9/ and not defined?(JRUBY_VERSION)
|
|
12
14
|
require 'eventmachine'
|
|
13
15
|
require 'fiber'
|
|
14
|
-
|
|
16
|
+
|
|
15
17
|
Thread.abort_on_exception = true
|
|
16
|
-
|
|
18
|
+
|
|
17
19
|
module RSpec
|
|
18
20
|
module Core
|
|
19
21
|
class ExampleGroup
|
|
20
|
-
|
|
22
|
+
|
|
21
23
|
class << self
|
|
22
24
|
alias_method :run_alias, :run
|
|
23
|
-
|
|
25
|
+
|
|
24
26
|
def run(reporter)
|
|
25
27
|
if EM.reactor_running?
|
|
26
28
|
run_alias reporter
|
|
@@ -50,16 +52,16 @@ Dir["#{SPEC_PATH}/support/**/*.rb"].each { |f| require f }
|
|
|
50
52
|
|
|
51
53
|
ENV['RACK_ENV'] = 'test'
|
|
52
54
|
ERROR = '0_broken_object_id' unless defined? ERROR
|
|
53
|
-
|
|
55
|
+
|
|
54
56
|
module TestHelpers
|
|
55
57
|
def get_testapp_path
|
|
56
58
|
File.expand_path(File.join(File.dirname(__FILE__),'apps','rhotestapp'))
|
|
57
59
|
end
|
|
58
|
-
|
|
60
|
+
|
|
59
61
|
def get_emptyapp_path
|
|
60
62
|
File.expand_path(File.join(File.dirname(__FILE__),'apps','emptyapp'))
|
|
61
63
|
end
|
|
62
|
-
|
|
64
|
+
|
|
63
65
|
def do_post(url,params,headers = {})
|
|
64
66
|
headers.merge!('CONTENT_TYPE'=>'application/json')
|
|
65
67
|
post url, params.to_json, headers
|
|
@@ -69,7 +71,7 @@ module TestHelpers
|
|
|
69
71
|
headers.merge!('CONTENT_TYPE'=>'application/json')
|
|
70
72
|
put url, params.to_json, headers
|
|
71
73
|
end
|
|
72
|
-
|
|
74
|
+
|
|
73
75
|
def bulk_data_docname(app_id,user_id)
|
|
74
76
|
if user_id == "*"
|
|
75
77
|
File.join(app_id,app_id)
|
|
@@ -77,13 +79,13 @@ module TestHelpers
|
|
|
77
79
|
File.join(app_id,user_id,user_id)
|
|
78
80
|
end
|
|
79
81
|
end
|
|
80
|
-
|
|
82
|
+
|
|
81
83
|
def dump_db_data(store)
|
|
82
|
-
puts "*"*50
|
|
84
|
+
puts "*"*50
|
|
83
85
|
puts "DATA DUMP"
|
|
84
86
|
puts "*"*50
|
|
85
87
|
store.db.keys('*').sort.each do |key|
|
|
86
|
-
next if not key =~ /md|cd/
|
|
88
|
+
next if not key =~ /md|cd/
|
|
87
89
|
line = ""
|
|
88
90
|
line << "#{key}: "
|
|
89
91
|
type = store.db.type key
|
|
@@ -92,7 +94,7 @@ module TestHelpers
|
|
|
92
94
|
line << "#{store.get_data(key).inspect}"
|
|
93
95
|
else
|
|
94
96
|
line << "#{store.db.smembers(key).inspect}"
|
|
95
|
-
end
|
|
97
|
+
end
|
|
96
98
|
else
|
|
97
99
|
line << "#{store.db.get key}"
|
|
98
100
|
end
|
|
@@ -100,22 +102,22 @@ module TestHelpers
|
|
|
100
102
|
end
|
|
101
103
|
puts "*"*50
|
|
102
104
|
end
|
|
103
|
-
|
|
105
|
+
|
|
104
106
|
def add_client_id(data)
|
|
105
107
|
res = Marshal.load(Marshal.dump(data))
|
|
106
108
|
res.each { |key,value| value['rhomobile.rhoclient'] = @c.id.to_s }
|
|
107
109
|
end
|
|
108
110
|
|
|
109
111
|
def add_error_object(data,error_message,error_name='wrongname')
|
|
110
|
-
error = {'an_attribute'=>error_message,'name'=>error_name}
|
|
112
|
+
error = {'an_attribute'=>error_message,'name'=>error_name}
|
|
111
113
|
data.merge!({ERROR=>error})
|
|
112
114
|
data
|
|
113
115
|
end
|
|
114
|
-
|
|
116
|
+
|
|
115
117
|
def delete_data_directory
|
|
116
118
|
FileUtils.rm_rf(Rhoconnect.data_directory)
|
|
117
119
|
end
|
|
118
|
-
|
|
120
|
+
|
|
119
121
|
def json_clone(data)
|
|
120
122
|
JSON.parse(data.to_json)
|
|
121
123
|
end
|
|
@@ -127,7 +129,7 @@ module TestHelpers
|
|
|
127
129
|
RestClient.stub!(:post).and_yield(response)
|
|
128
130
|
end
|
|
129
131
|
end
|
|
130
|
-
|
|
132
|
+
|
|
131
133
|
def set_state(state,append=false)
|
|
132
134
|
state.each do |dockey,data|
|
|
133
135
|
if data.is_a?(Hash) or data.is_a?(Array)
|
|
@@ -137,22 +139,22 @@ module TestHelpers
|
|
|
137
139
|
end
|
|
138
140
|
end
|
|
139
141
|
end
|
|
140
|
-
|
|
142
|
+
|
|
141
143
|
def set_zstate(state,assoc_key,append=false)
|
|
142
144
|
state.each do |dockey,data|
|
|
143
145
|
Store.put_zdata(dockey,assoc_key,data,append)
|
|
144
146
|
end
|
|
145
147
|
end
|
|
146
|
-
|
|
148
|
+
|
|
147
149
|
def set_test_data(dockey,data,error_message=nil,error_name='wrongname')
|
|
148
150
|
if error_message
|
|
149
|
-
error = {'an_attribute'=>error_message,'name'=>error_name}
|
|
151
|
+
error = {'an_attribute'=>error_message,'name'=>error_name}
|
|
150
152
|
data.merge!({ERROR=>error})
|
|
151
|
-
end
|
|
153
|
+
end
|
|
152
154
|
Store.put_data(dockey,data)
|
|
153
155
|
data
|
|
154
156
|
end
|
|
155
|
-
|
|
157
|
+
|
|
156
158
|
def verify_result(result)
|
|
157
159
|
result.keys.sort.each do |dockey|
|
|
158
160
|
expected = result[dockey]
|
|
@@ -170,7 +172,7 @@ module TestHelpers
|
|
|
170
172
|
end
|
|
171
173
|
end
|
|
172
174
|
end
|
|
173
|
-
|
|
175
|
+
|
|
174
176
|
def verify_zresult(result)
|
|
175
177
|
result.keys.sort.each do |dockey|
|
|
176
178
|
expected = result[dockey]
|
|
@@ -183,25 +185,25 @@ module TestHelpers
|
|
|
183
185
|
end
|
|
184
186
|
end
|
|
185
187
|
end
|
|
186
|
-
|
|
188
|
+
|
|
187
189
|
def validate_db(bulk_data,data)
|
|
188
|
-
validate_db_file(bulk_data.dbfile,bulk_data.sources[0, -1],data)
|
|
190
|
+
validate_db_file(bulk_data.dbfile,bulk_data.sources[0, -1],data)
|
|
189
191
|
end
|
|
190
|
-
|
|
191
|
-
def validate_db_file(dbfile,sources,data)
|
|
192
|
-
db = DBAdapter.instance.get_connection(dbfile)
|
|
192
|
+
|
|
193
|
+
def validate_db_file(dbfile,sources,data)
|
|
194
|
+
db = DBAdapter.instance.get_connection(dbfile)
|
|
193
195
|
sources.each do |source_name|
|
|
194
196
|
s = Source.load(source_name,{:app_id => APP_NAME,:user_id => @u.login})
|
|
195
197
|
return false unless validate_db_by_name(db,s,data[s.name])
|
|
196
|
-
end
|
|
197
|
-
true
|
|
198
|
+
end
|
|
199
|
+
true
|
|
198
200
|
end
|
|
199
|
-
|
|
201
|
+
|
|
200
202
|
def validate_db_by_name(db,s,data)
|
|
201
203
|
db.execute("select source_id,name,sync_priority,partition,sync_type,source_attribs,
|
|
202
204
|
metadata,schema,blob_attribs,associations,last_inserted_size, backend_refresh_time
|
|
203
205
|
from sources where name='#{s.name}'").each do |row|
|
|
204
|
-
|
|
206
|
+
|
|
205
207
|
return false if row[0].to_s != s.source_id.to_s
|
|
206
208
|
return false if row[1] != s.name
|
|
207
209
|
return false if row[2].to_s != s.priority.to_s
|
|
@@ -241,7 +243,7 @@ module TestHelpers
|
|
|
241
243
|
end
|
|
242
244
|
data.empty?
|
|
243
245
|
end
|
|
244
|
-
|
|
246
|
+
|
|
245
247
|
def get_attrib_counter(data)
|
|
246
248
|
counter = {}
|
|
247
249
|
data.each do |object_name,object|
|
|
@@ -251,7 +253,7 @@ module TestHelpers
|
|
|
251
253
|
end
|
|
252
254
|
BulkDataJob.refs_to_s(counter)
|
|
253
255
|
end
|
|
254
|
-
|
|
256
|
+
|
|
255
257
|
def mock_metadata_method(adapters, &block)
|
|
256
258
|
adapters.each do |klass|
|
|
257
259
|
klass.class_eval "def metadata; {'foo'=>'bar'}.to_json; end"
|
|
@@ -261,7 +263,7 @@ module TestHelpers
|
|
|
261
263
|
klass.class_eval "def metadata; end"
|
|
262
264
|
end
|
|
263
265
|
end
|
|
264
|
-
|
|
266
|
+
|
|
265
267
|
def mock_schema_method(adapters, &block)
|
|
266
268
|
adapters.each do |klass|
|
|
267
269
|
klass.class_eval 'def schema
|
|
@@ -296,7 +298,7 @@ module TestHelpers
|
|
|
296
298
|
klass.class_eval "def schema; end"
|
|
297
299
|
end
|
|
298
300
|
end
|
|
299
|
-
|
|
301
|
+
|
|
300
302
|
def unzip_file(file,file_dir)
|
|
301
303
|
Zip::ZipFile.open(file) do |zip_file|
|
|
302
304
|
zip_file.each do |f|
|
|
@@ -315,5 +317,5 @@ module TestHelpers
|
|
|
315
317
|
BulkDataJob.perform(params)
|
|
316
318
|
BulkDataJob.after_perform_x(params) if BulkData.is_exist?(params["data_name"])
|
|
317
319
|
end
|
|
318
|
-
|
|
320
|
+
|
|
319
321
|
end #TestHelpers
|