Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Integrate Launchable into make btest #11113

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Jul 8, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 15 additions & 2 deletions .github/actions/launchable/setup/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,19 @@ inputs:
Directory to (re-)checkout source codes. Launchable retrives the commit information
from the directory.

launchable-workspace:
required: true
default: ${{ github.event.repository.name }}
description: >-
A workspace name in Launchable

test-task:
required: true
default: ${{ matrix.test_task }}
description: >-
A test task that determine which tests are executed.
This value is used in the Launchable flavor.

runs:
using: composite

Expand Down Expand Up @@ -77,7 +90,7 @@ runs:
: # The following envs are necessary in Launchable tokenless authentication.
: # https://github.com/launchableinc/cli/blob/v1.80.1/launchable/utils/authentication.py#L20
echo "LAUNCHABLE_ORGANIZATION=${{ github.repository_owner }}" >> $GITHUB_ENV
echo "LAUNCHABLE_WORKSPACE=${{ github.event.repository.name }}" >> $GITHUB_ENV
echo "LAUNCHABLE_WORKSPACE=${{ inputs.launchable-workspace }}" >> $GITHUB_ENV
: # https://github.com/launchableinc/cli/blob/v1.80.1/launchable/utils/authentication.py#L71
echo "GITHUB_PR_HEAD_SHA=${{ github.event.pull_request.head.sha || github.sha }}" >> $GITHUB_ENV
echo "LAUNCHABLE_TOKEN=${{ inputs.launchable-token }}" >> $GITHUB_ENV
Expand Down Expand Up @@ -135,7 +148,7 @@ runs:
working-directory: ${{ inputs.srcdir }}
post: |
: # record
launchable record tests --flavor os=${{ inputs.os }} --flavor test_task=${{ matrix.test_task }} --flavor test_opts=${test_opts} raw ${report_path}
launchable record tests --flavor os=${{ inputs.os }} --flavor test_task=${{ inputs.test-task }} --flavor test_opts=${test_opts} raw ${report_path}
rm -f ${report_path}
if: ${{ always() && steps.enable-launchable.outputs.enable-launchable }}
env:
Expand Down
18 changes: 17 additions & 1 deletion .github/workflows/rjit.yml
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,8 @@ jobs:
srcdir: src
builddir: build
makeup: true
# Set fetch-depth: 10 so that Launchable can receive commits information.
fetch-depth: 10

- name: Run configure
env:
Expand All @@ -77,13 +79,27 @@ jobs:

- run: $SETARCH make

- name: Set up Launchable
uses: ./.github/actions/launchable/setup
with:
os: ubuntu-22.04
test-task: test
launchable-token: ${{ secrets.LAUNCHABLE_TOKEN }}
builddir: build
srcdir: src
launchable-workspace: ruby-make-btest
test-opts: ${{ matrix.run_opts }}
continue-on-error: true

- name: make test
run: |
$SETARCH make -s test RUN_OPTS="$RUN_OPTS"
timeout-minutes: 30
env:
GNUMAKEFLAGS: ''
RUBY_TESTOPTS: '--tty=no'
RUBY_TESTOPTS: >-
${{ env.TESTS }}
--tty=no
RUN_OPTS: ${{ matrix.run_opts }}

- name: make test-all
Expand Down
60 changes: 58 additions & 2 deletions bootstraptest/runner.rb
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ def Dir.mktmpdir(prefix_suffix=nil, tmpdir=nil)
:platform,
:timeout,
:timeout_scale,
:launchable_test_reports
)
BT = Class.new(bt) do
def indent=(n)
Expand Down Expand Up @@ -229,6 +230,19 @@ def main
exit true
when /\A-j/
true
when /--launchable-test-reports=(.*)/
if File.exist?($1)
# To protect files from overwritten, do nothing when the file exists.
return true
end

require_relative '../tool/lib/launchable'
BT.launchable_test_reports = writer = Launchable::JsonStreamWriter.new($1)
writer.write_array('testCases')
at_exit {
writer.close
}
true
else
false
end
Expand Down Expand Up @@ -345,6 +359,45 @@ def concurrent_exec_test
end
end

module Launchable
def show_progress(message = '')
faildesc, t = super

if writer = BT.launchable_test_reports
if !faildesc
status = 'TEST_PASSED'
else
status = 'TEST_FAILED'
end
repo_path = File.expand_path("#{__dir__}/../")
relative_path = self.path.delete_prefix("#{repo_path}/")
# The test path is a URL-encoded representation.
# https://github.com/launchableinc/cli/blob/v1.81.0/launchable/testpath.py#L18
test_path = {file: relative_path, testcase: self.id}.map{|key, val|
"#{encode_test_path_component(key)}=#{encode_test_path_component(val)}"
}.join('#')
writer.write_object(
{
testPath: test_path,
status: status,
duration: t,
createdAt: Time.now.to_s,
stderr: faildesc,
stdout: nil,
data: {
lineNumber: self.lineno
}
}
)
end
end

private
def encode_test_path_component component
component.to_s.gsub('%', '%25').gsub('=', '%3D').gsub('#', '%23').gsub('&', '%26')
end
end

def exec_test(paths)
# setup
load_test paths
Expand Down Expand Up @@ -421,6 +474,7 @@ def target_platform
end

class Assertion < Struct.new(:src, :path, :lineno, :proc)
prepend Launchable
@count = 0
@all = Hash.new{|h, k| h[k] = []}
@errbuf = []
Expand Down Expand Up @@ -495,9 +549,9 @@ def show_progress(message = '')
$stderr.print "#{BT.progress_bs}#{BT.progress[BT_STATE.count % BT.progress.size]}"
end

