occi-core 4.1.3 → 4.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (125) hide show
  1. data/.gitignore +1 -0
  2. data/Gemfile +8 -0
  3. data/README.md +49 -17
  4. data/lib/occi/collection.rb +37 -21
  5. data/lib/occi/core/action.rb +5 -5
  6. data/lib/occi/core/action_instance.rb +45 -3
  7. data/lib/occi/core/actions.rb +2 -1
  8. data/lib/occi/core/attributes.rb +253 -73
  9. data/lib/occi/core/categories.rb +1 -0
  10. data/lib/occi/core/category.rb +25 -8
  11. data/lib/occi/core/entities.rb +1 -0
  12. data/lib/occi/core/entity.rb +51 -74
  13. data/lib/occi/core/kind.rb +15 -11
  14. data/lib/occi/core/kinds.rb +1 -1
  15. data/lib/occi/core/link.rb +14 -15
  16. data/lib/occi/core/links.rb +1 -1
  17. data/lib/occi/core/mixin.rb +5 -5
  18. data/lib/occi/core/mixins.rb +2 -2
  19. data/lib/occi/core/properties.rb +90 -12
  20. data/lib/occi/core/resource.rb +7 -3
  21. data/lib/occi/core/resources.rb +2 -2
  22. data/lib/occi/errors/attribute_definitions_converted_error.rb +5 -0
  23. data/lib/occi/errors/attribute_missing_error.rb +5 -0
  24. data/lib/occi/errors/attribute_name_invalid_error.rb +5 -0
  25. data/lib/occi/errors/attribute_not_defined_error.rb +5 -0
  26. data/lib/occi/errors/attribute_property_type_error.rb +5 -0
  27. data/lib/occi/errors/attribute_type_error.rb +5 -0
  28. data/lib/occi/errors/kind_not_defined_error.rb +5 -0
  29. data/lib/occi/errors/parser_input_error.rb +5 -0
  30. data/lib/occi/errors/parser_type_error.rb +5 -0
  31. data/lib/occi/errors.rb +1 -0
  32. data/lib/occi/extensions/hashie.rb +25 -0
  33. data/lib/occi/helpers/comparators/action_instance.rb +22 -0
  34. data/lib/occi/helpers/comparators/attributes.rb +22 -0
  35. data/lib/occi/helpers/comparators/categories.rb +22 -0
  36. data/lib/occi/helpers/comparators/category.rb +22 -0
  37. data/lib/occi/helpers/comparators/collection.rb +40 -0
  38. data/lib/occi/helpers/comparators/entities.rb +22 -0
  39. data/lib/occi/helpers/comparators/entity.rb +22 -0
  40. data/lib/occi/helpers/comparators/properties.rb +26 -0
  41. data/lib/occi/helpers/comparators.rb +1 -0
  42. data/lib/occi/infrastructure/compute.rb +11 -9
  43. data/lib/occi/infrastructure/network.rb +27 -27
  44. data/lib/occi/infrastructure/networkinterface.rb +22 -23
  45. data/lib/occi/infrastructure/os_tpl.rb +1 -1
  46. data/lib/occi/infrastructure/resource_tpl.rb +1 -1
  47. data/lib/occi/infrastructure/storage.rb +7 -6
  48. data/lib/occi/infrastructure/storagelink.rb +4 -4
  49. data/lib/occi/log.rb +13 -10
  50. data/lib/occi/model.rb +9 -8
  51. data/lib/occi/parser/json.rb +11 -9
  52. data/lib/occi/parser/ova.rb +12 -6
  53. data/lib/occi/parser/ovf.rb +173 -116
  54. data/lib/occi/parser/text/constants.rb +87 -0
  55. data/lib/occi/parser/text.rb +161 -200
  56. data/lib/occi/parser/xml.rb +10 -8
  57. data/lib/occi/parser.rb +100 -50
  58. data/lib/occi/settings.rb +2 -1
  59. data/lib/occi/version.rb +1 -1
  60. data/lib/occi-core.rb +6 -4
  61. data/occi-core.gemspec +0 -7
  62. data/spec/occi/collection_samples/collection1.json +1 -0
  63. data/spec/occi/collection_samples/directory2/collection2.json +1 -0
  64. data/spec/occi/collection_spec.rb +961 -31
  65. data/spec/occi/core/action_instance_spec.rb +317 -0
  66. data/spec/occi/core/action_spec.rb +71 -0
  67. data/spec/occi/core/attributes_spec.rb +582 -27
  68. data/spec/occi/core/category_spec.rb +194 -18
  69. data/spec/occi/core/entities_spec.rb +96 -0
  70. data/spec/occi/core/entity_spec.rb +317 -28
  71. data/spec/occi/core/kind_spec.rb +127 -16
  72. data/spec/occi/core/link_spec.rb +35 -0
  73. data/spec/occi/core/links_spec.rb +130 -0
  74. data/spec/occi/core/mixins_spec.rb +107 -0
  75. data/spec/occi/core/properties_spec.rb +167 -0
  76. data/spec/occi/core/resource_spec.rb +23 -9
  77. data/spec/occi/core_spec.rb +12 -0
  78. data/spec/occi/infrastructure/compute_spec.rb +218 -18
  79. data/spec/occi/infrastructure/network_spec.rb +96 -0
  80. data/spec/occi/infrastructure/networkinterface_spec.rb +96 -0
  81. data/spec/occi/infrastructure/storage_spec.rb +33 -0
  82. data/spec/occi/infrastructure/storagelink_spec.rb +45 -0
  83. data/spec/occi/log_spec.rb +104 -1
  84. data/spec/occi/model_spec.rb +251 -39
  85. data/spec/occi/{test.json → parser/json_samples/test.json} +0 -0
  86. data/spec/occi/parser/ova_samples/test.dump +0 -0
  87. data/spec/occi/{test.ova → parser/ova_samples/test.ova} +0 -0
  88. data/spec/occi/parser/ovf_samples/test.dump +0 -0
  89. data/spec/occi/{test.ovf → parser/ovf_samples/test.ovf} +0 -0
  90. data/spec/occi/parser/text_samples/occi_categories.dump +0 -0
  91. data/spec/occi/parser/text_samples/occi_categories.text +2 -0
  92. data/spec/occi/parser/text_samples/occi_compute_rocci_server.dump +0 -0
  93. data/spec/occi/parser/text_samples/occi_compute_rocci_server.resource.dump +0 -0
  94. data/spec/occi/parser/text_samples/occi_compute_rocci_server.text +10 -0
  95. data/spec/occi/parser/text_samples/occi_link_resource_instance.dump +0 -0
  96. data/spec/occi/parser/text_samples/occi_link_resource_instance.text +7 -0
  97. data/spec/occi/parser/text_samples/occi_link_simple.dump +0 -0
  98. data/spec/occi/parser/text_samples/occi_link_simple.link_string.dump +0 -0
  99. data/spec/occi/parser/text_samples/occi_link_simple.text +1 -0
  100. data/spec/occi/parser/text_samples/occi_link_w_attributes.dump +0 -0
  101. data/spec/occi/parser/text_samples/occi_link_w_attributes.text +7 -0
  102. data/spec/occi/parser/text_samples/occi_link_w_category.dump +0 -0
  103. data/spec/occi/parser/text_samples/occi_link_w_category.text +3 -0
  104. data/spec/occi/parser/text_samples/occi_model_rocci_server.dump +0 -0
  105. data/spec/occi/parser/text_samples/occi_model_rocci_server.text +51 -0
  106. data/spec/occi/parser/text_samples/occi_network_rocci_server.dump +0 -0
  107. data/spec/occi/parser/text_samples/occi_network_rocci_server.resource.dump +0 -0
  108. data/spec/occi/parser/text_samples/occi_network_rocci_server.text +11 -0
  109. data/spec/occi/parser/text_samples/occi_resource_w_attributes.dump +0 -0
  110. data/spec/occi/parser/text_samples/occi_resource_w_attributes.text +11 -0
  111. data/spec/occi/parser/text_samples/occi_resource_w_inline_links.dump +0 -0
  112. data/spec/occi/parser/text_samples/occi_resource_w_inline_links.text +16 -0
  113. data/spec/occi/parser/text_samples/occi_resource_w_inline_links_only.dump +0 -0
  114. data/spec/occi/parser/text_samples/occi_resource_w_inline_links_only.text +13 -0
  115. data/spec/occi/parser/text_samples/occi_storage_rocci_server.dump +0 -0
  116. data/spec/occi/parser/text_samples/occi_storage_rocci_server.resource.dump +0 -0
  117. data/spec/occi/parser/text_samples/occi_storage_rocci_server.text +9 -0
  118. data/spec/occi/parser/text_spec.rb +274 -78
  119. data/spec/occi/parser/xml_samples/test.xml +352 -0
  120. data/spec/occi/parser_spec.rb +255 -104
  121. data/spec/occi-core_spec.rb +31 -0
  122. data/spec/spec_helper.rb +6 -2
  123. metadata +110 -111
  124. checksums.yaml +0 -7
  125. data/spec/occi/core/attribute_spec.rb +0 -0
