rhoconnect 3.3.6 → 3.4.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (152) hide show
  1. data/CHANGELOG.md +40 -4
  2. data/Gemfile +2 -2
  3. data/Gemfile.lock +27 -25
  4. data/bench/benchapp/Gemfile +7 -27
  5. data/bench/benchapp/config.ru +9 -31
  6. data/bench/blobapp/Gemfile +7 -27
  7. data/bench/blobapp/config.ru +9 -29
  8. data/bench/lib/bench.rb +8 -1
  9. data/bench/lib/bench/test_data.rb +4 -1
  10. data/bench/scripts/blob_cud_script.rb +4 -0
  11. data/bench/scripts/cud_script.rb +7 -1
  12. data/bench/scripts/helpers.rb +1 -1
  13. data/bench/scripts/test_query_script.rb +20 -7
  14. data/bench/spec/bench_spec_helper.rb +3 -1
  15. data/bin/rhoconnect +22 -12
  16. data/commands/{commands/dtach_commands → dtach}/dtach_about.rb +0 -0
  17. data/commands/{commands/dtach_commands → dtach}/dtach_install.rb +0 -0
  18. data/commands/{commands/redis_commands → dtach}/redis_attach.rb +0 -0
  19. data/commands/execute.rb +14 -15
  20. data/commands/generators/update.rb +26 -0
  21. data/commands/{commands/redis_commands → redis}/redis_about.rb +0 -0
  22. data/commands/redis/redis_download.rb +13 -0
  23. data/commands/redis/redis_install.rb +26 -0
  24. data/commands/{commands/redis_commands → redis}/redis_make.rb +0 -0
  25. data/commands/{commands/redis_commands → redis}/redis_restart.rb +3 -2
  26. data/commands/{commands/redis_commands → redis}/redis_start.rb +0 -0
  27. data/commands/{commands/redis_commands → redis}/redis_startbg.rb +0 -0
  28. data/commands/{commands/redis_commands → redis}/redis_stop.rb +3 -2
  29. data/commands/{commands/rhoconnect → rhoconnect}/clean_start.rb +0 -0
  30. data/commands/{commands/rhoconnect → rhoconnect}/config.rb +7 -2
  31. data/commands/{commands/rhoconnect → rhoconnect}/create_user.rb +0 -0
  32. data/commands/{commands/rhoconnect → rhoconnect}/delete_device.rb +0 -0
  33. data/commands/{commands/rhoconnect → rhoconnect}/delete_user.rb +0 -0
  34. data/commands/{commands/rhoconnect → rhoconnect}/flushdb.rb +4 -4
  35. data/commands/{commands/rhoconnect → rhoconnect}/get_token.rb +0 -0
  36. data/commands/{commands/rhoconnect → rhoconnect}/reset.rb +0 -0
  37. data/commands/{commands/rhoconnect → rhoconnect}/reset_refresh.rb +0 -0
  38. data/commands/{commands/rhoconnect → rhoconnect}/restart.rb +0 -0
  39. data/commands/{commands/rhoconnect → rhoconnect}/secret.rb +0 -0
  40. data/commands/{commands/rhoconnect → rhoconnect}/set_admin_password.rb +0 -0
  41. data/commands/{commands/rhoconnect → rhoconnect}/spec.rb +0 -0
  42. data/commands/rhoconnect/start.rb +27 -0
  43. data/commands/{commands/rhoconnect → rhoconnect}/startbg.rb +0 -0
  44. data/commands/{commands/rhoconnect → rhoconnect}/startdebug.rb +2 -2
  45. data/commands/{commands/rhoconnect → rhoconnect}/stop.rb +3 -4
  46. data/commands/{commands/rhoconnect → rhoconnect}/version.rb +0 -0
  47. data/commands/{commands/rhoconnect → rhoconnect}/web.rb +0 -0
  48. data/commands/rhoconnect_attach/attach.rb +10 -0
  49. data/commands/rhoconnect_console/console.rb +16 -0
  50. data/commands/{commands/rhoconnect → rhoconnect_console}/console_helper.rb +0 -0
  51. data/commands/{commands/rhoconnect → rhoconnect_war}/war.rb +0 -0
  52. data/commands/{commands/redis_commands → utilities}/redis_runner.rb +22 -19
  53. data/commands/utilities/utilities.rb +6 -0
  54. data/doc/benchmarks.txt +2 -2
  55. data/doc/bulk-sync.txt +12 -1
  56. data/doc/client-java.txt +3 -3
  57. data/doc/client-objc.txt +1 -1
  58. data/doc/client.txt +5 -5
  59. data/doc/command-line.txt +80 -135
  60. data/doc/deploying.txt +119 -12
  61. data/doc/extending-rhoconnect-server.txt +1 -1
  62. data/doc/heroku-addon.txt +119 -23
  63. data/doc/install.txt +101 -39
  64. data/doc/java-plugin.txt +2 -2
  65. data/doc/licensing.txt +1 -1
  66. data/doc/plugin-intro.txt +3 -1
  67. data/doc/preparing-production.txt +4 -4
  68. data/doc/public/cli.txt +2 -2
  69. data/doc/push-backend-setup.txt +11 -1
  70. data/doc/push-client-setup.txt +72 -2
  71. data/doc/push-server-setup.txt +129 -8
  72. data/doc/rails-plugin.txt +245 -40
  73. data/doc/rest-api.txt +10 -6
  74. data/doc/rhoconnect-calculator.txt +237 -0
  75. data/doc/rhoconnect-redis-stack.txt +35 -0
  76. data/doc/session-and-configuration.txt +24 -0
  77. data/doc/settings.txt +51 -41
  78. data/doc/source-adapters.txt +45 -45
  79. data/doc/stats-middleware.txt +2 -2
  80. data/doc/supported-platforms.txt +6 -6
  81. data/doc/testing.txt +2 -2
  82. data/doc/tutorial.txt +63 -63
  83. data/examples/simple/Gemfile +7 -35
  84. data/examples/simple/config.ru +8 -26
  85. data/examples/simple/sources/product.rb +6 -6
  86. data/generators/rhoconnect.rb +5 -0
  87. data/generators/templates/application/Gemfile +7 -37
  88. data/generators/templates/application/Rakefile +8 -0
  89. data/generators/templates/application/config.ru +12 -31
  90. data/generators/templates/application/rcgemfile +44 -0
  91. data/generators/templates/application/settings/settings.yml +7 -5
  92. data/install.sh +4 -4
  93. data/installer/unix-like/create_texts.rb +7 -2
  94. data/installer/unix-like/rho_connect_install_constants.rb +2 -2
  95. data/installer/unix-like/rho_connect_install_installers.rb +1 -16
  96. data/lib/rhoconnect.rb +51 -38
  97. data/lib/rhoconnect/api/app/query.rb +4 -1
  98. data/lib/rhoconnect/api/app/search.rb +4 -1
  99. data/lib/rhoconnect/api/client/list_client_docs.rb +3 -1
  100. data/lib/rhoconnect/api/user/ping.rb +1 -5
  101. data/lib/rhoconnect/application/init.rb +43 -0
  102. data/lib/rhoconnect/async.rb +11 -6
  103. data/lib/rhoconnect/client_sync.rb +30 -37
  104. data/lib/rhoconnect/document.rb +4 -0
  105. data/lib/rhoconnect/graph_helper.rb +74 -56
  106. data/lib/rhoconnect/middleware/helpers.rb +4 -0
  107. data/lib/rhoconnect/ping.rb +1 -0
  108. data/lib/rhoconnect/ping/gcm.rb +58 -0
  109. data/lib/rhoconnect/predefined_adapters/bench_adapter.rb +7 -1
  110. data/lib/rhoconnect/source.rb +70 -56
  111. data/lib/rhoconnect/source_sync.rb +33 -5
  112. data/lib/rhoconnect/store.rb +358 -110
  113. data/lib/rhoconnect/user.rb +8 -0
  114. data/lib/rhoconnect/utilities.rb +16 -14
  115. data/lib/rhoconnect/version.rb +1 -1
  116. data/lib/rhoconnect/web-console/models/client.js +1 -1
  117. data/lib/rhoconnect/web-console/public/UNVR67bold.ttf +0 -0
  118. data/lib/rhoconnect/web-console/public/bootstrap.css +6 -0
  119. data/lib/rhoconnect/web-console/public/logo.png +0 -0
  120. data/lib/rhoconnect/web-console/server.rb +13 -11
  121. data/lib/rhoconnect/web-console/templates/index.erb +5 -5
  122. data/lib/rhoconnect/web-console/templates/jqplot.erb +1 -0
  123. data/lib/rhoconnect/web-console/views/doc.js +0 -4
  124. data/lib/rhoconnect/web-console/views/home.js +2 -1
  125. data/lib/rhoconnect/web-console/views/new_ping.js +11 -6
  126. data/lib/rhoconnect/web-console/views/stats.js +9 -5
  127. data/rhoconnect.gemspec +6 -4
  128. data/spec/api/app/fast_update_spec.rb +2 -2
  129. data/spec/api/source/get_source_params_spec.rb +1 -0
  130. data/spec/apps/rhotestapp/settings/settings.yml +5 -5
  131. data/spec/client_sync_spec.rb +3 -14
  132. data/spec/perf/perf_spec_helper.rb +11 -7
  133. data/spec/perf/store_perf_spec.rb +88 -11
  134. data/spec/ping/gcm_spec.rb +99 -0
  135. data/spec/server/server_spec.rb +7 -0
  136. data/spec/server/stats_spec.rb +9 -2
  137. data/spec/source_sync_spec.rb +29 -0
  138. data/spec/spec_helper.rb +40 -38
  139. data/spec/stats/record_spec.rb +18 -9
  140. data/spec/store_spec.rb +128 -19
  141. data/spec/testdata/10000-data.txt +0 -0
  142. data/spec/testdata/5-data.txt +0 -0
  143. data/spec/testdata/5000-data.txt +0 -0
  144. data/tasks/jasmine.rake +1 -0
  145. data/tasks/redis.rake +16 -13
  146. metadata +71 -39
  147. data/commands/commands/redis_commands/redis_download.rb +0 -33
  148. data/commands/commands/redis_commands/redis_install.rb +0 -26
  149. data/commands/commands/rhoconnect/attach.rb +0 -8
  150. data/commands/commands/rhoconnect/console.rb +0 -15
  151. data/commands/commands/rhoconnect/start.rb +0 -18
  152. 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 1000 records (6000 elements)" do
6
- @data = get_test_data(1000)
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 single attribute update 1000-record doc" do
15
- @data = get_test_data(1000)
16
- @data1 = get_test_data(1000)
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('mdoc',@data).should == true
20
- Store.put_data('cdoc',@data1).should == true
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
- Store.get_diff_data('mdoc','cdoc').should == expected
23
- lap_timer('get_diff_data duration', start)
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
@@ -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
@@ -26,7 +26,14 @@ describe "Middleware" do
26
26
  end
27
27
 
28
28
  it "should compute http average" do
29
- Time.stub!(:now).and_return { @now += 0.3; @now }
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
 
@@ -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