Skip to content

Commit 49a7b1d

Browse files
authored
Merge pull request #130 from ianfixes/2019-07-31_bugfixes
Bugfixes
2 parents cb3fe8d + 04ff114 commit 49a7b1d

File tree

7 files changed

+90
-54
lines changed

7 files changed

+90
-54
lines changed

CHANGELOG.md

Lines changed: 15 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -7,35 +7,38 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
77

88
## [Unreleased]
99
### Added
10-
1110
- Minimal Wire mocks. Will not provide support for unit testing I2C communication yet, but will allow compilation of libraries that use I2C.
11+
- `StreamTape` class now bridges `Stream` and `HardwareSerial` to allow general-purpose stream mocking & history
1212

1313
### Changed
14+
- Arduino command failures (to read preferences) now causes a fatal error, with help for troubleshooting the underlying command
1415

1516
### Deprecated
1617

1718
### Removed
1819

1920
### Fixed
21+
- Arduino library dependencies are now installed prior to unit testing, instead of prior to compilation testing. Whoops.
22+
- Arduino library dependencies with spaces in their names are now handled properly during compilation -- spaces are automatically coerced to underscores
2023

2124
### Security
2225

2326

2427
## [0.2.0] - 2019-02-20
2528
### Added
26-
* `release-new-version.sh` script
27-
* outputs for `PinHistory` can now report timestamps
28-
* Fibonacci Clock for clock testing purposes (internal to this library)
29+
- `release-new-version.sh` script
30+
- outputs for `PinHistory` can now report timestamps
31+
- Fibonacci Clock for clock testing purposes (internal to this library)
2932

3033
### Changed
31-
* Shortened `ArduinoQueue` push and pop operations
32-
* `ci/Queue.h` is now `MockEventQueue.h`, with timing data
33-
* `MockEventQueue::Node` now contains struct `MockEventQueue::Event`, which contains both the templated type `T` and a field for a timestamp.
34-
* Construction of `MockEventQueue` now includes a constructor argument for the time-fetching function
35-
* Construction of `PinHistory` now includes a constructor argument for the time-fetching function
36-
* `PinHistory` can now return an array of timestamps for its events
37-
* `GodmodeState` is now a singleton pattern, which is necessary to support the globality of Arduino functions
38-
* `GodmodeState` now uses timestamped PinHistory for Analog and Digital
34+
- Shortened `ArduinoQueue` push and pop operations
35+
- `ci/Queue.h` is now `MockEventQueue.h`, with timing data
36+
- `MockEventQueue::Node` now contains struct `MockEventQueue::Event`, which contains both the templated type `T` and a field for a timestamp.
37+
- Construction of `MockEventQueue` now includes a constructor argument for the time-fetching function
38+
- Construction of `PinHistory` now includes a constructor argument for the time-fetching function
39+
- `PinHistory` can now return an array of timestamps for its events
40+
- `GodmodeState` is now a singleton pattern, which is necessary to support the globality of Arduino functions
41+
- `GodmodeState` now uses timestamped PinHistory for Analog and Digital
3942

4043
### Fixed
4144
* `ArduinoQueue` no longer leaks memory

cpp/arduino/HardwareSerial.h

Lines changed: 5 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
#pragma once
22

33
//#include <inttypes.h>
4-
#include "Stream.h"
4+
#include "ci/StreamTape.h"
55

66
// definitions neeeded for Serial.begin's config arg
77
#define SERIAL_5N1 0x00
@@ -29,38 +29,19 @@
2929
#define SERIAL_7O2 0x3C
3030
#define SERIAL_8O2 0x3E
3131

