Class: GeneratorTestResultsBacktrace

Inherits:
Object
  • Object
show all
Defined in:
lib/ceedling/generator_test_results_backtrace.rb

Overview

Ceedling - Test-Centered Build System for C
ThrowTheSwitch.org
Copyright (c) 2010-25 Mike Karlesky, Mark VanderVoord, & Greg Williams
SPDX-License-Identifier: MIT

Instance Method Summary collapse

Instance Method Details

#do_gdb(filename, executable, shell_result, test_cases) ⇒ Object



78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
# File 'lib/ceedling/generator_test_results_backtrace.rb', line 78

def do_gdb(filename, executable, shell_result, test_cases)
  gdb_script_filepath = File.join( @configurator.project_build_tests_root, BACKTRACE_GDB_SCRIPT_FILE )

  # Clean stats tracker
  test_case_results = @RESULTS_COLLECTOR.new( passed:0, failed:0, ignored:0, output:[] )

  # Reset time
  shell_result[:time] = 0

  # Iterate on test cases
  test_cases.each do |test_case|
    # Build the test fixture to run with our test case of interest
    command = @tool_executor.build_command_line(
      @configurator.tools_test_backtrace_gdb, [],
      gdb_script_filepath,
      executable,
      test_case[:test]
    )
    # Things are gonna go boom, so ignore booms to get output
    command[:options][:boom] = false

    crash_result = @tool_executor.exec( command )

    # Sum execution time for each test case
    # Note: Running tests serpatately increases total execution time)
    shell_result[:time] += crash_result[:time].to_f()

    test_output = ''

    # Process single test case stats
    case crash_result[:output]
    # Success test case
    when /(^#{filename}.+:PASS\s*$)/
      test_case_results[:passed]  += 1
      test_output = $1 # Grab regex match

    # Ignored test case
    when /(^#{filename}.+:IGNORE\s*$)/
      test_case_results[:ignored] += 1
      test_output = $1 # Grab regex match

    when /(^#{filename}.+:FAIL(:.+)?\s*$)/
      test_case_results[:failed]  += 1
      test_output = $1 # Grab regex match

    else # Crash failure case
      test_case_results[:failed]  += 1

      # Collect file_name and line in which crash occurred
      matched = crash_result[:output].match( /#{test_case[:test]}\s*\(\)\sat.+#{filename}:(\d+)\n/ )

      # If we found an error report line containing `test_case() at filename.c:###` in `gdb` output
      if matched
        # Line number
        line_number = matched[1]

        # Filter the `gdb` $stdout report to find most important lines of text
        crash_report = filter_gdb_test_report( crash_result[:output], test_case[:test], filename )

        # Unity’s test executable output is line oriented.
        # Multi-line output is not possible (it looks like random `printf()` statements to the results parser)
        # "Encode" newlines in multiline string to be handled by the test results parser.
        test_output = crash_report.gsub( "\n", NEWLINE_TOKEN )

        test_output = "#{filename}:#{line_number}:#{test_case[:test]}:FAIL: Test case crashed >> #{test_output}"

      # Otherwise communicate that `gdb` failed to produce a usable report
      else
        test_output = "#{filename}:#{test_case[:line_number]}:#{test_case[:test]}:FAIL: Test case crashed (no usable `gdb` report)"
      end
    end

    test_case_results[:output] << test_output
  end

  # Reset shell result exit code and output
  shell_result[:exit_code] = test_case_results[:failed]
  shell_result[:output] =
    @generator_test_results.regenerate_test_executable_stdout(
      total:   test_cases.size(),
      ignored: test_case_results[:ignored],
      failed:  test_case_results[:failed],
      output:  test_case_results[:output]
    )

  return shell_result
end

#do_simple(filename, executable, shell_result, test_cases) ⇒ 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
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
# File 'lib/ceedling/generator_test_results_backtrace.rb', line 16

def do_simple(filename, executable, shell_result, test_cases)
  # Clean stats tracker
  test_case_results = @RESULTS_COLLECTOR.new( passed:0, failed:0, ignored:0, output:[] )

  # Reset time
  shell_result[:time] = 0

  # Iterate on test cases
  test_cases.each do |test_case|
    # Build the test fixture to run with our test case of interest
    command = @tool_executor.build_command_line(
      @configurator.tools_test_fixture_simple_backtrace, [],
      executable,
      test_case[:test]
    )
    # Things are gonna go boom, so ignore booms to get output
    command[:options][:boom] = false

    crash_result = @tool_executor.exec( command )

    # Sum execution time for each test case
    # Note: Running tests serpatately increases total execution time)
    shell_result[:time] += crash_result[:time].to_f()

    # Process single test case stats
    case crash_result[:output]
    # Success test case
    when /(^#{filename}.+:PASS\s*$)/
      test_case_results[:passed]  += 1
      test_output = $1 # Grab regex match

    # Ignored test case
    when /(^#{filename}.+:IGNORE\s*$)/
      test_case_results[:ignored] += 1
      test_output = $1 # Grab regex match

    when /(^#{filename}.+:FAIL(:.+)?\s*$)/
      test_case_results[:failed]  += 1
      test_output = $1 # Grab regex match

    else # Crash failure case
      test_case_results[:failed]  += 1
      test_output = "#{filename}}:#{test_case[:line_number]}:#{test_case[:test]}:FAIL: Test case crashed"
    end

    # Collect up real and stand-in test results output
    test_case_results[:output] << test_output
  end

  # Reset shell result exit code and output
  shell_result[:exit_code] = test_case_results[:failed]
  shell_result[:output] =
    @generator_test_results.regenerate_test_executable_stdout(
      total:   test_cases.size(),
      ignored: test_case_results[:ignored],
      failed:  test_case_results[:failed],
      output:  test_case_results[:output]
    )

  return shell_result
end

#setupObject



12
13
14
# File 'lib/ceedling/generator_test_results_backtrace.rb', line 12

def setup()
  @RESULTS_COLLECTOR = Struct.new( :passed, :failed, :ignored, :output, keyword_init:true )
end