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.
- data/.gitignore +1 -0
- data/Gemfile +8 -0
- data/README.md +49 -17
- data/lib/occi/collection.rb +37 -21
- data/lib/occi/core/action.rb +5 -5
- data/lib/occi/core/action_instance.rb +45 -3
- data/lib/occi/core/actions.rb +2 -1
- data/lib/occi/core/attributes.rb +253 -73
- data/lib/occi/core/categories.rb +1 -0
- data/lib/occi/core/category.rb +25 -8
- data/lib/occi/core/entities.rb +1 -0
- data/lib/occi/core/entity.rb +51 -74
- data/lib/occi/core/kind.rb +15 -11
- data/lib/occi/core/kinds.rb +1 -1
- data/lib/occi/core/link.rb +14 -15
- data/lib/occi/core/links.rb +1 -1
- data/lib/occi/core/mixin.rb +5 -5
- data/lib/occi/core/mixins.rb +2 -2
- data/lib/occi/core/properties.rb +90 -12
- data/lib/occi/core/resource.rb +7 -3
- data/lib/occi/core/resources.rb +2 -2
- data/lib/occi/errors/attribute_definitions_converted_error.rb +5 -0
- data/lib/occi/errors/attribute_missing_error.rb +5 -0
- data/lib/occi/errors/attribute_name_invalid_error.rb +5 -0
- data/lib/occi/errors/attribute_not_defined_error.rb +5 -0
- data/lib/occi/errors/attribute_property_type_error.rb +5 -0
- data/lib/occi/errors/attribute_type_error.rb +5 -0
- data/lib/occi/errors/kind_not_defined_error.rb +5 -0
- data/lib/occi/errors/parser_input_error.rb +5 -0
- data/lib/occi/errors/parser_type_error.rb +5 -0
- data/lib/occi/errors.rb +1 -0
- data/lib/occi/extensions/hashie.rb +25 -0
- data/lib/occi/helpers/comparators/action_instance.rb +22 -0
- data/lib/occi/helpers/comparators/attributes.rb +22 -0
- data/lib/occi/helpers/comparators/categories.rb +22 -0
- data/lib/occi/helpers/comparators/category.rb +22 -0
- data/lib/occi/helpers/comparators/collection.rb +40 -0
- data/lib/occi/helpers/comparators/entities.rb +22 -0
- data/lib/occi/helpers/comparators/entity.rb +22 -0
- data/lib/occi/helpers/comparators/properties.rb +26 -0
- data/lib/occi/helpers/comparators.rb +1 -0
- data/lib/occi/infrastructure/compute.rb +11 -9
- data/lib/occi/infrastructure/network.rb +27 -27
- data/lib/occi/infrastructure/networkinterface.rb +22 -23
- data/lib/occi/infrastructure/os_tpl.rb +1 -1
- data/lib/occi/infrastructure/resource_tpl.rb +1 -1
- data/lib/occi/infrastructure/storage.rb +7 -6
- data/lib/occi/infrastructure/storagelink.rb +4 -4
- data/lib/occi/log.rb +13 -10
- data/lib/occi/model.rb +9 -8
- data/lib/occi/parser/json.rb +11 -9
- data/lib/occi/parser/ova.rb +12 -6
- data/lib/occi/parser/ovf.rb +173 -116
- data/lib/occi/parser/text/constants.rb +87 -0
- data/lib/occi/parser/text.rb +161 -200
- data/lib/occi/parser/xml.rb +10 -8
- data/lib/occi/parser.rb +100 -50
- data/lib/occi/settings.rb +2 -1
- data/lib/occi/version.rb +1 -1
- data/lib/occi-core.rb +6 -4
- data/occi-core.gemspec +0 -7
- data/spec/occi/collection_samples/collection1.json +1 -0
- data/spec/occi/collection_samples/directory2/collection2.json +1 -0
- data/spec/occi/collection_spec.rb +961 -31
- data/spec/occi/core/action_instance_spec.rb +317 -0
- data/spec/occi/core/action_spec.rb +71 -0
- data/spec/occi/core/attributes_spec.rb +582 -27
- data/spec/occi/core/category_spec.rb +194 -18
- data/spec/occi/core/entities_spec.rb +96 -0
- data/spec/occi/core/entity_spec.rb +317 -28
- data/spec/occi/core/kind_spec.rb +127 -16
- data/spec/occi/core/link_spec.rb +35 -0
- data/spec/occi/core/links_spec.rb +130 -0
- data/spec/occi/core/mixins_spec.rb +107 -0
- data/spec/occi/core/properties_spec.rb +167 -0
- data/spec/occi/core/resource_spec.rb +23 -9
- data/spec/occi/core_spec.rb +12 -0
- data/spec/occi/infrastructure/compute_spec.rb +218 -18
- data/spec/occi/infrastructure/network_spec.rb +96 -0
- data/spec/occi/infrastructure/networkinterface_spec.rb +96 -0
- data/spec/occi/infrastructure/storage_spec.rb +33 -0
- data/spec/occi/infrastructure/storagelink_spec.rb +45 -0
- data/spec/occi/log_spec.rb +104 -1
- data/spec/occi/model_spec.rb +251 -39
- data/spec/occi/{test.json → parser/json_samples/test.json} +0 -0
- data/spec/occi/parser/ova_samples/test.dump +0 -0
- data/spec/occi/{test.ova → parser/ova_samples/test.ova} +0 -0
- data/spec/occi/parser/ovf_samples/test.dump +0 -0
- data/spec/occi/{test.ovf → parser/ovf_samples/test.ovf} +0 -0
- data/spec/occi/parser/text_samples/occi_categories.dump +0 -0
- data/spec/occi/parser/text_samples/occi_categories.text +2 -0
- data/spec/occi/parser/text_samples/occi_compute_rocci_server.dump +0 -0
- data/spec/occi/parser/text_samples/occi_compute_rocci_server.resource.dump +0 -0
- data/spec/occi/parser/text_samples/occi_compute_rocci_server.text +10 -0
- data/spec/occi/parser/text_samples/occi_link_resource_instance.dump +0 -0
- data/spec/occi/parser/text_samples/occi_link_resource_instance.text +7 -0
- data/spec/occi/parser/text_samples/occi_link_simple.dump +0 -0
- data/spec/occi/parser/text_samples/occi_link_simple.link_string.dump +0 -0
- data/spec/occi/parser/text_samples/occi_link_simple.text +1 -0
- data/spec/occi/parser/text_samples/occi_link_w_attributes.dump +0 -0
- data/spec/occi/parser/text_samples/occi_link_w_attributes.text +7 -0
- data/spec/occi/parser/text_samples/occi_link_w_category.dump +0 -0
- data/spec/occi/parser/text_samples/occi_link_w_category.text +3 -0
- data/spec/occi/parser/text_samples/occi_model_rocci_server.dump +0 -0
- data/spec/occi/parser/text_samples/occi_model_rocci_server.text +51 -0
- data/spec/occi/parser/text_samples/occi_network_rocci_server.dump +0 -0
- data/spec/occi/parser/text_samples/occi_network_rocci_server.resource.dump +0 -0
- data/spec/occi/parser/text_samples/occi_network_rocci_server.text +11 -0
- data/spec/occi/parser/text_samples/occi_resource_w_attributes.dump +0 -0
- data/spec/occi/parser/text_samples/occi_resource_w_attributes.text +11 -0
- data/spec/occi/parser/text_samples/occi_resource_w_inline_links.dump +0 -0
- data/spec/occi/parser/text_samples/occi_resource_w_inline_links.text +16 -0
- data/spec/occi/parser/text_samples/occi_resource_w_inline_links_only.dump +0 -0
- data/spec/occi/parser/text_samples/occi_resource_w_inline_links_only.text +13 -0
- data/spec/occi/parser/text_samples/occi_storage_rocci_server.dump +0 -0
- data/spec/occi/parser/text_samples/occi_storage_rocci_server.resource.dump +0 -0
- data/spec/occi/parser/text_samples/occi_storage_rocci_server.text +9 -0
- data/spec/occi/parser/text_spec.rb +274 -78
- data/spec/occi/parser/xml_samples/test.xml +352 -0
- data/spec/occi/parser_spec.rb +255 -104
- data/spec/occi-core_spec.rb +31 -0
- data/spec/spec_helper.rb +6 -2
- metadata +110 -111
- checksums.yaml +0 -7
- data/spec/occi/core/attribute_spec.rb +0 -0
|
@@ -2,33 +2,209 @@ module Occi
|
|
|
2
2
|
module Core
|
|
3
3
|
describe Category do
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
let(:category) { Category.new }
|
|
6
|
+
let(:category_scheme) { Category.new 'http://example.org/test#', 'category' }
|
|
7
|
+
let(:category_term) { Category.new 'http://schemas.ogf.org/occi/core#', 'testcat' }
|
|
8
|
+
let(:category_scheme_term) { Category.new *'http://schemas.ogf.org/occi/test#category1'.split('#') }
|
|
6
9
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
10
|
+
context '#new' do
|
|
11
|
+
|
|
12
|
+
it 'with defaults' do
|
|
13
|
+
expect { Category.new }.not_to raise_error
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
it 'fails without scheme' do
|
|
17
|
+
expect { Category.new nil }.to raise_error(ArgumentError)
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
it 'fails without term' do
|
|
21
|
+
expect { Category.new 'scheme', nil }.to raise_error(ArgumentError)
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
it 'passes without attributes' do
|
|
25
|
+
expect { Category.new 'scheme', 'term', nil, nil }.not_to raise_error
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
context 'instance attributes' do
|
|
31
|
+
|
|
32
|
+
it 'default scheme is OGF OCCI Core' do
|
|
33
|
+
expect(category.scheme).to eq 'http://schemas.ogf.org/occi/core#'
|
|
14
34
|
end
|
|
15
35
|
|
|
16
|
-
it '
|
|
17
|
-
category
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
category.
|
|
22
|
-
|
|
36
|
+
it 'default term is "category"' do
|
|
37
|
+
expect(category.term).to eq 'category'
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
it 'default title is nil' do
|
|
41
|
+
expect(category.title).to be_nil
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
it 'default attributes are Occi::Core::Attributes' do
|
|
45
|
+
expect(category.attributes).to be_kind_of Occi::Core::Attributes
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
it 'default attributes are empty' do
|
|
49
|
+
expect(category.attributes).to be_empty
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
it 'scheme always ends with a #' do
|
|
53
|
+
expect(category_scheme_term.scheme).to eq 'http://schemas.ogf.org/occi/test#'
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
it 'term is always after the #' do
|
|
57
|
+
expect(category_scheme_term.term).to eq 'category1'
|
|
23
58
|
end
|
|
24
59
|
|
|
25
60
|
end
|
|
26
61
|
|
|
27
|
-
|
|
62
|
+
context '#type_identifier' do
|
|
28
63
|
|
|
29
64
|
it 'returns the type identifier of the category' do
|
|
30
|
-
category
|
|
31
|
-
|
|
65
|
+
expect(category.type_identifier).to eq 'http://schemas.ogf.org/occi/core#category'
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
context '#==' do
|
|
71
|
+
|
|
72
|
+
it 'matches the same instance' do
|
|
73
|
+
expect(category).to eq category
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
it 'matches a clone' do
|
|
77
|
+
expect(category).to eq category.clone
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
it 'matches with a different title' do
|
|
81
|
+
changed_clone = category.clone
|
|
82
|
+
changed_clone.title = 'newtitle'
|
|
83
|
+
|
|
84
|
+
expect(category).to eq changed_clone
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
it 'matches with different attributes' do
|
|
88
|
+
changed_clone = category.clone
|
|
89
|
+
changed_clone.attributes = Occi::Core::Attributes.new({ "id" => '123123' })
|
|
90
|
+
|
|
91
|
+
expect(category).to eq changed_clone
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
it 'does not match a nil' do
|
|
95
|
+
expect(category).not_to eq nil
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
it 'does not match with a different scheme' do
|
|
99
|
+
expect(category).not_to eq category_scheme
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
it 'does not match with a different term' do
|
|
103
|
+
expect(category).not_to eq category_term
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
it 'does not match with a different scheme and term' do
|
|
107
|
+
expect(category).not_to eq category_scheme_term
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
context '#eql?' do
|
|
113
|
+
|
|
114
|
+
it 'matches the same instance' do
|
|
115
|
+
expect(category).to eql category
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
it 'matches a clone' do
|
|
119
|
+
expect(category).to eql category.clone
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
it 'matches with a different title' do
|
|
123
|
+
changed_clone = category.clone
|
|
124
|
+
changed_clone.title = 'newtitle'
|
|
125
|
+
|
|
126
|
+
expect(category).to eql changed_clone
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
it 'matches with different attributes' do
|
|
130
|
+
changed_clone = category.clone
|
|
131
|
+
changed_clone.attributes = Occi::Core::Attributes.new({ "id" => '123123' })
|
|
132
|
+
|
|
133
|
+
expect(category).to eql changed_clone
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
it 'does not match a nil' do
|
|
137
|
+
expect(category).not_to eql nil
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
it 'does not match with a different scheme' do
|
|
141
|
+
expect(category).not_to eql category_scheme
|
|
142
|
+
end
|
|
143
|
+
|
|
144
|
+
it 'does not match with a different term' do
|
|
145
|
+
expect(category).not_to eql category_term
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
it 'does not match with a different scheme and term' do
|
|
149
|
+
expect(category).not_to eql category_scheme_term
|
|
150
|
+
end
|
|
151
|
+
|
|
152
|
+
end
|
|
153
|
+
|
|
154
|
+
context '#equal?' do
|
|
155
|
+
|
|
156
|
+
it 'matches the same instance' do
|
|
157
|
+
expect(category).to equal category
|
|
158
|
+
end
|
|
159
|
+
|
|
160
|
+
it 'does not match clones' do
|
|
161
|
+
expect(category).not_to equal category.clone
|
|
162
|
+
end
|
|
163
|
+
|
|
164
|
+
end
|
|
165
|
+
|
|
166
|
+
context '#hash' do
|
|
167
|
+
|
|
168
|
+
it 'matches for clones' do
|
|
169
|
+
expect(category.hash).to eq category.clone.hash
|
|
170
|
+
end
|
|
171
|
+
|
|
172
|
+
it 'matches for the same instance' do
|
|
173
|
+
expect(category.hash).to eq category.hash
|
|
174
|
+
end
|
|
175
|
+
|
|
176
|
+
it 'does not match when term is different' do
|
|
177
|
+
expect(category.hash).not_to eq category_term.hash
|
|
178
|
+
end
|
|
179
|
+
|
|
180
|
+
it 'does not match when scheme is different' do
|
|
181
|
+
expect(category.hash).not_to eq category_scheme.hash
|
|
182
|
+
end
|
|
183
|
+
|
|
184
|
+
it 'does not match when scheme and term are different' do
|
|
185
|
+
expect(category.hash).not_to eq category_scheme_term
|
|
186
|
+
end
|
|
187
|
+
|
|
188
|
+
end
|
|
189
|
+
|
|
190
|
+
context '#empty?' do
|
|
191
|
+
|
|
192
|
+
it 'returns false for a new instance with defaults' do
|
|
193
|
+
expect(category.empty?).to be_false
|
|
194
|
+
end
|
|
195
|
+
|
|
196
|
+
it 'returns true for an instance without a term' do
|
|
197
|
+
cat = category.clone
|
|
198
|
+
cat.term = nil
|
|
199
|
+
|
|
200
|
+
expect(cat.empty?).to be_true
|
|
201
|
+
end
|
|
202
|
+
|
|
203
|
+
it 'returns true for an instance without a scheme' do
|
|
204
|
+
cat = category.clone
|
|
205
|
+
cat.scheme = nil
|
|
206
|
+
|
|
207
|
+
expect(cat.empty?).to be_true
|
|
32
208
|
end
|
|
33
209
|
|
|
34
210
|
end
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
module Occi
|
|
2
|
+
module Core
|
|
3
|
+
describe Entities do
|
|
4
|
+
let(:entities){ Occi::Core::Entities.new }
|
|
5
|
+
let(:entity1){ entity1 = Occi::Core::Entity.new
|
|
6
|
+
entity1.id = "e1testid"
|
|
7
|
+
entity1 }
|
|
8
|
+
let(:entity2){ entity2 = Occi::Core::Entity.new 'http://example.org/test/schema#entity2'
|
|
9
|
+
entity2.id = "e2testid"
|
|
10
|
+
entity2 }
|
|
11
|
+
let(:testaction){ Occi::Core::Action.new scheme='http://schemas.ogf.org/occi/core/entity/action#', term='testaction', title='testaction action' }
|
|
12
|
+
|
|
13
|
+
context 'populating' do
|
|
14
|
+
|
|
15
|
+
it 'is created empty' do
|
|
16
|
+
expect(entities.count).to eq 0
|
|
17
|
+
end
|
|
18
|
+
it 'gets entity Nos. right, 1' do
|
|
19
|
+
entities << entity1
|
|
20
|
+
expect(entities.count).to eq 1
|
|
21
|
+
end
|
|
22
|
+
it 'gets entity Nos. right, 2' do
|
|
23
|
+
entities << entity1
|
|
24
|
+
entities << entity2
|
|
25
|
+
expect(entities.count).to eq 2
|
|
26
|
+
end
|
|
27
|
+
it 'gets correctly-typed elements' do
|
|
28
|
+
entities << entity1
|
|
29
|
+
entities << entity2
|
|
30
|
+
expect(entities.first).to be_an_instance_of(Occi::Core::Entity)
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
context '#model' do
|
|
35
|
+
it 'has no model by default' do
|
|
36
|
+
expect(entities.model).to be nil
|
|
37
|
+
end
|
|
38
|
+
it 'can be assigned model' do
|
|
39
|
+
modl = Occi::Model.new
|
|
40
|
+
entities.model = modl
|
|
41
|
+
expect(entities.model).to eql modl
|
|
42
|
+
end
|
|
43
|
+
it 'uses the assigned model for new members' do
|
|
44
|
+
modl = Occi::Model.new
|
|
45
|
+
entities.model = modl
|
|
46
|
+
entities << entity1
|
|
47
|
+
expect(entities.first.model).to eql modl
|
|
48
|
+
end
|
|
49
|
+
it 'uses the assigned model for existing members' do
|
|
50
|
+
entities << entity1
|
|
51
|
+
modl = Occi::Model.new
|
|
52
|
+
entities.model = modl
|
|
53
|
+
expect(entities.first.model).to eql modl
|
|
54
|
+
end
|
|
55
|
+
it 'does not use unassigned model' do
|
|
56
|
+
modl = Occi::Model.new
|
|
57
|
+
entities << entity1
|
|
58
|
+
expect(entities.first.model).to_not eql modl
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
context '#create' do
|
|
63
|
+
it 'creates a new element' do
|
|
64
|
+
entities.create
|
|
65
|
+
expect(entities.first).to be_instance_of(Occi::Core::Entity)
|
|
66
|
+
end
|
|
67
|
+
it 'accepts argument' do
|
|
68
|
+
entities.create 'http://example.com/testnamespace#test'
|
|
69
|
+
expect(entities.first).to be_kind_of 'Com::Example::Testnamespace::Test'.constantize
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
context '#join' do
|
|
74
|
+
it 'joins elements correctly' do
|
|
75
|
+
entities << entity1
|
|
76
|
+
entities << entity2
|
|
77
|
+
expect(entities.join('|')).to eq '/entity/e1testid|/entity2/e2testid'
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
context '#as_json' do
|
|
82
|
+
it 'renders elements with various attributes' do
|
|
83
|
+
entity2.actions << testaction
|
|
84
|
+
entities << entity1
|
|
85
|
+
entities << entity2
|
|
86
|
+
expected = []
|
|
87
|
+
hash=Hashie::Mash.new JSON.parse('{"kind":"http://schemas.ogf.org/occi/core#entity","attributes":{"occi":{"core":{"id":"e1testid"}}},"id":"e1testid"}')
|
|
88
|
+
hash2= Hashie::Mash.new JSON.parse('{"kind":"http://example.org/test/schema#entity2","actions":[{"scheme":"http://schemas.ogf.org/occi/core/entity/action#","term":"testaction","title":"testaction action","attributes":{}}],"attributes":{"occi":{"core":{"id":"e2testid"}}},"id":"e2testid"}')
|
|
89
|
+
expected << hash
|
|
90
|
+
expected << hash2
|
|
91
|
+
expect(entities.as_json).to eql expected
|
|
92
|
+
end
|
|
93
|
+
end
|
|
94
|
+
end
|
|
95
|
+
end
|
|
96
|
+
end
|
|
@@ -1,44 +1,333 @@
|
|
|
1
1
|
module Occi
|
|
2
2
|
module Core
|
|
3
3
|
describe Entity do
|
|
4
|
+
let(:entity){
|
|
5
|
+
entity = Occi::Core::Entity.new
|
|
6
|
+
entity.id = 'baf1'
|
|
7
|
+
entity
|
|
8
|
+
}
|
|
9
|
+
let(:testaction){ Occi::Core::Action.new scheme='http://schemas.ogf.org/occi/core/entity/action#', term='testaction', title='testaction action' }
|
|
4
10
|
|
|
5
11
|
it "initializes itself successfully" do
|
|
6
|
-
entity
|
|
7
|
-
entity.should be_kind_of Occi::Core::Entity
|
|
12
|
+
expect(entity).to be_kind_of Occi::Core::Entity
|
|
8
13
|
end
|
|
9
14
|
|
|
10
|
-
|
|
11
|
-
type_identifier
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
15
|
+
context 'initializiation of a subclass using a type identifier' do
|
|
16
|
+
let(:type_identifier){ 'http://example.com/testnamespace#test' }
|
|
17
|
+
let(:typed_entity){ Occi::Core::Entity.new type_identifier }
|
|
18
|
+
|
|
19
|
+
it 'has the correct kind' do
|
|
20
|
+
expect(typed_entity).to be_kind_of 'Com::Example::Testnamespace::Test'.constantize
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
it 'uses the right identifier' do
|
|
24
|
+
expect(typed_entity.kind.type_identifier).to eq type_identifier
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
it 'relates to Entity' do
|
|
28
|
+
expect(typed_entity.kind.related.first).to eq Occi::Core::Entity.kind
|
|
29
|
+
end
|
|
16
30
|
end
|
|
17
31
|
|
|
18
|
-
|
|
19
|
-
kind
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
32
|
+
context "initialization of a subclass using an OCCI Kind" do
|
|
33
|
+
let(:kind){ Occi::Core::Resource.kind }
|
|
34
|
+
let(:kind_entity){ Occi::Core::Entity.new kind }
|
|
35
|
+
|
|
36
|
+
it 'has the correct kind' do
|
|
37
|
+
expect(kind_entity).to be_kind_of Occi::Core::Resource
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
it 'uses the right identifier' do
|
|
41
|
+
expect(kind_entity.kind.type_identifier).to eq Occi::Core::Resource.type_identifier
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
it 'relates to Entity' do
|
|
45
|
+
expect(kind_entity.kind.related.first).to eq Occi::Core::Entity.kind
|
|
46
|
+
end
|
|
24
47
|
end
|
|
25
48
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
49
|
+
context '#kind' do
|
|
50
|
+
it 'accepts kind from string' do
|
|
51
|
+
entity.kind = 'http://example.com/testnamespace#test'
|
|
52
|
+
expect(entity.kind).to eql Com::Example::Testnamespace::Test
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
it 'accepts kind from class' do
|
|
56
|
+
entity.kind = Com::Example::Testnamespace::Test
|
|
57
|
+
expect(entity.kind).to eql Com::Example::Testnamespace::Test
|
|
58
|
+
end
|
|
31
59
|
end
|
|
32
60
|
|
|
33
|
-
#
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
61
|
+
context '#mixins' do
|
|
62
|
+
let(:mixin){ 'http://example.com/mynamespace#mymixin' }
|
|
63
|
+
|
|
64
|
+
it "converts mixin type identifiers to objects if a mixin is added to the entities mixins" do
|
|
65
|
+
entity.mixins << mixin
|
|
66
|
+
expect(entity.mixins.first.to_s).to eq mixin
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
context 'attributes' do
|
|
71
|
+
|
|
72
|
+
context 'checking attribute validity' do
|
|
73
|
+
before(:each) { Occi::Settings['compatibility']=false }
|
|
74
|
+
after(:each) { Occi::Settings.reload! }
|
|
75
|
+
|
|
76
|
+
it 'fails check with model missing' do
|
|
77
|
+
expect { entity.check }.to raise_error
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
it 'runs check successfully with a model registered' do
|
|
81
|
+
entity.model = Occi::Model.new
|
|
82
|
+
entity.title = 'test'
|
|
83
|
+
uuid = UUIDTools::UUID.random_create.to_s
|
|
84
|
+
Occi::Settings['verify_attribute_pattern']=true
|
|
85
|
+
expect { entity.id = uuid }.to_not raise_error
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
it 'rejects values not matching pattern' do
|
|
89
|
+
entity.model = Occi::Model.new
|
|
90
|
+
entity.id = 'id with spaces'
|
|
91
|
+
Occi::Settings['verify_attribute_pattern']=true
|
|
92
|
+
expect{ entity.id = 'id with spaces' }.to raise_error Occi::Errors::AttributeTypeError
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
context '#location' do
|
|
98
|
+
it 'can be set and read' do
|
|
99
|
+
entity.location = 'TestLoc'
|
|
100
|
+
expect(entity.location).to eq 'TestLoc'
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
it 'can be constructed from id' do
|
|
104
|
+
entity.id = UUIDTools::UUID.random_create.to_s
|
|
105
|
+
expect(entity.location).to eq '/entity/' + entity.id
|
|
106
|
+
end
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
context '#title' do
|
|
110
|
+
it 'can be set and read' do
|
|
111
|
+
entity.title = 'TestTitle'
|
|
112
|
+
expect(entity.title).to eq 'TestTitle'
|
|
113
|
+
end
|
|
114
|
+
end
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
context '#actions' do
|
|
118
|
+
it 'can be populated through redirection' do
|
|
119
|
+
entity.actions << testaction
|
|
120
|
+
expect(entity.actions.count).to eq 1
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
it 'can be assigned through the setter method' do
|
|
124
|
+
acts = Occi::Core::Actions.new
|
|
125
|
+
acts << testaction
|
|
126
|
+
entity.actions=acts
|
|
127
|
+
expect(entity.actions.count).to eq 1
|
|
128
|
+
end
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
context '#to_text' do
|
|
132
|
+
it 'renders fresh instance in text correctly' do
|
|
133
|
+
expected = %Q|Category: entity;scheme="http://schemas.ogf.org/occi/core#";class="kind"
|
|
134
|
+
X-OCCI-Attribute: occi.core.id="baf1"|
|
|
135
|
+
expect(entity.to_text).to eq(expected)
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
it 'renders instance with attributes in text correctly' do
|
|
139
|
+
entity.actions << testaction
|
|
140
|
+
entity.title = 'TestTitle'
|
|
141
|
+
entity.location = '/TestLoc/1'
|
|
142
|
+
entity.mixins << 'http://example.com/mynamespace#mymixin'
|
|
143
|
+
|
|
144
|
+
expected = %Q|Category: entity;scheme="http://schemas.ogf.org/occi/core#";class="kind"
|
|
145
|
+
Category: mymixin;scheme="http://example.com/mynamespace#";class="mixin"
|
|
146
|
+
X-OCCI-Attribute: occi.core.id="baf1"
|
|
147
|
+
X-OCCI-Attribute: occi.core.title="TestTitle"
|
|
148
|
+
Link: </TestLoc/1?action=testaction>;rel=http://schemas.ogf.org/occi/core/entity/action#testaction|
|
|
149
|
+
expect(entity.to_text).to eq(expected)
|
|
150
|
+
end
|
|
151
|
+
end
|
|
152
|
+
|
|
153
|
+
context '#to_header' do
|
|
154
|
+
it 'renders fresh instance in HTTP Header correctly' do
|
|
155
|
+
expected = Hashie::Mash.new
|
|
156
|
+
expected['Category'] = 'entity;scheme="http://schemas.ogf.org/occi/core#";class="kind"'
|
|
157
|
+
expected['X-OCCI-Attribute'] = 'occi.core.id="baf1"'
|
|
158
|
+
|
|
159
|
+
expect(entity.to_header).to eql(expected)
|
|
160
|
+
end
|
|
161
|
+
|
|
162
|
+
it 'renders instance with attributes in HTTP Header correctly' do
|
|
163
|
+
entity.actions << testaction
|
|
164
|
+
entity.title = 'TestTitle'
|
|
165
|
+
entity.location = '/TestLoc/1'
|
|
166
|
+
entity.mixins << 'http://example.com/mynamespace#mymixin'
|
|
167
|
+
|
|
168
|
+
expected = Hashie::Mash.new
|
|
169
|
+
expected['Category'] = 'entity;scheme="http://schemas.ogf.org/occi/core#";class="kind",mymixin;scheme="http://example.com/mynamespace#";class="mixin"'
|
|
170
|
+
expected['X-OCCI-Attribute'] = 'occi.core.id="baf1",occi.core.title="TestTitle"'
|
|
171
|
+
expected['Link'] = '</TestLoc/1?action=testaction>;rel=http://schemas.ogf.org/occi/core/entity/action#testaction'
|
|
172
|
+
|
|
173
|
+
expect(entity.to_header).to eql(expected)
|
|
174
|
+
end
|
|
175
|
+
end
|
|
176
|
+
|
|
177
|
+
context '#check' do
|
|
178
|
+
let(:defs){
|
|
179
|
+
defs = Occi::Core::Attributes.new
|
|
180
|
+
defs['occi.core.id'] = { :type=> 'string',
|
|
181
|
+
:required => true }
|
|
182
|
+
defs['numbertype'] = { :type => 'number',
|
|
183
|
+
:default => 42,
|
|
184
|
+
:mutable => true,
|
|
185
|
+
:pattern => '^[0-9]+' }
|
|
186
|
+
defs['stringtype'] = { :type => 'string',
|
|
187
|
+
:pattern => '[adefltuv]+',
|
|
188
|
+
:default => 'defaultvalue',
|
|
189
|
+
:mutable => true }
|
|
190
|
+
defs['booleantype'] = { :type => 'boolean',
|
|
191
|
+
:default => true,
|
|
192
|
+
:mutable => true}
|
|
193
|
+
defs['booleantypefalse'] = { :type => 'boolean',
|
|
194
|
+
:default => false,
|
|
195
|
+
:mutable => true }
|
|
196
|
+
defs['booleantypepattern'] = { :type => 'boolean',
|
|
197
|
+
:default => true,
|
|
198
|
+
:mutable => true,
|
|
199
|
+
:pattern => true }
|
|
200
|
+
defs }
|
|
201
|
+
let(:kind){ Occi::Core::Kind.new 'http://schemas.ogf.org/occi/core#', 'testkind', 'Test Kind', defs }
|
|
202
|
+
let(:model){ model = Occi::Model.new
|
|
203
|
+
model.register(kind)
|
|
204
|
+
model.register(defmixin)
|
|
205
|
+
model }
|
|
206
|
+
let(:defmixin){ defmixin = Occi::Core::Mixin.new 'http://schemas.ogf.org/occi/core#', 'testmixin'
|
|
207
|
+
defmixin.attributes['mixinstring'] = { :type => 'string',
|
|
208
|
+
:pattern => '.*',
|
|
209
|
+
:default => 'mixdefault',
|
|
210
|
+
:mutable => true }
|
|
211
|
+
defmixin }
|
|
212
|
+
let(:mixin){ Occi::Core::Mixin.new 'http://schemas.ogf.org/occi/core#', 'testmixin' }
|
|
213
|
+
|
|
214
|
+
let(:entity){ entity = Occi::Core::Entity.new(kind, [], defs)
|
|
215
|
+
entity.model = model
|
|
216
|
+
entity.mixins << mixin
|
|
217
|
+
entity }
|
|
218
|
+
|
|
219
|
+
|
|
220
|
+
before(:each){ Occi::Settings['compatibility']=false
|
|
221
|
+
Occi::Settings['verify_attribute_pattern']=true }
|
|
222
|
+
after(:each) { Occi::Settings.reload! }
|
|
223
|
+
context 'unsupported types' do
|
|
224
|
+
it 'refuses unsupported type' do
|
|
225
|
+
expect{ entity.attributes['othertype'] = { :type => 'other', :default => 'defaultvalue' } }.to raise_exception(Occi::Errors::AttributePropertyTypeError)
|
|
226
|
+
end
|
|
227
|
+
end
|
|
228
|
+
context 'defaults' do
|
|
229
|
+
context 'setting defaults' do
|
|
230
|
+
it 'sets numeric default' do
|
|
231
|
+
entity.check(true)
|
|
232
|
+
expect(entity.attributes['numbertype']).to eq 42
|
|
233
|
+
end
|
|
234
|
+
it 'sets string default' do
|
|
235
|
+
entity.check(true)
|
|
236
|
+
expect(entity.attributes['stringtype']).to eq 'defaultvalue'
|
|
237
|
+
end
|
|
238
|
+
it 'sets mixin string default' do
|
|
239
|
+
entity.check(true)
|
|
240
|
+
expect(entity.attributes['mixinstring']).to eq 'mixdefault'
|
|
241
|
+
end
|
|
242
|
+
it 'sets boolean default if true' do
|
|
243
|
+
entity.check(true)
|
|
244
|
+
expect(entity.attributes['booleantype']).to eq true
|
|
245
|
+
end
|
|
246
|
+
it 'sets boolean default if false' do
|
|
247
|
+
entity.check(true)
|
|
248
|
+
expect(entity.attributes['booleantypefalse']).to eq false
|
|
249
|
+
end
|
|
250
|
+
it 'can be checked twice in a row' do
|
|
251
|
+
entity.check(true)
|
|
252
|
+
expect{ entity.check(true) }.to_not raise_exception
|
|
253
|
+
end
|
|
254
|
+
it 'skips numeric default' do
|
|
255
|
+
entity.attributes['numbertype'] = 12
|
|
256
|
+
entity.check(true)
|
|
257
|
+
expect(entity.attributes['numbertype']).to eq 12
|
|
258
|
+
end
|
|
259
|
+
it 'skips string default' do
|
|
260
|
+
entity.attributes['stringtype'] = 'fault'
|
|
261
|
+
entity.check(true)
|
|
262
|
+
expect(entity.attributes['stringtype']).to eq 'fault'
|
|
263
|
+
end
|
|
264
|
+
it 'skips boolean default if true' do
|
|
265
|
+
entity.attributes['booleantype'] = false
|
|
266
|
+
entity.check(true)
|
|
267
|
+
expect(entity.attributes['booleantype']).to eq false
|
|
268
|
+
end
|
|
269
|
+
it 'skips boolean default if false' do
|
|
270
|
+
entity.attributes['booleantypefalse'] = true
|
|
271
|
+
entity.check(true)
|
|
272
|
+
expect(entity.attributes['booleantypefalse']).to eq true
|
|
273
|
+
end
|
|
274
|
+
end
|
|
275
|
+
|
|
276
|
+
context 'patterns' do
|
|
277
|
+
it 'checks string pattern' do
|
|
278
|
+
expect{ entity.attributes['stringtype'] = 'bflmpsvz' }.to raise_exception(Occi::Errors::AttributeTypeError)
|
|
279
|
+
end
|
|
280
|
+
it 'checks numeric pattern' do
|
|
281
|
+
expect{ entity.attributes['numbertype'] = -32 }.to raise_exception(Occi::Errors::AttributeTypeError)
|
|
282
|
+
end
|
|
283
|
+
it 'checks boolean pattern' do
|
|
284
|
+
expect{ entity.attributes['booleantypepattern'] = false }.to raise_exception(Occi::Errors::AttributeTypeError)
|
|
285
|
+
end
|
|
286
|
+
end
|
|
287
|
+
end
|
|
288
|
+
|
|
289
|
+
context 'exceptions' do
|
|
290
|
+
it 'raisees exception for missing model' do
|
|
291
|
+
ent = Occi::Core::Entity.new(kind, [], defs)
|
|
292
|
+
expect{ ent.check(true) }.to raise_exception ArgumentError
|
|
293
|
+
end
|
|
294
|
+
|
|
295
|
+
it 'raises exception for inexistent kind' do
|
|
296
|
+
ent = Occi::Core::Entity.new(kind, [], defs)
|
|
297
|
+
mod = Occi::Model.new
|
|
298
|
+
ent.model = mod
|
|
299
|
+
expect{ ent.check(true) }.to raise_exception Occi::Errors::KindNotDefinedError
|
|
300
|
+
end
|
|
301
|
+
end
|
|
302
|
+
end
|
|
303
|
+
|
|
304
|
+
context '#attribute_properties' do
|
|
305
|
+
it 'gets attribute properties' do
|
|
306
|
+
properties = entity.attribute_properties
|
|
307
|
+
expect(properties.occi.core.count).to eql 4
|
|
308
|
+
end
|
|
309
|
+
end
|
|
310
|
+
|
|
311
|
+
context '#empty?' do
|
|
312
|
+
|
|
313
|
+
it 'returns false for a new instance with defaults' do
|
|
314
|
+
expect(entity.empty?).to be_false
|
|
315
|
+
end
|
|
316
|
+
|
|
317
|
+
it 'returns true for an instance without a kind' do
|
|
318
|
+
ent = entity.clone
|
|
319
|
+
ent.kind = nil
|
|
320
|
+
|
|
321
|
+
expect(ent.empty?).to be_true
|
|
322
|
+
end
|
|
323
|
+
|
|
324
|
+
it 'returns true for an instance without an identifier' do
|
|
325
|
+
ent = entity.clone
|
|
326
|
+
ent.id = nil
|
|
327
|
+
|
|
328
|
+
expect(ent.empty?).to be_true
|
|
329
|
+
end
|
|
330
|
+
|
|
42
331
|
end
|
|
43
332
|
|
|
44
333
|
end
|