omf_common 6.0.0.pre.10 → 6.0.0.pre.11

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 (41) hide show
  1. data/bin/monitor_topic.rb +80 -0
  2. data/bin/send_create.rb +94 -0
  3. data/bin/send_request.rb +58 -0
  4. data/example/engine_alt.rb +136 -0
  5. data/example/vm_alt.rb +65 -0
  6. data/lib/omf_common.rb +224 -3
  7. data/lib/omf_common/comm.rb +113 -46
  8. data/lib/omf_common/comm/amqp/amqp_communicator.rb +76 -0
  9. data/lib/omf_common/comm/amqp/amqp_topic.rb +91 -0
  10. data/lib/omf_common/comm/local/local_communicator.rb +64 -0
  11. data/lib/omf_common/comm/local/local_topic.rb +42 -0
  12. data/lib/omf_common/comm/topic.rb +190 -0
  13. data/lib/omf_common/{dsl/xmpp.rb → comm/xmpp/communicator.rb} +93 -53
  14. data/lib/omf_common/comm/xmpp/topic.rb +147 -0
  15. data/lib/omf_common/{dsl → comm/xmpp}/xmpp_mp.rb +2 -0
  16. data/lib/omf_common/eventloop.rb +94 -0
  17. data/lib/omf_common/eventloop/em.rb +57 -0
  18. data/lib/omf_common/eventloop/local_evl.rb +78 -0
  19. data/lib/omf_common/message.rb +112 -229
  20. data/lib/omf_common/message/json/json_message.rb +129 -0
  21. data/lib/omf_common/message/xml/message.rb +410 -0
  22. data/lib/omf_common/message/xml/relaxng_schema.rb +17 -0
  23. data/lib/omf_common/message/xml/topic_message.rb +20 -0
  24. data/lib/omf_common/protocol/6.0.rnc +11 -21
  25. data/lib/omf_common/protocol/6.0.rng +52 -119
  26. data/lib/omf_common/version.rb +1 -1
  27. data/omf_common.gemspec +4 -2
  28. data/test/fixture/pubsub.rb +19 -19
  29. data/test/omf_common/{dsl/xmpp_spec.rb → comm/xmpp/communicator_spec.rb} +47 -111
  30. data/test/omf_common/comm/xmpp/topic_spec.rb +113 -0
  31. data/test/omf_common/comm_spec.rb +1 -0
  32. data/test/omf_common/message/xml/message_spec.rb +136 -0
  33. data/test/omf_common/message_spec.rb +37 -131
  34. data/test/test_helper.rb +4 -1
  35. metadata +38 -28
  36. data/lib/omf_common/core_ext/object.rb +0 -21
  37. data/lib/omf_common/relaxng_schema.rb +0 -17
  38. data/lib/omf_common/topic.rb +0 -34
  39. data/lib/omf_common/topic_message.rb +0 -20
  40. data/test/omf_common/topic_message_spec.rb +0 -114
  41. data/test/omf_common/topic_spec.rb +0 -75