@@ -2,41 +2,596 @@ module Occi
2
2
  module Core
3
3
  describe Attributes do
4
4
 
5
- it 'stores properties using hashes in hash notation' do
6
- attributes=Occi::Core::Attributes.new
7
- attributes['test']={}
8
- attributes['test'].should be_kind_of Occi::Core::Properties
5
+ context '#[]=' do
6
+ let(:attributes){ Occi::Core::Attributes.new }
7
+ it 'stores properties using hashes in hash notation' do
8
+ attributes['test']={}
9
+ expect(attributes['test']).to be_kind_of Occi::Core::Properties
10
+ end
11
+
12
+ it 'stores properties using hashes in dot notation' do
13
+ attributes.test={}
14
+ expect(attributes.test).to be_kind_of Occi::Core::Properties
15
+ end
16
+
17
+ it 'rejects keys starting with underscores' do
18
+ expect{ attributes['_test']={} }.to raise_error(Occi::Errors::AttributeNameInvalidError)
19
+ end
20
+
21
+ it 'accepts keys with underscores in other positions' do
22
+ expect{ attributes['t_est']={} }.to_not raise_error(Occi::Errors::AttributeNameInvalidError)
23
+ end
24
+ end
25
+
26
+ context '#remove' do
27
+ it 'removes attributes' do
28
+ attributes=Occi::Core::Attributes.new
29
+ attributes['one.two']={}
30
+ attributes['one.three']={}
31
+
32
+ attr=Occi::Core::Attributes.new
33
+ attr['one.two']={}
34
+ attributes.remove attr
35
+
36
+ expect(attributes['one.two']).to be_nil
37
+ expect(attributes['one.three']).to be_kind_of Occi::Core::Properties
38
+ end
39
+ end
40
+
41
+ context '#convert' do
42
+ it 'converts properties to an empty attribute' do
43
+ attributes=Occi::Core::Attributes.new
44
+ attributes.test={}
45
+
46
+ attr = attributes.convert
47
+ expect(attributes.test).to be_kind_of Occi::Core::Properties
48
+
49
+ expect(attr.test).to be_nil
50
+ expect(attr._test).to be_kind_of Occi::Core::Properties
51
+
52
+ attributes.convert!
53
+ expect(attributes.test).to be_nil
54
+ expect(attributes._test).to be_kind_of Occi::Core::Properties
55
+ end
56
+ end
57
+
58
+ context 'comparators' do
59
+ let(:attrs){
60
+ attrs = Occi::Core::Attributes.new
61
+ attrs['numbertype'] = { :type => 'number', :default => 42, :mutable => true, :pattern => '^[0-9]+' }
62
+ attrs['stringtype'] = { :type => 'string', :pattern => '[adefltuv]+', :default => 'defaultvalue', :mutable => true }
63
+ attrs['booleantype'] = { :type => 'boolean', :default => true, :mutable => true}
64
+ attrs['booleantypefalse'] = { :type => 'boolean', :default => false, :mutable => true }
65
+ attrs['booleantypepattern'] = { :type => 'boolean', :default => true, :mutable => true, :pattern => true }
66
+ attrs }
67
+ let(:clone){ clone = attrs.clone }
68
+ let(:newattrs){
69
+ newattrs = Occi::Core::Attributes.new
70
+ newattrs['numbertype'] = { :type => 'number', :default => 42, :mutable => true, :pattern => '^[0-9]+' }
71
+ newattrs['stringtype'] = { :type => 'string', :pattern => '[adefltuv]+', :default => 'defaultvalue', :mutable => true }
72
+ newattrs['booleantype'] = { :type => 'boolean', :default => true, :mutable => true}
73
+ newattrs['booleantypefalse'] = { :type => 'boolean', :default => false, :mutable => true }
74
+ newattrs['booleantypepattern'] = { :type => 'boolean', :default => true, :mutable => true, :pattern => true }
75
+ newattrs }
76
+ let(:diffattrs){
77
+ diffattrs = Occi::Core::Attributes.new
78
+ diffattrs['numbertype'] = { :type => 'number', :default => 42, :mutable => true, :pattern => '^[0-9]+' }
79
+ diffattrs['stringtype'] = { :type => 'string', :pattern => '[adefltuv]+', :default => 'anothervalue', :mutable => true } # <=
80
+ diffattrs['booleantype'] = { :type => 'boolean', :default => true, :mutable => true}
81
+ diffattrs['booleantypefalse'] = { :type => 'boolean', :default => false, :mutable => true }
82
+ diffattrs['booleantypepattern'] = { :type => 'boolean', :default => true, :mutable => true, :pattern => true }
83
+ diffattrs }
84
+
85
+ context '#==' do
86
+ it 'matches the same instance' do
87
+ expect(attrs==attrs).to eql true
88
+ end
89
+
90
+ it 'matches a clone' do
91
+ expect(attrs==clone).to eql true
92
+ end
93
+
94
+ it 'matches a new instance with the same content' do
95
+ expect(attrs==newattrs).to eql true
96
+ end
97
+
98
+ it 'does not match nil' do
99
+ expect(attrs==nil).to eql false
100
+ end
101
+
102
+ it 'does not match an instance with different content' do
103
+ expect(attrs==diffattrs).to eql false
104
+ end
105
+ end
106
+
107
+ context '#eql?' do
108
+ it 'matches the same instance' do
109
+ expect(attrs.eql?(attrs)).to eql true
110
+ end
111
+
112
+ it 'matches a clone' do
113
+ expect(attrs.eql?(clone)).to eql true
114
+ end
115
+
116
+ it 'matches a new instance with the same content' do
117
+ expect(attrs.eql?(newattrs)).to eql true
118
+ end
119
+
120
+ it 'does not match nil' do
121
+ expect(attrs.eql?(nil)).to eql false
122
+ end
123
+
124
+ it 'does not match an instance with different content' do
125
+ expect(attrs.eql?(diffattrs)).to eql false
126
+ end
127
+ end
128
+
129
+ context '#equal?' do
130
+ it 'matches the same instance' do
131
+ expect(attrs.equal?(attrs)).to eql true
132
+ end
133
+
134
+ it 'does not match a clone' do
135
+ expect(attrs.equal?(clone)).to eql false
136
+ end
137
+ end
138
+
139
+ context '#hash' do
140
+ it 'matches for the same instance' do
141
+ expect(attrs.hash).to eql attrs.hash
142
+ end
143
+
144
+ it 'matches for a clone' do
145
+ expect(attrs.hash).to eql clone.hash
146
+ end
147
+
148
+ it 'matches for a new instance with the same content' do
149
+ expect(attrs.hash).to eql newattrs.hash
150
+ end
151
+
152
+ it 'does not match for an instance with different content' do
153
+ expect(attrs.hash).to_not eql diffattrs.hash
154
+ end
155
+ end
9
156
  end
