fake_dynamo 0.2.4 → 0.2.5

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 8333d5e9d5e01c91f1ec911ad7b6ba01af87b16a
4
- data.tar.gz: c95189c6e7ef0b1bb321b1facd746ea49ee3f840
3
+ metadata.gz: 00648c19b3f1c992a04883bf4d11c9f20dbcb0fc
4
+ data.tar.gz: 682d63c6cdd1d7cfb71b5cb6e49015e2511e78cf
5
5
  SHA512:
6
- metadata.gz: 51aea4e7d2e47b6c9c16017b5704157c5ca39156a68e80a9825107a2aade9a745362a189ba1c2905afcfa98b5a41f6556efa0312f7b2fb77e56787f714687dbe
7
- data.tar.gz: 6adbf3ac4ce20bc9b89af8ee7717d2adbc86f066a305203926c5fa02acbc2ce68a1bbf4d8df31234182f73057b94ab3769e01319b9dba478ee641328527365e9
6
+ metadata.gz: 451e3ecb17977f41920ecc97c5a83f609914665be57d567624704b6b4b6ede06a5423e1208b7b811eebc44323610ab2141b8c2dc1ab1aad9866fd228e77b3401
7
+ data.tar.gz: ea9338856d85b0550e44fe69090a33872470fe2bf861f09985f4a4707d42f03c6656ce91be213999c4a58ee698a9f1191b60d34717f882f458e410d1b4264cb9
@@ -1,4 +1,4 @@
1
- ## 0.2.4 <2013-07-17>
1
+ ## 0.2.4 (2013-07-17)
2
2
 
3
3
  * Remove attribute if the set becomes empty - #27
4
4
  * Do not append '\n' at the end of base64 encoded binary - #24
data/README.md CHANGED
@@ -6,7 +6,7 @@ local hosted, inmemory Amazon DynamoDB emulator.
6
6
 
7
7
  | Amazon DynamoDB API version | FakeDynamo gem version|
8
8
  | --------------------------- | ----------------------|
9
- | [2012-08-10][v2] | 0.2.4 |
9
+ | [2012-08-10][v2] | 0.2.5 |
10
10
  | [2011-12-05][v1] | 0.1.3 |
11
11
 
12
12
 
@@ -19,7 +19,7 @@ local hosted, inmemory Amazon DynamoDB emulator.
19
19
  __requires ruby >= 1.9__
20
20
 
21
21
  ````
22
- gem install fake_dynamo --version 0.2.3
22
+ gem install fake_dynamo --version 0.2.5
23
23
 
24
24
  fake_dynamo --port 4567
25
25
  ````
@@ -53,6 +53,14 @@ AWS.config(:use_ssl => false,
53
53
  region: "xxx"});
54
54
  ````
55
55
 