@@ -0,0 +1,113 @@
1
+ require 'fixture/pubsub'
2
+ require 'em/minitest/spec'
3
+
4
+ require 'omf_common/comm/xmpp/topic'
5
+
6
+ describe OmfCommon::Comm::XMPP::Topic do
7
+ before do
8
+ @client = Blather::Client.new
9
+ @stream = MiniTest::Mock.new
10
+ @stream.expect(:send, true, [Blather::Stanza])
11
+ @client.post_init @stream, Blather::JID.new('n@d/r')
12
+ @xmpp = OmfCommon::Comm::XMPP::Communicator.new
13
+
14
+ OmfCommon.stub :comm, @xmpp do
15
+ Blather::Client.stub :new, @client do
16
+ @stream.expect(:send, true, [Blather::Stanza::PubSub::Create])
17
+ @topic = OmfCommon::Comm::XMPP::Topic.create(:test_topic)
18
+ end
19
+ end
20
+ end
21
+
22
+ describe "when calling operation method" do
23
+ it "must send create message" do
24
+ OmfCommon.stub :comm, @xmpp do
25
+ Blather::Client.stub :new, @client do
26
+ published = Blather::XMPPNode.parse(published_xml)
27
+
28
+ write_callback = proc do |event|
29
+ event.must_be_kind_of Blather::Stanza::PubSub::Publish
30
+ published.id = event.id
31
+ @client.receive_data published
32
+ end
33
+
34
+ @client.stub :write, write_callback do
35
+ @topic.create(:bob, { hrn: 'bob' })
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
41
+
42
+ describe "when informed message received" do
43
+ include EM::MiniTest::Spec
44
+
45
+ it "must react to omf created message" do
46
+ OmfCommon.stub :comm, @xmpp do
47
+ Blather::Client.stub :new, @client do
48
+ omf_create = OmfCommon::Message.create(:create, { type: 'engine' })
49
+ omf_create.stub :mid, "bf840fe9-c176-4fae-b7de-6fc27f183f76" do
50
+ omf_created = Blather::XMPPNode.parse(omf_created_xml)
51
+ @client.receive_data omf_created
52
+ @topic.on_creation_ok(omf_create) do |n|
53
+ n.must_equal OmfCommon::Message.parse(omf_created.items.first.payload)
54
+ done!
55
+ end
56
+ end
57
+ end
58
+ end
59
+ wait!
60
+ end
61
+
62
+ it "must react to omf status message" do
63
+ OmfCommon.stub :comm, @xmpp do
64
+ Blather::Client.stub :new, @client do
65
+ omf_request = OmfCommon::Message.create(:request, [:bob])
66
+ omf_request.stub :mid, "bf840fe9-c176-4fae-b7de-6fc27f183f76" do
67
+ omf_status = Blather::XMPPNode.parse(omf_status_xml)
68
+ @client.receive_data omf_status
69
+ @topic.on_status(omf_request) do |n|
70
+ n.must_equal OmfCommon::Message.parse(omf_status.items.first.payload)
71
+ done!
72
+ end
73
+ end
74
+ end
75
+ end
76
+ wait!
77
+ end
78
+
79
+ it "must react to omf release message" do
80
+ OmfCommon.stub :comm, @xmpp do
81
+ Blather::Client.stub :new, @client do
82
+ omf_release = OmfCommon::Message.create(:release, nil, { res_id: '100' })
83
+ omf_release.stub :mid, "bf840fe9-c176-4fae-b7de-6fc27f183f76" do
84
+ omf_released = Blather::XMPPNode.parse(omf_released_xml)
85
+ @client.receive_data omf_released
86
+ @topic.on_released(omf_release) do |n|
87
+ n.must_equal OmfCommon::Message.parse(omf_released.items.first.payload)
88
+ done!
89
+ end
90
+ end
91
+ end
92
+ end
93
+ wait!
94
+ end
95
+
96
+ it "must react to omf failed message" do
97
+ OmfCommon.stub :comm, @xmpp do
98
+ Blather::Client.stub :new, @client do
99
+ omf_create = OmfCommon::Message.create(:create, { type: 'engine' })
100
+ omf_create.stub :mid, "bf840fe9-c176-4fae-b7de-6fc27f183f76" do
101
+ omf_failed = Blather::XMPPNode.parse(omf_failed_xml)
102
+ @client.receive_data omf_failed
103
+ @topic.on_creation_failed(omf_create) do |n|
104
+ n.must_equal OmfCommon::Message.parse(omf_failed.items.first.payload)
105
+ done!
106
+ end
107
+ end
108
+ end
109
+ end
110
+ wait!
111
+ end
112
+ end
113
+ end
@@ -3,6 +3,7 @@ require 'test_helper'
3
3
  describe OmfCommon::Comm do
4
4
  describe 'when initialised with a pubsub implementation' do
5
5
  it 'must return a instance with all methods defined in corresponding module loaded' do
6
+ skip
6
7
  @comm = OmfCommon::Comm.new(:xmpp)
7
8
  %w(connect disconnect create_topic delete_topic subscribe unsubscribe publish affiliations).each do |m|
8
9
  @comm.must_respond_to m
