rbsim 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (71) hide show
  1. checksums.yaml +7 -0
  2. data/.hgignore +6 -0
  3. data/.rspec +2 -0
  4. data/Gemfile +12 -0
  5. data/Gemfile.lock +66 -0
  6. data/LICENSE.txt +674 -0
  7. data/README.md +960 -0
  8. data/TODO +28 -0
  9. data/basic_sim.rb +62 -0
  10. data/fast-tcpn.rb +3 -0
  11. data/lib/rbsim.rb +14 -0
  12. data/lib/rbsim/dsl.rb +30 -0
  13. data/lib/rbsim/dsl/infrastructure.rb +48 -0
  14. data/lib/rbsim/dsl/mapping.rb +32 -0
  15. data/lib/rbsim/dsl/process.rb +129 -0
  16. data/lib/rbsim/dsl/program.rb +10 -0
  17. data/lib/rbsim/experiment.rb +110 -0
  18. data/lib/rbsim/hlmodel.rb +25 -0
  19. data/lib/rbsim/hlmodel/infrastructure.rb +116 -0
  20. data/lib/rbsim/hlmodel/mapping.rb +5 -0
  21. data/lib/rbsim/hlmodel/process.rb +152 -0
  22. data/lib/rbsim/numeric_units.rb +107 -0
  23. data/lib/rbsim/simulator.rb +184 -0
  24. data/lib/rbsim/statistics.rb +77 -0
  25. data/lib/rbsim/tokens.rb +146 -0
  26. data/lib/rbsim/version.rb +3 -0
  27. data/new_process.rb +49 -0
  28. data/rbsim.gemspec +42 -0
  29. data/show_readme.rb +15 -0
  30. data/sim.rb +142 -0
  31. data/sim_bamboo.rb +251 -0
  32. data/sim_process.rb +83 -0
  33. data/sim_process_dsl.rb +58 -0
  34. data/spec/dsl/infrastructure_nets_spec.rb +39 -0
  35. data/spec/dsl/infrastructure_nodes_spec.rb +72 -0
  36. data/spec/dsl/infrastructure_routes_spec.rb +44 -0
  37. data/spec/dsl/mapping_spec.rb +70 -0
  38. data/spec/dsl/process_spec.rb +56 -0
  39. data/spec/dsl/program_spec.rb +36 -0
  40. data/spec/dsl_and_hlmodel/new_process_spec.rb +235 -0
  41. data/spec/hlmodel/net_spec.rb +112 -0
  42. data/spec/hlmodel/process_spec.rb +242 -0
  43. data/spec/hlmodel/route_spec.rb +47 -0
  44. data/spec/hlmodel/routes_spec.rb +44 -0
  45. data/spec/integration/basic_simulation_spec.rb +104 -0
  46. data/spec/integration/net_spec.rb +44 -0
  47. data/spec/integration/process_spec.rb +117 -0
  48. data/spec/integration/rbsim_spec.rb +40 -0
  49. data/spec/simulator/logger_spec.rb +35 -0
  50. data/spec/simulator/stats_spec.rb +93 -0
  51. data/spec/spec_helper.rb +26 -0
  52. data/spec/statistics_spec.rb +300 -0
  53. data/spec/tcpn/add_route_spec.rb +55 -0
  54. data/spec/tcpn/cpu_spec.rb +53 -0
  55. data/spec/tcpn/map_data_spec.rb +37 -0
  56. data/spec/tcpn/network_spec.rb +163 -0
  57. data/spec/tcpn/register_event_spec.rb +48 -0
  58. data/spec/tcpn/route_to_self_spec.rb +53 -0
  59. data/spec/tcpn/stats_spec.rb +77 -0
  60. data/spec/tokens/data_queue_obsolete.rb +121 -0
  61. data/spec/tokens/data_queue_spec.rb +111 -0
  62. data/spec/units_spec.rb +48 -0
  63. data/tcpn/model.rb +6 -0
  64. data/tcpn/model/add_route.rb +78 -0
  65. data/tcpn/model/application.rb +250 -0
  66. data/tcpn/model/cpu.rb +75 -0
  67. data/tcpn/model/map_data.rb +42 -0
  68. data/tcpn/model/network.rb +108 -0
  69. data/tcpn/model/register_event.rb +89 -0
  70. data/tcpn/model/stats.rb +46 -0
  71. metadata +221 -0
