arduino_ci 0.1.18 → 0.1.19

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: d7de3ae0cd1c73eb41fe0b7f897e20f7a3d2e5c0
4
- data.tar.gz: 29dc639c29a0dcb3841e3dd903002e1fc72ef892
3
+ metadata.gz: 70602a4768ed2df9cbd04f83888f229119f00267
4
+ data.tar.gz: 337f60474895f3cfdecd9497328a7772adcc9254
5
5
  SHA512:
6
- metadata.gz: cf8434e69d4b3cc1c65d4b37db875133fdd1055e2d435b3936c15ef1e731c9160238a597ed2e2f8c21d28ce4522963e02371482ddfebc00307b2b16c2bfebf9d
7
- data.tar.gz: db0f703d2d7dad26ccc1a54f098e64ef9953ef66266f4379e1936ff915dfb38e04899304ca666ea79fac8e1dee52868979b96d6ef2937a7a085a6383dec1f176
6
+ metadata.gz: 78f6e93158cd15a1398396a631646f20b4ce843d5fd386185505ea84b230f2fc5da927e532bdb174818bf73c060bdb09d2e870ab742653df58fa68c802a37c49
7
+ data.tar.gz: 2cf0fb5e0755ed5fe2ac989fa591a923fb162c922499c6467a45edb7dd6bd811a2e23ceb945597cf48311656fee45cb0eddbc5005d0688a52179dedf4cce01ec
data/README.md CHANGED
@@ -1,12 +1,12 @@
1
1
 
2
- # ArduinoCI Ruby gem (`arduino_ci`) [![Gem Version](https://badge.fury.io/rb/arduino_ci.svg)](https://rubygems.org/gems/arduino_ci) [![Documentation](http://img.shields.io/badge/docs-rdoc.info-blue.svg)](http://www.rubydoc.info/gems/arduino_ci/0.1.18)
2
+ # ArduinoCI Ruby gem (`arduino_ci`) [![Gem Version](https://badge.fury.io/rb/arduino_ci.svg)](https://rubygems.org/gems/arduino_ci) [![Documentation](http://img.shields.io/badge/docs-rdoc.info-blue.svg)](http://www.rubydoc.info/gems/arduino_ci/0.1.19)
3
3
 
