Skip to content

Commit 0ea7802

Browse files
committed
Add ability to use multiple compilers in a test
1 parent bc846b1 commit 0ea7802

10 files changed

+86
-48
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
88
### Added
99
- Definition of `LED_BUILTIN`, first reported by `dfrencham` on GitHub
1010
- Stubs for `tone` and `noTone`, first suggested by `dfrencham` on GitHub
11+
- Ability to specify multiple compilers for unit testing
1112

1213
### Changed
1314

README.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -349,6 +349,10 @@ For your unit tests, in addition to setting specific libraries and platforms, yo
349349
350350
```yaml
351351
unittest:
352+
compilers:
353+
- g++ # default
354+
- g++-4.9
355+
- g++-7
352356
testfiles:
353357
select:
354358
- "*-*.*"

exe/arduino_ci_remote.rb

Lines changed: 24 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -69,11 +69,15 @@ def assure(message, &block)
6969
attempt("Library installed at #{installed_library_path}") { true }
7070

7171
# 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
72+
compilers = config.compilers_to_use
73+
assure("The set of compilers (#{compilers.length}) isn't empty") { !compilers.empty? }
74+
compilers.each do |gcc_binary|
75+
attempt_multiline("Checking #{gcc_binary} version") do
76+
version = cpp_library.gcc_version(gcc_binary)
77+
next nil unless version
78+
puts version.split("\n").map { |l| " #{l}" }.join("\n")
79+
version
80+
end
7781
end
7882

7983
# gather up all required boards so we can install them up front.
@@ -121,20 +125,22 @@ def assure(message, &block)
121125
last_board = board
122126
cpp_library.test_files.each do |unittest_path|
123127
unittest_name = File.basename(unittest_path)
124-
attempt_multiline("Unit testing #{unittest_name}") do
125-
exe = cpp_library.build_for_test_with_configuration(
126-
unittest_path,
127-
config.aux_libraries_for_unittest,
128-
config.gcc_config(p)
129-
)
130-
puts
131-
unless exe
132-
puts "Last command: #{cpp_library.last_cmd}"
133-
puts cpp_library.last_out
134-
puts cpp_library.last_err
135-
next false
128+
compilers.each do |gcc_binary|
129+
attempt_multiline("Unit testing #{unittest_name} with #{gcc_binary}") do
130+
exe = cpp_library.build_for_test_with_configuration(
131+
unittest_path,
132+
config.aux_libraries_for_unittest,
133+
config.gcc_config(p)
134+
)
135+
puts
136+
unless exe
137+
puts "Last command: #{cpp_library.last_cmd}"
138+
puts cpp_library.last_out
139+
puts cpp_library.last_err
140+
next false
141+
end
142+
cpp_library.run_test_file(exe)
136143
end
137-
cpp_library.run_test_file(exe)
138144
end
139145
end
140146
end

lib/arduino_ci/ci_config.rb

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
}.freeze
2626

2727
UNITTEST_SCHEMA = {
28+
compilers: Array,
2829
platforms: Array,
2930
libraries: Array,
3031
testfiles: {
@@ -197,6 +198,13 @@ def package_url(package)
197198
@package_info[package][:url]
198199
end
199200

201+
# compilers to build (unit tests) with
202+
# @return [Array<String>] The compiler binary names (e.g. g++) to build with
203+
def compilers_to_use
204+
return [] if @unittest_info[:compilers].nil?
205+
@unittest_info[:compilers]
206+
end
207+
200208
# platforms to build [the examples on]
201209
# @return [Array<String>] The platforms to build
202210
def platforms_to_build

lib/arduino_ci/cpp_library.rb

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -107,10 +107,9 @@ def header_dirs
107107
end
108108

109109
# wrapper for the GCC command
110-
def run_gcc(*args, **kwargs)
111-
full_args = ["g++"] + args
110+
def run_gcc(gcc_binary, *args, **kwargs)
111+
full_args = [gcc_binary] + args
112112
@last_cmd = " $ #{full_args.join(' ')}"
113-
114113
ret = Host.run_and_capture(*full_args, **kwargs)
115114
@last_err = ret[:err]
116115
@last_out = ret[:out]
@@ -119,8 +118,8 @@ def run_gcc(*args, **kwargs)
119118

120119
# Return the GCC version
121120
# @return [String] the version reported by `gcc -v`
122-
def gcc_version
123-
return nil unless run_gcc("-v")
121+
def gcc_version(gcc_binary)
122+
return nil unless run_gcc(gcc_binary, "-v")
124123
@last_err
125124
end
126125

@@ -183,7 +182,7 @@ def test_args(aux_libraries, ci_gcc_config)
183182
# @param aux_libraries [String] The external Arduino libraries required by this project
184183
# @param ci_gcc_config [Hash] The GCC config object
185184
# @return [String] path to the compiled test executable
186-
def build_for_test_with_configuration(test_file, aux_libraries, ci_gcc_config)
185+
def build_for_test_with_configuration(test_file, aux_libraries, gcc_binary, ci_gcc_config)
187186
base = File.basename(test_file)
188187
executable = File.expand_path("unittest_#{base}.bin")
189188
File.delete(executable) if File.exist?(executable)
@@ -192,7 +191,7 @@ def build_for_test_with_configuration(test_file, aux_libraries, ci_gcc_config)
192191
test_args(aux_libraries, ci_gcc_config),
193192
[test_file],
194193
].flatten(1)
195-
return nil unless run_gcc(*args)
194+
return nil unless run_gcc(gcc_binary, *args)
196195
artifacts << executable
197196
executable
198197
end

misc/default.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,8 @@ compile:
8080
- leonardo
8181

8282
unittest:
83+
compilers:
84+
- g++
8385
libraries: ~
8486
platforms:
8587
- uno

spec/ci_config_spec.rb

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@
2828
expect(default_config.platforms_to_unittest).to match(["uno", "due", "zero", "leonardo"])
2929
expect(default_config.aux_libraries_for_build).to match([])
3030
expect(default_config.aux_libraries_for_unittest).to match([])
31+
32+
expect(default_config.compilers_to_use).to match(["g++"])
3133
end
3234
end
3335

@@ -63,6 +65,9 @@
6365
expect(combined_config.platforms_to_unittest).to match(["bogo"])
6466
expect(combined_config.aux_libraries_for_build).to match(["Adafruit FONA Library"])
6567
expect(combined_config.aux_libraries_for_unittest).to match(["abc123", "def456"])
68+
69+
expect(combined_config.compilers_to_use).to match(["g++", "g++-7"])
70+
6671
end
6772
end
6873

spec/cpp_library_spec.rb

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -62,10 +62,12 @@
6262
test_files = cpp_library.test_files
6363
test_files.each do |path|
6464
expected = path.include?("good")
65-
it "tests #{File.basename(path)} expecting #{expected}" do
66-
exe = cpp_library.build_for_test_with_configuration(path, [], config.gcc_config("uno"))
67-
expect(exe).not_to be nil
68-
expect(cpp_library.run_test_file(exe)).to eq(expected)
65+
config.compilers_to_use.each do |compiler|
66+
it "tests #{File.basename(path)} with #{compiler} expecting #{expected}" do
67+
exe = cpp_library.build_for_test_with_configuration(path, [], compiler, config.gcc_config("uno"))
68+
expect(exe).not_to be nil
69+
expect(cpp_library.run_test_file(exe)).to eq(expected)
70+
end
6971
end
7072
end
7173
end

spec/testsomething_unittests_spec.rb

Lines changed: 27 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -26,32 +26,40 @@
2626
expect(allowed_files.empty?).to be false
2727
end
2828

29+
it "has at least one compiler defined" do
30+
expect(config.compilers_to_use.length.zero?).to be(false)
31+
end
32+
2933
test_files = config.allowable_unittest_files(cpp_library.test_files)
3034
test_files.each do |path|
3135
tfn = File.basename(path)
32-
context "file #{tfn}" do
3336

34-
before(:all) do
35-
@exe = cpp_library.build_for_test_with_configuration(path, [], config.gcc_config("uno"))
36-
end
37+
config.compilers_to_use.each do |compiler|
3738

38-
# extra debug for c++ failures
39-
after(:each) do |example|
40-
if example.exception
41-
puts "Last command: #{cpp_library.last_cmd}"
42-
puts "========== Stdout:"
43-
puts cpp_library.last_out
44-
puts "========== Stderr:"
45-
puts cpp_library.last_err
39+
context "file #{tfn} (using #{compiler})" do
40+
41+
before(:all) do
42+
@exe = cpp_library.build_for_test_with_configuration(path, [], compiler, config.gcc_config("uno"))
4643
end
47-
end
4844

49-
it "#{tfn} builds successfully" do
50-
expect(@exe).not_to be nil
51-
end
52-
it "#{tfn} passes tests" do
53-
skip "Can't run the test program because it failed to build" if @exe.nil?
54-
expect(cpp_library.run_test_file(@exe)).to_not be_falsey
45+
# extra debug for c++ failures
46+
after(:each) do |example|
47+
if example.exception
48+
puts "Last command: #{cpp_library.last_cmd}"
49+
puts "========== Stdout:"
50+
puts cpp_library.last_out
51+
puts "========== Stderr:"
52+
puts cpp_library.last_err
53+
end
54+
end
55+
56+
it "#{tfn} builds successfully" do
57+
expect(@exe).not_to be nil
58+
end
59+
it "#{tfn} passes tests" do
60+
skip "Can't run the test program because it failed to build" if @exe.nil?
61+
expect(cpp_library.run_test_file(@exe)).to_not be_falsey
62+
end
5563
end
5664
end
5765
end

spec/yaml/o1.yaml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,9 @@ compile:
3232
- esp8266
3333

3434
unittest:
35+
compilers:
36+
- g++
37+
- g++-7
3538
testfiles:
3639
select:
3740
- "*-*.*"

0 commit comments

Comments
 (0)