isono 0.1.0 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,64 @@
1
+
2
+ require File.expand_path('../spec_helper', __FILE__)
3
+
4
+ require 'isono'
5
+ include Isono
6
+
7
+ class HookTest < Isono::NodeModules::Base
8
+ before_connect_hook do
9
+ $pass.shift.should.equal :before_connect
10
+ end
11
+
12
+ after_connect_hook do
13
+ $pass.shift.should.equal :after_connect
14
+ end
15
+
16
+ before_close_hook do
17
+ $pass.shift.should.equal :before_close
18
+ end
19
+
20
+ after_close_hook do
21
+ $pass.shift.should.equal :after_close
22
+ end
23
+ end
24
+
25
+ class MockNode < Isono::Node
26
+ def initialize()
27
+ super(Isono::Manifest.new do
28
+ end)
29
+ end
30
+ end
31
+
32
+ describe Isono::Node do
33
+
34
+ em "connects to AMQP broker" do
35
+ a = MockNode.new
36
+ a.connect('amqp://localhost/') {
37
+ a.amqp_client.should.not.nil?
38
+ a.amqp_client.instance_variable_get(:@connection_status).should.is_a?(Proc)
39
+ EM.next_tick {
40
+ a.close {
41
+ EM.stop
42
+ }
43
+ }
44
+ }
45
+ end
46
+
47
+ em "call node_module hooks" do
48
+ $pass = [:before_connect, :after_connect,
49
+ :before_close, :after_close]
50
+ a = Node.new(Isono::Manifest.new do
51
+ load_module HookTest
52
+ end)
53
+ a.connect('amqp://localhost/') {
54
+ EM.next_tick {
55
+ a.close {
56
+ $pass.size.should.equal 0
57
+ EM.stop
58
+ }
59
+ }
60
+ }
61
+ end
62
+
63
+
64
+ end
@@ -0,0 +1,113 @@
1
+ require File.expand_path('../spec_helper', __FILE__)
2
+
3
+ require 'isono'
4
+
5
+ MM = Isono::ManagerModules
6
+
7
+ describe "ResourceLoader Test" do
8
+
9
+ it "loads manifest block" do
10
+ rm = Isono::ResourceManifest.new('./')
11
+
12
+ Isono::ResourceManifest::Loader.new(rm).instance_eval {
13
+ state_monitor 'Hva::XenInstanceStore::XenMonitor'
14
+ #monitor Hva::XenCapacityMonitor
15
+
16
+ description "resource1"
17
+
18
+ statemachine {
19
+ trans :init, :on_load, :ready
20
+ trans :ready, :on_start, :starting
21
+ trans :starting, :on_online, :running
22
+ trans :running, :on_attach_volume, :attaching_volume
23
+ trans :attaching_volume, :on_back_to_run, :running
24
+ trans :running, :on_stop, :shuttingdown
25
+ trans :shuttingdown, :on_offline, :terminated
26
+ }
27
+
28
+ #entry_state(:running) do
29
+ # resource_graph.find(:connected, my_resource_uuid).each { |res_uuid|
30
+ # on_event :stopped, res_uuid do
31
+ # #do something
32
+ # end
33
+ # }
34
+ #end
35
+
36
+ entry_state(:running) do
37
+ on_event :stop_vm, 'mgr-master' do
38
+ process_event(:on_stop)
39
+ end
40
+
41
+ on_event(:attach_volume, 'storage_node') {
42
+ process_event(:on_attach_volume)
43
+ }
44
+
45
+ task {
46
+ }
47
+ end
48
+
49
+ entry_state(:ready) do
50
+ task do
51
+ # immediatry change the state
52
+ state_monitor.start
53
+ process_event(:on_start)
54
+ end
55
+ end
56
+
57
+ entry_state(:starting) {
58
+ task :rake, 'start_vm'
59
+ }
60
+
61
+ entry_state(:shuttingdown) {
62
+ task :rake, 'stop_vm'
63
+ }
64
+
65
+ entry_state(:attaching_volume) {
66
+ task :rake, 'attach_file_vol'
67
+ }
68
+
69
+ entry_state(:terminated) {
70
+ task do
71
+ state_monitor.stop
72
+ end
73
+ }
74
+
75
+ }
76
+
77
+ rm.stm.should.is_a? Statemachine::Statemachine
78
+
79
+ end
80
+
81
+
82
+
83
+ it "resource instance process" do
84
+
85
+ rm = Isono::ResourceManifest.new('./')
86
+
87
+ Isono::ResourceManifest::Loader.new(rm).instance_eval {
88
+ state_monitor 'Hva::XenInstanceStore::XenMonitor'
89
+ #monitor Hva::XenCapacityMonitor
90
+
91
+ description "resource1"
92
+
93
+ statemachine {
94
+ trans :init, :on_load, :ready
95
+ trans :ready, :on_start, :starting
96
+ trans :starting, :on_online, :running
97
+ trans :running, :on_attach_volume, :attaching_volume
98
+ trans :attaching_volume, :on_back_to_run, :running
99
+ trans :running, :on_stop, :shuttingdown
100
+ trans :shuttingdown, :on_offline, :terminated
101
+ }
102
+ }
103
+
104
+ EM.run {
105
+ Isono::ResourceInstance.start('testuuid', rm, {:amqp_server_uri => URI.parse('amqp://guest:guest@localhost/'),
106
+ })
107
+ EM.add_timer(1) {
108
+ Isono::ResourceInstance.stop
109
+ EM.stop
110
+ }
111
+ }
112
+ end
113
+ end
@@ -0,0 +1,172 @@
1
+
2
+ require File.expand_path('../spec_helper', __FILE__)
3
+
4
+ require 'isono'
5
+
6
+ MM = Isono::NodeModules
7
+ include Isono
8
+
9
+ def client_connect(main_cb, pre_cb=nil, post_cb=nil)
10
+ manifest = Manifest.new(File.expand_path('../', __FILE__)) {
11
+ node_name :cli
12
+ node_instance_id :xxx
13
+
14
+ load_module MM::EventChannel
15
+ load_module MM::RpcChannel
16
+ }
17
+ c = Node.new(manifest)
18
+ pre_cb.call if pre_cb
19
+ c.connect('amqp://localhost/') {
20
+ main_cb.call(c)
21
+ }
22
+ end
23
+
24
+
25
+ def svr_connect(main_cb, pre_cb=nil, post_cb=nil)
26
+ manifest = Manifest.new(File.expand_path('../', __FILE__)) {
27
+ node_name :endpoint
28
+ node_instance_id :xxx
29
+
30
+ load_module MM::EventChannel
31
+ load_module MM::RpcChannel
32
+ }
33
+ c = Node.new(manifest)
34
+ pre_cb.call if pre_cb
35
+ c.connect('amqp://localhost/') {
36
+ main_cb.call(c)
37
+ }
38
+ end
39
+
40
+
41
+ describe Isono::NodeModules::RpcChannel do
42
+ em "creates connection" do
43
+ done = []
44
+ svr_connect(proc{ |c|
45
+ c.close {
46
+ done << 1
47
+ }
48
+ })
49
+
50
+ client_connect(proc {|c|
51
+ c.close {
52
+ done << 1
53
+ }
54
+ })
55
+
56
+ EM.tick_loop {
57
+ if done == [1, 1]
58
+ done.should.equal [1, 1]
59
+ EM.stop
60
+ end
61
+ }
62
+ end
63
+
64
+ em "send async request" do
65
+ svr_connect(proc{|c|
66
+ rpc = MM::RpcChannel.new(c)
67
+ rpc.register_endpoint('endpoint1', Isono::Rack::Map.build { |t|
68
+ t.map('kill') {
69
+ request.args[0].should.equal 'arg1'
70
+ request.args[1].should.equal 'arg2'
71
+ request.args[2].should.equal 'arg3'
72
+
73
+ EM.next_tick { EM.stop }
74
+ response.response({:code=>1})
75
+ }
76
+ })
77
+ })
78
+ client_connect(proc {|c|
79
+ rpc = MM::RpcChannel.new(c)
80
+ req0 = rpc.request('endpoint1', 'kill', 'arg1', "arg2", "arg3") { |req|
81
+ req.on_success { |res|
82
+ req0.ticket.should.equal req.ticket
83
+ res[:code].should.equal 1
84
+ c.close
85
+ }
86
+ }
87
+ }
88
+ )
89
+
90
+ end
91
+
92
+
93
+ em "request timeout" do
94
+ client_connect(proc {|c|
95
+ rpc = MM::RpcChannel.new(c)
96
+ rpc.request('test', 'test1') { |req|
97
+ req.timeout_sec = 0.2
98
+ req.on_error { |e|
99
+ e.should.equal :timeout
100
+ c.close { EM.stop }
101
+ }
102
+ }
103
+ })
104
+ end
105
+
106
+
107
+ em "use Isono::Rack dispatcher" do
108
+ func1_count = 0
109
+ svr_connect(proc{|c|
110
+ rpc = MM::RpcChannel.new(c)
111
+ endpoint1 = Isono::Rack::Map.build { |t|
112
+ t.map('kill') {
113
+ func1_count.should.equal 10
114
+ EM.next_tick { EM.stop }
115
+ }
116
+ t.map('func1') {
117
+ request.args[0].should.equal 'arg1'
118
+ func1_count += 1
119
+ response.response({:code=>1})
120
+ }
121
+ }
122
+
123
+ rpc.register_endpoint('endpoint1', Isono::Rack::ThreadPass.new(endpoint1))
124
+ })
125
+ client_connect(proc {|c|
126
+ rpc = MM::RpcChannel.new(c)
127
+ 10.times { |no|
128
+ req0 = rpc.request('endpoint1', 'func1', 'arg1') { |req|
129
+ req.on_success { |res|
130
+ req0.ticket.should.equal req.ticket
131
+ req0.complete_status.should.equal :success
132
+ #((req0.completed_at - req0.sent_at) > 1.5).should.be.true
133
+ res[:code].should.equal 1
134
+ #puts "#{no} elapesed: #{req0.elapsed_time}"
135
+ if no == 9
136
+ rpc.request('endpoint1', 'kill') do |req|
137
+ req.on_success { |res|
138
+ res[:code].should.equal 1
139
+ }
140
+ end
141
+ end
142
+ }
143
+ }
144
+ }
145
+ })
146
+
147
+ end
148
+
149
+ em "catch remote exception" do
150
+ svr_connect(proc{|c|
151
+ rpc = MM::RpcChannel.new(c)
152
+ rpc.register_endpoint('endpoint1', Isono::Rack::Map.build { |t|
153
+ t.map('kill') {
154
+ raise StandardError, "message"
155
+ response.response({:code=>1})
156
+ }
157
+ })
158
+ }, proc{
159
+ })
160
+ client_connect(proc {|c|
161
+ rpc = MM::RpcChannel.new(c)
162
+ rpc.request('endpoint1', 'kill') { |req|
163
+ req.on_error { |e|
164
+ e.should.equal({:error_type=>'StandardError', :message=>'message'})
165
+ EM.stop
166
+ }
167
+ }
168
+ })
169
+
170
+ end
171
+
172
+ end
@@ -0,0 +1,62 @@
1
+
2
+ require 'rubygems'
3
+
4
+ $LOAD_PATH.unshift File.expand_path('../../lib', __FILE__)
5
+
6
+ require 'bacon'
7
+ #require 'spec'
8
+ require 'isono'
9
+
10
+ class AmqpStub < Isono::Node
11
+ include Isono::Logger
12
+
13
+
14
+ def fork_and_connect(broker_uri='amqp://localhost/', *args, &blk)
15
+ EM.fork_reactor {
16
+ connect(broker_uri, *args, &blk)
17
+ }
18
+ end
19
+
20
+ def connect(broker_uri='amqp://localhost/', *args, &blk)
21
+ super
22
+ end
23
+
24
+ def on_connect
25
+ manifest.managers.each { |a|
26
+ a[0].class.reset_instance
27
+ }
28
+
29
+ super
30
+ end
31
+
32
+ #def on_close
33
+ #end
34
+
35
+
36
+ def mm_instance(mgr_class, *args)
37
+ raise ArgumentError unless mgr_class < Isono::ManagerModules::Base
38
+
39
+ m = mgr_class.instance
40
+ m.agent = self
41
+ m.on_init(args)
42
+ m
43
+ end
44
+ end
45
+
46
+
47
+ def em_fork(main_cb, post_cb=nil)
48
+ fork {
49
+ EM.run {
50
+ main_cb.call
51
+ }
52
+ post_cb.call if post_cb
53
+ }
54
+ end
55
+
56
+ class Bacon::Context
57
+ def em(desc, &blk)
58
+ it(desc) {
59
+ EM.run &blk
60
+ }
61
+ end
62
+ end
@@ -0,0 +1,35 @@
1
+ require File.expand_path('../spec_helper', __FILE__)
2
+
3
+ require 'isono'
4
+
5
+
6
+ describe "ThreadPool Test" do
7
+
8
+ it "create a thread pool" do
9
+ a = Isono::ThreadPool.new
10
+ #a.should Isono::ThreadPool
11
+ end
12
+
13
+ it "call pass() with single thread" do
14
+ a = Isono::ThreadPool.new
15
+ t = 0
16
+ a.pass { t = 1 }
17
+
18
+ t.should eql(1)
19
+ end
20
+
21
+ it "call barrier() with single thread" do
22
+ a = Isono::ThreadPool.new
23
+ t = 0
24
+ a.barrier { t = 1 }
25
+
26
+ t.should eql(1)
27
+ end
28
+
29
+ it "catch exception from barrier()" do
30
+ a = Isono::ThreadPool.new
31
+ lambda {
32
+ a.barrier { raise "Error" }
33
+ }.should raise_error(RuntimeError, "Error")
34
+ end
35
+ end