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