From 7312d687ea8ea0fe9f268d3ecb223cc9d45c776c Mon Sep 17 00:00:00 2001 From: Shia Date: Tue, 10 Sep 2024 22:48:38 +0900 Subject: [PATCH] Add online_emit mode --- .gitignore | 1 + README.md | 20 ++++++++++++++ lib/akainaa.rb | 62 ++++++++++++++++++++++++++++++++++++++++++-- sample/.ruby-version | 1 - sample/Gemfile.lock | 2 +- sample/config.ru | 8 +++++- 6 files changed, 89 insertions(+), 5 deletions(-) delete mode 100644 sample/.ruby-version diff --git a/.gitignore b/.gitignore index 6853244..ab9924d 100644 --- a/.gitignore +++ b/.gitignore @@ -8,3 +8,4 @@ /tmp/ Gemfile.lock +coverage.json diff --git a/README.md b/README.md index a569f51..c104e08 100644 --- a/README.md +++ b/README.md @@ -45,6 +45,26 @@ run App Boot up application, do something, and access `/akainaa`. It will show Web UI what and how many executed. +### Enable online emit mode + +Akainaa can emit coverage data which recorded in interval to the file. +This feature is intended to be used with vscode-akainaa extension. + +```ruby +Akainaa.start( + project_dir: File.expand_path(__dir__), + ignore_glob_patterns: %w[ + config/application.rb + config/initializers/*_initializer.rb + ], + online_emit: { + mode: :file, + interval: 1, # seconds + output_path: '/tmp/akainaa.json', + }, +) +``` + ## Development After checking out the repo, run `bin/setup` to install dependencies. You can also run `bin/console` for an interactive prompt that will allow you to experiment. diff --git a/lib/akainaa.rb b/lib/akainaa.rb index 61e1b5e..21007a9 100644 --- a/lib/akainaa.rb +++ b/lib/akainaa.rb @@ -1,6 +1,7 @@ # frozen_string_literal: true require 'coverage' +require 'fileutils' require_relative 'akainaa/version' require_relative 'akainaa/call_node_visitor' @@ -15,7 +16,8 @@ class << self def start( project_dir:, ignore_glob_patterns: [], - hide_not_executed_files: false + hide_not_executed_files: false, + online_emit: nil ) @project_dir = project_dir @project_dir += '/' unless @project_dir.end_with?('/') @@ -24,8 +26,15 @@ def start( end @ignore_files = Set.new(ignore_files) @hide_not_executed_files = hide_not_executed_files + @monitor = Monitor.new Coverage.start(lines: true) + + if online_emit.is_a?(Hash) + option = default_online_emit.merge(online_emit) + FileUtils.mkdir_p(File.dirname(option[:path])) + start_multipart_emit(option) + end end def peek_result @@ -37,7 +46,56 @@ def peek_result end def reset - Coverage.result(stop: false, clear: true) + @monitor.synchronize do + Coverage.result(stop: false, clear: true) + @previous_result = {} + end + end + + private def default_online_emit + { + mode: :file, + interval: 1, + path: 'tmp/coverage.json', + } + end + + private def start_multipart_emit(option) + Thread.new do + @monitor.synchronize do + @previous_result = {} + end + + loop do + sleep option[:interval] + current_result = peek_result + + diff = {} + current_result.each do |path, path_coverage| + previous_path_coverage = @previous_result[path] + + if previous_path_coverage.nil? + diff[path] = path_coverage + elsif previous_path_coverage[:lines].size != path_coverage[:lines].size + diff[path] = path_coverage + else + diff[path] = { lines: [] } + + path_coverage[:lines].each_with_index do |count, index| + val = count ? count - previous_path_coverage[:lines][index] : nil + + diff[path][:lines] << val + end + end + end + + @monitor.synchronize do + @previous_result = current_result + end + File.write(option[:path], diff.to_json) + puts 'Akainaa: Coverage result emitted' + end + end end end diff --git a/sample/.ruby-version b/sample/.ruby-version deleted file mode 100644 index 15a2799..0000000 --- a/sample/.ruby-version +++ /dev/null @@ -1 +0,0 @@ -3.3.0 diff --git a/sample/Gemfile.lock b/sample/Gemfile.lock index c8b553e..b3de463 100644 --- a/sample/Gemfile.lock +++ b/sample/Gemfile.lock @@ -1,7 +1,7 @@ PATH remote: .. specs: - akainaa (0.1.1) + akainaa (0.1.3) GEM remote: https://rubygems.org/ diff --git a/sample/config.ru b/sample/config.ru index ec73b31..cfd97e2 100644 --- a/sample/config.ru +++ b/sample/config.ru @@ -2,7 +2,13 @@ require 'akainaa' -Akainaa.start(project_dir: File.expand_path(__dir__)) +Akainaa.start( + project_dir: File.expand_path(__dir__), + online_emit: { + mode: :file, + interval: 10, + }, +) require_relative 'app'