rbsim 0.0.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.hgignore +6 -0
- data/.rspec +2 -0
- data/Gemfile +12 -0
- data/Gemfile.lock +66 -0
- data/LICENSE.txt +674 -0
- data/README.md +960 -0
- data/TODO +28 -0
- data/basic_sim.rb +62 -0
- data/fast-tcpn.rb +3 -0
- data/lib/rbsim.rb +14 -0
- data/lib/rbsim/dsl.rb +30 -0
- data/lib/rbsim/dsl/infrastructure.rb +48 -0
- data/lib/rbsim/dsl/mapping.rb +32 -0
- data/lib/rbsim/dsl/process.rb +129 -0
- data/lib/rbsim/dsl/program.rb +10 -0
- data/lib/rbsim/experiment.rb +110 -0
- data/lib/rbsim/hlmodel.rb +25 -0
- data/lib/rbsim/hlmodel/infrastructure.rb +116 -0
- data/lib/rbsim/hlmodel/mapping.rb +5 -0
- data/lib/rbsim/hlmodel/process.rb +152 -0
- data/lib/rbsim/numeric_units.rb +107 -0
- data/lib/rbsim/simulator.rb +184 -0
- data/lib/rbsim/statistics.rb +77 -0
- data/lib/rbsim/tokens.rb +146 -0
- data/lib/rbsim/version.rb +3 -0
- data/new_process.rb +49 -0
- data/rbsim.gemspec +42 -0
- data/show_readme.rb +15 -0
- data/sim.rb +142 -0
- data/sim_bamboo.rb +251 -0
- data/sim_process.rb +83 -0
- data/sim_process_dsl.rb +58 -0
- data/spec/dsl/infrastructure_nets_spec.rb +39 -0
- data/spec/dsl/infrastructure_nodes_spec.rb +72 -0
- data/spec/dsl/infrastructure_routes_spec.rb +44 -0
- data/spec/dsl/mapping_spec.rb +70 -0
- data/spec/dsl/process_spec.rb +56 -0
- data/spec/dsl/program_spec.rb +36 -0
- data/spec/dsl_and_hlmodel/new_process_spec.rb +235 -0
- data/spec/hlmodel/net_spec.rb +112 -0
- data/spec/hlmodel/process_spec.rb +242 -0
- data/spec/hlmodel/route_spec.rb +47 -0
- data/spec/hlmodel/routes_spec.rb +44 -0
- data/spec/integration/basic_simulation_spec.rb +104 -0
- data/spec/integration/net_spec.rb +44 -0
- data/spec/integration/process_spec.rb +117 -0
- data/spec/integration/rbsim_spec.rb +40 -0
- data/spec/simulator/logger_spec.rb +35 -0
- data/spec/simulator/stats_spec.rb +93 -0
- data/spec/spec_helper.rb +26 -0
- data/spec/statistics_spec.rb +300 -0
- data/spec/tcpn/add_route_spec.rb +55 -0
- data/spec/tcpn/cpu_spec.rb +53 -0
- data/spec/tcpn/map_data_spec.rb +37 -0
- data/spec/tcpn/network_spec.rb +163 -0
- data/spec/tcpn/register_event_spec.rb +48 -0
- data/spec/tcpn/route_to_self_spec.rb +53 -0
- data/spec/tcpn/stats_spec.rb +77 -0
- data/spec/tokens/data_queue_obsolete.rb +121 -0
- data/spec/tokens/data_queue_spec.rb +111 -0
- data/spec/units_spec.rb +48 -0
- data/tcpn/model.rb +6 -0
- data/tcpn/model/add_route.rb +78 -0
- data/tcpn/model/application.rb +250 -0
- data/tcpn/model/cpu.rb +75 -0
- data/tcpn/model/map_data.rb +42 -0
- data/tcpn/model/network.rb +108 -0
- data/tcpn/model/register_event.rb +89 -0
- data/tcpn/model/stats.rb +46 -0
- metadata +221 -0
data/sim_bamboo.rb
ADDED
@@ -0,0 +1,251 @@
|
|
1
|
+
require 'rbsim'
|
2
|
+
|
3
|
+
client_no = 1
|
4
|
+
router_no = 100
|
5
|
+
server_no = 10
|
6
|
+
request_per_client = 1000
|
7
|
+
request_gap = 30.miliseconds
|
8
|
+
long_prob = 0.01
|
9
|
+
REQUEST_TIMES = {
|
10
|
+
long: 5000.miliseconds,
|
11
|
+
short: 50.miliseconds
|
12
|
+
}
|
13
|
+
|
14
|
+
model = RBSim.model do
|
15
|
+
|
16
|
+
# gets array of server names and assigns
|
17
|
+
# requests to servers using round-robin, but
|
18
|
+
# next request is assigned to a server only
|
19
|
+
# when previous is served.
|
20
|
+
program :router do |servers|
|
21
|
+
request_queue = []
|
22
|
+
on_event :data_received do |data|
|
23
|
+
if data.type == :request
|
24
|
+
stats :requests, process.name
|
25
|
+
request_queue << data
|
26
|
+
stats_start :request_in_queue, process.name
|
27
|
+
register_event :process_request
|
28
|
+
stats_save request_queue.size, :rqueue_len, process.name
|
29
|
+
elsif data.type == :response
|
30
|
+
servers << data.src
|
31
|
+
send_data to: data.content[:from], size: data.size, type: :response, content: data.content[:content]
|
32
|
+
register_event :process_request
|
33
|
+
else
|
34
|
+
raise "Unknown data type #{data.type} received by #{process.name}"
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
on_event :process_request do
|
39
|
+
unless servers.empty? or request_queue.empty?
|
40
|
+
data = request_queue.shift
|
41
|
+
stats_stop :request_in_queue, process.name
|
42
|
+
server = servers.shift
|
43
|
+
stats_save request_queue.size, :rqueue_len, process.name
|
44
|
+
send_data to: server, size: data.size, type: :request, content: { from: data.src, content: data.content }
|
45
|
+
register_event :process_request unless request_queue.empty?
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
program :webserver do
|
51
|
+
on_event :data_received do |data|
|
52
|
+
if data.type == :request
|
53
|
+
tag = "request_#{data.content[:content][:length]}".to_sym
|
54
|
+
stats tag, process.name
|
55
|
+
stats :request, process.name
|
56
|
+
#log "#{process.name} got request #{data.content[:content][:number]} from #{data.content[:from]} #{data.content[:content][:length]}"
|
57
|
+
cpu do |cpu|
|
58
|
+
# request holds information about its processing time
|
59
|
+
REQUEST_TIMES[data.content[:content][:length]] / cpu.performance
|
60
|
+
end
|
61
|
+
data.content[:content].merge!({ server: process.name })
|
62
|
+
send_data to: data.src, size: data.size * 10, type: :response, content: data.content
|
63
|
+
else
|
64
|
+
raise "Unknown data type #{data.type} received by #{process.name}"
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
# opts are: count, delay, target
|
70
|
+
program :wget do |opts|
|
71
|
+
sent = 0
|
72
|
+
on_event :send do
|
73
|
+
length = if rand < opts[:long_prob]
|
74
|
+
stats :requests_long#, process.name
|
75
|
+
stats_start :requests_long#, process.name
|
76
|
+
:long
|
77
|
+
else
|
78
|
+
stats :requests_short#, process.name
|
79
|
+
stats_start :requests_short#, process.name
|
80
|
+
:short
|
81
|
+
end
|
82
|
+
content = { number: sent, length: length }
|
83
|
+
target = opts[:targets][rand opts[:targets].length]
|
84
|
+
send_data to: target, size: 1024.bytes, type: :request, content: content
|
85
|
+
#log "#{process.name} sent request #{sent} #{length}"
|
86
|
+
stats_start :request, process.name
|
87
|
+
stats_start "request_#{sent}".to_sym, process.name
|
88
|
+
sent += 1
|
89
|
+
register_event :send, delay: opts[:delay] if sent < opts[:count]
|
90
|
+
end
|
91
|
+
|
92
|
+
on_event :data_received do |data|
|
93
|
+
stats_stop :request, process.name
|
94
|
+
stats_stop "requests_#{data.content[:length]}".to_sym#, process.name
|
95
|
+
#log "#{process.name} got response #{data.content[:number]} #{data.content[:server]} #{data.content[:length]}"
|
96
|
+
stats :request_served, process.name
|
97
|
+
stats_stop "request_#{data.content[:number]}".to_sym, process.name
|
98
|
+
end
|
99
|
+
|
100
|
+
register_event :send
|
101
|
+
end
|
102
|
+
|
103
|
+
|
104
|
+
|
105
|
+
|
106
|
+
|
107
|
+
clients = (0..client_no - 1).map { |i| "client#{i}".to_sym }
|
108
|
+
routers = (0..router_no - 1).map { |i| "router#{i}".to_sym }
|
109
|
+
servers = (0..server_no - 1).map { |i| "thin#{i}".to_sym }
|
110
|
+
|
111
|
+
servers.each do |s|
|
112
|
+
node s do
|
113
|
+
cpu 1
|
114
|
+
end
|
115
|
+
new_process s, program: :webserver
|
116
|
+
put s, on: s
|
117
|
+
end
|
118
|
+
|
119
|
+
|
120
|
+
routers.each_with_index do |r, i|
|
121
|
+
new_process r, program: :router, args: servers.clone
|
122
|
+
node r do
|
123
|
+
cpu 1
|
124
|
+
end
|
125
|
+
put r, on: r
|
126
|
+
end
|
127
|
+
|
128
|
+
clients.each do |c|
|
129
|
+
new_process c, program: :wget, args: { count: request_per_client, delay: request_gap, targets: routers, long_prob: long_prob }
|
130
|
+
node c do
|
131
|
+
cpu 1
|
132
|
+
end
|
133
|
+
put c, on: c
|
134
|
+
|
135
|
+
routers.each do |r|
|
136
|
+
route from: c, to: r, via: [ :wan ], twoway: true
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
net :wan, bw: 102400.bps
|
141
|
+
net :lan, bw: 1024000.bps
|
142
|
+
|
143
|
+
|
144
|
+
servers.each do |s|
|
145
|
+
routers.each do |r|
|
146
|
+
route from: r, to: s, via: [ :lan ], twoway: true
|
147
|
+
end
|
148
|
+
end
|
149
|
+
|
150
|
+
end
|
151
|
+
|
152
|
+
prev_seconds = 0
|
153
|
+
model.tcpn.cb_for :clock, :after do |tag, event|
|
154
|
+
print "\b"*40
|
155
|
+
seconds = event.clock.in_seconds.truncate
|
156
|
+
print "Time: #{seconds} sec." if seconds > prev_seconds
|
157
|
+
prev_seconds = seconds
|
158
|
+
end
|
159
|
+
|
160
|
+
puts "Clients\t\t: #{client_no}"
|
161
|
+
puts "Routers\t\t: #{router_no}"
|
162
|
+
puts "Servers\t\t: #{server_no}"
|
163
|
+
puts "Requests\t: #{request_per_client}"
|
164
|
+
puts "Request gap\t: #{request_gap.in_miliseconds}ms"
|
165
|
+
puts "Long req. prob.\t: #{long_prob}"
|
166
|
+
puts "Request times\t: #{REQUEST_TIMES.map{ |n,t| "#{n}: #{t.in_miliseconds}ms"}.join ', '}"
|
167
|
+
puts
|
168
|
+
|
169
|
+
model.run
|
170
|
+
|
171
|
+
#model.stats_print
|
172
|
+
#p model.stats_summary
|
173
|
+
|
174
|
+
=begin
|
175
|
+
puts "======================="
|
176
|
+
puts "Routers' queue length"
|
177
|
+
model.stats_data[:application].values.each do |process, tag, time, values|
|
178
|
+
next unless tag == :rqueue_len
|
179
|
+
puts "#{process}\t#{time}: #{values.last}"
|
180
|
+
end
|
181
|
+
=end
|
182
|
+
puts
|
183
|
+
|
184
|
+
max_rqueue_len = model.stats_summary[:application][:values].map do |process, records|
|
185
|
+
records[:rqueue_len].map{ |time, values| values.last }.max
|
186
|
+
end.max
|
187
|
+
|
188
|
+
max_thinqueue_len = model.stats_summary[:resources][:values]['DATAQ LEN'].map do |process, records|
|
189
|
+
if process.to_s =~ /thin*/
|
190
|
+
records.map{ |time, values| values.last }.max
|
191
|
+
else
|
192
|
+
0
|
193
|
+
end
|
194
|
+
end.max
|
195
|
+
|
196
|
+
#max_thinqueue_wait = model.stats_summary[:resources][:durations]['DATAQ WAIT'].select do |process, time|
|
197
|
+
# process.to_s =~ /thin*/
|
198
|
+
#end.values.max
|
199
|
+
|
200
|
+
max_thinq_wait = nil
|
201
|
+
model.stats_data[:resources].durations do |group, tag, start, stop|
|
202
|
+
next unless group == 'DATAQ WAIT'
|
203
|
+
next unless tag.to_s =~ /thin.*/
|
204
|
+
if max_thinq_wait.nil? || (stop - start) > max_thinq_wait[:time]
|
205
|
+
max_thinq_wait = { time: stop - start, tag: tag }
|
206
|
+
end
|
207
|
+
end
|
208
|
+
|
209
|
+
sum_rqueue_wait = 0
|
210
|
+
max_rqueue_wait = 0
|
211
|
+
model.stats_data[:application].durations do |group, tag, start, stop|
|
212
|
+
next unless group.to_s =~ /router.*/
|
213
|
+
next unless tag == :request_in_queue
|
214
|
+
wait = stop - start
|
215
|
+
sum_rqueue_wait += wait
|
216
|
+
max_rqueue_wait = wait if wait > max_rqueue_wait
|
217
|
+
end
|
218
|
+
|
219
|
+
summary_thinqueue_wait = model.stats_summary[:resources][:durations]['DATAQ WAIT'].select do |process, time|
|
220
|
+
process.to_s =~ /thin*/
|
221
|
+
end.values.reduce(:+)
|
222
|
+
|
223
|
+
puts
|
224
|
+
puts "Max rtr queue len\t: #{max_rqueue_len}"
|
225
|
+
puts "Max rtr queue wait\t: #{max_rqueue_wait.in_miliseconds}ms"
|
226
|
+
puts "Sum rtr queue wait\t: #{sum_rqueue_wait.in_miliseconds}ms"
|
227
|
+
puts "Avg rtr queue wait\t: #{(sum_rqueue_wait/(client_no*request_per_client)).in_miliseconds}ms"
|
228
|
+
puts "Max thin queue len\t: #{max_thinqueue_len}"
|
229
|
+
puts "Max thin queue wait\t: #{max_thinq_wait[:time].in_miliseconds}ms #{max_thinq_wait[:tag]}"
|
230
|
+
puts "Sum thin queue wait\t: #{summary_thinqueue_wait.in_miliseconds}ms"
|
231
|
+
puts "Avg. thin queue wait\t: #{(summary_thinqueue_wait/(client_no*request_per_client)).in_miliseconds}ms"
|
232
|
+
|
233
|
+
long_time = (model.stats_summary[:application][:durations][""][:requests_long] || 0).to_f
|
234
|
+
short_time = (model.stats_summary[:application][:durations][""][:requests_short] || 0).to_f
|
235
|
+
long_count = (model.stats_summary[:application][:counters][""][:requests_long] || 0).to_f
|
236
|
+
short_count = (model.stats_summary[:application][:counters][""][:requests_short] || 0).to_f
|
237
|
+
|
238
|
+
if short_count > 0
|
239
|
+
short_req_avg = short_time / short_count
|
240
|
+
puts "Short req. avg\t\t: #{short_req_avg.in_miliseconds}ms"
|
241
|
+
end
|
242
|
+
|
243
|
+
if long_count > 0
|
244
|
+
long_req_avg = long_time / long_count
|
245
|
+
puts "Long req. avg\t\t: #{long_req_avg.in_miliseconds}ms"
|
246
|
+
end
|
247
|
+
|
248
|
+
file = "rtr_#{router_no}_req_#{request_per_client}.dump"
|
249
|
+
model.stats_save file
|
250
|
+
puts "\nStats saved in #{file}"
|
251
|
+
|
data/sim_process.rb
ADDED
@@ -0,0 +1,83 @@
|
|
1
|
+
require 'hlmodel'
|
2
|
+
require 'tcpn'
|
3
|
+
|
4
|
+
class ProcessToken < RBSim::HLModel::Process
|
5
|
+
include TCPN::TokenMethods
|
6
|
+
end
|
7
|
+
|
8
|
+
class CPU
|
9
|
+
attr_accessor :node, :performance
|
10
|
+
def initialize(node, performance)
|
11
|
+
@node, @performance = node, performance
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
class CPUToken < CPU
|
16
|
+
include TCPN::TokenMethods
|
17
|
+
end
|
18
|
+
|
19
|
+
class Handler
|
20
|
+
def call(*)
|
21
|
+
2345
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def doproc(&block)
|
26
|
+
return block
|
27
|
+
end
|
28
|
+
|
29
|
+
model = TCPN.read 'lib/tcpn/model/application.rb'
|
30
|
+
|
31
|
+
process = ProcessToken.new(:node01)
|
32
|
+
process.on_event :data do |process, args|
|
33
|
+
handler = proc do |cpu|
|
34
|
+
4000 * args[:volume]/cpu.performance
|
35
|
+
end
|
36
|
+
process.register_event :cpu, block: handler
|
37
|
+
process.register_event :delay_for, time: 300
|
38
|
+
if args[:volume] > 10
|
39
|
+
process.register_event :data, volume: args[:volume]/10
|
40
|
+
else
|
41
|
+
constructor = proc do |process, args|
|
42
|
+
puts "===> FORKED <=="
|
43
|
+
process.register_event :delay_for, time: args
|
44
|
+
process.register_event :send_data, volume: args, type: :HTTP_REQUEST
|
45
|
+
end
|
46
|
+
process.register_event :new_process, program: :curl, constructor: constructor, constructor_args: 5000
|
47
|
+
end
|
48
|
+
process.register_event :send_data, volume: args[:volume], type: :response
|
49
|
+
end
|
50
|
+
|
51
|
+
|
52
|
+
#handler = Handler.new
|
53
|
+
handler = Proc.new { |cpu| 1000/cpu.performance } # java error if handler is set to Proc or lambda...
|
54
|
+
#handler = Proc.new { |cpu| 1000 } # java error if handler is set to Proc or lambda...
|
55
|
+
#handler = doproc do |cpu|
|
56
|
+
# 1000/cpu.performance
|
57
|
+
#end
|
58
|
+
process.register_event(:cpu, block: handler )
|
59
|
+
process.register_event(:cpu, block: handler )
|
60
|
+
process.register_event(:data, volume: 1000)
|
61
|
+
#process.register_event(:delay_for, time: 100)
|
62
|
+
model.add_marking_for 'process', process
|
63
|
+
|
64
|
+
cpu = CPUToken.new(:node01, 10)
|
65
|
+
model.add_marking_for 'CPU', cpu
|
66
|
+
|
67
|
+
sim = TCPN.sim model
|
68
|
+
|
69
|
+
sim.cb_for :transition, :after do |t, e|
|
70
|
+
puts "==> FIRING: #{e.transition} #{e.binding.map { |k, v| "#{k}: #{v}"}.join ',' }"
|
71
|
+
#puts model.marking
|
72
|
+
end
|
73
|
+
|
74
|
+
sim.cb_for :clock, :after do |t, e|
|
75
|
+
puts e.clock #if (tick += 1) % 100 == 0
|
76
|
+
end
|
77
|
+
|
78
|
+
sim.run
|
79
|
+
|
80
|
+
puts model.marking
|
81
|
+
|
82
|
+
process = sim.model.marking_for 'process'
|
83
|
+
p process
|
data/sim_process_dsl.rb
ADDED
@@ -0,0 +1,58 @@
|
|
1
|
+
require 'rbsim'
|
2
|
+
require 'tcpn'
|
3
|
+
|
4
|
+
class CPU
|
5
|
+
attr_accessor :node, :performance
|
6
|
+
def initialize(node, performance)
|
7
|
+
@node, @performance = node, performance
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
class CPUToken < CPU
|
12
|
+
include TCPN::TokenMethods
|
13
|
+
end
|
14
|
+
|
15
|
+
hlmodel = RBSim.dsl do
|
16
|
+
new_process :worker do
|
17
|
+
on_event :data do |volume|
|
18
|
+
delay_for 100
|
19
|
+
cpu do |c|
|
20
|
+
12/c.performance
|
21
|
+
end
|
22
|
+
end
|
23
|
+
delay_for 100
|
24
|
+
cpu do |cpu|
|
25
|
+
100/cpu.performance
|
26
|
+
end
|
27
|
+
register_event :data, 1000
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
|
32
|
+
process_token = hlmodel.processes[:worker]
|
33
|
+
process_token.node = :node01
|
34
|
+
cpu_token = CPUToken.new(:node01, 10)
|
35
|
+
|
36
|
+
|
37
|
+
tcpn = TCPN.read 'lib/tcpn/model/application.rb'
|
38
|
+
|
39
|
+
tcpn.add_marking_for 'CPU', cpu_token
|
40
|
+
tcpn.add_marking_for 'process', process_token
|
41
|
+
|
42
|
+
sim = TCPN.sim tcpn
|
43
|
+
|
44
|
+
transitions = []
|
45
|
+
sim.cb_for :transition, :after do |t, e|
|
46
|
+
transitions << e.transition
|
47
|
+
puts "==> FIRING: #{e.transition} #{e.binding.map { |k, v| "#{k}: #{v}"}.join ',' }"
|
48
|
+
#puts model.marking
|
49
|
+
end
|
50
|
+
|
51
|
+
sim.run
|
52
|
+
|
53
|
+
p transitions
|
54
|
+
|
55
|
+
puts " MARKING ".center(70, '=')
|
56
|
+
tcpn.marking.each do |p, m|
|
57
|
+
puts "#{p}: #{m}"
|
58
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe 'RBSim#dsl' do
|
4
|
+
context "model with two nets" do
|
5
|
+
|
6
|
+
let(:model) do
|
7
|
+
RBSim.dsl do
|
8
|
+
|
9
|
+
net :net01, bw: 100, delay: 10
|
10
|
+
net :net02, bw: 1000, delay: 20, drop: 0.3
|
11
|
+
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
it "has two nets" do
|
16
|
+
expect(model.nets.size).to eq 2
|
17
|
+
end
|
18
|
+
|
19
|
+
it "has net called :net01" do
|
20
|
+
expect(model.nets.first.name).to eq :net01
|
21
|
+
end
|
22
|
+
context "net called :net01" do
|
23
|
+
subject { model.nets.first }
|
24
|
+
its(:bw) { should eq(100) }
|
25
|
+
its(:delay) { should eq(10) }
|
26
|
+
end
|
27
|
+
|
28
|
+
it "has net called :net02" do
|
29
|
+
expect(model.nets[1].name).to eq :net02
|
30
|
+
end
|
31
|
+
context "net called :net02" do
|
32
|
+
subject { model.nets[1] }
|
33
|
+
its(:bw) { should eq(1000) }
|
34
|
+
its(:delay) { should eq(20) }
|
35
|
+
its(:drop) { should eq(0.3) }
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
end
|
@@ -0,0 +1,72 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe "RBSim#dsl" do
|
4
|
+
context "model with one empty node" do
|
5
|
+
let(:model) do
|
6
|
+
RBSim.dsl do
|
7
|
+
node :worker do
|
8
|
+
end
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
it "has one node" do
|
13
|
+
expect(model.nodes.size).to eq(1)
|
14
|
+
end
|
15
|
+
|
16
|
+
it "has node called :worker" do
|
17
|
+
expect(model.nodes.first.name).to eq(:worker)
|
18
|
+
end
|
19
|
+
|
20
|
+
it "has node with no CPUs" do
|
21
|
+
expect(model.nodes.first.cpus.size).to eq(0)
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
25
|
+
|
26
|
+
context "model with nodes and CPUs" do
|
27
|
+
let(:model) do
|
28
|
+
RBSim.dsl do
|
29
|
+
|
30
|
+
node :worker1 do
|
31
|
+
cpu 1000
|
32
|
+
cpu 2000
|
33
|
+
end
|
34
|
+
node :worker2 do
|
35
|
+
cpu 200
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
it "has two nodes" do
|
42
|
+
expect(model.nodes.size).to eq 2
|
43
|
+
end
|
44
|
+
|
45
|
+
it "has first node called :worker1" do
|
46
|
+
expect(model.nodes.first.name).to eq :worker1
|
47
|
+
end
|
48
|
+
|
49
|
+
it "has first node with two cpus" do
|
50
|
+
expect(model.nodes.first.cpus.size).to eq 2
|
51
|
+
end
|
52
|
+
|
53
|
+
it "has first node with first cpu with performance 1000" do
|
54
|
+
expect(model.nodes.first.cpus.first.performance).to eq 1000
|
55
|
+
end
|
56
|
+
|
57
|
+
|
58
|
+
it "has first node with second cpu with performance 2000" do
|
59
|
+
expect(model.nodes.first.cpus[1].performance).to eq 2000
|
60
|
+
end
|
61
|
+
|
62
|
+
it "has second node called :worker2" do
|
63
|
+
expect(model.nodes[1].name).to eq :worker2
|
64
|
+
end
|
65
|
+
|
66
|
+
it "has second node with cpu with performance 200" do
|
67
|
+
expect(model.nodes[1].cpus.first.performance).to eq 200
|
68
|
+
end
|
69
|
+
|
70
|
+
end
|
71
|
+
|
72
|
+
end
|