fake_dynamo 0.2.4 → 0.2.5

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.
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