rfc 0.0.7 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
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: []