@@ -0,0 +1,136 @@
1
+ require 'test_helper'
2
+ require 'omf_common/message/xml/message'
3
+
4
+ include OmfCommon
5
+
6
+ describe OmfCommon::Message::XML::Message do
7
+ describe "when create message initialised" do
8
+ before do
9
+ # We will test prop value other than just strings
10
+ @message = Message::XML::Message.create(:create,
11
+ { type: 'bob', p1: 'p1_value', p2: { unit: 'u', precision: 2 } },
12
+ { rtype: 'bob', guard: { p1: 'p1_value' } })
13
+ end
14
+
15
+ it "must to be validated using relaxng schema" do
16
+ @message.valid?.must_equal true
17
+ end
18
+
19
+ it "must be able to be serialised as XML" do
20
+ @message.to_xml.must_match /^<create(.+)create>$/m
21
+ @message.to_xml.must_match /<rtype>bob<\/rtype>/m
22
+ @message.to_xml.must_match /<props(.+)props>/m
23
+ @message.to_xml.must_match /<guard(.+)guard>/m
24
+ end
25
+ end
26
+
27
+ describe "when release message initialised" do
28
+ before do
29
+ # We will test prop value other than just strings
30
+ @message = Message::XML::Message.create(:release, {}, { res_id: 'bob', guard: { p1: 'p1_value' } })
31
+ end
32
+
33
+ it "must to be validated using relaxng schema" do
34
+ @message.valid?.must_equal true
35
+ end
36
+
37
+ it "must be able to be serialised as XML" do
38
+ @message.to_xml.must_match /^<release(.+)release>$/m
39
+ @message.to_xml.must_match /<res_id>bob<\/res_id>/m
40
+ @message.to_xml.must_match /<guard(.+)guard>/m
41
+ end
42
+ end
43
+
44
+ describe "when asked to parse a XML element into Message::XML::Message object" do
45
+ before do
46
+ @xml = Message::XML::Message.create(
47
+ :create,
48
+ { type: 'vm',
49
+ os: 'debian',
50
+ memory: { value: 1024, unit: 'mb', precision: 0 },
51
+ devices: [{ name: 'w0', driver: 'mod_bob'}, { name: 'w1', driver: ['mod1', 'mod2']} ],
52
+ true: true,
53
+ false: false,
54
+ empty: nil,
55
+ boolean_array: [false, true] },
56
+ { rtype: 'vm', guard: { os_type: 'linux' } }).to_xml
57
+
58
+ @message = Message::XML::Message.parse(@xml)
59
+ end
60
+
61
+ it "must create the object correctly" do
62
+ @message.must_be_kind_of Message::XML::Message
63
+ @message.operation.must_equal :create
64
+ end
65
+
66
+ it "must provide normal xml xpath query" do
67
+ @message.read_element("props").first.element_children.size.must_equal 8
68
+ # TODO how to handle complext xpath??? with ns...
69
+ # @message.read_content("//memory/unit").must_equal 'mb'
70
+ end
71
+
72
+ it "must provide unified message property access" do
73
+ @message["type"].must_equal 'vm'
74
+ @message[:type].must_equal 'vm'
75
+ end
76
+
77
+ it "must provide guard information" do
78
+ @message.guard[:os_type].must_equal 'linux'
79
+ end
80
+
81
+ it "must be able reconstruct complicate data" do
82
+ # Each property iterator
83
+ @message.each_property do |k, v|
84
+ %w(type os memory devices true false empty boolean_array).must_include k
85
+ end
86
+
87
+ memory = @message[:memory]
88
+ memory.must_be_kind_of Hashie::Mash
89
+ memory.value.must_equal 1024
90
+ memory.unit.must_equal 'mb'
91
+ memory.precision.must_equal 0
92
+
93
+ devices = @message[:devices]
94
+ devices.must_be_kind_of Array
95
+ devices.size.must_equal 2
96
+ devices.find { |v| v.name == 'w1'}.driver.size.must_equal 2
97
+ end
98
+
99
+ it "must be able ducktype string xml content for numbers, boolean, empty string" do
100
+ @message[:true].must_equal true
101
+ @message[:false].must_equal false
102
+ @message[:boolean_array].must_equal [false, true]
103
+ @message[:empty].must_equal nil
104
+ end
105
+
106
+ it "must fail if parse an empty xml" do
107
+ lambda { Message::XML::Message.parse("") }.must_raise ArgumentError
108
+ lambda { Message::XML::Message.parse(nil) }.must_raise ArgumentError
109
+ end
110
+ end
111
+
112
+ describe "when creating request messages" do
113
+ it "must accept an array of properties instead of hash" do
114
+ request_m = Message::XML::Message.create(:request, [:p1, :p2])
115
+ request_m.valid?.must_equal true
116
+ request_m[:p1].must_be_nil
117
+ end
118
+ end
119
+
120
+ describe "when parsing inform message" do
121
+ it "must validate against inform message schema" do
122
+ msg = Message::XML::Message.parse <<-XML
123
+ <inform xmlns="http://schema.mytestbed.net/omf/6.0/protocol" mid="bob">
124
+ <src>xmpp://bob@localhost</src>
125
+ <ts>100</ts>
126
+ <itype>CREATION.OK</itype>
127
+ </inform>
128
+ XML
129
+
130
+ msg.ts.must_equal "100"
131
+ msg.itype.must_equal "CREATION.OK"
132
+
133
+ msg.valid?.must_equal true
134
+ end
135
+ end
136
+ end
@@ -1,151 +1,57 @@
1
1
  require 'test_helper'