32-
class HardwareSerial : public Stream, public ObservableDataStream
32+
class HardwareSerial : public StreamTape
3333
{
34-
protected:
35-
String* mGodmodeDataOut;
36-
3734
public:
38-
HardwareSerial(String* dataIn, String* dataOut, unsigned long* delay): Stream(), ObservableDataStream() {
39-
mGodmodeDataIn = dataIn;
40-
mGodmodeDataOut = dataOut;
41-
mGodmodeMicrosDelay = delay;
42-
}
35+
HardwareSerial(String* dataIn, String* dataOut, unsigned long* delay): StreamTape(dataIn, dataOut, delay) {}
36+
4337
void begin(unsigned long baud) { begin(baud, SERIAL_8N1); }
4438
void begin(unsigned long baud, uint8_t config) {
4539
*mGodmodeMicrosDelay = 1000000 / baud;
4640
}
4741
void end() {}
4842

49-
// virtual int available(void);
50-
// virtual int peek(void);
51-
// virtual int read(void);
52-
// virtual int availableForWrite(void);
53-
// virtual void flush(void);
54-
virtual size_t write(uint8_t aChar) {
55-
mGodmodeDataOut->append(String((char)aChar));
56-
advertiseByte((unsigned char)aChar);
57-
return 1;
58-
}
59-
60-
// https://stackoverflow.com/a/4271276
61-
using Print::write; // pull in write(str) and write(buf, size) from Print
43+
// support "if (Serial1) {}" sorts of things
6244
operator bool() { return true; }
63-
6445
};
6546

6647
#if defined(UBRRH) || defined(UBRR0H)

cpp/arduino/ci/StreamTape.h

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
#pragma once
2+
3+
#include "../Stream.h"
4+
5+
/**
6+
* Stream with godmode-controlled input and godmode-persisted output
7+
*/
8+
class StreamTape : public Stream, public ObservableDataStream
9+
{
10+
protected:
11+
String* mGodmodeDataOut;
12+
// mGodmodeDataIn is provided by Stream
13+
14+
public:
15+
StreamTape(String* dataIn, String* dataOut, unsigned long* delay): Stream(), ObservableDataStream() {
16+
mGodmodeDataIn = dataIn;
17+
mGodmodeDataOut = dataOut;
18+
mGodmodeMicrosDelay = delay;
19+
}
20+
21+
// virtual int available(void);
22+
// virtual int peek(void);
23+
// virtual int read(void);
24+
// virtual int availableForWrite(void);
25+
// virtual void flush(void);
26+
virtual size_t write(uint8_t aChar) {
27+
mGodmodeDataOut->append(String((char)aChar));
28+
advertiseByte((unsigned char)aChar);
29+
return 1;
30+
}
31+
32+
// https://stackoverflow.com/a/4271276
33+
using Print::write; // pull in write(str) and write(buf, size) from Print
34+
35+
};
36+

exe/arduino_ci_remote.rb

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,16 @@ def display_files(pathname)
167167
non_hidden.each { |p| puts "#{margin}#{p}" }
168168
end
169169

170+
def install_arduino_library_dependencies(aux_libraries)
171+
aux_libraries.each do |l|
172+
if @arduino_cmd.library_present?(l)
173+
inform("Using pre-existing library") { l.to_s }
174+
else
175+
assure("Installing aux library '#{l}'") { @arduino_cmd.install_library(l) }
176+
end
177+
end
178+
end
179+
170180
def perform_unit_tests(file_config)
171181
if @cli_options[:skip_unittests]
172182
inform("Skipping unit tests") { "as requested via command line" }
@@ -209,6 +219,8 @@ def perform_unit_tests(file_config)
209219
elsif config.platforms_to_unittest.empty?
210220
inform("Skipping unit tests") { "no platforms were requested" }
211221
else
222+
install_arduino_library_dependencies(config.aux_libraries_for_unittest)
223+
212224
config.platforms_to_unittest.each do |p|
213225
config.allowable_unittest_files(cpp_library.test_files).each do |unittest_path|
214226
unittest_name = unittest_path.basename.to_s
@@ -273,7 +285,7 @@ def perform_compilation_tests(config)
273285
# while we're doing that, get the aux libraries as well
274286
example_platform_info = {}
275287
board_package_url = {}
276-
aux_libraries = Set.new(config.aux_libraries_for_unittest + config.aux_libraries_for_build)
288+
aux_libraries = Set.new(config.aux_libraries_for_build)
277289
# while collecting the platforms, ensure they're defined
278290

