appengine-apis 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,123 @@
1
+ #!/usr/bin/ruby1.8 -w
2
+ #
3
+ # Copyright:: Copyright 2007 Google Inc.
4
+ # Original Author:: Ryan Brown (mailto:ribrdb@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
+ #
19
+ # Helpers for installing stub apis in unit tests.
20
+
21
+ require 'appengine-apis/apiproxy'
22
+
23
+ module AppEngine
24
+ module Testing
25
+ import com.google.appengine.tools.development.ApiProxyLocalFactory
26
+ import com.google.appengine.api.datastore.dev.LocalDatastoreService
27
+
28
+ class TestEnv # :nodoc:
29
+ include AppEngine::ApiProxy::Environment
30
+
31
+ attr_writer :appid, :version, :email, :admin, :logged_in
32
+ attr_writer :auth_domain, :request_namespace, :default_namespace
33
+
34
+ def initialize
35
+ @appid = "test"
36
+ @version = "1.0"
37
+ @auth_domain = "gmail.com"
38
+ end
39
+
40
+ def getAppId
41
+ @appid
42
+ end
43
+
44
+ def getVersionId
45
+ @version
46
+ end
47
+
48
+ def getEmail
49
+ @email
50
+ end
51
+
52
+ def isLoggedIn
53
+ @logged_in
54
+ end
55
+
56
+ def isAdmin
57
+ @admin
58
+ end
59
+
60
+ def getAuthDomain
61
+ @auth_domain
62
+ end
63
+
64
+ def getRequestNamespace
65
+ @request_namespace
66
+ end
67
+
68
+ def getDefaultNamespace
69
+ @default_namespace
70
+ end
71
+
72
+ def setDefaultNamespace(s)
73
+ @default_namespace = s
74
+ end
75
+ end
76
+
77
+ class << self
78
+ def install_test_env
79
+ env = TestEnv.new
80
+ ApiProxy::setEnvironmentForCurrentThread(env)
81
+ env
82
+ end
83
+
84
+ def factory
85
+ @factory ||= ApiProxyLocalFactory.new
86
+ end
87
+
88
+ def app_dir
89
+ file = factory.getApplicationDirectory
90
+ file && file.path
91
+ end
92
+
93
+ def app_dir=(dir)
94
+ factory.setApplicationDirectory(java.io.File.new(dir))
95
+ end
96
+
97
+ # Force all datastore operations to use an in-memory datastore.
98
+ def install_test_datastore
99
+ self.app_dir = '.' if app_dir.nil?
100
+ delegate = factory.create
101
+ delegate.set_property(
102
+ LocalDatastoreService::NO_STORAGE_PROPERTY, "true")
103
+ delegate.set_property(
104
+ LocalDatastoreService::MAX_QUERY_LIFETIME_PROPERTY,
105
+ java.lang.Integer::MAX_VALUE.to_s)
106
+ delegate.set_property(
107
+ LocalDatastoreService::MAX_TRANSACTION_LIFETIME_PROPERTY,
108
+ java.lang.Integer::MAX_VALUE.to_s)
109
+ ApiProxy::setDelegate(delegate)
110
+ delegate
111
+ end
112
+
113
+ def install_api_stubs
114
+ self.app_dir = '.' if app_dir.nil?
115
+ delegate = factory.create
116
+ ApiProxy::setDelegate(delegate)
117
+ delegate
118
+ end
119
+
120
+ end
121
+
122
+ end
123
+ end
@@ -0,0 +1,10 @@
1
+ #!/usr/bin/env ruby
2
+ # File: script/console
3
+ irb = RUBY_PLATFORM =~ /(:?mswin|mingw)/ ? 'irb.bat' : 'irb'
4
+
5
+ libs = " -r irb/completion"
6
+ # Perhaps use a console_lib to store any extra methods I may want available in the cosole
7
+ # libs << " -r #{File.dirname(__FILE__) + '/../lib/console_lib/console_logger.rb'}"
8
+ libs << " -r #{File.dirname(__FILE__) + '/../lib/appengine-apis.rb'}"
9
+ puts "Loading appengine-apis gem"
10
+ exec "#{irb} #{libs} --simple-prompt"
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+ APP_ROOT = File.expand_path(File.join(File.dirname(__FILE__), '..'))
3
+
4
+ begin
5
+ require 'rubigen'
6
+ rescue LoadError
7
+ require 'rubygems'
8
+ require 'rubigen'
9
+ end
10
+ require 'rubigen/scripts/destroy'
11
+
12
+ ARGV.shift if ['--help', '-h'].include?(ARGV[0])
13
+ RubiGen::Base.use_component_sources! [:rubygems, :newgem, :newgem_theme, :test_unit]
14
+ RubiGen::Scripts::Destroy.new.run(ARGV)
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+ APP_ROOT = File.expand_path(File.join(File.dirname(__FILE__), '..'))
3
+
4
+ begin
5
+ require 'rubigen'
6
+ rescue LoadError
7
+ require 'rubygems'
8
+ require 'rubigen'
9
+ end
10
+ require 'rubigen/scripts/generate'
11
+
12
+ ARGV.shift if ['--help', '-h'].include?(ARGV[0])
13
+ RubiGen::Base.use_component_sources! [:rubygems, :newgem, :newgem_theme, :test_unit]
14
+ RubiGen::Scripts::Generate.new.run(ARGV)
@@ -0,0 +1,150 @@
1
+ # Copyright:: Copyright 2009 Google Inc.
2
+ # Original Author:: Ryan Brown (mailto:ribrdb@google.com)
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License");
5
+ # you may not use this file except in compliance with the License.
6
+ # You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS,
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ # See the License for the specific language governing permissions and
14
+ # limitations under the License.
15
+
16
+ require File.dirname(__FILE__) + '/spec_helper.rb'
17
+ require 'appengine-apis/datastore'
18
+
19
+ describe AppEngine::Datastore do
20
+ Datastore = AppEngine::Datastore
21
+
22
+ before :each do
23
+ AppEngine::Testing.install_test_datastore
24
+ end
25
+
26
+ it "should support get/put" do
27
+ entity = Datastore::Entity.new("Test")
28
+ entity[:a] = "a"
29
+ entity[:b] = "b"
30
+ key = Datastore.put(entity)
31
+ entity.key.should == key
32
+ stored = Datastore.get(key)
33
+ stored.should == entity
34
+ stored[:a].should == "a"
35
+ stored[:b].should == "b"
36
+ end
37
+
38
+ it "should put many" do
39
+ a = Datastore::Entity.new("A")
40
+ b = Datastore::Entity.new("B")
41
+ keys = Datastore.put(a, b)
42
+ keys.size.should == 2
43
+ keys[0].kind.should == "A"
44
+ keys[1].kind.should == "B"
45
+ got = Datastore.get(keys)
46
+ got.size.should == 2
47
+ got[0].should == a
48
+ got[1].should == b
49
+ end
50
+
51
+ it "should support failed transactions" do
52
+ pending("Real local transactions") do
53
+ a = Datastore::Entity.new("A")
54
+ a[:a] = 0
55
+ Datastore.put(a)
56
+ p = lambda do
57
+ Datastore.transaction do
58
+ a2 = Datastore.get(a.key)
59
+ a[:a] += 1
60
+ Datastore.put(nil, a)
61
+ Datastore.put(a2)
62
+ end
63
+ end
64
+ p.should raise_error Datastore::TransactionFailed
65
+ end
66
+ end
67
+
68
+ it "should retry transactions" do
69
+ pending("Real local transactions") do
70
+ a = Datastore::Entity.new("A")
71
+ a[:a] = 0
72
+ Datastore.put(a)
73
+ Datastore.transaction(3) do
74
+ a2 = Datastore.get(a.key)
75
+ a[:a] += 1
76
+ Datastore.put(nil, a) if a[:a] < 3
77
+ a2[:a] = "2: #{a2[:a]}"
78
+ Datastore.put(a2)
79
+ end
80
+
81
+ Datastore.get(a.key)[:a].should == '2: 2'
82
+ end
83
+ end
84
+
85
+ it "should close transactions" do
86
+ lambda {Datastore.transaction{ raise "Foo"}}.should raise_error "Foo"
87
+ Datastore.active_transactions.to_a.should == []
88
+ end
89
+ end
90
+
91
+ describe AppEngine::Datastore::Query do
92
+ Datastore = AppEngine::Datastore
93
+ Query = AppEngine::Datastore::Query
94
+
95
+ before :all do
96
+ AppEngine::Testing.install_test_datastore
97
+ @a = Datastore::Entity.new("A")
98
+ @a['name'] = 'a'
99
+ Datastore.put(@a)
100
+
101
+ @aa = Datastore::Entity.new("A", @a.key)
102
+ @aa['name'] = 'aa'
103
+
104
+ @b = Datastore::Entity.new("B")
105
+ @b['name'] = 'b'
106
+
107
+ @ab = Datastore::Entity.new("B", @a.key)
108
+ @ab['name'] = 'ab'
109
+ Datastore.put(@aa, @ab, @b)
110
+ end
111
+
112
+ it "should support chaining" do
113
+ q = Query.new("Foo")
114
+ q.set_ancestor(@a.key).sort('name').filter(
115
+ 'name', Query::EQUAL, 'Bob').should == q
116
+ end
117
+
118
+ it "should support ancestor" do
119
+ a = @a.key
120
+ q = Query.new("A", a)
121
+ q.java_query.ancestor.should == a
122
+ q.fetch.to_a.should == [@a, @aa]
123
+
124
+ q = Query.new("A")
125
+ q.set_ancestor(a)
126
+ q.java_query.ancestor.should == a
127
+ q.fetch.to_a.should == [@a, @aa]
128
+
129
+ q = Query.new("A")
130
+ q.ancestor = a
131
+ q.java_query.ancestor.should == a
132
+ q.fetch.to_a.should == [@a, @aa]
133
+ end
134
+
135
+ it "should support ancestor only" do
136
+ a = @a.key
137
+ q = Query.new(a)
138
+ q.java_query.ancestor.should == a
139
+ pending("Local ancestory only queries") do
140
+ q.fetch.to_a.should == [@a, @aa, @ab]
141
+ end
142
+ end
143
+
144
+ it "should support sort" do
145
+ q = Query.new("A")
146
+ q.sort('name', Query::DESCENDING)
147
+ q.fetch.to_a.should == [@aa, @a]
148
+ end
149
+
150
+ end
@@ -0,0 +1,198 @@
1
+ # Copyright:: Copyright 2009 Google Inc.
2
+ # Original Author:: Ryan Brown (mailto:ribrdb@google.com)
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License");
5
+ # you may not use this file except in compliance with the License.
6
+ # You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS,
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ # See the License for the specific language governing permissions and
14
+ # limitations under the License.
15
+
16
+ require File.dirname(__FILE__) + '/spec_helper.rb'
17
+ require 'appengine-apis/datastore_types'
18
+
19
+ describe AppEngine::Datastore::Key do
20
+ Key = AppEngine::Datastore::Key
21
+
22
+ it "should support ==" do
23
+ a1 = Key.from_path("A", 1)
24
+ a2 = Key.from_path("A", 1)
25
+ a1.should == a2
26
+ a2.should.eql? a1
27
+ a1.hash.should == a2.hash
28
+ pending("Key.compareTo") do
29
+ (a1 <=> a2).should == 0
30
+ end
31
+ end
32
+
33
+ it "should support <=>" do
34
+ pending("Key.compareTo") do
35
+ a1 = Key.from_path("A", 1)
36
+ a2 = Key.from_path("A", 2)
37
+ a1.should < a2
38
+ a2.should > a1
39
+ (a1 <=> a2).should == -1
40
+ (a2 <=> a1).should == 1
41
+ end
42
+ end
43
+
44
+ it "should create from id" do
45
+ key = Key.from_path("Foo", 27)
46
+ key.kind.should == 'Foo'
47
+ key.id.should == 27
48
+ key.id_or_name.should == 27
49
+ end
50
+
51
+ it "should create from name" do
52
+ key = Key.from_path("Bar", 'baz')
53
+ key.kind.should == 'Bar'
54
+ key.name.should == 'baz'
55
+ key.id_or_name.should == 'baz'
56
+ end
57
+
58
+ it "should create with parent" do
59
+ parent = Key.from_path("Foo", 1)
60
+ key = Key.from_path(parent, "Bar", 2)
61
+ key.kind.should == 'Bar'
62
+ key.id.should == 2
63
+ key.parent.should == parent
64
+ end
65
+
66
+ it "should support long paths" do
67
+ key = Key.from_path('A', 1, 'B', 2, 'C', 3)
68
+ key.kind.should == 'C'
69
+ key.id.should == 3
70
+ key.parent.kind.should == 'B'
71
+ key.parent.id.should == 2
72
+ key.parent.parent.kind.should == 'A'
73
+ key.parent.parent.id.should == 1
74
+ end
75
+
76
+ it "should encode" do
77
+ key = Key.from_path('Foo', 'bar')
78
+ key.to_s.should == 'agR0ZXN0cgwLEgNGb28iA2Jhcgw'
79
+ end
80
+
81
+ it "should create from encoded" do
82
+ decoded = Key.new('agR0ZXN0cgwLEgNGb28iA2Jhcgw')
83
+ key = Key.from_path('Foo', 'bar')
84
+ decoded.should == key
85
+ end
86
+
87
+ end
88
+
89
+ describe AppEngine::Datastore::Entity do
90
+
91
+ before :each do
92
+ @entity = AppEngine::Datastore::Entity.new('Test')
93
+ end
94
+
95
+ it "should support nil" do
96
+ @entity['nil'] = nil
97
+ @entity.has_property?('nil').should == true
98
+ @entity['nil'].should == nil
99
+ end
100
+
101
+ it "should support true" do
102
+ @entity['true'] = true
103
+ @entity['true'].should == true
104
+ end
105
+
106
+ it "should support false" do
107
+ @entity['false'] = false
108
+ @entity['false'].should == false
109
+ end
110
+
111
+ it "should support Strings" do
112
+ @entity['string'] = 'a string'
113
+ @entity['string'].should == 'a string'
114
+ end
115
+
116
+ it "should support Integers" do
117
+ @entity['int'] = 42
118
+ @entity['int'].should == 42
119
+ end
120
+
121
+ it "should support Floats" do
122
+ @entity['float'] = 3.1415
123
+ @entity['float'].should == 3.1415
124
+ end
125
+
126
+ it "should support Symbol for name" do
127
+ @entity[:foo] = 'bar'
128
+ @entity[:foo].should == 'bar'
129
+ @entity['foo'].should == 'bar'
130
+ end
131
+
132
+ it "should support Text" do
133
+ text = 'Some text. ' * 1000
134
+ @entity['text'] = AppEngine::Datastore::Text.new(text)
135
+ @entity['text'].should == text
136
+ @entity['text'].class.should == AppEngine::Datastore::Text
137
+ end
138
+
139
+ it "should support Blob" do
140
+ blob = "\0\1\2" * 1000
141
+ @entity['blob'] = AppEngine::Datastore::Blob.new(blob)
142
+ @entity['blob'].should == blob
143
+ @entity['blob'].class.should == AppEngine::Datastore::Blob
144
+ end
145
+
146
+ it "should support ByteString" do
147
+ blob = "\0\1\2"
148
+ @entity['blob'] = AppEngine::Datastore::ByteString.new(blob)
149
+ @entity['blob'].should == blob
150
+ @entity['blob'].class.should == AppEngine::Datastore::ByteString
151
+ end
152
+
153
+ it "should support Link" do
154
+ link = "http://example.com/" + "0" * 1000
155
+ @entity['link'] = AppEngine::Datastore::Link.new(link)
156
+ @entity['link'].should == link
157
+ @entity['link'].class.should == AppEngine::Datastore::Link
158
+ end
159
+
160
+ it "should support Time" do
161
+ time = Time.now - 3600
162
+ @entity['time'] = time
163
+ @entity['time'].to_s.should == time.to_s
164
+ @entity['time'].class.should == Time
165
+ end
166
+
167
+ it "should support multiple values" do
168
+ list = [1, 2, 3]
169
+ @entity['list'] = list
170
+ @entity['list'].should == list
171
+ end
172
+
173
+ it "should not support random types" do
174
+ lambda{@entity['foo'] = Kernel}.should raise_error(ArgumentError)
175
+ end
176
+
177
+ it "should support delete" do
178
+ @entity['foo'] = 'bar'
179
+ @entity.delete('foo')
180
+ @entity.has_property?('foo').should == false
181
+ end
182
+
183
+ it "should support delete symbol" do
184
+ @entity['foo'] = 'bar'
185
+ @entity.delete(:foo)
186
+ @entity.has_property?('foo').should == false
187
+ end
188
+
189
+ it "should support each" do
190
+ props = {'foo' => 'bar', 'count' => 3}
191
+ props.each {|name, value| @entity[name] = value}
192
+ @entity.each do |name, value|
193
+ props.delete(name).should == value
194
+ end
195
+ props.should == {}
196
+ end
197
+
198
+ end