2
2
 
3
- include OmfCommon
4
-
5
- PROP_ELEMENTS = %w(p1 p2 p3)
6
-
7
3
  describe OmfCommon::Message do
8
- describe "when constructing valid messages" do
9
- it "must return a create or configure XML element without failing" do
10
- %w(create configure).each do |msg_name|
11
- message = Message.__send__(msg_name) do |m|
12
-
13
- PROP_ELEMENTS.each_with_index do |prop_element, index|
14
- if index == 0
15
- m.property(prop_element, rand(100))
16
- else
17
- m.property(prop_element, rand(100)) do |p|
18
- p.element('unit', 'test')
19
- p.element('precision', 'test')
20
- end
21
-
22
- end
23
- end
24
-
25
- # Guard element optional
26
- m.element(:guard) do |g|
27
- g.property('p1', 1)
28
- g.property('p2', 2)
29
- end
30
- end
31
- message.valid?.must_equal true
32
- end
4
+ describe "when initialised" do
5
+ before do
6
+ @internal_attr = %w(type operation guard mid ts replyto cid itype)
7
+ @message = OmfCommon::Message.create(:create, { p1: 'p1_value', p2: 'p2_value' }, { rtype: :bob })
33
8
  end
34
9
 
35
- it "must return a request XML element without failing" do
36
- request = Message.request('foo@bar') do |m|
37
- PROP_ELEMENTS.each do |prop_element|
38
- m.property(prop_element, {min_value: 'test', max_value: 'test'})
39
- end
40
- end
41
- request.valid?.must_equal true
10
+ it "must be able to query internal properties" do
11
+ @message.type.must_equal :create
12
+ @message.operation.must_equal :create
13
+ @message.mid.wont_be_nil
14
+ @message.ts.wont_be_nil
42
15
  end
43
16
 
44
- it "must return a release XML element without failing" do
45
- release = Message.release { |v| v.element('resource_id', 'test') }
46
- release.valid?.must_equal true
17
+ it "must be able to get property value" do
18
+ @message[:p1].must_equal 'p1_value'
19
+ @message.read_property(:p1).must_equal 'p1_value'
47
20
  end
48
21
 
49
- it "must return a inform XML element without failing" do
50
- inform = Message.inform('CREATED', '9012c3bc-68de-459a-ac9f-530cc7168e22') do |m|
51
- m.element('resource_id', 'test')
52
- m.element('resource_address', 'test')
53
- PROP_ELEMENTS.each do |prop_element|
54
- m.property(prop_element, { current: 'test', target: 'test'})
55
- end
56
- end
57
- inform.valid?.must_equal true
22
+ it "must be able to set property value" do
23
+ @message[:p1] = 'new_value'
24
+ @message[:p1].must_equal 'new_value'
25
+ @message.write_property(:p2, 'new_value')
26
+ @message[:p2].must_equal 'new_value'
58
27
  end
59
28
 
60
- it "context_id & resource_id shortcut must work too" do
61
- m = Message.inform('CREATED', '9012c3bc-68de-459a-ac9f-530cc7168e22') do |m|
62
- m.element('resource_id', 'test')
29
+ it "must be able to query internal message properties" do
30
+ @internal_attr.each do |name|
31
+ @message.must_respond_to name
63
32
  end
64
- m.resource_id.must_equal 'test'
65
- m.context_id.must_equal '9012c3bc-68de-459a-ac9f-530cc7168e22'
66
33
  end
67
34
 
68
- it "must escape erb code in property" do
69
- m = Message.inform('CREATED', '9012c3bc-68de-459a-ac9f-530cc7168e22') do |m|
70
- m.property('bob', "hello <%= world %>")
71
- m.property('alice', "hello <%= 1 % 2 %>")
72
- end
73
- m.read_property('bob').must_equal "hello <%= world %>"
74
- world = 'world'
75
- m.read_property('bob', binding).must_equal "hello world"
76
- m.read_property('alice', binding).must_equal "hello 1"
35
+ it "must evaluate erb code when read property with evaluate option is true" do
36
+ skip
37
+ @message[:p3] = "1 + 1 = <%= 1 + 1 %>"
38
+ @message[:p4] = "1 + 1 = <%= two %>"
39
+ @message.read_property(:p3, binding).must_equal "1 + 1 = 2"
40
+ @message[:p3].must_equal "1 + 1 = <%= 1 + 1 %>"
41
+ two = 2
42
+ @message[:p4, binding].must_equal "1 + 1 = 2"
43
+ @message[:p4].must_equal "1 + 1 = <%= two %>"
77
44
  end
