arduino_ci 0.1.16 → 0.1.17

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: 45608f459dc2eeb5eaca6d2d825561a806ba7fcb
4
- data.tar.gz: c6c442695f3471518ae5abdbd4098629ecb868e0
3
+ metadata.gz: a089a7486b4295c2ed49a832a0dd148d6e31561a
4
+ data.tar.gz: 0c13b415b9b585c42ec2a8501c5e6ef606137c30
5
5
  SHA512:
6
- metadata.gz: ef50f062dde7ce201362da1a9a1e225ff4f0bd868985dd118d44afa7d50c9bd01250aef7fbefe156d5948a732daa7131dbdc023911aa1d640a6fa07a514f75fd
7
- data.tar.gz: 8578a23f2b8c4323279ad3b22950ee44aa991ab09593e666f936059192c5d8878fb69bb4335ad8aae3877cc7116a896654b364308d744d9959707ea214e752ff
6
+ metadata.gz: 74819da0c7bbaf23fbd5ceaf1952e43442d0bdd4789ecf1beb4c3a110038350797b9b6629698a3348bc9803afb444344badc2f0bdebbc930bf42835bb07b3109
7
+ data.tar.gz: 794e75954f74a2e9420d6ec4e884683b86f2a04d2ac0b0a3cf13776126e8db40c29724ebe397fb2d9bd062c5e3044cea206ed078aa5958dee825cd902d38e5a9
data/README.md CHANGED
@@ -1,9 +1,9 @@
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.16)
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.17)
3
3
 
4
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
5
 
6
- You want to run tests on your Arduino library without hardware present, but the IDE doesn't support that. Arduino CI proivdes that ability.
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.
7
7
 
8
8
  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
9
 
@@ -34,6 +34,25 @@ source 'https://rubygems.org'
34
34
  gem 'arduino_ci'
