Skip to content

Commit 44429db

Browse files
authored
Merge pull request #12 from ifreecarve/2018-01-25_tweaks
More CI fixes
2 parents 2332a97 + 3f4fb5f commit 44429db

16 files changed

+140
-69
lines changed

CHANGELOG.md

+9
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,23 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
66

77
## [Unreleased]
88
### Added
9+
- C++ functions for `assure`; `assert`s will run tests and continue, `assure`s will abort on failures
10+
- Missing dotfiles in the `DoSomething` project have been committed
911

1012
### Changed
13+
- `arduino_ci_remote.rb` doesn't attempt to set URLs if nothing needs to be downloaded
14+
- `arduino_ci_remote.rb` does unit tests first
15+
- `unittest_main()` is now the macro for the `int main()` of test files
1116

1217
### Deprecated
1318

1419
### Removed
1520

1621
### Fixed
22+
- All test files were reporting "not ok" in TAP output. Now they are OK iff all asserts pass.
23+
- Directories with a C++ extension in their name could cause problems. Now they are ignored.
24+
- `CppLibrary` had trouble with symlinks. It shoudn't anymore.
25+
- `CppLibrary` had trouble with vendor bundles. It might in the future, but I have a better fix ready to go if it's an issue.
1726

1827
### Security
1928

README.md

+2-4
Original file line numberDiff line numberDiff line change
@@ -43,12 +43,10 @@ unittest(your_test_name)
4343
assertEqual(4, doSomething());
4444
}
4545
46-
int main(int argc, char *argv[]) {
47-
return Test::run_and_report(argc, argv);
48-
}
46+
unittest_main()
4947
```
5048

51-
This test defines one `unittest` (a macro provided by `ArduionUnitTests.h`), called `your_test_name`, which makes some assertions on the target library. The `int main` section is boilerplate.
49+
This test defines one `unittest` (a macro provided by `ArduionUnitTests.h`), called `your_test_name`, which makes some assertions on the target library. The `unittest_main()` is a macro for the `int main()` boilerplate required for unit testing.
5250

5351

5452
## More Documentation
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
compile:
2+
libraries: ~
3+
platforms:
4+
- uno
5+
- due
6+
- leonardo
7+
8+
unittest:
9+
libraries: ~
10+
platforms:
11+
- uno
12+
- due
13+
- leonardo
+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
sudo: false
2+
language: ruby
3+
script:
4+
- bundle install
5+
- bundle exec arduino_ci_remote.rb

SampleProjects/DoSomething/README.md

+1-3
Original file line numberDiff line numberDiff line change
@@ -98,9 +98,7 @@ unittest(your_test_name)
9898
assertEqual(4, doSomething());
9999
}
100100
101-
int main(int argc, char *argv[]) {
102-
return Test::run_and_report(argc, argv);
103-
}
101+
unittest_main()
104102
```
105103

106104
This test defines one `unittest` (a macro provided by `ArduionUnitTests.h`), called `your_test_name`, which makes some assertions on the target library. The `int main` section is boilerplate.

SampleProjects/DoSomething/test/good-library.cpp

+1-3
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,4 @@ unittest(library_does_something)
66
assertEqual(4, doSomething());
77
}
88

9-
int main(int argc, char *argv[]) {
10-
return Test::run_and_report(argc, argv);
11-
}
9+
unittest_main()

SampleProjects/DoSomething/test/good-null.cpp

+1-3
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,4 @@ unittest(nothing)
1919
{
2020
}
2121

22-
int main(int argc, char *argv[]) {
23-
return Test::run_and_report(argc, argv);
24-
}
22+
unittest_main()

SampleProjects/TestSomething/test/bad-null.cpp

+1-3
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,4 @@ unittest(pretend_equal_things_arent)
77
assertNotEqual(x, y);
88
}
99

10-
int main(int argc, char *argv[]) {
11-
return Test::run_and_report(argc, argv);
12-
}
10+
unittest_main()

SampleProjects/TestSomething/test/good-library.cpp

+1-3
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,4 @@ unittest(library_tests_something)
66
assertEqual(4, testSomething());
77
}
88

9-
int main(int argc, char *argv[]) {
10-
return Test::run_and_report(argc, argv);
11-
}
9+
unittest_main()

