rhoconnect 3.3.6 → 3.4.2
Sign up to get free protection for your applications and to get access to all the features.
- 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
|