279291
library_examples.each do |path|
@@ -322,13 +334,7 @@ def perform_compilation_tests(config)
322334
end
323335
end
324336

325-
aux_libraries.each do |l|
326-
if @arduino_cmd.library_present?(l)
327-
inform("Using pre-existing library") { l.to_s }
328-
else
329-
assure("Installing aux library '#{l}'") { @arduino_cmd.install_library(l) }
330-
end
331-
end
337+
install_arduino_library_dependencies(aux_libraries)
332338

333339
last_board = nil
334340
if config.platforms_to_build.empty?

lib/arduino_ci/arduino_cmd.rb

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,9 @@
66

77
module ArduinoCI
88

9+
# To report errors that we can't resolve or possibly even explain
10+
class ArduinoExecutionError < StandardError; end
11+
912
# Wrap the Arduino executable. This requires, in some cases, a faked display.
1013
class ArduinoCmd
1114

@@ -42,14 +45,14 @@ def self.flag(name, text = nil)
4245
attr_reader :last_msg
4346

4447
# set the command line flags (undefined for now).
45-
# These vary between gui/cli
46-
flag :get_pref
47-
flag :set_pref
48-
flag :save_prefs
49-
flag :use_board
50-
flag :install_boards
51-
flag :install_library
52-
flag :verify
48+
# These vary between gui/cli. Inline comments added for greppability
49+
flag :get_pref # flag_get_pref
50+
flag :set_pref # flag_set_pref
51+
flag :save_prefs # flag_save_prefs
52+
flag :use_board # flag_use_board
53+
flag :install_boards # flag_install_boards
54+
flag :install_library # flag_install_library
55+
flag :verify # flag_verify
5356

5457
def initialize
5558
@prefs_cache = {}
@@ -82,7 +85,8 @@ def lib_dir
8285
# @return [String] Preferences as a set of lines
8386
def _prefs_raw
8487
resp = run_and_capture(flag_get_pref)
85-
return nil unless resp[:success]
88+
fail_msg = "Arduino binary failed to operate as expected; you will have to troubleshoot it manually"
89+
raise ArduinoExecutionError, "#{fail_msg}. The command was #{@last_msg}" unless resp[:success]
8690

8791
@prefs_fetched = true
8892
resp[:out]

lib/arduino_ci/ci_config.rb

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -293,9 +293,12 @@ def allowable_unittest_files(paths)
293293
return paths if @unittest_info[:testfiles].nil?
294294

295295
ret = paths
296+
# Check for array emptiness, otherwise nothing will be selected!
296297
unless @unittest_info[:testfiles][:select].nil? || @unittest_info[:testfiles][:select].empty?
297298
ret.select! { |p| unittest_info[:testfiles][:select].any? { |glob| p.basename.fnmatch(glob) } }
298299
end
300+
301+
# It's OK for the :reject array to be empty, that means nothing will be rejected by default
299302
unless @unittest_info[:testfiles][:reject].nil?
300303
ret.reject! { |p| unittest_info[:testfiles][:reject].any? { |glob| p.basename.fnmatch(glob) } }
301304
end

lib/arduino_ci/cpp_library.rb

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -220,7 +220,10 @@ def arduino_library_src_dirs(aux_libraries)
220220
# TODO: be smart and implement library spec (library.properties, etc)?
221221
subdirs = ["", "src", "utility"]
222222
all_aux_include_dirs_nested = aux_libraries.map do |libdir|
223-
subdirs.map { |subdir| Pathname.new(@arduino_lib_dir) + libdir + subdir }
223+
# library manager coerces spaces in package names to underscores
224+
# see https://github.com/ianfixes/arduino_ci/issues/132#issuecomment-518857059
225+
legal_libdir = libdir.tr(" ", "_")
226+
subdirs.map { |subdir| Pathname.new(@arduino_lib_dir) + legal_libdir + subdir }
224227
end
225228
all_aux_include_dirs_nested.flatten.select(&:exist?).select(&:directory?)
226229
end

0 commit comments

Comments
 (0)