From 792672b6528431997b824fa65f02bd990f08efc2 Mon Sep 17 00:00:00 2001 From: Dolf Andringa Date: Sat, 27 Jul 2019 16:19:32 +0800 Subject: [PATCH] #29 include ability to exclude certain directories from compilation --- REFERENCE.md | 8 +++++ SampleProjects/TestSomething/.arduino-ci.yml | 2 ++ .../excludeThis/exclude-this.cpp | 10 +++++++ .../TestSomething/excludeThis/exclude-this.h | 4 +++ exe/arduino_ci_remote.rb | 2 +- lib/arduino_ci/ci_config.rb | 9 ++++++ lib/arduino_ci/cpp_library.rb | 29 +++++++++++++++++-- spec/testsomething_unittests_spec.rb | 4 ++- 8 files changed, 63 insertions(+), 5 deletions(-) create mode 100644 SampleProjects/TestSomething/excludeThis/exclude-this.cpp create mode 100644 SampleProjects/TestSomething/excludeThis/exclude-this.h diff --git a/REFERENCE.md b/REFERENCE.md index ab202fdf..6ddad2d4 100644 --- a/REFERENCE.md +++ b/REFERENCE.md @@ -112,8 +112,16 @@ For your unit tests, in addition to setting specific libraries and platforms, yo Filtering your unit tests may help speed up targeted testing locally, but it is intended primarily as a means to temporarily disable tests between individual commits. +Furthermore, you can filter the files that will be included in the compilation step by specifying `exclude_dirs`. All cpp and header files in those directories will not be included in the compilation step, before the unittests are run. + ```yaml unittest: + + # Exclude these directories from compilation + exclude_dirs: + - someDirectory + - someOtherDirectory + # Perform unit tests with these compilers (these are the binaries that will be called via the shell) compilers: - g++ # default diff --git a/SampleProjects/TestSomething/.arduino-ci.yml b/SampleProjects/TestSomething/.arduino-ci.yml index f9890177..c418bdbe 100644 --- a/SampleProjects/TestSomething/.arduino-ci.yml +++ b/SampleProjects/TestSomething/.arduino-ci.yml @@ -1,4 +1,6 @@ unittest: + exclude_dirs: + - excludeThis platforms: - uno - due diff --git a/SampleProjects/TestSomething/excludeThis/exclude-this.cpp b/SampleProjects/TestSomething/excludeThis/exclude-this.cpp new file mode 100644 index 00000000..639719a7 --- /dev/null +++ b/SampleProjects/TestSomething/excludeThis/exclude-this.cpp @@ -0,0 +1,10 @@ +#include "test-something.h" +int testSomething(void) { + millis(); // this line is only here to test that we're able to refer to the builtins + return 4; +}; + +int* aNullPointer(void) { + int* ret = nullptr; + return ret; +} diff --git a/SampleProjects/TestSomething/excludeThis/exclude-this.h b/SampleProjects/TestSomething/excludeThis/exclude-this.h new file mode 100644 index 00000000..13831ea1 --- /dev/null +++ b/SampleProjects/TestSomething/excludeThis/exclude-this.h @@ -0,0 +1,4 @@ +#pragma once +#include +int testSomething(void); +int *aNullPointer(void); diff --git a/exe/arduino_ci_remote.rb b/exe/arduino_ci_remote.rb index b8998e33..12554124 100755 --- a/exe/arduino_ci_remote.rb +++ b/exe/arduino_ci_remote.rb @@ -173,7 +173,7 @@ def perform_unit_tests(file_config) return end config = file_config.with_override_config(@cli_options[:ci_config]) - cpp_library = ArduinoCI::CppLibrary.new(Pathname.new("."), @arduino_cmd.lib_dir) + cpp_library = ArduinoCI::CppLibrary.new(Pathname.new("."), @arduino_cmd.lib_dir, config.exclude_dirs) # check GCC compilers = config.compilers_to_use diff --git a/lib/arduino_ci/ci_config.rb b/lib/arduino_ci/ci_config.rb index b982f4f4..099258ff 100644 --- a/lib/arduino_ci/ci_config.rb +++ b/lib/arduino_ci/ci_config.rb @@ -28,6 +28,7 @@ compilers: Array, platforms: Array, libraries: Array, + exclude_dirs: Array, testfiles: { select: Array, reject: Array, @@ -256,6 +257,14 @@ def compilers_to_use @unittest_info[:compilers] end + # paths to exclude all files in for building and unitttests + # @return [Array] The directories (relative to base dir) to exclude + def exclude_dirs + return [] if @unittest_info[:exclude_dirs].nil? + + @unittest_info[:exclude_dirs] + end + # platforms to build [the examples on] # @return [Array] The platforms to build def platforms_to_build diff --git a/lib/arduino_ci/cpp_library.rb b/lib/arduino_ci/cpp_library.rb index 644b7800..0b72e6da 100644 --- a/lib/arduino_ci/cpp_library.rb +++ b/lib/arduino_ci/cpp_library.rb @@ -37,11 +37,14 @@ class CppLibrary # @param base_dir [Pathname] The path to the library being tested # @param arduino_lib_dir [Pathname] The path to the libraries directory - def initialize(base_dir, arduino_lib_dir) + def initialize(base_dir, arduino_lib_dir, exclude_dirs = []) raise ArgumentError, 'base_dir is not a Pathname' unless base_dir.is_a? Pathname raise ArgumentError, 'arduino_lib_dir is not a Pathname' unless arduino_lib_dir.is_a? Pathname + raise ArgumentError, 'exclude_dir is not an array of Pathnames' unless exclude_dirs.is_a?(Array) && + exclude_dirs.each { |p| p.is_a? Pathname } @base_dir = base_dir + @exclude_dirs = exclude_dirs @arduino_lib_dir = arduino_lib_dir.expand_path @artifacts = [] @last_err = "" @@ -115,6 +118,19 @@ def in_tests_dir?(path) false end + # Guess whether a file is part of any @excludes_dir dir (indicating library compilation should ignore it). + # + # @param path [Pathname] The path to check + # @return [bool] + def in_exclude_dir?(path) + # we could do this but some rubies don't return an enumerator for ascend + # path.ascend.any? { |part| tests_dir_aliases.include?(part) } + path.ascend do |part| + return true if exclude_dir.any? { |p| p.realpath == part } + end + false + end + # Check whether libasan (and by extension -fsanitizer=address) is supported # # This requires compilation of a sample program, and will be cached @@ -150,7 +166,7 @@ def cpp_files_in(some_dir) # CPP files that are part of the project library under test # @return [Array] def cpp_files - cpp_files_in(@base_dir).reject { |p| vendor_bundle?(p) || in_tests_dir?(p) } + cpp_files_in(@base_dir).reject { |p| vendor_bundle?(p) || in_tests_dir?(p) || in_exclude_dir?(p) } end # CPP files that are part of the arduino mock library we're providing @@ -172,6 +188,12 @@ def cpp_files_libraries(aux_libraries) arduino_library_src_dirs(aux_libraries).map { |d| cpp_files_in(d) }.flatten.uniq end + # Returns the Pathnames for all paths to exclude from testing and compilation + # @return [Array] + def exclude_dir + @exclude_dirs.map { |p| Pathname.new(@base_dir) + p }.select(&:exist?) + end + # The directory where we expect to find unit test defintions provided by the user # @return [Pathname] def tests_dir @@ -190,7 +212,8 @@ def header_dirs real = @base_dir.realpath all_files = Find.find(real).map { |f| Pathname.new(f) }.reject(&:directory?) unbundled = all_files.reject { |path| vendor_bundle?(path) } - files = unbundled.select { |path| HPP_EXTENSIONS.include?(path.extname.downcase) } + unexcluded = unbundled.reject { |path| in_exclude_dir?(path) } + files = unexcluded.select { |path| HPP_EXTENSIONS.include?(path.extname.downcase) } files.map(&:dirname).uniq end diff --git a/spec/testsomething_unittests_spec.rb b/spec/testsomething_unittests_spec.rb index 97d55694..d4e1ed33 100644 --- a/spec/testsomething_unittests_spec.rb +++ b/spec/testsomething_unittests_spec.rb @@ -13,7 +13,9 @@ def get_relative_dir(sampleprojects_tests_dir) RSpec.describe "TestSomething C++" do next if skip_cpp_tests cpp_lib_path = sampleproj_path + "TestSomething" - cpp_library = ArduinoCI::CppLibrary.new(cpp_lib_path, Pathname.new("my_fake_arduino_lib_dir")) + cpp_library = ArduinoCI::CppLibrary.new(cpp_lib_path, + Pathname.new("my_fake_arduino_lib_dir"), + ["excludeThis"]) context "cpp_files" do it "finds cpp files in directory" do testsomething_cpp_files = [Pathname.new("TestSomething/test-something.cpp")]