Class: TestContextExtractor

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

Defined Under Namespace

Modules: Context

Instance Method Summary collapse

Instance Method Details

#collect_context(filepath, input, *args) ⇒ Object

Reads through IO interface line by line to extract relevant information by context. *args is a list of context symbols. input must have the interface of IO -- StringIO for testing or File in typical use.



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
# File 'lib/ceedling/test_context_extractor.rb', line 78

def collect_context( filepath, input, *args )
  # Code error check--bad context symbol argument
  args.each do |context|
    msg = "Unrecognized test context for collection :#{context}"
    raise CeedlingException.new( msg ) if !Context::ALL.include?( context )
  end

  include_paths = []
  source_extras = []
  includes = []
  partials_config = {}

  @parsing_parcels.code_lines( input ) do |line|
    if args.include?( Context::BUILD_DIRECTIVE_INCLUDE_PATHS )
      # Scan for build directives: TEST_INCLUDE_PATH()
      include_paths += extract_build_directive_include_paths( line )
    end

    if args.include?( Context::BUILD_DIRECTIVE_SOURCE_FILES )
      # Scan for build directives: TEST_SOURCE_FILE()
      source_extras += extract_build_directive_source_files( line )
    end

    if args.include?( Context::INCLUDES )
      # Scan for contents of #include directives
      includes += _extract_includes( line )
    end
  end

  collect_build_directive_include_paths( filepath, include_paths ) if !include_paths.empty?
  collect_build_directive_source_files( filepath, source_extras ) if !source_extras.empty?

  # Different code processing pattern for test runner
  if args.include?( Context::TEST_RUNNER_DETAILS )
    # Go back to beginning of IO object for a full string extraction
    input.rewind()

    # Ultimately, we rely on Unity's runner generator that processes file contents as a single string
    _collect_test_runner_details( filepath, input.read().clean_encoding )
  end

  if args.include?( Context::PARTIALS_CONFIGURATION )
    # Go back to beginning of IO object for a full string extraction
    input.rewind()

    # Scan for Partials configuration directive macros
    partials_config = _extract_partials_config( input.read.clean_encoding )
    collect_partials_configuration( filepath, partials_config ) if !partials_config.empty?
  end  

  collect_includes( filepath, partials_config, includes ) if (!includes.empty? or !partials_config.empty?)
end

#collect_simple_context_from_file(content_filepath, source_filepath, *args) ⇒ Object

Reads through a file's content line by line to extract relevant information by context. content_filepath is the file to be read (could be preprocessed version of test file). source_fileapth is the test filepath to use for results storage and lookup. *args is a list of context symbols. If source_filepath is not provided, then content_filepath is used for results storage and lookup.



63
64
65
66
67
68
69
70
71
72
73
# File 'lib/ceedling/test_context_extractor.rb', line 63

def collect_simple_context_from_file( content_filepath, source_filepath, *args )
  # Load content_filepath
  @file_wrapper.open( content_filepath, 'r' ) do |input|
    collect_context(
      # Use source_filepath if provided, else use content_filepath
      (source_filepath.nil? ? content_filepath : source_filepath),
      input,
      *args
    )
  end
end

#collect_test_runner_details(test_filepath, input_filepath = nil) ⇒ Object



131
132
133
134
135
136
137
138
# File 'lib/ceedling/test_context_extractor.rb', line 131

def collect_test_runner_details(test_filepath, input_filepath=nil)
  # Ultimately, we rely on Unity's runner generator that processes file contents as a single string
  _collect_test_runner_details(
    test_filepath,
    @file_wrapper.read( test_filepath ),
    input_filepath.nil? ? nil : @file_wrapper.read( input_filepath )
  )
end

#ingest_includes(filepath, includes) ⇒ Object

Unlike other ingest() calls, ingest_includes() can be called externally.



238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
# File 'lib/ceedling/test_context_extractor.rb', line 238

def ingest_includes(filepath, includes)
  _includes = Includes.sanitize(includes)

  file_key = form_file_key( filepath )
  
  headers = []
  sources = []

  # Processing list of UserInclude and/or SystemInclude
  _includes.each do |include|
    # <*.h>
    if include.filename =~ /#{Regexp.escape(@configurator.extension_header)}$/
      # Add to .h includes list
      headers << include
    elsif include.filename =~ /#{Regexp.escape(@configurator.extension_source)}$/
      # Add to .c includes list
      sources << include
    end
  end

  @lock.synchronize do
    @header_includes[file_key] = headers
    @source_includes[file_key] = sources
  end

  return _includes
end

#inspect_include_pathsObject



231
232
233
234
235
# File 'lib/ceedling/test_context_extractor.rb', line 231

def inspect_include_paths()
  @lock.synchronize do
    @include_paths.each { |test, paths| yield test, paths }
  end
end

