oneshot_coverage 0.2.2 → 0.3.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: d60a116028cbd90801d1a0883c3bedbdd497c591458f91f9a8e285adf2d85100
4
- data.tar.gz: e5e04c825c36bab7e1405920a9b159d034152f8367fdc6432028269ec494ce0a
3
+ metadata.gz: 2b39908101b69a0d652f8219df289b541f44dd763586f938f714da7990aa801e
4
+ data.tar.gz: 9f71dd33954f1cc1e8e88f46a71cd99800f41afea57197851a9d4e46a9c98c49
5
5
  SHA512:
6
- metadata.gz: cab0f5ece8e3d3c258c3524af5f5ea16d60ff8dcab2f64cc9c7b109008420f29be4fda94c2ac64433b25229966a804a975464134c345bdb19b2c81d4a974d319
7
- data.tar.gz: 6d95ce0b3b5fc2d40cca0827e12805f125ed9d3c168b6a1ce467e021c8627dd1d86f7f006adc845e21fc3c993de58be75da8eb6f78e7e39af23059e31e10405d
6
+ metadata.gz: cf5c1b77da9e902783c2d62b65fb20827b78e7601cf9322ee0ac2802444d08db108a793634ae50a4891e1bf5809acb9203cd22fe7ad29351717f8f92787be56d
7
+ data.tar.gz: 9bad05fb306ccdf11c4ef94e8838f2eb63d24f69444c614439d578a812f2fd8decea5d8e3882256750c17fe8ec9b07f3539385d1c6bb89b01488449f27933a52
data/README.md CHANGED
@@ -35,7 +35,7 @@ Or install it yourself as:
35
35
  OneshotCoverage.configure(
36
36
  target_path: '/base/project/path',
37
37
  logger: OneshotCoverage::Logger::NullLogger.new,
38
- max_emit_at_once: nil, # Flush all when it set to `nil`, which is default
38
+ emit_term: nil, # emit per `emit_term` seconds. It tries to emit per request when `nil`.
39
39
  )
40
40
  OneshotCoverage.start
41
41
  ```
@@ -44,25 +44,44 @@ As default, OneshotCoverage supports 2 logger.
44
44
 
45
45
  - OneshotCoverage::Logger::NullLogger (default)
46
46
  - OneshotCoverage::Logger::StdoutLogger
47
+ - OneshotCoverage::Logger::FileLogger
47
48
 
48
49
  Only required interface is `#post` instance method, so you could implement
49
50
  by yourself easily.
50
51
 
51
52
  ```ruby
52
- class SampleFluentLogger
53
- def initialize
54
- @logger = Fluent::Logger::FluentLogger.new('tag_prefix')
53
+ class FileLogger
54
+ def initialize(log_path)
55
+ @log_path = log_path
55
56
  end
56
57
 
57
- def post(path:, md5_hash:, lineno:)
58
- @logger.post(nil, path: path, md5_hash: md5_hash, lineno: lineno)
58
+ # new_logs: Struct.new(:path, :md5_hash, :lines)
59
+ def post(new_logs)
60
+ current_coverage = fetch
61
+
62
+ new_logs.each do |new_log|
63
+ key = "#{new_log.path}-#{new_log.md5_hash}"
64
+
65
+ logged_lines = current_coverage.fetch(key, [])
66
+ current_coverage[key] = logged_lines | new_log.lines
67
+ end
68
+ save(current_coverage)
69
+ end
70
+
71
+ private
72
+
73
+ def fetch
74
+ JSON.load(File.read(@log_path))
75
+ rescue Errno::ENOENT
76
+ {}
77
+ end
78
+
79
+ def save(data)
80
+ File.write(@log_path, JSON.dump(data))
59
81
  end
60
82
  end
61
83
  ```
62
84
 
63
- Please note that it will retry to send data if `#post` returns falsy value.
64
- Hence, make sure to return `true` if you don't want to retry.
65
-
66
85
  ### Emit logs
67
86
 
68
87
  #### With rack application
@@ -19,29 +19,50 @@ module OneshotCoverage
19
19
  end
20
20
  end
21
21
 
22
+ OneshotLog = Struct.new(:path, :md5_hash, :lines)
23
+
22
24
  class Reporter
23
- def initialize(target_path:, logger:, max_emit_at_once:)
25
+ def initialize(target_path:, logger:, emit_term: nil)
24
26
  @target_path = target_path
25
27
  @logger = logger
26
- @buffer = []
27
- @max_emit_at_once = max_emit_at_once
28
+ @emit_term = emit_term
29
+ if @emit_term
30
+ @next_emit_time = Time.now.to_i + rand(@emit_term)
31
+ end
32
+
28
33
  if defined?(Bundler)
29
34
  @bundler_path = Bundler.bundle_path.to_s
30
35
  end
31
36
  end
32
37
 
33
- def emit
34
- Coverage.result(clear: true, stop: false).
38
+ def emit(force_emit)
39
+ if !force_emit
40
+ if !time_to_emit?
41
+ return true
42
+ end
43
+ end
44
+
45
+ logs =
46
+ Coverage.result(clear: true, stop: false).
35
47
  select { |k, v| is_target?(k, v) }.
36
- flat_map { |k, v| transform(k, v) }.
37
- each { |row| @buffer << row }
48
+ map do |filepath, v|
49
+ OneshotLog.new(relative_path(filepath), md5_hash_for(filepath), v[:oneshot_lines])
50
+ end
51
+
52
+ @logger.post(logs)
53
+ end
38
54
 