35
35
  ```
36
36
 
37
+ ### Testing Locally
38
+
39
+ First, pull in the `arduino_ci` library as a dependency.
40
+
41
+ ```
42
+ $ bundle install
43
+ ```
44
+
45
+
46
+ With that installed, just the following shell command each time you want the tests to execute:
47
+
48
+ ```
49
+ $ bundle exec arduino_ci_remote.rb
50
+ ```
51
+
52
+
53
+
54
+ ### Testing with remote CI
55
+
37
56
  > **Note:** `arduino_ci_remote.rb` expects to be run from the root directory of your Arduino project library.
38
57
 
39
58
 
@@ -0,0 +1,61 @@
1
+
2
+ #if 1 // This code is copied from https://people.cs.umu.se/isak/snippets/ltoa.c and then converted from ltoa to itoa.
3
+ /*
4
+ ** LTOA.C
5
+ **
6
+ ** Converts a integer to a string.
7
+ **
8
+ ** Copyright 1988-90 by Robert B. Stout dba MicroFirm
9
+ **
10
+ ** Released to public domain, 1991
11
+ **
12
+ ** Parameters: 1 - number to be converted
13
+ ** 2 - buffer in which to build the converted string
14
+ ** 3 - number base to use for conversion
15
+ **
16
+ ** Returns: A character pointer to the converted string if
17
+ ** successful, a NULL pointer if the number base specified
18
+ ** is out of range.
19
+ */
20
+
21
+ #include <stdlib.h>
22
+ #include <string.h>
23
+
24
+ #define BUFSIZE (sizeof(int) * 8 + 1)
25
+
26
+ char *itoa(int N, char *str, int base)
27
+ {
28
+ int i = 2;
29
+ int uarg;
30
+ char *tail, *head = str, buf[BUFSIZE];
31
+
32
+ if (36 < base || 2 > base)
33
+ base = 10; /* can only use 0-9, A-Z */
34
+ tail = &buf[BUFSIZE - 1]; /* last character position */
35
+ *tail-- = '\0';
36
+
37
+ if (10 == base && N < 0L)
38
+ {
39
+ *head++ = '-';
40
+ uarg = -N;
41
+ }
42
+ else uarg = N;
43
+
44
+ if (uarg)
45
+ {
46
+ for (i = 1; uarg; ++i)
47
+ {
48
+ ldiv_t r;
49
+
50
+ r = ldiv(uarg, base);
51
+ *tail-- = (char)(r.rem + ((9L < r.rem) ?
52
+ ('A' - 10L) : '0'));
53
+ uarg = r.quot;
54
+ }
55
+ }
56
+ else *tail-- = '0';
57
+
58
+ memcpy(head, ++tail, i);
59
+ return str;
60
+ }
61
+ #endif
@@ -0,0 +1,14 @@
1
+ #pragma once
2
+
3
+ // Header file to compensate for differences between
4
+ // arduino-1.x.x/hardware/tools/avr/avr/include/stdlib.h and /usr/include/stdlib.h.
5
+
6
+ #include_next <stdlib.h>
7
+
8
+ /*
9
+ * Arduino stdlib.h includes a prototype for itoa which is not a standard function,
10
+ * and is not available in /usr/include/stdlib.h. Provide one here.
11
+ * http://www.cplusplus.com/reference/cstdlib/itoa/
12
+ * https://stackoverflow.com/questions/190229/where-is-the-itoa-function-in-linux
13
+ */
14
+ char *itoa(int val, char *s, int radix);
@@ -2,6 +2,7 @@
2
2
  require 'arduino_ci'
3
3
  require 'set'
4
4
  require 'pathname'
5
+ require 'optparse'
5
6
 
6
7
  WIDTH = 80
7
8
  FIND_FILES_INDENT = 4
@@ -9,6 +10,41 @@ FIND_FILES_INDENT = 4
9
10
  @failure_count = 0
10
11
  @passfail = proc { |result| result ? "✓" : "✗" }
11
12
 
13
+ # Use some basic parsing to allow command-line overrides of config
14
+ class Parser
15
+ def self.parse(options)
16
+ parsed_config = {}
17
+ parsed_config["unittest"] = {}
18
+
19
+ opt_parser = OptionParser.new do |opts|
20
+ opts.banner = "Usage: #{File.basename(__FILE__)} [options]"
21
+
22
+ opts.on("--testfile-select=GLOB", "Unit test file (or glob) to select") do |p|
23
+ parsed_config["unittest"]["testfiles"] ||= {}
24
+ parsed_config["unittest"]["testfiles"]["select"] ||= []
25
+ parsed_config["unittest"]["testfiles"]["select"] << p
26
+ end
27
+
28
+ opts.on("--testfile-reject=GLOB", "Unit test file (or glob) to reject") do |p|
29
+ parsed_config["unittest"]["testfiles"] ||= {}
30
+ parsed_config["unittest"]["testfiles"]["reject"] ||= []
31
+ parsed_config["unittest"]["testfiles"]["reject"] << p
32
+ end
33
+
34
+ opts.on("-h", "--help", "Prints this help") do
35
+ puts opts
36
+ exit
37
+ end
38
+ end
39
+
40
+ opt_parser.parse!(options)
41
+ parsed_config
42
+ end
43
+ end
44
+
45
+ # Read in command line options and make them read-only
46
+ @cli_options = (Parser.parse ARGV).freeze
47
+
12
48
  # terminate after printing any debug info. TODO: capture debug info
13
49
  def terminate(final = nil)
14
50
  puts "Failures: #{@failure_count}"
@@ -28,6 +64,12 @@ end
28
64
  # without altering the signature because it only leaves space
29
65
  # for the checkmark _after_ the multiline, it doesn't know how
30
66
  # to make that conditionally the body
67
+ # @param message String the text of the progress indicator
68
+ # @param multiline boolean whether multiline output is expected
69
+ # @param mark_fn block (string) -> string that says how to describe the result
70
+ # @param on_fail_msg String custom message for failure
71
+ # @param tally_on_fail boolean whether to increment @failure_count
72
+ # @param abort_on_fail boolean whether to abort immediately on failure (i.e. if this is a fatal error)
31
73
  def perform_action(message, multiline, mark_fn, on_fail_msg, tally_on_fail, abort_on_fail)
32
74
  line = "#{message}... "
33
75
  endline = "...#{message} "
@@ -111,7 +153,10 @@ def display_files(pathname)
111
153
  non_hidden.each { |p| puts "#{margin}#{p}" }
112
154
  end
113
155
 
114
- def perform_unit_tests(config)
156
+ def perform_unit_tests(file_config)
157
+ puts file_config.to_h[:unittest].to_s
158
+ config = file_config.with_override_config(@cli_options)
159
+ puts config.to_h[:unittest].to_s
115
160
  cpp_library = ArduinoCI::CppLibrary.new(Pathname.new("."), @arduino_cmd.lib_dir)
116
161
 
117
162
  # check GCC
@@ -149,7 +194,7 @@ def perform_unit_tests(config)
149
194
  inform("Skipping unit tests") { "no platforms were requested" }
150
195
  else
151
196
  config.platforms_to_unittest.each do |p|
152
- cpp_library.test_files.each do |unittest_path|
197
+ config.allowable_unittest_files(cpp_library.test_files).each do |unittest_path|
153
198
  unittest_name = unittest_path.basename.to_s
154
199
  compilers.each do |gcc_binary|
155
200
  attempt_multiline("Unit testing #{unittest_name} with #{gcc_binary}") do
@@ -32,13 +32,7 @@ module ArduinoCI
32
32
  # if it exists. I'm not sure why we would have both, but if we did
33
33
  # a force install then let's make sure we actually use it.
34
34
  locations = [self.force_installed_executable, self.existing_executable]
35
- locations.each do |loc|
36
- next if loc.nil?
37
- next unless File.exist? loc
38
-
39
- return loc
40
- end
41
- nil
35
+ locations.find { |loc| !loc.nil? && File.exist?(loc) }
42
36
  end
43
37
 
44
38
  # The autolocated directory of the installation
@@ -49,13 +43,7 @@ module ArduinoCI
49
43
  # if it exists. I'm not sure why we would have both, but if we did
50
44
  # a force install then let's make sure we actually use it.
51
45
  locations = [self.force_install_location, self.existing_installation]
52
- locations.each do |loc|
53
- next if loc.nil?
54
- next unless File.exist? loc
55
-
56
- return loc
57
- end
58
- nil
46
+ locations.find { |loc| !loc.nil? && File.exist?(loc) }
59
47
  end
60
48
 
61
49
  # The path to the directory of an existing installation, or nil
@@ -198,7 +186,7 @@ module ArduinoCI
198
186
  elsif File.exist? extracted_file
199
187
  install
200
188
  else
201
- puts "Arduino force-install failed"
189
+ puts "Could not find extracted archive (tried #{extracted_file})"
202
190
  end
203
191
 
204
192
  File.exist? self.class.force_install_location
@@ -27,21 +27,17 @@ module ArduinoCI
27
27
  # @param Array<string> a list of places to look
28
28
  # @return [string]
29
29
  def self.find_existing_arduino_dir(paths)
30
- paths.each do |path|
31
- return path if File.exist? path
32
- end
33
- nil
30
+ paths.find(&File.method(:exist?))
34
31
  end
35
32
 
36
33
  # An existing Arduino file in one of the given directories, or nil
37
34
  # @param Array<string> a list of places to look for the executable
38
35
  # @return [string]
39
36
  def self.find_existing_arduino_exe(paths)
40
- paths.each do |path|
37
+ paths.find do |path|
41
38
  exe = File.join(path, "MacOS", "Arduino")
42
- return exe if File.exist? exe
39
+ File.exist? exe
43
40
  end
44
- nil
45
41
  end
46
42
 
47
43
  # The path to the directory of an existing installation, or nil
@@ -81,10 +81,10 @@ module ArduinoCI
81
81
  # @return [string]
82
82
  def self.existing_executable
83
83
  arduino_reg = 'SOFTWARE\WOW6432Node\Arduino'
84
- Win32::Registry::HKEY_LOCAL_MACHINE.open(arduino_reg) do |reg|
84
+ Win32::Registry::HKEY_LOCAL_MACHINE.open(arduino_reg).find do |reg|
85
85
  path = reg.read_s('Install_Dir')
86
86
  exe = File.join(path, "arduino_debug.exe")
87
- return exe if File.exist? exe
87
+ File.exist? exe
88
88
  end
89
89
  rescue
90
90
  nil
@@ -93,10 +93,7 @@ module ArduinoCI
93
93
  # The executable Arduino file in a forced installation, or nil
94
94
  # @return [string]
95
95
  def self.force_installed_executable
96
- exe = File.join(self.force_install_location, "arduino_debug.exe")
97
- return nil if exe.nil?
98
-
99
- exe
96
+ File.join(self.force_install_location, "arduino_debug.exe")
100
97
  end
101
98
 
102
99
  end
@@ -13,6 +13,8 @@ DESIRED_ARDUINO_IDE_VERSION = "1.8.6".freeze
13
13
 
14
14
  module ArduinoCI
15
15
 
16
+ class ArduinoInstallationError < StandardError; end
17
+
16
18
  # Manage the OS-specific install location of Arduino
17
19
  class ArduinoInstallation
18
20
 
@@ -78,7 +80,13 @@ module ArduinoCI
78
80
  # don't want to see is a java error.
79
81
  args = launcher + ["--bogus-option"]
80
82
  result = Host.run_and_capture(*args)
81
- next unless result[:err].include? "Error: unknown option: --bogus-option"
83
+
84
+ # NOTE: Was originally searching for "Error: unknown option: --bogus-option"
85
+ # but also need to find "Erreur: option inconnue : --bogus-option"
86
+ # and who knows how many other languages.
87
+ # For now, just search for the end of the error and hope that the java-style
88
+ # launch of this won't include a similar string in it
89
+ next unless result[:err].include? ": --bogus-option"
82
90
 
83
91
  ret.base_cmd = launcher
84
92
  ret.binary_path = Pathname.new(osx_root)
@@ -94,7 +102,8 @@ module ArduinoCI
94
102
  return candidate unless candidate.nil?
95
103
 
96
104
  # force the install
97
- force_install
105
+ raise ArduinoInstallationError, "Failed to force-install Arduino" unless force_install
106
+
98
107
  autolocate
99
108
  end
100
109
 
@@ -35,6 +35,8 @@ UNITTEST_SCHEMA = {
35
35
  }.freeze
36
36
  module ArduinoCI
37
37
 
38
+ class ConfigurationError < StandardError; end
39
+
38
40
  # The filename controlling (overriding) the defaults for testing.
39
41
  # Files with this name can be used in the root directory of the Arduino library and in any/all of the example directories
40
42
  CONFIG_FILENAMES = [
@@ -70,6 +72,21 @@ module ArduinoCI
70
72
  @unittest_info = {}
71
73
  end
72
74
 
75
+ # @return [Hash] config data as a hash
76
+ def to_h
77
+ {
78
+ packages: @package_info,
79
+ platforms: @platform_info,
80
+ compile: @compile_info,
81
+ unittest: @unittest_info
82
+ }
83
+ end
84
+
85
+ # @return [String] config data as a string
86
+ def to_s
87
+ to_h.to_s
88
+ end
89
+
73
90
  # Deep-clone a hash
74
91
  # @param hash [Hash] the source data
75
92
  # @return [Hash] a copy
@@ -108,8 +125,15 @@ module ArduinoCI
108
125
  # @return [ArduinoCI::CIConfig] a reference to self
109
126
  def load_yaml(path)
110
127
  yml = YAML.load_file(path)
111
- raise "The YAML file at #{path} failed to load" unless yml
128
+ raise ConfigurationError, "The YAML file at #{path} failed to load" unless yml
129
+
130
+ apply_configuration(yml)
131
+ end
112
132
 
133
+ # Load configuration from a hash
134
+ # @param yml [Hash] the source data
135
+ # @return [ArduinoCI::CIConfig] a reference to self
136
+ def apply_configuration(yml)
113
137
  if yml.include?("packages")
114
138
  yml["packages"].each do |k, v|
115
139
  valid_data = validate_data("packages", v, PACKAGE_SCHEMA)
@@ -137,19 +161,35 @@ module ArduinoCI
137
161
  self
138
162
  end
139
163
 
164
+ # Create a clone of this configuration and return it
165
+ # @return [ArduinoCI::CIConfig] the new settings object
166
+ def clone
167
+ cloned_config = self.class.new
168
+ cloned_config.package_info = deep_clone(@package_info)
169
+ cloned_config.platform_info = deep_clone(@platform_info)
170
+ cloned_config.compile_info = deep_clone(@compile_info)
171
+ cloned_config.unittest_info = deep_clone(@unittest_info)
172
+ cloned_config
173
+ end
174
+
140
175
  # Override these settings with settings from another file
141
176
  # @param path [String] the path to the settings yaml file
142
177
  # @return [ArduinoCI::CIConfig] the new settings object
143
178
  def with_override(path)
144
- overridden_config = self.class.new
145
- overridden_config.package_info = deep_clone(@package_info)
146
- overridden_config.platform_info = deep_clone(@platform_info)
147
- overridden_config.compile_info = deep_clone(@compile_info)
148
- overridden_config.unittest_info = deep_clone(@unittest_info)
179
+ overridden_config = clone
149
180
  overridden_config.load_yaml(path)
150
181
  overridden_config
151
182
  end
152
183
 
184
+ # Override these settings with settings from a hash
185
+ # @param config_hash [Hash] A configuration hash
186
+ # @return [ArduinoCI::CIConfig] the new settings object
187
+ def with_override_config(config_hash)
188
+ overridden_config = clone
189
+ overridden_config.apply_configuration(config_hash)
190
+ overridden_config
191
+ end
192
+
153
193
  # Get the config file at a given path, if it exists, and pass that to a block.
154
194
  # Many config files may exist, but only the first match is used
155
195
  # @param base_dir [String] The directory in which to search for a config file
@@ -1,3 +1,3 @@
1
1
  module ArduinoCI
2
- VERSION = "0.1.16".freeze
2
+ VERSION = "0.1.17".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.16
4
+ version: 0.1.17
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-06 00:00:00.000000000 Z
11
+ date: 2019-01-14 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: os
@@ -401,6 +401,8 @@ files:
401
401
  - cpp/arduino/ci/Queue.h
402
402
  - cpp/arduino/ci/README.md
403
403
  - cpp/arduino/ci/Table.h
404
+ - cpp/arduino/stdlib.cpp
405
+ - cpp/arduino/stdlib.h
404
406
  - cpp/unittest/ArduinoUnitTests.cpp
405
407
  - cpp/unittest/ArduinoUnitTests.h
406
408
  - cpp/unittest/Assertion.h