Skip to content

Add support to exclude directories #134

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Sep 3, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/).

## [Unreleased]
### Added
- Unit testing configuration now allows `exclude_dirs` to be set, which prevents stray source files from as part of unit testing allows

### Changed

Expand Down
8 changes: 8 additions & 0 deletions REFERENCE.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 2 additions & 0 deletions SampleProjects/TestSomething/.arduino-ci.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
unittest:
exclude_dirs:
- excludeThis
platforms:
- uno
- due
Expand Down
6 changes: 6 additions & 0 deletions SampleProjects/TestSomething/excludeThis/exclude-this.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
This file intentionally contains syntactically incorrect code
to break unit test compilation. If arduino_ci is working
properly, it should exclude this file (as per .arduino-ci.yml
configuration) and unit test compilation should succeed.

~!@#$%^&*()
6 changes: 6 additions & 0 deletions SampleProjects/TestSomething/excludeThis/exclude-this.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
This file intentionally contains syntactically incorrect code
to break unit test compilation. If arduino_ci is working
properly, it should exclude this file (as per .arduino-ci.yml
configuration) and unit test compilation should succeed.

~!@#$%^&*()
2 changes: 1 addition & 1 deletion arduino_ci.gemspec
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ Gem::Specification.new do |spec|
spec.add_dependency "os", "~> 1.0"
spec.add_dependency "rubyzip", "~> 1.2"

spec.add_development_dependency "bundler", "~> 1.15"
spec.add_development_dependency "bundler", "> 1.15"
spec.add_development_dependency "keepachangelog_manager", "~> 0.0.2"
spec.add_development_dependency "rspec", "~> 3.0"
spec.add_development_dependency 'rubocop', '~>0.59.0'
Expand Down
4 changes: 3 additions & 1 deletion exe/arduino_ci_remote.rb
Original file line number Diff line number Diff line change
Expand Up @@ -183,7 +183,9 @@ 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.map(&Pathname.method(:new)))

# check GCC
compilers = config.compilers_to_use
Expand Down
9 changes: 9 additions & 0 deletions lib/arduino_ci/ci_config.rb
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
compilers: Array,
platforms: Array,
libraries: Array,
exclude_dirs: Array,
testfiles: {
select: Array,
reject: Array,
Expand Down Expand Up @@ -256,6 +257,14 @@ def compilers_to_use
@unittest_info[:compilers]
end

# paths to exclude all files in for building and unitttests
# @return [Array<String>] 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<String>] The platforms to build
def platforms_to_build
Expand Down
30 changes: 27 additions & 3 deletions lib/arduino_ci/cpp_library.rb
Original file line number Diff line number Diff line change
Expand Up @@ -37,11 +37,15 @@ 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)
# @param exclude_dirs [Array<Pathname>] Directories that should be excluded from compilation
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)
raise ArgumentError, 'exclude_dir array contains non-Pathname elements' unless exclude_dirs.all? { |p| p.is_a? Pathname }

@base_dir = base_dir
@exclude_dirs = exclude_dirs
@arduino_lib_dir = arduino_lib_dir.expand_path
@artifacts = []
@last_err = ""
Expand Down Expand Up @@ -115,6 +119,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
Expand Down Expand Up @@ -150,7 +167,7 @@ def cpp_files_in(some_dir)
# CPP files that are part of the project library under test
# @return [Array<Pathname>]
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
Expand All @@ -172,6 +189,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<Pathname>]
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
Expand All @@ -190,7 +213,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

Expand Down
3 changes: 1 addition & 2 deletions spec/ci_config_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,7 @@

context "allowable_unittest_files" do
cpp_lib_path = Pathname.new(__dir__) + "fake_library"
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"), [])

it "starts with a known set of files" do
expect(cpp_library.test_files.map { |f| File.basename(f) }).to match_array([
Expand All @@ -177,4 +177,3 @@
end

end

2 changes: 1 addition & 1 deletion spec/cpp_library_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ def get_relative_dir(sampleprojects_tests_dir)
RSpec.describe ArduinoCI::CppLibrary do
next if skip_ruby_tests
cpp_lib_path = sampleproj_path + "DoSomething"
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"), [])
context "cpp_files" do
it "finds cpp files in directory" do
dosomething_cpp_files = [Pathname.new("DoSomething") + "do-something.cpp"]
Expand Down
36 changes: 35 additions & 1 deletion spec/testsomething_unittests_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,44 @@ def get_relative_dir(sampleprojects_tests_dir)
sampleprojects_tests_dir.relative_path_from(base_dir)
end

RSpec.describe "TestSomething C++ without excludes" 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"),
[])
context "cpp_files" do
it "finds cpp files in directory" do
testsomething_cpp_files = [
Pathname.new("TestSomething/test-something.cpp"),
Pathname.new("TestSomething/excludeThis/exclude-this.cpp")
]
relative_paths = cpp_library.cpp_files.map { |f| get_relative_dir(f) }
expect(relative_paths).to match_array(testsomething_cpp_files)
end
end

context "unit tests" do
it "can't build due to files that should have been excluded" do
config = ArduinoCI::CIConfig.default.from_example(cpp_lib_path)
path = config.allowable_unittest_files(cpp_library.test_files).first
compiler = config.compilers_to_use.first
result = cpp_library.build_for_test_with_configuration(path,
[],
compiler,
config.gcc_config("uno"))
expect(result).to be nil
end
end

end

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"].map(&Pathname.method(:new)))
context "cpp_files" do
it "finds cpp files in directory" do
testsomething_cpp_files = [Pathname.new("TestSomething/test-something.cpp")]
Expand Down