arduino_ci 0.1.5 → 0.1.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +1 -1
- data/cpp/arduino/Arduino.h +0 -77
- data/cpp/arduino/ArduinoDefines.h +2 -0
- data/cpp/arduino/PinHistory.h +1 -1
- data/cpp/arduino/Print.h +23 -22
- data/cpp/arduino/SoftwareSerial.h +5 -2
- data/cpp/arduino/WString.h +117 -121
- data/cpp/arduino/WString.h.orig +172 -0
- data/cpp/arduino/avr/pgmspace.h +45 -45
- data/cpp/arduino/avr/pgmspace.h.orig +95 -0
- data/cpp/arduino/ci/Queue.h +2 -2
- data/cpp/unittest/ArduinoUnitTests.h +2 -2
- data/cpp/unittest/Compare.h +557 -78
- data/exe/arduino_ci_remote.rb +27 -7
- data/lib/arduino_ci/arduino_cmd.rb +19 -18
- data/lib/arduino_ci/arduino_cmd_linux.rb +9 -2
- data/lib/arduino_ci/arduino_cmd_linux_builder.rb +9 -4
- data/lib/arduino_ci/arduino_cmd_osx.rb +9 -2
- data/lib/arduino_ci/ci_config.rb +2 -0
- data/lib/arduino_ci/cpp_library.rb +12 -15
- data/lib/arduino_ci/cpp_library.rb.orig +215 -0
- data/lib/arduino_ci/display_manager.rb +12 -8
- data/lib/arduino_ci/host.rb +7 -2
- data/lib/arduino_ci/version.rb +1 -1
- metadata +5 -2
data/exe/arduino_ci_remote.rb
CHANGED
@@ -21,11 +21,18 @@ def terminate(final = nil)
|
|
21
21
|
end
|
22
22
|
|
23
23
|
# make a nice status line for an action and react to the action
|
24
|
-
def perform_action(message, on_fail_msg, abort_on_fail)
|
25
|
-
line = "#{message}..."
|
26
|
-
|
24
|
+
def perform_action(message, multiline, on_fail_msg, abort_on_fail)
|
25
|
+
line = "#{message}... "
|
26
|
+
endline = "...#{message} "
|
27
|
+
if multiline
|
28
|
+
puts line
|
29
|
+
else
|
30
|
+
print line
|
31
|
+
end
|
27
32
|
result = yield
|
28
33
|
mark = result ? "✓" : "✗"
|
34
|
+
# if multline, put checkmark at full width
|
35
|
+
print endline if multiline
|
29
36
|
puts mark.rjust(WIDTH - line.length, " ")
|
30
37
|
unless result
|
31
38
|
puts on_fail_msg unless on_fail_msg.nil?
|
@@ -38,12 +45,17 @@ end
|
|
38
45
|
|
39
46
|
# Make a nice status for something that defers any failure code until script exit
|
40
47
|
def attempt(message, &block)
|
41
|
-
perform_action(message, nil, false, &block)
|
48
|
+
perform_action(message, false, nil, false, &block)
|
49
|
+
end
|
50
|
+
|
51
|
+
# Make a nice status for something that defers any failure code until script exit
|
52
|
+
def attempt_multiline(message, &block)
|
53
|
+
perform_action(message, true, nil, false, &block)
|
42
54
|
end
|
43
55
|
|
44
56
|
# Make a nice status for something that kills the script immediately on failure
|
45
57
|
def assure(message, &block)
|
46
|
-
perform_action(message, "This may indicate a problem with ArduinoCI!", true, &block)
|
58
|
+
perform_action(message, false, "This may indicate a problem with ArduinoCI!", true, &block)
|
47
59
|
end
|
48
60
|
|
49
61
|
# initialize command and config
|
@@ -56,6 +68,14 @@ library_examples = @arduino_cmd.library_examples(installed_library_path)
|
|
56
68
|
cpp_library = ArduinoCI::CppLibrary.new(installed_library_path)
|
57
69
|
attempt("Library installed at #{installed_library_path}") { true }
|
58
70
|
|
71
|
+
# check GCC
|
72
|
+
attempt_multiline("Checking GCC version") do
|
73
|
+
version = cpp_library.gcc_version
|
74
|
+
next nil unless version
|
75
|
+
puts version.split("\n").map { |l| " #{l}" }.join("\n")
|
76
|
+
version
|
77
|
+
end
|
78
|
+
|
59
79
|
# gather up all required boards so we can install them up front.
|
60
80
|
# start with the "platforms to unittest" and add the examples
|
61
81
|
# while we're doing that, get the aux libraries as well
|
@@ -97,11 +117,11 @@ elsif config.platforms_to_unittest.empty?
|
|
97
117
|
else
|
98
118
|
config.platforms_to_unittest.each do |p|
|
99
119
|
board = all_platforms[p][:board]
|
100
|
-
|
120
|
+
assure("Switching to board for #{p} (#{board})") { @arduino_cmd.use_board(board) } unless last_board == board
|
101
121
|
last_board = board
|
102
122
|
cpp_library.test_files.each do |unittest_path|
|
103
123
|
unittest_name = File.basename(unittest_path)
|
104
|
-
|
124
|
+
attempt_multiline("Unit testing #{unittest_name}") do
|
105
125
|
exe = cpp_library.build_for_test_with_configuration(
|
106
126
|
unittest_path,
|
107
127
|
config.aux_libraries_for_unittest,
|
@@ -114,12 +114,18 @@ module ArduinoCI
|
|
114
114
|
end
|
115
115
|
|
116
116
|
# run the arduino command
|
117
|
-
|
117
|
+
# @return [bool] whether the command succeeded
|
118
|
+
def _run_and_output(*args, **kwargs)
|
118
119
|
raise "Ian needs to implement this in a subclass #{args} #{kwargs}"
|
119
120
|
end
|
120
121
|
|
121
|
-
#
|
122
|
-
|
122
|
+
# run the arduino command
|
123
|
+
# @return [Hash] keys for :success, :out, and :err
|
124
|
+
def _run_and_capture(*args, **kwargs)
|
125
|
+
raise "Ian needs to implement this in a subclass #{args} #{kwargs}"
|
126
|
+
end
|
127
|
+
|
128
|
+
def _wrap_run(work_fn, *args, **kwargs)
|
123
129
|
# do some work to extract & merge environment variables if they exist
|
124
130
|
has_env = !args.empty? && args[0].class == Hash
|
125
131
|
env_vars = has_env ? args[0] : {}
|
@@ -129,26 +135,21 @@ module ArduinoCI
|
|
129
135
|
|
130
136
|
shell_vars = env_vars.map { |k, v| "#{k}=#{v}" }.join(" ")
|
131
137
|
@last_msg = " $ #{shell_vars} #{full_args.join(' ')}"
|
132
|
-
|
138
|
+
work_fn.call(*full_cmd, **kwargs)
|
139
|
+
end
|
140
|
+
|
141
|
+
# build and run the arduino command
|
142
|
+
def run_and_output(*args, **kwargs)
|
143
|
+
_wrap_run((proc { |*a, **k| _run_and_output(*a, **k) }), *args, **kwargs)
|
133
144
|
end
|
134
145
|
|
135
146
|
# run a command and capture its output
|
136
147
|
# @return [Hash] {:out => String, :err => String, :success => bool}
|
137
148
|
def run_and_capture(*args, **kwargs)
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
success = run(*args, **eventual_kwargs)
|
143
|
-
pipe_out_wr.close
|
144
|
-
pipe_err_wr.close
|
145
|
-
str_out = pipe_out.read
|
146
|
-
str_err = pipe_err.read
|
147
|
-
pipe_out.close
|
148
|
-
pipe_err.close
|
149
|
-
@last_err = str_err
|
150
|
-
@last_out = str_out
|
151
|
-
{ out: str_out, err: str_err, success: success }
|
149
|
+
ret = _wrap_run((proc { |*a, **k| _run_and_capture(*a, **k) }), *args, **kwargs)
|
150
|
+
@last_err = ret[:err]
|
151
|
+
@last_out = ret[:out]
|
152
|
+
ret
|
152
153
|
end
|
153
154
|
|
154
155
|
# run a command and don't capture its output, but use the same signature
|
@@ -39,8 +39,15 @@ module ArduinoCI
|
|
39
39
|
end
|
40
40
|
|
41
41
|
# run the arduino command
|
42
|
-
|
43
|
-
|
42
|
+
# @return [bool] whether the command succeeded
|
43
|
+
def _run_and_output(*args, **kwargs)
|
44
|
+
@display_mgr.run_and_output(*args, **kwargs)
|
45
|
+
end
|
46
|
+
|
47
|
+
# run the arduino command
|
48
|
+
# @return [Hash] keys for :success, :out, and :err
|
49
|
+
def _run_and_capture(*args, **kwargs)
|
50
|
+
@display_mgr.run_and_capture(*args, **kwargs)
|
44
51
|
end
|
45
52
|
|
46
53
|
def run_with_gui_guess(message, *args, **kwargs)
|
@@ -21,10 +21,15 @@ module ArduinoCI
|
|
21
21
|
end
|
22
22
|
|
23
23
|
# run the arduino command
|
24
|
-
# @
|
25
|
-
|
26
|
-
|
27
|
-
|
24
|
+
# @return [bool] whether the command succeeded
|
25
|
+
def _run_and_output(*args, **kwargs)
|
26
|
+
Host.run_and_output(*args, **kwargs)
|
27
|
+
end
|
28
|
+
|
29
|
+
# run the arduino command
|
30
|
+
# @return [Hash] keys for :success, :out, and :err
|
31
|
+
def _run_and_capture(*args, **kwargs)
|
32
|
+
Host.run_and_capture(*args, **kwargs)
|
28
33
|
end
|
29
34
|
|
30
35
|
end
|
@@ -14,8 +14,15 @@ module ArduinoCI
|
|
14
14
|
flag :verify, "--verify"
|
15
15
|
|
16
16
|
# run the arduino command
|
17
|
-
|
18
|
-
|
17
|
+
# @return [bool] whether the command succeeded
|
18
|
+
def _run_and_output(*args, **kwargs)
|
19
|
+
Host.run_and_output(*args, **kwargs)
|
20
|
+
end
|
21
|
+
|
22
|
+
# run the arduino command
|
23
|
+
# @return [Hash] keys for :success, :out, and :err
|
24
|
+
def _run_and_capture(*args, **kwargs)
|
25
|
+
Host.run_and_capture(*args, **kwargs)
|
19
26
|
end
|
20
27
|
|
21
28
|
def _lib_dir
|
data/lib/arduino_ci/ci_config.rb
CHANGED
@@ -200,12 +200,14 @@ module ArduinoCI
|
|
200
200
|
# platforms to build [the examples on]
|
201
201
|
# @return [Array<String>] The platforms to build
|
202
202
|
def platforms_to_build
|
203
|
+
return [] if @compile_info[:platforms].nil?
|
203
204
|
@compile_info[:platforms]
|
204
205
|
end
|
205
206
|
|
206
207
|
# platforms to unit test [the tests on]
|
207
208
|
# @return [Array<String>] The platforms to unit test on
|
208
209
|
def platforms_to_unittest
|
210
|
+
return [] if @unittest_info[:platforms].nil?
|
209
211
|
@unittest_info[:platforms]
|
210
212
|
end
|
211
213
|
|
@@ -108,23 +108,20 @@ module ArduinoCI
|
|
108
108
|
|
109
109
|
# wrapper for the GCC command
|
110
110
|
def run_gcc(*args, **kwargs)
|
111
|
-
pipe_out, pipe_out_wr = IO.pipe
|
112
|
-
pipe_err, pipe_err_wr = IO.pipe
|
113
111
|
full_args = ["g++"] + args
|
114
112
|
@last_cmd = " $ #{full_args.join(' ')}"
|
115
|
-
our_kwargs = { out: pipe_out_wr, err: pipe_err_wr }
|
116
|
-
eventual_kwargs = our_kwargs.merge(kwargs)
|
117
|
-
success = Host.run(*full_args, **eventual_kwargs)
|
118
113
|
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
114
|
+
ret = Host.run_and_capture(*full_args, **kwargs)
|
115
|
+
@last_err = ret[:err]
|
116
|
+
@last_out = ret[:out]
|
117
|
+
ret[:success]
|
118
|
+
end
|
119
|
+
|
120
|
+
# Return the GCC version
|
121
|
+
# @return [String] the version reported by `gcc -v`
|
122
|
+
def gcc_version
|
123
|
+
return nil unless run_gcc("-v")
|
124
|
+
@last_err
|
128
125
|
end
|
129
126
|
|
130
127
|
# GCC command line arguments for including aux libraries
|
@@ -207,7 +204,7 @@ module ArduinoCI
|
|
207
204
|
@last_cmd = executable
|
208
205
|
@last_out = ""
|
209
206
|
@last_err = ""
|
210
|
-
Host.
|
207
|
+
Host.run_and_output(executable)
|
211
208
|
end
|
212
209
|
|
213
210
|
end
|
@@ -0,0 +1,215 @@
|
|
1
|
+
require 'find'
|
2
|
+
require "arduino_ci/host"
|
3
|
+
|
4
|
+
HPP_EXTENSIONS = [".hpp", ".hh", ".h", ".hxx", ".h++"].freeze
|
5
|
+
CPP_EXTENSIONS = [".cpp", ".cc", ".c", ".cxx", ".c++"].freeze
|
6
|
+
ARDUINO_HEADER_DIR = File.expand_path("../../../cpp/arduino", __FILE__)
|
7
|
+
UNITTEST_HEADER_DIR = File.expand_path("../../../cpp/unittest", __FILE__)
|
8
|
+
|
9
|
+
module ArduinoCI
|
10
|
+
|
11
|
+
# Information about an Arduino CPP library, specifically for compilation purposes
|
12
|
+
class CppLibrary
|
13
|
+
|
14
|
+
# @return [String] The path to the library being tested
|
15
|
+
attr_reader :base_dir
|
16
|
+
|
17
|
+
# @return [Array<String>] The set of artifacts created by this class (note: incomplete!)
|
18
|
+
attr_reader :artifacts
|
19
|
+
|
20
|
+
# @return [String] STDERR from the last command
|
21
|
+
attr_reader :last_err
|
22
|
+
|
23
|
+
# @return [String] STDOUT from the last command
|
24
|
+
attr_reader :last_out
|
25
|
+
|
26
|
+
# @return [String] the last command
|
27
|
+
attr_reader :last_cmd
|
28
|
+
|
29
|
+
# @param base_dir [String] The path to the library being tested
|
30
|
+
def initialize(base_dir)
|
31
|
+
@base_dir = File.expand_path(base_dir)
|
32
|
+
@artifacts = []
|
33
|
+
@last_err = ""
|
34
|
+
@last_out = ""
|
35
|
+
@last_msg = ""
|
36
|
+
end
|
37
|
+
|
38
|
+
# Guess whether a file is part of the vendor bundle (indicating we should ignore it).
|
39
|
+
#
|
40
|
+
# This assumes the vendor bundle will be at `vendor/bundle` and not some other location
|
41
|
+
# @param path [String] The path to check
|
42
|
+
# @return [Array<String>] The paths of the found files
|
43
|
+
def vendor_bundle?(path)
|
44
|
+
# TODO: look for Gemfile, look for .bundle/config and get BUNDLE_PATH from there?
|
45
|
+
base = File.join(@base_dir, "vendor")
|
46
|
+
real = File.join(File.realpath(@base_dir), "vendor")
|
47
|
+
return true if path.start_with?(base)
|
48
|
+
return true if path.start_with?(real)
|
49
|
+
false
|
50
|
+
end
|
51
|
+
|
52
|
+
# Get a list of all CPP source files in a directory and its subdirectories
|
53
|
+
# @param some_dir [String] The directory in which to begin the search
|
54
|
+
# @return [Array<String>] The paths of the found files
|
55
|
+
def cpp_files_in(some_dir)
|
56
|
+
return [] unless File.exist?(some_dir)
|
57
|
+
real = File.realpath(some_dir)
|
58
|
+
files = Find.find(real).reject { |path| File.directory?(path) }
|
59
|
+
ret = files.select { |path| CPP_EXTENSIONS.include?(File.extname(path)) }
|
60
|
+
ret
|
61
|
+
end
|
62
|
+
|
63
|
+
# CPP files that are part of the project library under test
|
64
|
+
# @return [Array<String>]
|
65
|
+
def cpp_files
|
66
|
+
real_tests_dir = File.realpath(tests_dir)
|
67
|
+
cpp_files_in(@base_dir).reject do |p|
|
68
|
+
next true if File.dirname(p).include?(tests_dir)
|
69
|
+
next true if File.dirname(p).include?(real_tests_dir)
|
70
|
+
next true if vendor_bundle?(p)
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
# CPP files that are part of the arduino mock library we're providing
|
75
|
+
# @return [Array<String>]
|
76
|
+
def cpp_files_arduino
|
77
|
+
cpp_files_in(ARDUINO_HEADER_DIR)
|
78
|
+
end
|
79
|
+
|
80
|
+
# CPP files that are part of the unit test library we're providing
|
81
|
+
# @return [Array<String>]
|
82
|
+
def cpp_files_unittest
|
83
|
+
cpp_files_in(UNITTEST_HEADER_DIR)
|
84
|
+
end
|
85
|
+
|
86
|
+
# The directory where we expect to find unit test defintions provided by the user
|
87
|
+
# @return [String]
|
88
|
+
def tests_dir
|
89
|
+
File.join(@base_dir, "test")
|
90
|
+
end
|
91
|
+
|
92
|
+
# The files provided by the user that contain unit tests
|
93
|
+
# @return [Array<String>]
|
94
|
+
def test_files
|
95
|
+
cpp_files_in(tests_dir)
|
96
|
+
end
|
97
|
+
|
98
|
+
# Find all directories in the project library that include C++ header files
|
99
|
+
# @return [Array<String>]
|
100
|
+
def header_dirs
|
101
|
+
real = File.realpath(@base_dir)
|
102
|
+
all_files = Find.find(real).reject { |path| File.directory?(path) }
|
103
|
+
unbundled = all_files.reject { |path| vendor_bundle?(path) }
|
104
|
+
files = unbundled.select { |path| HPP_EXTENSIONS.include?(File.extname(path)) }
|
105
|
+
ret = files.map { |path| File.dirname(path) }.uniq
|
106
|
+
ret
|
107
|
+
end
|
108
|
+
|
109
|
+
# wrapper for the GCC command
|
110
|
+
def run_gcc(*args, **kwargs)
|
111
|
+
full_args = ["g++-4.9"] + args
|
112
|
+
@last_cmd = " $ #{full_args.join(' ')}"
|
113
|
+
<<<<<<< Updated upstream
|
114
|
+
|
115
|
+
=======
|
116
|
+
>>>>>>> Stashed changes
|
117
|
+
ret = Host.run_and_capture(*full_args, **kwargs)
|
118
|
+
@last_err = ret[:err]
|
119
|
+
@last_out = ret[:out]
|
120
|
+
ret[:success]
|
121
|
+
end
|
122
|
+
|
123
|
+
# Return the GCC version
|
124
|
+
# @return [String] the version reported by `gcc -v`
|
125
|
+
def gcc_version
|
126
|
+
return nil unless run_gcc("-v")
|
127
|
+
@last_err
|
128
|
+
end
|
129
|
+
|
130
|
+
# GCC command line arguments for including aux libraries
|
131
|
+
# @param aux_libraries [String] The external Arduino libraries required by this project
|
132
|
+
# @return [Array<String>] The GCC command-line flags necessary to include those libraries
|
133
|
+
def include_args(aux_libraries)
|
134
|
+
places = [ARDUINO_HEADER_DIR, UNITTEST_HEADER_DIR] + header_dirs + aux_libraries
|
135
|
+
places.map { |d| "-I#{d}" }
|
136
|
+
end
|
137
|
+
|
138
|
+
# GCC command line arguments for features (e.g. -fno-weak)
|
139
|
+
# @param ci_gcc_config [Hash] The GCC config object
|
140
|
+
# @return [Array<String>] GCC command-line flags
|
141
|
+
def feature_args(ci_gcc_config)
|
142
|
+
return [] if ci_gcc_config[:features].nil?
|
143
|
+
ci_gcc_config[:features].map { |f| "-f#{f}" }
|
144
|
+
end
|
145
|
+
|
146
|
+
# GCC command line arguments for warning (e.g. -Wall)
|
147
|
+
# @param ci_gcc_config [Hash] The GCC config object
|
148
|
+
# @return [Array<String>] GCC command-line flags
|
149
|
+
def warning_args(ci_gcc_config)
|
150
|
+
return [] if ci_gcc_config[:warnings].nil?
|
151
|
+
ci_gcc_config[:features].map { |w| "-W#{w}" }
|
152
|
+
end
|
153
|
+
|
154
|
+
# GCC command line arguments for defines (e.g. -Dhave_something)
|
155
|
+
# @param ci_gcc_config [Hash] The GCC config object
|
156
|
+
# @return [Array<String>] GCC command-line flags
|
157
|
+
def define_args(ci_gcc_config)
|
158
|
+
return [] if ci_gcc_config[:defines].nil?
|
159
|
+
ci_gcc_config[:defines].map { |d| "-D#{d}" }
|
160
|
+
end
|
161
|
+
|
162
|
+
# GCC command line arguments as-is
|
163
|
+
# @param ci_gcc_config [Hash] The GCC config object
|
164
|
+
# @return [Array<String>] GCC command-line flags
|
165
|
+
def flag_args(ci_gcc_config)
|
166
|
+
return [] if ci_gcc_config[:flags].nil?
|
167
|
+
ci_gcc_config[:flags]
|
168
|
+
end
|
169
|
+
|
170
|
+
# All GCC command line args for building any unit test
|
171
|
+
# @param aux_libraries [String] The external Arduino libraries required by this project
|
172
|
+
# @param ci_gcc_config [Hash] The GCC config object
|
173
|
+
# @return [Array<String>] GCC command-line flags
|
174
|
+
def test_args(aux_libraries, ci_gcc_config)
|
175
|
+
# TODO: something with libraries?
|
176
|
+
ret = include_args(aux_libraries) + cpp_files_arduino + cpp_files_unittest + cpp_files
|
177
|
+
unless ci_gcc_config.nil?
|
178
|
+
cgc = ci_gcc_config
|
179
|
+
ret = feature_args(cgc) + warning_args(cgc) + define_args(cgc) + flag_args(cgc) + ret
|
180
|
+
end
|
181
|
+
ret
|
182
|
+
end
|
183
|
+
|
184
|
+
# build a file for running a test of the given unit test file
|
185
|
+
# @param test_file [String] The path to the file containing the unit tests
|
186
|
+
# @param aux_libraries [String] The external Arduino libraries required by this project
|
187
|
+
# @param ci_gcc_config [Hash] The GCC config object
|
188
|
+
# @return [String] path to the compiled test executable
|
189
|
+
def build_for_test_with_configuration(test_file, aux_libraries, ci_gcc_config)
|
190
|
+
base = File.basename(test_file)
|
191
|
+
executable = File.expand_path("unittest_#{base}.bin")
|
192
|
+
File.delete(executable) if File.exist?(executable)
|
193
|
+
args = [
|
194
|
+
["-std=c++0x", "-o", executable, "-DARDUINO=100"],
|
195
|
+
test_args(aux_libraries, ci_gcc_config),
|
196
|
+
[test_file],
|
197
|
+
].flatten(1)
|
198
|
+
return nil unless run_gcc(*args)
|
199
|
+
artifacts << executable
|
200
|
+
executable
|
201
|
+
end
|
202
|
+
|
203
|
+
# run a test file
|
204
|
+
# @param [String] the path to the test file
|
205
|
+
# @return [bool] whether all tests were successful
|
206
|
+
def run_test_file(executable)
|
207
|
+
@last_cmd = executable
|
208
|
+
@last_out = ""
|
209
|
+
@last_err = ""
|
210
|
+
Host.run_and_output(executable)
|
211
|
+
end
|
212
|
+
|
213
|
+
end
|
214
|
+
|
215
|
+
end
|