10
157
 
11
- it 'stores properties using hashes in dot notation' do
12
- attributes=Occi::Core::Attributes.new
13
- attributes.test={}
14
- attributes.test.should be_kind_of Occi::Core::Properties
158
+ context '#converted?' do
159
+ let(:attrs){ attrs = Occi::Core::Attributes.new
160
+ attrs['numbertype'] = { :type => 'number', :default => 42, :mutable => true, :pattern => '^[0-9]+' }
161
+ attrs }
162
+
163
+ it 'correctly reports uncoverted' do
164
+ expect(attrs.converted?).to eql false
165
+ end
166
+
167
+ it 'correctly reports coverted' do
168
+ expect(attrs.convert.converted?).to eql true
169
+ end
15
170
  end
16
171
 
17
- it 'removes attributes' do
18
- attributes=Occi::Core::Attributes.new
19
- attributes['one.two']={}
20
- attributes['one.three']={}
21
- attr=Occi::Core::Attributes.new
22
- attr['one.two']={}
23
- attributes.remove attr
24
- attributes['one.two'].should be_nil
25
- attributes['one.three'].should be_kind_of Occi::Core::Properties
172
+
173
+ context 'rendering' do
174
+ let(:attrs){ attrs = Occi::Core::Attributes.new
175
+ attrs['numbertype'] = { :type => 'number', :default => 42, :mutable => true, :pattern => '^[0-9]+' }
176
+ attrs['stringtype'] = { :type => 'string', :pattern => '[adefltuv]+', :default => 'defaultvalue', :mutable => true }
177
+ attrs['booleantype'] = { :type => 'boolean', :default => true, :mutable => true}
178
+ attrs['booleantypefalse'] = { :type => 'boolean', :default => false, :mutable => true }
179
+ attrs['booleantypepattern'] = { :type => 'boolean', :default => true, :mutable => true, :pattern => true }
180
+ attrs.nest!.nested = { :type => 'number', :default => 42, :mutable => true, :pattern => '^[0-9]+' }
181
+ attrs['properties'] = Occi::Core::Properties.new
182
+ attrs.convert
183
+ attrs['numbertype'] = 42
184
+ attrs['stringtype'] = 'flute'
185
+ attrs['booleantype'] = true
186
+ attrs['booleantypefalse'] = false
187
+ attrs['booleantypepattern'] = true
188
+ attrs.nest!.nested = 11
189
+ attrs['category'] = Occi::Core::Category.new
190
+ attrs['properties'] = "prop"
191
+ attrs['entity'] = Occi::Core::Entity.new
192
+ attrs['entity'].id = "testid"
193
+ attrs }
194
+ let(:empty){ Occi::Core::Attributes.new.convert }
195
+
196
+ context '.parse_properties' do
197
+
198
+ it 'rejects unsuitable types' do
199
+ string = String.new("Teststring")
200
+ expect{ Occi::Core::Attributes.parse_properties(string) }.to raise_error(Occi::Errors::ParserInputError)
201
+ end
202
+
203
+ it 'parses a hashie Mash' do
204
+ hash = { :nr => {} }
205
+ hash[:nr][:type] = 'number'
206
+ hash[:nr][:default] = 42
207
+ hash[:nr][:mutable] = true
208
+
209
+ expected = Occi::Core::Attributes.new
210
+ expected['nr'] = { :type => 'number', :default => 42, :mutable => true }
211
+ expected.convert
212
+
213
+ attrs = Occi::Core::Attributes.parse_properties(hash)
214
+ attrs.convert
215
+
216
+ expect(attrs).to eql expected
217
+ end
218
+ end
219
+
220
+ context '#to_string' do
221
+ it 'renders attributes correctly' do
222
+ expected = ";numbertype=42;stringtype=\"flute\";booleantype=true;booleantypefalse=false;booleantypepattern=true;nest.nested=11;properties=\"prop\";category=\"http://schemas.ogf.org/occi/core#category\";entity=\"/entity/testid\""
223
+ expect(attrs.to_string).to eql expected
224
+ end
225
+
226
+ it 'copes with empty attributes' do
227
+ expected = ""
228
+ expect(empty.to_string).to eql expected
229
+ end
230
+ end
231
+
232
+ context '#to_string_short' do
233
+ it 'renders attributes correctly' do
234
+ expected = ";attributes=\"numbertype stringtype booleantype booleantypefalse booleantypepattern nest.nested properties category entity\""
235
+ expect(attrs.to_string_short).to eql expected
236
+ end
237
+
238
+ it 'copes with empty attributes' do
239
+ expected = ""
240
+ expect(empty.to_string_short).to eql expected
241
+ end
242
+ end
243
+
244
+ context '#to_text' do
245
+ it 'renders attributes correctly' do
246
+ expected = "\nX-OCCI-Attribute: numbertype=42\nX-OCCI-Attribute: stringtype=\"flute\"\nX-OCCI-Attribute: booleantype=true\nX-OCCI-Attribute: booleantypefalse=false\nX-OCCI-Attribute: booleantypepattern=true\nX-OCCI-Attribute: nest.nested=11\nX-OCCI-Attribute: properties=\"prop\"\nX-OCCI-Attribute: category=\"http://schemas.ogf.org/occi/core#category\"\nX-OCCI-Attribute: entity=\"/entity/testid\""
247
+ expect(attrs.to_text).to eql expected
248
+ end
249
+
250
+ it 'copes with empty attributes' do
251
+ expected = ""
252
+ expect(empty.to_text).to eql expected
253
+ end
254
+ end
255
+
256
+ context '#to_header' do
257
+ it 'renders attributes correctly' do
258
+ expected = "numbertype=42,stringtype=\"flute\",booleantype=true,booleantypefalse=false,booleantypepattern=true,nest.nested=11,properties=\"prop\",category=\"http://schemas.ogf.org/occi/core#category\",entity=\"/entity/testid\""
259
+ expect(attrs.to_header).to eql expected
260
+ end
261
+
262
+ it 'copes with empty attributes' do
263
+ expected = ""
264
+ expect(empty.to_header).to eql expected
265
+ end
266
+ end
267
+
268
+ context '#to_json' do
269
+ it 'renders attributes correctly' do
270
+ expected = '{"numbertype":42,"stringtype":"flute","booleantype":true,"booleantypefalse":false,"booleantypepattern":true,"nest":{"nested":11},"properties":"prop","category":"http://schemas.ogf.org/occi/core#category","entity":"/entity/testid"}'
271
+ expect(attrs.to_json).to eql expected
272
+ end
273
+
274
+ it 'copes with empty attributes' do
275
+ expected = "{}"
276
+ expect(empty.to_json).to eql expected
277
+ end
278
+ end
279
+
280
+ context '#as_json' do
281
+ it 'renders attributes correctly' do
282
+ expected = Hashie::Mash.new
283
+ expected["booleantype"] = true
284
+ expected["booleantypepattern"] = true
285
+ expected["numbertype"] = 42
286
+ expected["stringtype"] = "flute"
287
+ expected["booleantypefalse"] = false
288
+ expected.nest!.nested = 11
289
+ expected["category"] = "http://schemas.ogf.org/occi/core#category"
290
+ expected["properties"] = "prop"
291
+ expected["entity"] = "/entity/testid"
292
+
293
+ expect(attrs.as_json).to eql expected
294
+ end
295
+
296
+ it 'copes with empty attributes' do
297
+ expected = Hashie::Mash.new
298
+ expect(empty.as_json).to eql expected
299
+ end
300
+ end
26
301
  end
