rhosync 2.0.0.beta1
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG +5 -0
- data/LICENSE +674 -0
- data/README.md +26 -0
- data/Rakefile +109 -0
- data/bench/bench +6 -0
- data/bench/benchapp/Rakefile +14 -0
- data/bench/benchapp/application.rb +13 -0
- data/bench/benchapp/config.ru +32 -0
- data/bench/benchapp/settings/license.key +1 -0
- data/bench/benchapp/settings/settings.yml +18 -0
- data/bench/benchapp/sources/mock_adapter.rb +55 -0
- data/bench/benchapp/sources/queue_mock_adapter.rb +2 -0
- data/bench/benchapp/vendor/rhosync/lib/rhosync.rb +7 -0
- data/bench/lib/bench/cli.rb +16 -0
- data/bench/lib/bench/logging.rb +18 -0
- data/bench/lib/bench/mock_client.rb +41 -0
- data/bench/lib/bench/result.rb +50 -0
- data/bench/lib/bench/runner.rb +44 -0
- data/bench/lib/bench/session.rb +65 -0
- data/bench/lib/bench/statistics.rb +56 -0
- data/bench/lib/bench/test_data.rb +55 -0
- data/bench/lib/bench/timer.rb +10 -0
- data/bench/lib/bench/utils.rb +49 -0
- data/bench/lib/bench.rb +128 -0
- data/bench/lib/testdata/100-data.txt +148 -0
- data/bench/lib/testdata/5-data.txt +11 -0
- data/bench/scripts/cud_script.rb +77 -0
- data/bench/scripts/helpers.rb +101 -0
- data/bench/scripts/query_md_script.rb +46 -0
- data/bench/scripts/query_script.rb +46 -0
- data/bench/spec/bench_spec_helper.rb +65 -0
- data/bench/spec/logging_spec.rb +19 -0
- data/bench/spec/mock_adapter_spec.rb +61 -0
- data/bench/spec/mock_client_spec.rb +64 -0
- data/bench/spec/result_spec.rb +59 -0
- data/bench/spec/utils_spec.rb +35 -0
- data/bin/rhosync +34 -0
- data/doc/protocol.html +1901 -0
- data/doc/public/css/print.css +29 -0
- data/doc/public/css/screen.css +257 -0
- data/doc/public/css/style.css +20 -0
- data/examples/simple/application.rb +13 -0
- data/examples/simple/sources/sample_adapter.rb +5 -0
- data/examples/simple/sources/simple_adapter.rb +5 -0
- data/examples/simple/vendor/rhosync/lib/rhosync.rb +7 -0
- data/generators/rhosync.rb +98 -0
- data/generators/templates/application/Rakefile +19 -0
- data/generators/templates/application/application.rb +27 -0
- data/generators/templates/application/config.ru +33 -0
- data/generators/templates/application/settings/license.key +1 -0
- data/generators/templates/application/settings/settings.yml +14 -0
- data/generators/templates/source/source_adapter.rb +49 -0
- data/lib/rhosync/api/create_client.rb +3 -0
- data/lib/rhosync/api/create_user.rb +7 -0
- data/lib/rhosync/api/delete_client.rb +5 -0
- data/lib/rhosync/api/delete_user.rb +5 -0
- data/lib/rhosync/api/get_api_token.rb +7 -0
- data/lib/rhosync/api/get_client_params.rb +3 -0
- data/lib/rhosync/api/get_db_doc.rb +7 -0
- data/lib/rhosync/api/get_license_info.rb +7 -0
- data/lib/rhosync/api/get_source_params.rb +3 -0
- data/lib/rhosync/api/list_client_docs.rb +12 -0
- data/lib/rhosync/api/list_clients.rb +3 -0
- data/lib/rhosync/api/list_source_docs.rb +10 -0
- data/lib/rhosync/api/list_sources.rb +15 -0
- data/lib/rhosync/api/list_users.rb +3 -0
- data/lib/rhosync/api/ping.rb +7 -0
- data/lib/rhosync/api/push_deletes.rb +6 -0
- data/lib/rhosync/api/push_objects.rb +6 -0
- data/lib/rhosync/api/reset.rb +10 -0
- data/lib/rhosync/api/set_db_doc.rb +8 -0
- data/lib/rhosync/api/set_refresh_time.rb +8 -0
- data/lib/rhosync/api/update_user.rb +4 -0
- data/lib/rhosync/api/upload_file.rb +4 -0
- data/lib/rhosync/api_token.rb +19 -0
- data/lib/rhosync/app.rb +69 -0
- data/lib/rhosync/bulk_data/bulk_data.rb +75 -0
- data/lib/rhosync/bulk_data/syncdb.index.schema +3 -0
- data/lib/rhosync/bulk_data/syncdb.schema +37 -0
- data/lib/rhosync/bulk_data.rb +2 -0
- data/lib/rhosync/client.rb +74 -0
- data/lib/rhosync/client_sync.rb +296 -0
- data/lib/rhosync/console/app/helpers/auth_helper.rb +18 -0
- data/lib/rhosync/console/app/helpers/extensions.rb +19 -0
- data/lib/rhosync/console/app/helpers/helpers.rb +52 -0
- data/lib/rhosync/console/app/public/main.css +7 -0
- data/lib/rhosync/console/app/public/text.txt +0 -0
- data/lib/rhosync/console/app/routes/auth.rb +29 -0
- data/lib/rhosync/console/app/routes/client.rb +32 -0
- data/lib/rhosync/console/app/routes/docs.rb +84 -0
- data/lib/rhosync/console/app/routes/home.rb +22 -0
- data/lib/rhosync/console/app/routes/user.rb +63 -0
- data/lib/rhosync/console/app/views/client.erb +30 -0
- data/lib/rhosync/console/app/views/doc.erb +56 -0
- data/lib/rhosync/console/app/views/docs.erb +29 -0
- data/lib/rhosync/console/app/views/index.erb +50 -0
- data/lib/rhosync/console/app/views/layout.erb +12 -0
- data/lib/rhosync/console/app/views/newuser.erb +17 -0
- data/lib/rhosync/console/app/views/ping.erb +28 -0
- data/lib/rhosync/console/app/views/result.erb +11 -0
- data/lib/rhosync/console/app/views/user.erb +32 -0
- data/lib/rhosync/console/app/views/users.erb +14 -0
- data/lib/rhosync/console/rhosync_api.rb +102 -0
- data/lib/rhosync/console/server.rb +27 -0
- data/lib/rhosync/credential.rb +9 -0
- data/lib/rhosync/document.rb +43 -0
- data/lib/rhosync/indifferent_access.rb +132 -0
- data/lib/rhosync/jobs/bulk_data_job.rb +104 -0
- data/lib/rhosync/jobs/ping_job.rb +19 -0
- data/lib/rhosync/jobs/source_job.rb +16 -0
- data/lib/rhosync/license.rb +79 -0
- data/lib/rhosync/lock_ops.rb +11 -0
- data/lib/rhosync/model.rb +410 -0
- data/lib/rhosync/ping/blackberry.rb +55 -0
- data/lib/rhosync/ping/iphone.rb +44 -0
- data/lib/rhosync/ping.rb +2 -0
- data/lib/rhosync/read_state.rb +27 -0
- data/lib/rhosync/server/views/index.erb +12 -0
- data/lib/rhosync/server.rb +242 -0
- data/lib/rhosync/source.rb +112 -0
- data/lib/rhosync/source_adapter.rb +95 -0
- data/lib/rhosync/source_sync.rb +245 -0
- data/lib/rhosync/store.rb +199 -0
- data/lib/rhosync/tasks.rb +151 -0
- data/lib/rhosync/user.rb +83 -0
- data/lib/rhosync/version.rb +3 -0
- data/lib/rhosync.rb +251 -0
- data/spec/api/api_helper.rb +44 -0
- data/spec/api/create_client_spec.rb +13 -0
- data/spec/api/create_user_spec.rb +16 -0
- data/spec/api/delete_client_spec.rb +13 -0
- data/spec/api/delete_user_spec.rb +18 -0
- data/spec/api/get_api_token_spec.rb +25 -0
- data/spec/api/get_client_params_spec.rb +18 -0
- data/spec/api/get_db_doc_spec.rb +21 -0
- data/spec/api/get_license_info_spec.rb +16 -0
- data/spec/api/get_source_params_spec.rb +26 -0
- data/spec/api/list_client_docs_spec.rb +33 -0
- data/spec/api/list_clients_spec.rb +23 -0
- data/spec/api/list_source_docs_spec.rb +26 -0
- data/spec/api/list_sources_spec.rb +27 -0
- data/spec/api/list_users_spec.rb +21 -0
- data/spec/api/ping_spec.rb +24 -0
- data/spec/api/push_deletes_spec.rb +16 -0
- data/spec/api/push_objects_spec.rb +27 -0
- data/spec/api/reset_spec.rb +22 -0
- data/spec/api/set_db_doc_spec.rb +20 -0
- data/spec/api/set_refresh_time_spec.rb +43 -0
- data/spec/api/update_user_spec.rb +31 -0
- data/spec/api/upload_file_spec.rb +26 -0
- data/spec/api_token_spec.rb +13 -0
- data/spec/app_spec.rb +20 -0
- data/spec/apps/rhotestapp/Rakefile +1 -0
- data/spec/apps/rhotestapp/application.rb +16 -0
- data/spec/apps/rhotestapp/config.ru +1 -0
- data/spec/apps/rhotestapp/settings/apple_fake_cert.pem +1 -0
- data/spec/apps/rhotestapp/settings/license.key +1 -0
- data/spec/apps/rhotestapp/settings/settings.yml +23 -0
- data/spec/apps/rhotestapp/sources/base_adapter.rb +9 -0
- data/spec/apps/rhotestapp/sources/sample_adapter.rb +66 -0
- data/spec/apps/rhotestapp/sources/simple_adapter.rb +39 -0
- data/spec/apps/rhotestapp/sources/sub_adapter.rb +7 -0
- data/spec/apps/rhotestapp/vendor/mygem-0.1.0/lib/mygem/mygem.rb +8 -0
- data/spec/apps/rhotestapp/vendor/mygem-0.1.0/lib/mygem.rb +1 -0
- data/spec/bulk_data/bulk_data_spec.rb +79 -0
- data/spec/client_spec.rb +58 -0
- data/spec/client_sync_spec.rb +377 -0
- data/spec/doc/base.html +72 -0
- data/spec/doc/doc_spec.rb +303 -0
- data/spec/doc/footer.html +4 -0
- data/spec/doc/header.html +30 -0
- data/spec/document_spec.rb +27 -0
- data/spec/generator/generator_spec.rb +53 -0
- data/spec/generator/generator_spec_helper.rb +8 -0
- data/spec/jobs/bulk_data_job_spec.rb +76 -0
- data/spec/jobs/ping_job_spec.rb +26 -0
- data/spec/jobs/source_job_spec.rb +25 -0
- data/spec/license_spec.rb +48 -0
- data/spec/model_spec.rb +269 -0
- data/spec/perf/bulk_data_perf_spec.rb +33 -0
- data/spec/perf/perf_spec_helper.rb +51 -0
- data/spec/perf/store_perf_spec.rb +28 -0
- data/spec/ping/blackberry_spec.rb +62 -0
- data/spec/ping/iphone_spec.rb +50 -0
- data/spec/read_state_spec.rb +25 -0
- data/spec/rhosync_spec.rb +43 -0
- data/spec/server/server_spec.rb +341 -0
- data/spec/source_adapter_spec.rb +114 -0
- data/spec/source_spec.rb +77 -0
- data/spec/source_sync_spec.rb +248 -0
- data/spec/spec_helper.rb +240 -0
- data/spec/store_spec.rb +149 -0
- data/spec/sync_states_spec.rb +101 -0
- data/spec/testdata/1000-data.txt +1414 -0
- data/spec/testdata/compressed/compress-data.txt +1 -0
- data/spec/testdata/upload1.txt +1 -0
- data/spec/testdata/upload2.txt +1 -0
- data/spec/user_spec.rb +79 -0
- data/tasks/redis.rake +134 -0
- metadata +545 -0
@@ -0,0 +1,44 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__),'..','spec_helper')
|
2
|
+
require 'rack/test'
|
3
|
+
require 'spec'
|
4
|
+
require 'spec/autorun'
|
5
|
+
require 'spec/interop/test'
|
6
|
+
|
7
|
+
require File.join(File.dirname(__FILE__),'..','..','lib','rhosync','server.rb')
|
8
|
+
|
9
|
+
describe "ApiHelper", :shared => true do
|
10
|
+
it_should_behave_like "RhosyncDataHelper"
|
11
|
+
|
12
|
+
include Rack::Test::Methods
|
13
|
+
include Rhosync
|
14
|
+
|
15
|
+
before(:each) do
|
16
|
+
require File.join(get_testapp_path,@test_app_name)
|
17
|
+
Rhosync.bootstrap(get_testapp_path) do |rhosync|
|
18
|
+
rhosync.vendor_directory = File.join(rhosync.base_directory,'..','..','..','vendor')
|
19
|
+
end
|
20
|
+
Server.set(
|
21
|
+
:environment => :test,
|
22
|
+
:run => false,
|
23
|
+
:secret => "secure!"
|
24
|
+
)
|
25
|
+
@api_token = User.load('admin').token_id
|
26
|
+
end
|
27
|
+
|
28
|
+
def app
|
29
|
+
@app ||= Server.new
|
30
|
+
end
|
31
|
+
|
32
|
+
it_should_behave_like "DBObjectsHelper"
|
33
|
+
end
|
34
|
+
|
35
|
+
def compress(path)
|
36
|
+
path.sub!(%r[/$],'')
|
37
|
+
archive = File.join(path,File.basename(path))+'.zip'
|
38
|
+
FileUtils.rm archive, :force=>true
|
39
|
+
Zip::ZipFile.open(archive, 'w') do |zipfile|
|
40
|
+
Dir["#{path}/**/**"].reject{|f|f==archive}.each do |file|
|
41
|
+
zipfile.add(file.sub(path+'/',''),file)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__),'api_helper')
|
2
|
+
|
3
|
+
describe "RhosyncApiCreateUser" do
|
4
|
+
it_should_behave_like "ApiHelper"
|
5
|
+
|
6
|
+
it "should create client for a user" do
|
7
|
+
post "/api/create_client", {:app_name => @test_app_name, :api_token => @api_token, :user_id => @u_fields[:login]}
|
8
|
+
last_response.should be_ok
|
9
|
+
clients = User.load(@u_fields[:login]).clients.members
|
10
|
+
clients.size.should == 2
|
11
|
+
clients.include?(last_response.body).should == true
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__),'api_helper')
|
2
|
+
|
3
|
+
describe "RhosyncApiCreateUser" do
|
4
|
+
it_should_behave_like "ApiHelper"
|
5
|
+
|
6
|
+
it "should create user as admin" do
|
7
|
+
params = {:app_name => @test_app_name, :api_token => @api_token,
|
8
|
+
:attributes => {:login => 'testuser1', :password => 'testpass1'}}
|
9
|
+
post "/api/create_user", params
|
10
|
+
last_response.should be_ok
|
11
|
+
User.load(params[:attributes][:login]).login.should == params[:attributes][:login]
|
12
|
+
User.authenticate(params[:attributes][:login],
|
13
|
+
params[:attributes][:password]).login.should == params[:attributes][:login]
|
14
|
+
@a.users.members.sort.should == [@u.login, params[:attributes][:login]]
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__),'api_helper')
|
2
|
+
|
3
|
+
describe "RhosyncApiDeleteUser" do
|
4
|
+
it_should_behave_like "ApiHelper"
|
5
|
+
|
6
|
+
it "should delete client" do
|
7
|
+
post "/api/delete_client", {:app_name => @test_app_name, :api_token => @api_token,
|
8
|
+
:user_id => @u_fields[:login], :client_id => @c.id}
|
9
|
+
last_response.should be_ok
|
10
|
+
Client.is_exist?(@c.id).should == false
|
11
|
+
User.load(@u_fields[:login]).clients.members.should == []
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__),'api_helper')
|
2
|
+
|
3
|
+
describe "RhosyncApiDeleteUser" do
|
4
|
+
it_should_behave_like "ApiHelper"
|
5
|
+
|
6
|
+
it "should delete user" do
|
7
|
+
params = {:app_name => @test_app_name, :api_token => @api_token,
|
8
|
+
:attributes => {:login => 'testuser1', :password => 'testpass1'}}
|
9
|
+
post "/api/create_user", params
|
10
|
+
last_response.should be_ok
|
11
|
+
User.is_exist?(params[:attributes][:login]).should == true
|
12
|
+
post "/api/delete_user", {:app_name => @test_app_name, :api_token => @api_token,
|
13
|
+
:user_id => params[:attributes][:login]}
|
14
|
+
last_response.should be_ok
|
15
|
+
User.is_exist?(params[:attributes][:login]).should == false
|
16
|
+
App.load(@test_app_name).users.members.should == ["testuser"]
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__),'api_helper')
|
2
|
+
|
3
|
+
describe "RhosyncApiGetApiToken" do
|
4
|
+
it_should_behave_like "ApiHelper"
|
5
|
+
|
6
|
+
it "should get token string" do
|
7
|
+
post "/login", :login => 'admin',:password => ''
|
8
|
+
post "/api/get_api_token"
|
9
|
+
last_response.body.should == @api_token
|
10
|
+
end
|
11
|
+
|
12
|
+
it "should fail to get token if user is not admin" do
|
13
|
+
post "/login", :login => @u_fields[:login],:password => 'testpass'
|
14
|
+
post "/api/get_api_token"
|
15
|
+
last_response.status.should == 422
|
16
|
+
last_response.body.should == 'Invalid/missing API user'
|
17
|
+
end
|
18
|
+
|
19
|
+
it "should return 422 if no token provided" do
|
20
|
+
params = {:app_name => @test_app_name, :attributes =>
|
21
|
+
{:login => 'testuser1', :password => 'testpass1'}}
|
22
|
+
post "/api/create_user", params
|
23
|
+
last_response.status.should == 422
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__),'api_helper')
|
2
|
+
|
3
|
+
describe "RhosyncApiGetClientParams" do
|
4
|
+
it_should_behave_like "ApiHelper"
|
5
|
+
|
6
|
+
it "should list client attributes" do
|
7
|
+
post "/api/get_client_params", {:api_token => @api_token, :client_id =>@c.id}
|
8
|
+
res = JSON.parse(last_response.body)
|
9
|
+
res.delete_if { |attrib| attrib['name'] == 'rho__id' }
|
10
|
+
res.sort{|x,y| x['name']<=>y['name']}.should == [
|
11
|
+
{"name"=>"device_type", "value"=>"iPhone", "type"=>"string"},
|
12
|
+
{"name"=>"device_pin", "value"=>"abcd", "type"=>"string"},
|
13
|
+
{"name"=>"device_port", "value"=>"3333", "type"=>"string"},
|
14
|
+
{"name"=>"user_id", "value"=>"testuser", "type"=>"string"},
|
15
|
+
{"name"=>"app_id", "value"=>"application", "type"=>"string"}].sort{|x,y| x['name']<=>y['name']}
|
16
|
+
end
|
17
|
+
|
18
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__),'api_helper')
|
2
|
+
|
3
|
+
describe "RhosyncApiGetDbDoc" do
|
4
|
+
it_should_behave_like "ApiHelper"
|
5
|
+
|
6
|
+
it "should return db document by name" do
|
7
|
+
data = {'1' => {'foo' => 'bar'}}
|
8
|
+
set_state('abc:abc' => data)
|
9
|
+
post "/api/get_db_doc", :api_token => @api_token, :doc => 'abc:abc'
|
10
|
+
last_response.should be_ok
|
11
|
+
JSON.parse(last_response.body).should == data
|
12
|
+
end
|
13
|
+
|
14
|
+
it "should return db document by name and data_type" do
|
15
|
+
data = 'some string'
|
16
|
+
set_state('abc:abc' => data)
|
17
|
+
post "/api/get_db_doc", :api_token => @api_token, :doc => 'abc:abc', :data_type => :string
|
18
|
+
last_response.should be_ok
|
19
|
+
last_response.body.should == data
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__),'api_helper')
|
2
|
+
|
3
|
+
describe "RhosyncApiGetLicenseInfo" do
|
4
|
+
it_should_behave_like "ApiHelper"
|
5
|
+
|
6
|
+
it "should get license info" do
|
7
|
+
true.should == true
|
8
|
+
post "/api/get_license_info", {:api_token => @api_token}
|
9
|
+
JSON.parse(last_response.body).should == {
|
10
|
+
"available" => 9,
|
11
|
+
"issued" => "Fri Apr 23 17:20:13 -0700 2010",
|
12
|
+
"seats" => 10,
|
13
|
+
"rhosync_version" => "Version 1",
|
14
|
+
"licensee" => "Rhomobile" }
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__),'api_helper')
|
2
|
+
|
3
|
+
describe "RhosyncApiGetSourceParams" do
|
4
|
+
it_should_behave_like "ApiHelper"
|
5
|
+
|
6
|
+
it "should list source attributes" do
|
7
|
+
post "/api/get_source_params", {:app_name => @test_app_name, :api_token => @api_token, :source_id =>"SampleAdapter"}
|
8
|
+
JSON.parse(last_response.body).should == [
|
9
|
+
{"name"=>"rho__id", "value"=>"SampleAdapter", "type"=>"string"},
|
10
|
+
{"name"=>"source_id", "value"=>nil, "type"=>"integer"},
|
11
|
+
{"name"=>"name", "value"=>"SampleAdapter", "type"=>"string"},
|
12
|
+
{"name"=>"url", "value"=>"", "type"=>"string"},
|
13
|
+
{"name"=>"login", "value"=>"", "type"=>"string"},
|
14
|
+
{"name"=>"password", "value"=>"", "type"=>"string"},
|
15
|
+
{"name"=>"priority", "value"=>3, "type"=>"integer"},
|
16
|
+
{"name"=>"callback_url", "value"=>nil, "type"=>"string"},
|
17
|
+
{"name"=>"poll_interval", "value"=>300, "type"=>"integer"},
|
18
|
+
{"name"=>"partition_type", "value"=>"user", "type"=>"string"},
|
19
|
+
{"name"=>"sync_type", "value"=>"incremental", "type"=>"string"},
|
20
|
+
{"name"=>"queue", "value"=>nil, "type"=>"string"},
|
21
|
+
{"name"=>"query_queue", "value"=>nil, "type"=>"string"},
|
22
|
+
{"name"=>"cud_queue", "value"=>nil, "type"=>"string"}]
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
26
|
+
|
@@ -0,0 +1,33 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__),'api_helper')
|
2
|
+
|
3
|
+
describe "RhosyncApiListClientDocs" do
|
4
|
+
it_should_behave_like "ApiHelper"
|
5
|
+
|
6
|
+
it "should list client documents" do
|
7
|
+
post "/api/list_client_docs", {:app_name => @test_app_name, :api_token => @api_token,
|
8
|
+
:source_id => "SimpleAdapter", :client_id => @c.id}
|
9
|
+
JSON.parse(last_response.body).should == {
|
10
|
+
"cd"=>"client:application:testuser:#{@c.id}:SimpleAdapter:cd",
|
11
|
+
"cd_size"=>"client:application:testuser:#{@c.id}:SimpleAdapter:cd_size",
|
12
|
+
"create"=>"client:application:testuser:#{@c.id}:SimpleAdapter:create",
|
13
|
+
"update"=>"client:application:testuser:#{@c.id}:SimpleAdapter:update",
|
14
|
+
"delete"=>"client:application:testuser:#{@c.id}:SimpleAdapter:delete",
|
15
|
+
|
16
|
+
"page"=>"client:application:testuser:#{@c.id}:SimpleAdapter:page",
|
17
|
+
"page_token"=>"client:application:testuser:#{@c.id}:SimpleAdapter:page_token",
|
18
|
+
"delete_page"=>"client:application:testuser:#{@c.id}:SimpleAdapter:delete_page",
|
19
|
+
"create_links"=>"client:application:testuser:#{@c.id}:SimpleAdapter:create_links",
|
20
|
+
"create_links_page"=>"client:application:testuser:#{@c.id}:SimpleAdapter:create_links_page",
|
21
|
+
|
22
|
+
"delete_errors"=>"client:application:testuser:#{@c.id}:SimpleAdapter:delete_errors",
|
23
|
+
"login_error"=>"client:application:testuser:#{@c.id}:SimpleAdapter:login_error",
|
24
|
+
"create_errors"=>"client:application:testuser:#{@c.id}:SimpleAdapter:create_errors",
|
25
|
+
"update_errors"=>"client:application:testuser:#{@c.id}:SimpleAdapter:update_errors",
|
26
|
+
"logoff_error"=>"client:application:testuser:#{@c.id}:SimpleAdapter:logoff_error",
|
27
|
+
|
28
|
+
"search"=>"client:application:testuser:#{@c.id}:SimpleAdapter:search",
|
29
|
+
"search_token"=>"client:application:testuser:#{@c.id}:SimpleAdapter:search_token",
|
30
|
+
"search_errors"=>"client:application:testuser:#{@c.id}:SimpleAdapter:search_errors"}
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__),'api_helper')
|
2
|
+
|
3
|
+
describe "RhosyncApiListUsers" do
|
4
|
+
it_should_behave_like "ApiHelper"
|
5
|
+
|
6
|
+
it "should list clients" do
|
7
|
+
post "/api/list_clients", {:app_name => @test_app_name, :api_token => @api_token,
|
8
|
+
:user_id => @u_fields[:login]}
|
9
|
+
res = JSON.parse(last_response.body)
|
10
|
+
res.is_a?(Array).should == true
|
11
|
+
res.size.should == 1
|
12
|
+
res[0].is_a?(String) == true
|
13
|
+
res[0].length.should == 32
|
14
|
+
end
|
15
|
+
|
16
|
+
it "should handle empty client's list" do
|
17
|
+
@u.clients.delete(@c.id)
|
18
|
+
post "/api/list_clients", {:app_name => @test_app_name, :api_token => @api_token,
|
19
|
+
:user_id => @u_fields[:login]}
|
20
|
+
JSON.parse(last_response.body).should == []
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__),'api_helper')
|
2
|
+
|
3
|
+
describe "RhosyncApiListSourceDocs" do
|
4
|
+
it_should_behave_like "ApiHelper"
|
5
|
+
|
6
|
+
it "should list of shared source documents" do
|
7
|
+
post "/api/list_source_docs", {:app_name => @test_app_name, :api_token => @api_token,
|
8
|
+
:source_id => "SimpleAdapter", :user_id => '*'}
|
9
|
+
JSON.parse(last_response.body).should == {
|
10
|
+
"md"=>"source:application:__shared__:SimpleAdapter:md",
|
11
|
+
"errors"=>"source:application:__shared__:SimpleAdapter:errors",
|
12
|
+
"md_size"=>"source:application:__shared__:SimpleAdapter:md_size",
|
13
|
+
"md_copy"=>"source:application:__shared__:SimpleAdapter:md_copy"}
|
14
|
+
end
|
15
|
+
|
16
|
+
it "should list user source documents" do
|
17
|
+
post "/api/list_source_docs", {:app_name => @test_app_name, :api_token => @api_token,
|
18
|
+
:source_id => "SampleAdapter", :user_id => @u.id}
|
19
|
+
JSON.parse(last_response.body).should == {
|
20
|
+
"md"=>"source:application:testuser:SampleAdapter:md",
|
21
|
+
"errors"=>"source:application:testuser:SampleAdapter:errors",
|
22
|
+
"md_size"=>"source:application:testuser:SampleAdapter:md_size",
|
23
|
+
"md_copy"=>"source:application:testuser:SampleAdapter:md_copy"}
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__),'api_helper')
|
2
|
+
|
3
|
+
describe "RhosyncApiListSources" do
|
4
|
+
it_should_behave_like "ApiHelper"
|
5
|
+
|
6
|
+
it "should list all application sources" do
|
7
|
+
post "/api/list_sources", {:app_name => @test_app_name, :api_token => @api_token}
|
8
|
+
JSON.parse(last_response.body).should == ["SimpleAdapter", "SampleAdapter"]
|
9
|
+
end
|
10
|
+
|
11
|
+
it "should list all application sources using partition_type param" do
|
12
|
+
post "/api/list_sources",
|
13
|
+
{:app_name => @test_app_name, :api_token => @api_token, :partition_type => 'all'}
|
14
|
+
JSON.parse(last_response.body).should == ["SimpleAdapter", "SampleAdapter"]
|
15
|
+
end
|
16
|
+
|
17
|
+
it "should list app partition sources" do
|
18
|
+
post "/api/list_sources", {:app_name => @test_app_name, :api_token => @api_token, :partition_type => :app}
|
19
|
+
JSON.parse(last_response.body).should == ["SimpleAdapter"]
|
20
|
+
end
|
21
|
+
|
22
|
+
it "should list user partition sources" do
|
23
|
+
post "/api/list_sources", {:app_name => @test_app_name, :api_token => @api_token, :partition_type => :user}
|
24
|
+
JSON.parse(last_response.body).should == ["SampleAdapter"]
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__),'api_helper')
|
2
|
+
|
3
|
+
describe "RhosyncApiListUsers" do
|
4
|
+
it_should_behave_like "ApiHelper"
|
5
|
+
|
6
|
+
it "should list users" do
|
7
|
+
params = {:app_name => @test_app_name, :api_token => @api_token,
|
8
|
+
:attributes => {:login => 'testuser1', :password => 'testpass1'}}
|
9
|
+
post "/api/create_user", params
|
10
|
+
last_response.should be_ok
|
11
|
+
post "/api/list_users", {:app_name => @test_app_name, :api_token => @api_token}
|
12
|
+
JSON.parse(last_response.body).should == ["testuser", "testuser1"]
|
13
|
+
end
|
14
|
+
|
15
|
+
it "should handle empty user's list" do
|
16
|
+
@a.delete; @a = App.create(@a_fields)
|
17
|
+
post "/api/list_users", {:app_name => @test_app_name, :api_token => @api_token}
|
18
|
+
JSON.parse(last_response.body).should == []
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__),'api_helper')
|
2
|
+
|
3
|
+
describe "RhosyncApiPing" do
|
4
|
+
it_should_behave_like "ApiHelper"
|
5
|
+
|
6
|
+
it "should do ping synchronously" do
|
7
|
+
params = {"user_id" => @u.id, "api_token" => @api_token,
|
8
|
+
"sources" => [@s.name], "message" => 'hello world',
|
9
|
+
"vibrate" => '5', "badge" => '5', "sound" => 'hello.mp3'}
|
10
|
+
PingJob.should_receive(:perform).once.with(params)
|
11
|
+
post "/api/ping", params
|
12
|
+
last_response.should be_ok
|
13
|
+
end
|
14
|
+
|
15
|
+
it "should do ping asynchronously" do
|
16
|
+
params = {"user_id" => @u.id, "api_token" => @api_token,
|
17
|
+
"async" => "true","sources" => [@s.name], "message" => 'hello world',
|
18
|
+
"vibrate" => '5', "badge" => '5', "sound" => 'hello.mp3'}
|
19
|
+
PingJob.should_receive(:enqueue).once.with(params)
|
20
|
+
post "/api/ping", params
|
21
|
+
last_response.should be_ok
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__),'api_helper')
|
2
|
+
|
3
|
+
describe "RhosyncApiPushDeletes" do
|
4
|
+
it_should_behave_like "ApiHelper"
|
5
|
+
|
6
|
+
it "should delete object from :md" do
|
7
|
+
data = {'1' => @product1, '2' => @product2, '3' => @product3}
|
8
|
+
set_state(@s.docname(:md) => data)
|
9
|
+
data.delete('2')
|
10
|
+
post "/api/push_deletes", :api_token => @api_token,
|
11
|
+
:user_id => @u.id, :source_id => @s_fields[:name], :objects => ['2']
|
12
|
+
last_response.should be_ok
|
13
|
+
verify_result(@s.docname(:md) => data,@s.docname(:md_size)=>'2')
|
14
|
+
end
|
15
|
+
|
16
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__),'api_helper')
|
2
|
+
|
3
|
+
describe "RhosyncApiPushObjects" do
|
4
|
+
it_should_behave_like "ApiHelper"
|
5
|
+
|
6
|
+
it "should push new objects to rhosync's :md" do
|
7
|
+
data = {'1' => @product1, '2' => @product2, '3' => @product3}
|
8
|
+
post "/api/push_objects", :api_token => @api_token,
|
9
|
+
:user_id => @u.id, :source_id => @s_fields[:name], :objects => data
|
10
|
+
last_response.should be_ok
|
11
|
+
verify_result(@s.docname(:md) => data,@s.docname(:md_size)=>'3')
|
12
|
+
end
|
13
|
+
|
14
|
+
it "should push updates to existing objects to rhosync's :md" do
|
15
|
+
data = {'1' => @product1, '2' => @product2, '3' => @product3}
|
16
|
+
update = {'price' => '0.99', 'new_field' => 'value'}
|
17
|
+
set_state(@s.docname(:md) => data)
|
18
|
+
update.each do |key,value|
|
19
|
+
data['2'][key] = value
|
20
|
+
end
|
21
|
+
post "/api/push_objects", :api_token => @api_token,
|
22
|
+
:user_id => @u.id, :source_id => @s_fields[:name], :objects => {'2'=>update}
|
23
|
+
last_response.should be_ok
|
24
|
+
verify_result(@s.docname(:md) => data,@s.docname(:md_size)=>'3')
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__),'api_helper')
|
2
|
+
|
3
|
+
describe "RhosyncApiReset" do
|
4
|
+
it_should_behave_like "ApiHelper"
|
5
|
+
|
6
|
+
it "should reset and re-create admin user with bootstrap" do
|
7
|
+
Store.put_data('somedoc',{'foo'=>'bar'})
|
8
|
+
post "/api/reset", :api_token => @api_token
|
9
|
+
App.is_exist?(@test_app_name).should == true
|
10
|
+
Store.get_data('somedoc').should == {}
|
11
|
+
User.authenticate('admin','').should_not be_nil
|
12
|
+
end
|
13
|
+
|
14
|
+
it "should reset and re-create admin user with initializer" do
|
15
|
+
Store.put_data('somedoc',{'foo'=>'bar'})
|
16
|
+
post "/api/reset", :api_token => @api_token
|
17
|
+
App.is_exist?(@test_app_name).should == true
|
18
|
+
Store.get_data('somedoc').should == {}
|
19
|
+
User.authenticate('admin','').should_not be_nil
|
20
|
+
load File.join(Rhosync.base_directory,@test_app_name+'.rb')
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__),'api_helper')
|
2
|
+
|
3
|
+
describe "RhosyncApiSetDbDoc" do
|
4
|
+
it_should_behave_like "ApiHelper"
|
5
|
+
|
6
|
+
it "should set db document by doc name and data" do
|
7
|
+
data = {'1' => {'foo' => 'bar'}}
|
8
|
+
post "/api/set_db_doc", :api_token => @api_token, :doc => 'abc:abc', :data => data
|
9
|
+
last_response.should be_ok
|
10
|
+
verify_result('abc:abc' => data)
|
11
|
+
end
|
12
|
+
|
13
|
+
it "should set db document by doc name, data type, and data" do
|
14
|
+
data = 'some string'
|
15
|
+
post "/api/set_db_doc", :api_token => @api_token, :doc => 'abc:abc:str', :data => data, :data_type => :string
|
16
|
+
last_response.should be_ok
|
17
|
+
verify_result('abc:abc:str' => data)
|
18
|
+
end
|
19
|
+
|
20
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__),'api_helper')
|
2
|
+
|
3
|
+
describe "RhosyncApiSetRefreshTime" do
|
4
|
+
it_should_behave_like "ApiHelper"
|
5
|
+
|
6
|
+
it "should set refresh time to 100s from 'now'" do
|
7
|
+
before = Time.now.to_i
|
8
|
+
post "/api/set_refresh_time", :api_token => @api_token, :source_name => @s_fields[:name],
|
9
|
+
:app_name => @a_fields[:name], :user_name => @u_fields[:login], :refresh_time => 100
|
10
|
+
after = Time.now.to_i
|
11
|
+
last_response.should be_ok
|
12
|
+
@s = Source.load(@s.id,@s_params)
|
13
|
+
@s.read_state.refresh_time.should >= before + 100
|
14
|
+
@s.read_state.refresh_time.should <= after + 100
|
15
|
+
end
|
16
|
+
|
17
|
+
it "should set refresh time to 'now' if no refresh_time provided" do
|
18
|
+
before = Time.now.to_i
|
19
|
+
post "/api/set_refresh_time", :api_token => @api_token, :source_name => @s_fields[:name],
|
20
|
+
:app_name => @a_fields[:name], :user_name => @u_fields[:login]
|
21
|
+
after = Time.now.to_i
|
22
|
+
last_response.should be_ok
|
23
|
+
@s = Source.load(@s.id,@s_params)
|
24
|
+
@s.read_state.refresh_time.should >= before
|
25
|
+
@s.read_state.refresh_time.should <= after
|
26
|
+
end
|
27
|
+
|
28
|
+
it "should set poll interval" do
|
29
|
+
post "/api/set_refresh_time", :api_token => @api_token, :source_name => @s_fields[:name],
|
30
|
+
:app_name => @a_fields[:name], :user_name => @u_fields[:login], :poll_interval => 100
|
31
|
+
last_response.should be_ok
|
32
|
+
@s = Source.load(@s.id,@s_params)
|
33
|
+
@s.poll_interval.should == 100
|
34
|
+
end
|
35
|
+
|
36
|
+
it "should should not set nil poll interval" do
|
37
|
+
post "/api/set_refresh_time", :api_token => @api_token, :source_name => @s_fields[:name],
|
38
|
+
:app_name => @a_fields[:name], :user_name => @u_fields[:login], :poll_interval => nil
|
39
|
+
last_response.should be_ok
|
40
|
+
@s = Source.load(@s.id,@s_params)
|
41
|
+
@s.poll_interval.should == 300
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__),'api_helper')
|
2
|
+
|
3
|
+
describe "RhosyncApiUpdateUser" do
|
4
|
+
it_should_behave_like "ApiHelper"
|
5
|
+
|
6
|
+
it "should update user successfully" do
|
7
|
+
post "/api/update_user", :api_token => @api_token,
|
8
|
+
:attributes => {:new_password => '123'}
|
9
|
+
last_response.should be_ok
|
10
|
+
user = User.authenticate('admin','123')
|
11
|
+
user.login.should == 'admin'
|
12
|
+
user.admin.should == 1
|
13
|
+
end
|
14
|
+
|
15
|
+
it "should fail to update user with wrong attributes" do
|
16
|
+
post "/api/update_user", :api_token => @api_token,
|
17
|
+
:attributes => {:missingattrib => '123'}
|
18
|
+
last_response.status.should == 500
|
19
|
+
last_response.body.match('undefined method').should_not be_nil
|
20
|
+
end
|
21
|
+
|
22
|
+
it "should not update login attribute for user" do
|
23
|
+
post "/api/update_user", :api_token => @api_token,
|
24
|
+
:attributes => {:new_password => '123', :login => 'admin1'}
|
25
|
+
last_response.should be_ok
|
26
|
+
user = User.authenticate('admin','123')
|
27
|
+
user.login.should == 'admin'
|
28
|
+
user.admin.should == 1
|
29
|
+
User.is_exist?('admin1').should == false
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__),'api_helper')
|
2
|
+
|
3
|
+
describe "RhosyncApiUploadFile" do
|
4
|
+
it_should_behave_like "ApiHelper"
|
5
|
+
|
6
|
+
it "should upload and unzip file" do
|
7
|
+
file = File.join(File.dirname(__FILE__),'..','testdata','compressed')
|
8
|
+
compress(file)
|
9
|
+
zipfile = File.join(file,"compressed.zip")
|
10
|
+
post "/api/upload_file", :app_name => @test_app_name, :api_token => @api_token,
|
11
|
+
:upload_file => Rack::Test::UploadedFile.new(zipfile, "application/octet-stream")
|
12
|
+
FileUtils.rm zipfile
|
13
|
+
expected = File.join(Rhosync.app_directory,'compress-data.txt')
|
14
|
+
File.exists?(expected).should == true
|
15
|
+
File.read(expected).should == 'some compressed text'
|
16
|
+
FileUtils.rm expected
|
17
|
+
end
|
18
|
+
|
19
|
+
it "should fail to upload a non-zip file" do
|
20
|
+
file = File.join(File.dirname(__FILE__),'..','testdata','compressed','compress-data.txt')
|
21
|
+
post "/api/upload_file", :app_name => @test_app_name, :api_token => @api_token,
|
22
|
+
:upload_file => Rack::Test::UploadedFile.new(file, "application/octet-stream")
|
23
|
+
last_response.status.should == 500
|
24
|
+
File.exists?(File.join(Rhosync.app_directory,'compress-data.txt')).should == false
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__),'spec_helper')
|
2
|
+
|
3
|
+
describe "ApiToken" do
|
4
|
+
it_should_behave_like "SpecBootstrapHelper"
|
5
|
+
it_should_behave_like "SourceAdapterHelper"
|
6
|
+
|
7
|
+
it "should generate api token with user" do
|
8
|
+
token = ApiToken.create(:user_id => @u.id)
|
9
|
+
token.value.length.should == 32
|
10
|
+
token.user_id.should == @u.id
|
11
|
+
token.user.login.should == @u.login
|
12
|
+
end
|
13
|
+
end
|
data/spec/app_spec.rb
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__),'spec_helper')
|
2
|
+
|
3
|
+
describe "App" do
|
4
|
+
it_should_behave_like "SpecBootstrapHelper"
|
5
|
+
it_should_behave_like "SourceAdapterHelper"
|
6
|
+
|
7
|
+
it "should create app with fields" do
|
8
|
+
@a.id.should == @a_fields[:name]
|
9
|
+
@a1 = App.load(@a_fields[:name])
|
10
|
+
@a1.id.should == @a.id
|
11
|
+
@a1.name.should == @a_fields[:name]
|
12
|
+
end
|
13
|
+
|
14
|
+
it "should add source adapters" do
|
15
|
+
@a.sources << "SimpleAdapter"
|
16
|
+
@a.sources << "SampleAdapter"
|
17
|
+
@a1 = App.load(@a_fields[:name])
|
18
|
+
@a1.sources.members.sort.should == ["SampleAdapter", "SimpleAdapter"]
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
# Dummy Rakefile for testing...
|
@@ -0,0 +1,16 @@
|
|
1
|
+
class Application < Rhosync::Base
|
2
|
+
class << self
|
3
|
+
def authenticate(username,password,session)
|
4
|
+
session[:auth] = "delegated"
|
5
|
+
password == 'wrongpass' ? false : true
|
6
|
+
end
|
7
|
+
|
8
|
+
# Add hooks for application startup here
|
9
|
+
# Don't forget to call super at the end!
|
10
|
+
def initializer(path)
|
11
|
+
super
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
Application.initializer(File.dirname(__FILE__))
|
@@ -0,0 +1 @@
|
|
1
|
+
# Dummy config.ru for testing...
|
@@ -0,0 +1 @@
|
|
1
|
+
This is fake!
|
@@ -0,0 +1 @@
|
|
1
|
+
858fc60fadfde40273d0ac505906969318aa4931d1a2c4aeb24d98393c74379f60e226651601969874257f7f1fbda9b099ecd551a641519aa46819947fda0191
|