SampleProjects/TestSomething/test/good-null.cpp

+1-3
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,4 @@ unittest(nothing)
1919
{
2020
}
2121

22-
int main(int argc, char *argv[]) {
23-
return Test::run_and_report(argc, argv);
24-
}
22+
unittest_main()

cpp/unittest/ArduinoUnitTests.h

+16-4
Original file line numberDiff line numberDiff line change
@@ -130,14 +130,16 @@ class Test
130130
Results results = {0, 0, 0};
131131

132132
for (Test *p = sRoot; p; p = p->mNext) {
133-
TestData td = {p->name(), p->result()};
133+
p->prepare();
134134
p->mReporter = reporter;
135-
if (reporter) reporter->onTestStart(td);
135+
TestData t1 = {p->name(), p->result()};
136+
if (reporter) reporter->onTestStart(t1);
136137
p->test();
137138
if (p->mResult == RESULT_PASS) ++results.passed;
138139
if (p->mResult == RESULT_FAIL) ++results.failed;
139140
if (p->mResult == RESULT_SKIP) ++results.skipped;
140-
if (reporter) reporter->onTestEnd(td);
141+
TestData t2 = {p->name(), p->result()};
142+
if (reporter) reporter->onTestEnd(t2);
141143
}
142144

143145
return results;
@@ -154,8 +156,12 @@ class Test
154156
return results.failed + results.skipped;
155157
}
156158

159+
void prepare() {
160+
mResult = RESULT_PASS; // not None, and not fail unless we hear otherwise
161+
}
162+
157163
void test() {
158-
mResult = RESULT_PASS; // not None, and not fail unless we hear otherwise
164+
// thin wrapper. nothing to do here for now
159165
task();
160166
}
161167

@@ -210,3 +216,9 @@ class Test
210216
void task(); \
211217
} test_##name##_instance; \
212218
void test_##name ::task()
219+
220+
221+
#define unittest_main() \
222+
int main(int argc, char *argv[]) { \
223+
return Test::run_and_report(argc, argv); \
224+
}

cpp/unittest/Assertion.h

+32-13
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,30 @@
11
#pragma once
22
#include "Compare.h"
33

