appengine-apis 0.0.12 → 0.0.13
Sign up to get free protection for your applications and to get access to all the features.
- data/lib/appengine-apis.rb +1 -1
- data/lib/appengine-apis/apiproxy.rb +11 -4
- data/lib/appengine-apis/labs/taskqueue.rb +2 -2
- data/lib/appengine-apis/memcache.rb +8 -8
- data/lib/appengine-apis/runtime.rb +32 -0
- data/lib/appengine-apis/testing.rb +63 -159
- data/lib/appengine-apis/urlfetch.rb +8 -2
- data/spec/memcache_spec.rb +64 -55
- data/spec/spec_helper.rb +9 -10
- data/spec/users_spec.rb +16 -14
- metadata +19 -9
data/lib/appengine-apis.rb
CHANGED
@@ -23,16 +23,22 @@ module AppEngine
|
|
23
23
|
import com.google.apphosting.api.ApiProxy
|
24
24
|
|
25
25
|
class << ApiProxy
|
26
|
-
def
|
26
|
+
def version
|
27
|
+
version_id = get_current_environment.getVersionId
|
28
|
+
version_id[0,version_id.rindex(".").to_i] # nil to 0
|
29
|
+
end
|
30
|
+
|
31
|
+
def app_id
|
27
32
|
get_current_environment.getAppId
|
28
33
|
end
|
29
|
-
|
30
|
-
|
34
|
+
alias :get_app_id :app_id
|
35
|
+
|
36
|
+
def auth_domain
|
31
37
|
get_current_environment.getAuthDomain
|
32
38
|
end
|
39
|
+
alias :get_auth_domain :auth_domain
|
33
40
|
|
34
41
|
alias :add_log_record :log
|
35
|
-
|
36
42
|
def log(level, message)
|
37
43
|
message = (message || "").to_s.chomp
|
38
44
|
return if message.nil? || message.empty?
|
@@ -40,6 +46,7 @@ module AppEngine
|
|
40
46
|
level, java.lang.System.currentTimeMillis() * 1000, message.to_s)
|
41
47
|
add_log_record(record)
|
42
48
|
end
|
49
|
+
|
43
50
|
end
|
44
51
|
end
|
45
52
|
end
|
@@ -112,7 +112,7 @@ module AppEngine
|
|
112
112
|
# - queue: Name of the queue where this Task should be added. (optional)
|
113
113
|
#
|
114
114
|
def add(queue=nil)
|
115
|
-
queue = Queue.new(queue) unless
|
115
|
+
queue = Queue.new(queue) unless queue.kind_of? Queue
|
116
116
|
@handle = queue.java_queue.add(_task)
|
117
117
|
self
|
118
118
|
end
|
@@ -263,4 +263,4 @@ module AppEngine
|
|
263
263
|
end
|
264
264
|
end
|
265
265
|
end
|
266
|
-
end
|
266
|
+
end
|
@@ -433,7 +433,7 @@ module AppEngine
|
|
433
433
|
|
434
434
|
def memcache_key(obj)
|
435
435
|
key = obj
|
436
|
-
key = key.to_s
|
436
|
+
key = java.lang.String.new(key.to_s) if key
|
437
437
|
key
|
438
438
|
end
|
439
439
|
|
@@ -450,10 +450,10 @@ module AppEngine
|
|
450
450
|
else
|
451
451
|
if obj.class == String
|
452
452
|
# Convert plain strings to Java strings
|
453
|
-
obj
|
453
|
+
java.lang.String.new(obj)
|
454
454
|
else
|
455
455
|
bytes = Marshal.dump(obj).to_java_bytes
|
456
|
-
java.util.ArrayList.new([MARSHAL_MARKER
|
456
|
+
java.util.ArrayList.new([java.lang.String.new(MARSHAL_MARKER), bytes])
|
457
457
|
end
|
458
458
|
end
|
459
459
|
end
|
@@ -502,8 +502,8 @@ module AppEngine
|
|
502
502
|
convert_exceptions do
|
503
503
|
key = memcache_key(key)
|
504
504
|
value = memcache_value(value)
|
505
|
-
|
506
|
-
service.put(key, value,
|
505
|
+
expiration = memcache_expiration(expiration)
|
506
|
+
service.put(key, value, expiration, mode)
|
507
507
|
end
|
508
508
|
end
|
509
509
|
|
@@ -541,7 +541,7 @@ module AppEngine
|
|
541
541
|
end
|
542
542
|
@map[string_key] = key
|
543
543
|
if string_key
|
544
|
-
string_key
|
544
|
+
java.lang.String.new(string_key)
|
545
545
|
else
|
546
546
|
string_key
|
547
547
|
end
|
@@ -550,7 +550,7 @@ module AppEngine
|
|
550
550
|
def java_keys
|
551
551
|
@map.keys.collect do |key|
|
552
552
|
if key
|
553
|
-
key
|
553
|
+
java.lang.String.new(key)
|
554
554
|
else
|
555
555
|
key
|
556
556
|
end
|
@@ -577,4 +577,4 @@ module AppEngine
|
|
577
577
|
end
|
578
578
|
end
|
579
579
|
end
|
580
|
-
end
|
580
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
#!/usr/bin/ruby1.8 -w
|
2
|
+
#
|
3
|
+
# Copyright:: Copyright 2009 Google Inc.
|
4
|
+
# Original Author:: John Woodell (mailto:woodie@google.com)
|
5
|
+
#
|
6
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
7
|
+
# you may not use this file except in compliance with the License.
|
8
|
+
# You may obtain a copy of the License at
|
9
|
+
#
|
10
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
11
|
+
#
|
12
|
+
# Unless required by applicable law or agreed to in writing, software
|
13
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
14
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
15
|
+
# See the License for the specific language governing permissions and
|
16
|
+
# limitations under the License.
|
17
|
+
|
18
|
+
module AppEngine
|
19
|
+
if defined? Java
|
20
|
+
import com.google.appengine.api.utils.SystemProperty
|
21
|
+
|
22
|
+
class Runtime
|
23
|
+
def self.environment
|
24
|
+
SystemProperty.environment.get.to_s.downcase
|
25
|
+
end
|
26
|
+
|
27
|
+
def self.version
|
28
|
+
SystemProperty.version.get.to_s
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -18,10 +18,8 @@
|
|
18
18
|
#
|
19
19
|
# Helpers for installing stub apis in unit tests.
|
20
20
|
|
21
|
-
require 'appengine-apis/apiproxy'
|
22
|
-
|
23
21
|
module AppEngine
|
24
|
-
|
22
|
+
|
25
23
|
# Local testing support for Google App Engine
|
26
24
|
#
|
27
25
|
# If you run your code on Google's servers or under dev_appserver,
|
@@ -31,187 +29,93 @@ module AppEngine
|
|
31
29
|
# api stubs.
|
32
30
|
module Testing
|
33
31
|
|
34
|
-
|
35
|
-
include AppEngine::ApiProxy::Environment
|
36
|
-
|
37
|
-
attr_writer :appid, :version, :email, :admin
|
38
|
-
attr_writer :auth_domain, :request_namespace, :default_namespace
|
39
|
-
attr_reader :attributes
|
40
|
-
|
41
|
-
def initialize
|
42
|
-
@appid = "test"
|
43
|
-
@version = "1.0"
|
44
|
-
@auth_domain= "gmail.com"
|
45
|
-
@default_namespace = @request_namespace = ""
|
46
|
-
@email = ""
|
47
|
-
@attributes = java.util.HashMap.new
|
48
|
-
end
|
49
|
-
|
50
|
-
def getAppId
|
51
|
-
@appid
|
52
|
-
end
|
53
|
-
|
54
|
-
def getVersionId
|
55
|
-
@version
|
56
|
-
end
|
57
|
-
|
58
|
-
def getEmail
|
59
|
-
@email
|
60
|
-
end
|
61
|
-
|
62
|
-
def isLoggedIn
|
63
|
-
!(@email.nil? || @auth_domain.nil? || @email.empty?)
|
64
|
-
end
|
65
|
-
|
66
|
-
def isAdmin
|
67
|
-
!!@admin
|
68
|
-
end
|
69
|
-
|
70
|
-
def getAuthDomain
|
71
|
-
@auth_domain
|
72
|
-
end
|
73
|
-
|
74
|
-
def getRequestNamespace
|
75
|
-
@request_namespace
|
76
|
-
end
|
77
|
-
|
78
|
-
def getDefaultNamespace
|
79
|
-
@default_namespace
|
80
|
-
end
|
81
|
-
|
82
|
-
def setDefaultNamespace(s)
|
83
|
-
@default_namespace = s
|
84
|
-
end
|
85
|
-
|
86
|
-
def getAttributes
|
87
|
-
@attributes
|
88
|
-
end
|
89
|
-
|
90
|
-
def inspect
|
91
|
-
"#<TestEnv>"
|
92
|
-
end
|
93
|
-
end
|
94
|
-
|
32
|
+
|
95
33
|
class << self
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
#
|
103
|
-
#
|
104
|
-
def
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
34
|
+
def delegate # :nodoc:
|
35
|
+
helper # make sure everything's loaded
|
36
|
+
require 'appengine-apis/apiproxy'
|
37
|
+
AppEngine::ApiProxy.getDelegate
|
38
|
+
end
|
39
|
+
|
40
|
+
# The LocalServiceTestHelper used by this class.
|
41
|
+
# Use this to set the logged in user, etc.
|
42
|
+
def helper
|
43
|
+
failed = false
|
44
|
+
@helper ||= begin
|
45
|
+
testing = Java::ComGoogleAppengineToolsDevelopmentTesting
|
46
|
+
@datastore_config = testing::LocalDatastoreServiceTestConfig.new
|
47
|
+
configs = [
|
48
|
+
@datastore_config,
|
49
|
+
testing::LocalBlobstoreServiceTestConfig.new,
|
50
|
+
testing::LocalImagesServiceTestConfig.new,
|
51
|
+
testing::LocalMailServiceTestConfig.new,
|
52
|
+
testing::LocalMemcacheServiceTestConfig.new,
|
53
|
+
testing::LocalTaskQueueTestConfig.new,
|
54
|
+
testing::LocalURLFetchServiceTestConfig.new,
|
55
|
+
testing::LocalUserServiceTestConfig.new,
|
56
|
+
testing::LocalXMPPServiceTestConfig.new,
|
57
|
+
].to_java(testing::LocalServiceTestConfig)
|
58
|
+
testing::LocalServiceTestHelper.new(configs)
|
59
|
+
rescue => ex
|
60
|
+
if failed
|
61
|
+
raise ex
|
62
|
+
else
|
63
|
+
failed = true
|
64
|
+
require 'appengine-sdk'
|
65
|
+
AppEngine::SDK.load_local_test_helper
|
66
|
+
retry
|
67
|
+
end
|
116
68
|
end
|
117
69
|
end
|
118
|
-
|
119
|
-
# The application directory, or '.' if not set.
|
120
|
-
# Composite index definitions are written to "#{app_dir}/WEB-INF/".
|
121
|
-
def app_dir
|
122
|
-
file = factory.getApplicationDirectory
|
123
|
-
file && file.path
|
124
|
-
end
|
125
70
|
|
126
|
-
# Sets the application directory. Should be called before
|
127
|
-
# creating stubs.
|
128
|
-
#
|
129
|
-
# Composite index definitions are written to "#{app_dir}/WEB-INF/".
|
130
|
-
def app_dir=(dir)
|
131
|
-
factory.setApplicationDirectory(java.io.File.new(dir))
|
132
|
-
end
|
133
|
-
|
134
71
|
# Install stub apis and force all datastore operations to use
|
135
72
|
# an in-memory datastore.
|
136
73
|
#
|
137
74
|
# You may call this multiple times to reset to a new in-memory datastore.
|
138
75
|
def install_test_datastore
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
delegate.set_property(
|
143
|
-
lds::NO_STORAGE_PROPERTY, "true")
|
144
|
-
delegate.set_property(
|
145
|
-
lds::MAX_QUERY_LIFETIME_PROPERTY,
|
146
|
-
java.lang.Integer::MAX_VALUE.to_s)
|
147
|
-
delegate.set_property(
|
148
|
-
lds::MAX_TRANSACTION_LIFETIME_PROPERTY,
|
149
|
-
java.lang.Integer::MAX_VALUE.to_s)
|
150
|
-
ApiProxy::setDelegate(delegate)
|
151
|
-
delegate
|
76
|
+
self.persistent_datastore = false
|
77
|
+
setup
|
152
78
|
end
|
153
|
-
|
154
|
-
# Install stub apis. The datastore will be written to the disk
|
155
|
-
# inside #app_dir.
|
156
|
-
#
|
157
|
-
# You could potentially use this to run under a ruby web server
|
158
|
-
# instead of dev_appserver. In that case you will need to install
|
159
|
-
# and configure a test environment for each request.
|
160
|
-
def install_api_stubs
|
161
|
-
current_delegate = ApiProxy.getDelegate
|
162
|
-
current_delegate.stop if current_delegate.respond_to? :stop
|
163
79
|
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
80
|
+
def persistent_datastore
|
81
|
+
helper
|
82
|
+
!@datastore_config.is_no_storage
|
83
|
+
end
|
84
|
+
|
85
|
+
def persistent_datastore=(value)
|
86
|
+
helper
|
87
|
+
@datastore_config.set_no_storage(!value)
|
88
|
+
setup
|
89
|
+
end
|
90
|
+
|
91
|
+
def setup
|
92
|
+
if delegate
|
93
|
+
teardown rescue nil
|
169
94
|
end
|
170
|
-
|
95
|
+
helper.setUp
|
171
96
|
end
|
172
|
-
|
97
|
+
|
98
|
+
def teardown
|
99
|
+
helper.tearDown
|
100
|
+
end
|
101
|
+
|
173
102
|
# Loads stub API implementations if no API implementation is
|
174
103
|
# currently configured.
|
175
104
|
#
|
176
|
-
# Sets up a datastore saved to disk in
|
177
|
-
# to ENV['APPLICATION_ROOT'] or '.' if not specified.
|
105
|
+
# Sets up a datastore saved to disk in '.'.
|
178
106
|
#
|
179
107
|
# Does nothing is APIs are already configured (e.g. in production).
|
180
108
|
#
|
181
109
|
# As a shortcut you can use
|
182
110
|
# require 'appengine-apis/local_boot'
|
183
111
|
#
|
184
|
-
def boot
|
185
|
-
if
|
186
|
-
AppEngine::ApiProxy.getDelegate
|
112
|
+
def boot
|
113
|
+
if delegate
|
187
114
|
return
|
188
115
|
end
|
189
|
-
|
190
|
-
|
191
|
-
env = install_test_env
|
192
|
-
appid = get_app_id(app_dir)
|
193
|
-
env.appid = appid if appid
|
194
|
-
end
|
195
|
-
unless AppEngine::ApiProxy.getDelegate
|
196
|
-
self.app_dir = app_dir
|
197
|
-
install_api_stubs
|
198
|
-
end
|
199
|
-
end
|
200
|
-
|
201
|
-
# Looks for app.yaml or WEB-INF/appengine-web.xml in +app_dir+
|
202
|
-
# and parses the application id.
|
203
|
-
def get_app_id(app_dir)
|
204
|
-
require 'appengine-rack'
|
205
|
-
app_id = AppEngine::Rack.app.id
|
206
|
-
return app_id if app_id
|
207
|
-
aeweb_path = File.join(app_dir, 'WEB-INF', 'appengine-web.xml')
|
208
|
-
if File.exist?(aeweb_path)
|
209
|
-
require 'rexml/document'
|
210
|
-
aeweb = REXML::Document.new(File.new(aeweb_path))
|
211
|
-
return aeweb.root.elements['application'].text
|
212
|
-
end
|
116
|
+
self.persistent_datastore = true
|
117
|
+
setup
|
213
118
|
end
|
214
|
-
|
215
119
|
end
|
216
120
|
|
217
121
|
end
|
@@ -103,9 +103,11 @@ module AppEngine
|
|
103
103
|
payload = options.delete(:payload)
|
104
104
|
headers = options.delete(:headers) || {}
|
105
105
|
truncate = options.delete(:allow_truncated)
|
106
|
-
follow_redirects = options.delete(:follow_redirects)
|
106
|
+
follow_redirects = options.delete(:follow_redirects)
|
107
107
|
deadline = options.delete(:deadline)
|
108
108
|
|
109
|
+
follow_redirects = true if follow_redirects.nil?
|
110
|
+
|
109
111
|
unless options.empty?
|
110
112
|
raise ArgumentError, "Unsupported options #{options.inspect}."
|
111
113
|
end
|
@@ -204,7 +206,11 @@ module Net # :nodoc:
|
|
204
206
|
yield res if block_given?
|
205
207
|
}
|
206
208
|
return res
|
207
|
-
end
|
209
|
+
end
|
210
|
+
|
211
|
+
def use_ssl=(flag)
|
212
|
+
@use_ssl = flag
|
213
|
+
end
|
208
214
|
end
|
209
215
|
|
210
216
|
class HTTPResponse # :nodoc:
|
data/spec/memcache_spec.rb
CHANGED
@@ -21,61 +21,57 @@ describe AppEngine::Memcache do
|
|
21
21
|
AppEngine::Testing::install_test_datastore
|
22
22
|
@cache = AppEngine::Memcache.new
|
23
23
|
end
|
24
|
-
|
25
|
-
before :all do
|
26
|
-
AppEngine::Testing::install_test_env
|
27
|
-
end
|
28
|
-
|
24
|
+
|
29
25
|
describe 'get' do
|
30
|
-
|
26
|
+
|
31
27
|
it 'should return nil on miss' do
|
32
28
|
@cache.get('foobar').should == nil
|
33
29
|
@cache['foobar'].should == nil
|
34
30
|
end
|
35
|
-
|
31
|
+
|
36
32
|
it 'should support strings' do
|
37
33
|
@cache.set('foobar', 'test').should == true
|
38
34
|
@cache.get('foobar').should == 'test'
|
39
35
|
@cache['foobar'].should == 'test'
|
40
36
|
end
|
41
|
-
|
37
|
+
|
42
38
|
it 'should support multiple values' do
|
43
39
|
@cache.get('foo', 'bar', 'baz').should == [nil, nil, nil]
|
44
40
|
@cache['foo', 'bar', 'baz'].should == [nil, nil, nil]
|
45
41
|
@cache.set('bar', 'food').should == true
|
46
42
|
@cache['foo', 'bar', 'baz'].should == [nil, 'food', nil]
|
47
43
|
end
|
48
|
-
|
44
|
+
|
49
45
|
it 'should support getting an array of keys' do
|
50
46
|
@cache.set('foobar', 'test').should == true
|
51
47
|
@cache.get(['foobar', 'flowers']).should == ['test', nil]
|
52
48
|
@cache.get(['foobar']).should == ['test']
|
53
49
|
end
|
54
|
-
|
50
|
+
|
55
51
|
it 'should support numbers' do
|
56
52
|
@cache.set('one', 1).should == true
|
57
53
|
@cache.set('pi', 3.14).should == true
|
58
54
|
@cache.get('pi').should == 3.14
|
59
55
|
@cache.get('one').should === 1
|
60
56
|
end
|
61
|
-
|
57
|
+
|
62
58
|
it 'should support symbol keys' do
|
63
59
|
@cache.set(:a, 'A')
|
64
60
|
@cache.get(:a).should == 'A'
|
65
61
|
end
|
66
|
-
|
62
|
+
|
67
63
|
it 'should support booleans' do
|
68
64
|
@cache.set('true', true)
|
69
65
|
@cache.set('false', false)
|
70
66
|
@cache.get('true').should == true
|
71
67
|
@cache.get('false').should == false
|
72
68
|
end
|
73
|
-
|
69
|
+
|
74
70
|
it 'should support marshaled objects' do
|
75
71
|
@cache.set('a', 1..5)
|
76
72
|
@cache.get('a').should == (1..5)
|
77
73
|
end
|
78
|
-
|
74
|
+
|
79
75
|
it 'should support false keys' do
|
80
76
|
@cache.set(nil, 'nil')
|
81
77
|
@cache.set(false, 'false')
|
@@ -83,19 +79,19 @@ describe AppEngine::Memcache do
|
|
83
79
|
@cache.get(false).should == 'false'
|
84
80
|
end
|
85
81
|
end
|
86
|
-
|
82
|
+
|
87
83
|
describe 'get_hash' do
|
88
84
|
it 'should not include missing keys' do
|
89
85
|
@cache.get_hash(:a, :b).should == {}
|
90
86
|
end
|
91
|
-
|
87
|
+
|
92
88
|
it 'should get objects' do
|
93
89
|
@cache.set('a', 'A')
|
94
90
|
@cache.set('b', 3)
|
95
91
|
@cache.get_hash('a', 'c', 'b').should == {'a' => 'A', 'b' => 3 }
|
96
92
|
end
|
97
93
|
end
|
98
|
-
|
94
|
+
|
99
95
|
describe 'clear' do
|
100
96
|
it 'should clear the cache' do
|
101
97
|
@cache.set(:a, 'A')
|
@@ -104,7 +100,7 @@ describe AppEngine::Memcache do
|
|
104
100
|
@cache.get_hash(:a, 'b', :c).should == {}
|
105
101
|
end
|
106
102
|
end
|
107
|
-
|
103
|
+
|
108
104
|
describe 'flush_all' do
|
109
105
|
it 'should clear the cache' do
|
110
106
|
@cache.set(:a, 'A')
|
@@ -113,7 +109,7 @@ describe AppEngine::Memcache do
|
|
113
109
|
@cache.get_hash(:a, 'b', :c).should == {}
|
114
110
|
end
|
115
111
|
end
|
116
|
-
|
112
|
+
|
117
113
|
describe 'stats' do
|
118
114
|
it 'should count items' do
|
119
115
|
@cache.stats[:items].should == 0
|
@@ -130,11 +126,11 @@ describe AppEngine::Memcache do
|
|
130
126
|
@cache.get(:a).should == nil
|
131
127
|
@cache.get_hash(:a).should == {}
|
132
128
|
end
|
133
|
-
|
129
|
+
|
134
130
|
it 'should return false on missing items' do
|
135
131
|
@cache.delete(:a).should == false
|
136
132
|
end
|
137
|
-
|
133
|
+
|
138
134
|
it 'should allow blocking adds' do
|
139
135
|
@cache.set(:a, '1')
|
140
136
|
@cache.set(:b, '2')
|
@@ -144,7 +140,7 @@ describe AppEngine::Memcache do
|
|
144
140
|
@cache.add(:b, 'B').should == false
|
145
141
|
end
|
146
142
|
end
|
147
|
-
|
143
|
+
|
148
144
|
describe 'delete_many' do
|
149
145
|
it 'should remove items' do
|
150
146
|
@cache.set(:a, 'A')
|
@@ -153,7 +149,7 @@ describe AppEngine::Memcache do
|
|
153
149
|
@cache.delete_many([:a, :c])
|
154
150
|
@cache.get_hash(:a, :b, :c).should == {:b => 'B'}
|
155
151
|
end
|
156
|
-
|
152
|
+
|
157
153
|
it 'should return removed keys' do
|
158
154
|
@cache.set('a', 'A')
|
159
155
|
@cache.set('b', 'B')
|
@@ -161,7 +157,7 @@ describe AppEngine::Memcache do
|
|
161
157
|
removed = @cache.delete_many(['a', 'c'])
|
162
158
|
removed.sort.should == ['a', 'c']
|
163
159
|
end
|
164
|
-
|
160
|
+
|
165
161
|
it 'should not return missing keys' do
|
166
162
|
@cache.set('a', 'A')
|
167
163
|
@cache.set('b', 'B')
|
@@ -170,8 +166,8 @@ describe AppEngine::Memcache do
|
|
170
166
|
removed.sort.should == ['a', 'c']
|
171
167
|
@cache.delete_many(['e']).should == []
|
172
168
|
end
|
173
|
-
|
174
|
-
|
169
|
+
|
170
|
+
|
175
171
|
it 'should allow blocking adds' do
|
176
172
|
@cache.set(:a, '1')
|
177
173
|
@cache.set(:b, '2')
|
@@ -181,44 +177,44 @@ describe AppEngine::Memcache do
|
|
181
177
|
@cache.add(:b, 'B').should == false
|
182
178
|
end
|
183
179
|
end
|
184
|
-
|
180
|
+
|
185
181
|
describe 'add' do
|
186
182
|
it 'should add missing' do
|
187
183
|
@cache.add(:a, 'A').should == true
|
188
184
|
@cache.get(:a).should == 'A'
|
189
185
|
end
|
190
|
-
|
186
|
+
|
191
187
|
it 'should not replace existing entries' do
|
192
188
|
@cache.set(:a, 1)
|
193
189
|
@cache.add(:a, 'A').should == false
|
194
190
|
@cache.get(:a).should == 1
|
195
191
|
end
|
196
192
|
end
|
197
|
-
|
193
|
+
|
198
194
|
describe 'add_many' do
|
199
195
|
it 'should add missing' do
|
200
196
|
@cache.add_many({:a => 1, :b =>2})
|
201
197
|
@cache.get(:b, :a).should == [2, 1]
|
202
198
|
end
|
203
|
-
|
199
|
+
|
204
200
|
it 'should not replace existing entries' do
|
205
201
|
@cache.set(:a, 1)
|
206
202
|
@cache.add_many({:a => 'A', :b => 'B'})
|
207
203
|
@cache.get(:a, :b).should == [1, 'B']
|
208
204
|
end
|
209
|
-
|
205
|
+
|
210
206
|
it 'should return existing keys' do
|
211
207
|
@cache.set(:a, 1)
|
212
208
|
@cache.add_many({:a => 'A', :b => 'B'}).should == [:a]
|
213
209
|
end
|
214
210
|
end
|
215
|
-
|
211
|
+
|
216
212
|
describe 'set' do
|
217
213
|
it 'should add missing' do
|
218
214
|
@cache.set(:a, :A).should == true
|
219
215
|
@cache.get(:a).should == :A
|
220
216
|
end
|
221
|
-
|
217
|
+
|
222
218
|
it 'should replace existing' do
|
223
219
|
@cache.set(:a, :A).should == true
|
224
220
|
@cache.get(:a).should == :A
|
@@ -226,13 +222,13 @@ describe AppEngine::Memcache do
|
|
226
222
|
@cache.get(:a).should == 1
|
227
223
|
end
|
228
224
|
end
|
229
|
-
|
225
|
+
|
230
226
|
describe 'set_many' do
|
231
227
|
it 'should set multiple values' do
|
232
228
|
@cache.set_many({:a => 1, :b => 2}).should == []
|
233
229
|
end
|
234
230
|
end
|
235
|
-
|
231
|
+
|
236
232
|
describe 'replace' do
|
237
233
|
it 'should replace existing' do
|
238
234
|
@cache.set(:a, :A).should == true
|
@@ -240,12 +236,12 @@ describe AppEngine::Memcache do
|
|
240
236
|
@cache.replace(:a, 1).should == true
|
241
237
|
@cache.get(:a).should == 1
|
242
238
|
end
|
243
|
-
|
239
|
+
|
244
240
|
it 'should not replace missing' do
|
245
241
|
@cache.replace(:a, :A).should == false
|
246
242
|
end
|
247
243
|
end
|
248
|
-
|
244
|
+
|
249
245
|
describe 'replace_many' do
|
250
246
|
it 'should replace many' do
|
251
247
|
@cache.set_many({:a => 1, :c => 3})
|
@@ -253,7 +249,7 @@ describe AppEngine::Memcache do
|
|
253
249
|
@cache.get(:a, :b, :c).should == [:A, nil, :C]
|
254
250
|
end
|
255
251
|
end
|
256
|
-
|
252
|
+
|
257
253
|
describe 'dict access' do
|
258
254
|
it 'should support getting with []' do
|
259
255
|
@cache.set(:a, 7)
|
@@ -261,7 +257,7 @@ describe AppEngine::Memcache do
|
|
261
257
|
@cache.set(:b, :B)
|
262
258
|
@cache[:a, :b].should == [7, :B]
|
263
259
|
end
|
264
|
-
|
260
|
+
|
265
261
|
it 'should support setting with []=' do
|
266
262
|
@cache[:a, :b] = [1, :B]
|
267
263
|
@cache[:c] = 3
|
@@ -270,7 +266,7 @@ describe AppEngine::Memcache do
|
|
270
266
|
@cache[:c].should == 3
|
271
267
|
end
|
272
268
|
end
|
273
|
-
|
269
|
+
|
274
270
|
describe 'incr' do
|
275
271
|
it 'should increment number' do
|
276
272
|
@cache.set(:a, 1)
|
@@ -278,13 +274,13 @@ describe AppEngine::Memcache do
|
|
278
274
|
@cache.incr(:a, 7).should == 9
|
279
275
|
@cache.get(:a).should == 9
|
280
276
|
end
|
281
|
-
|
277
|
+
|
282
278
|
it 'should wrap' do
|
283
279
|
@cache.set(:a, 7)
|
284
280
|
@cache.incr(:a, 2**62).should == 2**62 + 7
|
285
281
|
@cache.incr(:a, 2**62).should < 2**62
|
286
282
|
end
|
287
|
-
|
283
|
+
|
288
284
|
it 'should fail if not number' do
|
289
285
|
@cache.incr(:a).should == nil
|
290
286
|
@cache.get_hash([:a]).should == {}
|
@@ -292,13 +288,13 @@ describe AppEngine::Memcache do
|
|
292
288
|
lambda {@cache.incr(:b)}.should raise_error(
|
293
289
|
AppEngine::Memcache::InvalidValueError)
|
294
290
|
end
|
295
|
-
|
291
|
+
|
296
292
|
it 'should increment strings' do
|
297
293
|
@cache.set(:a, '7')
|
298
294
|
@cache.incr(:a).should == 8
|
299
295
|
end
|
300
296
|
end
|
301
|
-
|
297
|
+
|
302
298
|
describe 'decr' do
|
303
299
|
it 'should decrement number' do
|
304
300
|
@cache.set(:a, 7)
|
@@ -312,72 +308,85 @@ describe AppEngine::Memcache do
|
|
312
308
|
@cache.get(:a).should == 0
|
313
309
|
end
|
314
310
|
end
|
315
|
-
|
311
|
+
|
316
312
|
describe 'readonly' do
|
317
313
|
before :each do
|
318
314
|
@rocache = AppEngine::Memcache.new(:readonly => true)
|
319
315
|
@ex = AppEngine::Memcache::MemcacheError
|
320
316
|
end
|
321
|
-
|
317
|
+
|
322
318
|
it 'should allow reads' do
|
323
319
|
@cache[:a] = 1
|
324
320
|
@rocache.get(:a).should == 1
|
325
321
|
end
|
326
|
-
|
322
|
+
|
327
323
|
it 'should allow stats' do
|
328
324
|
@cache[:a] = 7
|
329
325
|
@rocache.stats[:items].should == 1
|
330
326
|
end
|
331
|
-
|
327
|
+
|
332
328
|
it 'should block delete' do
|
333
329
|
@cache[:a] = 1
|
334
330
|
lambda {@rocache.delete(:a)}.should raise_error(@ex)
|
335
331
|
@cache[:a].should == 1
|
336
332
|
end
|
337
|
-
|
333
|
+
|
338
334
|
it 'should block add' do
|
339
335
|
lambda {@rocache.add(:a, 1)}.should raise_error(@ex)
|
340
336
|
lambda {@rocache.add_many({:b => 1})}.should raise_error(@ex)
|
341
337
|
@rocache.get_hash(:a, :b).should == {}
|
342
338
|
end
|
343
|
-
|
339
|
+
|
344
340
|
it 'should block set' do
|
345
341
|
lambda {@rocache.set(:a, 1)}.should raise_error(@ex)
|
346
342
|
lambda {@rocache.set_many({:b => 1})}.should raise_error(@ex)
|
347
343
|
@rocache.get_hash(:a, :b).should == {}
|
348
344
|
end
|
349
|
-
|
345
|
+
|
350
346
|
it 'should block replace' do
|
351
347
|
@cache[:a, :b] = :A, :B
|
352
348
|
lambda {@rocache.replace(:a, 1)}.should raise_error(@ex)
|
353
349
|
lambda {@rocache.replace_many({:b => 1})}.should raise_error(@ex)
|
354
350
|
@rocache[:a, :b].should == [:A, :B]
|
355
351
|
end
|
356
|
-
|
352
|
+
|
357
353
|
it 'should block clear' do
|
358
354
|
@cache[:a] = 1
|
359
355
|
lambda {@rocache.clear}.should raise_error(@ex)
|
360
356
|
lambda {@rocache.flush_all}.should raise_error(@ex)
|
361
357
|
@rocache[:a].should == 1
|
362
358
|
end
|
363
|
-
|
359
|
+
|
364
360
|
it 'should block incr' do
|
365
361
|
@cache[:a] = 1
|
366
362
|
lambda {@rocache.incr(:a)}.should raise_error(@ex)
|
367
363
|
@rocache[:a].should == 1
|
368
364
|
end
|
369
|
-
|
365
|
+
|
370
366
|
it 'should block decr' do
|
371
367
|
@cache[:a] = 1
|
372
368
|
lambda {@rocache.decr(:a)}.should raise_error(@ex)
|
373
369
|
@rocache[:a].should == 1
|
374
370
|
end
|
375
371
|
end
|
376
|
-
|
372
|
+
|
377
373
|
describe "namespaces" do
|
378
374
|
it 'should get namespace from initialize' do
|
379
375
|
cache = AppEngine::Memcache.new(:namespace => "foo")
|
380
376
|
cache.namespace.should == "foo"
|
381
377
|
end
|
382
378
|
end
|
379
|
+
|
380
|
+
describe "utf8" do
|
381
|
+
it "should support utf8 value" do
|
382
|
+
@cache.set('foobar', 'テスト').should == true
|
383
|
+
@cache.get('foobar').should == 'テスト'
|
384
|
+
@cache['foobar'].should == 'テスト'
|
385
|
+
end
|
386
|
+
it "should support utf8 key" do
|
387
|
+
@cache.set('ふーばー', 'てすと').should == true
|
388
|
+
@cache.get('ふーばー').should == 'てすと'
|
389
|
+
@cache['ふーばー'].should == 'てすと'
|
390
|
+
end
|
391
|
+
end
|
383
392
|
end
|
data/spec/spec_helper.rb
CHANGED
@@ -8,9 +8,8 @@ rescue LoadError
|
|
8
8
|
end
|
9
9
|
|
10
10
|
$:.unshift(File.dirname(__FILE__) + '/../lib')
|
11
|
-
AppEngine::SDK.load_apiproxy
|
12
11
|
require 'appengine-apis/testing'
|
13
|
-
AppEngine::Testing.
|
12
|
+
AppEngine::Testing.setup
|
14
13
|
|
15
14
|
class ProtoMatcher
|
16
15
|
def compare(hash, proto, prefix='')
|
@@ -36,19 +35,19 @@ class ProtoMatcher
|
|
36
35
|
end
|
37
36
|
end
|
38
37
|
end
|
39
|
-
|
38
|
+
|
40
39
|
def compare_value(label, expected, actual)
|
41
40
|
if expected != actual
|
42
|
-
@failures << "%s differs. expected: %s actual: %s" %
|
41
|
+
@failures << "%s differs. expected: %s actual: %s" %
|
43
42
|
[label, expected.inspect, actual.inspect]
|
44
43
|
end
|
45
44
|
end
|
46
|
-
|
45
|
+
|
47
46
|
def initialize(klass, expected)
|
48
47
|
@klass = klass
|
49
48
|
@expected = expected
|
50
49
|
end
|
51
|
-
|
50
|
+
|
52
51
|
def matches(bytes)
|
53
52
|
@failures = []
|
54
53
|
@proto = @klass.new
|
@@ -56,12 +55,12 @@ class ProtoMatcher
|
|
56
55
|
compare(@expected, @proto)
|
57
56
|
@failures.empty?
|
58
57
|
end
|
59
|
-
|
58
|
+
|
60
59
|
def ==(bytes)
|
61
60
|
Spec::Expectations.fail_with(failure_message) unless matches(bytes)
|
62
61
|
true
|
63
62
|
end
|
64
|
-
|
63
|
+
|
65
64
|
def failure_message
|
66
65
|
@failures.join("\n")
|
67
66
|
end
|
@@ -72,7 +71,7 @@ module ProtoMethods
|
|
72
71
|
ProtoMatcher.new(klass, hash)
|
73
72
|
end
|
74
73
|
alias be_proto proto
|
75
|
-
|
74
|
+
|
76
75
|
def mock_delegate
|
77
76
|
delegate = mock("apiproxy")
|
78
77
|
delegate.instance_eval do
|
@@ -80,7 +79,7 @@ module ProtoMethods
|
|
80
79
|
include AppEngine::ApiProxy::Delegate
|
81
80
|
end
|
82
81
|
end
|
83
|
-
end
|
82
|
+
end
|
84
83
|
end
|
85
84
|
|
86
85
|
Spec::Runner.configure do |config|
|
data/spec/users_spec.rb
CHANGED
@@ -18,50 +18,52 @@ require 'appengine-apis/users'
|
|
18
18
|
|
19
19
|
describe AppEngine::Users do
|
20
20
|
before :all do
|
21
|
-
AppEngine::Testing::
|
21
|
+
AppEngine::Testing::setup
|
22
22
|
end
|
23
|
-
|
23
|
+
|
24
24
|
before :each do
|
25
|
-
@env = AppEngine::Testing::
|
26
|
-
@env.
|
25
|
+
@env = AppEngine::Testing::helper
|
26
|
+
@env.set_env_email 'foo@example.com'
|
27
|
+
@env.set_env_auth_domain 'gmail.com'
|
28
|
+
@env.set_env_is_logged_in true
|
27
29
|
end
|
28
|
-
|
30
|
+
|
29
31
|
it "should have default auth_domain" do
|
30
32
|
user = AppEngine::Users.current_user
|
31
33
|
user.email.should == 'foo@example.com'
|
32
34
|
user.auth_domain.should == 'gmail.com'
|
33
35
|
end
|
34
|
-
|
36
|
+
|
35
37
|
it 'should read auth_domain' do
|
36
|
-
@env.
|
38
|
+
@env.set_env_auth_domain 'example.com'
|
37
39
|
AppEngine::Users.current_user.auth_domain.should == 'example.com'
|
38
40
|
end
|
39
|
-
|
41
|
+
|
40
42
|
it 'should read admin' do
|
41
43
|
AppEngine::Users.admin?.should == false
|
42
|
-
@env.
|
44
|
+
@env.set_env_is_admin true
|
43
45
|
AppEngine::Users.admin?.should == true
|
44
46
|
end
|
45
47
|
|
46
48
|
it 'should set logged_in?' do
|
47
49
|
AppEngine::Users.logged_in?.should == true
|
48
|
-
@env.
|
50
|
+
@env.set_env_is_logged_in nil
|
49
51
|
AppEngine::Users.logged_in?.should == false
|
50
52
|
end
|
51
|
-
|
53
|
+
|
52
54
|
it 'should create urls' do
|
53
55
|
login = AppEngine::Users.create_login_url('/foobar')
|
54
56
|
logout = AppEngine::Users.create_logout_url('/foobaz')
|
55
57
|
login.should =~ /foobar/
|
56
58
|
logout.should =~ /foobaz/
|
57
59
|
end
|
58
|
-
|
60
|
+
|
59
61
|
it 'should support new without auth domain' do
|
60
62
|
user = AppEngine::Users::User.new('foo@example.com')
|
61
63
|
user.auth_domain.should == 'gmail.com'
|
62
64
|
end
|
63
|
-
|
64
|
-
|
65
|
+
|
66
|
+
|
65
67
|
it 'should support new with auth domain' do
|
66
68
|
user = AppEngine::Users::User.new('foo@example.com', 'example.com')
|
67
69
|
user.auth_domain.should == 'example.com'
|
metadata
CHANGED
@@ -1,7 +1,12 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: appengine-apis
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
|
4
|
+
prerelease: false
|
5
|
+
segments:
|
6
|
+
- 0
|
7
|
+
- 0
|
8
|
+
- 13
|
9
|
+
version: 0.0.13
|
5
10
|
platform: ruby
|
6
11
|
authors:
|
7
12
|
- Ryan Brown
|
@@ -9,19 +14,21 @@ autorequire:
|
|
9
14
|
bindir: bin
|
10
15
|
cert_chain: []
|
11
16
|
|
12
|
-
date:
|
17
|
+
date: 2010-04-08 00:00:00 -07:00
|
13
18
|
default_executable:
|
14
19
|
dependencies:
|
15
20
|
- !ruby/object:Gem::Dependency
|
16
21
|
name: appengine-rack
|
17
|
-
|
18
|
-
|
19
|
-
version_requirements: !ruby/object:Gem::Requirement
|
22
|
+
prerelease: false
|
23
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
20
24
|
requirements:
|
21
25
|
- - ">="
|
22
26
|
- !ruby/object:Gem::Version
|
27
|
+
segments:
|
28
|
+
- 0
|
23
29
|
version: "0"
|
24
|
-
|
30
|
+
type: :runtime
|
31
|
+
version_requirements: *id001
|
25
32
|
description: Ruby API wrappers for App Engine
|
26
33
|
email: ribrdb@gmail.com
|
27
34
|
executables: []
|
@@ -45,6 +52,7 @@ files:
|
|
45
52
|
- lib/appengine-apis/mail.rb
|
46
53
|
- lib/appengine-apis/memcache.rb
|
47
54
|
- lib/appengine-apis/merb-logger.rb
|
55
|
+
- lib/appengine-apis/runtime.rb
|
48
56
|
- lib/appengine-apis/sdk.rb
|
49
57
|
- lib/appengine-apis/tempfile.rb
|
50
58
|
- lib/appengine-apis/testing.rb
|
@@ -76,18 +84,20 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
76
84
|
requirements:
|
77
85
|
- - ">="
|
78
86
|
- !ruby/object:Gem::Version
|
87
|
+
segments:
|
88
|
+
- 0
|
79
89
|
version: "0"
|
80
|
-
version:
|
81
90
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
82
91
|
requirements:
|
83
92
|
- - ">="
|
84
93
|
- !ruby/object:Gem::Version
|
94
|
+
segments:
|
95
|
+
- 0
|
85
96
|
version: "0"
|
86
|
-
version:
|
87
97
|
requirements: []
|
88
98
|
|
89
99
|
rubyforge_project:
|
90
|
-
rubygems_version: 1.3.
|
100
|
+
rubygems_version: 1.3.6
|
91
101
|
signing_key:
|
92
102
|
specification_version: 3
|
93
103
|
summary: Ruby API wrappers for App Engine
|