t = Time.now if BT.verbose
t = Time.now if BT.verbose || BT.launchable_test_reports
faildesc, errout = with_stderr {yield}
t = Time.now - t if BT.verbose
t = Time.now - t if BT.verbose || BT.launchable_test_reports

if !faildesc
# success
Expand All @@ -524,6 +578,8 @@ def show_progress(message = '')
$stderr.printf("%-*s%s", BT.width, path, BT.progress[BT_STATE.count % BT.progress.size])
end
end

[faildesc, t]
rescue Interrupt
$stderr.puts "\##{@id} #{path}:#{lineno}"
raise
Expand Down
91 changes: 91 additions & 0 deletions tool/lib/launchable.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
# frozen_string_literal: true
require 'json'
require 'uri'

module Launchable
##
# JsonStreamWriter writes a JSON file using a stream.
# By utilizing a stream, we can minimize memory usage, especially for large files.
class JsonStreamWriter
def initialize(path)
@file = File.open(path, "w")
@file.write("{")
@indent_level = 0
@is_first_key_val = true
@is_first_obj = true
write_new_line
end

def write_object obj
if @is_first_obj
@is_first_obj = false
else
write_comma
write_new_line
end
@indent_level += 1
@file.write(to_json_str(obj))
@indent_level -= 1
@is_first_key_val = true
# Occasionally, invalid JSON will be created as shown below, especially when `--repeat-count` is specified.
# {
# "testPath": "file=test%2Ftest_timeout.rb&class=TestTimeout&testcase=test_allows_zero_seconds",
# "status": "TEST_PASSED",
# "duration": 2.7e-05,
# "createdAt": "2024-02-09 12:21:07 +0000",
# "stderr": null,
# "stdout": null
# }: null <- here
# },
# To prevent this, IO#flush is called here.
@file.flush
end

def write_array(key)
@indent_level += 1
@file.write(to_json_str(key))
write_colon
@file.write(" ", "[")
write_new_line
end

def close
return if @file.closed?
close_array
@indent_level -= 1
write_new_line
@file.write("}", "\n")
@file.flush
@file.close
end

private
def to_json_str(obj)
json = JSON.pretty_generate(obj)
json.gsub(/^/, ' ' * (2 * @indent_level))
end

def write_indent
@file.write(" " * 2 * @indent_level)
end

def write_new_line
@file.write("\n")
end

def write_comma
@file.write(',')
end

def write_colon
@file.write(":")
end

def close_array
write_new_line
write_indent
@file.write("]")
@indent_level -= 1
end
end
end
91 changes: 2 additions & 89 deletions tool/lib/test/unit.rb
Original file line number Diff line number Diff line change
Expand Up @@ -1450,9 +1450,8 @@ def record(suite, method, assertions, time, error, source_location = nil)
def setup_options(opts, options)
super
opts.on_tail '--launchable-test-reports=PATH', String, 'Report test results in Launchable JSON format' do |path|
require 'json'
require 'uri'
options[:launchable_test_reports] = writer = JsonStreamWriter.new(path)
require_relative '../launchable'
options[:launchable_test_reports] = writer = Launchable::JsonStreamWriter.new(path)
writer.write_array('testCases')
main_pid = Process.pid
at_exit {
Expand All @@ -1469,92 +1468,6 @@ def encode_test_path_component component
component.to_s.gsub('%', '%25').gsub('=', '%3D').gsub('#', '%23').gsub('&', '%26')
end
end

##
# JsonStreamWriter writes a JSON file using a stream.
# By utilizing a stream, we can minimize memory usage, especially for large files.
class JsonStreamWriter
def initialize(path)
@file = File.open(path, "w")
@file.write("{")
@indent_level = 0
@is_first_key_val = true
@is_first_obj = true
write_new_line
end

def write_object obj
if @is_first_obj
@is_first_obj = false
else
write_comma
write_new_line
end
@indent_level += 1
@file.write(to_json_str(obj))
@indent_level -= 1
@is_first_key_val = true
# Occasionally, invalid JSON will be created as shown below, especially when `--repeat-count` is specified.
# {
# "testPath": "file=test%2Ftest_timeout.rb&class=TestTimeout&testcase=test_allows_zero_seconds",
# "status": "TEST_PASSED",
# "duration": 2.7e-05,
# "createdAt": "2024-02-09 12:21:07 +0000",
# "stderr": null,
# "stdout": null
# }: null <- here
# },
# To prevent this, IO#flush is called here.
@file.flush
end

def write_array(key)
@indent_level += 1
@file.write(to_json_str(key))
write_colon
@file.write(" ", "[")
write_new_line
end

def close
return if @file.closed?
close_array
@indent_level -= 1
write_new_line
@file.write("}", "\n")
@file.flush
@file.close
end

private
def to_json_str(obj)
json = JSON.pretty_generate(obj)
json.gsub(/^/, ' ' * (2 * @indent_level))
end

def write_indent
@file.write(" " * 2 * @indent_level)
end

def write_new_line
@file.write("\n")
end

def write_comma
@file.write(',')
end

def write_colon
@file.write(":")
end

def close_array
write_new_line
write_indent
@file.write("]")
@indent_level -= 1
end
end
end

class Runner # :nodoc: all
Expand Down
3 changes: 2 additions & 1 deletion tool/test/testunit/test_launchable.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,12 @@
require 'test/unit'
require 'tempfile'
require 'json'
require_relative '../../lib/launchable'

class TestLaunchable < Test::Unit::TestCase
def test_json_stream_writer
Tempfile.create(['launchable-test-', '.json']) do |f|
json_stream_writer = Test::Unit::LaunchableOption::JsonStreamWriter.new(f.path)
json_stream_writer = Launchable::JsonStreamWriter.new(f.path)
json_stream_writer.write_array('testCases')
json_stream_writer.write_object(
{
Expand Down
Loading