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
@@ -0,0 +1,117 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe "Application process activity" do
|
4
|
+
|
5
|
+
module ProcessActivitySpec
|
6
|
+
class CPU
|
7
|
+
attr_accessor :node, :performance
|
8
|
+
def initialize(node, performance)
|
9
|
+
@node, @performance = node, performance
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
class CPUToken < CPU
|
14
|
+
#include TCPN::TokenMethods
|
15
|
+
end
|
16
|
+
|
17
|
+
end
|
18
|
+
|
19
|
+
let :hlmodel do
|
20
|
+
RBSim.dsl do
|
21
|
+
new_process :worker do
|
22
|
+
on_event :data do |volume|
|
23
|
+
delay_for 100
|
24
|
+
cpu do |c|
|
25
|
+
12/c.performance
|
26
|
+
end
|
27
|
+
new_process :child do
|
28
|
+
delay_for 500
|
29
|
+
cpu do |c|
|
30
|
+
450/c.performance
|
31
|
+
end
|
32
|
+
send_data to: :worker, size: 1024, type: :hi, content: 'hello!'
|
33
|
+
end
|
34
|
+
end
|
35
|
+
delay_for 100
|
36
|
+
cpu do |cpu|
|
37
|
+
100/cpu.performance
|
38
|
+
end
|
39
|
+
register_event :data, delay: 200, args: 1000
|
40
|
+
log "a log message here"
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
let(:process_token) { hlmodel.processes[:worker] }
|
46
|
+
let(:data_queue) { RBSim::Tokens::DataQueueToken.new(process_token.name) }
|
47
|
+
|
48
|
+
# FIXME: marking for TCPN should be set by DSL!
|
49
|
+
let :tcpn do
|
50
|
+
process_token.node = :node01
|
51
|
+
cpu_token = ProcessActivitySpec::CPUToken.new(:node01, 10)
|
52
|
+
mapping_token = { ts: 0, val: { process_token.name => process_token.node } }
|
53
|
+
|
54
|
+
|
55
|
+
tcpn = FastTCPN.read 'tcpn/model/application.rb'
|
56
|
+
|
57
|
+
tcpn.add_marking_for 'CPU', cpu_token
|
58
|
+
tcpn.add_marking_for 'process', process_token
|
59
|
+
tcpn.add_marking_for 'mapping', mapping_token
|
60
|
+
tcpn.add_marking_for 'data to receive', data_queue
|
61
|
+
tcpn
|
62
|
+
end
|
63
|
+
|
64
|
+
it "produces correct transition firing sequence and final TCPN marking" do
|
65
|
+
transitions = []
|
66
|
+
tcpn.cb_for :transition, :after do |t, e|
|
67
|
+
transitions << e.transition
|
68
|
+
end
|
69
|
+
|
70
|
+
tcpn.sim
|
71
|
+
|
72
|
+
expect(transitions).to eq ["event::delay_for",
|
73
|
+
"event::cpu",
|
74
|
+
"event::cpu_finished",
|
75
|
+
"event::register_event",
|
76
|
+
"event::log",
|
77
|
+
"event::enqueue_event",
|
78
|
+
"event::serve_user",
|
79
|
+
"event::delay_for",
|
80
|
+
"event::cpu",
|
81
|
+
"event::cpu_finished",
|
82
|
+
"event::new_process",
|
83
|
+
"event::delay_for",
|
84
|
+
"event::cpu",
|
85
|
+
"event::cpu_finished",
|
86
|
+
"event::send_data"
|
87
|
+
]
|
88
|
+
# mapping token should be updated after new
|
89
|
+
# process is created
|
90
|
+
mapping = tcpn.marking_for('mapping').first[:val]
|
91
|
+
expect(mapping[:child]).to eq(:node01)
|
92
|
+
|
93
|
+
# do we have data to send token in proper place?
|
94
|
+
data = tcpn.marking_for('data to send').first[:val]
|
95
|
+
expect(data.dst).to eq(:worker)
|
96
|
+
end
|
97
|
+
|
98
|
+
it "receives data" do
|
99
|
+
data = RBSim::Tokens::DataToken.new(867545, :node01, :process01, to: :child, size: 1234)
|
100
|
+
data.fragments = 1
|
101
|
+
data_queue.put data
|
102
|
+
received_data = false
|
103
|
+
transitions = []
|
104
|
+
tcpn.cb_for :transition, :before do |t, e|
|
105
|
+
transitions << e.transition
|
106
|
+
if e.transition == 'event::serve_user' && e.binding['process'].value.has_event?(:data_received)
|
107
|
+
received_data = true
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
tcpn.sim
|
112
|
+
|
113
|
+
expect(transitions).to include("event::data_received")
|
114
|
+
expect(received_data).to be true
|
115
|
+
end
|
116
|
+
|
117
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
require 'tempfile'
|
4
|
+
|
5
|
+
describe RBSim do
|
6
|
+
|
7
|
+
describe "#model" do
|
8
|
+
it "passes its params to the loaded model" do
|
9
|
+
o = Object.new
|
10
|
+
expect(o).to receive(:to_s)
|
11
|
+
m = RBSim.model name: :apache, run: true do |params|
|
12
|
+
o.to_s
|
13
|
+
expect(params[:name]).to eq :apache
|
14
|
+
expect(params[:run]).to be true
|
15
|
+
end
|
16
|
+
m.hlmodel
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
describe "#read" do
|
21
|
+
it "reads model from file" do
|
22
|
+
file = Tempfile.new "rbsim_model_test"
|
23
|
+
file.write "program :prg do;end"
|
24
|
+
file.close
|
25
|
+
m = RBSim.read file.path
|
26
|
+
file.unlink
|
27
|
+
expect(m.hlmodel.programs).to have_key :prg
|
28
|
+
end
|
29
|
+
|
30
|
+
it "passes params to the model from file as 'params' variable" do
|
31
|
+
file = Tempfile.new "rbsim_model_test"
|
32
|
+
file.write "program params[:name] do;end"
|
33
|
+
file.close
|
34
|
+
m = RBSim.read file.path, name: :prg
|
35
|
+
file.unlink
|
36
|
+
expect(m.hlmodel.programs).to have_key :prg
|
37
|
+
end
|
38
|
+
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe RBSim::Simulator do
|
4
|
+
describe "#logger" do
|
5
|
+
let :model do
|
6
|
+
RBSim.model do
|
7
|
+
new_process :worker do
|
8
|
+
log "start"
|
9
|
+
delay_for 20.seconds
|
10
|
+
log "stop"
|
11
|
+
end
|
12
|
+
|
13
|
+
node :n1 do
|
14
|
+
cpu 100.miliseconds
|
15
|
+
end
|
16
|
+
|
17
|
+
put :worker, on: :n1
|
18
|
+
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
it "logs to default logger" do
|
23
|
+
expect { model.run }.to output("0.000: start\n20.000: stop\n").to_stdout
|
24
|
+
end
|
25
|
+
|
26
|
+
it "logs to custom logger" do
|
27
|
+
logs = []
|
28
|
+
model.logger do |clock, message|
|
29
|
+
logs << { time: clock, message: message }
|
30
|
+
end
|
31
|
+
model.run
|
32
|
+
expect(logs).to eq [ {time: 0, message: "start" }, {time: 20.seconds, message: "stop"} ]
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,93 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe RBSim::Simulator do
|
4
|
+
describe "statistics" do
|
5
|
+
let :model do
|
6
|
+
RBSim.model do
|
7
|
+
new_process :worker do
|
8
|
+
stats_start tag: :work, group_name: 'worker'
|
9
|
+
delay_for 200
|
10
|
+
stats_stop tag: :work, group_name: 'worker'
|
11
|
+
delay_for 100
|
12
|
+
stats tag: :wait, group_name: 'worker'
|
13
|
+
delay_for 100
|
14
|
+
stats tag: :wait, group_name: 'worker'
|
15
|
+
stats_save 31415, tag: :queue_length, group_name: 'worker'
|
16
|
+
end
|
17
|
+
|
18
|
+
node :n1 do
|
19
|
+
cpu 100
|
20
|
+
end
|
21
|
+
|
22
|
+
put :worker, on: :n1
|
23
|
+
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
it "registers events in Statistisc" do
|
28
|
+
expect_any_instance_of(RBSim::Statistics).to receive(:event).with(:start, {tag: :work, group_name: 'worker'}, 0).once
|
29
|
+
expect_any_instance_of(RBSim::Statistics).to receive(:event).with(:stop, {tag: :work, group_name: 'worker'}, 200)
|
30
|
+
expect_any_instance_of(RBSim::Statistics).to receive(:event).with(:stats, {tag: :wait, group_name: 'worker'}, 300)
|
31
|
+
expect_any_instance_of(RBSim::Statistics).to receive(:event).with(:stats, {tag: :wait, group_name: 'worker'}, 400)
|
32
|
+
expect_any_instance_of(RBSim::Statistics).to receive(:event).with(:save, {value: 31415, tags: { tag: :queue_length, group_name: 'worker'} }, 400)
|
33
|
+
model.run
|
34
|
+
end
|
35
|
+
|
36
|
+
describe "net dropping packages" do
|
37
|
+
let :model do
|
38
|
+
RBSim.model do
|
39
|
+
new_process :sender do
|
40
|
+
10.times { send_data to: :receiver, size: 10, content: "Test message" }
|
41
|
+
end
|
42
|
+
|
43
|
+
new_process :receiver do
|
44
|
+
end
|
45
|
+
|
46
|
+
node :sender do
|
47
|
+
cpu 1
|
48
|
+
end
|
49
|
+
|
50
|
+
node :receiver do
|
51
|
+
cpu 1
|
52
|
+
end
|
53
|
+
|
54
|
+
net :net01, bw: 1024, drop: drop
|
55
|
+
|
56
|
+
put :sender, on: :sender
|
57
|
+
put :receiver, on: :receiver
|
58
|
+
route from: :sender, to: :receiver, via: [ :net01 ], toway: true
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
describe "when dropping" do
|
63
|
+
let(:drop) { 1 }
|
64
|
+
|
65
|
+
it "counts dropped" do
|
66
|
+
|
67
|
+
allow(RBSim::Statistics).to receive(:dropped_stats)
|
68
|
+
allow_any_instance_of(RBSim::Statistics).to receive(:event) do |*a|
|
69
|
+
if a[1..-2] == [:stats, {net: :net01, event: 'NET DROP'}]
|
70
|
+
RBSim::Statistics.dropped_stats
|
71
|
+
end
|
72
|
+
end
|
73
|
+
expect(RBSim::Statistics).to receive(:dropped_stats).exactly(10 * model.data_fragmentation).times
|
74
|
+
model.run
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
describe "when not dropping" do
|
79
|
+
let(:drop) { 1 }
|
80
|
+
|
81
|
+
it "counts dropped" do
|
82
|
+
expect_any_instance_of(RBSim::Statistics).not_to receive(:event).with(:stats,
|
83
|
+
{tag: :net01,
|
84
|
+
group_name: 'NET DROP'})
|
85
|
+
model.run
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
end
|
91
|
+
|
92
|
+
end
|
93
|
+
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
require 'simplecov'
|
2
|
+
SimpleCov.start do
|
3
|
+
add_filter '/spec/'
|
4
|
+
end
|
5
|
+
|
6
|
+
require 'rbsim'
|
7
|
+
require 'rspec/its'
|
8
|
+
|
9
|
+
|
10
|
+
# This file was generated by the `rspec --init` command. Conventionally, all
|
11
|
+
# specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`.
|
12
|
+
# Require this file using `require "spec_helper"` to ensure that it is only
|
13
|
+
# loaded once.
|
14
|
+
#
|
15
|
+
# See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
|
16
|
+
RSpec.configure do |config|
|
17
|
+
#config.treat_symbols_as_metadata_keys_with_true_values = true
|
18
|
+
config.run_all_when_everything_filtered = true
|
19
|
+
config.filter_run :focus
|
20
|
+
|
21
|
+
# Run specs in random order to surface order dependencies. If you find an
|
22
|
+
# order dependency and want to debug it, you can fix the order by providing
|
23
|
+
# the seed, which is printed after each run.
|
24
|
+
# --seed 1234
|
25
|
+
config.order = 'random'
|
26
|
+
end
|
@@ -0,0 +1,300 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe RBSim::Statistics do
|
4
|
+
|
5
|
+
describe "with hash based tags" do
|
6
|
+
describe "event counters" do
|
7
|
+
let :stats do
|
8
|
+
stats = RBSim::Statistics.new
|
9
|
+
stats.event :stats, { score: :hit, target: 'small' }, 100
|
10
|
+
stats.event :stats, { score: :hit, target: 'big' }, 300
|
11
|
+
stats.event :stats, { score: :miss, target: 'small' }, 500
|
12
|
+
stats.event :stats, { score: :hit, target: 'small' }, 500
|
13
|
+
stats.event :stats, { score: :miss, target: 'small' }, 500
|
14
|
+
stats.event :stats, { score: :hit, target: 'big' }, 900
|
15
|
+
stats.event :stats, { score: :hit3, target: 'big' }, 900
|
16
|
+
stats.event :stats, { score: :hit, target: 'big', value: 23 }, 900
|
17
|
+
stats.event :stats, { score: :hit, target: 'big', value: 230 }, 900
|
18
|
+
stats.event :stats, { score: :hit5, target: 'huge' }, 950
|
19
|
+
stats.clock = 1000
|
20
|
+
stats
|
21
|
+
end
|
22
|
+
subject { stats }
|
23
|
+
|
24
|
+
it "returns all counters" do
|
25
|
+
counters = subject.counters.to_h
|
26
|
+
expected_counters = {
|
27
|
+
{ score: :hit, target: 'small' } => [ 100, 500 ],
|
28
|
+
{ score: :hit, target: 'big' } => [ 300, 900 ],
|
29
|
+
{ score: :hit, target: 'big', value: 23 } => [ 900 ],
|
30
|
+
{ score: :hit, target: 'big', value: 230 } => [ 900 ],
|
31
|
+
{ score: :miss, target: 'small' } => [ 500, 500 ],
|
32
|
+
{ score: :hit3, target: 'big' } => [ 900 ],
|
33
|
+
{ score: :hit5, target: 'huge' } => [ 950 ],
|
34
|
+
}
|
35
|
+
expect(counters).to eq expected_counters
|
36
|
+
end
|
37
|
+
|
38
|
+
it "filters counters by single tag" do
|
39
|
+
counters = subject.counters(score: :hit).to_h
|
40
|
+
expected_counters = {
|
41
|
+
{ score: :hit, target: 'small' } => [ 100, 500 ],
|
42
|
+
{ score: :hit, target: 'big' } => [ 300, 900 ],
|
43
|
+
{ score: :hit, target: 'big', value: 23 } => [ 900 ],
|
44
|
+
{ score: :hit, target: 'big', value: 230 } => [ 900 ],
|
45
|
+
}
|
46
|
+
expect(counters).to eq expected_counters
|
47
|
+
end
|
48
|
+
|
49
|
+
it "filters counters by two tags" do
|
50
|
+
counters = subject.counters(score: :hit, target: 'big').to_h
|
51
|
+
expected_counters = {
|
52
|
+
{ score: :hit, target: 'big' } => [ 300, 900 ],
|
53
|
+
{ score: :hit, target: 'big', value: 23 } => [ 900 ],
|
54
|
+
{ score: :hit, target: 'big', value: 230 } => [ 900 ],
|
55
|
+
}
|
56
|
+
expect(counters).to eq expected_counters
|
57
|
+
end
|
58
|
+
|
59
|
+
it "filters counters by rare tag" do
|
60
|
+
counters = subject.counters(value: 23).to_h
|
61
|
+
expected_counters = {
|
62
|
+
{ score: :hit, target: 'big', value: 23 } => [ 900 ],
|
63
|
+
}
|
64
|
+
expect(counters).to eq expected_counters
|
65
|
+
end
|
66
|
+
|
67
|
+
it "filters counters by regexp" do
|
68
|
+
counters = subject.counters(score: /hit.?/).to_h
|
69
|
+
expected_counters = {
|
70
|
+
{ score: :hit, target: 'small' } => [ 100, 500 ],
|
71
|
+
{ score: :hit, target: 'big' } => [ 300, 900 ],
|
72
|
+
{ score: :hit, target: 'big', value: 23 } => [ 900 ],
|
73
|
+
{ score: :hit, target: 'big', value: 230 } => [ 900 ],
|
74
|
+
{ score: :hit3, target: 'big' } => [ 900 ],
|
75
|
+
{ score: :hit5, target: 'huge' } => [ 950 ],
|
76
|
+
}
|
77
|
+
expect(counters).to eq expected_counters
|
78
|
+
end
|
79
|
+
|
80
|
+
it "filters counters by any regexp matching any value if key exists" do
|
81
|
+
counters = subject.counters(value: /.*/).to_h
|
82
|
+
expected_counters = {
|
83
|
+
{ score: :hit, target: 'big', value: 23 } => [ 900 ],
|
84
|
+
{ score: :hit, target: 'big', value: 230 } => [ 900 ],
|
85
|
+
}
|
86
|
+
expect(counters).to eq expected_counters
|
87
|
+
end
|
88
|
+
|
89
|
+
end
|
90
|
+
|
91
|
+
describe "correctly computes event duration" do
|
92
|
+
context "for correct data" do
|
93
|
+
let :stats do
|
94
|
+
stats = RBSim::Statistics.new
|
95
|
+
stats.event :start, { tag: :working, name: 'apache' }, 100
|
96
|
+
stats.event :start, { tag: :working, name: 'nginx' }, 100
|
97
|
+
|
98
|
+
stats.event :start, { tag: :request, name: 'apache' }, 200
|
99
|
+
stats.event :stop, { tag: :request, name: 'apache' }, 300
|
100
|
+
stats.event :start, { tag: :request, name: 'nginx' }, 350
|
101
|
+
stats.event :start, { tag: :request, name: 'apache' }, 350
|
102
|
+
stats.event :stop, { tag: :request, name: 'nginx' }, 400
|
103
|
+
stats.event :stop, { tag: :request, name: 'apache' }, 420
|
104
|
+
stats.event :start, { tag: :compute, name: 'apache', mod: :php }, 500
|
105
|
+
stats.event :stop, { tag: :compute, name: 'apache', mod: :php }, 600
|
106
|
+
|
107
|
+
stats.event :stop, { tag: :working, name: 'nginx' }, 850
|
108
|
+
stats.event :stop, { tag: :working, name: 'apache' }, 900
|
109
|
+
stats.clock = 1000
|
110
|
+
|
111
|
+
stats
|
112
|
+
end
|
113
|
+
|
114
|
+
subject { stats }
|
115
|
+
|
116
|
+
it "returns all durations" do
|
117
|
+
durations = subject.durations.to_a
|
118
|
+
expected_durations = [
|
119
|
+
[ { tag: :working, name: 'apache' }, 100, 900 ],
|
120
|
+
[ { tag: :working, name: 'nginx' }, 100, 850 ],
|
121
|
+
[ { tag: :request, name: 'apache' }, 200, 300 ],
|
122
|
+
[ { tag: :request, name: 'apache' }, 350, 420 ],
|
123
|
+
[ { tag: :compute, name: 'apache', mod: :php }, 500, 600 ],
|
124
|
+
[ { tag: :request, name: 'nginx' }, 350, 400 ],
|
125
|
+
]
|
126
|
+
expect(durations).to match_array expected_durations
|
127
|
+
end
|
128
|
+
|
129
|
+
it "filters durations by single tag" do
|
130
|
+
durations = subject.durations(tag: :working).to_a
|
131
|
+
expected_durations = [
|
132
|
+
[ { tag: :working, name: 'apache' }, 100, 900 ],
|
133
|
+
[ { tag: :working, name: 'nginx' }, 100, 850 ],
|
134
|
+
]
|
135
|
+
expect(durations).to match_array expected_durations
|
136
|
+
end
|
137
|
+
|
138
|
+
it "filters durations by two tags" do
|
139
|
+
durations = subject.durations(tag: :request, name: 'apache').to_a
|
140
|
+
expected_durations = [
|
141
|
+
[ { tag: :request, name: 'apache' }, 200, 300 ],
|
142
|
+
[ { tag: :request, name: 'apache' }, 350, 420 ],
|
143
|
+
]
|
144
|
+
expect(durations).to match_array expected_durations
|
145
|
+
end
|
146
|
+
|
147
|
+
it "filters durations by rare tag" do
|
148
|
+
durations = subject.durations(tag: :compute).to_a
|
149
|
+
expected_durations = [
|
150
|
+
[ { tag: :compute, name: 'apache', mod: :php }, 500, 600 ],
|
151
|
+
]
|
152
|
+
expect(durations).to match_array expected_durations
|
153
|
+
end
|
154
|
+
|
155
|
+
it "filters durations by regexp" do
|
156
|
+
durations = subject.durations(tag: /r/).to_a
|
157
|
+
expected_durations = [
|
158
|
+
[ { tag: :working, name: 'apache' }, 100, 900 ],
|
159
|
+
[ { tag: :working, name: 'nginx' }, 100, 850 ],
|
160
|
+
[ { tag: :request, name: 'apache' }, 200, 300 ],
|
161
|
+
[ { tag: :request, name: 'apache' }, 350, 420 ],
|
162
|
+
[ { tag: :request, name: 'nginx' }, 350, 400 ],
|
163
|
+
]
|
164
|
+
expect(durations).to match_array expected_durations
|
165
|
+
end
|
166
|
+
|
167
|
+
it "filters durations by any regexp matching any value if key exists" do
|
168
|
+
durations = subject.durations(mod: /.*/).to_a
|
169
|
+
expected_durations = [
|
170
|
+
[ { tag: :compute, name: 'apache', mod: :php }, 500, 600 ],
|
171
|
+
]
|
172
|
+
expect(durations).to match_array expected_durations
|
173
|
+
end
|
174
|
+
|
175
|
+
end
|
176
|
+
context "for incorrect data" do
|
177
|
+
let :stats do
|
178
|
+
stats = RBSim::Statistics.new
|
179
|
+
stats.event :start, { tag: :request, name: 'apache' }, 200
|
180
|
+
stats.event :start, { tag: :request, name: 'apache' }, 300
|
181
|
+
stats.event :start, { tag: :request, name: 'apache' }, 400
|
182
|
+
stats.event :stop, { tag: :request, name: 'apache' }, 450
|
183
|
+
stats.event :stop, { tag: :request, name: 'apache' }, 550
|
184
|
+
stats.event :stop, { tag: :request, name: 'apache' }, 650
|
185
|
+
|
186
|
+
stats.clock = 1000
|
187
|
+
|
188
|
+
stats
|
189
|
+
end
|
190
|
+
|
191
|
+
subject { stats }
|
192
|
+
|
193
|
+
it "correctly yields first start with first stop and so on" do
|
194
|
+
durations = subject.durations.to_a
|
195
|
+
expected_durations = [
|
196
|
+
[ { tag: :request, name: 'apache' }, 200, 450 ],
|
197
|
+
[ { tag: :request, name: 'apache' }, 300, 550 ],
|
198
|
+
[ { tag: :request, name: 'apache' }, 400, 650 ],
|
199
|
+
]
|
200
|
+
expect(durations).to match_array expected_durations
|
201
|
+
end
|
202
|
+
end
|
203
|
+
end
|
204
|
+
|
205
|
+
describe "saves reported values" do
|
206
|
+
let :stats do
|
207
|
+
stats = RBSim::Statistics.new
|
208
|
+
|
209
|
+
stats.event :save, { value: 1024, tags: { tag: :queue_length, name: 'apache' } }, 100
|
210
|
+
stats.event :save, { value: 1524, tags: { tag: :queue_length, name: 'apache' } }, 100
|
211
|
+
stats.event :save, { value: 1024, tags: { tag: :queue_length, name: 'nginx' } }, 100
|
212
|
+
stats.event :save, { value: 2048, tags: { tag: :queue_length, name: 'apache' } }, 200
|
213
|
+
stats.event :save, { value: 2048, tags: { tag: :queue_length, name: 'apache', mod: :php } }, 200
|
214
|
+
stats.event :save, { value: 2048, tags: { tag: :queue_length, name: 'nginx' } }, 200
|
215
|
+
stats.event :save, { value: 2048, tags: { tag: :queue_length, name: 'nginx', mod: :php } }, 300
|
216
|
+
stats.event :save, { value: 20, tags: { tag: :wait_time, name: 'nginx' } }, 350
|
217
|
+
stats.event :save, { value: 512, tags: { tag: :queue_length, name: 'apache' } }, 400
|
218
|
+
stats.event :save, { value: 30, tags: { tag: :wait_time, name: 'nginx' } }, 400
|
219
|
+
|
220
|
+
stats.clock = 1000
|
221
|
+
|
222
|
+
stats
|
223
|
+
end
|
224
|
+
|
225
|
+
subject { stats }
|
226
|
+
|
227
|
+
it "returns all values" do
|
228
|
+
values = subject.values.to_a
|
229
|
+
expected_values = [
|
230
|
+
[ { tag: :queue_length, name: 'apache' }, 100, [ 1024, 1524 ] ],
|
231
|
+
[ { tag: :queue_length, name: 'nginx' }, 100, [ 1024 ] ],
|
232
|
+
[ { tag: :queue_length, name: 'apache' }, 200, [ 2048 ] ],
|
233
|
+
[ { tag: :queue_length, name: 'apache', mod: :php }, 200, [ 2048 ] ],
|
234
|
+
[ { tag: :queue_length, name: 'nginx' }, 200, [ 2048 ] ],
|
235
|
+
[ { tag: :queue_length, name: 'nginx', mod: :php }, 300, [ 2048 ] ],
|
236
|
+
[ { tag: :wait_time, name: 'nginx' }, 350, [ 20 ] ],
|
237
|
+
[ { tag: :queue_length, name: 'apache' }, 400, [ 512 ] ],
|
238
|
+
[ { tag: :wait_time, name: 'nginx' }, 400, [ 30 ] ],
|
239
|
+
]
|
240
|
+
expect(values).to match_array expected_values
|
241
|
+
end
|
242
|
+
|
243
|
+
it "filters values by single tag" do
|
244
|
+
values = subject.values(tag: :queue_length).to_a
|
245
|
+
expected_values = [
|
246
|
+
[ { tag: :queue_length, name: 'apache' }, 100, [ 1024, 1524 ] ],
|
247
|
+
[ { tag: :queue_length, name: 'nginx' }, 100, [ 1024 ] ],
|
248
|
+
[ { tag: :queue_length, name: 'apache' }, 200, [ 2048 ] ],
|
249
|
+
[ { tag: :queue_length, name: 'apache', mod: :php }, 200, [ 2048 ] ],
|
250
|
+
[ { tag: :queue_length, name: 'nginx' }, 200, [ 2048 ] ],
|
251
|
+
[ { tag: :queue_length, name: 'nginx', mod: :php }, 300, [ 2048 ] ],
|
252
|
+
[ { tag: :queue_length, name: 'apache' }, 400, [ 512 ] ],
|
253
|
+
]
|
254
|
+
expect(values).to match_array expected_values
|
255
|
+
end
|
256
|
+
|
257
|
+
it "filters values by two tags" do
|
258
|
+
values = subject.values(tag: :queue_length, name: 'apache').to_a
|
259
|
+
expected_values = [
|
260
|
+
[ { tag: :queue_length, name: 'apache' }, 100, [ 1024, 1524 ] ],
|
261
|
+
[ { tag: :queue_length, name: 'apache' }, 200, [ 2048 ] ],
|
262
|
+
[ { tag: :queue_length, name: 'apache', mod: :php }, 200, [ 2048 ] ],
|
263
|
+
[ { tag: :queue_length, name: 'apache' }, 400, [ 512 ] ],
|
264
|
+
]
|
265
|
+
expect(values).to match_array expected_values
|
266
|
+
end
|
267
|
+
|
268
|
+
it "filters values by rare tag" do
|
269
|
+
values = subject.values(mod: :php).to_a
|
270
|
+
expected_values = [
|
271
|
+
[ { tag: :queue_length, name: 'apache', mod: :php }, 200, [ 2048 ] ],
|
272
|
+
[ { tag: :queue_length, name: 'nginx', mod: :php }, 300, [ 2048 ] ],
|
273
|
+
]
|
274
|
+
expect(values).to match_array expected_values
|
275
|
+
end
|
276
|
+
|
277
|
+
it "filters values by regexp" do
|
278
|
+
values = subject.values(name: /^a.*/).to_a
|
279
|
+
expected_values = [
|
280
|
+
[ { tag: :queue_length, name: 'apache' }, 100, [ 1024, 1524 ] ],
|
281
|
+
[ { tag: :queue_length, name: 'apache' }, 200, [ 2048 ] ],
|
282
|
+
[ { tag: :queue_length, name: 'apache', mod: :php }, 200, [ 2048 ] ],
|
283
|
+
[ { tag: :queue_length, name: 'apache' }, 400, [ 512 ] ],
|
284
|
+
]
|
285
|
+
expect(values).to match_array expected_values
|
286
|
+
end
|
287
|
+
|
288
|
+
it "filters values by any regexp matching any value if key exists" do
|
289
|
+
values = subject.values(mod: /.*/).to_a
|
290
|
+
expected_values = [
|
291
|
+
[ { tag: :queue_length, name: 'apache', mod: :php }, 200, [ 2048 ] ],
|
292
|
+
[ { tag: :queue_length, name: 'nginx', mod: :php }, 300, [ 2048 ] ],
|
293
|
+
]
|
294
|
+
expect(values).to match_array expected_values
|
295
|
+
end
|
296
|
+
|
297
|
+
end
|
298
|
+
end
|
299
|
+
|
300
|
+
end
|