rbsim 0.0.3
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.
- 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
|