27
302
 
28
- it 'converts properties to an empty attribute' do
29
- attributes=Occi::Core::Attributes.new
30
- attributes.test={}
31
- attr = attributes.convert
32
- attributes.test.should be_kind_of Occi::Core::Properties
33
- attr.test.should be_nil
34
- attr._test.should be_kind_of Occi::Core::Properties
35
- attributes.convert!
36
- attributes.test.should be_nil
37
- attributes._test.should be_kind_of Occi::Core::Properties
303
+ context '.check!' do
304
+ let(:attrs){ attrs = Occi::Core::Attributes.new }
305
+
306
+ let(:defs){
307
+ defs = Occi::Core::Attributes.new
308
+ defs['numbertype'] = { :type => 'number',
309
+ :default => 42,
310
+ :mutable => true,
311
+ :pattern => '^[0-9]+' }
312
+ defs['stringtype'] = { :type => 'string',
313
+ :pattern => '[adefltuv]+',
314
+ :default => 'defaultvalue',
315
+ :mutable => true }
316
+ defs['booleantype'] = { :type => 'boolean',
317
+ :default => true,
318
+ :mutable => true}
319
+ defs['booleantypefalse'] = { :type => 'boolean', #Regression test
320
+ :default => false,
321
+ :mutable => true }
322
+ defs['booleantypepattern'] = { :type => 'boolean',
323
+ :default => true,
324
+ :mutable => true,
325
+ :pattern => true }
326
+ defs['nonmandatory'] = { :type => 'string',
327
+ :mutable => true,
328
+ :required => false }
329
+ defs }
330
+
331
+ context 'unsupported types and attributes' do
332
+ before(:each){ Occi::Settings['compatibility']=false
333
+ Occi::Settings['verify_attribute_pattern']=true }
334
+ after(:each) { Occi::Settings.reload! }
335
+ it 'refuses undefined attribute' do
336
+ attrs['otherstring'] = { :type => 'string', :pattern => '[adefltuv]+', :default => 'defaultvalue', :mutable => true }
337
+ expect{attrs.check! defs, true}.to raise_exception(Occi::Errors::AttributeNotDefinedError)
338
+ end
339
+
340
+ it 'refuses unsupported type' do
341
+ expect{ defs['unsupported'] = { :type => 'float', :mutable => true } }.to raise_exception(Occi::Errors::AttributePropertyTypeError)
342
+ end
343
+ end
344
+
345
+ context 'nonmandatory attributes' do
346
+ it 'removes nil attribute' do
347
+ attrs['nonmandatory'] = nil
348
+ attrs.check!(defs, true)
349
+ expect(attrs.key?('nonmandatory')).to eql false
350
+ end
351
+
352
+ it 'raises error for unknown attribute with non-nil value' do
353
+ attrs['undefined'] = "undefined"
354
+ expect{ attrs.check!(defs, true) }.to raise_error(Occi::Errors::AttributeNotDefinedError)
355
+ end
356
+ end
357
+
358
+ context 'mandatory attributes' do
359
+ it 'no value and no default, set_defaults true' do
360
+ defs['nodefault'] = { :type => 'string', :mutable => true, :required => true }
361
+ expect{ attrs.check!(defs, true) }.to raise_error(Occi::Errors::AttributeMissingError)
362
+ end
363
+
364
+ it 'no value and no default, set_defaults false' do
365
+ defs['nodefault'] = { :type => 'string', :mutable => true, :required => true }
366
+ expect{ attrs.check!(defs, false) }.to raise_error(Occi::Errors::AttributeMissingError)
367
+ end
368
+
369
+ it 'nil value and no default, set_defaults true' do
370
+ defs['nodefault'] = { :type => 'string', :mutable => true, :required => true }
371
+ attrs['nodefault'] = nil
372
+ expect{ attrs.check!(defs, true) }.to raise_error(Occi::Errors::AttributeMissingError)
373
+ end
374
+
375
+ it 'nil value and no default, set_defaults false' do
376
+ defs['nodefault'] = { :type => 'string', :mutable => true, :required => true }
377
+ attrs['nodefault'] = nil
378
+ expect{ attrs.check!(defs, false) }.to raise_error(Occi::Errors::AttributeMissingError)
379
+ end
380
+
381
+ end
382
+
383
+ context 'unsupported attributes' do
384
+ before(:each){ Occi::Settings['compatibility']=false
385
+ Occi::Settings['verify_attribute_pattern']=true }
386
+ after(:each) { Occi::Settings.reload! }
387
+ it 'refuses attribute not mentioned in defs' do
388
+ attrs['otherstring'] = { :type => 'string',
389
+ :default => 'defaultvalue' }
390
+ expect{attrs.check! defs, true}.to raise_exception(Occi::Errors::AttributeNotDefinedError)
391
+ end
392
+ end
393
+
394
+ context 'defaults' do
395
+ before(:each){ Occi::Settings['compatibility']=false
396
+ Occi::Settings['verify_attribute_pattern']=true }
397
+ after(:each) { Occi::Settings.reload! }
398
+
399
+ context 'setting defaults' do
400
+ it 'sets numeric default' do
401
+ attrs.check! defs, true
402
+ expect(attrs['numbertype']).to eq 42
403
+ end
404
+ it 'sets string default' do
405
+ attrs.check! defs, true
406
+ expect(attrs['stringtype']).to eq 'defaultvalue'
407
+ end
408
+ it 'sets boolean default if true' do
409
+ attrs.check! defs, true
410
+ expect(attrs['booleantype']).to eq true
411
+ end
412
+ it 'sets boolean default if false' do
413
+ attrs.check! defs, true
414
+ expect(attrs['booleantypefalse']).to eq false
415
+ end
416
+ it 'can be checked twice in a row' do
417
+ attrs.check! defs, true
418
+ expect{ attrs.check! defs, true }.to_not raise_exception
419
+ end
420
+ end
421
+
422
+ context 'skipping defaults if already set' do
423
+ it 'skips numeric default' do
424
+ attrs['numbertype'] = 12
425
+ attrs.check! defs, true
426
+ expect(attrs['numbertype']).to eq 12
427
+ end
428
+ it 'skips string default' do
429
+ attrs['stringtype'] = 'fault'
430
+ attrs.check! defs, true
431
+ expect(attrs['stringtype']).to eq 'fault'
432
+ end
433
+ it 'skips boolean default if true' do
434
+ attrs['booleantype'] = false
435
+ attrs.check! defs, true
436
+ expect(attrs['booleantype']).to eq false
437
+ end
438
+ it 'skips boolean default if false' do
439
+ attrs['booleantypefalse'] = true
440
+ attrs.check! defs, true
441
+ expect(attrs['booleantypefalse']).to eq true
442
+ end
443
+ end
444
+
445
+ context 'skipping defaults if set_defaults is false' do
446
+ it 'skips numeric default' do
447
+ attrs.check! defs, false
448
+ expect(attrs['numbertype']).to_not eq 42
449
+ end
450
+ it 'skips string default' do
451
+ attrs.check! defs, false
452
+ expect(attrs['stringtype']).to_not eq 'defaultvalue'
453
+ end
454
+ it 'skips boolean default if true' do
455
+ attrs.check! defs, false
456
+ expect(attrs['booleantype']).to_not eq true
457
+ end
458
+ it 'skips boolean default if false' do
459
+ attrs.check! defs, false
460
+ expect(attrs['booleantypefalse']).to_not eq false
461
+ end
462
+ end
463
+
464
+ context 'patterns' do
465
+ it 'checks string pattern' do
466
+ attrs['stringtype'] = 'bflmpsvz'
467
+ expect{attrs.check! defs, true}.to raise_exception(Occi::Errors::AttributeTypeError)
468
+ end
469
+ it 'checks numeric pattern' do
470
+ attrs['numbertype'] = -32
471
+ expect{attrs.check! defs, true}.to raise_exception(Occi::Errors::AttributeTypeError)
472
+ end
473
+ it 'checks boolean pattern' do # Possibly an overkill
474
+ attrs['booleantypepattern'] = false
475
+ expect{attrs.check! defs, true}.to raise_exception(Occi::Errors::AttributeTypeError)
476
+ end
477
+ end
478
+ end
479
+
480
+ context 'calling through #check' do
481
+ before(:each){ Occi::Settings['compatibility']=false
482
+ Occi::Settings['verify_attribute_pattern']=true }
483
+ after(:each) { Occi::Settings.reload! }
484
+
485
+ context 'setting defaults' do
486
+ it 'sets numeric default' do
487
+ as = attrs.check defs, true
488
+ expect(as['numbertype']).to eq 42
489
+ end
490
+ it 'sets string default' do
491
+ as = attrs.check defs, true
492
+ expect(as['stringtype']).to eq 'defaultvalue'
493
+ end
494
+ it 'sets boolean default if true' do
495
+ as = attrs.check defs, true
496
+ expect(as['booleantype']).to eq true
497
+ end
498
+ it 'sets boolean default if false' do
499
+ as = attrs.check defs, true
500
+ expect(as['booleantypefalse']).to eq false
501
+ end
502
+ end
503
+ end
504
+
505
+ context 'converted definitions' do
506
+ it 'succeeds for unconverted definitions' do
507
+ expect{attrs.check! defs, true}.to_not raise_exception
508
+ end
509
+
510
+ it 'throws exception for converted definitions' do
511
+ defs.convert!
512
+ expect{attrs.check! defs, true}.to raise_exception(Occi::Errors::AttributeDefinitionsConvrertedError)
513
+ end
514
+ end
38
515
  end