4
- You want your Arduino library to be automatically built and tested every time someone contributes code to your project on GitHub, but the Arduino IDE lacks the ability to run unit tests. [Arduino CI](https://github.com/ianfixes/arduino_ci) provides that ability.
5
-
6
- You want to run tests on your Arduino library without hardware present, but the IDE doesn't support that. Arduino CI provides that ability.
4
+ You want to run tests on your Arduino library (bonus: without hardware present), but the IDE doesn't support that. Arduino CI provides that ability.
7
5
 
8
6
  You want to precisely replicate certain software states in your library, but you don't have sub-millisecond reflexes for physically faking the inputs, outputs, and serial port. Arduino CI fakes 100% of the physical input and output of an Arduino board, including the clock.
9
7
 
8
+ You want your Arduino library to be automatically built and tested every time someone contributes code to your project on GitHub, but the Arduino IDE lacks the ability to run unit tests. [Arduino CI](https://github.com/ianfixes/arduino_ci) provides that ability.
9
+
10
10
  `arduino_ci` is a cross-platform build/test system, consisting of a Ruby gem and a series of C++ mocks. It enables tests to be run both locally and as part of a CI service like Travis or Appveyor. Any OS that can run the Arduino IDE can run `arduino_ci`.
11
11
 
12
12
  Platform | CI Status
@@ -16,13 +16,36 @@ Linux | [![Linux Build Status](http://badges.herokuapp.com/travis/ianfixes/ar
16
16
  Windows | [![Windows Build status](https://ci.appveyor.com/api/projects/status/8f6e39dea319m83q/branch/master?svg=true)](https://ci.appveyor.com/project/ianfixes/arduino-ci)
17
17
 
18
18
 
19
- ## Installation In Your GitHub Project And Using Travis CI
19
+ ## Comparison to Other Arduino Testing Tools
20
20
 
21
- The following prerequisites must be fulfilled:
21
+ | Project | CI | Builds Examples | Unittest | Arduino Mocks | Windows | OSX | Linux | License |
22
+ |-----------------------------------------------------------------------------|:--:|:---------------:|:--------:|:-------------:|:-------:|:---:|:-----:|:--------|
23
+ |[ArduinoCI](https://github.com/ianfixes/arduino_ci) | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |Free (Apache-2.0)|
24
+ |[ArduinoUnit](https://github.com/mmurdoch/arduinounit) | ❌ | ❌ | ⚠️ Hardware-based|❌ | ✅ | ✅ | ✅ |Free (MIT)|
25
+ |[Adafruit `travis-ci-arduino`](https://github.com/adafruit/travis-ci-arduino)| ✅ | ✅ | ❌ | ❌ | ❌ | ❌ | ✅ |Free (MIT)|
26
+ |[PlatformIO](https://platformio.org) | ✅ | ✅ | ⚠️ Paid only | ❌ | ✅ | ✅ | ✅ |⚠️ EULA|
27
+ |Official [Arduino IDE](https://www.arduino.cc/en/main/software) | ❌ | ⚠️ Manually | ❌ |N/A 😉| ✅ | ✅ | ✅ |Free (GPLv2)|
22
28
 
23
- * A compiler; [g++](https://gcc.gnu.org/) is preferred. On OSX, this is provided by the built-in `clang`.
24
- * A GitHub (or other repository-hosting) project for your library
25
- * A CI system like Travis or Appveor that is linked to your project
29
+
30
+ ## Quick Start
31
+
32
+ For a bare-bones example that you can copy from, see [SampleProjects/DoSomething](SampleProjects/DoSomething).
33
+
34
+ The complete set of C++ unit tests for the `arduino_ci` library itself are in the [SampleProjects/TestSomething](SampleProjects/TestSomething) project. The [test files](SampleProjects/TestSomething/test/) are named after the type of feature being tested.
35
+
36
+
37
+ ### You Need Ruby and Bundler
38
+
39
+ You'll need Ruby version 2.2 or higher, and to `gem install bundler` if it's not already there.
40
+
41
+
42
+ ### You Need A Compiler (`g++`)
43
+
44
+ For unit testing, you will need a compiler; [g++](https://gcc.gnu.org/) is preferred.
45
+
46
+ * **Linux**: `gcc`/`g++` is likely pre-installed.
47
+ * **OSX**: `g++` is an alias for `clang`, which is provided by Xcode and the developer tools. You are free to `brew install gcc` as well; this is also tested and working.
48
+ * **Windows**: you will need Cygwin, and the `mingw-gcc-g++` package. A full set of (working) install instructions can be found in `appveyor.yml`, as this is how CI runs for this project.
26
49
 
27
50
 
28
51
  ### Changes to Your Repo
@@ -34,21 +57,66 @@ source 'https://rubygems.org'
34
57
  gem 'arduino_ci'
35
58
  ```
36
59
 
37
- ### Testing Locally
60
+ It would also make sense to add the following to your `.gitignore`, or copy [the `.gitignore` used by this project](.gitignore):
61
+
62
+ ```
63
+ /.bundle/
64
+ /.yardoc
65
+ Gemfile.lock
66
+ /_yardoc/
67
+ /coverage/
68
+ /doc/
69
+ /pkg/
70
+ /spec/reports/
71
+ vendor
72
+ *.gem
73
+
74
+ # rspec failure tracking
75
+ .rspec_status
76
+
77
+ # C++ stuff
78
+ *.bin
79
+ *.bin.dSYM
80
+ ```
81
+
82
+
83
+ ### Installing the Dependencies
38
84
 
39
- First, pull in the `arduino_ci` library as a dependency.
85
+ Fulfilling the `arduino_ci` library dependency is as easy as running this command:
40
86
 
41
87
  ```
42
88
  $ bundle install
43
89
  ```
44
90
 
45
91
 
92
+ ### Running tests
93
+
46
94
  With that installed, just the following shell command each time you want the tests to execute:
47
95
 
48
96
  ```
49
97
  $ bundle exec arduino_ci_remote.rb
50
98
  ```
51
99
 
100
+ `arduino_ci_remote.rb` is the main entry point for this library. This command will iterate over all the library's `examples/` and attempt to compile them. If you set up unit tests, it will run those as well.
101
+
102
+
103
+ ### Reference
104
+
105
+ For more information on the usage of `arduino_ci_remote.rb`, see [REFERENCE.md](REFERENCE.md). It contains information such as:
106
+
107
+ * How to configure build options (platforms to test, Arduino library dependencies to install) with an `.arduino-ci.yml` file
108
+ * Where to put unit test files
109
+ * How to structure unit test files
110
+ * How to control the global (physical) state of the Arduino board
111
+ * How to modify the Arduino platforms, compilers, test plans, etc
112
+
113
+
114
+ ## Setting up Pull Request Testing and/or External CI
115
+
116
+ The following prerequisites must be fulfilled:
117
+
118
+ * A GitHub (or other repository-hosting) project for your library
119
+ * A CI system like [Travis CI](https://travis-ci.org/) or [Appveyor](https://www.appveyor.com/) that is linked to your project
52
120
 
53
121
 
54
122
  ### Testing with remote CI
@@ -66,10 +134,11 @@ Next, you need this in `.travis.yml` in your repo
66
134
  sudo: false
67
135
  language: ruby
68
136
  script:
69
- - bundle install
70
- - bundle exec arduino_ci_remote.rb
137
+ - bundle install
138
+ - bundle exec arduino_ci_remote.rb
71
139
  ```
72
140
 
141
+
73
142
  #### Appveyor CI
74
143
 
75
144
  You'll need to go to https://ci.appveyor.com/projects and add your project.
@@ -83,20 +152,6 @@ test_script:
83
152
  - bundle exec arduino_ci_remote.rb
84
153
  ```
85
154
 
86
- ## Quick Start
87
-
88
- This software is in beta. But [SampleProjects/DoSomething](SampleProjects/DoSomething) has a decent writeup and is a good bare-bones example of all the features.
89
-
90
- ## Reference
91
-
92
- For more information on the usage of `arduino_ci`, see [REFERENCE.md](REFERENCE.md). It contains information such as:
93
-
94
- * Where to put unit test files
95
- * How to structure unit test files
96
- * How to control the global (physical) state of the Arduino board
97
- * How to modify the Arduino platforms, compilers, test plans, etc
98
-
99
-
100
155
  ## Known Problems
101
156
 
102
157
  * The Arduino library is not fully mocked.
@@ -104,16 +159,6 @@ For more information on the usage of `arduino_ci`, see [REFERENCE.md](REFERENCE.
104
159
  * https://github.com/ianfixes/arduino_ci/issues
105
160
 
106
161
 
107
- ## Comparison to Other Arduino Testing Tools
108
-
109
-
110
- | Project | CI | Builds Examples | Unittest | Arduino Mocks | Windows | OSX | Linux | License |
111
- |---------|----|-----------------|----------|---------------|---------|-----|-------|---------|
112
- |[ArduinoCI](https://github.com/ianfixes/arduino_ci)| ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |Free (Apache-2.0)|
113
- |[ArduinoUnit](https://github.com/mmurdoch/arduinounit)|❌ |❌ |Hardware-based|❌ | ✅ | ✅ | ✅ |Free (MIT)| |
114
- |[Adafruit `travis-ci-arduino`](https://github.com/adafruit/travis-ci-arduino) | ✅ | ✅ | ❌| ❌ | ❌ | ❌ | ✅ |Free (MIT)|
115
- |[PlatformIO](https://platformio.org)| ✅ | ✅ | Paid only | ❌ | ✅ | ✅ | ✅ |Proprietary (EULA)|
116
-
117
162
  ## Author
118
163
 
119
164
  This gem was written by Ian Katz (ianfixes@gmail.com) in 2018. It's released under the Apache 2.0 license.
@@ -15,6 +15,7 @@ Where possible, variable names from the Arduino library are used to avoid confli
15
15
  #include "Stream.h"
16
16
  #include "HardwareSerial.h"
17
17
  #include "SPI.h"
18
+ #include "Nullptr.h"
18
19
 
19
20
  typedef bool boolean;
20
21
  typedef uint8_t byte;
@@ -72,7 +73,3 @@ inline unsigned int makeWord(unsigned char h, unsigned char l) { return (h << 8)
72
73
  #define word(...) makeWord(__VA_ARGS__)
73
74
 
74
75
 
75
- // Define C++11 nullptr
76
- #define nullptr (std::nullptr_t)NULL
77
-
78
-
@@ -0,0 +1,7 @@
1
+ #pragma once
2
+
3
+ // Define C++11 nullptr
4
+ typedef void * my_nullptr_t;
5
+ #define nullptr (my_nullptr_t)NULL
6
+
7
+ inline std::ostream& operator << (std::ostream& out, const my_nullptr_t &np) { return out << "nullptr"; }
@@ -39,6 +39,7 @@
39
39
  #define assertTrue(arg) assertEqual(true, arg)
40
40
  #define assertFalse(arg) assertEqual(false, arg)
41
41
  #define assertNull(arg) assertEqual((void*)NULL, (void*)arg)
42
+ #define assertNotNull(arg) assertNotEqual((void*)NULL, (void*)arg)
42
43
 
43
44
  /** macro generates optional output and calls fail() followed by a return if false. */
44
45
  #define assureEqual(arg1,arg2) assureOp("assureEqual","expected",arg1,compareEqual,"==","actual",arg2)
@@ -50,4 +51,5 @@
50
51
  #define assureTrue(arg) assureEqual(true, arg)
51
52
  #define assureFalse(arg) assureEqual(false, arg)
52
53
  #define assureNull(arg) assureEqual((void*)NULL, (void*)arg)
54
+ #define assureNotNull(arg) assureNotEqual((void*)NULL, (void*)arg)
53
55
 
@@ -1,6 +1,7 @@
1
1
  #pragma once
2
2
  #include <avr/pgmspace.h>
3
3
  #include <WString.h>
4
+ #include <Nullptr.h>
4
5
 
5
6
  template < typename A, typename B > struct Compare
6
7
  {
@@ -897,10 +898,21 @@ template < size_t N, size_t M > struct Compare<char [N],char [M]>
897
898
  return between(a,b) >= 0;
898
899
  } // moreOrEqual
899
900
  };
900
- template <typename A, typename B> int compareBetween(const A &a, const B &b) { return Compare<A,B>::between(a,b); }
901
- template <typename A, typename B> bool compareEqual(const A &a, const B &b) { return Compare<A,B>::equal(a,b); }
902
- template <typename A, typename B> bool compareNotEqual(const A &a, const B &b) { return Compare<A,B>::notEqual(a,b); }
903
- template <typename A, typename B> bool compareLess(const A &a, const B &b) { return Compare<A,B>::less(a,b); }
904
- template <typename A, typename B> bool compareMore(const A &a, const B &b) { return Compare<A,B>::more(a,b); }
905
- template <typename A, typename B> bool compareLessOrEqual(const A &a, const B &b) { return Compare<A,B>::lessOrEqual(a,b); }
906
- template <typename A, typename B> bool compareMoreOrEqual(const A &a, const B &b) { return Compare<A,B>::moreOrEqual(a,b); }
901
+
902
+ // null pointer comparisons
903
+ template <typename B> int compareBetween( const my_nullptr_t &a, const B &b) { return Compare<my_nullptr_t,B>::between( a, b); }
904
+ template <typename B> bool compareEqual( const my_nullptr_t &a, const B &b) { return Compare<my_nullptr_t,B>::equal( a, b); }
905
+ template <typename B> bool compareNotEqual( const my_nullptr_t &a, const B &b) { return Compare<my_nullptr_t,B>::notEqual( a, b); }
906
+ template <typename B> bool compareLess( const my_nullptr_t &a, const B &b) { return Compare<my_nullptr_t,B>::less( a, b); }
907
+ template <typename B> bool compareMore( const my_nullptr_t &a, const B &b) { return Compare<my_nullptr_t,B>::more( a, b); }
908
+ template <typename B> bool compareLessOrEqual(const my_nullptr_t &a, const B &b) { return Compare<my_nullptr_t,B>::lessOrEqual(a, b); }
909
+ template <typename B> bool compareMoreOrEqual(const my_nullptr_t &a, const B &b) { return Compare<my_nullptr_t,B>::moreOrEqual(a, b); }
910
+
911
+ // super general comparisons
912
+ template <typename A, typename B> int compareBetween( const A &a, const B &b) { return Compare<A,B>::between( a, b); }
913
+ template <typename A, typename B> bool compareEqual( const A &a, const B &b) { return Compare<A,B>::equal( a, b); }
914
+ template <typename A, typename B> bool compareNotEqual( const A &a, const B &b) { return Compare<A,B>::notEqual( a, b); }
915
+ template <typename A, typename B> bool compareLess( const A &a, const B &b) { return Compare<A,B>::less( a, b); }
916
+ template <typename A, typename B> bool compareMore( const A &a, const B &b) { return Compare<A,B>::more( a, b); }
917
+ template <typename A, typename B> bool compareLessOrEqual(const A &a, const B &b) { return Compare<A,B>::lessOrEqual(a, b); }
918
+ template <typename A, typename B> bool compareMoreOrEqual(const A &a, const B &b) { return Compare<A,B>::moreOrEqual(a, b); }
@@ -287,17 +287,17 @@ module ArduinoCI
287
287
  end
288
288
 
289
289
  # Config allows select / reject (aka whitelist / blacklist) criteria. Enforce on a dir
290
- # @param paths [Array<String>] the initial set of test files
291
- # @return [Array<String>] files that match the select/reject criteria
290
+ # @param paths [Array<Pathname>] the initial set of test files
291
+ # @return [Array<Pathname>] files that match the select/reject criteria
292
292
  def allowable_unittest_files(paths)
293
293
  return paths if @unittest_info[:testfiles].nil?
294
294
 
295
295
  ret = paths
296
296
  unless @unittest_info[:testfiles][:select].nil? || @unittest_info[:testfiles][:select].empty?
297
- ret = ret.select { |p| unittest_info[:testfiles][:select].any? { |glob| File.fnmatch(glob, File.basename(p)) } }
297
+ ret.select! { |p| unittest_info[:testfiles][:select].any? { |glob| p.basename.fnmatch(glob) } }
298
298
  end
299
299
  unless @unittest_info[:testfiles][:reject].nil?
300
- ret = ret.reject { |p| unittest_info[:testfiles][:reject].any? { |glob| File.fnmatch(glob, File.basename(p)) } }
300
+ ret.reject! { |p| unittest_info[:testfiles][:reject].any? { |glob| p.basename.fnmatch(glob) } }
301
301
  end
302
302
  ret
303
303
  end
@@ -1,3 +1,3 @@
1
1
  module ArduinoCI
2
- VERSION = "0.1.18".freeze
2
+ VERSION = "0.1.19".freeze
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: arduino_ci
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.18
4
+ version: 0.1.19
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ian Katz
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2019-01-29 00:00:00.000000000 Z
11
+ date: 2019-01-30 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: os
@@ -113,7 +113,6 @@ email:
113
113
  - ianfixes@gmail.com
114
114
  executables:
115
115
  - arduino_ci_remote.rb
116
- - arduino_ci_remote.rb.orig
117
116
  - arduino_library_location.rb
118
117
  - ensure_arduino_installation.rb
119
118
  - libasan.rb
@@ -129,6 +128,7 @@ files:
129
128
  - cpp/arduino/Godmode.cpp
130
129
  - cpp/arduino/Godmode.h
131
130
  - cpp/arduino/HardwareSerial.h
131
+ - cpp/arduino/Nullptr.h
132
132
  - cpp/arduino/PinHistory.h
133
133
  - cpp/arduino/Print.h
134
134
  - cpp/arduino/SPI.h
@@ -424,7 +424,6 @@ files:
424
424
  - cpp/unittest/Assertion.h
425
425
  - cpp/unittest/Compare.h
426
426
  - exe/arduino_ci_remote.rb
427
- - exe/arduino_ci_remote.rb.orig
428
427
  - exe/arduino_library_location.rb
429
428
  - exe/ensure_arduino_installation.rb
430
429
  - exe/libasan.rb
@@ -1,387 +0,0 @@
1
- #!/usr/bin/env ruby
2
- require 'arduino_ci'
3
- require 'set'
4
- require 'pathname'
5
- require 'optparse'
6
-
7
- WIDTH = 80
8
- FIND_FILES_INDENT = 4
9
-
10
- @failure_count = 0
11
- @passfail = proc { |result| result ? "✓" : "✗" }
12
-
13
- # Use some basic parsing to allow command-line overrides of config
14
- class Parser
15
- def self.parse(options)
16
- unit_config = {}
17
- output_options = {
18
- skip_unittests: false,
19
- skip_compilation: false,
20
- ci_config: {
21
- "unittest" => unit_config
22
- },
23
- }
24
-
25
- opt_parser = OptionParser.new do |opts|
26
- opts.banner = "Usage: #{File.basename(__FILE__)} [options]"
27
-
28
- opts.on("--skip-unittests", "Don't run unit tests") do |p|
29
- output_options[:skip_unittests] = p
30
- end
31
-
32
- opts.on("--skip-compilation", "Don't compile example sketches") do |p|
33
- output_options[:skip_compilation] = p
34
- end
35
-
36
- opts.on("--testfile-select=GLOB", "Unit test file (or glob) to select") do |p|
37
- unit_config["testfiles"] ||= {}
38
- unit_config["testfiles"]["select"] ||= []
39
- unit_config["testfiles"]["select"] << p
40
- end
41
-
42
- opts.on("--testfile-reject=GLOB", "Unit test file (or glob) to reject") do |p|
43
- unit_config["testfiles"] ||= {}
44
- unit_config["testfiles"]["reject"] ||= []
45
- unit_config["testfiles"]["reject"] << p
46
- end
47
-
48
- opts.on("-h", "--help", "Prints this help") do
49
- puts opts
50
- exit
51
- end
52
- end
53
-
54
- opt_parser.parse!(options)
55
- output_options
56
- end
57
- end
58
-
59
- # Read in command line options and make them read-only
60
- @cli_options = (Parser.parse ARGV).freeze
61
-
62
- # terminate after printing any debug info. TODO: capture debug info
63
- def terminate(final = nil)
64
- puts "Failures: #{@failure_count}"
65
- unless @failure_count.zero? || final
66
- puts "Last message: #{@arduino_cmd.last_msg}"
67
- puts "========== Stdout:"
68
- puts @arduino_cmd.last_out
69
- puts "========== Stderr:"
70
- puts @arduino_cmd.last_err
71
- end
72
- retcode = @failure_count.zero? ? 0 : 1
73
- exit(retcode)
74
- end
75
-
76
- # make a nice status line for an action and react to the action
77
- # TODO / note to self: inform_multline is tougher to write
78
- # without altering the signature because it only leaves space
79
- # for the checkmark _after_ the multiline, it doesn't know how
80
- # to make that conditionally the body
81
- # @param message String the text of the progress indicator
82
- # @param multiline boolean whether multiline output is expected
83
- # @param mark_fn block (string) -> string that says how to describe the result
84
- # @param on_fail_msg String custom message for failure
85
- # @param tally_on_fail boolean whether to increment @failure_count
86
- # @param abort_on_fail boolean whether to abort immediately on failure (i.e. if this is a fatal error)
87
- def perform_action(message, multiline, mark_fn, on_fail_msg, tally_on_fail, abort_on_fail)
88
- line = "#{message}... "
89
- endline = "...#{message} "
90
- if multiline
91
- puts line
92
- else
93
- print line
94
- end
95
- STDOUT.flush
96
- result = yield
97
- mark = mark_fn.nil? ? "" : mark_fn.call(result)
98
- # if multline, put checkmark at full width
99
- print endline if multiline
100
- puts mark.to_s.rjust(WIDTH - line.length, " ")
101
- unless result
102
- puts on_fail_msg unless on_fail_msg.nil?
103
- @failure_count += 1 if tally_on_fail
104
- # print out error messaging here if we've captured it
105
- terminate if abort_on_fail
106
- end
107
- result
108
- end
109
-
110
- # Make a nice status for something that defers any failure code until script exit
111
- def attempt(message, &block)
112
- perform_action(message, false, @passfail, nil, true, false, &block)
113
- end
114
-
115
- # Make a nice status for something that defers any failure code until script exit
116
- def attempt_multiline(message, &block)
117
- perform_action(message, true, @passfail, nil, true, false, &block)
118
- end
119
-
120
- # Make a nice status for something that kills the script immediately on failure
121
- FAILED_ASSURANCE_MESSAGE = "This may indicate a problem with ArduinoCI, or your configuration".freeze
122
- def assure(message, &block)
123
- perform_action(message, false, @passfail, FAILED_ASSURANCE_MESSAGE, true, true, &block)
124
- end
125
-
126
- def assure_multiline(message, &block)
127
- perform_action(message, true, @passfail, FAILED_ASSURANCE_MESSAGE, true, true, &block)
128
- end
129
-
130
- def inform(message, &block)
131
- perform_action(message, false, proc { |x| x }, nil, false, false, &block)
132
- end
133
-
134
- def inform_multiline(message, &block)
135
- perform_action(message, true, nil, nil, false, false, &block)
136
- end
137
-
138
- # Assure that a platform exists and return its definition
139
- def assured_platform(purpose, name, config)
140
- platform_definition = config.platform_definition(name)
141
- assure("Requested #{purpose} platform '#{name}' is defined in 'platforms' YML") do
142
- !platform_definition.nil?
143
- end
144
- platform_definition
145
- end
146
-
147
- # Return true if the file (or one of the dirs containing it) is hidden
148
- def file_is_hidden_somewhere?(path)
149
- # this is clunkly but pre-2.2-ish ruby doesn't return ascend as an enumerator
150
- path.ascend do |part|
151
- return true if part.basename.to_s.start_with? "."
152
- end
153
- false
154
- end
155
-
156
- # print out some files
157
- def display_files(pathname)
158
- # `find` doesn't follow symlinks, so we should instead
159
- realpath = pathname.symlink? ? pathname.readlink : pathname
160
-
161
- # suppress directories and dotfile-based things
162
- all_files = realpath.find.select(&:file?)
163
- non_hidden = all_files.reject { |path| file_is_hidden_somewhere?(path) }
164
-
165
- # print files with an indent
166
- margin = " " * FIND_FILES_INDENT
167
- non_hidden.each { |p| puts "#{margin}#{p}" }
168
- end
169
-
170
- def perform_unit_tests(file_config)
171
- <<<<<<< HEAD
172
- puts file_config.to_h[:unittest].to_s
173
- config = file_config.with_override_config(@cli_options)
174
- puts config.to_h[:unittest].to_s
175
- =======
176
- if @cli_options[:skip_unittests]
177
- inform("Skipping unit tests") { "as requested via command line" }
178
- return
179
- end
180
- config = file_config.with_override_config(@cli_options[:ci_config])
181
- >>>>>>> 9c4b0f0... Allow skipping of unittests and/or compilation in arduino_ci_remote.rb
182
- cpp_library = ArduinoCI::CppLibrary.new(Pathname.new("."), @arduino_cmd.lib_dir)
183
-
184
- # check GCC
185
- compilers = config.compilers_to_use
186
- assure("The set of compilers (#{compilers.length}) isn't empty") { !compilers.empty? }
187
- compilers.each do |gcc_binary|
188
- attempt_multiline("Checking #{gcc_binary} version") do
189
- version = cpp_library.gcc_version(gcc_binary)
190
- next nil unless version
191
-
192
- puts version.split("\n").map { |l| " #{l}" }.join("\n")
193
- version
194
- end
195
- inform("libasan availability for #{gcc_binary}") { cpp_library.libasan?(gcc_binary) }
196
- end
197
-
198
- # Ensure platforms exist for unit test, and save their info in all_platform_info keyed by name
199
- all_platform_info = {}
200
- config.platforms_to_unittest.each { |p| all_platform_info[p] = assured_platform("unittest", p, config) }
201
-
202
- # iterate boards / tests
203
- if !cpp_library.tests_dir.exist?
204
- inform_multiline("Skipping unit tests; no tests dir at #{cpp_library.tests_dir}") do
205
- puts " In case that's an error, this is what was found in the library:"
206
- display_files(cpp_library.tests_dir.parent)
207
- true
208
- end
209
- elsif cpp_library.test_files.empty?
210
- inform_multiline("Skipping unit tests; no test files were found in #{cpp_library.tests_dir}") do
211
- puts " In case that's an error, this is what was found in the tests directory:"
212
- display_files(cpp_library.tests_dir)
213
- true
214
- end
215
- elsif config.platforms_to_unittest.empty?
216
- inform("Skipping unit tests") { "no platforms were requested" }
217
- else
218
- config.platforms_to_unittest.each do |p|
219
- config.allowable_unittest_files(cpp_library.test_files).each do |unittest_path|
220
- unittest_name = unittest_path.basename.to_s
221
- compilers.each do |gcc_binary|
222
- attempt_multiline("Unit testing #{unittest_name} with #{gcc_binary}") do
223
- exe = cpp_library.build_for_test_with_configuration(
224
- unittest_path,
225
- config.aux_libraries_for_unittest,
226
- gcc_binary,
227
- config.gcc_config(p)
228
- )
229
- puts
230
- unless exe
231
- puts "Last command: #{cpp_library.last_cmd}"
232
- puts cpp_library.last_out
233
- puts cpp_library.last_err
234
- next false
235
- end
236
- cpp_library.run_test_file(exe)
237
- end
238
- end
239
- end
240
- end
241
- end
242
- end
243
-
244
- def perform_compilation_tests(config)
245
- if @cli_options[:skip_compilation]
246
- inform("Skipping compilation of examples") { "as requested via command line" }
247
- return
248
- end
249
-
250
- # index the existing libraries
251
- attempt("Indexing libraries") { @arduino_cmd.index_libraries } unless @arduino_cmd.libraries_indexed
252
-
253
- # initialize library under test
254
- installed_library_path = attempt("Installing library under test") do
255
- @arduino_cmd.install_local_library(Pathname.new("."))
256
- end
257
- if installed_library_path.exist?
258
- inform("Library installed at") { installed_library_path.to_s }
259
- else
260
- assure_multiline("Library installed successfully") do
261
- # print out the contents of the deepest directory we actually find
262
- @arduino_cmd.lib_dir.ascend do |path_part|
263
- next unless path_part.exist?
264
-
265
- break display_files(path_part)
266
- end
267
- false
268
- end
269
- end
270
- library_examples = @arduino_cmd.library_examples(installed_library_path)
271
-
272
- # gather up all required boards for compilation so we can install them up front.
273
- # start with the "platforms to unittest" and add the examples
274
- # while we're doing that, get the aux libraries as well
275
- example_platform_info = {}
276
- board_package_url = {}
277
- aux_libraries = Set.new(config.aux_libraries_for_unittest + config.aux_libraries_for_build)
278
- # while collecting the platforms, ensure they're defined
279
-
280
- library_examples.each do |path|
281
- ovr_config = config.from_example(path)
282
- ovr_config.platforms_to_build.each do |platform|
283
- # assure the platform if we haven't already
284
- next if example_platform_info.key?(platform)
285
-
286
- platform_info = assured_platform("library example", platform, config)
287
- next if platform_info.nil?
288
-
289
- example_platform_info[platform] = platform_info
290
- package = platform_info[:package]
291
- board_package_url[package] = ovr_config.package_url(package)
292
- end
293
- aux_libraries.merge(ovr_config.aux_libraries_for_build)
294
- end
295
-
296
- # with all platform info, we can extract unique packages and their urls
297
- # do that, set the URLs, and download the packages
298
- all_packages = example_platform_info.values.map { |v| v[:package] }.uniq.reject(&:nil?)
299
-
300
- # inform about builtin packages
301
- all_packages.select { |p| config.package_builtin?(p) }.each do |p|
302
- inform("Using built-in board package") { p }
303
- end
304
-
305
- # make sure any non-builtin package has a URL defined
306
- all_packages.reject { |p| config.package_builtin?(p) }.each do |p|
307
- assure("Board package #{p} has a defined URL") { board_package_url[p] }
308
- end
309
-
310
- # set up all the board manager URLs.
311
- # we can safely reject nils now, they would be for the builtins
312
- all_urls = all_packages.map { |p| board_package_url[p] }.uniq.reject(&:nil?)
313
-
314
- unless all_urls.empty?
315
- assure("Setting board manager URLs") do
316
- @arduino_cmd.board_manager_urls = all_urls
317
- end
318
- end
319
-
320
- all_packages.each do |p|
321
- assure("Installing board package #{p}") do
322
- @arduino_cmd.install_boards(p)
323
- end
324
- end
325
-
326
- aux_libraries.each do |l|
327
- if @arduino_cmd.library_present?(l)
328
- inform("Using pre-existing library") { l.to_s }
329
- else
330
- assure("Installing aux library '#{l}'") { @arduino_cmd.install_library(l) }
331
- end
332
- end
333
-
334
- last_board = nil
335
- if config.platforms_to_build.empty?
336
- inform("Skipping builds") { "no platforms were requested" }
337
- return
338
- elsif library_examples.empty?
339
- inform_multiline("Skipping builds; no examples found in #{installed_library_path}") do
340
- display_files(installed_library_path)
341
- end
342
- return
343
- end
344
-
345
- attempt("Setting compiler warning level") { @arduino_cmd.set_pref("compiler.warning_level", "all") }
346
-
347
- # switching boards takes time, so iterate board first
348
- # _then_ whichever examples match it
349
- examples_by_platform = library_examples.each_with_object({}) do |example_path, acc|
350
- ovr_config = config.from_example(example_path)
351
- ovr_config.platforms_to_build.each do |p|
352
- acc[p] = [] unless acc.key?(p)
353
- acc[p] << example_path
354
- end
355
- end
356
-
357
- examples_by_platform.each do |platform, example_paths|
358
- board = example_platform_info[platform][:board]
359
- assure("Switching to board for #{platform} (#{board})") { @arduino_cmd.use_board(board) } unless last_board == board
360
- last_board = board
361
-
362
- example_paths.each do |example_path|
363
- example_name = File.basename(example_path)
364
- attempt("Verifying #{example_name}") do
365
- ret = @arduino_cmd.verify_sketch(example_path)
366
- unless ret
367
- puts
368
- puts "Last command: #{@arduino_cmd.last_msg}"
369
- puts @arduino_cmd.last_err
370
- end
371
- ret
372
- end
373
- end
374
- end
375
-
376
- end
377
-
378
- # initialize command and config
379
- config = ArduinoCI::CIConfig.default.from_project_library
380
-
381
- @arduino_cmd = ArduinoCI::ArduinoInstallation.autolocate!
382
- inform("Located Arduino binary") { @arduino_cmd.binary_path.to_s }
383
-
384
- perform_unit_tests(config)
385
- perform_compilation_tests(config)
386
-
387
- terminate(true)