From 0750d59aeacdcd04239fc9809a3f92323aeb7782 Mon Sep 17 00:00:00 2001 From: James Foster Date: Mon, 15 Feb 2021 10:47:58 -0800 Subject: [PATCH 01/36] Set all text files to have endings --- .gitattributes | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitattributes b/.gitattributes index 4282322a..d56abbf3 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,2 +1,2 @@ # Set the default behavior, in case people don't have core.autocrlf set. -* text eol=lf +* text=auto eol=lf From 32a021896cfb00f41170cd876ca8684bcb372530 Mon Sep 17 00:00:00 2001 From: James Foster Date: Mon, 15 Feb 2021 10:58:04 -0800 Subject: [PATCH 02/36] Update workflow to test on push. --- .github/workflows/README.md | 2 +- .github/workflows/linux.yaml | 2 +- .github/workflows/macos.yaml | 2 +- .github/workflows/windows.yaml | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/README.md b/.github/workflows/README.md index 7e1b5195..0e2ce744 100644 --- a/.github/workflows/README.md +++ b/.github/workflows/README.md @@ -7,4 +7,4 @@ In this project, we define a workflow for each target platform. **If you're loo The reason that all platforms are tested in _this_ project is to ensure that, as a framework, `arduino_ci` will run properly on any developer's personal workstation (regardless of OS). -For testing an individual Arduino library in the context of GitHub, [Linux is the cheapest option](https://docs.github.com/en/free-pro-team@latest/github/setting-up-and-managing-billing-and-payments-on-github/about-billing-for-github-actions) and produces results identical to the other OSes. +For testing an individual Arduino library in the context of GitHub, [Linux is the cheapest option](https://docs.github.com/en/free-pro-team@latest/github/setting-up-and-managing-billing-and-payments-on-github/about-billing-for-github-actions) and should produce results identical to the other OSes. diff --git a/.github/workflows/linux.yaml b/.github/workflows/linux.yaml index 8a05f584..9c9247a8 100644 --- a/.github/workflows/linux.yaml +++ b/.github/workflows/linux.yaml @@ -1,7 +1,7 @@ # This is the name of the workflow, visible on GitHub UI name: linux -on: [pull_request] +on: [push, pull_request] jobs: "unittest_lint_sampleproject": diff --git a/.github/workflows/macos.yaml b/.github/workflows/macos.yaml index ffd88f9d..96357648 100644 --- a/.github/workflows/macos.yaml +++ b/.github/workflows/macos.yaml @@ -1,7 +1,7 @@ # This is the name of the workflow, visible on GitHub UI name: macos -on: [pull_request] +on: [push, pull_request] jobs: "unittest_lint_sampleproject": diff --git a/.github/workflows/windows.yaml b/.github/workflows/windows.yaml index 6001624e..6a4afa72 100644 --- a/.github/workflows/windows.yaml +++ b/.github/workflows/windows.yaml @@ -1,7 +1,7 @@ # This is the name of the workflow, visible on GitHub UI name: windows -on: [pull_request] +on: [push, pull_request] jobs: "unittest_lint_sampleproject": From aed9f3832b26f79b85ea46ebe931d9b13a8a6eb3 Mon Sep 17 00:00:00 2001 From: James Foster Date: Mon, 15 Feb 2021 11:43:26 -0800 Subject: [PATCH 03/36] Add to CHANGELOG.md --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0cac76ad..bd451c6f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/). ### Added ### Changed +- Run tests on push as well as on a pull request so developers can see impact ### Deprecated From 9a76e705ae5ade724727e339428b68b5e84af474 Mon Sep 17 00:00:00 2001 From: James Foster Date: Mon, 15 Feb 2021 11:47:59 -0800 Subject: [PATCH 04/36] Update CHANGELOG.md to describe line endings change. --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0cac76ad..9a37941b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/). ### Added ### Changed +- Update .gitattributes so we have consistent line endings ### Deprecated From c88d7d7a51c6339e96763d0c0c22ef2f7d5da7b9 Mon Sep 17 00:00:00 2001 From: James Foster Date: Mon, 15 Feb 2021 20:31:07 -0800 Subject: [PATCH 05/36] Update to more descriptive line ending handling. --- .gitattributes | 32 ++++++++++++++++++++++++++++++-- 1 file changed, 30 insertions(+), 2 deletions(-) diff --git a/.gitattributes b/.gitattributes index d56abbf3..3f9aff51 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,2 +1,30 @@ -# Set the default behavior, in case people don't have core.autocrlf set. -* text=auto eol=lf +# https://docs.github.com/en/github/using-git/configuring-git-to-handle-line-endings +# https://git-scm.com/docs/gitattributes +# https://git-scm.com/docs/git-config +# https://adaptivepatchwork.com/2012/03/01/mind-the-end-of-your-line/ + +# Configure this repository to use Git's type detection algorithm to guess +# whether a file is text or binary. Text files will have line endings converted +# as if you had set +# eol=native +# That is, on Windows text files will have CRLF line endings in your working +# directory while on Linux and macOS your text files will have LF line endings +# in your working directory. In either case, they will have LF line endings in +# the Git repository itself. + +* text=auto + +# Explicitly declare text files you want to always be normalized and converted +# to native line endings on checkout. Git would likely get these right, but +# we can be sure by adding them here. +*.c text +*.cpp text +*.h text +*.md text +*.yaml text +*.yml text + +# Denote all files that are truly binary and should not be modified. +# Even if we don't have any of these, they make a good example. +*.png binary +*.jpg binary From 4648fda122b2c8ae96468d32ea1be7f7d48f0dbc Mon Sep 17 00:00:00 2001 From: James Foster Date: Tue, 16 Feb 2021 12:06:20 -0800 Subject: [PATCH 06/36] Use `before(:each)` rather than `before(:all)` as recommended [here](https://makandracards.com/makandra/11507-using-before-all-in-rspec-will-cause-you-lots-of-trouble-unless-you-know-what-you-are-doing) to fix #288. --- spec/testsomething_unittests_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/testsomething_unittests_spec.rb b/spec/testsomething_unittests_spec.rb index c882399f..bf3f9f62 100644 --- a/spec/testsomething_unittests_spec.rb +++ b/spec/testsomething_unittests_spec.rb @@ -72,7 +72,7 @@ context "file #{tfn} (using #{compiler})" do around(:example) { |example| fld.in_pristine_fake_libraries_dir(example) } - before(:all) do + before(:each) do @cpp_library = backend.install_local_library(cpp_lib_path) @exe = @cpp_library.build_for_test_with_configuration(path, [], compiler, config.gcc_config("uno")) end From 90c5504989cc50524ae115b1d1397e11b2d64e98 Mon Sep 17 00:00:00 2001 From: James Foster Date: Tue, 23 Feb 2021 12:02:24 -0800 Subject: [PATCH 07/36] Hide build artifacts. --- lib/arduino_ci/cpp_library.rb | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/lib/arduino_ci/cpp_library.rb b/lib/arduino_ci/cpp_library.rb index 4ad7307f..eb609855 100644 --- a/lib/arduino_ci/cpp_library.rb +++ b/lib/arduino_ci/cpp_library.rb @@ -491,7 +491,10 @@ def test_args(aux_libraries, ci_gcc_config) # @return [Pathname] path to the compiled test executable def build_for_test_with_configuration(test_file, aux_libraries, gcc_binary, ci_gcc_config) base = test_file.basename - executable = Pathname.new("unittest_#{base}.bin").expand_path + # hide build artifacts + build_dir = '.arduino_ci' + Dir.mkdir build_dir unless File.exists?(build_dir) + executable = Pathname.new("#{build_dir}/unittest_#{base}.bin").expand_path File.delete(executable) if File.exist?(executable) arg_sets = [] arg_sets << ["-std=c++0x", "-o", executable.to_s, "-DARDUINO=100"] From 86c8e953a67d4186887bef1f6901c6afd023bed3 Mon Sep 17 00:00:00 2001 From: James Foster Date: Tue, 23 Feb 2021 12:06:01 -0800 Subject: [PATCH 08/36] Add note to CHANGELOG.md. --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0cac76ad..df675d54 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/). ### Added ### Changed +- Put build artifacts in a separate directory to reduce clutter. ### Deprecated From a516e7c0f691935afb1bce199c70375eda5ca563 Mon Sep 17 00:00:00 2001 From: James Foster Date: Tue, 23 Feb 2021 12:14:29 -0800 Subject: [PATCH 09/36] Reeplace deprecated function call. --- lib/arduino_ci/cpp_library.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/arduino_ci/cpp_library.rb b/lib/arduino_ci/cpp_library.rb index eb609855..cedd3ba2 100644 --- a/lib/arduino_ci/cpp_library.rb +++ b/lib/arduino_ci/cpp_library.rb @@ -493,7 +493,7 @@ def build_for_test_with_configuration(test_file, aux_libraries, gcc_binary, ci_g base = test_file.basename # hide build artifacts build_dir = '.arduino_ci' - Dir.mkdir build_dir unless File.exists?(build_dir) + Dir.mkdir build_dir unless File.exist?(build_dir) executable = Pathname.new("#{build_dir}/unittest_#{base}.bin").expand_path File.delete(executable) if File.exist?(executable) arg_sets = [] From 4667db94582ecb63afe1f1f61661352e3627f723 Mon Sep 17 00:00:00 2001 From: James Foster Date: Wed, 24 Mar 2021 00:17:07 -0700 Subject: [PATCH 10/36] Speed up tests by building a shared library with everything but the tests and reusing it for each test. --- .gitignore | 2 ++ exe/arduino_ci.rb | 24 ++++++++++++++--- lib/arduino_ci/cpp_library.rb | 51 +++++++++++++++++++++++++---------- 3 files changed, 60 insertions(+), 17 deletions(-) diff --git a/.gitignore b/.gitignore index 2b5aa6a7..ea2d3da0 100644 --- a/.gitignore +++ b/.gitignore @@ -15,3 +15,5 @@ vendor # C++ stuff *.bin *.bin.dSYM +*.so +*.so.dSYM diff --git a/exe/arduino_ci.rb b/exe/arduino_ci.rb index 01234e7c..9e5c2be5 100755 --- a/exe/arduino_ci.rb +++ b/exe/arduino_ci.rb @@ -416,9 +416,27 @@ def perform_unit_tests(cpp_library, file_config) platforms.each do |p| puts - config.allowable_unittest_files(cpp_library.test_files).each do |unittest_path| - unittest_name = unittest_path.basename.to_s - compilers.each do |gcc_binary| + compilers.each do |gcc_binary| + # before compiling the tests, build a shared library of everything except the test code + attempt_multiline("Build shared library with #{gcc_binary} for #{p}") do + exe = cpp_library.build_for_test_with_configuration( + nil, # nil is a flag that we are building the shared library with everything else + config.aux_libraries_for_unittest, + gcc_binary, + config.gcc_config(p) + ) + puts + unless exe + puts "Last command: #{cpp_library.last_cmd}" + puts cpp_library.last_out + puts cpp_library.last_err + next false + end + true + end + # now build and run each test using the shared library build above + config.allowable_unittest_files(cpp_library.test_files).each do |unittest_path| + unittest_name = unittest_path.basename.to_s attempt_multiline("Unit testing #{unittest_name} with #{gcc_binary} for #{p}") do exe = cpp_library.build_for_test_with_configuration( unittest_path, diff --git a/lib/arduino_ci/cpp_library.rb b/lib/arduino_ci/cpp_library.rb index 4ad7307f..e40ab2e8 100644 --- a/lib/arduino_ci/cpp_library.rb +++ b/lib/arduino_ci/cpp_library.rb @@ -41,6 +41,12 @@ class CppLibrary # @return [Array] Directories suspected of being vendor-bundle attr_reader :vendor_bundle_cache + # @return [Array] Libraries we are dependent on + @@full_dependencies + + # @return [Array] Compiler arguments, including include directories, but not .cpp files + @@test_args + # @param friendly_name [String] The "official" name of the library, which can contain spaces # @param backend [ArduinoBackend] The support backend def initialize(friendly_name, backend) @@ -471,9 +477,9 @@ def flag_args(ci_gcc_config) def test_args(aux_libraries, ci_gcc_config) # TODO: something with libraries? ret = include_args(aux_libraries) - ret += cpp_files_arduino.map(&:to_s) - ret += cpp_files_unittest.map(&:to_s) - ret += cpp_files.map(&:to_s) + # ret += cpp_files_arduino.map(&:to_s) + # ret += cpp_files_unittest.map(&:to_s) + # ret += cpp_files.map(&:to_s) unless ci_gcc_config.nil? cgc = ci_gcc_config ret = feature_args(cgc) + warning_args(cgc) + define_args(cgc) + flag_args(cgc) + ret @@ -485,16 +491,26 @@ def test_args(aux_libraries, ci_gcc_config) # # The dependent libraries configuration is appended with data from library.properties internal to the library under test # - # @param test_file [Pathname] The path to the file containing the unit tests + # @param test_file [Pathname] The path to the file containing the unit tests (nil to compile application as shared library) # @param aux_libraries [Array] The external Arduino libraries required by this project # @param ci_gcc_config [Hash] The GCC config object # @return [Pathname] path to the compiled test executable def build_for_test_with_configuration(test_file, aux_libraries, gcc_binary, ci_gcc_config) - base = test_file.basename - executable = Pathname.new("unittest_#{base}.bin").expand_path - File.delete(executable) if File.exist?(executable) arg_sets = [] - arg_sets << ["-std=c++0x", "-o", executable.to_s, "-DARDUINO=100"] + arg_sets << ["-std=c++0x"] + if test_file.nil? + executable = Pathname.new("libarduino.so").expand_path + arg_sets << ["-shared", "-fPIC", "-Wl,-undefined,dynamic_lookup"] + # the following two take some time, so are cached when we build the shared library + @@full_dependencies = all_arduino_library_dependencies!(aux_libraries) + @@test_args = test_args(@@full_dependencies, ci_gcc_config) + else + base = test_file.basename + executable = Pathname.new("unittest_#{base}.bin").expand_path + end + arg_sets << ["-o", executable.to_s, "-L."] + File.delete(executable) if File.exist?(executable) + arg_sets << ["-DARDUINO=100"] if libasan?(gcc_binary) arg_sets << [ # Stuff to help with dynamic memory mishandling "-g", "-O1", @@ -504,15 +520,22 @@ def build_for_test_with_configuration(test_file, aux_libraries, gcc_binary, ci_g ] end + # puts "#{Time.now.to_s} arg_sets" # = #{arg_sets.to_s}" # combine library.properties defs (if existing) with config file. # TODO: as much as I'd like to rely only on the properties file(s), I think that would prevent testing 1.0-spec libs - full_dependencies = all_arduino_library_dependencies!(aux_libraries) - arg_sets << test_args(full_dependencies, ci_gcc_config) - arg_sets << cpp_files_libraries(full_dependencies).map(&:to_s) - arg_sets << [test_file.to_s] - args = arg_sets.flatten(1) - return nil unless run_gcc(gcc_binary, *args) + arg_sets << @@test_args # used cached value since building full set of include directories can take time + + if test_file.nil? # CPP files for the shared library + arg_sets << cpp_files_arduino.map(&:to_s) # Arduino.cpp, Godmode.cpp, and stdlib.cpp + arg_sets << cpp_files_unittest.map(&:to_s) # ArduinoUnitTests.cpp + arg_sets << cpp_files.map(&:to_s) # CPP files for the primary application library under test + arg_sets << cpp_files_libraries(@@full_dependencies).map(&:to_s) # CPP files for all the libraries we depend on + else # add the test file and the shared library + arg_sets << [test_file.to_s, "-larduino"] + end + args = arg_sets.flatten(1) + return nil unless run_gcc(gcc_binary, *args) # 0:54 artifacts << executable executable end From 2284f1d4a969118fce3c86d9a7e8d555ec3e839e Mon Sep 17 00:00:00 2001 From: James Foster Date: Wed, 24 Mar 2021 00:26:28 -0700 Subject: [PATCH 11/36] Add meaningful comments and remove commented-out code. --- CHANGELOG.md | 1 + lib/arduino_ci/cpp_library.rb | 8 +++----- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0cac76ad..a63c3d98 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/). ### Added ### Changed +- We now compile a shared library to be used for each test ### Deprecated diff --git a/lib/arduino_ci/cpp_library.rb b/lib/arduino_ci/cpp_library.rb index e40ab2e8..2aac142b 100644 --- a/lib/arduino_ci/cpp_library.rb +++ b/lib/arduino_ci/cpp_library.rb @@ -470,16 +470,15 @@ def flag_args(ci_gcc_config) ci_gcc_config[:flags] end - # All GCC command line args for building any unit test + # All non-CPP GCC command line args for building any unit test. + # We leave out the CPP files so they can be included or not + # depending on whether we are building a shared library. # @param aux_libraries [Array] The external Arduino libraries required by this project # @param ci_gcc_config [Hash] The GCC config object # @return [Array] GCC command-line flags def test_args(aux_libraries, ci_gcc_config) # TODO: something with libraries? ret = include_args(aux_libraries) - # ret += cpp_files_arduino.map(&:to_s) - # ret += cpp_files_unittest.map(&:to_s) - # ret += cpp_files.map(&:to_s) unless ci_gcc_config.nil? cgc = ci_gcc_config ret = feature_args(cgc) + warning_args(cgc) + define_args(cgc) + flag_args(cgc) + ret @@ -520,7 +519,6 @@ def build_for_test_with_configuration(test_file, aux_libraries, gcc_binary, ci_g ] end - # puts "#{Time.now.to_s} arg_sets" # = #{arg_sets.to_s}" # combine library.properties defs (if existing) with config file. # TODO: as much as I'd like to rely only on the properties file(s), I think that would prevent testing 1.0-spec libs arg_sets << @@test_args # used cached value since building full set of include directories can take time From 452cf0826aefb038f685049cf2929ddd68dba5d0 Mon Sep 17 00:00:00 2001 From: James Foster Date: Wed, 24 Mar 2021 00:59:13 -0700 Subject: [PATCH 12/36] See if this fixes the lint complaints. --- lib/arduino_ci/cpp_library.rb | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) diff --git a/lib/arduino_ci/cpp_library.rb b/lib/arduino_ci/cpp_library.rb index 2aac142b..2972b720 100644 --- a/lib/arduino_ci/cpp_library.rb +++ b/lib/arduino_ci/cpp_library.rb @@ -41,12 +41,6 @@ class CppLibrary # @return [Array] Directories suspected of being vendor-bundle attr_reader :vendor_bundle_cache - # @return [Array] Libraries we are dependent on - @@full_dependencies - - # @return [Array] Compiler arguments, including include directories, but not .cpp files - @@test_args - # @param friendly_name [String] The "official" name of the library, which can contain spaces # @param backend [ArduinoBackend] The support backend def initialize(friendly_name, backend) @@ -501,8 +495,8 @@ def build_for_test_with_configuration(test_file, aux_libraries, gcc_binary, ci_g executable = Pathname.new("libarduino.so").expand_path arg_sets << ["-shared", "-fPIC", "-Wl,-undefined,dynamic_lookup"] # the following two take some time, so are cached when we build the shared library - @@full_dependencies = all_arduino_library_dependencies!(aux_libraries) - @@test_args = test_args(@@full_dependencies, ci_gcc_config) + @full_dependencies = all_arduino_library_dependencies!(aux_libraries) + @test_args = test_args(@full_dependencies, ci_gcc_config) else base = test_file.basename executable = Pathname.new("unittest_#{base}.bin").expand_path @@ -521,19 +515,20 @@ def build_for_test_with_configuration(test_file, aux_libraries, gcc_binary, ci_g # combine library.properties defs (if existing) with config file. # TODO: as much as I'd like to rely only on the properties file(s), I think that would prevent testing 1.0-spec libs - arg_sets << @@test_args # used cached value since building full set of include directories can take time + arg_sets << @test_args # used cached value since building full set of include directories can take time if test_file.nil? # CPP files for the shared library arg_sets << cpp_files_arduino.map(&:to_s) # Arduino.cpp, Godmode.cpp, and stdlib.cpp arg_sets << cpp_files_unittest.map(&:to_s) # ArduinoUnitTests.cpp arg_sets << cpp_files.map(&:to_s) # CPP files for the primary application library under test - arg_sets << cpp_files_libraries(@@full_dependencies).map(&:to_s) # CPP files for all the libraries we depend on + arg_sets << cpp_files_libraries(@full_dependencies).map(&:to_s) # CPP files for all the libraries we depend on else # add the test file and the shared library arg_sets << [test_file.to_s, "-larduino"] end args = arg_sets.flatten(1) - return nil unless run_gcc(gcc_binary, *args) # 0:54 + return nil unless run_gcc(gcc_binary, *args) + artifacts << executable executable end From 24c37b6b3927ef69ae284bd70a8e313382c0b74a Mon Sep 17 00:00:00 2001 From: James Foster Date: Wed, 24 Mar 2021 07:12:58 -0700 Subject: [PATCH 13/36] Build single test executable if we don't have a shared library. --- lib/arduino_ci/cpp_library.rb | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/lib/arduino_ci/cpp_library.rb b/lib/arduino_ci/cpp_library.rb index 2972b720..e31076ed 100644 --- a/lib/arduino_ci/cpp_library.rb +++ b/lib/arduino_ci/cpp_library.rb @@ -494,9 +494,6 @@ def build_for_test_with_configuration(test_file, aux_libraries, gcc_binary, ci_g if test_file.nil? executable = Pathname.new("libarduino.so").expand_path arg_sets << ["-shared", "-fPIC", "-Wl,-undefined,dynamic_lookup"] - # the following two take some time, so are cached when we build the shared library - @full_dependencies = all_arduino_library_dependencies!(aux_libraries) - @test_args = test_args(@full_dependencies, ci_gcc_config) else base = test_file.basename executable = Pathname.new("unittest_#{base}.bin").expand_path @@ -515,15 +512,19 @@ def build_for_test_with_configuration(test_file, aux_libraries, gcc_binary, ci_g # combine library.properties defs (if existing) with config file. # TODO: as much as I'd like to rely only on the properties file(s), I think that would prevent testing 1.0-spec libs + # the following two take some time, so are cached when we build the shared library + @full_dependencies ||= all_arduino_library_dependencies!(aux_libraries) + @test_args ||= test_args(@full_dependencies, ci_gcc_config) arg_sets << @test_args # used cached value since building full set of include directories can take time - if test_file.nil? # CPP files for the shared library + if File.exists?("libarduino.so") # add the test file and the shared library + arg_sets << [test_file.to_s, "-larduino"] + else # CPP files for the shared library arg_sets << cpp_files_arduino.map(&:to_s) # Arduino.cpp, Godmode.cpp, and stdlib.cpp arg_sets << cpp_files_unittest.map(&:to_s) # ArduinoUnitTests.cpp arg_sets << cpp_files.map(&:to_s) # CPP files for the primary application library under test arg_sets << cpp_files_libraries(@full_dependencies).map(&:to_s) # CPP files for all the libraries we depend on - else # add the test file and the shared library - arg_sets << [test_file.to_s, "-larduino"] + arg_sets << [test_file.to_s] if test_file end args = arg_sets.flatten(1) From 432828f6415214c4579c0f5cb7fe0a33c75b4751 Mon Sep 17 00:00:00 2001 From: James Foster Date: Wed, 24 Mar 2021 07:15:55 -0700 Subject: [PATCH 14/36] Use `File.exist?()` instead of `File.exists?()`. --- lib/arduino_ci/cpp_library.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/arduino_ci/cpp_library.rb b/lib/arduino_ci/cpp_library.rb index e31076ed..9d0c8cb4 100644 --- a/lib/arduino_ci/cpp_library.rb +++ b/lib/arduino_ci/cpp_library.rb @@ -517,7 +517,7 @@ def build_for_test_with_configuration(test_file, aux_libraries, gcc_binary, ci_g @test_args ||= test_args(@full_dependencies, ci_gcc_config) arg_sets << @test_args # used cached value since building full set of include directories can take time - if File.exists?("libarduino.so") # add the test file and the shared library + if File.exist?("libarduino.so") # add the test file and the shared library arg_sets << [test_file.to_s, "-larduino"] else # CPP files for the shared library arg_sets << cpp_files_arduino.map(&:to_s) # Arduino.cpp, Godmode.cpp, and stdlib.cpp From 009f7327bd630951109484881d72e5f8d7cdf9c0 Mon Sep 17 00:00:00 2001 From: James Foster Date: Wed, 24 Mar 2021 08:24:08 -0700 Subject: [PATCH 15/36] Set LD_LIBRARY_PATH to directory with shared library. --- lib/arduino_ci/cpp_library.rb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/arduino_ci/cpp_library.rb b/lib/arduino_ci/cpp_library.rb index 9d0c8cb4..5f810115 100644 --- a/lib/arduino_ci/cpp_library.rb +++ b/lib/arduino_ci/cpp_library.rb @@ -498,7 +498,8 @@ def build_for_test_with_configuration(test_file, aux_libraries, gcc_binary, ci_g base = test_file.basename executable = Pathname.new("unittest_#{base}.bin").expand_path end - arg_sets << ["-o", executable.to_s, "-L."] + ENV["$LD_LIBRARY_PATH"]=Dir.pwd + arg_sets << ["-o", executable.to_s, "-L" + Dir.pwd] File.delete(executable) if File.exist?(executable) arg_sets << ["-DARDUINO=100"] if libasan?(gcc_binary) From e24ec9e713e58e9dbcd5443a5127bb8bd4c0c09b Mon Sep 17 00:00:00 2001 From: James Foster Date: Wed, 24 Mar 2021 08:35:04 -0700 Subject: [PATCH 16/36] Fix formatting (lint) issue. --- lib/arduino_ci/cpp_library.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/arduino_ci/cpp_library.rb b/lib/arduino_ci/cpp_library.rb index 5f810115..77495ff2 100644 --- a/lib/arduino_ci/cpp_library.rb +++ b/lib/arduino_ci/cpp_library.rb @@ -498,7 +498,7 @@ def build_for_test_with_configuration(test_file, aux_libraries, gcc_binary, ci_g base = test_file.basename executable = Pathname.new("unittest_#{base}.bin").expand_path end - ENV["$LD_LIBRARY_PATH"]=Dir.pwd + ENV["$LD_LIBRARY_PATH"] = Dir.pwd arg_sets << ["-o", executable.to_s, "-L" + Dir.pwd] File.delete(executable) if File.exist?(executable) arg_sets << ["-DARDUINO=100"] From 2f5153f62091b8424d5a2a7eea1b2c1ac0c96ab3 Mon Sep 17 00:00:00 2001 From: James Foster Date: Wed, 24 Mar 2021 08:52:39 -0700 Subject: [PATCH 17/36] Should find LD_LIBRARY_PATH on Linux. --- lib/arduino_ci/cpp_library.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/arduino_ci/cpp_library.rb b/lib/arduino_ci/cpp_library.rb index 77495ff2..aa9342b5 100644 --- a/lib/arduino_ci/cpp_library.rb +++ b/lib/arduino_ci/cpp_library.rb @@ -498,7 +498,7 @@ def build_for_test_with_configuration(test_file, aux_libraries, gcc_binary, ci_g base = test_file.basename executable = Pathname.new("unittest_#{base}.bin").expand_path end - ENV["$LD_LIBRARY_PATH"] = Dir.pwd + ENV["LD_LIBRARY_PATH"] = Dir.pwd arg_sets << ["-o", executable.to_s, "-L" + Dir.pwd] File.delete(executable) if File.exist?(executable) arg_sets << ["-DARDUINO=100"] From aa2ad44e6acde032904638d2ef546fde0577622d Mon Sep 17 00:00:00 2001 From: Ian Date: Tue, 6 Apr 2021 16:56:38 -0400 Subject: [PATCH 18/36] Update gitattributes as per PR discussion via https://github.com/Arduino-CI/arduino_ci/pull/285/ --- .gitattributes | 26 ++++++++++++++++++-------- 1 file changed, 18 insertions(+), 8 deletions(-) diff --git a/.gitattributes b/.gitattributes index 3f9aff51..640e8d08 100644 --- a/.gitattributes +++ b/.gitattributes @@ -12,19 +12,29 @@ # in your working directory. In either case, they will have LF line endings in # the Git repository itself. +# Set the default behavior, in case people don't have core.autocrlf set. * text=auto # Explicitly declare text files you want to always be normalized and converted # to native line endings on checkout. Git would likely get these right, but # we can be sure by adding them here. -*.c text -*.cpp text -*.h text -*.md text -*.yaml text -*.yml text +*.ino text diff=cpp +*.c text diff=c +*.cc text diff=cpp +*.cxx text diff=cpp +*.cpp text diff=cpp +*.c++ text diff=cpp +*.hpp text diff=cpp +*.h text diff=c +*.h++ text diff=cpp +*.hh text diff=cpp + +*.md text +*.yaml text +*.yml text + # Denote all files that are truly binary and should not be modified. # Even if we don't have any of these, they make a good example. -*.png binary -*.jpg binary +*.png binary +*.jpg binary From e67d2e92981f2ce08c45a5861a2c7c0cbda27472 Mon Sep 17 00:00:00 2001 From: James Foster Date: Thu, 3 Jun 2021 17:30:58 -0700 Subject: [PATCH 19/36] Stream::readStreamUntil() should not return delimiter. --- SampleProjects/TestSomething/test/stream.cpp | 12 ++++++++++++ cpp/arduino/Stream.h | 2 +- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/SampleProjects/TestSomething/test/stream.cpp b/SampleProjects/TestSomething/test/stream.cpp index 78f0a0fa..dd218d97 100644 --- a/SampleProjects/TestSomething/test/stream.cpp +++ b/SampleProjects/TestSomething/test/stream.cpp @@ -69,4 +69,16 @@ unittest(stream_parse) } +unittest(readStringUntil) { + String data = ""; + unsigned long micros = 100; + data = "abc:def"; + + Stream s; + s.mGodmodeDataIn = &data; + s.mGodmodeMicrosDelay = µs; + // result should not include delimiter + assertEqual("abc", s.readStringUntil(':')); + assertEqual("def", s.readStringUntil(':')); +} unittest_main() diff --git a/cpp/arduino/Stream.h b/cpp/arduino/Stream.h index 9f766cbf..ef572095 100644 --- a/cpp/arduino/Stream.h +++ b/cpp/arduino/Stream.h @@ -186,7 +186,7 @@ class Stream : public Print ret = String(*mGodmodeDataIn); mGodmodeDataIn->clear(); } else { - ret = mGodmodeDataIn->substring(0, idxTrm + 1); + ret = mGodmodeDataIn->substring(0, idxTrm); fastforward(idxTrm + 1); } return ret; From a12369b02fb4240e9caac75225fb68914d7c6109 Mon Sep 17 00:00:00 2001 From: James Foster Date: Thu, 3 Jun 2021 17:36:01 -0700 Subject: [PATCH 20/36] Update CHANGELOG.md --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index f29be1a6..0cb09b05 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -27,6 +27,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/). ### Changed - Topmost installtion instructions now suggest `gem install arduino_ci` instead of using a `Gemfile`. Reasons for using a `Gemfile` are listed and discussed separately further down the README. +- Stream::readStreamUntil() no longer returns delimiter ### Removed - scanning of `library.properties`; this can and should now be performed by the standalone [`arduino-lint` tool](https://arduino.github.io/arduino-lint). From ba00749556451e863c2ab3cfa3cfeafdc8606c85 Mon Sep 17 00:00:00 2001 From: James Foster Date: Thu, 17 Jun 2021 13:33:05 -0700 Subject: [PATCH 21/36] Fix test run problem from merge. --- lib/arduino_ci/cpp_library.rb | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/lib/arduino_ci/cpp_library.rb b/lib/arduino_ci/cpp_library.rb index 4e8ca6d4..0a85815c 100644 --- a/lib/arduino_ci/cpp_library.rb +++ b/lib/arduino_ci/cpp_library.rb @@ -489,21 +489,19 @@ def test_args(aux_libraries, ci_gcc_config) # @param ci_gcc_config [Hash] The GCC config object # @return [Pathname] path to the compiled test executable def build_for_test_with_configuration(test_file, aux_libraries, gcc_binary, ci_gcc_config) - base = test_file.basename # hide build artifacts build_dir = '.arduino_ci' Dir.mkdir build_dir unless File.exist?(build_dir) - executable = Pathname.new("#{build_dir}/unittest_#{base}.bin").expand_path - File.delete(executable) if File.exist?(executable) + arg_sets = [] arg_sets << ["-std=c++0x"] if test_file.nil? - executable = Pathname.new("libarduino.so").expand_path + executable = Pathname.new("#{build_dir}/libarduino.so").expand_path arg_sets << ["-shared", "-fPIC", "-Wl,-undefined,dynamic_lookup"] else - base = test_file.basename - executable = Pathname.new("unittest_#{base}.bin").expand_path + executable = Pathname.new("#{build_dir}/unittest_#{test_file.basename}.bin").expand_path end + File.delete(executable) if File.exist?(executable) ENV["LD_LIBRARY_PATH"] = Dir.pwd arg_sets << ["-o", executable.to_s, "-L" + Dir.pwd] File.delete(executable) if File.exist?(executable) From 1cfccdf325268c12674977b9e45558d4bacfaa1a Mon Sep 17 00:00:00 2001 From: James Foster Date: Thu, 17 Jun 2021 14:02:38 -0700 Subject: [PATCH 22/36] Fix problem with hiding build artifacts. --- .gitignore | 1 + lib/arduino_ci/cpp_library.rb | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index ea2d3da0..0c895baf 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ +.arduino_ci /.bundle/ /.yardoc Gemfile.lock diff --git a/lib/arduino_ci/cpp_library.rb b/lib/arduino_ci/cpp_library.rb index 0a85815c..f189e2d5 100644 --- a/lib/arduino_ci/cpp_library.rb +++ b/lib/arduino_ci/cpp_library.rb @@ -496,7 +496,7 @@ def build_for_test_with_configuration(test_file, aux_libraries, gcc_binary, ci_g arg_sets = [] arg_sets << ["-std=c++0x"] if test_file.nil? - executable = Pathname.new("#{build_dir}/libarduino.so").expand_path + executable = Pathname.new("libarduino.so").expand_path arg_sets << ["-shared", "-fPIC", "-Wl,-undefined,dynamic_lookup"] else executable = Pathname.new("#{build_dir}/unittest_#{test_file.basename}.bin").expand_path From 5f9db70b1b06f715f3fa38aeae9c71e1d7ff84b2 Mon Sep 17 00:00:00 2001 From: James Foster Date: Thu, 1 Jul 2021 08:47:51 -0700 Subject: [PATCH 23/36] Replace `#define yield() _NOP()` with `inline void yield() { _NOP(); }` so that other code can define a `yield()` function. --- cpp/arduino/Arduino.h | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/cpp/arduino/Arduino.h b/cpp/arduino/Arduino.h index ad7d5a99..7061023a 100644 --- a/cpp/arduino/Arduino.h +++ b/cpp/arduino/Arduino.h @@ -36,11 +36,11 @@ typedef uint8_t byte; #define highByte(w) ((uint8_t) ((w) >> 8)) #define lowByte(w) ((uint8_t) ((w) & 0xff)) -// might as well use that NO-op macro for these, while unit testing -// you need interrupts? interrupt yourself -#define yield() _NOP() -#define interrupts() _NOP() -#define noInterrupts() _NOP() +// using #define for these makes it impossible for other code to use as function +// names! +inline void yield() { _NOP(); } +inline void interrupts() { _NOP(); } +inline void noInterrupts() { _NOP(); } // TODO: correctly establish this per-board! #define F_CPU 1000000UL From e52667ed67831c9d0e45849c29eb258573a7f16d Mon Sep 17 00:00:00 2001 From: James Foster Date: Thu, 1 Jul 2021 08:49:33 -0700 Subject: [PATCH 24/36] CHANGELOG.md --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index f29be1a6..8f63503f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/). ### Changed - Change 266 files from CRLF to LF. +- Replace `#define yield() _NOP()` with `inline void yield() { _NOP(); }` so that other code can define a `yield()` function. ### Deprecated From 6762e636ff629a0c93f4950ba121d3dff5b3b3b7 Mon Sep 17 00:00:00 2001 From: James Foster Date: Thu, 1 Jul 2021 13:15:47 -0700 Subject: [PATCH 25/36] Add `_BV()` macro. --- CHANGELOG.md | 1 + cpp/arduino/Arduino.h | 5 +---- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f29be1a6..e2db134a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/). ### Changed - Change 266 files from CRLF to LF. +- Add `_BV()` macro. ### Deprecated diff --git a/cpp/arduino/Arduino.h b/cpp/arduino/Arduino.h index ad7d5a99..d613a9ff 100644 --- a/cpp/arduino/Arduino.h +++ b/cpp/arduino/Arduino.h @@ -50,10 +50,7 @@ typedef uint8_t byte; typedef unsigned int word; -#define bit(b) (1UL << (b)) - - - +#define _BV(bit) (1 << (bit)) // Get the bit location within the hardware port of the given virtual pin. // This comes from the pins_*.c file for the active board configuration. From 7ad4a7402fc6bbda15ec0d11d75ea61362c2de8a Mon Sep 17 00:00:00 2001 From: James Foster Date: Thu, 8 Jul 2021 12:47:19 -0700 Subject: [PATCH 26/36] Add `avr/wdt.h` and simple test that ensures the header can be found and the functions can be called. --- CHANGELOG.md | 1 + SampleProjects/TestSomething/test/wdt.cpp | 12 ++++++++++++ cpp/arduino/avr/wdt.h | 16 ++++++++++++++++ 3 files changed, 29 insertions(+) create mode 100644 SampleProjects/TestSomething/test/wdt.cpp create mode 100644 cpp/arduino/avr/wdt.h diff --git a/CHANGELOG.md b/CHANGELOG.md index f29be1a6..5da22856 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -24,6 +24,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/). ### Added - Better indications of the build phases in the test runner `arduino_ci.rb` - Better indications of which example sketch is being compiled as part of testing +- Allow use of watchdog timer in application code (though it doesn't do anything) ### Changed - Topmost installtion instructions now suggest `gem install arduino_ci` instead of using a `Gemfile`. Reasons for using a `Gemfile` are listed and discussed separately further down the README. diff --git a/SampleProjects/TestSomething/test/wdt.cpp b/SampleProjects/TestSomething/test/wdt.cpp new file mode 100644 index 00000000..a037363c --- /dev/null +++ b/SampleProjects/TestSomething/test/wdt.cpp @@ -0,0 +1,12 @@ +#include +#include +#include + +unittest(wdt) { + wdt_disable(); + wdt_enable(WDTO_8S); + wdt_reset(); + assertTrue(true); +} + +unittest_main() diff --git a/cpp/arduino/avr/wdt.h b/cpp/arduino/avr/wdt.h new file mode 100644 index 00000000..ab489f6b --- /dev/null +++ b/cpp/arduino/avr/wdt.h @@ -0,0 +1,16 @@ +// Stub for testing that doesn't do anything (but at least compiles!) + +#define wdt_disable() (void)0 +#define wdt_enable(timeout) (void)0 +#define wdt_reset() (void)0 + +#define WDTO_15MS 0 +#define WDTO_30MS 1 +#define WDTO_60MS 2 +#define WDTO_120MS 3 +#define WDTO_250MS 4 +#define WDTO_500MS 5 +#define WDTO_1S 6 +#define WDTO_2S 7 +#define WDTO_4S 8 +#define WDTO_8S 9 From f8ab8b85f783bec9462f740e292f707b02222e68 Mon Sep 17 00:00:00 2001 From: James Foster Date: Thu, 19 Aug 2021 14:17:24 -0700 Subject: [PATCH 27/36] Rule of three: if you have a custom destructor, then you probably need a custom copy constructor and a custom copy assignment operator. --- SampleProjects/TestSomething/test/clientServer.cpp | 7 +++++++ cpp/arduino/Client.h | 14 ++++++++++++++ 2 files changed, 21 insertions(+) diff --git a/SampleProjects/TestSomething/test/clientServer.cpp b/SampleProjects/TestSomething/test/clientServer.cpp index f088c821..5e66b6b3 100644 --- a/SampleProjects/TestSomething/test/clientServer.cpp +++ b/SampleProjects/TestSomething/test/clientServer.cpp @@ -19,6 +19,13 @@ unittest(Client) { assertEqual(outData + "\r\n", inData); } +unittest(Client_copy_constructor) { + Client client1; + Client client2; + client2 = client1; + assertTrue(true); +} + unittest(IPAddress) { IPAddress ipAddress0; assertEqual(0, ipAddress0.asWord()); diff --git a/cpp/arduino/Client.h b/cpp/arduino/Client.h index 154e618d..74d0809e 100644 --- a/cpp/arduino/Client.h +++ b/cpp/arduino/Client.h @@ -11,6 +11,20 @@ class Client : public Stream { mGodmodeDataIn = new String; } } + Client(const Client &client) { + // copy constructor + if (mGodmodeDataIn) { + mGodmodeDataIn = new String(mGodmodeDataIn->c_str()); + } + std::cout << __FILE__ << ":" << __LINE__ << std::endl; + } + Client & operator=(const Client &client) { + // copy assignment operator + if (mGodmodeDataIn) { + mGodmodeDataIn = new String(mGodmodeDataIn->c_str()); + } + return *this; + } ~Client() { if (mGodmodeDataIn) { delete mGodmodeDataIn; From 4be329e7373c3ee27c61f7392552795f533b554c Mon Sep 17 00:00:00 2001 From: James Foster Date: Thu, 19 Aug 2021 14:28:17 -0700 Subject: [PATCH 28/36] Remove debugging output. --- cpp/arduino/Client.h | 1 - 1 file changed, 1 deletion(-) diff --git a/cpp/arduino/Client.h b/cpp/arduino/Client.h index 74d0809e..ae368426 100644 --- a/cpp/arduino/Client.h +++ b/cpp/arduino/Client.h @@ -16,7 +16,6 @@ class Client : public Stream { if (mGodmodeDataIn) { mGodmodeDataIn = new String(mGodmodeDataIn->c_str()); } - std::cout << __FILE__ << ":" << __LINE__ << std::endl; } Client & operator=(const Client &client) { // copy assignment operator From a9ac410fd44bd554d2cf29ffc426a0e0fec02383 Mon Sep 17 00:00:00 2001 From: James Foster Date: Tue, 24 Aug 2021 20:52:17 -0700 Subject: [PATCH 29/36] Fix memory leak in copy constructor and copy assignment operator. --- cpp/arduino/Client.h | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/cpp/arduino/Client.h b/cpp/arduino/Client.h index ae368426..31290871 100644 --- a/cpp/arduino/Client.h +++ b/cpp/arduino/Client.h @@ -1,7 +1,7 @@ #pragma once -#include #include +#include class Client : public Stream { public: @@ -11,16 +11,20 @@ class Client : public Stream { mGodmodeDataIn = new String; } } - Client(const Client &client) { - // copy constructor - if (mGodmodeDataIn) { - mGodmodeDataIn = new String(mGodmodeDataIn->c_str()); + Client(const Client &client) { // copy constructor + if (this != &client) { // not a self-assignment + if (mGodmodeDataIn) { // replace what we previously had + delete mGodmodeDataIn; // get rid of previous value + mGodmodeDataIn = new String(client.mGodmodeDataIn->c_str()); + } } } - Client & operator=(const Client &client) { - // copy assignment operator - if (mGodmodeDataIn) { - mGodmodeDataIn = new String(mGodmodeDataIn->c_str()); + Client &operator=(const Client &client) { // copy assignment operator + if (this != &client) { // not a self-assignment + if (mGodmodeDataIn) { // replace what we previously had + delete mGodmodeDataIn; // get rid of previous value + mGodmodeDataIn = new String(client.mGodmodeDataIn->c_str()); + } } return *this; } From e323378e81a1e4407381cf3ca6a748d0069c3573 Mon Sep 17 00:00:00 2001 From: James Foster Date: Tue, 24 Aug 2021 21:00:43 -0700 Subject: [PATCH 30/36] Further work to address copy assignment memory leak. --- CHANGELOG.md | 1 + cpp/arduino/Client.h | 10 ++++++---- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f29be1a6..caf736fc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/). ### Changed - Change 266 files from CRLF to LF. +- Apply "rule of three" to Client copy constructor and copy assignment operator ### Deprecated diff --git a/cpp/arduino/Client.h b/cpp/arduino/Client.h index 31290871..759267a4 100644 --- a/cpp/arduino/Client.h +++ b/cpp/arduino/Client.h @@ -13,16 +13,18 @@ class Client : public Stream { } Client(const Client &client) { // copy constructor if (this != &client) { // not a self-assignment - if (mGodmodeDataIn) { // replace what we previously had - delete mGodmodeDataIn; // get rid of previous value + if (mGodmodeDataIn && + client.mGodmodeDataIn) { // replace what we previously had + delete mGodmodeDataIn; // get rid of previous value mGodmodeDataIn = new String(client.mGodmodeDataIn->c_str()); } } } Client &operator=(const Client &client) { // copy assignment operator if (this != &client) { // not a self-assignment - if (mGodmodeDataIn) { // replace what we previously had - delete mGodmodeDataIn; // get rid of previous value + if (mGodmodeDataIn && + client.mGodmodeDataIn) { // replace what we previously had + delete mGodmodeDataIn; // get rid of previous value mGodmodeDataIn = new String(client.mGodmodeDataIn->c_str()); } } From 362cf1554fc573d16200ac0fd0890b56776395bf Mon Sep 17 00:00:00 2001 From: James Foster Date: Fri, 27 Aug 2021 14:32:16 -0700 Subject: [PATCH 31/36] * Report output from compile. * Allow test for minimum free space. --- CHANGELOG.md | 2 ++ exe/arduino_ci.rb | 14 ++++++++++++-- lib/arduino_ci/arduino_backend.rb | 1 + 3 files changed, 15 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f29be1a6..d97279dc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,8 @@ and this project adheres to [Semantic Versioning](http://semver.org/). ## [Unreleased] ### Added +- Show output from successful compile +- `--min-free-space=N` command-line argument to fail if free space is below requred value ### Changed - Change 266 files from CRLF to LF. diff --git a/exe/arduino_ci.rb b/exe/arduino_ci.rb index 01234e7c..932f754d 100755 --- a/exe/arduino_ci.rb +++ b/exe/arduino_ci.rb @@ -478,8 +478,18 @@ def perform_example_compilation_tests(cpp_library, config) board = ovr_config.platform_info[p][:board] attempt("Compiling #{example_name} for #{board}") do ret = @backend.compile_sketch(example_path, board) - unless ret - puts + puts + if ret + output = @backend.last_msg + puts output + i = output.index("leaving") + free_space = output[i + 8..-1].to_i() + min_free_space = @cli_options[:min_free_space] + if free_space < min_free_space + puts "Free space of #{free_space} is less than minimum of #{min_free_space}" + ret = false + end + else puts "Last command: #{@backend.last_msg}" puts @backend.last_err end diff --git a/lib/arduino_ci/arduino_backend.rb b/lib/arduino_ci/arduino_backend.rb index 4e04f5b3..e67710bf 100644 --- a/lib/arduino_ci/arduino_backend.rb +++ b/lib/arduino_ci/arduino_backend.rb @@ -164,6 +164,7 @@ def compile_sketch(path, boardname) return false end ret = run_and_capture("compile", "--fqbn", boardname, "--warnings", "all", "--dry-run", path.to_s) + @last_msg = ret[:out] ret[:success] end From c23fbd0d363a41ea7b187612ef8912b55b3e8f0b Mon Sep 17 00:00:00 2001 From: James Foster Date: Fri, 27 Aug 2021 14:41:18 -0700 Subject: [PATCH 32/36] Add in missed code. --- exe/arduino_ci.rb | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/exe/arduino_ci.rb b/exe/arduino_ci.rb index 932f754d..ac159f06 100755 --- a/exe/arduino_ci.rb +++ b/exe/arduino_ci.rb @@ -24,6 +24,7 @@ def self.parse(options) ci_config: { "unittest" => unit_config }, + min_free_space: 0, } opt_parser = OptionParser.new do |opts| @@ -49,6 +50,10 @@ def self.parse(options) unit_config["testfiles"]["reject"] << p end + opts.on("--min-free-space=VALUE", "Minimum free SRAM memory for stack/heap") do |p| + output_options[:min_free_space] = p.to_i() + end + opts.on("-h", "--help", "Prints this help") do puts opts puts From 8d58657ccff259b48a40e9ed634a373704ad1cb7 Mon Sep 17 00:00:00 2001 From: James Foster Date: Fri, 27 Aug 2021 14:44:59 -0700 Subject: [PATCH 33/36] Do not use parenthesis for method calls with no arguments. --- exe/arduino_ci.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/exe/arduino_ci.rb b/exe/arduino_ci.rb index ac159f06..ba043274 100755 --- a/exe/arduino_ci.rb +++ b/exe/arduino_ci.rb @@ -51,7 +51,7 @@ def self.parse(options) end opts.on("--min-free-space=VALUE", "Minimum free SRAM memory for stack/heap") do |p| - output_options[:min_free_space] = p.to_i() + output_options[:min_free_space] = p.to_i end opts.on("-h", "--help", "Prints this help") do From c29936431debe8174ca6346d79e3da4049deff0d Mon Sep 17 00:00:00 2001 From: James Foster Date: Fri, 27 Aug 2021 14:50:46 -0700 Subject: [PATCH 34/36] Another parenthesis with no arguments! --- exe/arduino_ci.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/exe/arduino_ci.rb b/exe/arduino_ci.rb index ba043274..91b1f0ac 100755 --- a/exe/arduino_ci.rb +++ b/exe/arduino_ci.rb @@ -488,7 +488,7 @@ def perform_example_compilation_tests(cpp_library, config) output = @backend.last_msg puts output i = output.index("leaving") - free_space = output[i + 8..-1].to_i() + free_space = output[i + 8..-1].to_i min_free_space = @cli_options[:min_free_space] if free_space < min_free_space puts "Free space of #{free_space} is less than minimum of #{min_free_space}" From 9c61a44f63233030eda559abb26a12dc1cb65a02 Mon Sep 17 00:00:00 2001 From: James Foster Date: Thu, 2 Sep 2021 10:05:20 -0700 Subject: [PATCH 35/36] Fix problem with warnings (https://github.com/Arduino-CI/arduino_ci/pull/297). --- SampleProjects/TestSomething/.arduino-ci.yml | 15 +++++++++++++++ lib/arduino_ci/cpp_library.rb | 2 +- 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/SampleProjects/TestSomething/.arduino-ci.yml b/SampleProjects/TestSomething/.arduino-ci.yml index f9890177..1754effb 100644 --- a/SampleProjects/TestSomething/.arduino-ci.yml +++ b/SampleProjects/TestSomething/.arduino-ci.yml @@ -1,3 +1,18 @@ +platforms: + uno: + board: arduino:avr:uno + package: arduino:avr + gcc: + features: + defines: + - __AVR__ + - __AVR_ATmega328P__ + - ARDUINO_ARCH_AVR + - ARDUINO_AVR_UNO + warnings: + - no-unknown-attributes + flags: + unittest: platforms: - uno diff --git a/lib/arduino_ci/cpp_library.rb b/lib/arduino_ci/cpp_library.rb index f189e2d5..ceaf99e9 100644 --- a/lib/arduino_ci/cpp_library.rb +++ b/lib/arduino_ci/cpp_library.rb @@ -443,7 +443,7 @@ def feature_args(ci_gcc_config) def warning_args(ci_gcc_config) return [] if ci_gcc_config[:warnings].nil? - ci_gcc_config[:features].map { |w| "-W#{w}" } + ci_gcc_config[:warnings].map { |w| "-W#{w}" } end # GCC command line arguments for defines (e.g. -Dhave_something) From 4a3f8de94a74a6616c6a7fd6559381db5c72a107 Mon Sep 17 00:00:00 2001 From: James Foster Date: Thu, 2 Sep 2021 11:27:10 -0700 Subject: [PATCH 36/36] Add support for `dtostrf()`. --- CHANGELOG.md | 1 + SampleProjects/TestSomething/test/stdlib.cpp | 8 ++++++++ cpp/arduino/stdlib.cpp | 20 ++++++++++++++++++++ cpp/arduino/stdlib.h | 3 +++ 4 files changed, 32 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 27619e0a..1e02a80b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/). ### Added - Show output from successful compile - `--min-free-space=N` command-line argument to fail if free space is below requred value +- Support for `dtostrf()` ### Changed - Change 266 files from CRLF to LF. diff --git a/SampleProjects/TestSomething/test/stdlib.cpp b/SampleProjects/TestSomething/test/stdlib.cpp index ce0b72fb..31bd0735 100644 --- a/SampleProjects/TestSomething/test/stdlib.cpp +++ b/SampleProjects/TestSomething/test/stdlib.cpp @@ -43,4 +43,12 @@ unittest(library_tests_itoa) } +unittest(library_tests_dtostrf) +{ + float num = 123.456; + char buffer[10]; + dtostrf(num, 7, 3, buffer); + assertEqual(strncmp(buffer, "123.456", sizeof(buffer)), 0); +} + unittest_main() diff --git a/cpp/arduino/stdlib.cpp b/cpp/arduino/stdlib.cpp index 931e5138..57b05600 100644 --- a/cpp/arduino/stdlib.cpp +++ b/cpp/arduino/stdlib.cpp @@ -18,6 +18,7 @@ ** is out of range. */ +#include #include #include @@ -59,3 +60,22 @@ char *itoa(int N, char *str, int base) return str; } #endif + +/* +The dtostrf() function converts the double value passed in val into +an ASCII representationthat will be stored under s. The caller is +responsible for providing sufficient storage in s. + +Conversion is done in the format “[-]d.ddd”. The minimum field width +of the output string (including the ‘.’ and the possible sign for +negative values) is given in width, and prec determines the number of +digits after the decimal sign. width is signed value, negative for +left adjustment. + +The dtostrf() function returns the pointer to the converted string s. +*/ + +char *dtostrf(double __val, signed char __width, unsigned char __prec, char *__s) { + sprintf(__s, "%*.*f", __width, __prec, __val); + return __s; +} diff --git a/cpp/arduino/stdlib.h b/cpp/arduino/stdlib.h index c685e645..b7fec869 100644 --- a/cpp/arduino/stdlib.h +++ b/cpp/arduino/stdlib.h @@ -12,3 +12,6 @@ * https://stackoverflow.com/questions/190229/where-is-the-itoa-function-in-linux */ char *itoa(int val, char *s, int radix); + +// another function provided by Arduino +char * dtostrf(double __val, signed char __width, unsigned char __prec, char *__s);