Class: TestInvokerHelper
Instance Method Summary collapse
- #clean_test_results(path, tests) ⇒ Object
- #collect_test_framework_sources(mocks) ⇒ Object
- #compile_defines(context:, filepath:) ⇒ Object
-
#convert_libraries_to_arguments ⇒ Object
Convert libraries configuration form YAML configuration into a string that can be given to the compiler.
- #extract_include_directives(arg_hash) ⇒ Object
- #extract_sources(test_filepath) ⇒ Object
- #fetch_include_search_paths_for_test_file(test_filepath) ⇒ Object
- #fetch_shallow_source_includes(test_filepath) ⇒ Object
-
#find_header_input_for_mock(mock, search_paths) ⇒ Object
TODO: Use search_paths to find/match header file from which to generate mock Today, this is just a pass-through wrapper.
- #flags(context:, operation:, filepath:, default: []) ⇒ Object
-
#form_mock_filenames(mocklist) ⇒ Object
Transform list of mock names into filenames with source extension.
- #framework_defines ⇒ Object
- #generate_executable_now(context:, build_path:, executable:, objects:, flags:, lib_args:, lib_paths:, options:) ⇒ Object
- #get_library_paths_to_arguments ⇒ Object
- #preprocess_defines(test_defines:, filepath:) ⇒ Object
- #preprocess_flags(context:, compile_flags:, filepath:) ⇒ Object
- #process_project_include_paths ⇒ Object
- #remove_mock_original_headers(filelist, mocklist) ⇒ Object
- #run_fixture_now(context:, test_name:, test_filepath:, executable:, result:, options:) ⇒ Object
- #runner_defines ⇒ Object
- #search_paths(filepath, subdir) ⇒ Object
- #setup ⇒ Object
- #tailor_search_paths(filepath:, search_paths:) ⇒ Object
- #validate_build_directive_source_files(test:, filepath:) ⇒ Object
Instance Method Details
#clean_test_results(path, tests) ⇒ Object
266 267 268 269 270 |
# File 'lib/ceedling/test_invoker_helper.rb', line 266 def clean_test_results(path, tests) tests.each do |test| @file_wrapper.rm_f( Dir.glob( File.join( path, test + '.*' ) ) ) end end |
#collect_test_framework_sources(mocks) ⇒ Object
192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 |
# File 'lib/ceedling/test_invoker_helper.rb', line 192 def collect_test_framework_sources(mocks) sources = [] sources << File.join(PROJECT_BUILD_VENDOR_UNITY_PATH, UNITY_C_FILE) sources << File.join(PROJECT_BUILD_VENDOR_CMOCK_PATH, CMOCK_C_FILE) if @configurator.project_use_mocks and mocks sources << File.join(PROJECT_BUILD_VENDOR_CEXCEPTION_PATH, CEXCEPTION_C_FILE) if @configurator.project_use_exceptions # If we're (a) using mocks (b) a Unity helper is defined and (c) that unity helper includes a source file component, # then link in the unity_helper object file too. if @configurator.project_use_mocks @configurator.cmock_unity_helper_path.each do |helper| if @file_wrapper.exist?( helper.ext( EXTENSION_SOURCE ) ) sources << helper end end end return sources end |
#compile_defines(context:, filepath:) ⇒ Object
152 153 154 155 156 157 158 159 160 |
# File 'lib/ceedling/test_invoker_helper.rb', line 152 def compile_defines(context:, filepath:) # If this context exists ([:defines][context]), use it. Otherwise, default to test context. context = TEST_SYM unless @defineinator.defines_defined?( context:context ) defines = @defineinator.generate_test_definition( filepath:filepath ) defines += @defineinator.defines( subkey:context, filepath:filepath ) return defines.uniq end |
#convert_libraries_to_arguments ⇒ Object
Convert libraries configuration form YAML configuration into a string that can be given to the compiler.
274 275 276 277 278 279 280 |
# File 'lib/ceedling/test_invoker_helper.rb', line 274 def convert_libraries_to_arguments() args = ((@configurator.project_config_hash[:libraries_test] || []) + ((defined? LIBRARIES_SYSTEM) ? LIBRARIES_SYSTEM : [])).flatten if (defined? LIBRARIES_FLAG) args.map! {|v| LIBRARIES_FLAG.gsub(/\$\{1\}/, v) } end return args end |
#extract_include_directives(arg_hash) ⇒ Object
38 39 40 41 42 43 44 |
# File 'lib/ceedling/test_invoker_helper.rb', line 38 def extract_include_directives(arg_hash) # Run test file through preprocessor to parse out include statements and then collect header files, mocks, etc. includes = @preprocessinator.preprocess_includes( **arg_hash ) # Store the include statements we found @test_context_extractor.ingest_includes( arg_hash[:filepath], includes ) end |
#extract_sources(test_filepath) ⇒ Object
212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 |
# File 'lib/ceedling/test_invoker_helper.rb', line 212 def extract_sources(test_filepath) sources = [] # Get any additional source files specified by TEST_SOURCE_FILE() in test file _sources = @test_context_extractor.lookup_build_directive_sources_list(test_filepath) _sources.each do |source| sources << @file_finder.find_build_input_file(filepath: source, complain: :ignore, context: TEST_SYM) end _support_headers = COLLECTION_ALL_SUPPORT.map { |filepath| File.basename(filepath).ext(EXTENSION_HEADER) } # Get all #include .h files from test file so we can find any source files by convention includes = @test_context_extractor.lookup_full_header_includes_list(test_filepath) includes.each do |include| _basename = File.basename(include) next if _basename == UNITY_H_FILE # Ignore Unity in this list next if _basename.start_with?(CMOCK_MOCK_PREFIX) # Ignore mocks in this list next if _support_headers.include?(_basename) # Ignore any sources in our support files list sources << @file_finder.find_build_input_file(filepath: include, complain: :ignore, context: TEST_SYM) end # Remove any nil or duplicate entries in list return sources.compact.uniq end |
#fetch_include_search_paths_for_test_file(test_filepath) ⇒ Object
242 243 244 |
# File 'lib/ceedling/test_invoker_helper.rb', line 242 def fetch_include_search_paths_for_test_file(test_filepath) return @test_context_extractor.lookup_include_paths_list(test_filepath) end |
#fetch_shallow_source_includes(test_filepath) ⇒ Object
238 239 240 |
# File 'lib/ceedling/test_invoker_helper.rb', line 238 def fetch_shallow_source_includes(test_filepath) return @test_context_extractor.lookup_source_includes_list(test_filepath) end |
#find_header_input_for_mock(mock, search_paths) ⇒ Object
TODO: Use search_paths to find/match header file from which to generate mock Today, this is just a pass-through wrapper
248 249 250 |
# File 'lib/ceedling/test_invoker_helper.rb', line 248 def find_header_input_for_mock(mock, search_paths) return @file_finder.find_header_input_for_mock( mock ) end |
#flags(context:, operation:, filepath:, default: []) ⇒ Object
174 175 176 177 178 179 |
# File 'lib/ceedling/test_invoker_helper.rb', line 174 def flags(context:, operation:, filepath:, default:[]) # If this context + operation exists ([:flags][context][operation]), use it. Otherwise, default to test context. context = TEST_SYM unless @flaginator.flags_defined?( context:context, operation:operation ) return @flaginator.flag_down( context:context, operation:operation, filepath:filepath, default:default ) end |
#form_mock_filenames(mocklist) ⇒ Object
Transform list of mock names into filenames with source extension
253 254 255 |
# File 'lib/ceedling/test_invoker_helper.rb', line 253 def form_mock_filenames(mocklist) return mocklist.map {|mock| mock + @configurator.extension_source} end |
#framework_defines ⇒ Object
94 95 96 97 98 99 100 101 102 103 104 105 106 107 |
# File 'lib/ceedling/test_invoker_helper.rb', line 94 def framework_defines() defines = [] # Unity defines defines += @defineinator.defines( topkey:UNITY_SYM, subkey: :defines ) # CMock defines defines += @defineinator.defines( topkey:CMOCK_SYM, subkey: :defines ) # CException defines defines += @defineinator.defines( topkey:CEXCEPTION_SYM, subkey: :defines ) return defines.uniq end |
#generate_executable_now(context:, build_path:, executable:, objects:, flags:, lib_args:, lib_paths:, options:) ⇒ Object
290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 |
# File 'lib/ceedling/test_invoker_helper.rb', line 290 def generate_executable_now(context:, build_path:, executable:, objects:, flags:, lib_args:, lib_paths:, options:) begin @generator.generate_executable_file( [:test_linker], context, objects.map{|v| "\"#{v}\""}, flags, executable, @file_path_utils.form_test_build_map_filepath( build_path, executable ), lib_args, lib_paths ) rescue ShellException => ex if ex.shell_result[:output] =~ /symbol/i notice = "If the linker reports missing symbols, the following may be to blame:\n" + " 1. This test lacks #include statements corresponding to needed source files (see note below).\n" + " 2. Project file paths omit source files corresponding to #include statements in this test.\n" + " 3. Complex macros, #ifdefs, etc. have obscured correct #include statements in this test.\n" + " 4. Your project is attempting to mix C++ and C file extensions (not supported).\n" if (@configurator.project_use_mocks) notice += " 5. This test does not #include needed mocks (that triggers their generation).\n" end notice += "\n" notice += "NOTE: A test file directs the build of a test executable with #include statemetns:\n" + " * By convention, Ceedling assumes header filenames correspond to source filenames.\n" + " * Which code files to compile and link are determined by #include statements.\n" if (@configurator.project_use_mocks) notice += " * An #include statement convention directs the generation of mocks from header files.\n" end notice += "\n" notice += "OPTIONS:\n" + " 1. Doublecheck this test's #include statements.\n" + " 2. Simplify complex macros or fully specify symbols for this test in :project ↳ :defines.\n" + " 3. If no header file corresponds to the needed source file, use the #{UNITY_TEST_SOURCE_FILE}()\n" + " build diective macro in this test to inject a source file into the build.\n\n" + "See the docs on conventions, paths, preprocessing, compilation symbols, and build directive macros.\n\n" # Print helpful notice @loginator.log( notice, Verbosity::COMPLAIN, LogLabels::NOTICE ) end # Re-raise the exception raise ex end end |
#get_library_paths_to_arguments ⇒ Object
282 283 284 285 286 287 288 |
# File 'lib/ceedling/test_invoker_helper.rb', line 282 def get_library_paths_to_arguments() paths = (defined? PATHS_LIBRARIES) ? (PATHS_LIBRARIES || []).clone : [] if (defined? LIBRARIES_PATH_FLAG) paths.map! {|v| LIBRARIES_PATH_FLAG.gsub(/\$\{1\}/, v) } end return paths end |
#preprocess_defines(test_defines:, filepath:) ⇒ Object
162 163 164 165 166 167 168 169 170 171 172 |
# File 'lib/ceedling/test_invoker_helper.rb', line 162 def preprocess_defines(test_defines:, filepath:) # Preprocessing defines for the test file preprocessing_defines = @defineinator.defines( subkey:PREPROCESS_SYM, filepath:filepath, default:nil ) # If no defines were set, default to using test_defines return test_defines if preprocessing_defines.nil? # Otherwise, return the defines we looked up # This includes an explicitly set empty list to override / clear test_defines return preprocessing_defines end |
#preprocess_flags(context:, compile_flags:, filepath:) ⇒ Object
181 182 183 184 185 186 187 188 189 190 |
# File 'lib/ceedling/test_invoker_helper.rb', line 181 def preprocess_flags(context:, compile_flags:, filepath:) preprocessing_flags = flags( context:context, operation:OPERATION_PREPROCESS_SYM, filepath:filepath, default:nil ) # If no flags were set, default to using compile_flags return compile_flags if preprocessing_flags.nil? # Otherwise, return the flags we looked up # This includes an explicitly set empty list to override / clear compile_flags return preprocessing_flags end |
#process_project_include_paths ⇒ Object
32 33 34 35 36 |
# File 'lib/ceedling/test_invoker_helper.rb', line 32 def process_project_include_paths() @include_pathinator.validate_test_build_directive_paths() headers = @include_pathinator.validate_header_files_collection() @include_pathinator.augment_environment_header_files( headers ) end |
#remove_mock_original_headers(filelist, mocklist) ⇒ Object
257 258 259 260 261 262 263 264 |
# File 'lib/ceedling/test_invoker_helper.rb', line 257 def remove_mock_original_headers( filelist, mocklist ) filelist.delete_if do |filepath| # Create a simple mock name from the filepath => mock prefix + filepath base name with no extension mock_name = @configurator.cmock_mock_prefix + File.basename( filepath, '.*' ) # Tell `delete_if()` logic to remove inspected filepath if simple mocklist includes the name we just generated mocklist.include?( mock_name ) end end |
#run_fixture_now(context:, test_name:, test_filepath:, executable:, result:, options:) ⇒ Object
337 338 339 340 341 342 343 344 345 |
# File 'lib/ceedling/test_invoker_helper.rb', line 337 def run_fixture_now(context:, test_name:, test_filepath:, executable:, result:, options:) @generator.generate_test_results( tool: [:test_fixture], context: context, test_name: test_name, test_filepath: test_filepath, executable: executable, result: result) end |
#runner_defines ⇒ Object
148 149 150 |
# File 'lib/ceedling/test_invoker_helper.rb', line 148 def runner_defines() return @test_runner_manager.collect_defines() end |
#search_paths(filepath, subdir) ⇒ Object
78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 |
# File 'lib/ceedling/test_invoker_helper.rb', line 78 def search_paths(filepath, subdir) paths = [] # Start with mock path to ensure any CMock-reworked header files are encountered first paths << File.join( @configurator.cmock_mock_path, subdir ) if @configurator.project_use_mocks paths += @include_pathinator.lookup_test_directive_include_paths( filepath ) paths += @include_pathinator.collect_test_include_paths() paths += @configurator.collection_paths_support paths += @configurator.collection_paths_include paths += @configurator.collection_paths_libraries paths += @configurator.collection_paths_vendor paths += @configurator.collection_paths_test_toolchain_include return paths.uniq end |
#setup ⇒ Object
27 28 29 30 |
# File 'lib/ceedling/test_invoker_helper.rb', line 27 def setup() # Alias for brevity @batchinator = @build_batchinator end |
#tailor_search_paths(filepath:, search_paths:) ⇒ Object
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 |
# File 'lib/ceedling/test_invoker_helper.rb', line 109 def tailor_search_paths(filepath:, search_paths:) _search_paths = [] # Unity search paths if filepath == File.join(PROJECT_BUILD_VENDOR_UNITY_PATH, UNITY_C_FILE) _search_paths += @configurator.collection_paths_support _search_paths << PROJECT_BUILD_VENDOR_UNITY_PATH # CMock search paths elsif @configurator.project_use_mocks and (filepath == File.join(PROJECT_BUILD_VENDOR_CMOCK_PATH, CMOCK_C_FILE)) _search_paths += @configurator.collection_paths_support _search_paths << PROJECT_BUILD_VENDOR_UNITY_PATH _search_paths << PROJECT_BUILD_VENDOR_CMOCK_PATH _search_paths << PROJECT_BUILD_VENDOR_CEXCEPTION_PATH if @configurator.project_use_exceptions # CException search paths elsif @configurator.project_use_exceptions and (filepath == File.join(PROJECT_BUILD_VENDOR_CEXCEPTION_PATH, CEXCEPTION_C_FILE)) _search_paths += @configurator.collection_paths_support _search_paths << PROJECT_BUILD_VENDOR_CEXCEPTION_PATH # Support files search paths elsif (@configurator.collection_all_support.include?(filepath)) _search_paths = search_paths _search_paths += @configurator.collection_paths_support _search_paths << PROJECT_BUILD_VENDOR_UNITY_PATH _search_paths << PROJECT_BUILD_VENDOR_CMOCK_PATH if @configurator.project_use_mocks _search_paths << PROJECT_BUILD_VENDOR_CEXCEPTION_PATH if @configurator.project_use_exceptions end # Not a vendor file, return original search paths if _search_paths.length == 0 return search_paths end return _search_paths.uniq end |
#validate_build_directive_source_files(test:, filepath:) ⇒ Object
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/test_invoker_helper.rb', line 46 def validate_build_directive_source_files(test:, filepath:) sources = @test_context_extractor.lookup_build_directive_sources_list(filepath) = @configurator.extension_source if @configurator.test_build_use_assembly += " or #{@configurator.extension_assembly}" end sources.each do |source| valid_extension = true # Only C files in test build if not @configurator.test_build_use_assembly valid_extension = false if @file_wrapper.extname(source) != @configurator.extension_source # C and assembly files in test build else ext = @file_wrapper.extname(source) valid_extension = false if (ext != @configurator.extension_assembly) and (ext != @configurator.extension_source) end if not valid_extension error = "File '#{source}' specified with #{UNITY_TEST_SOURCE_FILE}() in #{test} is not a #{} source file" raise CeedlingException.new(error) end if @file_finder.find_build_input_file(filepath: source, complain: :ignore, context: TEST_SYM).nil? error = "File '#{source}' specified with #{UNITY_TEST_SOURCE_FILE}() in #{test} cannot be found in the source file collection" raise CeedlingException.new(error) end end end |