#lookup_all_header_includes_list(filepath) ⇒ Object

All header includes .h as list of Include objects of test file



141
142
143
144
145
146
147
# File 'lib/ceedling/test_context_extractor.rb', line 141

def lookup_all_header_includes_list(filepath)
  val = nil
  @lock.synchronize do
    val = @header_includes[form_file_key( filepath )] || []
  end
  return val
end

#lookup_all_include_pathsObject

Full list of all search paths added through individual test files using TEST_INCLUDE_PATH()



223
224
225
226
227
228
229
# File 'lib/ceedling/test_context_extractor.rb', line 223

def lookup_all_include_paths()
  val = nil
  @lock.synchronize do
    val = @all_include_paths.uniq
  end
  return val
end

#lookup_build_directive_sources_list(filepath) ⇒ Object

Source extras as list of string via TEST_SOURCE_FILE() within test file



168
169
170
171
172
173
174
# File 'lib/ceedling/test_context_extractor.rb', line 168

def lookup_build_directive_sources_list(filepath)
  val = nil
  @lock.synchronize do
    val = @source_extras[form_file_key( filepath )] || []
  end
  return val
end

#lookup_include_paths_list(filepath) ⇒ Object

Include paths of test file specified with TEST_INCLUDE_PATH()



150
151
152
153
154
155
156
# File 'lib/ceedling/test_context_extractor.rb', line 150

def lookup_include_paths_list(filepath)
  val = nil
  @lock.synchronize do
    val = @include_paths[form_file_key( filepath )] || []
  end
  return val
end

#lookup_mock_header_includes_list(filepath) ⇒ Object

Mocks within test file header includes list as list of MockInclude objects



201
202
203
204
# File 'lib/ceedling/test_context_extractor.rb', line 201

def lookup_mock_header_includes_list(filepath)
  includes = lookup_all_header_includes_list(filepath)
  return includes.select { |include| include.is_a?( MockInclude ) }
end

#lookup_nonmock_header_includes_list(filepath) ⇒ Object

Test file header includes list minus mocks as list of Include objects



207
208
209
210
# File 'lib/ceedling/test_context_extractor.rb', line 207

def lookup_nonmock_header_includes_list(filepath)
  includes = lookup_all_header_includes_list(filepath)
  return includes.reject { |include| include.is_a?( MockInclude ) }
end

#lookup_partials_config(filepath) ⇒ Object

List of single item hashes for Partials configuration by test name { => }



214
215
216
217
218
219
220
# File 'lib/ceedling/test_context_extractor.rb', line 214

def lookup_partials_config(filepath)
  val = nil
  @lock.synchronize do
    val = @partials_config[form_file_key( filepath )] || {}
  end
  return val
end

#lookup_source_includes_list(filepath) ⇒ Object

Source C includes as list of Include objects within test file



159
160
161
162
163
164
165
# File 'lib/ceedling/test_context_extractor.rb', line 159

def lookup_source_includes_list(filepath)
  val = nil
  @lock.synchronize do
    val = @source_includes[form_file_key( filepath )] || []
  end
  return val
end

#lookup_test_cases(filepath) ⇒ Object

Test case names as list of strings



177
178
179
180
181
182
183
184
185
186
# File 'lib/ceedling/test_context_extractor.rb', line 177

def lookup_test_cases(filepath)
  val = []
  @lock.synchronize do
    details = @test_runner_details[form_file_key( filepath )]
    if !details.nil?
      val = details[:test_cases]
    end
  end
  return val
end

#lookup_test_runner_generator(filepath) ⇒ Object

Fetch Unity runner generator instance for test file



189
190
191
192
193
194
195
196
197
198
# File 'lib/ceedling/test_context_extractor.rb', line 189

def lookup_test_runner_generator(filepath)
  val = nil
  @lock.synchronize do
    details = @test_runner_details[form_file_key( filepath )]
    if !details.nil?
      val = details[:generator]
    end
  end
  return val
end

#setupObject



43
44
45
46
47
48
49
50
51
52
53
54
55
56
# File 'lib/ceedling/test_context_extractor.rb', line 43

def setup
  # Per test-file lookup hashes
  @header_includes     = {} # Full list of all headers as Include objects from #include statements
  @source_includes     = {} # List of C files #include'd in a test file as Include objects
  @source_extras       = {} # List of C source files as strings outside of header convention added to test build by TEST_SOURCE_FILE()
  @test_runner_details = {} # Test case lists & Unity runner generator instances
  @partials_config     = {} # Hash of module_name => PartializerConfig::Config structs per test file
  @include_paths       = {} # List of additional search paths as strings added to a test build via TEST_INCLUDE_PATH()
  
  # Arrays
  @all_include_paths   = [] # List of all search paths added through individual test files using TEST_INCLUDE_PATH()

  @lock = Mutex.new
end