39
516
 
517
+
518
+ context '.validate_and_assign' do
519
+ let(:attrs){ Occi::Core::Attributes.new }
520
+
521
+ it 'correctly accepts Occi::Core::Attributes' do
522
+ inattrs = Occi::Core::Attributes.new
523
+ inattrs['numbertype'] = { :type => 'number', :default => 42, :mutable => true, :pattern => '^[0-9]+' }
524
+ inattrs.convert
525
+ inattrs['numbertype'] = 13
526
+
527
+ attrs['numbertype'] = inattrs['numbertype']
528
+ expect(attrs).to eql inattrs
529
+ end
530
+
531
+ it 'correctly accepts Occi::Core::Properties' do
532
+ attrs['properties'] = Occi::Core::Properties.new
533
+
534
+ expected = Occi::Core::Attributes.new
535
+ expected['properties'] = { :type => 'string', :pattern => '.*', :mutable => false, :required => false }
536
+ expected.convert
537
+
538
+ expect(attrs).to eql expected
539
+ end
540
+
541
+ it 'correctly accepts Hash' do
542
+ attrs['hash'] = { :type => 'string', :pattern => '.*', :mutable => false, :required => false }
543
+
544
+ expected = Occi::Core::Attributes.new
545
+ expected['hash'] = { :type => 'string', :pattern => '.*', :mutable => false, :required => false }
546
+ expected.convert
547
+
548
+ expect(attrs).to eql expected
549
+ end
550
+
551
+ it 'correctly accepts Occi::Core::Entity' do
552
+ entity = Occi::Core::Entity.new
553
+ attrs['entity'] = entity
554
+
555
+ expect(attrs['entity']).to eql entity
556
+ end
557
+
558
+ it 'correctly accepts Occi::Core::Category' do
559
+ category = Occi::Core::Category.new
560
+ attrs['category'] = category
561
+
562
+ expect(attrs['category']).to eql category
563
+ end
564
+
565
+ it 'correctly accepts String' do
566
+ attrs['string'] = "teststring"
567
+ expect(attrs['string']).to eql "teststring"
568
+ end
569
+
570
+ it 'correctly accepts Numeric' do
571
+ attrs['numeric'] = 16
572
+ expect(attrs['numeric']).to eql 16
573
+ end
574
+
575
+ it 'correctly accepts TrueClass' do
576
+ attrs['tr'] = true
577
+ expect(attrs['tr']).to eql true
578
+ end
579
+
580
+ it 'correctly accepts FalseClass' do
581
+ attrs['fal'] = false
582
+ expect(attrs['fal']).to eql false
583
+ end
584
+
585
+ it 'correctly responds to NilClass' do
586
+ attrs['nil'] = nil
587
+ expect(attrs['nil']).to eql nil
588
+ end
589
+
590
+ it 'rejects unsupported types' do
591
+ type = Occi::Log.new(nil)
592
+ expect{ attrs['log'] = type }.to raise_error(Occi::Errors::AttributeTypeError)
593
+ end
594
+ end
40
595
  end
41
596
  end
42
597
  end