78
45
 
79
46
  it "must be able to pretty print an app_event message" do
80
- Message.inform('STATUS') do |m|
81
- m.property('status_type', 'APP_EVENT')
82
- m.property('event', 'DONE.OK')
83
- m.property('app', 'app100')
84
- m.property('msg', 'Everything will be OK')
85
- m.property('seq', 1)
86
- end.print_app_event.must_equal "APP_EVENT (app100, #1, DONE.OK): Everything will be OK"
87
- end
88
- end
89
-
90
- describe "when asked to parse a XML element into Message object" do
91
- it "must create the message object correctly " do
92
- xml = Message.create do |m|
93
- m.property('type', 'vm')
94
- m.property('os', 'debian')
95
- m.property('memory', { value: 1024, unit: 'mb', precision: 0 })
96
- m.property('devices', [{ name: 'w0', driver: 'mod_bob'}, { name: 'w1', driver: ['mod1', 'mod2']} ])
97
- m.property('true', true)
98
- m.property('false', false)
99
- m.property('boolean_array', [false, true])
100
- end.canonicalize
101
-
102
- message = Message.parse(xml)
103
-
104
- message.must_be_kind_of Message
105
- message.operation.must_equal :create
106
- message.read_element("property").size.must_equal 7
107
- message.read_content("property[@key='memory']/unit").must_equal 'mb'
108
- message.read_element("property").size.must_equal 7
109
- message.read_property("type").must_equal 'vm'
110
- message.read_property(:type).must_equal 'vm'
111
-
112
- memory = message.read_property(:memory)
113
- memory.must_be_kind_of Hashie::Mash
114
- memory.value.must_equal 1024
115
- memory.unit.must_equal 'mb'
116
- memory.precision.must_equal 0
117
-
118
- devices = message.read_property(:devices)
119
- devices.must_be_kind_of Array
120
- devices.size.must_equal 2
121
- devices.find { |v| v.name == 'w1'}.driver.size.must_equal 2
122
- # Each property iterator
123
- message.each_property do |v|
124
- %w(type os memory devices true false boolean_array).must_include v.attr('key')
125
- end
126
-
127
- message.read_property(:true).must_equal true
128
- message.read_property(:false).must_equal false
129
- message.read_property('boolean_array').must_equal [false, true]
130
- end
131
-
132
- it "must fail if parse an empty xml" do
133
- lambda { Message.parse("") }.must_raise ArgumentError
134
- lambda { Message.parse(nil) }.must_raise ArgumentError
135
- end
136
- end
137
-
138
- describe "when query the message object" do
139
- it "must return nil if content of a property is empty string" do
140
- xml = Message.request do |m|
141
- m.property('type', 'vm')
142
- m.property('empty')
143
- m.element('empty')
144
- end
145
-
146
- xml.read_property('type').must_equal 'vm'
147
- xml.read_property('empty').must_equal nil
148
- xml.read_content('empty').must_equal nil
47
+ @message = OmfCommon::Message.create(:inform,
48
+ { status_type: 'APP_EVENT',
49
+ event: 'DONE.OK',
50
+ app: 'app100',
51
+ msg: 'Everything will be OK',
52
+ seq: 1 },
53
+ { itype: 'STATUS' })
54
+ @message.print_app_event.must_equal "APP_EVENT (app100, #1, DONE.OK): Everything will be OK"
149
55
  end
150
56
  end
151
57
  end
data/test/test_helper.rb CHANGED
@@ -4,9 +4,12 @@ SimpleCov.start { add_filter "/test" }
4
4
  gem 'minitest'
5
5
  require 'minitest/autorun'
6
6
  require 'minitest/pride'
7
+ require 'minitest/spec'
8
+ require 'minitest/mock'
7
9
 
8
10
  require 'omf_common'
9
11
 
12
+ OmfCommon::Message.init(type: :xml)
13
+
10
14
  # Shut up all the loggers
11
15
  Logging.logger.root.clear_appenders
12
-