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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: c2bd98f4ee027dedf465a06422cd238ddce586defb49eb2ca864c79975c88d5b
4
- data.tar.gz: d8f3f0d13c12fb1f75778e9f4612b9cce2c07ea5c4481131658909f42586e619
3
+ metadata.gz: f978de1d87822212ecd4f4164491cd25c05e19fa7858c6e29d072d521bee1e76
4
+ data.tar.gz: b357da050dbabf49d475ac54b9fdc0ed8d8ad0aa96c2a17a279886e4ab63b011
5
5
  SHA512:
6
- metadata.gz: 023c98057230d614c70be9ec22765afc4d04a2fc49908ebb7b0e53541a98db9d3e521a1cd58863b482bdaa0f4190cc286e695d7672ff632914338d8d39aae5ac
7
- data.tar.gz: 1c862442efc54a7b507044824b0d8519e48c9c4a989b2fe8d056f66cbd0c8c93ce120128feeb7f88c29810ad8de74f1905527e2ca9d2f0dd02289d3e0a1ef039
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
- RIFF was originally developed for running large test suites in a
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
@@ -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
@@ -1,3 +1,3 @@
1
1
  module Rfc
2
- VERSION = '0.0.7'.freeze
2
+ VERSION = '0.1.0'.freeze
3
3
  end
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.7
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-08 00:00:00.000000000 Z
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.7
65
+ summary: rfc-0.1.0
65
66
  test_files: []