39
- @buffer.shift(emit_at_once).each do |row|
40
- # Retry when fail to post
41
- unless @logger.post(row)
42
- @buffer << row
55
+ private
56
+
57
+ def time_to_emit?
58
+ if @emit_term
59
+ if @next_emit_time > Time.now.to_i
60
+ return false # Do not emit until next_emit_time
61
+ else
62
+ @next_emit_time += @emit_term
43
63
  end
44
64
  end
65
+ true
45
66
  end
46
67
 
47
68
  def is_target?(filepath, value)
@@ -51,30 +72,20 @@ module OneshotCoverage
51
72
  true
52
73
  end
53
74
 
54
- def transform(filepath, value)
55
- rel_path = filepath[@target_path.size..-1]
56
- md5_hash =
57
- if md5_hash_cache.key?(filepath)
58
- md5_hash_cache[filepath]
59
- else
60
- md5_hash_cache[filepath] = Digest::MD5.file(filepath).hexdigest
61
- end
62
-
63
- value[:oneshot_lines].map do |line|
64
- {
65
- path: rel_path,
66
- md5_hash: md5_hash,
67
- lineno: line
68
- }
69
- end
75
+ def relative_path(filepath)
76
+ filepath[@target_path.size..-1]
70
77
  end
71
78
 
72
79
  def md5_hash_cache
73
80
  @md5_hash_cache ||= {}
74
81
  end
75
82
 
76
- def emit_at_once
77
- @max_emit_at_once || @buffer.size
83
+ def md5_hash_for(filepath)
84
+ if md5_hash_cache.key? filepath
85
+ md5_hash_cache[filepath]
86
+ else
87
+ md5_hash_cache[filepath] = Digest::MD5.file(filepath).hexdigest
88
+ end
78
89
  end
79
90
  end
80
91
 
@@ -85,15 +96,15 @@ module OneshotCoverage
85
96
 
86
97
  # To handle execution with exit immediatly
87
98
  at_exit do
88
- OneshotCoverage.emit
99
+ OneshotCoverage.emit(force_emit: true)
89
100
  end
90
101
  end
91
102
 
92
- def emit
93
- @reporter&.emit
103
+ def emit(force_emit: false)
104
+ @reporter&.emit(force_emit)
94
105
  end
95
106
 
96
- def configure(target_path:, logger: OneshotCoverage::Logger::NullLogger.new, max_emit_at_once: nil)
107
+ def configure(target_path:, logger: OneshotCoverage::Logger::NullLogger.new, emit_term: nil)
97
108
  target_path_by_pathname =
98
109
  if target_path.is_a? Pathname
99
110
  target_path
@@ -103,7 +114,7 @@ module OneshotCoverage
103
114
  @reporter = OneshotCoverage::Reporter.new(
104
115
  target_path: target_path_by_pathname.cleanpath.to_s + "/",
105
116
  logger: logger,
106
- max_emit_at_once: max_emit_at_once
117
+ emit_term: emit_term,
107
118
  )
108
119
  end
109
120
  end
@@ -0,0 +1,35 @@
1
+ require 'json'
2
+
3
+ module OneshotCoverage
4
+ module Logger
5
+ class FileLogger
6
+ def initialize(log_path)
7
+ @log_path = log_path
8
+ end
9
+
10
+ def post(new_logs)
11
+ current_coverage = fetch
12
+
13
+ new_logs.each do |new_log|
14
+ key = "#{new_log.path}-#{new_log.md5_hash}"
15
+
16
+ logged_lines = current_coverage.fetch(key, [])
17
+ current_coverage[key] = logged_lines | new_log.lines
18
+ end
19
+ save(current_coverage)
20
+ end
21
+
22
+ private
23
+
24
+ def fetch
25
+ JSON.load(File.read(@log_path))
26
+ rescue Errno::ENOENT
27
+ {}
28
+ end
29
+
30
+ def save(data)
31
+ File.write(@log_path, JSON.dump(data))
32
+ end
33
+ end
34
+ end
35
+ end
@@ -3,7 +3,6 @@ module OneshotCoverage
3
3
  class NullLogger
4
4
  def post(_row)
5
5
  # Do nothing
6
- true
7
6
  end
8
7
  end
9
8
  end
@@ -1,11 +1,12 @@
1
1
  module OneshotCoverage
2
2
  module Logger
3
3
  class StdoutLogger
4
- def post(path:, md5_hash:, lineno:)
5
- $stdout.puts(
6
- "[OneshotCoverage] logged path: #{path}, md5_hash: #{md5_hash}, lineno: #{lineno}"
7
- )
8
- true
4
+ def post(logs)
5
+ logs.each do |log|
6
+ $stdout.puts(
7
+ "[OneshotCoverage] logged path: #{log.path}, md5_hash: #{log.md5_hash}, executed_lines: #{log.lines}"
8
+ )
9
+ end
9
10
  end
10
11
  end
11
12
  end
@@ -1,3 +1,3 @@
1
1
  module OneshotCoverage
2
- VERSION = "0.2.2"
2
+ VERSION = "0.3.0"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: oneshot_coverage
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.2
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Shia
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-03-27 00:00:00.000000000 Z
11
+ date: 2019-04-16 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -55,6 +55,7 @@ files:
55
55
  - bin/console
56
56
  - bin/setup
57
57
  - lib/oneshot_coverage.rb
58
+ - lib/oneshot_coverage/logger/file_logger.rb
58
59
  - lib/oneshot_coverage/logger/null_logger.rb
59
60
  - lib/oneshot_coverage/logger/stdout_logger.rb
60
61
  - lib/oneshot_coverage/railtie.rb