From 146bd379d810fa7b840fca2c87ef2c8c96db3f9b Mon Sep 17 00:00:00 2001 From: Ian Katz Date: Wed, 30 Jan 2019 13:36:04 -0500 Subject: [PATCH 1/3] Use Pathname properly in CiConfig::allowable_unittest_files --- CHANGELOG.md | 1 + lib/arduino_ci/ci_config.rb | 8 ++++---- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f3347138..24c6de63 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/). ### Added ### Changed +- `CiConfig::allowable_unittest_files` now uses `Pathname` to full effect ### Deprecated diff --git a/lib/arduino_ci/ci_config.rb b/lib/arduino_ci/ci_config.rb index a1d674dd..b982f4f4 100644 --- a/lib/arduino_ci/ci_config.rb +++ b/lib/arduino_ci/ci_config.rb @@ -287,17 +287,17 @@ def aux_libraries_for_unittest end # Config allows select / reject (aka whitelist / blacklist) criteria. Enforce on a dir - # @param paths [Array] the initial set of test files - # @return [Array] files that match the select/reject criteria + # @param paths [Array] the initial set of test files + # @return [Array] files that match the select/reject criteria def allowable_unittest_files(paths) return paths if @unittest_info[:testfiles].nil? ret = paths unless @unittest_info[:testfiles][:select].nil? || @unittest_info[:testfiles][:select].empty? - ret = ret.select { |p| unittest_info[:testfiles][:select].any? { |glob| File.fnmatch(glob, File.basename(p)) } } + ret.select! { |p| unittest_info[:testfiles][:select].any? { |glob| p.basename.fnmatch(glob) } } end unless @unittest_info[:testfiles][:reject].nil? - ret = ret.reject { |p| unittest_info[:testfiles][:reject].any? { |glob| File.fnmatch(glob, File.basename(p)) } } + ret.reject! { |p| unittest_info[:testfiles][:reject].any? { |glob| p.basename.fnmatch(glob) } } end ret end From e707c9e86f9b5618e54162a5d3573e1ba5e7f7e6 Mon Sep 17 00:00:00 2001 From: Ian Katz Date: Wed, 30 Jan 2019 13:38:03 -0500 Subject: [PATCH 2/3] Add sensitivity to ARDUINO_CI_SELECT_CPP_TESTS to narrow the scope of rspec testing C++ files --- CHANGELOG.md | 1 + CONTRIBUTING.md | 3 ++- spec/testsomething_unittests_spec.rb | 8 ++++++++ 3 files changed, 11 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 24c6de63..eb9c374c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/). ## [Unreleased] ### Added +- Added rspec sensitivity to the environment variable `$ARDUINO_CI_SELECT_CPP_TESTS=` (for `arduino_ci` gem hackers) ### Changed - `CiConfig::allowable_unittest_files` now uses `Pathname` to full effect diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 2fd40f23..541d1a6a 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -32,8 +32,9 @@ To speed up testing by targeting only the files you're working on, you can set s * `ARDUINO_CI_SKIP_SPLASH_SCREEN_RSPEC_TESTS`: if set, this will avoid any rspec test that calls the arduino executable (and as such, causes the splash screen to pop up). * `ARDUINO_CI_SKIP_RUBY_RSPEC_TESTS`: if set, this will skip all tests against ruby code (useful if you are not changing Ruby code). * `ARDUINO_CI_SKIP_CPP_RSPEC_TESTS`: if set, this will skip all tests against the `TestSomething` sample project (useful if you are not changing C++ code). +* `ARDUINO_CI_SELECT_CPP_TESTS=`: if set, this will skip all C++ unit tests whose filenames don't match the provided glob (executed in the tests directory) -You can set them to any value, they just have to be set. Example usage: +Example usage: ```shell ARDUINO_CI_SKIP_RUBY_RSPEC_TESTS=1 bundle exec rspec diff --git a/spec/testsomething_unittests_spec.rb b/spec/testsomething_unittests_spec.rb index 3cd16678..97d55694 100644 --- a/spec/testsomething_unittests_spec.rb +++ b/spec/testsomething_unittests_spec.rb @@ -44,6 +44,14 @@ def get_relative_dir(sampleprojects_tests_dir) end test_files = config.allowable_unittest_files(cpp_library.test_files) + + # filter the list based on a glob, if provided + unless ENV["ARDUINO_CI_SELECT_CPP_TESTS"].nil? + Dir.chdir(cpp_library.tests_dir) do + globbed = Pathname.glob(ENV["ARDUINO_CI_SELECT_CPP_TESTS"]) + test_files.select! { |p| globbed.include?(p.basename) } + end + end test_files.each do |path| tfn = File.basename(path) From 36be6caeb9cdc30912117a7de63b080b4e09d0a9 Mon Sep 17 00:00:00 2001 From: Ian Katz Date: Wed, 30 Jan 2019 15:56:41 -0500 Subject: [PATCH 3/3] Fix nullptr and its assertions --- CHANGELOG.md | 4 ++++ SampleProjects/TestSomething/test/null.cpp | 22 ++++++++++++++++++ cpp/arduino/Arduino.h | 5 +---- cpp/arduino/Nullptr.h | 7 ++++++ cpp/unittest/Assertion.h | 2 ++ cpp/unittest/Compare.h | 26 ++++++++++++++++------ 6 files changed, 55 insertions(+), 11 deletions(-) create mode 100644 cpp/arduino/Nullptr.h diff --git a/CHANGELOG.md b/CHANGELOG.md index eb9c374c..390af25b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,15 +8,19 @@ and this project adheres to [Semantic Versioning](http://semver.org/). ## [Unreleased] ### Added - Added rspec sensitivity to the environment variable `$ARDUINO_CI_SELECT_CPP_TESTS=` (for `arduino_ci` gem hackers) +- `assertNotNull()` and `assureNotNull()` C++ comparisons ### Changed - `CiConfig::allowable_unittest_files` now uses `Pathname` to full effect +- `nullptr` now defined in its own class ### Deprecated ### Removed ### Fixed +- Assertions on `nullptr` +- The defintion of `nullptr` ### Security diff --git a/SampleProjects/TestSomething/test/null.cpp b/SampleProjects/TestSomething/test/null.cpp index 27292fe6..834cbf7a 100644 --- a/SampleProjects/TestSomething/test/null.cpp +++ b/SampleProjects/TestSomething/test/null.cpp @@ -22,8 +22,30 @@ unittest(nothing) unittest(nullpointer) { int* myPointer = NULL; + int **notNullPointer = &myPointer; + assertNull(myPointer); assertNull(nullptr); + assertEqual(myPointer, nullptr); + assertNotEqual(nullptr, notNullPointer); + assertNotNull(notNullPointer); +} + +unittest(nullpointer_equal) +{ + int* myPointer = NULL; + int **notNullPointer = &myPointer; + assertEqual(nullptr, myPointer); + assertNotEqual(nullptr, notNullPointer); + + assertLessOrEqual(nullptr, myPointer); + assertMoreOrEqual(myPointer, nullptr); + assertLessOrEqual(nullptr, notNullPointer); + assertMoreOrEqual(notNullPointer, nullptr); + assertLessOrEqual(myPointer, nullptr); + assertMoreOrEqual(notNullPointer, nullptr); + assertLess(nullptr, notNullPointer); + assertMore(notNullPointer, nullptr); } unittest_main() diff --git a/cpp/arduino/Arduino.h b/cpp/arduino/Arduino.h index 7cc69a58..3886e517 100644 --- a/cpp/arduino/Arduino.h +++ b/cpp/arduino/Arduino.h @@ -15,6 +15,7 @@ Where possible, variable names from the Arduino library are used to avoid confli #include "Stream.h" #include "HardwareSerial.h" #include "SPI.h" +#include "Nullptr.h" typedef bool boolean; typedef uint8_t byte; @@ -72,7 +73,3 @@ inline unsigned int makeWord(unsigned char h, unsigned char l) { return (h << 8) #define word(...) makeWord(__VA_ARGS__) -// Define C++11 nullptr -#define nullptr (std::nullptr_t)NULL - - diff --git a/cpp/arduino/Nullptr.h b/cpp/arduino/Nullptr.h new file mode 100644 index 00000000..667ff879 --- /dev/null +++ b/cpp/arduino/Nullptr.h @@ -0,0 +1,7 @@ +#pragma once + +// Define C++11 nullptr +typedef void * my_nullptr_t; +#define nullptr (my_nullptr_t)NULL + +inline std::ostream& operator << (std::ostream& out, const my_nullptr_t &np) { return out << "nullptr"; } diff --git a/cpp/unittest/Assertion.h b/cpp/unittest/Assertion.h index 1231e760..f5e1b129 100644 --- a/cpp/unittest/Assertion.h +++ b/cpp/unittest/Assertion.h @@ -39,6 +39,7 @@ #define assertTrue(arg) assertEqual(true, arg) #define assertFalse(arg) assertEqual(false, arg) #define assertNull(arg) assertEqual((void*)NULL, (void*)arg) +#define assertNotNull(arg) assertNotEqual((void*)NULL, (void*)arg) /** macro generates optional output and calls fail() followed by a return if false. */ #define assureEqual(arg1,arg2) assureOp("assureEqual","expected",arg1,compareEqual,"==","actual",arg2) @@ -50,4 +51,5 @@ #define assureTrue(arg) assureEqual(true, arg) #define assureFalse(arg) assureEqual(false, arg) #define assureNull(arg) assureEqual((void*)NULL, (void*)arg) +#define assureNotNull(arg) assureNotEqual((void*)NULL, (void*)arg) diff --git a/cpp/unittest/Compare.h b/cpp/unittest/Compare.h index 3ae331fb..d6958ea2 100644 --- a/cpp/unittest/Compare.h +++ b/cpp/unittest/Compare.h @@ -1,6 +1,7 @@ #pragma once #include #include +#include template < typename A, typename B > struct Compare { @@ -897,10 +898,21 @@ template < size_t N, size_t M > struct Compare return between(a,b) >= 0; } // moreOrEqual }; -template int compareBetween(const A &a, const B &b) { return Compare::between(a,b); } -template bool compareEqual(const A &a, const B &b) { return Compare::equal(a,b); } -template bool compareNotEqual(const A &a, const B &b) { return Compare::notEqual(a,b); } -template bool compareLess(const A &a, const B &b) { return Compare::less(a,b); } -template bool compareMore(const A &a, const B &b) { return Compare::more(a,b); } -template bool compareLessOrEqual(const A &a, const B &b) { return Compare::lessOrEqual(a,b); } -template bool compareMoreOrEqual(const A &a, const B &b) { return Compare::moreOrEqual(a,b); } + +// null pointer comparisons +template int compareBetween( const my_nullptr_t &a, const B &b) { return Compare::between( a, b); } +template bool compareEqual( const my_nullptr_t &a, const B &b) { return Compare::equal( a, b); } +template bool compareNotEqual( const my_nullptr_t &a, const B &b) { return Compare::notEqual( a, b); } +template bool compareLess( const my_nullptr_t &a, const B &b) { return Compare::less( a, b); } +template bool compareMore( const my_nullptr_t &a, const B &b) { return Compare::more( a, b); } +template bool compareLessOrEqual(const my_nullptr_t &a, const B &b) { return Compare::lessOrEqual(a, b); } +template bool compareMoreOrEqual(const my_nullptr_t &a, const B &b) { return Compare::moreOrEqual(a, b); } + +// super general comparisons +template int compareBetween( const A &a, const B &b) { return Compare::between( a, b); } +template bool compareEqual( const A &a, const B &b) { return Compare::equal( a, b); } +template bool compareNotEqual( const A &a, const B &b) { return Compare::notEqual( a, b); } +template bool compareLess( const A &a, const B &b) { return Compare::less( a, b); } +template bool compareMore( const A &a, const B &b) { return Compare::more( a, b); } +template bool compareLessOrEqual(const A &a, const B &b) { return Compare::lessOrEqual(a, b); } +template bool compareMoreOrEqual(const A &a, const B &b) { return Compare::moreOrEqual(a, b); }