waz-storage 1.2.0 → 1.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.gitignore +9 -9
- data/CHANGELOG.rdoc +72 -72
- data/Gemfile +4 -4
- data/Gemfile.lock +46 -40
- data/LICENSE +18 -18
- data/README.rdoc +310 -310
- data/lib/waz-blobs.rb +4 -4
- data/lib/waz-queues.rb +6 -6
- data/lib/waz-storage.rb +39 -39
- data/lib/waz-tables.rb +4 -4
- data/lib/waz/blobs/blob_object.rb +122 -122
- data/lib/waz/blobs/container.rb +172 -161
- data/lib/waz/blobs/exceptions.rb +10 -10
- data/lib/waz/blobs/service.rb +181 -156
- data/lib/waz/queues/exceptions.rb +28 -28
- data/lib/waz/queues/message.rb +64 -64
- data/lib/waz/queues/queue.rb +164 -164
- data/lib/waz/queues/service.rb +105 -105
- data/lib/waz/storage/base.rb +70 -70
- data/lib/waz/storage/exceptions.rb +33 -33
- data/lib/waz/storage/validation_rules.rb +25 -25
- data/lib/waz/tables/edm_type_helper.rb +44 -44
- data/lib/waz/tables/exceptions.rb +44 -44
- data/lib/waz/tables/service.rb +178 -178
- data/lib/waz/tables/table.rb +74 -74
- data/lib/waz/tables/table_array.rb +10 -10
- data/rakefile +8 -21
- data/{tests → spec}/configuration.rb +22 -22
- data/{tests/waz/blobs/blob_object_test.rb → spec/waz/blobs/blob_object_spec.rb} +80 -80
- data/{tests/waz/blobs/container_test.rb → spec/waz/blobs/container_spec.rb} +175 -162
- data/{tests/waz/blobs/service_test.rb → spec/waz/blobs/service_spec.rb} +336 -282
- data/{tests/waz/queues/message_test.rb → spec/waz/queues/message_spec.rb} +32 -32
- data/{tests/waz/queues/queue_test.rb → spec/waz/queues/queue_spec.rb} +205 -205
- data/{tests/waz/queues/service_test.rb → spec/waz/queues/service_spec.rb} +298 -298
- data/{tests → spec}/waz/storage/base_tests.rb +81 -81
- data/{tests/waz/storage/shared_key_core_service_test.rb → spec/waz/storage/shared_key_core_service_spec.rb} +141 -141
- data/{tests/waz/tables/service_test.rb → spec/waz/tables/service_spec.rb} +613 -613
- data/{tests/waz/tables/table_test.rb → spec/waz/tables/table_spec.rb} +97 -97
- data/waz-storage.gemspec +29 -27
- metadata +47 -26
@@ -1,81 +1,81 @@
|
|
1
|
-
# enabling the load of files from root (on RSpec)
|
2
|
-
$LOAD_PATH.unshift(File.dirname(__FILE__) + '/../')
|
3
|
-
require '
|
4
|
-
require 'lib/waz-blobs'
|
5
|
-
|
6
|
-
describe "Base class for connection management" do
|
7
|
-
it "should throw an exception when it is not connected" do
|
8
|
-
lambda {WAZ::Storage::Base.default_connection}.should raise_error(WAZ::Storage::NotConnected)
|
9
|
-
end
|
10
|
-
|
11
|
-
it "establish connection and set it as default connection" do
|
12
|
-
WAZ::Storage::Base.establish_connection!(:account_name => 'myAccount',
|
13
|
-
:access_key => "accountKey",
|
14
|
-
:use_ssl => true)
|
15
|
-
|
16
|
-
connection = WAZ::Storage::Base.default_connection
|
17
|
-
connection[:account_name].should == "myAccount"
|
18
|
-
connection[:access_key].should == "accountKey"
|
19
|
-
connection[:use_ssl].should == true
|
20
|
-
end
|
21
|
-
|
22
|
-
it "should throw an exception when no account_name is provided" do
|
23
|
-
lambda {WAZ::Storage::Base.establish_connection!(:access_key => "accountKey", :use_ssl => false)}.should raise_error(WAZ::Storage::InvalidOption)
|
24
|
-
end
|
25
|
-
|
26
|
-
it "should throw an exception when no access_key is provided and no use_sas_auth_only" do
|
27
|
-
lambda {WAZ::Storage::Base.establish_connection!(:account_name => "my_account", :use_ssl => false)}.should raise_error(WAZ::Storage::InvalidOption)
|
28
|
-
end
|
29
|
-
|
30
|
-
it "should throw and exception when use_sas_auth_only is provided but no sharedaccessignature" do
|
31
|
-
lambda {WAZ::Storage::Base.establish_connection!(:account_name => "my_account",:use_sas_auth_only => true, :use_ssl => false)}.should raise_error(WAZ::Storage::InvalidOption)
|
32
|
-
end
|
33
|
-
|
34
|
-
|
35
|
-
it "should set use_ssl to false when no paramter provided" do
|
36
|
-
WAZ::Storage::Base.establish_connection!(:account_name => 'myAccount',
|
37
|
-
:access_key => "accountKey")
|
38
|
-
|
39
|
-
connection = WAZ::Storage::Base.default_connection
|
40
|
-
connection[:account_name].should == "myAccount"
|
41
|
-
connection[:access_key].should == "accountKey"
|
42
|
-
connection[:use_ssl].should == false
|
43
|
-
end
|
44
|
-
|
45
|
-
it "should set :use_sas_auth_only to false when no parameter provided" do
|
46
|
-
WAZ::Storage::Base.establish_connection!(:account_name => 'myAccount',
|
47
|
-
:access_key => "accountKey")
|
48
|
-
connection = WAZ::Storage::Base.default_connection
|
49
|
-
connection[:account_name].should == "myAccount"
|
50
|
-
connection[:access_key].should == "accountKey"
|
51
|
-
connection[:use_sas_auth_only] == false
|
52
|
-
end
|
53
|
-
|
54
|
-
|
55
|
-
it "should be able to tell whether it's connected or not" do
|
56
|
-
WAZ::Storage::Base.establish_connection!(:account_name => 'myAccount',
|
57
|
-
:access_key => "accountKey")
|
58
|
-
|
59
|
-
WAZ::Storage::Base.connected?.should == true
|
60
|
-
end
|
61
|
-
|
62
|
-
it "should be able to tell whters it's connected by shared access signature" do
|
63
|
-
WAZ::Storage::Base.establish_connection!(:account_name => 'myAccount',:use_sas_auth_only=>true, :sharedaccesssignature=>"?se=2011-12-13T23%3A54%3A07Z&sr=c&si=escrituraPAC&sig=e%2Bz6wsGhVRg%2FaxWATiS8A4WjWU%2FbfWjWa6zJ%2BTQIPzM%3D")
|
64
|
-
WAZ::Storage::Base.connected?.should == true
|
65
|
-
end
|
66
|
-
|
67
|
-
it "should be able manage scoped connections" do
|
68
|
-
WAZ::Storage::Base.establish_connection!(:account_name => 'myAccount', :access_key => "accountKey")
|
69
|
-
|
70
|
-
WAZ::Storage::Base.default_connection[:account_name].should == 'myAccount'
|
71
|
-
|
72
|
-
block_executed = false
|
73
|
-
WAZ::Storage::Base.establish_connection(:account_name => 'otherAccount', :access_key => "accountKey") do
|
74
|
-
WAZ::Storage::Base.default_connection[:account_name].should == 'otherAccount'
|
75
|
-
block_executed = true
|
76
|
-
end
|
77
|
-
block_executed.should == true
|
78
|
-
|
79
|
-
WAZ::Storage::Base.default_connection[:account_name].should == 'myAccount'
|
80
|
-
end
|
81
|
-
end
|
1
|
+
# enabling the load of files from root (on RSpec)
|
2
|
+
$LOAD_PATH.unshift(File.dirname(__FILE__) + '/../')
|
3
|
+
require 'spec/configuration'
|
4
|
+
require 'lib/waz-blobs'
|
5
|
+
|
6
|
+
describe "Base class for connection management" do
|
7
|
+
it "should throw an exception when it is not connected" do
|
8
|
+
lambda {WAZ::Storage::Base.default_connection}.should raise_error(WAZ::Storage::NotConnected)
|
9
|
+
end
|
10
|
+
|
11
|
+
it "establish connection and set it as default connection" do
|
12
|
+
WAZ::Storage::Base.establish_connection!(:account_name => 'myAccount',
|
13
|
+
:access_key => "accountKey",
|
14
|
+
:use_ssl => true)
|
15
|
+
|
16
|
+
connection = WAZ::Storage::Base.default_connection
|
17
|
+
connection[:account_name].should == "myAccount"
|
18
|
+
connection[:access_key].should == "accountKey"
|
19
|
+
connection[:use_ssl].should == true
|
20
|
+
end
|
21
|
+
|
22
|
+
it "should throw an exception when no account_name is provided" do
|
23
|
+
lambda {WAZ::Storage::Base.establish_connection!(:access_key => "accountKey", :use_ssl => false)}.should raise_error(WAZ::Storage::InvalidOption)
|
24
|
+
end
|
25
|
+
|
26
|
+
it "should throw an exception when no access_key is provided and no use_sas_auth_only" do
|
27
|
+
lambda {WAZ::Storage::Base.establish_connection!(:account_name => "my_account", :use_ssl => false)}.should raise_error(WAZ::Storage::InvalidOption)
|
28
|
+
end
|
29
|
+
|
30
|
+
it "should throw and exception when use_sas_auth_only is provided but no sharedaccessignature" do
|
31
|
+
lambda {WAZ::Storage::Base.establish_connection!(:account_name => "my_account",:use_sas_auth_only => true, :use_ssl => false)}.should raise_error(WAZ::Storage::InvalidOption)
|
32
|
+
end
|
33
|
+
|
34
|
+
|
35
|
+
it "should set use_ssl to false when no paramter provided" do
|
36
|
+
WAZ::Storage::Base.establish_connection!(:account_name => 'myAccount',
|
37
|
+
:access_key => "accountKey")
|
38
|
+
|
39
|
+
connection = WAZ::Storage::Base.default_connection
|
40
|
+
connection[:account_name].should == "myAccount"
|
41
|
+
connection[:access_key].should == "accountKey"
|
42
|
+
connection[:use_ssl].should == false
|
43
|
+
end
|
44
|
+
|
45
|
+
it "should set :use_sas_auth_only to false when no parameter provided" do
|
46
|
+
WAZ::Storage::Base.establish_connection!(:account_name => 'myAccount',
|
47
|
+
:access_key => "accountKey")
|
48
|
+
connection = WAZ::Storage::Base.default_connection
|
49
|
+
connection[:account_name].should == "myAccount"
|
50
|
+
connection[:access_key].should == "accountKey"
|
51
|
+
connection[:use_sas_auth_only] == false
|
52
|
+
end
|
53
|
+
|
54
|
+
|
55
|
+
it "should be able to tell whether it's connected or not" do
|
56
|
+
WAZ::Storage::Base.establish_connection!(:account_name => 'myAccount',
|
57
|
+
:access_key => "accountKey")
|
58
|
+
|
59
|
+
WAZ::Storage::Base.connected?.should == true
|
60
|
+
end
|
61
|
+
|
62
|
+
it "should be able to tell whters it's connected by shared access signature" do
|
63
|
+
WAZ::Storage::Base.establish_connection!(:account_name => 'myAccount',:use_sas_auth_only=>true, :sharedaccesssignature=>"?se=2011-12-13T23%3A54%3A07Z&sr=c&si=escrituraPAC&sig=e%2Bz6wsGhVRg%2FaxWATiS8A4WjWU%2FbfWjWa6zJ%2BTQIPzM%3D")
|
64
|
+
WAZ::Storage::Base.connected?.should == true
|
65
|
+
end
|
66
|
+
|
67
|
+
it "should be able manage scoped connections" do
|
68
|
+
WAZ::Storage::Base.establish_connection!(:account_name => 'myAccount', :access_key => "accountKey")
|
69
|
+
|
70
|
+
WAZ::Storage::Base.default_connection[:account_name].should == 'myAccount'
|
71
|
+
|
72
|
+
block_executed = false
|
73
|
+
WAZ::Storage::Base.establish_connection(:account_name => 'otherAccount', :access_key => "accountKey") do
|
74
|
+
WAZ::Storage::Base.default_connection[:account_name].should == 'otherAccount'
|
75
|
+
block_executed = true
|
76
|
+
end
|
77
|
+
block_executed.should == true
|
78
|
+
|
79
|
+
WAZ::Storage::Base.default_connection[:account_name].should == 'myAccount'
|
80
|
+
end
|
81
|
+
end
|
@@ -1,142 +1,142 @@
|
|
1
|
-
# enabling the load of files from root (on RSpec)
|
2
|
-
$LOAD_PATH.unshift(File.dirname(__FILE__) + '/../')
|
3
|
-
require '
|
4
|
-
require 'lib/waz-queues'
|
5
|
-
|
6
|
-
describe "storage service core behavior" do
|
7
|
-
it "should generate URI with given operation" do
|
8
|
-
service = WAZ::Queues::Service.new(:account_name => "mock-account", :access_key => "mock-key", :type_of_service => "queue", :use_ssl => true, :base_url => "localhost")
|
9
|
-
service.generate_request_uri(nil, :comp => 'list').should == "https://mock-account.queue.localhost/?comp=list"
|
10
|
-
end
|
11
|
-
|
12
|
-
it "should generate an URI without operation when operation is not given" do
|
13
|
-
service = WAZ::Queues::Service.new(:account_name => "mock-account", :access_key => "mock-key", :type_of_service => "queue", :use_ssl => true, :base_url => "localhost")
|
14
|
-
service.generate_request_uri("queue").should == "https://mock-account.queue.localhost/queue"
|
15
|
-
end
|
16
|
-
|
17
|
-
it "should generate a safe URI when path includes forward slash" do
|
18
|
-
service = WAZ::Queues::Service.new(:account_name => "mock-account", :access_key => "mock-key", :type_of_service => "queue", :use_ssl => true, :base_url => "localhost")
|
19
|
-
service.generate_request_uri("/queue").should == "https://mock-account.queue.localhost/queue"
|
20
|
-
end
|
21
|
-
|
22
|
-
it "should include additional parameters when given" do
|
23
|
-
service = WAZ::Queues::Service.new(:account_name => "mock-account", :access_key => "mock-key", :type_of_service => "queue", :use_ssl => true, :base_url => "localhost")
|
24
|
-
service.generate_request_uri("/queue", {:comp => 'list', :prefix => "p"}).should == "https://mock-account.queue.localhost/queue?comp=list&prefix=p"
|
25
|
-
end
|
26
|
-
|
27
|
-
it "should include additional parameters when given althought when there is no comp" do
|
28
|
-
service = WAZ::Queues::Service.new(:account_name => "mock-account", :access_key => "mock-key", :type_of_service => "queue", :use_ssl => true, :base_url => "localhost")
|
29
|
-
service.generate_request_uri("/queue", {:prefix => "p", :other => "other"}).should == "https://mock-account.queue.localhost/queue?other=other&prefix=p"
|
30
|
-
end
|
31
|
-
|
32
|
-
it "should include additional parameters when given althought when there is no comp" do
|
33
|
-
service = WAZ::Queues::Service.new(:account_name => "mock-account", :access_key => "mock-key", :type_of_service => "queue", :use_ssl => true, :base_url => "localhost")
|
34
|
-
service.generate_request_uri("/queue", {:comp => "metadata", :messagettl => 650}).should == "https://mock-account.queue.localhost/queue?comp=metadata&messagettl=650"
|
35
|
-
end
|
36
|
-
|
37
|
-
it "should include additional parameters when given althought when there is no comp" do
|
38
|
-
service = WAZ::Queues::Service.new(:account_name => "mock-account", :access_key => "mock-key", :type_of_service => "queue", :use_ssl => true, :base_url => "localhost")
|
39
|
-
service.generate_request_uri("/queue", {:item => "%"}).should == "https://mock-account.queue.localhost/queue?item=%25"
|
40
|
-
end
|
41
|
-
|
42
|
-
it "should canonicalize headers (order lexicographical, trim values, and join by NEW_LINES)" do
|
43
|
-
service = WAZ::Queues::Service.new(:account_name => "mock-account", :access_key => "mock-key", :type_of_service => "queue", :use_ssl => true, :base_url => "localhost")
|
44
|
-
headers = { "Content-Type" => "application/xml",
|
45
|
-
"x-ms-prop-z" => "p",
|
46
|
-
"x-ms-meta-name" => "a ",
|
47
|
-
"x-other" => "other"}
|
48
|
-
|
49
|
-
service.canonicalize_headers(headers).should == "x-ms-meta-name:a\nx-ms-prop-z:p"
|
50
|
-
end
|
51
|
-
|
52
|
-
it "should return empty string when no MS headers" do
|
53
|
-
service = WAZ::Queues::Service.new(:account_name => "mock-account", :access_key => "mock-key", :type_of_service => "queue", :use_ssl => true, :base_url => "localhost")
|
54
|
-
headers = { "Content-Type" => "application/xml",
|
55
|
-
"x-other" => "other"}
|
56
|
-
|
57
|
-
service.canonicalize_headers(headers).should == ""
|
58
|
-
end
|
59
|
-
|
60
|
-
it "should cannonicalize message by appending account_name to the request path" do
|
61
|
-
service = WAZ::Queues::Service.new(:account_name => "mock-account", :access_key => "mock-key", :type_of_service => "queue", :use_ssl => true, :base_url => "localhost")
|
62
|
-
service.canonicalize_message("http://localhost/queue?comp=list").should == "/mock-account/queue?comp=list"
|
63
|
-
end
|
64
|
-
|
65
|
-
it "should ignore every other querystring parameter rather than comp=" do
|
66
|
-
service = WAZ::Queues::Service.new(:account_name => "mock-account", :access_key => "mock-key", :type_of_service => "queue", :use_ssl => true, :base_url => "localhost")
|
67
|
-
service.canonicalize_message("http://localhost/queue?myparam=1").should == "/mock-account/queue"
|
68
|
-
end
|
69
|
-
|
70
|
-
it "should properly canonicalize message when no parameter associated with it" do
|
71
|
-
service = WAZ::Queues::Service.new(:account_name => "mock-account", :access_key => "mock-key", :type_of_service => "queue", :use_ssl => true, :base_url => "localhost")
|
72
|
-
service.canonicalize_message("http://mock-account.queue.core.windows.net/").should == "/mock-account/"
|
73
|
-
end
|
74
|
-
|
75
|
-
it "should properly canonicalize message when a resource is associated with it" do
|
76
|
-
service = WAZ::Queues::Service.new(:account_name => "mock-account", :access_key => "mock-key", :type_of_service => "queue", :use_ssl => true, :base_url => "localhost")
|
77
|
-
service.canonicalize_message("http://mock-account.queue.core.windows.net/resource?comp=list").should == "/mock-account/resource?comp=list"
|
78
|
-
end
|
79
|
-
|
80
|
-
it "should generate request with proper headers" do
|
81
|
-
mock_time = Time.new
|
82
|
-
Time.stubs(:new).returns(mock_time)
|
83
|
-
service = WAZ::Queues::Service.new(:account_name => "mock-account", :access_key => "mock-key", :type_of_service => "queue", :use_ssl => true, :base_url => "localhost")
|
84
|
-
|
85
|
-
expected_request_hash = {:headers => {'x-ms-Date' => mock_time.httpdate, "Content-Length" => "payload".length},
|
86
|
-
:method => :put,
|
87
|
-
:url => "http://localhost/johnny",
|
88
|
-
:payload => "payload"}
|
89
|
-
|
90
|
-
# mock the generate signature method since we want to assert against a know value
|
91
|
-
service.expects(:generate_signature).with(expected_request_hash).returns("a_mock_signature")
|
92
|
-
|
93
|
-
request = service.generate_request("PUT", "http://localhost/johnny", nil, "payload")
|
94
|
-
request.headers["x-ms-Date"].should == mock_time.httpdate
|
95
|
-
request.headers["Content-Length"].should == "payload".length
|
96
|
-
request.headers["Authorization"] = "SharedKey mock-account:a_mock_signature"
|
97
|
-
end
|
98
|
-
|
99
|
-
it "should set content length when it is not provided" do
|
100
|
-
mock_time = Time.new
|
101
|
-
Time.stubs(:new).returns(mock_time)
|
102
|
-
service = WAZ::Queues::Service.new(:account_name => "mock-account", :access_key => "mock-key", :type_of_service => "queue", :use_ssl => true, :base_url => "localhost")
|
103
|
-
|
104
|
-
expected_request_hash = {:headers => {'x-ms-Date' => mock_time.httpdate, 'Content-Length' => 0},
|
105
|
-
:method => :put,
|
106
|
-
:url => "http://localhost/johnny",
|
107
|
-
:payload => nil}
|
108
|
-
|
109
|
-
# mock the generate signature method since we want to assert against a know value
|
110
|
-
service.expects(:generate_signature).with(expected_request_hash).returns("a_mock_signature")
|
111
|
-
|
112
|
-
request = service.generate_request("PUT", "http://localhost/johnny", nil)
|
113
|
-
request.headers["x-ms-Date"].should == mock_time.httpdate
|
114
|
-
request.headers["Content-Length"].should == 0
|
115
|
-
request.headers["Authorization"] = "SharedKey mock-account:a_mock_signature"
|
116
|
-
end
|
117
|
-
|
118
|
-
it "should name headers properly when they are provided as symbols" do
|
119
|
-
mock_time = Time.new
|
120
|
-
Time.stubs(:new).returns(mock_time)
|
121
|
-
service = WAZ::Queues::Service.new(:account_name => "mock-account", :access_key => "mock-key", :type_of_service => "queue", :use_ssl => true, :base_url => "localhost")
|
122
|
-
|
123
|
-
expected_request_hash = {:headers => {'x-ms-Date' => mock_time.httpdate, "Content-Length" => 0, 'Content-Type' => "plain/xml"},
|
124
|
-
:method => :put,
|
125
|
-
:url => "http://localhost/johnny",
|
126
|
-
:payload => nil}
|
127
|
-
|
128
|
-
# mock the generate signature method since we want to assert against a know value
|
129
|
-
service.expects(:generate_signature).with(expected_request_hash).returns("a_mock_signature")
|
130
|
-
|
131
|
-
request = service.generate_request("PUT", "http://localhost/johnny", {:Content_Type => "plain/xml"})
|
132
|
-
request.headers["x-ms-Date"].should == mock_time.httpdate
|
133
|
-
request.headers["Content-Length"].should == 0
|
134
|
-
request.headers["Authorization"] = "SharedKey mock-account:a_mock_signature"
|
135
|
-
end
|
136
|
-
|
137
|
-
it "should cannonicalize message by appending account_name to the request path following 2009-09-19 version of the API" do
|
138
|
-
service = WAZ::Queues::Service.new(:account_name => "myaccount", :access_key => "mock-key", :type_of_service => "queue", :use_ssl => true, :base_url => "localhost")
|
139
|
-
canonical_message = service.canonicalize_message20090919("http://myaccount.blob.core.windows.net/mycontainer?restype=container&comp=metadata")
|
140
|
-
canonical_message.should == "/myaccount/mycontainer\ncomp:metadata\nrestype:container"
|
141
|
-
end
|
1
|
+
# enabling the load of files from root (on RSpec)
|
2
|
+
$LOAD_PATH.unshift(File.dirname(__FILE__) + '/../')
|
3
|
+
require 'spec/configuration'
|
4
|
+
require 'lib/waz-queues'
|
5
|
+
|
6
|
+
describe "storage service core behavior" do
|
7
|
+
it "should generate URI with given operation" do
|
8
|
+
service = WAZ::Queues::Service.new(:account_name => "mock-account", :access_key => "mock-key", :type_of_service => "queue", :use_ssl => true, :base_url => "localhost")
|
9
|
+
service.generate_request_uri(nil, :comp => 'list').should == "https://mock-account.queue.localhost/?comp=list"
|
10
|
+
end
|
11
|
+
|
12
|
+
it "should generate an URI without operation when operation is not given" do
|
13
|
+
service = WAZ::Queues::Service.new(:account_name => "mock-account", :access_key => "mock-key", :type_of_service => "queue", :use_ssl => true, :base_url => "localhost")
|
14
|
+
service.generate_request_uri("queue").should == "https://mock-account.queue.localhost/queue"
|
15
|
+
end
|
16
|
+
|
17
|
+
it "should generate a safe URI when path includes forward slash" do
|
18
|
+
service = WAZ::Queues::Service.new(:account_name => "mock-account", :access_key => "mock-key", :type_of_service => "queue", :use_ssl => true, :base_url => "localhost")
|
19
|
+
service.generate_request_uri("/queue").should == "https://mock-account.queue.localhost/queue"
|
20
|
+
end
|
21
|
+
|
22
|
+
it "should include additional parameters when given" do
|
23
|
+
service = WAZ::Queues::Service.new(:account_name => "mock-account", :access_key => "mock-key", :type_of_service => "queue", :use_ssl => true, :base_url => "localhost")
|
24
|
+
service.generate_request_uri("/queue", {:comp => 'list', :prefix => "p"}).should == "https://mock-account.queue.localhost/queue?comp=list&prefix=p"
|
25
|
+
end
|
26
|
+
|
27
|
+
it "should include additional parameters when given althought when there is no comp" do
|
28
|
+
service = WAZ::Queues::Service.new(:account_name => "mock-account", :access_key => "mock-key", :type_of_service => "queue", :use_ssl => true, :base_url => "localhost")
|
29
|
+
service.generate_request_uri("/queue", {:prefix => "p", :other => "other"}).should == "https://mock-account.queue.localhost/queue?other=other&prefix=p"
|
30
|
+
end
|
31
|
+
|
32
|
+
it "should include additional parameters when given althought when there is no comp" do
|
33
|
+
service = WAZ::Queues::Service.new(:account_name => "mock-account", :access_key => "mock-key", :type_of_service => "queue", :use_ssl => true, :base_url => "localhost")
|
34
|
+
service.generate_request_uri("/queue", {:comp => "metadata", :messagettl => 650}).should == "https://mock-account.queue.localhost/queue?comp=metadata&messagettl=650"
|
35
|
+
end
|
36
|
+
|
37
|
+
it "should include additional parameters when given althought when there is no comp" do
|
38
|
+
service = WAZ::Queues::Service.new(:account_name => "mock-account", :access_key => "mock-key", :type_of_service => "queue", :use_ssl => true, :base_url => "localhost")
|
39
|
+
service.generate_request_uri("/queue", {:item => "%"}).should == "https://mock-account.queue.localhost/queue?item=%25"
|
40
|
+
end
|
41
|
+
|
42
|
+
it "should canonicalize headers (order lexicographical, trim values, and join by NEW_LINES)" do
|
43
|
+
service = WAZ::Queues::Service.new(:account_name => "mock-account", :access_key => "mock-key", :type_of_service => "queue", :use_ssl => true, :base_url => "localhost")
|
44
|
+
headers = { "Content-Type" => "application/xml",
|
45
|
+
"x-ms-prop-z" => "p",
|
46
|
+
"x-ms-meta-name" => "a ",
|
47
|
+
"x-other" => "other"}
|
48
|
+
|
49
|
+
service.canonicalize_headers(headers).should == "x-ms-meta-name:a\nx-ms-prop-z:p"
|
50
|
+
end
|
51
|
+
|
52
|
+
it "should return empty string when no MS headers" do
|
53
|
+
service = WAZ::Queues::Service.new(:account_name => "mock-account", :access_key => "mock-key", :type_of_service => "queue", :use_ssl => true, :base_url => "localhost")
|
54
|
+
headers = { "Content-Type" => "application/xml",
|
55
|
+
"x-other" => "other"}
|
56
|
+
|
57
|
+
service.canonicalize_headers(headers).should == ""
|
58
|
+
end
|
59
|
+
|
60
|
+
it "should cannonicalize message by appending account_name to the request path" do
|
61
|
+
service = WAZ::Queues::Service.new(:account_name => "mock-account", :access_key => "mock-key", :type_of_service => "queue", :use_ssl => true, :base_url => "localhost")
|
62
|
+
service.canonicalize_message("http://localhost/queue?comp=list").should == "/mock-account/queue?comp=list"
|
63
|
+
end
|
64
|
+
|
65
|
+
it "should ignore every other querystring parameter rather than comp=" do
|
66
|
+
service = WAZ::Queues::Service.new(:account_name => "mock-account", :access_key => "mock-key", :type_of_service => "queue", :use_ssl => true, :base_url => "localhost")
|
67
|
+
service.canonicalize_message("http://localhost/queue?myparam=1").should == "/mock-account/queue"
|
68
|
+
end
|
69
|
+
|
70
|
+
it "should properly canonicalize message when no parameter associated with it" do
|
71
|
+
service = WAZ::Queues::Service.new(:account_name => "mock-account", :access_key => "mock-key", :type_of_service => "queue", :use_ssl => true, :base_url => "localhost")
|
72
|
+
service.canonicalize_message("http://mock-account.queue.core.windows.net/").should == "/mock-account/"
|
73
|
+
end
|
74
|
+
|
75
|
+
it "should properly canonicalize message when a resource is associated with it" do
|
76
|
+
service = WAZ::Queues::Service.new(:account_name => "mock-account", :access_key => "mock-key", :type_of_service => "queue", :use_ssl => true, :base_url => "localhost")
|
77
|
+
service.canonicalize_message("http://mock-account.queue.core.windows.net/resource?comp=list").should == "/mock-account/resource?comp=list"
|
78
|
+
end
|
79
|
+
|
80
|
+
it "should generate request with proper headers" do
|
81
|
+
mock_time = Time.new
|
82
|
+
Time.stubs(:new).returns(mock_time)
|
83
|
+
service = WAZ::Queues::Service.new(:account_name => "mock-account", :access_key => "mock-key", :type_of_service => "queue", :use_ssl => true, :base_url => "localhost")
|
84
|
+
|
85
|
+
expected_request_hash = {:headers => {'x-ms-Date' => mock_time.httpdate, "Content-Length" => "payload".length},
|
86
|
+
:method => :put,
|
87
|
+
:url => "http://localhost/johnny",
|
88
|
+
:payload => "payload"}
|
89
|
+
|
90
|
+
# mock the generate signature method since we want to assert against a know value
|
91
|
+
service.expects(:generate_signature).with(expected_request_hash).returns("a_mock_signature")
|
92
|
+
|
93
|
+
request = service.generate_request("PUT", "http://localhost/johnny", nil, "payload")
|
94
|
+
request.headers["x-ms-Date"].should == mock_time.httpdate
|
95
|
+
request.headers["Content-Length"].should == "payload".length
|
96
|
+
request.headers["Authorization"] = "SharedKey mock-account:a_mock_signature"
|
97
|
+
end
|
98
|
+
|
99
|
+
it "should set content length when it is not provided" do
|
100
|
+
mock_time = Time.new
|
101
|
+
Time.stubs(:new).returns(mock_time)
|
102
|
+
service = WAZ::Queues::Service.new(:account_name => "mock-account", :access_key => "mock-key", :type_of_service => "queue", :use_ssl => true, :base_url => "localhost")
|
103
|
+
|
104
|
+
expected_request_hash = {:headers => {'x-ms-Date' => mock_time.httpdate, 'Content-Length' => 0},
|
105
|
+
:method => :put,
|
106
|
+
:url => "http://localhost/johnny",
|
107
|
+
:payload => nil}
|
108
|
+
|
109
|
+
# mock the generate signature method since we want to assert against a know value
|
110
|
+
service.expects(:generate_signature).with(expected_request_hash).returns("a_mock_signature")
|
111
|
+
|
112
|
+
request = service.generate_request("PUT", "http://localhost/johnny", nil)
|
113
|
+
request.headers["x-ms-Date"].should == mock_time.httpdate
|
114
|
+
request.headers["Content-Length"].should == 0
|
115
|
+
request.headers["Authorization"] = "SharedKey mock-account:a_mock_signature"
|
116
|
+
end
|
117
|
+
|
118
|
+
it "should name headers properly when they are provided as symbols" do
|
119
|
+
mock_time = Time.new
|
120
|
+
Time.stubs(:new).returns(mock_time)
|
121
|
+
service = WAZ::Queues::Service.new(:account_name => "mock-account", :access_key => "mock-key", :type_of_service => "queue", :use_ssl => true, :base_url => "localhost")
|
122
|
+
|
123
|
+
expected_request_hash = {:headers => {'x-ms-Date' => mock_time.httpdate, "Content-Length" => 0, 'Content-Type' => "plain/xml"},
|
124
|
+
:method => :put,
|
125
|
+
:url => "http://localhost/johnny",
|
126
|
+
:payload => nil}
|
127
|
+
|
128
|
+
# mock the generate signature method since we want to assert against a know value
|
129
|
+
service.expects(:generate_signature).with(expected_request_hash).returns("a_mock_signature")
|
130
|
+
|
131
|
+
request = service.generate_request("PUT", "http://localhost/johnny", {:Content_Type => "plain/xml"})
|
132
|
+
request.headers["x-ms-Date"].should == mock_time.httpdate
|
133
|
+
request.headers["Content-Length"].should == 0
|
134
|
+
request.headers["Authorization"] = "SharedKey mock-account:a_mock_signature"
|
135
|
+
end
|
136
|
+
|
137
|
+
it "should cannonicalize message by appending account_name to the request path following 2009-09-19 version of the API" do
|
138
|
+
service = WAZ::Queues::Service.new(:account_name => "myaccount", :access_key => "mock-key", :type_of_service => "queue", :use_ssl => true, :base_url => "localhost")
|
139
|
+
canonical_message = service.canonicalize_message20090919("http://myaccount.blob.core.windows.net/mycontainer?restype=container&comp=metadata")
|
140
|
+
canonical_message.should == "/myaccount/mycontainer\ncomp:metadata\nrestype:container"
|
141
|
+
end
|
142
142
|
end
|
@@ -1,614 +1,614 @@
|
|
1
|
-
# enabling the load of files from root (on RSpec)
|
2
|
-
$LOAD_PATH.unshift(File.dirname(__FILE__) + '/../')
|
3
|
-
require '
|
4
|
-
require 'lib/waz-tables'
|
5
|
-
|
6
|
-
describe "tables service behavior" do
|
7
|
-
|
8
|
-
before do
|
9
|
-
@table_service = WAZ::Tables::Service.new(:account_name => "mock-account", :access_key => "mock-key", :type_of_service => "table", :use_ssl => true, :base_url => "localhost")
|
10
|
-
end
|
11
|
-
|
12
|
-
it "should get a table" do
|
13
|
-
response = <<-eos
|
14
|
-
<?xml version=\"1.0" encoding=\"utf-8" standalone=\"yes"?>
|
15
|
-
<entry xml:base=\"http://wazstoragejohnny.table.core.windows.net/" xmlns:d=\"http://schemas.microsoft.com/ado/2007/08/dataservices" xmlns:m=\"http://schemas.microsoft.com/ado/2007/08/dataservices/metadata" xmlns=\"http://www.w3.org/2005/Atom">
|
16
|
-
<id>http://myaccount.table.core.windows.net/Tables('table1')</id>
|
17
|
-
<title type=\"text"></title>
|
18
|
-
<updated>2009-12-28T02:00:21Z</updated>
|
19
|
-
<author>
|
20
|
-
<name />
|
21
|
-
</author>
|
22
|
-
<link rel=\"edit" title=\"Tables" href=\"Tables('table1')" />
|
23
|
-
<category term=\"wazstoragejohnny.Tables" scheme=\"http://schemas.microsoft.com/ado/2007/08/dataservices/scheme" />
|
24
|
-
<content type=\"application/xml">
|
25
|
-
<m:properties>
|
26
|
-
<d:TableName>table1</d:TableName>
|
27
|
-
</m:properties>
|
28
|
-
</content>
|
29
|
-
</entry>
|
30
|
-
eos
|
31
|
-
|
32
|
-
response.stubs(:headers).returns({:x_ms_continuation_nexttablename => 'next-table'})
|
33
|
-
|
34
|
-
RestClient::Request.any_instance.expects(:execute).returns(response)
|
35
|
-
@table_service.expects(:generate_request_uri).with("Tables('table1')", {}, nil).returns("http://localhost/Tables('table1')")
|
36
|
-
@table_service.expects(:generate_request).with(:get, "http://localhost/Tables('table1')", { 'Content-Type' => 'application/atom+xml', 'Date' => Time.new.httpdate, 'DataServiceVersion' => '1.0;NetFx', 'MaxDataServiceVersion' => '1.0;NetFx'}, nil).returns(RestClient::Request.new(:method => :get, :url => "http://localhost/Tables('table1')"))
|
37
|
-
table = @table_service.get_table('table1')
|
38
|
-
table[:name].should == 'table1'
|
39
|
-
table[:url].should == "http://myaccount.table.core.windows.net/Tables('table1')"
|
40
|
-
end
|
41
|
-
|
42
|
-
it "should list all tables" do
|
43
|
-
response = <<-eos
|
44
|
-
<?xml version=\"1.0" encoding=\"utf-8" standalone=\"yes"?>
|
45
|
-
<feed xml:base=\"http://myaccount.tables.core.windows.net/" xmlns:d=\"http://schemas.microsoft.com/ado/2007/08/dataservices" xmlns:m=\"http://schemas.microsoft.com/ado/2007/08/dataservices/metadata" xmlns=\"http://www.w3.org/2005/Atom">
|
46
|
-
<title type=\"text">Tables</title>
|
47
|
-
<id>http://myaccount.tables.core.windows.net/Tables</id>
|
48
|
-
<updated>2009-01-04T17:18:54.7062347Z</updated>
|
49
|
-
<link rel=\"self" title=\"Tables" href=\"Tables" />
|
50
|
-
<entry>
|
51
|
-
<id>http://myaccount.tables.core.windows.net/Tables('table1')</id>
|
52
|
-
<title type=\"text"></title>
|
53
|
-
<updated>2009-01-04T17:18:54.7062347Z</updated>
|
54
|
-
<author>
|
55
|
-
<name />
|
56
|
-
</author>
|
57
|
-
<link rel=\"edit" title=\"Tables" href=\"Tables('table1')" />
|
58
|
-
<category term=\"myaccount.Tables" scheme=\"http://schemas.microsoft.com/ado/2007/08/dataservices/scheme" />
|
59
|
-
<content type=\"application/xml">
|
60
|
-
<m:properties>
|
61
|
-
<d:TableName>table1</d:TableName>
|
62
|
-
</m:properties>
|
63
|
-
</content>
|
64
|
-
</entry>
|
65
|
-
<entry>
|
66
|
-
<id>http://myaccount.tables.core.windows.net/Tables('table2')</id>
|
67
|
-
<title type=\"text"></title>
|
68
|
-
<updated>2009-01-04T17:18:54.7062347Z</updated>
|
69
|
-
<author>
|
70
|
-
<name />
|
71
|
-
</author>
|
72
|
-
<link rel=\"edit" title=\"Tables" href=\"Tables('table2')" />
|
73
|
-
<category term=\"myaccount.Tables" scheme=\"http://schemas.microsoft.com/ado/2007/08/dataservices/scheme" />
|
74
|
-
<content type=\"application/xml">
|
75
|
-
<m:properties>
|
76
|
-
<d:TableName>table2</d:TableName>
|
77
|
-
</m:properties>
|
78
|
-
</content>
|
79
|
-
</entry>
|
80
|
-
</feed>
|
81
|
-
eos
|
82
|
-
response.stubs(:headers).returns({:x_ms_continuation_nexttablename => 'next-table'})
|
83
|
-
|
84
|
-
RestClient::Request.any_instance.expects(:execute).returns(response)
|
85
|
-
@table_service.expects(:generate_request_uri).with("Tables", {}, nil).returns("http://localhost/Tables")
|
86
|
-
@table_service.expects(:generate_request).with(:get, "http://localhost/Tables", {'Content-Type' => 'application/atom+xml', 'Date' => Time.new.httpdate, 'DataServiceVersion' => '1.0;NetFx', 'MaxDataServiceVersion' => '1.0;NetFx'}, nil).returns(RestClient::Request.new(:method => :get, :url => "http://localhost/Tables"))
|
87
|
-
tables, next_table_name = @table_service.list_tables
|
88
|
-
tables.length.should == 2
|
89
|
-
tables.first()[:name].should == 'table1'
|
90
|
-
tables.first()[:url].should == "http://myaccount.tables.core.windows.net/Tables('table1')"
|
91
|
-
tables.last()[:name].should == 'table2'
|
92
|
-
tables.last()[:url].should == "http://myaccount.tables.core.windows.net/Tables('table2')"
|
93
|
-
next_table_name.should == 'next-table'
|
94
|
-
end
|
95
|
-
|
96
|
-
it "should include the NextTableName parameter when a continuation token is provided" do
|
97
|
-
response = ''
|
98
|
-
response.stubs(:headers).returns({:x_ms_continuation_nexttablename => 'next-table'})
|
99
|
-
RestClient::Request.any_instance.expects(:execute).returns(response)
|
100
|
-
@table_service.expects(:generate_request_uri).with("Tables", { 'NextTableName' => 'next-table-name' }, nil).returns("http://localhost/Tables?NextTableName=next-table-name")
|
101
|
-
@table_service.expects(:generate_request).with(:get, "http://localhost/Tables?NextTableName=next-table-name", {'Content-Type' => 'application/atom+xml','Date' => Time.new.httpdate, 'DataServiceVersion' => '1.0;NetFx', 'MaxDataServiceVersion' => '1.0;NetFx'}, nil).returns(RestClient::Request.new(:method => :get, :url => "http://localhost/Tables?NextTableName=next-table-name"))
|
102
|
-
tables, next_table_name = @table_service.list_tables('next-table-name')
|
103
|
-
end
|
104
|
-
|
105
|
-
it "should create a table" do
|
106
|
-
expected_payload = "<?xml version=\"1.0\" encoding=\"utf-8\" standalone=\"yes\"?><entry xmlns:d=\"http://schemas.microsoft.com/ado/2007/08/dataservices\" xmlns:m=\"http://schemas.microsoft.com/ado/2007/08/dataservices/metadata\" xmlns=\"http://www.w3.org/2005/Atom\"><title /><updated>#{Time.now.utc.iso8601}</updated><author><name/></author><id/><content type=\"application/xml\"><m:properties><d:TableName>Customers</d:TableName></m:properties></content></entry>"
|
107
|
-
expected_headers = { 'Date' => Time.new.httpdate, 'Content-Type' => 'application/atom+xml', 'DataServiceVersion' => '1.0;NetFx', 'MaxDataServiceVersion' => '1.0;NetFx' }
|
108
|
-
RestClient::Request.any_instance.expects(:execute)
|
109
|
-
@table_service.expects(:generate_request_uri).with("Tables", {}).returns("http://localhost/Tables")
|
110
|
-
@table_service.expects(:generate_request).with(:post, "http://localhost/Tables", expected_headers, expected_payload).returns(RestClient::Request.new(:method => :post, :url => "http://localhost/Tables", :headers => expected_headers, :payload => expected_payload))
|
111
|
-
@table_service.create_table('Customers')
|
112
|
-
end
|
113
|
-
|
114
|
-
it "should throw when a table already exists" do
|
115
|
-
failed_response = RestClient::RequestFailed.new
|
116
|
-
failed_response.stubs(:http_code).returns(409)
|
117
|
-
RestClient::Request.any_instance.expects(:execute).raises(failed_response)
|
118
|
-
lambda { @table_service.create_table('existingtable') }.should raise_error(WAZ::Tables::TableAlreadyExists, "The table existingtable already exists on your account.")
|
119
|
-
end
|
120
|
-
|
121
|
-
it "should delete a table" do
|
122
|
-
expected_headers = { 'Date' => Time.new.httpdate, 'Content-Type' => 'application/atom+xml', 'DataServiceVersion' => '1.0;NetFx', 'MaxDataServiceVersion' => '1.0;NetFx' }
|
123
|
-
|
124
|
-
response = mock()
|
125
|
-
response.stubs(:code).returns(204)
|
126
|
-
RestClient::Request.any_instance.expects(:execute).returns(response)
|
127
|
-
@table_service.expects(:generate_request_uri).with("Tables('tabletodelete')", {}).returns("http://localhost/Tables('tabletodelete')")
|
128
|
-
@table_service.expects(:generate_request).with(:delete, "http://localhost/Tables('tabletodelete')", expected_headers, nil).returns(RestClient::Request.new(:method => :delete, :url => "http://localhost/Tables('tabletodelete')", :headers => expected_headers))
|
129
|
-
@table_service.delete_table('tabletodelete')
|
130
|
-
end
|
131
|
-
|
132
|
-
it "should throw when trying to get an unexisting table" do
|
133
|
-
failed_response = RestClient::ResourceNotFound.new
|
134
|
-
failed_response.stubs(:http_code).returns(404)
|
135
|
-
RestClient::Request.any_instance.expects(:execute).raises(failed_response)
|
136
|
-
lambda { @table_service.get_table('unexistingtable') }.should raise_error(WAZ::Tables::TableDoesNotExist, "The specified table unexistingtable does not exist.")
|
137
|
-
end
|
138
|
-
|
139
|
-
it "should throw when trying to delete an unexisting table" do
|
140
|
-
failed_response = RestClient::ResourceNotFound.new
|
141
|
-
failed_response.stubs(:http_code).returns(404)
|
142
|
-
RestClient::Request.any_instance.expects(:execute).raises(failed_response)
|
143
|
-
lambda { @table_service.delete_table('unexistingtable') }.should raise_error(WAZ::Tables::TableDoesNotExist, "The specified table unexistingtable does not exist.")
|
144
|
-
end
|
145
|
-
|
146
|
-
it "should insert a new entity" do
|
147
|
-
expected_payload = "<?xml version=\"1.0\" encoding=\"utf-8\" standalone=\"yes\"?>" \
|
148
|
-
"<entry xmlns:d=\"http://schemas.microsoft.com/ado/2007/08/dataservices\" xmlns:m=\"http://schemas.microsoft.com/ado/2007/08/dataservices/metadata\" xmlns=\"http://www.w3.org/2005/Atom\">" \
|
149
|
-
"<id>http://localhost/Customers(PartitionKey='myPartitionKey',RowKey='myRowKey1')</id>" \
|
150
|
-
"<title /><updated>#{Time.now.utc.iso8601}</updated><author><name /></author><link rel=\"edit\" title=\"Customers\" href=\"Customers(PartitionKey='myPartitionKey',RowKey='myRowKey1')\" />" \
|
151
|
-
"<content type=\"application/xml\">" \
|
152
|
-
"<m:properties>" \
|
153
|
-
"<d:address m:type=\"Edm.String\">Mountain View</d:address>" \
|
154
|
-
"<d:age m:type=\"Edm.Int32\">23</d:age>" \
|
155
|
-
"<d:amount_due m:type=\"Edm.Double\">200.23</d:amount_due>" \
|
156
|
-
"<d:binary_data m:type=\"Edm.Binary\" m:null=\"true\" />" \
|
157
|
-
"<d:customer_code m:type=\"Edm.Guid\">c9da6455-213d-42c9-9a79-3e9149a57833</d:customer_code>" \
|
158
|
-
"<d:customer_since m:type=\"Edm.DateTime\">#{Time.now.utc.iso8601}</d:customer_since>" \
|
159
|
-
"<d:is_active m:type=\"Edm.Boolean\">true</d:is_active>" \
|
160
|
-
"<d:num_of_orders m:type=\"Edm.Int64\">255</d:num_of_orders>" \
|
161
|
-
"<d:PartitionKey>myPartitionKey</d:PartitionKey>" \
|
162
|
-
"<d:RowKey>myRowKey1</d:RowKey>" \
|
163
|
-
"</m:properties></content></entry>"
|
164
|
-
|
165
|
-
expected_headers = {'Date' => Time.new.httpdate, 'DataServiceVersion' => '1.0;NetFx', 'Content-Type' => 'application/atom+xml', 'MaxDataServiceVersion' => '1.0;NetFx'}
|
166
|
-
|
167
|
-
RestClient::Request.any_instance.expects(:execute).returns(expected_payload)
|
168
|
-
@table_service.expects(:generate_request_uri).with("Customers").returns("http://localhost/Customers")
|
169
|
-
@table_service.expects(:generate_request_uri).with("Customers", {}).returns("http://localhost/Customers")
|
170
|
-
request = RestClient::Request.new(:method => :post, :url => "http://localhost/Customers", :headers => expected_headers, :payload => expected_payload)
|
171
|
-
@table_service.expects(:generate_request).with(:post, "http://localhost/Customers", expected_headers , expected_payload).returns(request)
|
172
|
-
|
173
|
-
:binary_data.edm_type = 'Edm.Binary'
|
174
|
-
:customer_code.edm_type = 'Edm.Guid'
|
175
|
-
:num_of_orders.edm_type = 'Edm.Int64'
|
176
|
-
|
177
|
-
entity = { :address => 'Mountain View',
|
178
|
-
:age => 23,
|
179
|
-
:amount_due => 200.23,
|
180
|
-
:binary_data => nil,
|
181
|
-
:customer_code => 'c9da6455-213d-42c9-9a79-3e9149a57833',
|
182
|
-
:customer_since => Time.now.utc,
|
183
|
-
:is_active => true,
|
184
|
-
:num_of_orders => 255,
|
185
|
-
:partition_key => 'myPartitionKey',
|
186
|
-
:row_key => 'myRowKey1' }
|
187
|
-
|
188
|
-
new_entity = @table_service.insert_entity('Customers', entity)
|
189
|
-
new_entity.length.should == 10
|
190
|
-
new_entity.reject{|k,v| entity.keys.include?(k) and entity.values.to_s.include?(v.to_s)}.length.should == 0
|
191
|
-
end
|
192
|
-
|
193
|
-
it "should update an existing entity" do
|
194
|
-
expected_payload = "<?xml version=\"1.0\" encoding=\"utf-8\" standalone=\"yes\"?>" \
|
195
|
-
"<entry xmlns:d=\"http://schemas.microsoft.com/ado/2007/08/dataservices\" xmlns:m=\"http://schemas.microsoft.com/ado/2007/08/dataservices/metadata\" xmlns=\"http://www.w3.org/2005/Atom\">" \
|
196
|
-
"<id>http://localhost/Customers(PartitionKey='myPartitionKey',RowKey='myRowKey1')</id>" \
|
197
|
-
"<title /><updated>#{Time.now.utc.iso8601}</updated><author><name /></author><link rel=\"edit\" title=\"Customers\" href=\"Customers(PartitionKey='myPartitionKey',RowKey='myRowKey1')\" />" \
|
198
|
-
"<content type=\"application/xml\">" \
|
199
|
-
"<m:properties>" \
|
200
|
-
"<d:Timestamp m:type=\"Edm.DateTime\">#{Time.now.utc.iso8601}</d:Timestamp>" \
|
201
|
-
"<d:address m:type=\"Edm.String\">Mountain View</d:address>" \
|
202
|
-
"<d:age m:type=\"Edm.Int32\">23</d:age>" \
|
203
|
-
"<d:amount_due m:type=\"Edm.Double\">200.23</d:amount_due>" \
|
204
|
-
"<d:binary_data m:type=\"Edm.Binary\">#{Base64.encode64(File.read(__FILE__))}</d:binary_data>" \
|
205
|
-
"<d:customer_code m:type=\"Edm.Guid\">c9da6455-213d-42c9-9a79-3e9149a57833</d:customer_code>" \
|
206
|
-
"<d:customer_since m:type=\"Edm.DateTime\">#{Time.now.utc.iso8601}</d:customer_since>" \
|
207
|
-
"<d:is_active m:type=\"Edm.Boolean\">true</d:is_active>" \
|
208
|
-
"<d:num_of_orders m:type=\"Edm.Int64\">255</d:num_of_orders>" \
|
209
|
-
"<d:PartitionKey>myPartitionKey</d:PartitionKey>" \
|
210
|
-
"<d:RowKey>myRowKey1</d:RowKey>" \
|
211
|
-
"</m:properties></content></entry>"
|
212
|
-
expected_headers = {'If-Match' => '*', 'Content-Type' => 'application/atom+xml', 'Date' => Time.new.httpdate, 'DataServiceVersion' => '1.0;NetFx', 'MaxDataServiceVersion' => '1.0;NetFx'}
|
213
|
-
expected_url = "http://localhost/Customers(PartitionKey='myPartitionKey',RowKey='myRowKey1')"
|
214
|
-
|
215
|
-
RestClient::Request.any_instance.expects(:execute).returns(expected_payload)
|
216
|
-
@table_service.expects(:generate_request_uri).with("Customers").returns("http://localhost/Customers")
|
217
|
-
@table_service.expects(:generate_request_uri).with("Customers(PartitionKey='myPartitionKey',RowKey='myRowKey1')", {}).returns(expected_url)
|
218
|
-
request = RestClient::Request.new(:method => :put, :url => expected_url, :headers => expected_headers, :payload => expected_payload)
|
219
|
-
@table_service.expects(:generate_request).with(:put, expected_url, expected_headers , expected_payload).returns(request)
|
220
|
-
|
221
|
-
:binary_data.edm_type = 'Edm.Binary'
|
222
|
-
:customer_code.edm_type = 'Edm.Guid'
|
223
|
-
:num_of_orders.edm_type = 'Edm.Int64'
|
224
|
-
|
225
|
-
entity = { :address => 'Mountain View',
|
226
|
-
:age => 23,
|
227
|
-
:amount_due => 200.23,
|
228
|
-
:binary_data => File.open(__FILE__),
|
229
|
-
:customer_code => 'c9da6455-213d-42c9-9a79-3e9149a57833',
|
230
|
-
:customer_since => Time.now.utc,
|
231
|
-
:is_active => true,
|
232
|
-
:num_of_orders => 255,
|
233
|
-
:partition_key => 'myPartitionKey',
|
234
|
-
:row_key => 'myRowKey1',
|
235
|
-
:Timestamp => Time.now.utc}
|
236
|
-
|
237
|
-
|
238
|
-
updated_entity = @table_service.update_entity('Customers', entity)
|
239
|
-
|
240
|
-
updated_entity.length.should == 11
|
241
|
-
# 1 because of binary_data
|
242
|
-
updated_entity.reject{|k,v| entity.keys.include?(k) and entity.values.to_s.include?(v.to_s)}.length.should == 1
|
243
|
-
entity[:binary_data].pos = 0
|
244
|
-
updated_entity[:binary_data].read.should == entity[:binary_data].read
|
245
|
-
end
|
246
|
-
|
247
|
-
it "should merge an existing entity" do
|
248
|
-
expected_payload = "<?xml version=\"1.0\" encoding=\"utf-8\" standalone=\"yes\"?>" \
|
249
|
-
"<entry xmlns:d=\"http://schemas.microsoft.com/ado/2007/08/dataservices\" xmlns:m=\"http://schemas.microsoft.com/ado/2007/08/dataservices/metadata\" xmlns=\"http://www.w3.org/2005/Atom\">" \
|
250
|
-
"<id>http://localhost/Customers(PartitionKey='myPartitionKey',RowKey='myRowKey1')</id>" \
|
251
|
-
"<title /><updated>#{Time.now.utc.iso8601}</updated><author><name /></author><link rel=\"edit\" title=\"Customers\" href=\"Customers(PartitionKey='myPartitionKey',RowKey='myRowKey1')\" />" \
|
252
|
-
"<content type=\"application/xml\">" \
|
253
|
-
"<m:properties>" \
|
254
|
-
"<d:Timestamp m:type=\"Edm.DateTime\">#{Time.now.utc.iso8601}</d:Timestamp>" \
|
255
|
-
"<d:address m:type=\"Edm.String\">Mountain View</d:address>" \
|
256
|
-
"<d:age m:type=\"Edm.Int32\">23</d:age>" \
|
257
|
-
"<d:amount_due m:type=\"Edm.Double\">200.23</d:amount_due>" \
|
258
|
-
"<d:binary_data m:type=\"Edm.Binary\" m:null=\"true\" />" \
|
259
|
-
"<d:customer_code m:type=\"Edm.Guid\">c9da6455-213d-42c9-9a79-3e9149a57833</d:customer_code>" \
|
260
|
-
"<d:customer_since m:type=\"Edm.DateTime\">#{Time.now.utc.iso8601}</d:customer_since>" \
|
261
|
-
"<d:is_active m:type=\"Edm.Boolean\">true</d:is_active>" \
|
262
|
-
"<d:num_of_orders m:type=\"Edm.Int64\">255</d:num_of_orders>" \
|
263
|
-
"<d:PartitionKey>myPartitionKey</d:PartitionKey>" \
|
264
|
-
"<d:RowKey>myRowKey1</d:RowKey>" \
|
265
|
-
"</m:properties></content></entry>"
|
266
|
-
|
267
|
-
expected_headers = {'If-Match' => '*', 'Content-Type' => 'application/atom+xml', 'Date' => Time.new.httpdate, 'DataServiceVersion' => '1.0;NetFx', 'MaxDataServiceVersion' => '1.0;NetFx'}
|
268
|
-
expected_url = "http://localhost/Customers(PartitionKey='myPartitionKey',RowKey='myRowKey1')"
|
269
|
-
request = RestClient::Request.new(:method => :merge, :url => expected_url, :headers => expected_headers, :payload => expected_payload)
|
270
|
-
|
271
|
-
RestClient::Request.any_instance.expects(:execute).returns(expected_payload)
|
272
|
-
@table_service.expects(:generate_request_uri).with("Customers").returns("http://localhost/Customers")
|
273
|
-
@table_service.expects(:generate_request_uri).with("Customers(PartitionKey='myPartitionKey',RowKey='myRowKey1')", {}).returns(expected_url)
|
274
|
-
@table_service.expects(:generate_request).with(:merge, expected_url, expected_headers , expected_payload).returns(request)
|
275
|
-
|
276
|
-
:binary_data.edm_type = 'Edm.Binary'
|
277
|
-
:customer_code.edm_type = 'Edm.Guid'
|
278
|
-
:num_of_orders.edm_type = 'Edm.Int64'
|
279
|
-
|
280
|
-
entity = { :address => 'Mountain View',
|
281
|
-
:age => 23,
|
282
|
-
:amount_due => 200.23,
|
283
|
-
:binary_data => nil,
|
284
|
-
:customer_code => 'c9da6455-213d-42c9-9a79-3e9149a57833',
|
285
|
-
:customer_since => Time.now.utc,
|
286
|
-
:is_active => true,
|
287
|
-
:num_of_orders => 255,
|
288
|
-
:partition_key => 'myPartitionKey',
|
289
|
-
:row_key => 'myRowKey1',
|
290
|
-
:Timestamp => Time.now.utc}
|
291
|
-
|
292
|
-
merged_entity = @table_service.merge_entity('Customers', entity)
|
293
|
-
merged_entity.length.should == 11
|
294
|
-
merged_entity.reject{|k,v| entity.keys.include?(k) and entity.values.to_s.include?(v.to_s)}.length.should == 0
|
295
|
-
end
|
296
|
-
|
297
|
-
it "should throw TooManyProperties exception" do
|
298
|
-
long_entity = {}
|
299
|
-
253.times { |i| long_entity.merge!({ "test#{i.to_s}".to_sym => "value#{i}"} ) }
|
300
|
-
lambda {@table_service.insert_entity('Customers', long_entity)}.should raise_error(WAZ::Tables::TooManyProperties, "The entity contains more properties than allowed (252). The entity has 253 properties.")
|
301
|
-
end
|
302
|
-
|
303
|
-
it "should throw EntityAlreadyExists exception" do
|
304
|
-
|
305
|
-
entity = { :partition_key => 'myPartitionKey', :row_key => 'myRowKey1', :name => 'name' }
|
306
|
-
|
307
|
-
response = mock()
|
308
|
-
response.stubs(:body).returns('EntityAlreadyExists The specified entity already exists')
|
309
|
-
request_failed = RestClient::RequestFailed.new
|
310
|
-
request_failed.stubs(:response).returns(response)
|
311
|
-
request_failed.stubs(:http_code).returns(409)
|
312
|
-
|
313
|
-
RestClient::Request.any_instance.expects(:execute).raises(request_failed)
|
314
|
-
lambda {@table_service.insert_entity('Customers', entity)}.should raise_error(WAZ::Tables::EntityAlreadyExists, "The specified entity already exists. RowKey: myRowKey1")
|
315
|
-
end
|
316
|
-
|
317
|
-
it "should delete an existing entity" do
|
318
|
-
RestClient::Request.any_instance.expects(:execute).returns(mock())
|
319
|
-
expected_headers = {'If-Match' => '*', 'Date' => Time.new.httpdate, 'DataServiceVersion' => '1.0;NetFx', 'Content-Type' => 'application/atom+xml', 'MaxDataServiceVersion' => '1.0;NetFx'}
|
320
|
-
expected_url = "http://localhost/Customers(PartitionKey='myPartitionKey',RowKey='myRowKey1'"
|
321
|
-
request = RestClient::Request.new(:method => :post, :url => expected_url, :headers => expected_headers)
|
322
|
-
@table_service.expects(:generate_request_uri).with("Customers(PartitionKey='myPartitionKey',RowKey='myRowKey1')", {}).returns(expected_url)
|
323
|
-
@table_service.expects(:generate_request).with(:delete, expected_url, expected_headers, nil).returns(request)
|
324
|
-
@table_service.delete_entity('Customers', 'myPartitionKey', 'myRowKey1')
|
325
|
-
end
|
326
|
-
|
327
|
-
it "should throw when trying to delete and entity and the table does not exists" do
|
328
|
-
response = mock()
|
329
|
-
response.stubs(:body).returns('TableNotFound')
|
330
|
-
request_failed = RestClient::ResourceNotFound.new
|
331
|
-
request_failed.stubs(:response).returns(response)
|
332
|
-
request_failed.stubs(:http_code).returns(404)
|
333
|
-
|
334
|
-
RestClient::Request.any_instance.expects(:execute).raises(request_failed)
|
335
|
-
lambda { @table_service.delete_entity('unexistingtable', 'myPartitionKey', 'myRowKey1') }.should raise_error(WAZ::Tables::TableDoesNotExist, "The specified table unexistingtable does not exist.")
|
336
|
-
end
|
337
|
-
|
338
|
-
it "should throw when trying to delete and entity and the table does not exists" do
|
339
|
-
response = mock()
|
340
|
-
response.stubs(:body).returns('ResourceNotFound')
|
341
|
-
request_failed = RestClient::ResourceNotFound.new
|
342
|
-
request_failed.stubs(:response).returns(response)
|
343
|
-
request_failed.stubs(:http_code).returns(404)
|
344
|
-
|
345
|
-
RestClient::Request.any_instance.expects(:execute).raises(request_failed)
|
346
|
-
lambda { @table_service.delete_entity('table', 'myPartitionKey', 'myRowKey1') }.should raise_error(WAZ::Tables::EntityDoesNotExist, "The specified entity with (PartitionKey='myPartitionKey',RowKey='myRowKey1') does not exist.")
|
347
|
-
end
|
348
|
-
|
349
|
-
it "should get an entity by a given partitionkey and rowkey" do
|
350
|
-
mock_response = <<-eom
|
351
|
-
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
|
352
|
-
<entry xml:base="http://myaccount.tables.core.windows.net/" xmlns:d="http://schemas.microsoft.com/ado/2007/08/dataservices" xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata" m:etag="W/"datetime'2010-01-01T15%3A50%3A49.9612116Z'"" xmlns="http://www.w3.org/2005/Atom">
|
353
|
-
<id>http://myaccount.tables.core.windows.net/Customers(PartitionKey='myPartitionKey',RowKey='myRowKey1')</id>
|
354
|
-
<title type="text"></title>
|
355
|
-
<updated>2008-10-01T15:26:13Z</updated>
|
356
|
-
<author>
|
357
|
-
<name />
|
358
|
-
</author>
|
359
|
-
<link rel="edit" title="Customers" href="Customers (PartitionKey='myPartitionKey',RowKey='myRowKey1')" />
|
360
|
-
<category term="myaccount.Customers" scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme" />
|
361
|
-
<content type="application/xml">
|
362
|
-
<m:properties>
|
363
|
-
<d:PartitionKey>myPartitionKey</d:PartitionKey>
|
364
|
-
<d:RowKey>myRowKey1</d:RowKey>
|
365
|
-
<d:Timestamp m:type="Edm.DateTime">2008-10-01T15:26:04.6812774Z</d:Timestamp>
|
366
|
-
<d:Address>123 Lakeview Blvd, Redmond WA 98052</d:Address>
|
367
|
-
<d:CustomerSince m:type="Edm.DateTime">2008-10-01T15:25:05.2852025Z</d:CustomerSince>
|
368
|
-
<d:Discount m:type="Edm.Double">10</d:Discount>
|
369
|
-
<d:Rating16 m:type="Edm.Int16">3</d:Rating16>
|
370
|
-
<d:Rating32 m:type="Edm.Int32">6</d:Rating32>
|
371
|
-
<d:Rating64 m:type="Edm.Int64">9</d:Rating64>
|
372
|
-
<d:BinaryData m:type="Edm.Binary" m:null="true" />
|
373
|
-
<d:SomeBoolean m:type="Edm.Boolean">true</d:SomeBoolean>
|
374
|
-
<d:SomeSingle m:type="Edm.Single">9.3</d:SomeSingle>
|
375
|
-
</m:properties>
|
376
|
-
</content>
|
377
|
-
</entry>
|
378
|
-
eom
|
379
|
-
expected_headers = {'Date' => Time.new.httpdate, 'DataServiceVersion' => '1.0;NetFx', 'Content-Type' => 'application/atom+xml', 'MaxDataServiceVersion' => '1.0;NetFx'}
|
380
|
-
expected_url = "http://myaccount.tables.core.windows.net/Customers(PartitionKey='myPartitionKey',RowKey='myRowKey1')"
|
381
|
-
RestClient::Request.any_instance.expects(:execute).returns(mock_response)
|
382
|
-
@table_service.expects(:generate_request_uri).with("Customers(PartitionKey='myPartitionKey',RowKey='myRowKey1')", {}).returns(expected_url)
|
383
|
-
@table_service.expects(:generate_request).with(:get, expected_url, expected_headers, nil).returns(RestClient::Request.new(:method => :post, :url => expected_url, :headers => expected_headers))
|
384
|
-
|
385
|
-
entity = @table_service.get_entity('Customers', 'myPartitionKey', 'myRowKey1')
|
386
|
-
|
387
|
-
entity.length.should == 12
|
388
|
-
|
389
|
-
entity[:partition_key].should == 'myPartitionKey'
|
390
|
-
entity[:row_key].should == 'myRowKey1'
|
391
|
-
entity[:Timestamp].should == Time.parse('2008-10-01T15:26:04.6812774Z')
|
392
|
-
entity[:Address].should == '123 Lakeview Blvd, Redmond WA 98052'
|
393
|
-
entity[:CustomerSince].should == Time.parse('2008-10-01T15:25:05.2852025Z')
|
394
|
-
entity[:Discount].should == 10
|
395
|
-
entity[:Rating16].should == 3
|
396
|
-
entity[:Rating32].should == 6
|
397
|
-
entity[:Rating64].should == 9
|
398
|
-
entity[:BinaryData].should == nil
|
399
|
-
entity[:SomeBoolean].should == true
|
400
|
-
entity[:SomeSingle].should == 9.3
|
401
|
-
end
|
402
|
-
|
403
|
-
it "should get a set of entities" do
|
404
|
-
mock_response = <<-eom
|
405
|
-
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
|
406
|
-
<feed xml:base="http://myaccount.tables.core.windows.net/" xmlns:d="http://schemas.microsoft.com/ado/2007/08/dataservices" xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata" xmlns="http://www.w3.org/2005/Atom">
|
407
|
-
<title type="text">Customers</title>
|
408
|
-
<id>http://myaccount.tables.core.windows.net/Customers</id>
|
409
|
-
<updated>2008-10-01T15:26:13Z</updated>
|
410
|
-
<link rel="self" title="Customers" href="Customers" />
|
411
|
-
<entry xml:base="http://myaccount.tables.core.windows.net/" xmlns:d="http://schemas.microsoft.com/ado/2007/08/dataservices" xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata" m:etag="W/"datetime'2010-01-01T15%3A50%3A49.9612116Z'"" xmlns="http://www.w3.org/2005/Atom">
|
412
|
-
<id>http://myaccount.tables.core.windows.net/Customers(PartitionKey='myPartitionKey',RowKey='myRowKey1')</id>
|
413
|
-
<title type="text"></title>
|
414
|
-
<updated>2008-10-01T15:26:13Z</updated>
|
415
|
-
<author>
|
416
|
-
<name />
|
417
|
-
</author>
|
418
|
-
<link rel="edit" title="Customers" href="Customers (PartitionKey='myPartitionKey',RowKey='myRowKey1')" />
|
419
|
-
<category term="myaccount.Customers" scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme" />
|
420
|
-
<content type="application/xml">
|
421
|
-
<m:properties>
|
422
|
-
<d:PartitionKey>myPartitionKey</d:PartitionKey>
|
423
|
-
<d:RowKey>myRowKey1</d:RowKey>
|
424
|
-
<d:Timestamp m:type="Edm.DateTime">2008-10-01T15:26:04.6812774Z</d:Timestamp>
|
425
|
-
<d:Address>123 Lakeview Blvd, Redmond WA 98052</d:Address>
|
426
|
-
<d:CustomerSince m:type="Edm.DateTime">2008-10-01T15:25:05.2852025Z</d:CustomerSince>
|
427
|
-
<d:Discount m:type="Edm.Double">10</d:Discount>
|
428
|
-
<d:Rating m:type="Edm.Int32">3</d:Rating>
|
429
|
-
<d:BinaryData m:type="Edm.Binary" m:null="true" />
|
430
|
-
</m:properties>
|
431
|
-
</content>
|
432
|
-
</entry>
|
433
|
-
<entry xml:base="http://myaccount.tables.core.windows.net/" xmlns:d="http://schemas.microsoft.com/ado/2007/08/dataservices" xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata" m:etag="W/"datetime'2010-01-01T15%3A50%3A49.9612116Z'"" xmlns="http://www.w3.org/2005/Atom">
|
434
|
-
<id>http://myaccount.tables.core.windows.net/Customers(PartitionKey='myPartitionKey',RowKey='myRowKey2')</id>
|
435
|
-
<title type="text"></title>
|
436
|
-
<updated>2008-10-01T15:26:13Z</updated>
|
437
|
-
<author>
|
438
|
-
<name />
|
439
|
-
</author>
|
440
|
-
<link rel="edit" title="Customers" href="Customers (PartitionKey='myPartitionKey',RowKey='myRowKey2')" />
|
441
|
-
<category term="myaccount.Customers" scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme" />
|
442
|
-
<content type="application/xml">
|
443
|
-
<m:properties>
|
444
|
-
<d:PartitionKey>myPartitionKey</d:PartitionKey>
|
445
|
-
<d:RowKey>myRowKey2</d:RowKey>
|
446
|
-
<d:Timestamp m:type="Edm.DateTime">2009-10-01T15:26:04.6812774Z</d:Timestamp>
|
447
|
-
<d:Address>234 Lakeview Blvd, Redmond WA 98052</d:Address>
|
448
|
-
<d:CustomerSince m:type="Edm.DateTime">2009-10-01T15:25:05.2852025Z</d:CustomerSince>
|
449
|
-
<d:Discount m:type="Edm.Double">11</d:Discount>
|
450
|
-
<d:Rating m:type="Edm.Int32">4</d:Rating>
|
451
|
-
<d:BinaryData m:type="Edm.Binary" m:null="true" />
|
452
|
-
</m:properties>
|
453
|
-
</content>
|
454
|
-
</entry>
|
455
|
-
</feed>
|
456
|
-
eom
|
457
|
-
mock_response.stubs(:headers).returns({})
|
458
|
-
expected_headers = {'Date' => Time.new.httpdate, 'DataServiceVersion' => '1.0;NetFx', 'Content-Type' => 'application/atom+xml', 'MaxDataServiceVersion' => '1.0;NetFx'}
|
459
|
-
expected_url = "http://myaccount.tables.core.windows.net/Customers()?$filter=expression"
|
460
|
-
expected_query = { '$filter' => "expression" }
|
461
|
-
|
462
|
-
RestClient::Request.any_instance.expects(:execute).once().returns(mock_response)
|
463
|
-
@table_service.expects(:generate_request_uri).with("Customers()", expected_query).returns(expected_url)
|
464
|
-
@table_service.expects(:generate_request).with(:get, expected_url, expected_headers, nil).returns(RestClient::Request.new(:method => :post, :url => expected_url, :headers => expected_headers))
|
465
|
-
entities = @table_service.query('Customers', {:expression => 'expression'})
|
466
|
-
|
467
|
-
entities.length.should == 2
|
468
|
-
entities.continuation_token[:next_partition_key].nil?.should == true
|
469
|
-
entities.continuation_token[:next_row_key].nil?.should == true
|
470
|
-
|
471
|
-
entities.first.length.should == 8
|
472
|
-
entities.first[:partition_key].should == 'myPartitionKey'
|
473
|
-
entities.first[:row_key].should == 'myRowKey1'
|
474
|
-
entities.first[:Timestamp].should == Time.parse('2008-10-01T15:26:04.6812774Z')
|
475
|
-
entities.first[:Address].should == '123 Lakeview Blvd, Redmond WA 98052'
|
476
|
-
entities.first[:CustomerSince].should == Time.parse('2008-10-01T15:25:05.2852025Z')
|
477
|
-
entities.first[:Discount].should == 10
|
478
|
-
entities.first[:Rating].should == 3
|
479
|
-
entities.first[:BinaryData].should == nil
|
480
|
-
|
481
|
-
entities.last.length.should == 8
|
482
|
-
entities.last[:partition_key].should == 'myPartitionKey'
|
483
|
-
entities.last[:row_key].should == 'myRowKey2'
|
484
|
-
entities.last[:Timestamp].should == Time.parse('2009-10-01T15:26:04.6812774Z')
|
485
|
-
entities.last[:Address].should == '234 Lakeview Blvd, Redmond WA 98052'
|
486
|
-
entities.last[:CustomerSince].should == Time.parse('2009-10-01T15:25:05.2852025Z')
|
487
|
-
entities.last[:Discount].should == 11
|
488
|
-
entities.last[:Rating].should == 4
|
489
|
-
entities.last[:BinaryData].should == nil
|
490
|
-
end
|
491
|
-
|
492
|
-
it "should send the $top query parameter when calling the service with top option " do
|
493
|
-
mock_response = <<-eom
|
494
|
-
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
|
495
|
-
<feed xml:base="http://myaccount.tables.core.windows.net/" xmlns:d="http://schemas.microsoft.com/ado/2007/08/dataservices" xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata" xmlns="http://www.w3.org/2005/Atom">
|
496
|
-
<title type="text">Customers</title>
|
497
|
-
<id>http://myaccount.tables.core.windows.net/Customers</id>
|
498
|
-
<updated>2008-10-01T15:26:13Z</updated>
|
499
|
-
<link rel="self" title="Customers" href="Customers" />
|
500
|
-
<entry xml:base="http://myaccount.tables.core.windows.net/" xmlns:d="http://schemas.microsoft.com/ado/2007/08/dataservices" xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata" m:etag="W/"datetime'2010-01-01T15%3A50%3A49.9612116Z'"" xmlns="http://www.w3.org/2005/Atom">
|
501
|
-
<id>http://myaccount.tables.core.windows.net/Customers(PartitionKey='myPartitionKey',RowKey='myRowKey1')</id>
|
502
|
-
<title type="text"></title>
|
503
|
-
<updated>2008-10-01T15:26:13Z</updated>
|
504
|
-
<author>
|
505
|
-
<name />
|
506
|
-
</author>
|
507
|
-
<link rel="edit" title="Customers" href="Customers (PartitionKey='myPartitionKey',RowKey='myRowKey1')" />
|
508
|
-
<category term="myaccount.Customers" scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme" />
|
509
|
-
<content type="application/xml">
|
510
|
-
<m:properties>
|
511
|
-
<d:PartitionKey>myPartitionKey</d:PartitionKey>
|
512
|
-
<d:RowKey>myRowKey1</d:RowKey>
|
513
|
-
<d:Rating m:type="Edm.Int32">3</d:Rating>
|
514
|
-
</m:properties>
|
515
|
-
</content>
|
516
|
-
</entry>
|
517
|
-
</feed>
|
518
|
-
eom
|
519
|
-
mock_response.stubs(:headers).returns({})
|
520
|
-
|
521
|
-
expected_headers = {'Date' => Time.new.httpdate, 'DataServiceVersion' => '1.0;NetFx', 'Content-Type' => 'application/atom+xml', 'MaxDataServiceVersion' => '1.0;NetFx'}
|
522
|
-
expected_url = "http://myaccount.tables.core.windows.net/Customers()?$filter=expression&$top=1"
|
523
|
-
expected_query = { '$filter' => "expression", '$top' => 1 }
|
524
|
-
|
525
|
-
RestClient::Request.any_instance.expects(:execute).once().returns(mock_response)
|
526
|
-
@table_service.expects(:generate_request_uri).once().with("Customers()", expected_query).returns(expected_url)
|
527
|
-
@table_service.expects(:generate_request).once().with(:get, expected_url, expected_headers, nil).returns(RestClient::Request.new(:method => :post, :url => expected_url, :headers => expected_headers))
|
528
|
-
entities = @table_service.query('Customers', {:expression => 'expression', :top => 1 })
|
529
|
-
|
530
|
-
entities.length.should == 1
|
531
|
-
entities.continuation_token[:next_partition_key].nil?.should == true
|
532
|
-
entities.continuation_token[:next_row_key].nil?.should == true
|
533
|
-
end
|
534
|
-
|
535
|
-
it "should return a continuation token as array property" do
|
536
|
-
sample_feed = <<-eom
|
537
|
-
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
|
538
|
-
<feed xml:base="http://myaccount.tables.core.windows.net/" xmlns:d="http://schemas.microsoft.com/ado/2007/08/dataservices" xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata" xmlns="http://www.w3.org/2005/Atom">
|
539
|
-
<title type="text">Customers</title>
|
540
|
-
<id>http://myaccount.tables.core.windows.net/Customers</id>
|
541
|
-
<updated>2008-10-01T15:26:13Z</updated>
|
542
|
-
<link rel="self" title="Customers" href="Customers" />
|
543
|
-
<entry xml:base="http://myaccount.tables.core.windows.net/" xmlns:d="http://schemas.microsoft.com/ado/2007/08/dataservices" xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata" m:etag="W/"datetime'2010-01-01T15%3A50%3A49.9612116Z'"" xmlns="http://www.w3.org/2005/Atom">
|
544
|
-
<id>http://myaccount.tables.core.windows.net/Customers(PartitionKey='myPartitionKey',RowKey='myRowKey1')</id>
|
545
|
-
<title type="text"></title>
|
546
|
-
<updated>2008-10-01T15:26:13Z</updated>
|
547
|
-
<author>
|
548
|
-
<name />
|
549
|
-
</author>
|
550
|
-
<link rel="edit" title="Customers" href="Customers (PartitionKey='myPartitionKey',RowKey='myRowKey1')" />
|
551
|
-
<category term="myaccount.Customers" scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme" />
|
552
|
-
<content type="application/xml">
|
553
|
-
<m:properties>
|
554
|
-
<d:PartitionKey>myPartitionKey</d:PartitionKey>
|
555
|
-
<d:RowKey>myRowKey1</d:RowKey>
|
556
|
-
<d:Rating m:type="Edm.Int32">3</d:Rating>
|
557
|
-
</m:properties>
|
558
|
-
</content>
|
559
|
-
</entry>
|
560
|
-
</feed>
|
561
|
-
eom
|
562
|
-
mock_response, mock_response2 = sample_feed
|
563
|
-
mock_response.stubs(:headers).returns({:x_ms_continuation_nextpartitionkey => 'next_partition_key_value', :x_ms_continuation_nextrowkey => 'next_row_key_value'})
|
564
|
-
|
565
|
-
expected_headers = {'Date' => Time.new.httpdate, 'DataServiceVersion' => '1.0;NetFx', 'Content-Type' => 'application/atom+xml', 'MaxDataServiceVersion' => '1.0;NetFx'}
|
566
|
-
expected_query = { '$filter' => "expression" }
|
567
|
-
rest_client = RestClient::Request.new(:method => :post, :url => "http://myaccount.tables.core.windows.net/Customers()?$filter=expression", :headers => expected_headers)
|
568
|
-
rest_client.expects(:execute).once().returns(mock_response)
|
569
|
-
|
570
|
-
@table_service.expects(:generate_request_uri).with("Customers()", expected_query).returns("http://myaccount.tables.core.windows.net/Customers()?$filter=expression")
|
571
|
-
@table_service.expects(:generate_request).once().with(:get, "http://myaccount.tables.core.windows.net/Customers()?$filter=expression", expected_headers, nil).returns(rest_client)
|
572
|
-
entities = @table_service.query('Customers', {:expression => 'expression'})
|
573
|
-
|
574
|
-
entities.length.should == 1
|
575
|
-
entities.continuation_token['NextPartitionKey'].should == 'next_partition_key_value'
|
576
|
-
entities.continuation_token['NextRowKey'].should == 'next_row_key_value'
|
577
|
-
end
|
578
|
-
|
579
|
-
it "should throw when invalid table name is provided" do
|
580
|
-
lambda { @table_service.create_table('9existing') }.should raise_error(WAZ::Tables::InvalidTableName)
|
581
|
-
end
|
582
|
-
|
583
|
-
it "should throw when invalid table name is provided" do
|
584
|
-
lambda { @table_service.delete_table('9existing') }.should raise_error(WAZ::Tables::InvalidTableName)
|
585
|
-
end
|
586
|
-
|
587
|
-
it "should throw when invalid table name is provided" do
|
588
|
-
lambda { @table_service.get_table('9existing') }.should raise_error(WAZ::Tables::InvalidTableName)
|
589
|
-
end
|
590
|
-
|
591
|
-
it "should throw when invalid table name is provided" do
|
592
|
-
lambda { @table_service.insert_entity('9existing', 'entity') }.should raise_error(WAZ::Tables::InvalidTableName)
|
593
|
-
end
|
594
|
-
|
595
|
-
it "should throw when invalid table name is provided" do
|
596
|
-
lambda { @table_service.delete_entity('9existing', 'foo', 'foo') }.should raise_error(WAZ::Tables::InvalidTableName)
|
597
|
-
end
|
598
|
-
|
599
|
-
it "should throw when invalid table name is provided" do
|
600
|
-
lambda { @table_service.get_entity('9existing', 'foo', 'foo') }.should raise_error(WAZ::Tables::InvalidTableName)
|
601
|
-
end
|
602
|
-
|
603
|
-
it "should throw when invalid table name is provided" do
|
604
|
-
lambda { @table_service.query('9existing', 'foo') }.should raise_error(WAZ::Tables::InvalidTableName)
|
605
|
-
end
|
606
|
-
|
607
|
-
it "should throw when invalid table name is provided" do
|
608
|
-
lambda { @table_service.update_entity('9existing', {}) }.should raise_error(WAZ::Tables::InvalidTableName)
|
609
|
-
end
|
610
|
-
|
611
|
-
it "should throw when invalid table name is provided" do
|
612
|
-
lambda { @table_service.merge_entity('9existing', {}) }.should raise_error(WAZ::Tables::InvalidTableName)
|
613
|
-
end
|
1
|
+
# enabling the load of files from root (on RSpec)
|
2
|
+
$LOAD_PATH.unshift(File.dirname(__FILE__) + '/../')
|
3
|
+
require 'spec/configuration'
|
4
|
+
require 'lib/waz-tables'
|
5
|
+
|
6
|
+
describe "tables service behavior" do
|
7
|
+
|
8
|
+
before do
|
9
|
+
@table_service = WAZ::Tables::Service.new(:account_name => "mock-account", :access_key => "mock-key", :type_of_service => "table", :use_ssl => true, :base_url => "localhost")
|
10
|
+
end
|
11
|
+
|
12
|
+
it "should get a table" do
|
13
|
+
response = <<-eos
|
14
|
+
<?xml version=\"1.0" encoding=\"utf-8" standalone=\"yes"?>
|
15
|
+
<entry xml:base=\"http://wazstoragejohnny.table.core.windows.net/" xmlns:d=\"http://schemas.microsoft.com/ado/2007/08/dataservices" xmlns:m=\"http://schemas.microsoft.com/ado/2007/08/dataservices/metadata" xmlns=\"http://www.w3.org/2005/Atom">
|
16
|
+
<id>http://myaccount.table.core.windows.net/Tables('table1')</id>
|
17
|
+
<title type=\"text"></title>
|
18
|
+
<updated>2009-12-28T02:00:21Z</updated>
|
19
|
+
<author>
|
20
|
+
<name />
|
21
|
+
</author>
|
22
|
+
<link rel=\"edit" title=\"Tables" href=\"Tables('table1')" />
|
23
|
+
<category term=\"wazstoragejohnny.Tables" scheme=\"http://schemas.microsoft.com/ado/2007/08/dataservices/scheme" />
|
24
|
+
<content type=\"application/xml">
|
25
|
+
<m:properties>
|
26
|
+
<d:TableName>table1</d:TableName>
|
27
|
+
</m:properties>
|
28
|
+
</content>
|
29
|
+
</entry>
|
30
|
+
eos
|
31
|
+
|
32
|
+
response.stubs(:headers).returns({:x_ms_continuation_nexttablename => 'next-table'})
|
33
|
+
|
34
|
+
RestClient::Request.any_instance.expects(:execute).returns(response)
|
35
|
+
@table_service.expects(:generate_request_uri).with("Tables('table1')", {}, nil).returns("http://localhost/Tables('table1')")
|
36
|
+
@table_service.expects(:generate_request).with(:get, "http://localhost/Tables('table1')", { 'Content-Type' => 'application/atom+xml', 'Date' => Time.new.httpdate, 'DataServiceVersion' => '1.0;NetFx', 'MaxDataServiceVersion' => '1.0;NetFx'}, nil).returns(RestClient::Request.new(:method => :get, :url => "http://localhost/Tables('table1')"))
|
37
|
+
table = @table_service.get_table('table1')
|
38
|
+
table[:name].should == 'table1'
|
39
|
+
table[:url].should == "http://myaccount.table.core.windows.net/Tables('table1')"
|
40
|
+
end
|
41
|
+
|
42
|
+
it "should list all tables" do
|
43
|
+
response = <<-eos
|
44
|
+
<?xml version=\"1.0" encoding=\"utf-8" standalone=\"yes"?>
|
45
|
+
<feed xml:base=\"http://myaccount.tables.core.windows.net/" xmlns:d=\"http://schemas.microsoft.com/ado/2007/08/dataservices" xmlns:m=\"http://schemas.microsoft.com/ado/2007/08/dataservices/metadata" xmlns=\"http://www.w3.org/2005/Atom">
|
46
|
+
<title type=\"text">Tables</title>
|
47
|
+
<id>http://myaccount.tables.core.windows.net/Tables</id>
|
48
|
+
<updated>2009-01-04T17:18:54.7062347Z</updated>
|
49
|
+
<link rel=\"self" title=\"Tables" href=\"Tables" />
|
50
|
+
<entry>
|
51
|
+
<id>http://myaccount.tables.core.windows.net/Tables('table1')</id>
|
52
|
+
<title type=\"text"></title>
|
53
|
+
<updated>2009-01-04T17:18:54.7062347Z</updated>
|
54
|
+
<author>
|
55
|
+
<name />
|
56
|
+
</author>
|
57
|
+
<link rel=\"edit" title=\"Tables" href=\"Tables('table1')" />
|
58
|
+
<category term=\"myaccount.Tables" scheme=\"http://schemas.microsoft.com/ado/2007/08/dataservices/scheme" />
|
59
|
+
<content type=\"application/xml">
|
60
|
+
<m:properties>
|
61
|
+
<d:TableName>table1</d:TableName>
|
62
|
+
</m:properties>
|
63
|
+
</content>
|
64
|
+
</entry>
|
65
|
+
<entry>
|
66
|
+
<id>http://myaccount.tables.core.windows.net/Tables('table2')</id>
|
67
|
+
<title type=\"text"></title>
|
68
|
+
<updated>2009-01-04T17:18:54.7062347Z</updated>
|
69
|
+
<author>
|
70
|
+
<name />
|
71
|
+
</author>
|
72
|
+
<link rel=\"edit" title=\"Tables" href=\"Tables('table2')" />
|
73
|
+
<category term=\"myaccount.Tables" scheme=\"http://schemas.microsoft.com/ado/2007/08/dataservices/scheme" />
|
74
|
+
<content type=\"application/xml">
|
75
|
+
<m:properties>
|
76
|
+
<d:TableName>table2</d:TableName>
|
77
|
+
</m:properties>
|
78
|
+
</content>
|
79
|
+
</entry>
|
80
|
+
</feed>
|
81
|
+
eos
|
82
|
+
response.stubs(:headers).returns({:x_ms_continuation_nexttablename => 'next-table'})
|
83
|
+
|
84
|
+
RestClient::Request.any_instance.expects(:execute).returns(response)
|
85
|
+
@table_service.expects(:generate_request_uri).with("Tables", {}, nil).returns("http://localhost/Tables")
|
86
|
+
@table_service.expects(:generate_request).with(:get, "http://localhost/Tables", {'Content-Type' => 'application/atom+xml', 'Date' => Time.new.httpdate, 'DataServiceVersion' => '1.0;NetFx', 'MaxDataServiceVersion' => '1.0;NetFx'}, nil).returns(RestClient::Request.new(:method => :get, :url => "http://localhost/Tables"))
|
87
|
+
tables, next_table_name = @table_service.list_tables
|
88
|
+
tables.length.should == 2
|
89
|
+
tables.first()[:name].should == 'table1'
|
90
|
+
tables.first()[:url].should == "http://myaccount.tables.core.windows.net/Tables('table1')"
|
91
|
+
tables.last()[:name].should == 'table2'
|
92
|
+
tables.last()[:url].should == "http://myaccount.tables.core.windows.net/Tables('table2')"
|
93
|
+
next_table_name.should == 'next-table'
|
94
|
+
end
|
95
|
+
|
96
|
+
it "should include the NextTableName parameter when a continuation token is provided" do
|
97
|
+
response = ''
|
98
|
+
response.stubs(:headers).returns({:x_ms_continuation_nexttablename => 'next-table'})
|
99
|
+
RestClient::Request.any_instance.expects(:execute).returns(response)
|
100
|
+
@table_service.expects(:generate_request_uri).with("Tables", { 'NextTableName' => 'next-table-name' }, nil).returns("http://localhost/Tables?NextTableName=next-table-name")
|
101
|
+
@table_service.expects(:generate_request).with(:get, "http://localhost/Tables?NextTableName=next-table-name", {'Content-Type' => 'application/atom+xml','Date' => Time.new.httpdate, 'DataServiceVersion' => '1.0;NetFx', 'MaxDataServiceVersion' => '1.0;NetFx'}, nil).returns(RestClient::Request.new(:method => :get, :url => "http://localhost/Tables?NextTableName=next-table-name"))
|
102
|
+
tables, next_table_name = @table_service.list_tables('next-table-name')
|
103
|
+
end
|
104
|
+
|
105
|
+
it "should create a table" do
|
106
|
+
expected_payload = "<?xml version=\"1.0\" encoding=\"utf-8\" standalone=\"yes\"?><entry xmlns:d=\"http://schemas.microsoft.com/ado/2007/08/dataservices\" xmlns:m=\"http://schemas.microsoft.com/ado/2007/08/dataservices/metadata\" xmlns=\"http://www.w3.org/2005/Atom\"><title /><updated>#{Time.now.utc.iso8601}</updated><author><name/></author><id/><content type=\"application/xml\"><m:properties><d:TableName>Customers</d:TableName></m:properties></content></entry>"
|
107
|
+
expected_headers = { 'Date' => Time.new.httpdate, 'Content-Type' => 'application/atom+xml', 'DataServiceVersion' => '1.0;NetFx', 'MaxDataServiceVersion' => '1.0;NetFx' }
|
108
|
+
RestClient::Request.any_instance.expects(:execute)
|
109
|
+
@table_service.expects(:generate_request_uri).with("Tables", {}).returns("http://localhost/Tables")
|
110
|
+
@table_service.expects(:generate_request).with(:post, "http://localhost/Tables", expected_headers, expected_payload).returns(RestClient::Request.new(:method => :post, :url => "http://localhost/Tables", :headers => expected_headers, :payload => expected_payload))
|
111
|
+
@table_service.create_table('Customers')
|
112
|
+
end
|
113
|
+
|
114
|
+
it "should throw when a table already exists" do
|
115
|
+
failed_response = RestClient::RequestFailed.new
|
116
|
+
failed_response.stubs(:http_code).returns(409)
|
117
|
+
RestClient::Request.any_instance.expects(:execute).raises(failed_response)
|
118
|
+
lambda { @table_service.create_table('existingtable') }.should raise_error(WAZ::Tables::TableAlreadyExists, "The table existingtable already exists on your account.")
|
119
|
+
end
|
120
|
+
|
121
|
+
it "should delete a table" do
|
122
|
+
expected_headers = { 'Date' => Time.new.httpdate, 'Content-Type' => 'application/atom+xml', 'DataServiceVersion' => '1.0;NetFx', 'MaxDataServiceVersion' => '1.0;NetFx' }
|
123
|
+
|
124
|
+
response = mock()
|
125
|
+
response.stubs(:code).returns(204)
|
126
|
+
RestClient::Request.any_instance.expects(:execute).returns(response)
|
127
|
+
@table_service.expects(:generate_request_uri).with("Tables('tabletodelete')", {}).returns("http://localhost/Tables('tabletodelete')")
|
128
|
+
@table_service.expects(:generate_request).with(:delete, "http://localhost/Tables('tabletodelete')", expected_headers, nil).returns(RestClient::Request.new(:method => :delete, :url => "http://localhost/Tables('tabletodelete')", :headers => expected_headers))
|
129
|
+
@table_service.delete_table('tabletodelete')
|
130
|
+
end
|
131
|
+
|
132
|
+
it "should throw when trying to get an unexisting table" do
|
133
|
+
failed_response = RestClient::ResourceNotFound.new
|
134
|
+
failed_response.stubs(:http_code).returns(404)
|
135
|
+
RestClient::Request.any_instance.expects(:execute).raises(failed_response)
|
136
|
+
lambda { @table_service.get_table('unexistingtable') }.should raise_error(WAZ::Tables::TableDoesNotExist, "The specified table unexistingtable does not exist.")
|
137
|
+
end
|
138
|
+
|
139
|
+
it "should throw when trying to delete an unexisting table" do
|
140
|
+
failed_response = RestClient::ResourceNotFound.new
|
141
|
+
failed_response.stubs(:http_code).returns(404)
|
142
|
+
RestClient::Request.any_instance.expects(:execute).raises(failed_response)
|
143
|
+
lambda { @table_service.delete_table('unexistingtable') }.should raise_error(WAZ::Tables::TableDoesNotExist, "The specified table unexistingtable does not exist.")
|
144
|
+
end
|
145
|
+
|
146
|
+
it "should insert a new entity" do
|
147
|
+
expected_payload = "<?xml version=\"1.0\" encoding=\"utf-8\" standalone=\"yes\"?>" \
|
148
|
+
"<entry xmlns:d=\"http://schemas.microsoft.com/ado/2007/08/dataservices\" xmlns:m=\"http://schemas.microsoft.com/ado/2007/08/dataservices/metadata\" xmlns=\"http://www.w3.org/2005/Atom\">" \
|
149
|
+
"<id>http://localhost/Customers(PartitionKey='myPartitionKey',RowKey='myRowKey1')</id>" \
|
150
|
+
"<title /><updated>#{Time.now.utc.iso8601}</updated><author><name /></author><link rel=\"edit\" title=\"Customers\" href=\"Customers(PartitionKey='myPartitionKey',RowKey='myRowKey1')\" />" \
|
151
|
+
"<content type=\"application/xml\">" \
|
152
|
+
"<m:properties>" \
|
153
|
+
"<d:address m:type=\"Edm.String\">Mountain View</d:address>" \
|
154
|
+
"<d:age m:type=\"Edm.Int32\">23</d:age>" \
|
155
|
+
"<d:amount_due m:type=\"Edm.Double\">200.23</d:amount_due>" \
|
156
|
+
"<d:binary_data m:type=\"Edm.Binary\" m:null=\"true\" />" \
|
157
|
+
"<d:customer_code m:type=\"Edm.Guid\">c9da6455-213d-42c9-9a79-3e9149a57833</d:customer_code>" \
|
158
|
+
"<d:customer_since m:type=\"Edm.DateTime\">#{Time.now.utc.iso8601}</d:customer_since>" \
|
159
|
+
"<d:is_active m:type=\"Edm.Boolean\">true</d:is_active>" \
|
160
|
+
"<d:num_of_orders m:type=\"Edm.Int64\">255</d:num_of_orders>" \
|
161
|
+
"<d:PartitionKey>myPartitionKey</d:PartitionKey>" \
|
162
|
+
"<d:RowKey>myRowKey1</d:RowKey>" \
|
163
|
+
"</m:properties></content></entry>"
|
164
|
+
|
165
|
+
expected_headers = {'Date' => Time.new.httpdate, 'DataServiceVersion' => '1.0;NetFx', 'Content-Type' => 'application/atom+xml', 'MaxDataServiceVersion' => '1.0;NetFx'}
|
166
|
+
|
167
|
+
RestClient::Request.any_instance.expects(:execute).returns(expected_payload)
|
168
|
+
@table_service.expects(:generate_request_uri).with("Customers").returns("http://localhost/Customers")
|
169
|
+
@table_service.expects(:generate_request_uri).with("Customers", {}).returns("http://localhost/Customers")
|
170
|
+
request = RestClient::Request.new(:method => :post, :url => "http://localhost/Customers", :headers => expected_headers, :payload => expected_payload)
|
171
|
+
@table_service.expects(:generate_request).with(:post, "http://localhost/Customers", expected_headers , expected_payload).returns(request)
|
172
|
+
|
173
|
+
:binary_data.edm_type = 'Edm.Binary'
|
174
|
+
:customer_code.edm_type = 'Edm.Guid'
|
175
|
+
:num_of_orders.edm_type = 'Edm.Int64'
|
176
|
+
|
177
|
+
entity = { :address => 'Mountain View',
|
178
|
+
:age => 23,
|
179
|
+
:amount_due => 200.23,
|
180
|
+
:binary_data => nil,
|
181
|
+
:customer_code => 'c9da6455-213d-42c9-9a79-3e9149a57833',
|
182
|
+
:customer_since => Time.now.utc,
|
183
|
+
:is_active => true,
|
184
|
+
:num_of_orders => 255,
|
185
|
+
:partition_key => 'myPartitionKey',
|
186
|
+
:row_key => 'myRowKey1' }
|
187
|
+
|
188
|
+
new_entity = @table_service.insert_entity('Customers', entity)
|
189
|
+
new_entity.length.should == 10
|
190
|
+
new_entity.reject{|k,v| entity.keys.include?(k) and entity.values.to_s.include?(v.to_s)}.length.should == 0
|
191
|
+
end
|
192
|
+
|
193
|
+
it "should update an existing entity" do
|
194
|
+
expected_payload = "<?xml version=\"1.0\" encoding=\"utf-8\" standalone=\"yes\"?>" \
|
195
|
+
"<entry xmlns:d=\"http://schemas.microsoft.com/ado/2007/08/dataservices\" xmlns:m=\"http://schemas.microsoft.com/ado/2007/08/dataservices/metadata\" xmlns=\"http://www.w3.org/2005/Atom\">" \
|
196
|
+
"<id>http://localhost/Customers(PartitionKey='myPartitionKey',RowKey='myRowKey1')</id>" \
|
197
|
+
"<title /><updated>#{Time.now.utc.iso8601}</updated><author><name /></author><link rel=\"edit\" title=\"Customers\" href=\"Customers(PartitionKey='myPartitionKey',RowKey='myRowKey1')\" />" \
|
198
|
+
"<content type=\"application/xml\">" \
|
199
|
+
"<m:properties>" \
|
200
|
+
"<d:Timestamp m:type=\"Edm.DateTime\">#{Time.now.utc.iso8601}</d:Timestamp>" \
|
201
|
+
"<d:address m:type=\"Edm.String\">Mountain View</d:address>" \
|
202
|
+
"<d:age m:type=\"Edm.Int32\">23</d:age>" \
|
203
|
+
"<d:amount_due m:type=\"Edm.Double\">200.23</d:amount_due>" \
|
204
|
+
"<d:binary_data m:type=\"Edm.Binary\">#{Base64.encode64(File.read(__FILE__))}</d:binary_data>" \
|
205
|
+
"<d:customer_code m:type=\"Edm.Guid\">c9da6455-213d-42c9-9a79-3e9149a57833</d:customer_code>" \
|
206
|
+
"<d:customer_since m:type=\"Edm.DateTime\">#{Time.now.utc.iso8601}</d:customer_since>" \
|
207
|
+
"<d:is_active m:type=\"Edm.Boolean\">true</d:is_active>" \
|
208
|
+
"<d:num_of_orders m:type=\"Edm.Int64\">255</d:num_of_orders>" \
|
209
|
+
"<d:PartitionKey>myPartitionKey</d:PartitionKey>" \
|
210
|
+
"<d:RowKey>myRowKey1</d:RowKey>" \
|
211
|
+
"</m:properties></content></entry>"
|
212
|
+
expected_headers = {'If-Match' => '*', 'Content-Type' => 'application/atom+xml', 'Date' => Time.new.httpdate, 'DataServiceVersion' => '1.0;NetFx', 'MaxDataServiceVersion' => '1.0;NetFx'}
|
213
|
+
expected_url = "http://localhost/Customers(PartitionKey='myPartitionKey',RowKey='myRowKey1')"
|
214
|
+
|
215
|
+
RestClient::Request.any_instance.expects(:execute).returns(expected_payload)
|
216
|
+
@table_service.expects(:generate_request_uri).with("Customers").returns("http://localhost/Customers")
|
217
|
+
@table_service.expects(:generate_request_uri).with("Customers(PartitionKey='myPartitionKey',RowKey='myRowKey1')", {}).returns(expected_url)
|
218
|
+
request = RestClient::Request.new(:method => :put, :url => expected_url, :headers => expected_headers, :payload => expected_payload)
|
219
|
+
@table_service.expects(:generate_request).with(:put, expected_url, expected_headers , expected_payload).returns(request)
|
220
|
+
|
221
|
+
:binary_data.edm_type = 'Edm.Binary'
|
222
|
+
:customer_code.edm_type = 'Edm.Guid'
|
223
|
+
:num_of_orders.edm_type = 'Edm.Int64'
|
224
|
+
|
225
|
+
entity = { :address => 'Mountain View',
|
226
|
+
:age => 23,
|
227
|
+
:amount_due => 200.23,
|
228
|
+
:binary_data => File.open(__FILE__),
|
229
|
+
:customer_code => 'c9da6455-213d-42c9-9a79-3e9149a57833',
|
230
|
+
:customer_since => Time.now.utc,
|
231
|
+
:is_active => true,
|
232
|
+
:num_of_orders => 255,
|
233
|
+
:partition_key => 'myPartitionKey',
|
234
|
+
:row_key => 'myRowKey1',
|
235
|
+
:Timestamp => Time.now.utc}
|
236
|
+
|
237
|
+
|
238
|
+
updated_entity = @table_service.update_entity('Customers', entity)
|
239
|
+
|
240
|
+
updated_entity.length.should == 11
|
241
|
+
# 1 because of binary_data
|
242
|
+
updated_entity.reject{|k,v| entity.keys.include?(k) and entity.values.to_s.include?(v.to_s)}.length.should == 1
|
243
|
+
entity[:binary_data].pos = 0
|
244
|
+
updated_entity[:binary_data].read.should == entity[:binary_data].read
|
245
|
+
end
|
246
|
+
|
247
|
+
it "should merge an existing entity" do
|
248
|
+
expected_payload = "<?xml version=\"1.0\" encoding=\"utf-8\" standalone=\"yes\"?>" \
|
249
|
+
"<entry xmlns:d=\"http://schemas.microsoft.com/ado/2007/08/dataservices\" xmlns:m=\"http://schemas.microsoft.com/ado/2007/08/dataservices/metadata\" xmlns=\"http://www.w3.org/2005/Atom\">" \
|
250
|
+
"<id>http://localhost/Customers(PartitionKey='myPartitionKey',RowKey='myRowKey1')</id>" \
|
251
|
+
"<title /><updated>#{Time.now.utc.iso8601}</updated><author><name /></author><link rel=\"edit\" title=\"Customers\" href=\"Customers(PartitionKey='myPartitionKey',RowKey='myRowKey1')\" />" \
|
252
|
+
"<content type=\"application/xml\">" \
|
253
|
+
"<m:properties>" \
|
254
|
+
"<d:Timestamp m:type=\"Edm.DateTime\">#{Time.now.utc.iso8601}</d:Timestamp>" \
|
255
|
+
"<d:address m:type=\"Edm.String\">Mountain View</d:address>" \
|
256
|
+
"<d:age m:type=\"Edm.Int32\">23</d:age>" \
|
257
|
+
"<d:amount_due m:type=\"Edm.Double\">200.23</d:amount_due>" \
|
258
|
+
"<d:binary_data m:type=\"Edm.Binary\" m:null=\"true\" />" \
|
259
|
+
"<d:customer_code m:type=\"Edm.Guid\">c9da6455-213d-42c9-9a79-3e9149a57833</d:customer_code>" \
|
260
|
+
"<d:customer_since m:type=\"Edm.DateTime\">#{Time.now.utc.iso8601}</d:customer_since>" \
|
261
|
+
"<d:is_active m:type=\"Edm.Boolean\">true</d:is_active>" \
|
262
|
+
"<d:num_of_orders m:type=\"Edm.Int64\">255</d:num_of_orders>" \
|
263
|
+
"<d:PartitionKey>myPartitionKey</d:PartitionKey>" \
|
264
|
+
"<d:RowKey>myRowKey1</d:RowKey>" \
|
265
|
+
"</m:properties></content></entry>"
|
266
|
+
|
267
|
+
expected_headers = {'If-Match' => '*', 'Content-Type' => 'application/atom+xml', 'Date' => Time.new.httpdate, 'DataServiceVersion' => '1.0;NetFx', 'MaxDataServiceVersion' => '1.0;NetFx'}
|
268
|
+
expected_url = "http://localhost/Customers(PartitionKey='myPartitionKey',RowKey='myRowKey1')"
|
269
|
+
request = RestClient::Request.new(:method => :merge, :url => expected_url, :headers => expected_headers, :payload => expected_payload)
|
270
|
+
|
271
|
+
RestClient::Request.any_instance.expects(:execute).returns(expected_payload)
|
272
|
+
@table_service.expects(:generate_request_uri).with("Customers").returns("http://localhost/Customers")
|
273
|
+
@table_service.expects(:generate_request_uri).with("Customers(PartitionKey='myPartitionKey',RowKey='myRowKey1')", {}).returns(expected_url)
|
274
|
+
@table_service.expects(:generate_request).with(:merge, expected_url, expected_headers , expected_payload).returns(request)
|
275
|
+
|
276
|
+
:binary_data.edm_type = 'Edm.Binary'
|
277
|
+
:customer_code.edm_type = 'Edm.Guid'
|
278
|
+
:num_of_orders.edm_type = 'Edm.Int64'
|
279
|
+
|
280
|
+
entity = { :address => 'Mountain View',
|
281
|
+
:age => 23,
|
282
|
+
:amount_due => 200.23,
|
283
|
+
:binary_data => nil,
|
284
|
+
:customer_code => 'c9da6455-213d-42c9-9a79-3e9149a57833',
|
285
|
+
:customer_since => Time.now.utc,
|
286
|
+
:is_active => true,
|
287
|
+
:num_of_orders => 255,
|
288
|
+
:partition_key => 'myPartitionKey',
|
289
|
+
:row_key => 'myRowKey1',
|
290
|
+
:Timestamp => Time.now.utc}
|
291
|
+
|
292
|
+
merged_entity = @table_service.merge_entity('Customers', entity)
|
293
|
+
merged_entity.length.should == 11
|
294
|
+
merged_entity.reject{|k,v| entity.keys.include?(k) and entity.values.to_s.include?(v.to_s)}.length.should == 0
|
295
|
+
end
|
296
|
+
|
297
|
+
it "should throw TooManyProperties exception" do
|
298
|
+
long_entity = {}
|
299
|
+
253.times { |i| long_entity.merge!({ "test#{i.to_s}".to_sym => "value#{i}"} ) }
|
300
|
+
lambda {@table_service.insert_entity('Customers', long_entity)}.should raise_error(WAZ::Tables::TooManyProperties, "The entity contains more properties than allowed (252). The entity has 253 properties.")
|
301
|
+
end
|
302
|
+
|
303
|
+
it "should throw EntityAlreadyExists exception" do
|
304
|
+
|
305
|
+
entity = { :partition_key => 'myPartitionKey', :row_key => 'myRowKey1', :name => 'name' }
|
306
|
+
|
307
|
+
response = mock()
|
308
|
+
response.stubs(:body).returns('EntityAlreadyExists The specified entity already exists')
|
309
|
+
request_failed = RestClient::RequestFailed.new
|
310
|
+
request_failed.stubs(:response).returns(response)
|
311
|
+
request_failed.stubs(:http_code).returns(409)
|
312
|
+
|
313
|
+
RestClient::Request.any_instance.expects(:execute).raises(request_failed)
|
314
|
+
lambda {@table_service.insert_entity('Customers', entity)}.should raise_error(WAZ::Tables::EntityAlreadyExists, "The specified entity already exists. RowKey: myRowKey1")
|
315
|
+
end
|
316
|
+
|
317
|
+
it "should delete an existing entity" do
|
318
|
+
RestClient::Request.any_instance.expects(:execute).returns(mock())
|
319
|
+
expected_headers = {'If-Match' => '*', 'Date' => Time.new.httpdate, 'DataServiceVersion' => '1.0;NetFx', 'Content-Type' => 'application/atom+xml', 'MaxDataServiceVersion' => '1.0;NetFx'}
|
320
|
+
expected_url = "http://localhost/Customers(PartitionKey='myPartitionKey',RowKey='myRowKey1'"
|
321
|
+
request = RestClient::Request.new(:method => :post, :url => expected_url, :headers => expected_headers)
|
322
|
+
@table_service.expects(:generate_request_uri).with("Customers(PartitionKey='myPartitionKey',RowKey='myRowKey1')", {}).returns(expected_url)
|
323
|
+
@table_service.expects(:generate_request).with(:delete, expected_url, expected_headers, nil).returns(request)
|
324
|
+
@table_service.delete_entity('Customers', 'myPartitionKey', 'myRowKey1')
|
325
|
+
end
|
326
|
+
|
327
|
+
it "should throw when trying to delete and entity and the table does not exists" do
|
328
|
+
response = mock()
|
329
|
+
response.stubs(:body).returns('TableNotFound')
|
330
|
+
request_failed = RestClient::ResourceNotFound.new
|
331
|
+
request_failed.stubs(:response).returns(response)
|
332
|
+
request_failed.stubs(:http_code).returns(404)
|
333
|
+
|
334
|
+
RestClient::Request.any_instance.expects(:execute).raises(request_failed)
|
335
|
+
lambda { @table_service.delete_entity('unexistingtable', 'myPartitionKey', 'myRowKey1') }.should raise_error(WAZ::Tables::TableDoesNotExist, "The specified table unexistingtable does not exist.")
|
336
|
+
end
|
337
|
+
|
338
|
+
it "should throw when trying to delete and entity and the table does not exists" do
|
339
|
+
response = mock()
|
340
|
+
response.stubs(:body).returns('ResourceNotFound')
|
341
|
+
request_failed = RestClient::ResourceNotFound.new
|
342
|
+
request_failed.stubs(:response).returns(response)
|
343
|
+
request_failed.stubs(:http_code).returns(404)
|
344
|
+
|
345
|
+
RestClient::Request.any_instance.expects(:execute).raises(request_failed)
|
346
|
+
lambda { @table_service.delete_entity('table', 'myPartitionKey', 'myRowKey1') }.should raise_error(WAZ::Tables::EntityDoesNotExist, "The specified entity with (PartitionKey='myPartitionKey',RowKey='myRowKey1') does not exist.")
|
347
|
+
end
|
348
|
+
|
349
|
+
it "should get an entity by a given partitionkey and rowkey" do
|
350
|
+
mock_response = <<-eom
|
351
|
+
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
|
352
|
+
<entry xml:base="http://myaccount.tables.core.windows.net/" xmlns:d="http://schemas.microsoft.com/ado/2007/08/dataservices" xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata" m:etag="W/"datetime'2010-01-01T15%3A50%3A49.9612116Z'"" xmlns="http://www.w3.org/2005/Atom">
|
353
|
+
<id>http://myaccount.tables.core.windows.net/Customers(PartitionKey='myPartitionKey',RowKey='myRowKey1')</id>
|
354
|
+
<title type="text"></title>
|
355
|
+
<updated>2008-10-01T15:26:13Z</updated>
|
356
|
+
<author>
|
357
|
+
<name />
|
358
|
+
</author>
|
359
|
+
<link rel="edit" title="Customers" href="Customers (PartitionKey='myPartitionKey',RowKey='myRowKey1')" />
|
360
|
+
<category term="myaccount.Customers" scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme" />
|
361
|
+
<content type="application/xml">
|
362
|
+
<m:properties>
|
363
|
+
<d:PartitionKey>myPartitionKey</d:PartitionKey>
|
364
|
+
<d:RowKey>myRowKey1</d:RowKey>
|
365
|
+
<d:Timestamp m:type="Edm.DateTime">2008-10-01T15:26:04.6812774Z</d:Timestamp>
|
366
|
+
<d:Address>123 Lakeview Blvd, Redmond WA 98052</d:Address>
|
367
|
+
<d:CustomerSince m:type="Edm.DateTime">2008-10-01T15:25:05.2852025Z</d:CustomerSince>
|
368
|
+
<d:Discount m:type="Edm.Double">10</d:Discount>
|
369
|
+
<d:Rating16 m:type="Edm.Int16">3</d:Rating16>
|
370
|
+
<d:Rating32 m:type="Edm.Int32">6</d:Rating32>
|
371
|
+
<d:Rating64 m:type="Edm.Int64">9</d:Rating64>
|
372
|
+
<d:BinaryData m:type="Edm.Binary" m:null="true" />
|
373
|
+
<d:SomeBoolean m:type="Edm.Boolean">true</d:SomeBoolean>
|
374
|
+
<d:SomeSingle m:type="Edm.Single">9.3</d:SomeSingle>
|
375
|
+
</m:properties>
|
376
|
+
</content>
|
377
|
+
</entry>
|
378
|
+
eom
|
379
|
+
expected_headers = {'Date' => Time.new.httpdate, 'DataServiceVersion' => '1.0;NetFx', 'Content-Type' => 'application/atom+xml', 'MaxDataServiceVersion' => '1.0;NetFx'}
|
380
|
+
expected_url = "http://myaccount.tables.core.windows.net/Customers(PartitionKey='myPartitionKey',RowKey='myRowKey1')"
|
381
|
+
RestClient::Request.any_instance.expects(:execute).returns(mock_response)
|
382
|
+
@table_service.expects(:generate_request_uri).with("Customers(PartitionKey='myPartitionKey',RowKey='myRowKey1')", {}).returns(expected_url)
|
383
|
+
@table_service.expects(:generate_request).with(:get, expected_url, expected_headers, nil).returns(RestClient::Request.new(:method => :post, :url => expected_url, :headers => expected_headers))
|
384
|
+
|
385
|
+
entity = @table_service.get_entity('Customers', 'myPartitionKey', 'myRowKey1')
|
386
|
+
|
387
|
+
entity.length.should == 12
|
388
|
+
|
389
|
+
entity[:partition_key].should == 'myPartitionKey'
|
390
|
+
entity[:row_key].should == 'myRowKey1'
|
391
|
+
entity[:Timestamp].should == Time.parse('2008-10-01T15:26:04.6812774Z')
|
392
|
+
entity[:Address].should == '123 Lakeview Blvd, Redmond WA 98052'
|
393
|
+
entity[:CustomerSince].should == Time.parse('2008-10-01T15:25:05.2852025Z')
|
394
|
+
entity[:Discount].should == 10
|
395
|
+
entity[:Rating16].should == 3
|
396
|
+
entity[:Rating32].should == 6
|
397
|
+
entity[:Rating64].should == 9
|
398
|
+
entity[:BinaryData].should == nil
|
399
|
+
entity[:SomeBoolean].should == true
|
400
|
+
entity[:SomeSingle].should == 9.3
|
401
|
+
end
|
402
|
+
|
403
|
+
it "should get a set of entities" do
|
404
|
+
mock_response = <<-eom
|
405
|
+
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
|
406
|
+
<feed xml:base="http://myaccount.tables.core.windows.net/" xmlns:d="http://schemas.microsoft.com/ado/2007/08/dataservices" xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata" xmlns="http://www.w3.org/2005/Atom">
|
407
|
+
<title type="text">Customers</title>
|
408
|
+
<id>http://myaccount.tables.core.windows.net/Customers</id>
|
409
|
+
<updated>2008-10-01T15:26:13Z</updated>
|
410
|
+
<link rel="self" title="Customers" href="Customers" />
|
411
|
+
<entry xml:base="http://myaccount.tables.core.windows.net/" xmlns:d="http://schemas.microsoft.com/ado/2007/08/dataservices" xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata" m:etag="W/"datetime'2010-01-01T15%3A50%3A49.9612116Z'"" xmlns="http://www.w3.org/2005/Atom">
|
412
|
+
<id>http://myaccount.tables.core.windows.net/Customers(PartitionKey='myPartitionKey',RowKey='myRowKey1')</id>
|
413
|
+
<title type="text"></title>
|
414
|
+
<updated>2008-10-01T15:26:13Z</updated>
|
415
|
+
<author>
|
416
|
+
<name />
|
417
|
+
</author>
|
418
|
+
<link rel="edit" title="Customers" href="Customers (PartitionKey='myPartitionKey',RowKey='myRowKey1')" />
|
419
|
+
<category term="myaccount.Customers" scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme" />
|
420
|
+
<content type="application/xml">
|
421
|
+
<m:properties>
|
422
|
+
<d:PartitionKey>myPartitionKey</d:PartitionKey>
|
423
|
+
<d:RowKey>myRowKey1</d:RowKey>
|
424
|
+
<d:Timestamp m:type="Edm.DateTime">2008-10-01T15:26:04.6812774Z</d:Timestamp>
|
425
|
+
<d:Address>123 Lakeview Blvd, Redmond WA 98052</d:Address>
|
426
|
+
<d:CustomerSince m:type="Edm.DateTime">2008-10-01T15:25:05.2852025Z</d:CustomerSince>
|
427
|
+
<d:Discount m:type="Edm.Double">10</d:Discount>
|
428
|
+
<d:Rating m:type="Edm.Int32">3</d:Rating>
|
429
|
+
<d:BinaryData m:type="Edm.Binary" m:null="true" />
|
430
|
+
</m:properties>
|
431
|
+
</content>
|
432
|
+
</entry>
|
433
|
+
<entry xml:base="http://myaccount.tables.core.windows.net/" xmlns:d="http://schemas.microsoft.com/ado/2007/08/dataservices" xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata" m:etag="W/"datetime'2010-01-01T15%3A50%3A49.9612116Z'"" xmlns="http://www.w3.org/2005/Atom">
|
434
|
+
<id>http://myaccount.tables.core.windows.net/Customers(PartitionKey='myPartitionKey',RowKey='myRowKey2')</id>
|
435
|
+
<title type="text"></title>
|
436
|
+
<updated>2008-10-01T15:26:13Z</updated>
|
437
|
+
<author>
|
438
|
+
<name />
|
439
|
+
</author>
|
440
|
+
<link rel="edit" title="Customers" href="Customers (PartitionKey='myPartitionKey',RowKey='myRowKey2')" />
|
441
|
+
<category term="myaccount.Customers" scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme" />
|
442
|
+
<content type="application/xml">
|
443
|
+
<m:properties>
|
444
|
+
<d:PartitionKey>myPartitionKey</d:PartitionKey>
|
445
|
+
<d:RowKey>myRowKey2</d:RowKey>
|
446
|
+
<d:Timestamp m:type="Edm.DateTime">2009-10-01T15:26:04.6812774Z</d:Timestamp>
|
447
|
+
<d:Address>234 Lakeview Blvd, Redmond WA 98052</d:Address>
|
448
|
+
<d:CustomerSince m:type="Edm.DateTime">2009-10-01T15:25:05.2852025Z</d:CustomerSince>
|
449
|
+
<d:Discount m:type="Edm.Double">11</d:Discount>
|
450
|
+
<d:Rating m:type="Edm.Int32">4</d:Rating>
|
451
|
+
<d:BinaryData m:type="Edm.Binary" m:null="true" />
|
452
|
+
</m:properties>
|
453
|
+
</content>
|
454
|
+
</entry>
|
455
|
+
</feed>
|
456
|
+
eom
|
457
|
+
mock_response.stubs(:headers).returns({})
|
458
|
+
expected_headers = {'Date' => Time.new.httpdate, 'DataServiceVersion' => '1.0;NetFx', 'Content-Type' => 'application/atom+xml', 'MaxDataServiceVersion' => '1.0;NetFx'}
|
459
|
+
expected_url = "http://myaccount.tables.core.windows.net/Customers()?$filter=expression"
|
460
|
+
expected_query = { '$filter' => "expression" }
|
461
|
+
|
462
|
+
RestClient::Request.any_instance.expects(:execute).once().returns(mock_response)
|
463
|
+
@table_service.expects(:generate_request_uri).with("Customers()", expected_query).returns(expected_url)
|
464
|
+
@table_service.expects(:generate_request).with(:get, expected_url, expected_headers, nil).returns(RestClient::Request.new(:method => :post, :url => expected_url, :headers => expected_headers))
|
465
|
+
entities = @table_service.query('Customers', {:expression => 'expression'})
|
466
|
+
|
467
|
+
entities.length.should == 2
|
468
|
+
entities.continuation_token[:next_partition_key].nil?.should == true
|
469
|
+
entities.continuation_token[:next_row_key].nil?.should == true
|
470
|
+
|
471
|
+
entities.first.length.should == 8
|
472
|
+
entities.first[:partition_key].should == 'myPartitionKey'
|
473
|
+
entities.first[:row_key].should == 'myRowKey1'
|
474
|
+
entities.first[:Timestamp].should == Time.parse('2008-10-01T15:26:04.6812774Z')
|
475
|
+
entities.first[:Address].should == '123 Lakeview Blvd, Redmond WA 98052'
|
476
|
+
entities.first[:CustomerSince].should == Time.parse('2008-10-01T15:25:05.2852025Z')
|
477
|
+
entities.first[:Discount].should == 10
|
478
|
+
entities.first[:Rating].should == 3
|
479
|
+
entities.first[:BinaryData].should == nil
|
480
|
+
|
481
|
+
entities.last.length.should == 8
|
482
|
+
entities.last[:partition_key].should == 'myPartitionKey'
|
483
|
+
entities.last[:row_key].should == 'myRowKey2'
|
484
|
+
entities.last[:Timestamp].should == Time.parse('2009-10-01T15:26:04.6812774Z')
|
485
|
+
entities.last[:Address].should == '234 Lakeview Blvd, Redmond WA 98052'
|
486
|
+
entities.last[:CustomerSince].should == Time.parse('2009-10-01T15:25:05.2852025Z')
|
487
|
+
entities.last[:Discount].should == 11
|
488
|
+
entities.last[:Rating].should == 4
|
489
|
+
entities.last[:BinaryData].should == nil
|
490
|
+
end
|
491
|
+
|
492
|
+
it "should send the $top query parameter when calling the service with top option " do
|
493
|
+
mock_response = <<-eom
|
494
|
+
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
|
495
|
+
<feed xml:base="http://myaccount.tables.core.windows.net/" xmlns:d="http://schemas.microsoft.com/ado/2007/08/dataservices" xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata" xmlns="http://www.w3.org/2005/Atom">
|
496
|
+
<title type="text">Customers</title>
|
497
|
+
<id>http://myaccount.tables.core.windows.net/Customers</id>
|
498
|
+
<updated>2008-10-01T15:26:13Z</updated>
|
499
|
+
<link rel="self" title="Customers" href="Customers" />
|
500
|
+
<entry xml:base="http://myaccount.tables.core.windows.net/" xmlns:d="http://schemas.microsoft.com/ado/2007/08/dataservices" xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata" m:etag="W/"datetime'2010-01-01T15%3A50%3A49.9612116Z'"" xmlns="http://www.w3.org/2005/Atom">
|
501
|
+
<id>http://myaccount.tables.core.windows.net/Customers(PartitionKey='myPartitionKey',RowKey='myRowKey1')</id>
|
502
|
+
<title type="text"></title>
|
503
|
+
<updated>2008-10-01T15:26:13Z</updated>
|
504
|
+
<author>
|
505
|
+
<name />
|
506
|
+
</author>
|
507
|
+
<link rel="edit" title="Customers" href="Customers (PartitionKey='myPartitionKey',RowKey='myRowKey1')" />
|
508
|
+
<category term="myaccount.Customers" scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme" />
|
509
|
+
<content type="application/xml">
|
510
|
+
<m:properties>
|
511
|
+
<d:PartitionKey>myPartitionKey</d:PartitionKey>
|
512
|
+
<d:RowKey>myRowKey1</d:RowKey>
|
513
|
+
<d:Rating m:type="Edm.Int32">3</d:Rating>
|
514
|
+
</m:properties>
|
515
|
+
</content>
|
516
|
+
</entry>
|
517
|
+
</feed>
|
518
|
+
eom
|
519
|
+
mock_response.stubs(:headers).returns({})
|
520
|
+
|
521
|
+
expected_headers = {'Date' => Time.new.httpdate, 'DataServiceVersion' => '1.0;NetFx', 'Content-Type' => 'application/atom+xml', 'MaxDataServiceVersion' => '1.0;NetFx'}
|
522
|
+
expected_url = "http://myaccount.tables.core.windows.net/Customers()?$filter=expression&$top=1"
|
523
|
+
expected_query = { '$filter' => "expression", '$top' => 1 }
|
524
|
+
|
525
|
+
RestClient::Request.any_instance.expects(:execute).once().returns(mock_response)
|
526
|
+
@table_service.expects(:generate_request_uri).once().with("Customers()", expected_query).returns(expected_url)
|
527
|
+
@table_service.expects(:generate_request).once().with(:get, expected_url, expected_headers, nil).returns(RestClient::Request.new(:method => :post, :url => expected_url, :headers => expected_headers))
|
528
|
+
entities = @table_service.query('Customers', {:expression => 'expression', :top => 1 })
|
529
|
+
|
530
|
+
entities.length.should == 1
|
531
|
+
entities.continuation_token[:next_partition_key].nil?.should == true
|
532
|
+
entities.continuation_token[:next_row_key].nil?.should == true
|
533
|
+
end
|
534
|
+
|
535
|
+
it "should return a continuation token as array property" do
|
536
|
+
sample_feed = <<-eom
|
537
|
+
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
|
538
|
+
<feed xml:base="http://myaccount.tables.core.windows.net/" xmlns:d="http://schemas.microsoft.com/ado/2007/08/dataservices" xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata" xmlns="http://www.w3.org/2005/Atom">
|
539
|
+
<title type="text">Customers</title>
|
540
|
+
<id>http://myaccount.tables.core.windows.net/Customers</id>
|
541
|
+
<updated>2008-10-01T15:26:13Z</updated>
|
542
|
+
<link rel="self" title="Customers" href="Customers" />
|
543
|
+
<entry xml:base="http://myaccount.tables.core.windows.net/" xmlns:d="http://schemas.microsoft.com/ado/2007/08/dataservices" xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata" m:etag="W/"datetime'2010-01-01T15%3A50%3A49.9612116Z'"" xmlns="http://www.w3.org/2005/Atom">
|
544
|
+
<id>http://myaccount.tables.core.windows.net/Customers(PartitionKey='myPartitionKey',RowKey='myRowKey1')</id>
|
545
|
+
<title type="text"></title>
|
546
|
+
<updated>2008-10-01T15:26:13Z</updated>
|
547
|
+
<author>
|
548
|
+
<name />
|
549
|
+
</author>
|
550
|
+
<link rel="edit" title="Customers" href="Customers (PartitionKey='myPartitionKey',RowKey='myRowKey1')" />
|
551
|
+
<category term="myaccount.Customers" scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme" />
|
552
|
+
<content type="application/xml">
|
553
|
+
<m:properties>
|
554
|
+
<d:PartitionKey>myPartitionKey</d:PartitionKey>
|
555
|
+
<d:RowKey>myRowKey1</d:RowKey>
|
556
|
+
<d:Rating m:type="Edm.Int32">3</d:Rating>
|
557
|
+
</m:properties>
|
558
|
+
</content>
|
559
|
+
</entry>
|
560
|
+
</feed>
|
561
|
+
eom
|
562
|
+
mock_response, mock_response2 = sample_feed
|
563
|
+
mock_response.stubs(:headers).returns({:x_ms_continuation_nextpartitionkey => 'next_partition_key_value', :x_ms_continuation_nextrowkey => 'next_row_key_value'})
|
564
|
+
|
565
|
+
expected_headers = {'Date' => Time.new.httpdate, 'DataServiceVersion' => '1.0;NetFx', 'Content-Type' => 'application/atom+xml', 'MaxDataServiceVersion' => '1.0;NetFx'}
|
566
|
+
expected_query = { '$filter' => "expression" }
|
567
|
+
rest_client = RestClient::Request.new(:method => :post, :url => "http://myaccount.tables.core.windows.net/Customers()?$filter=expression", :headers => expected_headers)
|
568
|
+
rest_client.expects(:execute).once().returns(mock_response)
|
569
|
+
|
570
|
+
@table_service.expects(:generate_request_uri).with("Customers()", expected_query).returns("http://myaccount.tables.core.windows.net/Customers()?$filter=expression")
|
571
|
+
@table_service.expects(:generate_request).once().with(:get, "http://myaccount.tables.core.windows.net/Customers()?$filter=expression", expected_headers, nil).returns(rest_client)
|
572
|
+
entities = @table_service.query('Customers', {:expression => 'expression'})
|
573
|
+
|
574
|
+
entities.length.should == 1
|
575
|
+
entities.continuation_token['NextPartitionKey'].should == 'next_partition_key_value'
|
576
|
+
entities.continuation_token['NextRowKey'].should == 'next_row_key_value'
|
577
|
+
end
|
578
|
+
|
579
|
+
it "should throw when invalid table name is provided" do
|
580
|
+
lambda { @table_service.create_table('9existing') }.should raise_error(WAZ::Tables::InvalidTableName)
|
581
|
+
end
|
582
|
+
|
583
|
+
it "should throw when invalid table name is provided" do
|
584
|
+
lambda { @table_service.delete_table('9existing') }.should raise_error(WAZ::Tables::InvalidTableName)
|
585
|
+
end
|
586
|
+
|
587
|
+
it "should throw when invalid table name is provided" do
|
588
|
+
lambda { @table_service.get_table('9existing') }.should raise_error(WAZ::Tables::InvalidTableName)
|
589
|
+
end
|
590
|
+
|
591
|
+
it "should throw when invalid table name is provided" do
|
592
|
+
lambda { @table_service.insert_entity('9existing', 'entity') }.should raise_error(WAZ::Tables::InvalidTableName)
|
593
|
+
end
|
594
|
+
|
595
|
+
it "should throw when invalid table name is provided" do
|
596
|
+
lambda { @table_service.delete_entity('9existing', 'foo', 'foo') }.should raise_error(WAZ::Tables::InvalidTableName)
|
597
|
+
end
|
598
|
+
|
599
|
+
it "should throw when invalid table name is provided" do
|
600
|
+
lambda { @table_service.get_entity('9existing', 'foo', 'foo') }.should raise_error(WAZ::Tables::InvalidTableName)
|
601
|
+
end
|
602
|
+
|
603
|
+
it "should throw when invalid table name is provided" do
|
604
|
+
lambda { @table_service.query('9existing', 'foo') }.should raise_error(WAZ::Tables::InvalidTableName)
|
605
|
+
end
|
606
|
+
|
607
|
+
it "should throw when invalid table name is provided" do
|
608
|
+
lambda { @table_service.update_entity('9existing', {}) }.should raise_error(WAZ::Tables::InvalidTableName)
|
609
|
+
end
|
610
|
+
|
611
|
+
it "should throw when invalid table name is provided" do
|
612
|
+
lambda { @table_service.merge_entity('9existing', {}) }.should raise_error(WAZ::Tables::InvalidTableName)
|
613
|
+
end
|
614
614
|
end
|