Class: Canopus::TestRunner::Execution

Inherits:
Object
  • Object
show all
Defined in:
lib/canopus/test_runner/execution.rb

Constant Summary collapse

MAX_OUTPUT_BYTES =
256 << 10
MAX_PARSE_LINES =
10_000
MAX_FILTER_BYTES =
8_192
ANSI =
/\e(?:\[[0-?]*[ -\/]*[@-~]|\][^\a]*(?:\a|\e\\))/n

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(test, output, generation: nil, tests: [test]) ⇒ Execution

Returns a new instance of Execution.



51
52
53
54
# File 'lib/canopus/test_runner/execution.rb', line 51

def initialize(test, output, generation: nil, tests: [test])
  @test, @tests, @output, @generation = test, tests.dup.freeze, output, generation
  @bytes, @cancelled = +"".b, false
end

Instance Attribute Details

#generation ⇒ Object (readonly)

Returns the value of attribute generation.



14
15
16
# File 'lib/canopus/test_runner/execution.rb', line 14

def generation
  @generation
end

#output ⇒ Object (readonly)

Returns the value of attribute output.



14
15
16
# File 'lib/canopus/test_runner/execution.rb', line 14

def output
  @output
end

#test ⇒ Object (readonly)

Returns the value of attribute test.



14
15
16
# File 'lib/canopus/test_runner/execution.rb', line 14

def test
  @test
end

#tests ⇒ Object (readonly)

Returns the value of attribute tests.



14
15
16
# File 'lib/canopus/test_runner/execution.rb', line 14

def tests
  @tests
end

Class Method Details

.task(test, root:, tests: [test]) ⇒ Object



16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
# File 'lib/canopus/test_runner/execution.rb', line 16

def self.task(test, root:, tests: [test])
  raise ArgumentError, "discovered test required" unless test.is_a?(Test)
  unless tests.is_a?(Array) && !tests.empty? && tests.length <= Discovery::MAX_TESTS &&
      tests.all? { |candidate| candidate.is_a?(Test) && candidate.framework == test.framework &&
        candidate.path == test.path && candidate.line == test.line }
    raise ArgumentError, "related discovered tests required"
  end

  root = File.realpath(root)
  relative = TestRunner.normalize_path(test.path)
  raise Error, "Test target is invalid" unless relative == test.path

  candidate = File.join(root, relative)
  raise Error, "Test target is not a file" if File.lstat(candidate).symlink?
  path = File.realpath(candidate)
  prefix = root.end_with?(File::SEPARATOR) ? root : root + File::SEPARATOR
  raise Error, "Test target is outside the workspace" unless path.start_with?(prefix) && File.file?(path)

  command = case test.framework
  when :minitest then minitest_command(tests)
  when :rspec then rspec_command(tests)
  else raise Error, "Unknown test framework"
  end
  gemfile = File.join(root, "Gemfile")
  bundled = regular_file?(gemfile)
  command = [RbConfig.ruby, "-S", "bundle", "exec", *command] if bundled
  environment = unbundled_environment
  environment["BUNDLE_GEMFILE"] = gemfile if bundled
  {"label" => label(test), "command" => command.freeze, "cwd" => root,
   "env" => environment.freeze,
   "presentation" => {"panel" => "output", "reveal" => "silent"}.freeze}.freeze
rescue SystemCallError, TypeError => error
  raise Error, "Cannot run test: #{error.message}"
end

Instance Method Details

#append(bytes) ⇒ Object



56
57
58
59
60
61
62
# File 'lib/canopus/test_runner/execution.rb', line 56

def append(bytes)
  return if bytes.nil? || bytes.empty?

  @bytes << bytes.b
  @bytes = @bytes.byteslice(-MAX_OUTPUT_BYTES, MAX_OUTPUT_BYTES) if @bytes.bytesize > MAX_OUTPUT_BYTES
  nil
end

#cancel ⇒ Object



64
# File 'lib/canopus/test_runner/execution.rb', line 64

def cancel = (@cancelled = true)

#finish(status) ⇒ Object



66
67
68
69
70
71
72
73
74
# File 'lib/canopus/test_runner/execution.rb', line 66

def finish(status)
  return result(:skipped) if @cancelled
  return failure_result unless status&.success?

  count, skipped = summary
  return failure_result unless count == tests.length

  skipped == count ? result(:skipped) : result(:success)
end