@@ -0,0 +1,242 @@
1
+ require 'spec_helper'
2
+
3
+ describe RBSim::HLModel::Process do
4
+ let :block do
5
+ Proc.new do
6
+ end
7
+ end
8
+
9
+ subject do
10
+ process = RBSim::HLModel::Process.new(:test_process)
11
+ process.node = :node01
12
+ process
13
+ end
14
+
15
+ its(:name){ should eq :test_process }
16
+
17
+
18
+ context "not assigned to node" do
19
+ subject do
20
+ process = RBSim::HLModel::Process.new(:not_assigned_process)
21
+ process
22
+ end
23
+ it "raises error and does not serve system events" do
24
+ subject.enqueue_event :delay_for, 100
25
+ expect { subject.serve_system_event :delay_for }.to raise_error RuntimeError
26
+ end
27
+ it "raises error and does not serve user events" do
28
+ subject.on_event :data do
29
+ end
30
+ subject.enqueue_event :data
31
+ expect { subject.serve_user_event }.to raise_error RuntimeError
32
+ end
33
+ end
34
+
35
+ # Here is basic usage example
36
+ it "serves user events in order" do
37
+ subject.on_event :be_glad do |process, who|
38
+ "I am glad #{who}"
39
+ end
40
+ subject.on_event :be_happy do |process, who|
41
+ "I am happy #{who}"
42
+ end
43
+ subject.enqueue_event :be_happy, "Jack"
44
+ subject.enqueue_event :be_glad, "John"
45
+ subject.enqueue_event :be_happy, "John"
46
+ expect(subject.serve_user_event).to eq "I am happy Jack"
47
+ expect(subject.serve_user_event).to eq "I am glad John"
48
+ expect(subject.serve_user_event).to eq "I am happy John"
49
+ end
50
+
51
+ it "serves system events" do
52
+ sysevent1 = subject.system_event_names[0]
53
+ sysevent2 = subject.system_event_names[1]
54
+ subject.enqueue_event sysevent1, block: block, param2: 123
55
+ subject.enqueue_event sysevent2, time: 1000
56
+ expect(subject.serve_system_event sysevent1).
57
+ to eq({ name: sysevent1, args: { block: block, param2: 123 } })
58
+ expect(subject.serve_system_event sysevent2).
59
+ to eq({ name: sysevent2, args: { time: 1000 } })
60
+ end
61
+
62
+ it "has generic event handler for :data_received event" do
63
+ data = "for this test anything representing received data"
64
+ subject.enqueue_event :data_received, data
65
+ expect(subject.has_event? :data_received).to be true
66
+ expect{ subject.serve_user_event }.not_to raise_error
67
+ end
68
+
69
+ context "with program name given" do
70
+ subject { RBSim::HLModel::Process.new(:test_process, :apache_webserver) }
71
+ its(:program){ should eq :apache_webserver }
72
+ end
73
+
74
+ describe "#on_event" do
75
+ it "registers new event handler" do
76
+ expect {
77
+ subject.on_event :example_event, &block
78
+ }.to change(subject, :handlers_size).by(1)
79
+ end
80
+ end
81
+
82
+ describe "#enqueue_event" do
83
+ it "puts user event in event queue" do
84
+ subject.on_event :example_event, &block
85
+ expect {
86
+ subject.enqueue_event :example_event, param1: 123, param2: 345
87
+ }.to change(subject, :event_queue_size).by(1)
88
+ end
89
+ it "puts system event in event queue" do
90
+ system_event = subject.system_event_names.first
91
+ expect {
92
+ subject.enqueue_event system_event
93
+ }.to change(subject, :event_queue_size).by(1)
94
+ end
95
+ it "does not enqueue user event if has no handler" do
96
+ expect {
97
+ subject.enqueue_event :nonexistent_event, params: 23
98
+ }.to raise_error RuntimeError
99
+ end
100
+ end
101
+
102
+
103
+ describe "#serve_user_event" do
104
+ before :each do
105
+ subject.on_event :example_event, &block
106
+ end
107
+ it "serves first event from queue calling event handler" do
108
+ expect(block).to receive(:call).with(subject, { param1: 123, param2: 345 })
109
+ subject.enqueue_event :example_event, param1: 123, param2: 345
110
+ subject.serve_user_event
111
+ end
112
+ it "removes served event from queue" do
113
+ subject.enqueue_event :example_event
114
+ expect{ subject.serve_user_event }.to change(subject, :event_queue_size).by(-1)
115
+ end
116
+ it "refuses to serve system event" do
117
+ system_event = subject.system_event_names.first
118
+ subject.enqueue_event system_event
119
+ expect { subject.serve_user_event }.to raise_error RuntimeError
120
+ end
121
+ end
122
+
123
+ describe "#serve_system_event" do
124
+ let(:sysevent1){ subject.system_event_names[0] }
125
+ let(:sysevent2){ subject.system_event_names[1] }
126
+ it "serves first event from queue" do
127
+ subject.enqueue_event sysevent1, param1: 123, param2: 345
128
+ expect(subject.serve_system_event sysevent1).to eq({name: sysevent1, args: { param1: 123, param2: 345 } })
129
+ end
130
+ it "removes served event from queue" do
131
+ subject.enqueue_event sysevent1
132
+ expect{ subject.serve_system_event sysevent1 }.to change(subject, :event_queue_size).by(-1)
133
+ end
134
+ it "refuses to serve user event" do
135
+ subject.on_event :user_event do
136
+ end
137
+ subject.enqueue_event :user_event
138
+ expect { subject.serve_system_event :user_event}.to raise_error RuntimeError
139
+ end
140
+ it "raises error when event names do not match" do
141
+ subject.enqueue_event sysevent1
142
+ subject.enqueue_event sysevent2
143
+ expect{ subject.serve_system_event sysevent2 }.to raise_error RuntimeError
144
+ end
145
+
146
+ end
147
+
148
+ describe "#has_event?" do
149
+ before :each do
150
+ subject.on_event :example_event, &block
151
+ end
152
+
153
+ context "without event name" do
154
+ it "is true if user event is first in event queue" do
155
+ subject.enqueue_event :example_event
156
+ expect(subject.has_event?).to be true
157
+ end
158
+
159
+ it "is false if event queue is empty" do
160
+ expect(subject.has_event?).to be false
161
+ end
162
+
163
+ it "is true if system event is first in queue" do
164
+ system_event = subject.system_event_names.first
165
+ subject.enqueue_event system_event
166
+ expect(subject.has_event?).to be true
167
+ end
168
+ end
169
+
170
+ context "with event name" do
171
+ it "is false if event queue is empty" do
172
+ expect(subject.has_event? :example_event).to be false
173
+ end
174
+
175
+ it "is true if user event with given name is first in event queue" do
176
+ subject.enqueue_event :example_event
177
+ expect(subject.has_event? :example_event).to be true
178
+ end
179
+
180
+ it "is true if system event with given name is first in event queue" do
181
+ system_event = subject.system_event_names.first
182
+ subject.enqueue_event system_event
183
+ expect(subject.has_event? system_event).to be true
184
+ end
185
+
186
+ it "is false if user event with given name is not first in event queue" do
187
+ subject.enqueue_event :example_event
188
+ expect(subject.has_event? :other_event).to be false
189
+ end
190
+
191
+ it "is false if system event with given name is not first in event queue" do
192
+ system_event = subject.system_event_names[0]
193
+ other_system_event = subject.system_event_names[1]
194
+ subject.enqueue_event system_event
195
+ expect(subject.has_event? other_system_event).to be false
196
+ end
197
+ end
198
+ end
199
+
200
+ describe "#has_user_event?" do
201
+ before :each do
202
+ subject.on_event :example_event, &block
203
+ end
204
+
205
+ it "is true if user event is first in event queue" do
206
+ subject.enqueue_event :example_event
207
+ expect(subject.has_user_event?).to be true
208
+ end
209
+
210
+ it "is false if event queue is empty" do
211
+ expect(subject.has_user_event?).to be false
212
+ end
213
+
214
+ it "is false if system event is first in queue" do
215
+ system_event = subject.system_event_names.first
216
+ subject.enqueue_event system_event
217
+ expect(subject.has_user_event?).to be false
218
+ end
219
+ end
220
+
221
+ describe "#has_system_event?" do
222
+ before :each do
223
+ subject.on_event :example_event, &block
224
+ end
225
+
226
+ it "is false if user event is first in event queue" do
227
+ subject.enqueue_event :example_event
228
+ expect(subject.has_system_event?).to be false
229
+ end
230
+
231
+ it "is false if event queue is empty" do
232
+ expect(subject.has_system_event?).to be false
233
+ end
234
+
235
+ it "is true if system event is first in queue" do
236
+ system_event = subject.system_event_names.first
237
+ subject.enqueue_event system_event
238
+ expect(subject.has_system_event?).to be true
239
+ end
240
+ end
241
+
242
+ end
@@ -0,0 +1,47 @@
1
+ require 'spec_helper'
2
+
3
+ describe "HLModel::Route" do
4
+
5
+ subject { RBSim::HLModel::Route.new :node01, :node02, [ :net01, :net02 ] }
6
+
7
+ describe "#next_net" do
8
+ it "iterates over subsequent net segments" do
9
+ expect(subject.next_net).to eq :net01
10
+ expect(subject.next_net).to eq :net02
11
+ expect{ subject.next_net }.to raise_error StopIteration
12
+ end
13
+ end
14
+
15
+ describe "#has_next_net?" do
16
+ it "is true if there are more nets to go" do
17
+ expect(subject.has_next_net?).to be true
18
+ end
19
+
20
+ it "is false it there are no more nets to go" do
21
+ 2.times { subject.next_net }
22
+ expect(subject.has_next_net?).to be false
23
+ end
24
+ end
25
+
26
+ describe "#reverse!" do
27
+ context "twoway route" do
28
+ subject { RBSim::HLModel::Route.new :node01, :node02, [ :net01, :net02 ], true }
29
+ it "is reversed" do
30
+ src = subject.src
31
+ dst = subject.dst
32
+ subject.reverse!
33
+ expect(subject.src).to eq dst
34
+ expect(subject.dst).to eq src
35
+ expect(subject.next_net).to eq :net02
36
+ expect(subject.next_net).to eq :net01
37
+ end
38
+ end
39
+ context "oneway route" do
40
+ subject { model.routes[0] }
41
+ it "raises error" do
42
+ expect{ subject.reverse! }.to raise_error
43
+ end
44
+ end
45
+ end
46
+
47
+ end
@@ -0,0 +1,44 @@
1
+ require 'spec_helper'
2
+
3
+ describe "HLModel::Routes" do
4
+
5
+ let(:routes) { RBSim::HLModel::Routes.new }
6
+
7
+ let(:oneway) { RBSim::HLModel::Route.new :node01, :node02, [ :net01, :net02 ] }
8
+ let(:twoway) { RBSim::HLModel::Route.new :node07, :node08, [ :net07, :net08 ], true }
9
+
10
+ describe "with oneway route" do
11
+ subject { routes.add oneway; routes }
12
+ it "finds the route" do
13
+ expect(subject.find(:node01, :node02)).to eq oneway
14
+ end
15
+ it "does not find reverse route" do
16
+ expect(subject.find(:node02, :node01)).to be nil
17
+ end
18
+ end
19
+
20
+ describe "with twoway route" do
21
+ subject { routes.add twoway; routes }
22
+ it "finds the route" do
23
+ expect(subject.find(:node07, :node08)).to eq twoway
24
+ end
25
+ it "finds reverse route" do
26
+ expect(subject.find(:node08, :node07)).to eq twoway.reverse!
27
+ end
28
+ end
29
+
30
+ describe "multiple routes for same endpoints" do
31
+ let(:oneway_alternative) { RBSim::HLModel::Route.new :node01, :node02, [ :net05, :net06 ] }
32
+ subject do
33
+ routes.add oneway
34
+ routes.add oneway_alternative
35
+ routes
36
+ end
37
+
38
+ # FIXME: how to test that it is random?
39
+ it "finds one of alternative routes" do
40
+ expect([oneway, oneway_alternative]).to include(subject.find :node01, :node02)
41
+ end
42
+ end
43
+
44
+ end
@@ -0,0 +1,104 @@
1
+ require 'spec_helper'
2
+
3
+ describe "Basic simulation example" do
4
+ let :model do
5
+
6
+ m = RBSim.model do
7
+
8
+ program :wget do |opts|
9
+ sent = 0
10
+ on_event :send do
11
+ cpu do |cpu|
12
+ 150/cpu.performance
13
+ end
14
+ send_data to: opts[:target], size: 1024, type: :request, content: sent
15
+ sent += 1
16
+ delay_for 5*rand
17
+ register_event :send if sent < opts[:count]
18
+ end
19
+
20
+ on_event :data_received do |data|
21
+ #log "Got data #{data} in process #{process.name}"
22
+ stats tag: :request_served, group_name: process.name
23
+ end
24
+
25
+ register_event :send
26
+ end
27
+
28
+ program :apache do
29
+ log "apache starting"
30
+ on_event :data_received do |data|
31
+ stats_start tag: :apache, group_name: process.name
32
+ cpu do |cpu|
33
+ 100*data.size*rand / cpu.performance
34
+ end
35
+ send_data to: data.src, size: data.size * 10, type: :response, content: data.content
36
+ stats_stop tag: :apache, group_name: process.name
37
+ end
38
+ end
39
+
40
+ program :just_load_cpu do
41
+ cpu do |cpu|
42
+ 10
43
+ end
44
+ end
45
+
46
+ program :just_send do
47
+ send_data to: process.name, size: 1024, type: :request, content: :nothing_important
48
+ on_event :data_received do
49
+ end
50
+ end
51
+
52
+ node :desktop do
53
+ cpu 100, tags: { custom_tag: 'cpu_name1' }
54
+ end
55
+
56
+ node :gandalf do
57
+ cpu 1400, tags: { custom_tag: 'cpu_name2' }
58
+ end
59
+
60
+ node :whatever do
61
+ cpu 100
62
+ end
63
+
64
+ new_process :client1, program: :wget, args: { target: :server, count: 10 }, tags: { kind: :client }
65
+ new_process :client2, program: :wget, args: { target: :server, count: 10 }, tags: { kind: :client }
66
+ new_process :server, program: :apache, args: 'apache1', tags: { kind: :server }
67
+ new_process :cpu_loader, program: :just_load_cpu
68
+ new_process :net_loader, program: :just_send
69
+
70
+ net :net01, bw: 1024, tags: { custom_tag: 'name1' }
71
+ net :net02, bw: 510, tags: { custom_tag: 'name2' }
72
+ net :no_tags, bw: 1024
73
+
74
+ route from: :desktop, to: :gandalf, via: [ :net01, :net02 ], twoway: true
75
+ route from: :whatever, to: :whatever, via: [ :no_tags ]
76
+
77
+ put :server, on: :gandalf
78
+ put :client1, on: :desktop
79
+ put :client2, on: :desktop
80
+ put :cpu_loader, on: :whatever
81
+ put :net_loader, on: :whatever
82
+
83
+ end
84
+
85
+ m.data_fragmentation = 2
86
+ m
87
+ end
88
+
89
+ it "serves all requests" do
90
+ expect{ model.run }.to output("0.000: apache starting\n").to_stdout
91
+ expect(model.stats[:application].counters(group_name: :client1, tag: :request_served).to_h.values.flatten.size).to eq 10
92
+ expect(model.stats[:application].counters(group_name: :client2, tag: :request_served).to_h.values.flatten.size).to eq 10
93
+ end
94
+
95
+ it "saves resource stats with tags" do
96
+ model.run
97
+ expect(model.stats[:resources].durations(resource: 'NET', custom_tag: 'name1').to_a).not_to be_empty
98
+ expect(model.stats[:resources].durations(resource: 'NET', custom_tag: 'name2').to_a).not_to be_empty
99
+ expect(model.stats[:resources].durations(resource: 'CPU', custom_tag: 'cpu_name1').to_a).not_to be_empty
100
+ expect(model.stats[:resources].durations(resource: 'CPU', custom_tag: 'cpu_name2').to_a).not_to be_empty
101
+ expect(model.stats[:resources].durations(resource: 'DATAQ WAIT', kind: :client).to_a).not_to be_empty
102
+ expect(model.stats[:resources].durations(resource: 'DATAQ WAIT', kind: :server).to_a).not_to be_empty
103
+ end
104
+ end
@@ -0,0 +1,44 @@
1
+ require 'spec_helper'
2
+
3
+ describe "Network model" do
4
+
5
+ let :model do
6
+ RBSim.model do
7
+ new_process :sender do
8
+ send_data to: :receiver, size: 10, content: "Test message"
9
+ end
10
+
11
+ new_process :receiver do
12
+ end
13
+
14
+ node :sender do
15
+ cpu 1
16
+ end
17
+
18
+ node :receiver do
19
+ cpu 1
20
+ end
21
+
22
+ net :net01, bw: 1024, drop: 1
23
+
24
+ put :sender, on: :sender
25
+ put :receiver, on: :receiver
26
+ route from: :sender, to: :receiver, via: [ :net01 ], toway: true
27
+ end
28
+ end
29
+
30
+ it "checks if a packet should be dropped" do
31
+ # for the sake of cloning we don't have the object that will
32
+ # receive the message at the beginning of simulation
33
+ # twice, because stats calls it too and that also counts
34
+ #
35
+ # http://stackoverflow.com/questions/9800992/how-to-say-any-instance-should-receive-any-number-of-times-in-rspec
36
+ allow(RBSim::HLModel::Net).to receive(:drop?)
37
+ allow_any_instance_of(RBSim::HLModel::Net).to receive(:drop?) { |*a| RBSim::HLModel::Net.drop? *a }
38
+
39
+ # twice in TCPN (arc to data and arc to net) and while collecting statistics
40
+ expect(RBSim::HLModel::Net).to receive(:drop?).exactly(3 * model.data_fragmentation) #.and_return true
41
+ model.run
42
+ end
43
+
44
+ end