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

Sign up to get free protection for your applications and to get access to all the features.
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
-