@@ -99,7 +99,7 @@ def perform_action(message, multiline, mark_fn, on_fail_msg, tally_on_fail, abor
99
99
else
100
100
print line
101
101
end
102
- STDOUT . flush
102
+ $stdout . flush
103
103
result = yield
104
104
mark = mark_fn . nil? ? "" : mark_fn . call ( result )
105
105
# if multline, put checkmark at full width
@@ -125,7 +125,7 @@ def attempt_multiline(message, &block)
125
125
end
126
126
127
127
# Make a nice status for something that kills the script immediately on failure
128
- FAILED_ASSURANCE_MESSAGE = "This may indicate a problem with ArduinoCI, or your configuration" . freeze
128
+ FAILED_ASSURANCE_MESSAGE = "This may indicate a problem with ArduinoCI, or your configuration; halting here " . freeze
129
129
def assure ( message , &block )
130
130
perform_action ( message , false , @passfail , FAILED_ASSURANCE_MESSAGE , true , true , &block )
131
131
end
@@ -145,9 +145,7 @@ def inform_multiline(message, &block)
145
145
# Assure that a platform exists and return its definition
146
146
def assured_platform ( purpose , name , config )
147
147
platform_definition = config . platform_definition ( name )
148
- assure ( "Requested #{ purpose } platform '#{ name } ' is defined in 'platforms' YML" ) do
149
- !platform_definition . nil?
150
- end
148
+ assure ( "Requested #{ purpose } platform '#{ name } ' is defined in 'platforms' YML" ) { !platform_definition . nil? }
151
149
platform_definition
152
150
end
153
151
@@ -177,10 +175,8 @@ def display_files(pathname)
177
175
# @return [Array<String>] The list of installed libraries
178
176
def install_arduino_library_dependencies ( library_names , on_behalf_of , already_installed = [ ] )
179
177
installed = already_installed . clone
180
- library_names . map { |n | @backend . library_of_name ( n ) } . each do |l |
181
- if installed . include? ( l )
182
- # do nothing
183
- elsif l . installed?
178
+ ( library_names . map { |n | @backend . library_of_name ( n ) } - installed ) . each do |l |
179
+ if l . installed?
184
180
inform ( "Using pre-existing dependency of #{ on_behalf_of } " ) { l . name }
185
181
else
186
182
assure ( "Installing dependency of #{ on_behalf_of } : '#{ l . name } '" ) do
@@ -195,30 +191,69 @@ def install_arduino_library_dependencies(library_names, on_behalf_of, already_in
195
191
installed
196
192
end
197
193
198
- def handle_expectation_of_files ( expectation_envvar , operation , filegroup_name , dir_description , dir )
194
+ # @param example_platform_info [Hash] mapping of platform name to package information
195
+ # @param board_package_url [Hash] mapping of package name to URL
196
+ def install_all_packages ( example_platform_info , board_package_url )
197
+ # with all platform info, we can extract unique packages and their urls
198
+ # do that, set the URLs, and download the packages
199
+ all_packages = example_platform_info . values . map { |v | v [ :package ] } . uniq . reject ( &:nil? )
200
+
201
+ # make sure any non-builtin package has a URL defined
202
+ all_packages . each { |p | assure ( "Board package #{ p } has a defined URL" ) { board_package_url [ p ] } }
203
+
204
+ # set up all the board manager URLs.
205
+ # we can safely reject nils now, they would be for the builtins
206
+ all_urls = all_packages . map { |p | board_package_url [ p ] } . uniq . reject ( &:nil? )
207
+ assure ( "Setting board manager URLs" ) { @backend . board_manager_urls = all_urls } unless all_urls . empty?
208
+ all_packages . each { |p | assure ( "Installing board package #{ p } " ) { @backend . install_boards ( p ) } }
209
+ end
210
+
211
+ # @param expectation_envvar [String] the name of the env var to check
212
+ # @param operation [String] a description of what operation we might be skipping
213
+ # @param filegroup_name [String] a description of the set of files without which we effectively skip the operation
214
+ # @param dir_description [String] a description of the directory where we looked for the files
215
+ # @param dir [Pathname] the directory where we looked for the files
216
+ def handle_expectation_of_files ( expectation_envvar , operation , filegroup_name , dir_description , dir_path )
217
+ # alert future me about running the script from the wrong directory, instead of doing the huge file dump
218
+ # otherwise, assume that the user might be running the script on a library with no actual unit tests
219
+ if Pathname . new ( __dir__ ) . parent == Pathname . new ( Dir . pwd )
220
+ inform_multiline ( "arduino_ci seems to be trying to test itself" ) do
221
+ [
222
+ "arduino_ci (the ruby gem) isn't an arduino project itself, so running the CI test script against" ,
223
+ "the core library isn't really a valid thing to do... but it's easy for a developer (including the" ,
224
+ "owner) to mistakenly do just that. Hello future me, you probably meant to run this against one of" ,
225
+ "the sample projects in SampleProjects/ ... if not, please submit a bug report; what a wild case!"
226
+ ] . each { |l | puts " #{ l } " }
227
+ false
228
+ end
229
+ exit ( 1 )
230
+ end
231
+
232
+ # either the directory is empty, or it doesn't exist at all. message accordingly.
233
+ ( problem , dir_desc , dir ) = if dir . exist?
234
+ [ "No #{ filegroup_name } were found in #{ dir } " , dir_description , dir_path ]
235
+ else
236
+ [ "No #{ dir_description } at #{ dir } " , "base directory" , dir_path . parent ]
237
+ end
238
+
239
+ inform ( "#{ problem } , value of #{ expectation_envvar } is" ) { ENV [ expectation_envvar ] }
199
240
if ENV [ expectation_envvar ] . nil?
200
- inform_multiline ( "Skipping #{ operation } ; no #{ filegroup_name } were found in #{ dir } " ) do
201
- puts " In case that's an error, this is what was found in the #{ dir_description } :"
241
+ inform_multiline ( "Skipping #{ operation } " ) do
242
+ puts " In case that's an error, this is what was found in the #{ dir_desc } :"
202
243
display_files ( dir )
203
244
puts "To force an error in this case, set the environment variable #{ expectation_envvar } "
204
245
true
205
246
end
206
247
else
207
- assure_multiline ( "No #{ filegroup_name } were found in #{ dir } and #{ expectation_envvar } was set" ) do
208
- puts " This is what was found in the #{ dir_description } :"
248
+ assure_multiline ( "Dumping project's #{ dir_desc } before exit" ) do
209
249
display_files ( dir )
210
250
false
211
251
end
212
252
end
213
253
end
214
254
215
- def perform_unit_tests ( cpp_library , file_config )
216
- if @cli_options [ :skip_unittests ]
217
- inform ( "Skipping unit tests" ) { "as requested via command line" }
218
- return
219
- end
220
- config = file_config . with_override_config ( @cli_options [ :ci_config ] )
221
-
255
+ # report and return the set of compilers
256
+ def get_annotated_compilers ( config , cpp_library )
222
257
# check GCC
223
258
compilers = config . compilers_to_use
224
259
assure ( "The set of compilers (#{ compilers . length } ) isn't empty" ) { !compilers . empty? }
@@ -232,62 +267,54 @@ def perform_unit_tests(cpp_library, file_config)
232
267
end
233
268
inform ( "libasan availability for #{ gcc_binary } " ) { cpp_library . libasan? ( gcc_binary ) }
234
269
end
270
+ compilers
271
+ end
235
272
236
- # Ensure platforms exist for unit test, and save their info in all_platform_info keyed by name
237
- all_platform_info = { }
238
- config . platforms_to_unittest . each { |p | all_platform_info [ p ] = assured_platform ( "unittest" , p , config ) }
273
+ def perform_unit_tests ( cpp_library , file_config )
274
+ if @cli_options [ :skip_unittests ]
275
+ inform ( "Skipping unit tests" ) { "as requested via command line" }
276
+ return
277
+ end
278
+
279
+ config = file_config . with_override_config ( @cli_options [ :ci_config ] )
280
+ compilers = get_annotated_compilers ( config , cpp_library )
281
+ config . platforms_to_unittest . each_with_object ( { } ) { |p , acc | acc [ p ] = assured_platform ( "unittest" , p , config ) }
239
282
240
283
inform ( "Library conforms to Arduino library specification" ) { cpp_library . one_point_five? ? "1.5" : "1.0" }
241
284
242
- # iterate boards / tests
243
- if !cpp_library . tests_dir . exist?
244
- # alert future me about running the script from the wrong directory, instead of doing the huge file dump
245
- # otherwise, assume that the user might be running the script on a library with no actual unit tests
246
- if Pathname . new ( __dir__ ) . parent == Pathname . new ( Dir . pwd )
247
- inform_multiline ( "arduino_ci seems to be trying to test itself" ) do
248
- [
249
- "arduino_ci (the ruby gem) isn't an arduino project itself, so running the CI test script against" ,
250
- "the core library isn't really a valid thing to do... but it's easy for a developer (including the" ,
251
- "owner) to mistakenly do just that. Hello future me, you probably meant to run this against one of" ,
252
- "the sample projects in SampleProjects/ ... if not, please submit a bug report; what a wild case!"
253
- ] . each { |l | puts " #{ l } " }
254
- false
255
- end
256
- exit ( 1 )
257
- else
258
- inform_multiline ( "Skipping unit tests; no tests dir at #{ cpp_library . tests_dir } " ) do
259
- puts " In case that's an error, this is what was found in the library:"
260
- display_files ( cpp_library . tests_dir . parent )
261
- true
262
- end
263
- end
264
- elsif cpp_library . test_files . empty?
285
+ # Handle lack of test files
286
+ if cpp_library . test_files . empty?
265
287
handle_expectation_of_files ( VAR_EXPECT_UNITTESTS , "unit tests" , "test files" , "tests directory" , cpp_library . tests_dir )
266
- elsif config . platforms_to_unittest . empty?
288
+ return
289
+ end
290
+
291
+ # Handle lack of platforms
292
+ if config . platforms_to_unittest . empty?
267
293
inform ( "Skipping unit tests" ) { "no platforms were requested" }
268
- else
269
- install_arduino_library_dependencies ( config . aux_libraries_for_unittest , "<unittest/libraries>" )
270
-
271
- config . platforms_to_unittest . each do | p |
272
- config . allowable_unittest_files ( cpp_library . test_files ) . each do | unittest_path |
273
- unittest_name = unittest_path . basename . to_s
274
- compilers . each do |gcc_binary |
275
- attempt_multiline ( "Unit testing #{ unittest_name } with #{ gcc_binary } for #{ p } " ) do
276
- exe = cpp_library . build_for_test_with_configuration (
277
- unittest_path ,
278
- config . aux_libraries_for_unittest ,
279
- gcc_binary ,
280
- config . gcc_config ( p )
281
- )
282
- puts
283
- unless exe
284
- puts "Last command: #{ cpp_library . last_cmd } "
285
- puts cpp_library . last_out
286
- puts cpp_library . last_err
287
- next false
288
- end
289
- cpp_library . run_test_file ( exe )
294
+ return
295
+ end
296
+
297
+ install_arduino_library_dependencies ( config . aux_libraries_for_unittest , "<unittest/libraries>" )
298
+
299
+ config . platforms_to_unittest . each do | p |
300
+ config . allowable_unittest_files ( cpp_library . test_files ) . each do |unittest_path |
301
+ unittest_name = unittest_path . basename . to_s
302
+ compilers . each do | gcc_binary |
303
+ attempt_multiline ( "Unit testing #{ unittest_name } with #{ gcc_binary } for #{ p } " ) do
304
+ exe = cpp_library . build_for_test_with_configuration (
305
+ unittest_path ,
306
+ config . aux_libraries_for_unittest ,
307
+ gcc_binary ,
308
+ config . gcc_config ( p )
309
+ )
310
+ puts
311
+ unless exe
312
+ puts "Last command: #{ cpp_library . last_cmd } "
313
+ puts cpp_library . last_out
314
+ puts cpp_library . last_err
315
+ next false
290
316
end
317
+ cpp_library . run_test_file ( exe )
291
318
end
292
319
end
293
320
end
@@ -325,38 +352,14 @@ def perform_example_compilation_tests(cpp_library, config)
325
352
aux_libraries . merge ( ovr_config . aux_libraries_for_build )
326
353
end
327
354
328
- # with all platform info, we can extract unique packages and their urls
329
- # do that, set the URLs, and download the packages
330
- all_packages = example_platform_info . values . map { |v | v [ :package ] } . uniq . reject ( &:nil? )
331
-
332
- # make sure any non-builtin package has a URL defined
333
- all_packages . each do |p |
334
- assure ( "Board package #{ p } has a defined URL" ) { board_package_url [ p ] }
335
- end
336
-
337
- # set up all the board manager URLs.
338
- # we can safely reject nils now, they would be for the builtins
339
- all_urls = all_packages . map { |p | board_package_url [ p ] } . uniq . reject ( &:nil? )
340
-
341
- unless all_urls . empty?
342
- assure ( "Setting board manager URLs" ) do
343
- @backend . board_manager_urls = all_urls
344
- end
345
- end
346
-
347
- all_packages . each do |p |
348
- assure ( "Installing board package #{ p } " ) do
349
- @backend . install_boards ( p )
350
- end
351
- end
352
-
355
+ install_all_packages ( example_platform_info , board_package_url )
353
356
install_arduino_library_dependencies ( aux_libraries , "<compile/libraries>" )
354
357
355
358
if config . platforms_to_build . empty?
356
359
inform ( "Skipping builds" ) { "no platforms were requested" }
357
360
return
358
361
elsif library_examples . empty?
359
- handle_expectation_of_files ( VAR_EXPECT_EXAMPLES , "builds" , "examples" , "the library directory" , installed_library_path )
362
+ handle_expectation_of_files ( VAR_EXPECT_EXAMPLES , "builds" , "examples" , "the examples directory" , cpp_library . examples_dir )
360
363
return
361
364
end
362
365
0 commit comments