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