4-
// helper define for the operators below
5-
#define assertOp(desc, relevance1, arg1, op, op_name, relevance2, arg2) \
6-
do \
7-
{ \
8-
if (!assertion<typeof(arg1), typeof(arg2)>(__FILE__, __LINE__, \
9-
desc, \
10-
relevance1, #arg1, (arg1), \
11-
op_name, op, \
12-
relevance2, #arg2, (arg2))) \
13-
{ \
14-
return; \
15-
} \
4+
#define testBehaviorOp(die, desc, rel1, arg1, op, op_name, rel2, arg2) \
5+
do \
6+
{ \
7+
if (!assertion<typeof(arg1), typeof(arg2)>(__FILE__, __LINE__, \
8+
desc, \
9+
rel1, #arg1, (arg1), \
10+
op_name, op, \
11+
rel2, #arg2, (arg2))) \
12+
{ \
13+
if (die) return; \
14+
} \
1615
} while (0)
1716

18-
/** macro generates optional output and calls fail() followed by a return if false. */
17+
18+
19+
// helper define for the operators below
20+
#define assertOp(desc, rel1, arg1, op, op_name, rel2, arg2) \
21+
testBehaviorOp(false, desc, rel1, arg1, op, op_name, rel2, arg2)
22+
23+
#define assureOp(desc, rel1, arg1, op, op_name, rel2, arg2) \
24+
testBehaviorOp(true, desc, rel1, arg1, op, op_name, rel2, arg2)
25+
26+
27+
/** macro generates optional output and calls fail() but does not return if false. */
1928
#define assertEqual(arg1,arg2) assertOp("assertEqual","expected",arg1,compareEqual,"==","actual",arg2)
2029
#define assertNotEqual(arg1,arg2) assertOp("assertNotEqual","unwanted",arg1,compareNotEqual,"!=","actual",arg2)
2130
#define assertLess(arg1,arg2) assertOp("assertLess","lowerBound",arg1,compareLess,"<","upperBound",arg2)
@@ -25,3 +34,13 @@
2534
#define assertTrue(arg) assertEqual(arg,true)
2635
#define assertFalse(arg) assertEqual(arg,false)
2736

37+
/** macro generates optional output and calls fail() followed by a return if false. */
38+
#define assureEqual(arg1,arg2) assureOp("assureEqual","expected",arg1,compareEqual,"==","actual",arg2)
39+
#define assureNotEqual(arg1,arg2) assureOp("assureNotEqual","unwanted",arg1,compareNotEqual,"!=","actual",arg2)
40+
#define assureLess(arg1,arg2) assureOp("assureLess","lowerBound",arg1,compareLess,"<","upperBound",arg2)
41+
#define assureMore(arg1,arg2) assureOp("assureMore","upperBound",arg1,compareMore,">","lowerBound",arg2)
42+
#define assureLessOrEqual(arg1,arg2) assureOp("assureLessOrEqual","lowerBound",arg1,compareLessOrEqual,"<=","upperBound",arg2)
43+
#define assureMoreOrEqual(arg1,arg2) assureOp("assureMoreOrEqual","upperBound",arg1,compareMoreOrEqual,">=","lowerBound",arg2)
44+
#define assureTrue(arg) assertEqual(arg,true)
45+
#define assureFalse(arg) assertEqual(arg,false)
46+

exe/arduino_ci_remote.rb

+24-22
Original file line numberDiff line numberDiff line change
@@ -72,8 +72,10 @@ def assure(message, &block)
7272
# do that, set the URLs, and download the packages
7373
all_packages = all_platforms.values.map { |v| v[:package] }.uniq.reject(&:nil?)
7474
all_urls = all_packages.map { |p| config.package_url(p) }.uniq.reject(&:nil?)
75-
assure("Setting board manager URLs") do
76-
@arduino_cmd.set_pref("boardsmanager.additional.urls", all_urls.join(","))
75+
unless all_urls.empty?
76+
assure("Setting board manager URLs") do
77+
@arduino_cmd.set_pref("boardsmanager.additional.urls", all_urls.join(","))
78+
end
7779
end
7880

7981
all_packages.each do |p|
@@ -86,26 +88,6 @@ def assure(message, &block)
8688
assure("Installing aux library '#{l}'") { @arduino_cmd.install_library(l) }
8789
end
8890

89-
attempt("Setting compiler warning level") { @arduino_cmd.set_pref("compiler.warning_level", "all") }
90-
91-
library_examples.each do |example_path|
92-
ovr_config = config.from_example(example_path)
93-
ovr_config.platforms_to_build.each do |p|
94-
board = all_platforms[p][:board]
95-
assure("Switching to board for #{p} (#{board})") { @arduino_cmd.use_board(board) }
96-
example_name = File.basename(example_path)
97-
attempt("Verifying #{example_name}") do
98-
ret = @arduino_cmd.verify_sketch(example_path)
99-
unless ret
100-
puts
101-
puts "Last command: #{@arduino_cmd.last_msg}"
102-
puts @arduino_cmd.last_err
103-
end
104-
ret
105-
end
106-
end
107-
end
108-
10991
config.platforms_to_unittest.each do |p|
11092
board = all_platforms[p][:board]
11193
assure("Switching to board for #{p} (#{board})") { @arduino_cmd.use_board(board) }
@@ -129,4 +111,24 @@ def assure(message, &block)
129111
end
130112
end
131113

114+
attempt("Setting compiler warning level") { @arduino_cmd.set_pref("compiler.warning_level", "all") }
115+
116+
library_examples.each do |example_path|
117+
ovr_config = config.from_example(example_path)
118+
ovr_config.platforms_to_build.each do |p|
119+
board = all_platforms[p][:board]
120+
assure("Switching to board for #{p} (#{board})") { @arduino_cmd.use_board(board) }
121+
example_name = File.basename(example_path)
122+
attempt("Verifying #{example_name}") do
123+
ret = @arduino_cmd.verify_sketch(example_path)
124+
unless ret
125+
puts
126+
puts "Last command: #{@arduino_cmd.last_msg}"
127+
puts @arduino_cmd.last_err
128+
end
129+
ret
130+
end
131+
end
132+
end
133+
132134
terminate(true)

lib/arduino_ci/cpp_library.rb

+24-3
Original file line numberDiff line numberDiff line change
@@ -35,12 +35,28 @@ def initialize(base_dir)
3535
@last_msg = ""
3636
end
3737

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+
3852
# Get a list of all CPP source files in a directory and its subdirectories
3953
# @param some_dir [String] The directory in which to begin the search
4054
# @return [Array<String>] The paths of the found files
4155
def cpp_files_in(some_dir)
4256
real = File.realpath(some_dir)
43-
Find.find(real).select { |path| CPP_EXTENSIONS.include?(File.extname(path)) }
57+
files = Find.find(real).reject { |path| File.directory?(path) }
58+
ret = files.select { |path| CPP_EXTENSIONS.include?(File.extname(path)) }
59+
ret
4460
end
4561

4662
# CPP files that are part of the project library under test
@@ -50,6 +66,7 @@ def cpp_files
5066
cpp_files_in(@base_dir).reject do |p|
5167
next true if File.dirname(p).include?(tests_dir)
5268
next true if File.dirname(p).include?(real_tests_dir)
69+
next true if vendor_bundle?(p)
5370
end
5471
end
5572

@@ -80,8 +97,12 @@ def test_files
8097
# Find all directories in the project library that include C++ header files
8198
# @return [Array<String>]
8299
def header_dirs
83-
files = Find.find(@base_dir).select { |path| HPP_EXTENSIONS.include?(File.extname(path)) }
84-
files.map { |path| File.dirname(path) }.uniq
100+
real = File.realpath(@base_dir)
101+
all_files = Find.find(real).reject { |path| File.directory?(path) }
102+
unbundled = all_files.reject { |path| vendor_bundle?(path) }
103+
files = unbundled.select { |path| HPP_EXTENSIONS.include?(File.extname(path)) }
104+
ret = files.map { |path| File.dirname(path) }.uniq
105+
ret
85106
end
86107

87108
# wrapper for the GCC command

misc/default.yaml

+6-2
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
# Note that ci_config_spec.rb has tests for this file's contents
2+
13
packages:
24
esp8266:esp8266:
35
url: http://arduino.esp8266.com/stable/package_esp8266com_index.json
@@ -22,15 +24,15 @@ platforms:
2224
warnings:
2325
flags:
2426
zero:
25-
board: arduino:samd:zero
27+
board: arduino:samd:arduino_zero_native
2628
package: arduino:samd
2729
gcc:
2830
features:
2931
defines:
3032
warnings:
3133
flags:
3234
esp8266:
33-
board: esp8266:esp8266:huzzah
35+
board: esp8266:esp8266:huzzah:FlashSize=4M3M,CpuFrequency=80
3436
package: esp8266:esp8266
3537
gcc:
3638
features:
@@ -67,11 +69,13 @@ compile:
6769
platforms:
6870
- uno
6971
- due
72+
- zero
7073
- leonardo
7174

7275
unittest:
7376
libraries: ~
7477
platforms:
7578
- uno
7679
- due
80+
- zero
7781
- leonardo

spec/ci_config_spec.rb

+3-3
Original file line numberDiff line numberDiff line change
@@ -19,13 +19,13 @@
1919

2020
zero = default_config.platform_definition("zero")
2121
expect(zero.class).to eq(Hash)
22-
expect(zero[:board]).to eq("arduino:samd:zero")
22+
expect(zero[:board]).to eq("arduino:samd:arduino_zero_native")
2323
expect(zero[:package]).to eq("arduino:samd")
2424
expect(zero[:gcc].class).to eq(Hash)
2525

2626
expect(default_config.package_url("adafruit:avr")).to eq("https://adafruit.github.io/arduino-board-index/package_adafruit_index.json")
27-
expect(default_config.platforms_to_build).to match(["uno", "due", "leonardo"])
28-
expect(default_config.platforms_to_unittest).to match(["uno", "due", "leonardo"])
27+
expect(default_config.platforms_to_build).to match(["uno", "due", "zero", "leonardo"])
28+
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([])
3131
end

0 commit comments

Comments
 (0)