56
+ * [aws-sdk-java](https://github.com/aws/aws-sdk-java) (AWS SDK for Java)
57
+
58
+ ````java
59
+ AWSCredentials credentials = new BasicAWSCredentials("xxx", "xxx");
60
+ AmazonDynamoDB client = new AmazonDynamoDBClient(credentials);
61
+ client.setEndpoint("http://localhost:4567");
62
+ ````
63
+
56
64
  __please open a pull request with your configuration if you are using
57
65
  fake_dynamo with clients other than the ones mentioned above__.
58
66
 
@@ -57,7 +57,7 @@ if (pid = options[:pid])
57
57
  File.open(pid, 'w') { |f| f.write(Process.pid) }
58
58
  end
59
59
 
60
- FakeDynamo::Storage.db_path = options[:db]
60
+ FakeDynamo::Storage.instance.init_db(options[:db])
61
61
  FakeDynamo::Logger.setup(options[:log_level])
62
62
 
63
63
  if options[:compact]
@@ -1065,6 +1065,7 @@
1065
1065
  - :required
1066
1066
  - :enum: [EQ, LE, LT, GE, GT, BEGINS_WITH, BETWEEN]
1067
1067
  - :within: !ruby/range 1..2
1068
+ - :required
1068
1069
  ScanIndexForward:
1069
1070
  - :boolean
1070
1071
  ExclusiveStartKey:
@@ -4,7 +4,7 @@ module FakeDynamo
4
4
  attr_accessor :key, :attributes
5
5
 
6
6
  class << self
7
- def from_data(data, key_schema)
7
+ def from_data(data, key_schema, attribute_definitions)
8
8
  item = Item.new
9
9
  item.key = Key.from_schema(data, key_schema)
10
10
 
@@ -14,6 +14,8 @@ module FakeDynamo
14
14
  item.attributes[name] = Attribute.from_hash(name, value)
15
15
  end
16
16
  end
17
+
18
+ item.validate_attribute_types(attribute_definitions)
17
19
  item
18
20
  end
19
21
 
@@ -116,5 +118,13 @@ module FakeDynamo
116
118
  {}
117
119
  end
118
120
  end
121
+
122
+ def validate_attribute_types(definitions)
123
+ definitions.each do |definition|
124
+ if attr = self[definition.name]
125
+ validate_type(attr.as_hash[definition.name], definition)
126
+ end
127
+ end
128
+ end
119
129
  end
120
130
  end
@@ -4,11 +4,9 @@ require 'tempfile'
4
4
  module FakeDynamo
5
5
  class Storage
6
6
 
7
- attr_accessor :compacted, :loaded
7
+ attr_accessor :compacted, :loaded, :db_path
8
8
 
9
9
  class << self
10
- attr_accessor :db_path
11
-
12
10
  def instance
13
11
  @storage ||= Storage.new
14
12
  end
@@ -18,10 +16,6 @@ module FakeDynamo
18
16
  Logger.log
19
17
  end
20
18
 
21
- def initialize
22
- init_db
23
- end
24
-
25
19
  def write_commands
26
20
  %w[CreateTable DeleteItem DeleteTable PutItem UpdateItem UpdateTable BatchWriteItem]
27
21
  end
@@ -30,14 +24,17 @@ module FakeDynamo
30
24
  write_commands.include?(command)
31
25
  end
32
26
 
33
- def db_path
34
- self.class.db_path
35
- end
27
+ def init_db(path)
28
+ @db_path = path
29
+
30
+ return if File.exists?(db_path) && File.writable?(db_path)
36
31
 
37
- def init_db
38
- return if File.exists? db_path
39
32
  FileUtils.mkdir_p(File.dirname(db_path))
40
33
  FileUtils.touch(db_path)
34
+ rescue Errno::EACCES
35
+ puts "Cannot create or access db file at #{db_path}"
36
+ puts "Make sure you have write access to #{db_path}"
37
+ exit(1)
41
38
  end
42
39
 
43
40
  def delete_db
@@ -106,7 +106,7 @@ module FakeDynamo
106
106
  end
107
107
 
108
108
  def put_item(data)
109
- item = Item.from_data(data['Item'], key_schema)
109
+ item = Item.from_data(data['Item'], key_schema, attribute_definitions)
110
110
  old_item = @items[item.key]
111
111
  check_conditions(old_item, data['Expected'])
112
112
  @items[item.key] = item
@@ -115,7 +115,7 @@ module FakeDynamo
115
115
  end
116
116
 
117
117
  def batch_put_request(data)
118
- Item.from_data(data['Item'], key_schema)
118
+ Item.from_data(data['Item'], key_schema, attribute_definitions)
119
119
  end
120
120
 
121
121
  def batch_put(item)
@@ -193,6 +193,8 @@ module FakeDynamo
193
193
  attribute_updates.each do |name, update_data|
194
194
  item.update(name, update_data)
195
195
  end
196
+
197
+ item.validate_attribute_types(attribute_definitions)
196
198
  end
197
199
  rescue => e
198
200
  if item_created
@@ -318,14 +320,14 @@ module FakeDynamo
318
320
  end
319
321
 
320
322
  def sack_attributes(data, index)
321
- return unless index
323
+ return if !index || index.projection.type == 'ALL'
322
324
 
323
325
  if data['Select'] == 'COUNT'
324
326
  return projected_attributes(index)
325
327
  end
326
328
 
327
329
  if attrs = attributes_to_get(data, index)
328
- if (attrs - projected_attributes(index)).empty?
330
+ if (attrs - (projected_attributes(index))).empty?
329
331
  return projected_attributes(index)
330
332
  end
331
333
  end
@@ -1,3 +1,3 @@
1
1
  module FakeDynamo
2
- VERSION = "0.2.4"
2
+ VERSION = "0.2.5"
3
3
  end
@@ -30,7 +30,7 @@ module FakeDynamo
30
30
  'Item' => {
31
31
  'AttributeName1' => { 'S' => "test" },
32
32
  'AttributeName2' => { 'N' => '11' },
33
- 'AttributeName3' => { 'S' => "another" },
33
+ 'AttributeName3' => { 'N' => "14" },
34
34
  'binary' => { 'B' => Base64.strict_encode64("binary") },
35
35
  'binary_set' => { 'BS' => [Base64.strict_encode64("binary")] }
36
36
  },
@@ -146,6 +146,17 @@ module FakeDynamo
146
146
  end.to raise_error(ValidationException, /mismatch/i)
147
147
  end
148
148
 
149
+ it 'should fail on index type mismatch' do
150
+ expect do
151
+ subject.put_item({ 'TableName' => 'Table1',
152
+ 'Item' => {
153
+ 'AttributeName1' => { 'S' => "test" },
154
+ 'AttributeName2' => { 'N' => '11' },
155
+ 'AttributeName3' => { 'S' => 'another' },
156
+ }})
157
+ end.to raise_error(ValidationException, /mismatch/i)
158
+ end
159
+
149
160
  it 'should fail if the attribute value contains empty string' do
150
161
  expect do
151
162
  subject.put_item({ 'TableName' => 'Table1',
@@ -204,9 +215,9 @@ module FakeDynamo
204
215
  [[{}, /set to null/],
205
216
  [{'Exists' => true}, /set to true/],
206
217
  [{'Exists' => false}],
207
- [{'Value' => { 'S' => 'xxx' } }],
208
- [{'Value' => { 'S' => 'xxx' }, 'Exists' => true}],
209
- [{'Value' => { 'S' => 'xxx' }, 'Exists' => false}, /cannot expect/i]].each do |value, message|
218
+ [{'Value' => { 'N' => '15' } }],
219
+ [{'Value' => { 'N' => '15' }, 'Exists' => true}],
220
+ [{'Value' => { 'N' => '15' }, 'Exists' => false}, /cannot expect/i]].each do |value, message|
210
221
 
211
222
  op = lambda {
212
223
  subject.put_item(item.merge({'Expected' => { 'AttributeName3' => value }}))
@@ -221,14 +232,14 @@ module FakeDynamo
221
232
  end
222
233
 
223
234
  it 'should give default response' do
224
- item['Item']['AttributeName3'] = { 'S' => "new" }
235
+ item['Item']['AttributeName3'] = { 'N' => "17" }
225
236
  subject.put_item(item).should include(consumed_capacity)
226
237
  end
227
238
 
228
239
  it 'should send old item' do
229
240
  old_item = Utils.deep_copy(item)
230
241
  new_item = Utils.deep_copy(item)
231
- new_item['Item']['AttributeName3'] = { 'S' => "new" }
242
+ new_item['Item']['AttributeName3'] = { 'N' => "17" }
232
243
  new_item.merge!({'ReturnValues' => 'ALL_OLD'})
233
244
  subject.put_item(new_item)['Attributes'].should == old_item['Item']
234
245
  end
@@ -261,7 +272,7 @@ module FakeDynamo
261
272
  'AttributesToGet' => ['AttributeName3', 'xxx'],
262
273
  'ReturnConsumedCapacity' => 'TOTAL'
263
274
  })
264
- response.should eq({ 'Item' => { 'AttributeName3' => { 'S' => 'another'}}}
275
+ response.should eq({ 'Item' => { 'AttributeName3' => { 'N' => '14'}}}
265
276
  .merge(consumed_capacity))
266
277
  end
267
278
  end
@@ -293,13 +304,13 @@ module FakeDynamo
293
304
 
294
305
  response = subject.delete_item(key.merge({'Expected' =>
295
306
  {'AttributeName3' =>
296
- {'Value' => { 'S' => 'another'}}}}))
307
+ {'Value' => { 'N' => '14'}}}}))
297
308
  response.should eq(consumed_capacity)
