occi-core 4.1.3 → 4.2.0

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