rfc 0.0.7 → 0.1.0
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 +4 -4
- data/README.md +22 -2
- data/lib/rfc/cpu_time_averager.rb +50 -0
- data/lib/rfc/rif.rb +64 -0
- data/lib/rfc/version.rb +1 -1
- metadata +4 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f978de1d87822212ecd4f4164491cd25c05e19fa7858c6e29d072d521bee1e76
|
4
|
+
data.tar.gz: b357da050dbabf49d475ac54b9fdc0ed8d8ad0aa96c2a17a279886e4ab63b011
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 614d52a87cb62de11bf3ba1188d59ac251816dba957bd4f285c01ac657c2460d513236310b701fd336dc3e0dd982f05d8926e39bc0e8d548ef368e6128c884ec
|
7
|
+
data.tar.gz: 8d9efb9c30bf2bb17d2c71fd61e4f6fe04b39e2e3cc2a20940c16c1d45fa72b1e05eacc98a93b58d5f2c753e450dde35bd3c56b49cca7740b84e47ea4cd2db74
|
data/README.md
CHANGED
@@ -2,9 +2,10 @@
|
|
2
2
|
|
3
3
|
A collection of RSpec formatters.
|
4
4
|
|
5
|
-
## RSpec Insta-Failing Formatter (Rif, Riff)
|
6
5
|
|
7
|
-
|
6
|
+
## RSpec Insta-Failing Formatter (`Rif`, `Riff`)
|
7
|
+
|
8
|
+
This formatter was originally developed for running large test suites in a
|
8
9
|
continuous integration environment, where the runs are non-interactive
|
9
10
|
and the output is saved to a file/stream of some kind.
|
10
11
|
It has the following features;
|
@@ -12,6 +13,23 @@ It has the following features;
|
|
12
13
|
- Immediate error/failure reporting
|
13
14
|
- Timestamped percentage progress output
|
14
15
|
- No output overwrites or terminal manipulation
|
16
|
+
- Optionally reports system statistics
|
17
|
+
|
18
|
+
To assist in diagnosing test failures caused by resource exhaustion,
|
19
|
+
`Rif` can output the following additional statistics:
|
20
|
+
|
21
|
+
- Ruby object space stats: number of objects total and free
|
22
|
+
- System memory stats: memory and swap used, free and total
|
23
|
+
- CPU stats: average CPU load during test suite execution
|
24
|
+
|
25
|
+
To enable object space stastistics reporting, add to your `spec_helper.rb`:
|
26
|
+
|
27
|
+
Rfc::Rif.output_object_space_stats = true
|
28
|
+
|
29
|
+
To enable memory and CPU statistics reporting, add to your `spec_helper.rb`:
|
30
|
+
|
31
|
+
Rfc::Rif.output_system_load = true
|
32
|
+
|
15
33
|
|
16
34
|
## Announce Formatter (Announce)
|
17
35
|
|
@@ -23,11 +41,13 @@ by global test setup code as well as a specific test, or by multiple tests.
|
|
23
41
|
This formatter reports failures at the end of the test run, like
|
24
42
|
RSpec's documentation formatter does.
|
25
43
|
|
44
|
+
|
26
45
|
## Announce Insta-Failing Formatter (Aif, AIF)
|
27
46
|
|
28
47
|
This is the announce formatter with insta-fail feature. It reports
|
29
48
|
failures as soon as they happen, after each example is executed.
|
30
49
|
|
50
|
+
|
31
51
|
## License
|
32
52
|
|
33
53
|
MIT
|
@@ -0,0 +1,50 @@
|
|
1
|
+
module Rfc
|
2
|
+
class CpuTimeAverager
|
3
|
+
Sample = Struct.new(
|
4
|
+
:user, :nice, :system, :idle, :iowait, :irq, :softirq, :steal,
|
5
|
+
:guest, :guest_nice,
|
6
|
+
)
|
7
|
+
|
8
|
+
def initialize
|
9
|
+
@samples = []
|
10
|
+
end
|
11
|
+
|
12
|
+
def sample
|
13
|
+
# https://www.linuxhowtos.org/manpages/5/proc.htm
|
14
|
+
IO.readlines('/proc/stat').each do |line|
|
15
|
+
if line =~ /^cpu/
|
16
|
+
_, user, nice, system, idle, iowait, irq, softirq, steal,
|
17
|
+
guest, guest_nice = line.split.map(&:to_i)
|
18
|
+
@samples << [Time.now, Sample.new(
|
19
|
+
user, nice, system, idle, iowait, irq, softirq, steal,
|
20
|
+
guest, guest_nice,
|
21
|
+
)]
|
22
|
+
break
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
threshold = Time.now - 10
|
27
|
+
while @samples.length > 2 && @samples.first.first < threshold
|
28
|
+
@samples.shift
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def enough?
|
33
|
+
@samples.last.first - @samples.first.first >= 2
|
34
|
+
end
|
35
|
+
|
36
|
+
def first
|
37
|
+
@samples.first
|
38
|
+
end
|
39
|
+
|
40
|
+
def last
|
41
|
+
@samples.last
|
42
|
+
end
|
43
|
+
|
44
|
+
%i(user nice system idle iowait irq softirq steal guest guest_nice).each do |attr|
|
45
|
+
define_method("#{attr}_delta") do
|
46
|
+
last.last.send(attr) - first.last.send(attr)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
data/lib/rfc/rif.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
require 'rspec/core'
|
2
|
+
require 'rfc/cpu_time_averager'
|
2
3
|
RSpec::Support.require_rspec_core "formatters/base_text_formatter"
|
3
4
|
|
4
5
|
module Rfc
|
@@ -15,6 +16,8 @@ class Rif < RSpec::Core::Formatters::BaseTextFormatter
|
|
15
16
|
# ObjectSpace statistics are generally not available on JRuby:
|
16
17
|
# RuntimeError (ObjectSpace is disabled; each_object will only work with Class, pass -X+O to enable)
|
17
18
|
attr_accessor :output_object_space_stats
|
19
|
+
|
20
|
+
attr_accessor :output_system_load
|
18
21
|
end
|
19
22
|
self.heartbeat_interval = 10
|
20
23
|
|
@@ -53,6 +56,12 @@ class Rif < RSpec::Core::Formatters::BaseTextFormatter
|
|
53
56
|
end
|
54
57
|
|
55
58
|
def report_progress
|
59
|
+
if total_count == 0
|
60
|
+
# When a test suite has no examples or they are all filtered out,
|
61
|
+
# there is no meaningful progress to report.
|
62
|
+
return
|
63
|
+
end
|
64
|
+
|
56
65
|
this_percent = @completed_count * 100 / total_count
|
57
66
|
if @reported_percent != this_percent || @reported_at.nil? ||
|
58
67
|
Time.now-@reported_at > self.class.heartbeat_interval
|
@@ -69,6 +78,9 @@ class Rif < RSpec::Core::Formatters::BaseTextFormatter
|
|
69
78
|
if self.class.output_object_space_stats
|
70
79
|
progress_msg += "; objects: #{ObjectSpace.count_objects[:TOTAL]} total, #{ObjectSpace.count_objects[:FREE]} free"
|
71
80
|
end
|
81
|
+
if self.class.output_system_load
|
82
|
+
progress_msg += "\n#{system_load_msg}"
|
83
|
+
end
|
72
84
|
output.puts progress_msg
|
73
85
|
@reported_percent = this_percent
|
74
86
|
@reported_at = Time.now
|
@@ -77,5 +89,57 @@ class Rif < RSpec::Core::Formatters::BaseTextFormatter
|
|
77
89
|
|
78
90
|
def dump_failures(notification)
|
79
91
|
end
|
92
|
+
|
93
|
+
private
|
94
|
+
|
95
|
+
def system_load_msg
|
96
|
+
stats = {}
|
97
|
+
IO.readlines('/proc/meminfo').each do |line|
|
98
|
+
measure, value, unit = line.split
|
99
|
+
value = value.to_i
|
100
|
+
if value != 0
|
101
|
+
if unit != 'kB'
|
102
|
+
return "Unexpected unit: #{unit} for #{line}"
|
103
|
+
end
|
104
|
+
value = value * 1024
|
105
|
+
measure.sub!(/:$/, '')
|
106
|
+
stats[measure] = value
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
mem_used = stats['MemTotal'] - stats['MemFree'] - stats['Buffers'] - stats['Cached']
|
111
|
+
swap_used = stats['SwapTotal'] - stats['SwapFree']
|
112
|
+
buf_used = stats['Buffers'] + stats['Cached']
|
113
|
+
total = stats['MemTotal']
|
114
|
+
swap = stats['SwapTotal']
|
115
|
+
avail = stats['MemFree'] + stats['Buffers'] + stats['Cached']
|
116
|
+
|
117
|
+
msg = "Memory: #{m(mem_used)} RAM + #{m(swap_used)} swap used, #{m(buf_used)} buf, #{m(total)} RAM + #{m(swap)} swap total, #{m(avail)} avail"
|
118
|
+
|
119
|
+
@cpu_time_averager ||= CpuTimeAverager.new
|
120
|
+
@cpu_time_averager.sample
|
121
|
+
if @cpu_time_averager.enough?
|
122
|
+
all = @cpu_time_averager.user_delta +
|
123
|
+
@cpu_time_averager.nice_delta +
|
124
|
+
@cpu_time_averager.system_delta +
|
125
|
+
@cpu_time_averager.irq_delta +
|
126
|
+
@cpu_time_averager.iowait_delta +
|
127
|
+
@cpu_time_averager.idle_delta
|
128
|
+
used = ((@cpu_time_averager.user_delta +
|
129
|
+
@cpu_time_averager.nice_delta +
|
130
|
+
@cpu_time_averager.system_delta +
|
131
|
+
@cpu_time_averager.irq_delta) * 100.0 / all).round
|
132
|
+
idle = (@cpu_time_averager.idle_delta * 100 / all).round
|
133
|
+
iowait = (@cpu_time_averager.iowait_delta * 100 / all).round
|
134
|
+
|
135
|
+
msg += "\nCPU: %2d%% used, %2d%% iowait, %2d%% idle" % [used, iowait, idle]
|
136
|
+
end
|
137
|
+
|
138
|
+
msg
|
139
|
+
end
|
140
|
+
|
141
|
+
def m(value)
|
142
|
+
"#{(value / 1024.0 / 1024).round}M"
|
143
|
+
end
|
80
144
|
end
|
81
145
|
end
|
data/lib/rfc/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rfc
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0
|
4
|
+
version: 0.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Oleg Pudeyev
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2020-03-
|
11
|
+
date: 2020-03-24 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rspec-core
|
@@ -35,6 +35,7 @@ files:
|
|
35
35
|
- lib/rfc.rb
|
36
36
|
- lib/rfc/aif.rb
|
37
37
|
- lib/rfc/announce.rb
|
38
|
+
- lib/rfc/cpu_time_averager.rb
|
38
39
|
- lib/rfc/rif.rb
|
39
40
|
- lib/rfc/riff.rb
|
40
41
|
- lib/rfc/version.rb
|
@@ -61,5 +62,5 @@ requirements: []
|
|
61
62
|
rubygems_version: 3.1.2
|
62
63
|
signing_key:
|
63
64
|
specification_version: 4
|
64
|
-
summary: rfc-0.0
|
65
|
+
summary: rfc-0.1.0
|
65
66
|
test_files: []
|