298
309
 
299
310
  expect do
300
311
  subject.delete_item(key.merge({'Expected' =>
301
312
  {'AttributeName3' =>
302
- {'Value' => { 'S' => 'another'}}}}))
313
+ {'Value' => { 'N' => '14'}}}}))
303
314
  end.to raise_error(ConditionalCheckFailedException)
304
315
  end
305
316
 
@@ -317,7 +328,7 @@ module FakeDynamo
317
328
  end
318
329
 
319
330
  let(:put) do
320
- {'AttributeUpdates' => {'AttributeName3' => { 'Value' => { 'S' => 'updated' },
331
+ {'AttributeUpdates' => {'AttributeName3' => { 'Value' => { 'N' => '18' },
321
332
  'Action' => 'PUT'}}}
322
333
  end
323
334
 
@@ -348,13 +359,20 @@ module FakeDynamo
348
359
  end.to raise_error(ConditionalCheckFailedException)
349
360
  end
350
361
 
362
+ it "should check index types" do
363
+ expect do
364
+ put['AttributeUpdates']['AttributeName3']['Value'] = {'S' => 'another'}
365
+ subject.update_item(key.merge(put))
366
+ end.to raise_error(ValidationException, /mismatch/i)
367
+ end
368
+
351
369
  it "should create new item if the key doesn't exist" do
352
370
  key['Key']['AttributeName1']['S'] = 'new'
353
371
  subject.update_item(key.merge(put))
354
372
  subject.get_item(key).should include( "Item"=>
355
373
  {"AttributeName1"=>{"S"=>"new"},
356
374
  "AttributeName2"=>{"N"=>"11"},
357
- "AttributeName3"=>{"S"=>"updated"}})
375
+ "AttributeName3"=>{"N"=>"18"}})
358
376
  end
359
377
 
360
378
  it "shouldn't create a new item if key doesn't exist and action is delete" do
@@ -365,13 +383,13 @@ module FakeDynamo
365
383
 
366
384
  it "should handle return values" do
367
385
  data = key.merge(put).merge({'ReturnValues' => 'UPDATED_NEW'})
368
- subject.update_item(data).should include({'Attributes' => { 'AttributeName3' => { 'S' => 'updated'}}})
386
+ subject.update_item(data).should include({'Attributes' => { 'AttributeName3' => { 'N' => '18'}}})
369
387
  end
370
388
  end
371
389
 
372
390
  context '#return_values' do
373
391
  let(:put) do
374
- {'AttributeUpdates' => {'AttributeName3' => { 'Value' => { 'S' => 'updated' },
392
+ {'AttributeUpdates' => {'AttributeName3' => { 'Value' => { 'N' => '19' },
375
393
  'Action' => 'PUT'}}}
376
394
  end
377
395
 
@@ -388,13 +406,13 @@ module FakeDynamo
388
406
  it "should return update old value" do
389
407
  subject.put_item(item)
390
408
  data = key.merge(put).merge({'ReturnValues' => 'UPDATED_OLD'})
391
- subject.update_item(data).should include({'Attributes' => { 'AttributeName3' => { 'S' => 'another'}}})
409
+ subject.update_item(data).should include({'Attributes' => { 'AttributeName3' => { 'N' => '14'}}})
392
410
  end
393
411
 
394
412
  it "should return update new value" do
395
413
  subject.put_item(item)
396
414
  data = key.merge(put).merge({'ReturnValues' => 'UPDATED_NEW'})
397
- subject.update_item(data).should include({'Attributes' => { 'AttributeName3' => { 'S' => 'updated'}}})
415
+ subject.update_item(data).should include({'Attributes' => { 'AttributeName3' => { 'N' => '19'}}})
398
416
  end
399
417
  end
400
418
 
@@ -636,6 +654,12 @@ module FakeDynamo
636
654
  result['Items'].first.should eq('AttributeName1' => { 'S' => 'att1'},
637
655
  'AttributeName2' => { 'N' => '3' })
638
656
  end
657
+
658
+ it 'should handle attributes_to_get within index' do
659
+ index_query['AttributesToGet'] = ['AttributeName1']
660
+ result = subject.query(index_query)
661
+ result['Items'].first.should eq('AttributeName1' => { 'S' => 'att1'})
662
+ end
639
663
  end
640
664
 
641
665
  context '#scan' do
@@ -17,11 +17,10 @@ end
17
17
  module FakeDynamo
18
18
  class Storage
19
19
  def initialize
20
+ init_db('/tmp/test_db.fdb')
20
21
  delete_db
21
- init_db
22
22
  end
23
23
  end
24
24
  end
25
25
 
26
- FakeDynamo::Storage.db_path = '/tmp/test_db.fdb'
27
26
  FakeDynamo::Logger.setup(:debug)
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: fake_dynamo
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.4
4
+ version: 0.2.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Anantha Kumaran
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2013-07-17 00:00:00.000000000 Z
11
+ date: 2013-09-21 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: sinatra