From 522448fb3885f6dfdc750c64b9391f32320a1441 Mon Sep 17 00:00:00 2001 From: Warren MacEvoy Date: Tue, 1 May 2018 11:16:36 +0545 Subject: [PATCH 01/80] add abort to tests and use in advanced example --- examples/advanced/advanced.ino | 6 +- examples/advanced/mockAdvanced.cpp | 96 +++++++++++++++++++++----- src/ArduinoUnit.h | 3 + src/ArduinoUnitUtility/ArduinoUnit.cpp | 16 +++++ 4 files changed, 101 insertions(+), 20 deletions(-) diff --git a/examples/advanced/advanced.ino b/examples/advanced/advanced.ino index 33b99df..f163a1b 100644 --- a/examples/advanced/advanced.ino +++ b/examples/advanced/advanced.ino @@ -3,7 +3,7 @@ test(simple1) { - assertTrue(true); + assertTrue(true,"message"); } test(simple2) @@ -72,6 +72,10 @@ MyTest myTest1("myTest1"); MyTest myTest2("myTest2"); MyTest myTest3("myTest3"); +testing(long) { + if (millis() > 5000) pass(); +} + void setup() { Serial.begin(9600); diff --git a/examples/advanced/mockAdvanced.cpp b/examples/advanced/mockAdvanced.cpp index a7e5076..9cee12a 100644 --- a/examples/advanced/mockAdvanced.cpp +++ b/examples/advanced/mockAdvanced.cpp @@ -3,11 +3,24 @@ // only used for "en vitro" tests (not on actual board) #include +#include +#include #include #include +#include +#include #include "ArduinoUnit.h" #include "ArduinoUnitMock.h" +#include +#include +jmp_buf sigJump; + +// break out of main loop on signal +// for (ctrl-c/INT or kill/TERM) +void sig(int num) { longjmp(sigJump, num); } + +// simple impl of random int random(int n) { static bool setup = false; if (!setup) { @@ -26,33 +39,78 @@ void loop(); CppIOStream Serial; -int main(int argc, char *argv[]) { - setup(); +struct Mock { + double timeLimit; + std::vector> selection; - // parse --exclude/-e and --include/-i commands - for (int i=1; i("exclude",argv[i])); + continue; + } + if (strcmp(argv[i],"--include")==0 || strcmp(argv[i],"-i")==0) { + ++i; + selection.push_back(std::pair("include",argv[i])); + continue; + } + if (strcmp(argv[i],"--time")==0 || strcmp(argv[i],"-t")==0) { + ++i; + timeLimit = atof(argv[i]); + continue; + } + if (strcmp(argv[i],"--")==0) { break; } + std::cerr << "unknown argument '" << argv[i] << "'" << std::endl; + exit(1); } - if (strcmp(argv[i],"--include")==0 || strcmp(argv[i],"-i")==0) { - ++i; - Test::include(argv[i]); - continue; + } + + void run() { + setup(); + + for (auto select : selection) { + if (select.first == "exclude") { + Test::exclude(select.second.c_str()); + } else if (select.first == "include") { + Test::include(select.second.c_str()); + } + } + + // loop until tests complete + while (Test::remaining() > 0) { + loop(); } - if (strcmp(argv[i],"--")==0) { break; } - std::cerr << "unknown argument '" << argv[i] << "'" << std::endl; - exit(1); } - // instead of looping forever, loop while there are active tests - while (Test::remaining() > 0) { - loop(); +}; + + +int main(int argc, const char *argv[]) { + Mock mock; + mock.args(argc,argv); + + signal(SIGINT,sig); // ctrl-c + signal(SIGTERM,sig);// kill + signal(SIGALRM,sig);// timeout + + { + // C++ "finally" clause + struct Fin { ~Fin() { Test::abort(); } } fin; + + // branch back here with signal ctrl-c/kill/alarm != 0 + if (setjmp(sigJump) == 0) { + if (mock.timeLimit > 0 && mock.timeLimit*1000000 < INT_MAX) { + ualarm(mock.timeLimit*1000000.0,0); + } + mock.run(); + } } - return 0; + + return Test::getCurrentFailed() > 0 ? 1 : 0; } + #include "advanced.ino" #endif diff --git a/src/ArduinoUnit.h b/src/ArduinoUnit.h index cbd9d71..89ecb67 100644 --- a/src/ArduinoUnit.h +++ b/src/ArduinoUnit.h @@ -535,6 +535,9 @@ void loop() { #endif return ok; } + + /** abort all testing - all unresolved tests are resolved as failed */ + public: static void abort(); }; /** Class for creating a once-only test. Test::run() on such a test diff --git a/src/ArduinoUnitUtility/ArduinoUnit.cpp b/src/ArduinoUnitUtility/ArduinoUnit.cpp index c3bd3f9..62bdc50 100644 --- a/src/ArduinoUnitUtility/ArduinoUnit.cpp +++ b/src/ArduinoUnitUtility/ArduinoUnit.cpp @@ -159,6 +159,22 @@ void Test::run() current = 0; } +void Test::abort() +{ + while (root != 0) { + current=root; + current->state = DONE_FAIL; + Test::out->print(ARDUINO_UNIT_STRING("Assertion failed: test ")); + Test::out->print(current->name); + Test::out->print(ARDUINO_UNIT_STRING(" aborted, file ArduinoUnit.cpp, line ")); + Test::out->print(__LINE__); + Test::out->println(ARDUINO_UNIT_STRING(".")); + root=root->next; + current->resolve(); + } + current=0; +} + Test::~Test() { remove(); From cfb703f0b45521128f77fdc03162b9d2054d772e Mon Sep 17 00:00:00 2001 From: Warren MacEvoy Date: Tue, 1 May 2018 11:17:12 +0545 Subject: [PATCH 02/80] edit changelog --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 96bda7b..b34e228 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -47,4 +47,4 @@ * assertNear(a,b,max[,message]) for float/double * assertRelation(args [,message [,retval]]) * assertRelativelyNear(a,b,max[,message]) for float/double - +* Test::abort() to complete all unresolved tests From 996ebc4b245eaf6d4d35d9cd0f1026cf82d5add4 Mon Sep 17 00:00:00 2001 From: Warren MacEvoy Date: Wed, 2 May 2018 15:30:19 +0545 Subject: [PATCH 03/80] better advanced example --- examples/advanced/advanced.ino | 4 ++-- examples/advanced/mockAdvanced.cpp | 3 +-- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/examples/advanced/advanced.ino b/examples/advanced/advanced.ino index f163a1b..ea5e6aa 100644 --- a/examples/advanced/advanced.ino +++ b/examples/advanced/advanced.ino @@ -73,12 +73,12 @@ MyTest myTest2("myTest2"); MyTest myTest3("myTest3"); testing(long) { - if (millis() > 5000) pass(); + if (millis() > 2000) pass(); } void setup() { - Serial.begin(9600); + Serial.begin(115200L); while(!Serial) {} // Portability for Leonardo/Micro Test::min_verbosity |= TEST_VERBOSITY_ASSERTIONS_ALL; diff --git a/examples/advanced/mockAdvanced.cpp b/examples/advanced/mockAdvanced.cpp index 9cee12a..8faffa9 100644 --- a/examples/advanced/mockAdvanced.cpp +++ b/examples/advanced/mockAdvanced.cpp @@ -83,8 +83,7 @@ struct Mock { } } -}; - +}; int main(int argc, const char *argv[]) { Mock mock; From 0e728f477dbc9265c3b03cd3baefddba28dde1bd Mon Sep 17 00:00:00 2001 From: Warren MacEvoy Date: Wed, 2 May 2018 15:33:15 +0545 Subject: [PATCH 04/80] edit guide --- guidebook.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/guidebook.md b/guidebook.md index 24f040b..0578ebf 100644 --- a/guidebook.md +++ b/guidebook.md @@ -106,18 +106,18 @@ In a test block `{ ... }` you can put code. Any code really, but some particula * `pass()` or `fail()` mark this test as passed or failed. The current test will continue to the end (which may change it's mind), but it will be resolved. This means a `testing()` environment will not loop again. -#### `assertRelation(between [,foot << note])` +#### `assertRelation(...)` -* `assertRelation(a,b [,foot << note])` or `assertTestStatus(testName [,foot << note])` +* `assertRelation(a,b [,foot << note])` or `assertTestStatus(testName [,foot << note])` - * `Relation` is one of: `Equal`, `NotEqual`, `Less`, `More`, `LessOrEqual`, `MoreOrEqual`. - * `Status` is one of: `Done`, `Pass`, `Skip`, `Fail`, `NotDone`, `NotPass`, `NotSkip`, `NotFail`. + * `Relation` is one of: `Equal`, `NotEqual`, `Less`, `More`, `LessOrEqual`, `MoreOrEqual`. + * `Status` is one of: `Done`, `Pass`, `Skip`, `Fail`, `NotDone`, `NotPass`, `NotSkip`, `NotFail`. * `testName` is some test/testing name. * The `<<` in the optional `foot << note` separates things you can print. * For float and double values, `assertNear(a,b,max [,foot << note])` tests `|b-a|<=max`. If you are working with very large or very small numbers, use `assertRelativelyNear`, which divides the error by the average magnitude, `½(|a|+|b|)`. Floating point arithmetic is almost never exact so don't expect them to be `Equal`. -* `checkTestStatus(testName)` Just true/false depending on the current status of `testName`. +* `checkTestStatus(testName)` Just true/false depending on the current status of `testName`. The asserts are replaced with code like From b5b167b3ce3fccf048c5adfa1be70d4af3024de2 Mon Sep 17 00:00:00 2001 From: Warren MacEvoy Date: Wed, 2 May 2018 15:33:44 +0545 Subject: [PATCH 05/80] edit guide --- guidebook.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/guidebook.md b/guidebook.md index 0578ebf..72dc88f 100644 --- a/guidebook.md +++ b/guidebook.md @@ -106,7 +106,7 @@ In a test block `{ ... }` you can put code. Any code really, but some particula * `pass()` or `fail()` mark this test as passed or failed. The current test will continue to the end (which may change it's mind), but it will be resolved. This means a `testing()` environment will not loop again. -#### `assertRelation(...)` +#### Assertions * `assertRelation(a,b [,foot << note])` or `assertTestStatus(testName [,foot << note])` From 3b456cb8b18f06cce27dff8a463530da5a237f8f Mon Sep 17 00:00:00 2001 From: Warren MacEvoy Date: Wed, 2 May 2018 15:38:11 +0545 Subject: [PATCH 06/80] edit guide --- guidebook.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/guidebook.md b/guidebook.md index 72dc88f..6ad74fa 100644 --- a/guidebook.md +++ b/guidebook.md @@ -108,7 +108,7 @@ In a test block `{ ... }` you can put code. Any code really, but some particula #### Assertions -* `assertRelation(a,b [,foot << note])` or `assertTestStatus(testName [,foot << note])` +* `assert__Relation__(a,b [,foot << note])` or `assertTest__Status__(testName [,foot << note])` * `Relation` is one of: `Equal`, `NotEqual`, `Less`, `More`, `LessOrEqual`, `MoreOrEqual`. * `Status` is one of: `Done`, `Pass`, `Skip`, `Fail`, `NotDone`, `NotPass`, `NotSkip`, `NotFail`. From 3aa4c9574650fce1813da339e4d64a3c35d065e0 Mon Sep 17 00:00:00 2001 From: Warren MacEvoy Date: Wed, 2 May 2018 15:41:12 +0545 Subject: [PATCH 07/80] edit guide --- guidebook.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/guidebook.md b/guidebook.md index 6ad74fa..a080e5e 100644 --- a/guidebook.md +++ b/guidebook.md @@ -108,16 +108,16 @@ In a test block `{ ... }` you can put code. Any code really, but some particula #### Assertions -* `assert__Relation__(a,b [,foot << note])` or `assertTest__Status__(testName [,foot << note])` +* `assert[Relation]`(a,b [,foot << note])` or `assertTest[Status](testName [,foot << note])` - * `Relation` is one of: `Equal`, `NotEqual`, `Less`, `More`, `LessOrEqual`, `MoreOrEqual`. - * `Status` is one of: `Done`, `Pass`, `Skip`, `Fail`, `NotDone`, `NotPass`, `NotSkip`, `NotFail`. + * `[Relation]` is one of: `Equal`, `NotEqual`, `Less`, `More`, `LessOrEqual`, `MoreOrEqual`. + * `[Status]` is one of: `Done`, `Pass`, `Skip`, `Fail`, `NotDone`, `NotPass`, `NotSkip`, `NotFail`. * `testName` is some test/testing name. * The `<<` in the optional `foot << note` separates things you can print. * For float and double values, `assertNear(a,b,max [,foot << note])` tests `|b-a|<=max`. If you are working with very large or very small numbers, use `assertRelativelyNear`, which divides the error by the average magnitude, `½(|a|+|b|)`. Floating point arithmetic is almost never exact so don't expect them to be `Equal`. -* `checkTestStatus(testName)` Just true/false depending on the current status of `testName`. +* `checkTest[Status](thingFor)` Just true/false depending on the current status of `test/ing(thingFor)`. The asserts are replaced with code like From ea9caf53346136e43907701a96b40465cdb6ba8c Mon Sep 17 00:00:00 2001 From: Warren MacEvoy Date: Wed, 2 May 2018 15:45:52 +0545 Subject: [PATCH 08/80] edit guide --- guidebook.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/guidebook.md b/guidebook.md index a080e5e..cf3a13d 100644 --- a/guidebook.md +++ b/guidebook.md @@ -108,12 +108,13 @@ In a test block `{ ... }` you can put code. Any code really, but some particula #### Assertions -* `assert[Relation]`(a,b [,foot << note])` or `assertTest[Status](testName [,foot << note])` +* `assert[Relation]`(a,b [,foot << note, [,retval]])` or `assertTest[Status](thingFor [,foot << note [,retval]])` * `[Relation]` is one of: `Equal`, `NotEqual`, `Less`, `More`, `LessOrEqual`, `MoreOrEqual`. * `[Status]` is one of: `Done`, `Pass`, `Skip`, `Fail`, `NotDone`, `NotPass`, `NotSkip`, `NotFail`. - * `testName` is some test/testing name. + * `thingFor` is some test/testing name. * The `<<` in the optional `foot << note` separates things you can print. + * The optional `retval` is to control the return value (normally nothing) when failing an assertion. * For float and double values, `assertNear(a,b,max [,foot << note])` tests `|b-a|<=max`. If you are working with very large or very small numbers, use `assertRelativelyNear`, which divides the error by the average magnitude, `½(|a|+|b|)`. Floating point arithmetic is almost never exact so don't expect them to be `Equal`. @@ -121,7 +122,7 @@ In a test block `{ ... }` you can put code. Any code really, but some particula The asserts are replaced with code like - if (not assertion) { fail(); return; } + if (not assertion) { fail(); return retval; } But also print out a status message (by default only if the assertion fails). For example: From b9d350d81b3b66d98cb7726afc0437f24f073b54 Mon Sep 17 00:00:00 2001 From: Warren MacEvoy Date: Wed, 2 May 2018 15:50:55 +0545 Subject: [PATCH 09/80] edit guide --- guidebook.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/guidebook.md b/guidebook.md index cf3a13d..e4b75cc 100644 --- a/guidebook.md +++ b/guidebook.md @@ -108,13 +108,13 @@ In a test block `{ ... }` you can put code. Any code really, but some particula #### Assertions -* `assert[Relation]`(a,b [,foot << note, [,retval]])` or `assertTest[Status](thingFor [,foot << note [,retval]])` +* `assert[Relation]`(a,b[,foot< Date: Wed, 2 May 2018 15:52:13 +0545 Subject: [PATCH 10/80] edit guide --- guidebook.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/guidebook.md b/guidebook.md index e4b75cc..854b007 100644 --- a/guidebook.md +++ b/guidebook.md @@ -108,7 +108,7 @@ In a test block `{ ... }` you can put code. Any code really, but some particula #### Assertions -* `assert[Relation]`(a,b[,foot< Date: Thu, 3 May 2018 01:33:42 +0545 Subject: [PATCH 11/80] ci init --- ci/bin/arduino | 91 ++++++++ ci/bin/arduino_exe | 47 ++++ ci/bin/au2ju | 541 +++++++++++++++++++++++++++++++++++++++++++++ ci/bin/cache_ide | 173 +++++++++++++++ ci/bin/dir | 30 +++ ci/bin/os | 74 +++++++ ci/bin/preferences | 19 ++ ci/bin/sketchbook | 24 ++ ci/bin/versions | 31 +++ 9 files changed, 1030 insertions(+) create mode 100755 ci/bin/arduino create mode 100755 ci/bin/arduino_exe create mode 100755 ci/bin/au2ju create mode 100755 ci/bin/cache_ide create mode 100755 ci/bin/dir create mode 100755 ci/bin/os create mode 100755 ci/bin/preferences create mode 100755 ci/bin/sketchbook create mode 100755 ci/bin/versions diff --git a/ci/bin/arduino b/ci/bin/arduino new file mode 100755 index 0000000..60b3883 --- /dev/null +++ b/ci/bin/arduino @@ -0,0 +1,91 @@ +#!/bin/bash + +if [ "$(type -t dir)" != "function" ] +then + . "$(cd "$(dirname "${BASH_SOURCE[0]}")"; pwd)"/dir +fi + +if [ "$(type -t os)" != "function" ] +then + . "$(cd "$(dirname "${BASH_SOURCE[0]}")"; pwd)"/os +fi + +if [ "$(type -t versions)" != "function" ] +then + . "$(cd "$(dirname "${BASH_SOURCE[0]}")"; pwd)"/versions +fi + +if [ "$(type -t preferences)" != "function" ] +then + . "$(cd "$(dirname "${BASH_SOURCE[0]}")"; pwd)"/preferences +fi + +if [ "$(type -t sketchbook)" != "function" ] +then + . "$(cd "$(dirname "${BASH_SOURCE[0]}")"; pwd)"/sketchbook +fi + +if [ "$(type -t arduino_exe)" != "function" ] +then + . "$(cd "$(dirname "${BASH_SOURCE[0]}")"; pwd)"/arduino_exe +fi + +if [ "$(type -t cache_ide)" != "function" ] +then + . "$(cd "$(dirname "${BASH_SOURCE[0]}")"; pwd)"/cache_ide +fi + +arduino() { + OS="$(os "$@")" + DIR="$(dir "$@")" + VERSIONS="$(versions "$@")" + PREFERENCES="$(preferences "$@")" + SKETCHBOOK="$(sketchbook "$@")" + + while [ $# -gt 0 ] + do + case "$1" + in + --background=*) BACKGROUND=${1#--background=}; shift;; + --*=*) shift;; + --) shift; break;; + *) break;; + esac + done + + if [ "$BACKGROUND" = "" ] + then + BACKGROUND=false + fi + + PIDS="" + OK=true + for VERSION in $VERSIONS + do + ARDUINO_EXE="$(arduino_exe --os="$OS" -- $VERSION)" + + if [ ! -x "$ARDUINO_EXE" ] + then + if [ "$BACKGROUND" = "true" ] + then + cache_ide --os="$OS" --version="$VERSION" && "$ARDUINO_EXE" --preferences-file "$PREFERENCES" --pref sketchbook.path="$SKETCHBOOK" --pref update.check=false "$@" & + PIDS="$PIDS $!" + else + cache_ide --os="$OS" --version="$VERSION" && "$ARDUINO_EXE" --preferences-file "$PREFERENCES" --pref sketchbook.path="$SKETCHBOOK" --pref update.check=false "$@" + fi + else + if [ "$BACKGROUND" = "true" ] + then + "$ARDUINO_EXE" --preferences-file "$PREFERENCES" --pref sketchbook.path="$SKETCHBOOK" --pref update.check=false "$@" & + PIDS="$PIDS $!" + else + "$ARDUINO_EXE" "$@" + fi + fi + done +} + +if [[ "${BASH_SOURCE[0]}" == "${0}" ]] +then + arduino "$@" +fi diff --git a/ci/bin/arduino_exe b/ci/bin/arduino_exe new file mode 100755 index 0000000..b1040a0 --- /dev/null +++ b/ci/bin/arduino_exe @@ -0,0 +1,47 @@ +#!/bin/bash + +if [ "$(type -t dir)" != "function" ] +then + . "$(cd "$(dirname "${BASH_SOURCE[0]}")"; pwd)"/dir +fi + +if [ "$(type -t os)" != "function" ] +then + . "$(cd "$(dirname "${BASH_SOURCE[0]}")"; pwd)"/os +fi + +if [ "$(type -t versions)" != "function" ] +then + . "$(cd "$(dirname "${BASH_SOURCE[0]}")"; pwd)"/versions +fi + +arduino_exe() { + if [ "$ARDUINO_EXE" != "" ] + then + echo "$ARDUINO_EXE" + return + fi + + OS="$(os "$@")" + DIR="$(dir "$@")" + VERSIONS="$(versions "$@")" + + for VERSION in $VERSIONS + do + if [ "$OS" = "macosx" ] + then + ARDUINO_EXE="${DIR}/cache/${VERSION}-${OS}/Arduino.app/Contents/MacOS/Arduino" + elif [ "$OS" = "windows" ] + then + ARDUINO_EXE="${DIR}/cache/${VERSION}-${OS}/arduino-${VERSION}/arduino.exe" + else + ARDUINO_EXE="${DIR}/cache/${VERSION}-${OS}/arduino-${VERSION}/arduino" + fi + echo "$ARDUINO_EXE" + done +} + +if [[ "${BASH_SOURCE[0]}" == "${0}" ]] +then + arduino_exe "$@" +fi diff --git a/ci/bin/au2ju b/ci/bin/au2ju new file mode 100755 index 0000000..5f9d640 --- /dev/null +++ b/ci/bin/au2ju @@ -0,0 +1,541 @@ +#!/usr/bin/env python + +import os +import re +import sys +import glob +import threading +import xml.etree.cElementTree as xet + +class Test: + _re = re.compile('.*Test (.*) (skipped|passed|failed)\.') + + def __init__(self, result, assertions,stdout,stderr): + if result != None: + self.name = result.group(1) + self.state = result.group(2) + self.stdout = stdout + self.stderr = stderr + else: + self.name = "unknown" + self.state = "unknown" + self.stdout = stdout + self.stderr = stderr + + if assertions != None: + self.assertions = assertions + else: + self.assertions=[] + + def __str__(self): + return "test(name='"+str(self.name)+"',state='"+str(self.state)+"',assertions="+str(self.assertions) + ",stdout=" + str(self.stdout) + ",stderr=" + str(self.stdout)+")" + + def __repr__(self): + return self.__str__() + + +class Assert: + _re = re.compile('.*Assertion (passed|failed): (.*)\.') + _details = re.compile('(.*), file (.*), line ([0-9]+) *(\[(.*)\])?') + + def __init__(self,result): + if result == None: + self.state = None + self.message = None + self.footnote = None + self.file = None + self.line = None + else: + self.state = result.group(1) + details = Assert._details.match(result.group(2)) + if details != None: + self.message = details.group(1) + self.file = details.group(2) + self.line = int(details.group(3)) + if details.group(5) != None: + self.footnote = details.group(5) + else: + self.footnote = None + else: + self.message = result.group(2) + self.file = None + self.line = None + self.footnote = None + + def __str__(self): + return "assert(state='"+str(self.state)+"',message='"+str(self.message)+"',file='"+str(self.file)+"',line="+str(self.line)+",footnote='" + self.footnote + "')" + + def __repr__(self): + return self.__str__() + +class Summary: + _re = re.compile('.*Test summary: (.*) passed, (.*) failed, and (.*) skipped, out of (.*) test\(s\)\.') + + def __init__(self,result): + if result != None: + self.passed = int(result.group(1)) + self.failed = int(result.group(2)) + self.skipped = int(result.group(3)) + self.count = int(result.group(4)) + else: + self.passed = 0 + self.failed = 0 + self.skipped = 0 + self.count = 0 + + def __str__(self): + return 'summary(passed=' + str(self.passed) + ',failed='+str(self.failed)+',skipped='+str(self.skipped)+',count='+str(self.count)+')' + + def __repr__(self): + return self.__str__() + + +class TestSet: + def __init__(self,result,tests,assertions,stdout,stderr): + self.summary = Summary(result) + if tests != None: + self.tests = tests + else: + self.tests = [] + if len(assertions) > 0: + self.tests.append(Test(None,assertions,stdout,stderr)) + + def __str__(self): + return 'testset(tests='+str(self.tests)+',summary='+str(self.summary)+')' + def __repr__(self): + return self.__str__() + +class Processor: + def __init__(self,parser,stream,isStderr): + self.parser = parser + self.stream = stream + self.isStderr=isStderr + + def run(self): + for line in self.stream: + line=line.rstrip() + self.parser.parseLine(line,self.isStderr) + +class Parser: + def __init__(self): + self.reTest = re.compile('.*Test (.*) (skipped|passed|failed)\.') + self.testSets = [] + self.tests = [] + self.assertions = [] + self.stdout = [] + self.stderr = [] + + def end(self): + if len(self.tests) != 0 or len(self.assertions) != 0: + self.testSets.append(TestSet(None,self.tests,self.assertions,self.stdout,self.stderr)) + self.tests=[] + self.assertions=[] + self.stdout = [] + self.stderr = [] + + def parseLine(self,line,stderr=False): + if line == None: + self.end() + return + if (stderr == False): + self.stdout.append(line) + else: + self.stderr.append(line) + + result=Assert._re.match(line) + if result: + self.assertions.append(Assert(result)) + result=Test._re.match(line) + if result: + self.tests.append(Test(result,self.assertions,self.stdout,self.stderr)) + self.assertions=[] + self.stdout=[] + self.stderr=[] + result=Summary._re.match(line) + if result: + self.testSets.append(TestSet(result,self.tests,self.assertions,self.stdout,self.stderr)) + self.tests=[] + self.assertions=[] + self.stdout = [] + self.stderr = [] + + def process(self,inFromStdout=sys.stdin,inFromStderr=None): + self.testSet = [] + self.assertions = [] + self.tests = [] + self.stdin = [] + self.stderr = [] + + workers = [Processor(self,inFromStdout,False)] + if inFromStderr != None: + worders.append(Processor(self,inFromStderr,True)) + threads = [threading.Thread(target=workers[i].run) for i in range(len(workers))] + for thread in threads: + thread.start() + for thread in threads: + thread.join() + self.end() + +class Summary: + _re = re.compile('.*Test summary: (.*) passed, (.*) failed, and (.*) skipped, out of (.*) test\(s\)\.') + + def __init__(self,result): + if result != None: + self.passed = int(result.group(1)) + self.failed = int(result.group(2)) + self.skipped = int(result.group(3)) + self.count = int(result.group(4)) + else: + self.passed = 0 + self.failed = 0 + self.skipped = 0 + self.count = 0 + + def __str__(self): + return 'summary(passed=' + str(self.passed) + ',failed='+str(self.failed)+',skipped='+str(self.skipped)+',count='+str(self.count)+')' + + def __repr__(self): + return self.__str__() + + +class TestSet: + def __init__(self,result,tests,assertions,stdout,stderr): + self.summary = Summary(result) + if tests != None: + self.tests = tests + else: + self.tests = [] + if len(assertions) > 0: + self.tests.append(Test(None,assertions,stdout,stderr)) + + def __str__(self): + return 'testset(tests='+str(self.tests)+',summary='+str(self.summary)+')' + def __repr__(self): + return self.__str__() + +class Processor: + def __init__(self,parser,stream,isStderr): + self.parser = parser + self.stream = stream + self.isStderr=isStderr + + def run(self): + for line in self.stream: + line=line.rstrip() + self.parser.parseLine(line,self.isStderr) + +class Parser: + def __init__(self): + self.reTest = re.compile('.*Test (.*) (skipped|passed|failed)\.') + self.testSets = [] + self.tests = [] + self.assertions = [] + self.stdout = [] + self.stderr = [] + + def end(self): + if len(self.tests) != 0 or len(self.assertions) != 0: + self.testSets.append(TestSet(None,self.tests,self.assertions,self.stdout,self.stderr)) + self.tests=[] + self.assertions=[] + self.stdout = [] + self.stderr = [] + + def parseLine(self,line,stderr=False): + if line == None: + self.end() + return + if (stderr == False): + self.stdout.append(line) + else: + self.stderr.append(line) + + result=Assert._re.match(line) + if result: + self.assertions.append(Assert(result)) + result=Test._re.match(line) + if result: + self.tests.append(Test(result,self.assertions,self.stdout,self.stderr)) + self.assertions=[] + self.stdout=[] + self.stderr=[] + result=Summary._re.match(line) + if result: + self.testSets.append(TestSet(result,self.tests,self.assertions,self.stdout,self.stderr)) + self.tests=[] + self.assertions=[] + self.stdout = [] + self.stderr = [] + + def process(self,inFromStdout=sys.stdin,inFromStderr=None): + self.testSet = [] + self.assertions = [] + self.tests = [] + self.stdin = [] + self.stderr = [] + + workers = [Processor(self,inFromStdout,False)] + if inFromStderr != None: + worders.append(Processor(self,inFromStderr,True)) + threads = [threading.Thread(target=workers[i].run) for i in range(len(workers))] + for thread in threads: + thread.start() + for thread in threads: + thread.join() + self.end() + +class Summary: + _re = re.compile('.*Test summary: (.*) passed, (.*) failed, and (.*) skipped, out of (.*) test\(s\)\.') + + def __init__(self,result): + if result != None: + self.passed = int(result.group(1)) + self.failed = int(result.group(2)) + self.skipped = int(result.group(3)) + self.count = int(result.group(4)) + else: + self.passed = 0 + self.failed = 0 + self.skipped = 0 + self.count = 0 + + def __str__(self): + return 'summary(passed=' + str(self.passed) + ',failed='+str(self.failed)+',skipped='+str(self.skipped)+',count='+str(self.count)+')' + + def __repr__(self): + return self.__str__() + + +class TestSet: + def __init__(self,result,tests,assertions,stdout,stderr): + self.summary = Summary(result) + if tests != None: + self.tests = tests + else: + self.tests = [] + if len(assertions) > 0: + self.tests.append(Test(None,assertions,stdout,stderr)) + + def __str__(self): + return 'testset(tests='+str(self.tests)+',summary='+str(self.summary)+')' + def __repr__(self): + return self.__str__() + +class Processor: + def __init__(self,parser,stream,isStderr): + self.parser = parser + self.stream = stream + self.isStderr=isStderr + + def run(self): + for line in self.stream: + line=line.rstrip() + self.parser.parseLine(line,self.isStderr) + +class Parser: + def __init__(self): + self.reTest = re.compile('.*Test (.*) (skipped|passed|failed)\.') + self.testSets = [] + self.tests = [] + self.assertions = [] + self.stdout = [] + self.stderr = [] + + def end(self): + if len(self.tests) != 0 or len(self.assertions) != 0: + self.testSets.append(TestSet(None,self.tests,self.assertions,self.stdout,self.stderr)) + self.tests=[] + self.assertions=[] + self.stdout = [] + self.stderr = [] + + def parseLine(self,line,stderr=False): + if line == None: + self.end() + return + if (stderr == False): + self.stdout.append(line) + else: + self.stderr.append(line) + + result=Assert._re.match(line) + if result: + self.assertions.append(Assert(result)) + result=Test._re.match(line) + if result: + self.tests.append(Test(result,self.assertions,self.stdout,self.stderr)) + self.assertions=[] + self.stdout=[] + self.stderr=[] + result=Summary._re.match(line) + if result: + self.testSets.append(TestSet(result,self.tests,self.assertions,self.stdout,self.stderr)) + self.tests=[] + self.assertions=[] + self.stdout = [] + self.stderr = [] + + def process(self,inFromStdout=sys.stdin,inFromStderr=None): + self.testSet = [] + self.assertions = [] + self.tests = [] + self.stdin = [] + self.stderr = [] + + workers = [Processor(self,inFromStdout,False)] + if inFromStderr != None: + worders.append(Processor(self,inFromStderr,True)) + threads = [threading.Thread(target=workers[i].run) for i in range(len(workers))] + for thread in threads: + thread.start() + for thread in threads: + thread.join() + self.end() + +class JUnit4: + def __init__(self): + pass + + def indent(self, elem, level=0): + i = "\n" + level*" " + j = "\n" + (level-1)*" " + + if len(elem): + if not elem.text or not elem.text.strip(): + elem.text = i + " " + if not elem.tail or not elem.tail.strip(): + elem.tail = i + for subelem in elem: + self.indent(subelem, level+1) + if not elem.tail or not elem.tail.strip(): + elem.tail = j + else: + if level and (not elem.tail or not elem.tail.strip()): + elem.tail = j + return elem + + def printTestSets(self,testSets,prettyPrint=True): + doc = self.addTestSets(testSets) + xml = xet.ElementTree(doc) + if prettyPrint: + self.indent(doc) + xml.write(sys.stdout, xml_declaration=True, encoding='utf-8') + + def addTestSets(self,testSets,parent=None): + ans = None + if parent != None: + ans =xet.SubElement(parent,"testsuites") + else: + ans =xet.Element("testsuites") + + for testSet in testSets: + self.addTestSet(testSet,ans) + return ans + + def addTestSet(self,testSet,parent=None): + ans = None + if parent != None: + ans = xet.SubElement(parent,"testsuite") + else: + ans = xet.Element("testsuite") + + ans.set("tests",str(len(testSet.tests))) + + for test in testSet.tests: + self.addTest(test,ans) + + return ans + + def addTest(self,test,parent=None): + ans = None + if parent != None: + ans = xet.SubElement(parent,"testcase") + else: + ans = xet.Element("testcase") + + ans.set("name",test.name) + + if test.state == 'skipped': + xet.SubElement(ans,"skipped") + return + + for assertion in test.assertions: + self.addAssertion(assertion,ans) + + self.addStdout(test.stdout,ans) + self.addStderr(test.stderr,ans) + + def addStdout(Self,stdout,parent=None): + if (len(stdout) == 0): + return None + ans = None + if parent != None: + ans = xet.SubElement(parent,"stdout") + else: + ans = xet.Element("stdout") + + ans.text = "\n" + "\n".join(stdout) + "\n" + return ans + + def addStderr(Self,stderr,parent=None): + if (len(stderr) == 0): + return None + ans = None + if parent != None: + ans = xet.SubElement(parent,"stderr") + else: + ans = xet.Element("stderr") + + ans.text = "\n" + "\n".join(stderr) + return ans + + def addAssertion(self,assertion,parent=None): + ans = None + if (assertion.state == 'passed'): + return None + + if parent != None: + ans = xet.SubElement(parent,"failure") + else: + ans = xet.Element("failure") + + message = assertion.file + ":" + str(assertion.line) + " " + assertion.message + ans.set("message",message) + + text = ["\n"] + + if assertion.file != None: + text.append("File \"" + assertion.file + "\"") + else: + text.append("File None") + + if assertion.line != None: + text.append(", line " + str(assertion.line)) + else: + text.append(", line unknown") + if parent != None: + text.append(", in " + parent.get("name") + "\n") + else: + text.append(", in unknown\n") + text.append(" Assertion failed: " + assertion.message) + if assertion.file != None: + text.append(", file " + assertion.file) + if assertion.line != None: + text.append(", line " + str(assertion.line)) + if (assertion.footnote != None): + text.append(" [" + assertion.footnote + "]") + text.append(".") + text.append("\n") + + ans.text = "".join(text) + + return ans + +def main(): + p = Parser() + p.process() + junit4=JUnit4() + junit4.printTestSets(p.testSets) + +if __name__ == '__main__': + main() diff --git a/ci/bin/cache_ide b/ci/bin/cache_ide new file mode 100755 index 0000000..2a25602 --- /dev/null +++ b/ci/bin/cache_ide @@ -0,0 +1,173 @@ +#!/bin/bash -x + +if [ "$(type -t os)" != "function" ] +then + . "$(cd "$(dirname "${BASH_SOURCE[0]}")"; pwd)"/os +fi + +if [ "$(type -t dir)" != "function" ] +then + . "$(cd "$(dirname "${BASH_SOURCE[0]}")"; pwd)"/dir +fi + +if [ "$(type -t versions)" != "function" ] +then + . "$(cd "$(dirname "${BASH_SOURCE[0]}")"; pwd)"/versions +fi + +cache_ide() { + OS="$(os "$@")" + DIR="$(dir "$@")" + VERSIONS="$(versions "$@")" + + while [ $# -gt 0 ] + do + case "$1" + in + --extension=*) EXTENSION=${1#--extension=}; shift;; + --tries=*) TRIES=${1#--tries=}; shift;; + --reload=*) RELOAD=${1#--reload=}; shift;; + --timeout=*) TIMEOUT=${1#--timeout=}; shift;; + --*=*) shift;; + --) shift; break;; + *) break;; + esac + done + + CACHE="${DIR}/cache" + if [ ! -d "$CACHE" ] + then + mkdir -p "$CACHE" + fi + + PORTABLE="${DIR}/portable" + if [ ! -d "$PORTABLE" ] + then + mkdir -p "$PORTABLE" + fi + + if [ "$EXTENSION" = "" ] + then + if [ "$OS" = "macosx" -o "$OS" = "windows" ] + then + EXTENSION="zip" + elif [ "${OS#linux}" != "$OS" ] + then + EXTENSION="tar.xz" + else + echo "Unsupported architecture." + exit 1 + fi + fi + + if [ "$TRIES" = "" ] + then + TRIES=3 + fi + + if [ "$RELOAD" = "" ] + then + RELOAD=false + fi + + if [ "$TIMEOUT" = "" ] + then + TIMEOUT=10 + fi + + for VERSION in $VERSIONS + do + ARCHIVE="arduino-${VERSION}-${OS}.${EXTENSION}" + CHECKSUM="arduino-${VERSION}.sha512sum.txt" + + OK=false + for TRY in $(seq $TRIES) + do + if [ -r "${CACHE}/${CHECKSUM}" ] + then + if grep -q "${ARCHIVE}" "${CACHE}/${CHECKSUM}" + then + OK=true + break + fi + fi + curl --connect-timeout "$TIMEOUT" -o "${CACHE}/${CHECKSUM}" "https://downloads.arduino.cc/${CHECKSUM}" + done + if [ "$OK" != "true" ] + then + echo "Could not download checksum ${CHECKSUM}" + /bin/rm -rf "${CACHE}/${CHECKSUM}" + continue + fi + + grep "${ARCHIVE}" "${CACHE}/${CHECKSUM}" > "${CACHE}/${ARCHIVE}.sha512sum.txt" + + OK=false + for TRY in $(seq $TRIES) + do + if [ -r "${CACHE}/${ARCHIVE}" ] + then + if cd "$CACHE" && shasum -a512 -c "${ARCHIVE}.sha512sum.txt" > /dev/null + then + OK=true + break + fi + fi + /bin/rm -rf "${CACHE}/${ARCHIVE}" + curl --connect-timeout "$TIMEOUT" -o "${CACHE}/${ARCHIVE}" "https://downloads.arduino.cc/${ARCHIVE}" + done + + if [ "$OK" != "true" ] + then + echo "Could not download archive ${ARCHIVE}" + /bin/rm -rf "${CACHE}/${ARCHIVE}" + /bin/rm -rf "${CACHE}/${VERSION}-${OS}" + continue + fi + + if [ "${RELOAD}" = "true" ] + then + /bin/rm -rf "${CACHE}/${VERSION}-${OS}" + fi + + if [ "${EXTENSION}" = "zip" ] + then + if [ ! -d "${CACHE}/${VERSION}-${OS}" ] + then + (cd "${CACHE}" && mkdir -p "${VERSION}-${OS}" && unzip -d "${VERSION}-${OS}" -a -o "${ARCHIVE}" > /dev/null) + if [ "${OS}" = "macosx" ] + then + (cd "${CACHE}/${VERSION}-${OS}/Arduino.app/Contents/Java"; ln -s ../../../../../portable portable) + else + (cd "${CACHE}/${VERSION}-${OS}/arduino-${VERSION}"; ln -s ../../../portable portable) + fi + fi + else + if [ ! -d "${CACHE}/${VERSION}-${OS}" ] + then + (cd "${CACHE}" && mkdir -p "${VERSION}-${OS}" && tar -C "${VERSION}-${OS}" -xf "${ARCHIVE}") + (cd "${CACHE}/${VERSION}-${OS}/arduino-${VERSION}"; ln -s ../../../portable portable) + fi + fi + done + + OK=true + for VERSION in $VERSIONS + do + if [ ! -d "${CACHE}/${VERSION}-${OS}" ] + then + OK=false + break + fi + done + + if [ "$OK" = "false" ] + then + exit 1 + fi +} + +if [[ "${BASH_SOURCE[0]}" == "${0}" ]] +then + cache_ide "$@" +fi diff --git a/ci/bin/dir b/ci/bin/dir new file mode 100755 index 0000000..c87dcfd --- /dev/null +++ b/ci/bin/dir @@ -0,0 +1,30 @@ +#!/bin/bash + +dir() { + while [ $# -gt 0 ] + do + case "$1" + in + --dir=*) DIR=${1#--dir=}; shift;; + --*=*) shift;; + --) shift; break;; + *) break;; + esac + done + + if [ "$DIR" = "" ] + then + DIR="$HOME/.arduino" + fi + + if [ ! -d "${DIR}" ] + then + mkdir -p "${DIR}" + fi + echo "${DIR}" +} + +if [[ "${BASH_SOURCE[0]}" == "${0}" ]] +then + dir "$@" +fi diff --git a/ci/bin/os b/ci/bin/os new file mode 100755 index 0000000..71356f9 --- /dev/null +++ b/ci/bin/os @@ -0,0 +1,74 @@ +#!/bin/bash + +os() { + while [ $# -gt 0 ] + do + case "$1" + in + --os=*) OS=${1#--os=}; shift;; + --*=*) shift;; + --) shift; break;; + *) break;; + esac + done + + if [ "$OS" != "" ] + then + echo "$OS" + return + fi + + if [ "$(uname)" = "Darwin" ] + then + echo "macosx" + return + fi + + # Windows Subsystem for Linux + if [ -f "/proc/version" ] + then + if grep -q Windows /proc/version + then + echo "windows" + return + fi + fi + + # cygwin + if uname -s | grep -q -i "cygwin" + then + echo "windows" + return + fi + + # mingw + if uname -s | grep -q -i "mingw" + then + echo "windows" + return + fi + + if [ "$(uname)" = "Linux" ] + then + if uname -m | grep -q arm + then + echo "linuxarm" + return + elif lscpu | grep "CPU op-modes(s)" | grep -q "64-bit" + then + echo "linux64" + return + else + echo "linux32" + return + fi + fi + + echo "Unsupported operating system." + exit 1 +} + +if [[ "${BASH_SOURCE[0]}" == "${0}" ]] +then + os "$@" +fi diff --git a/ci/bin/preferences b/ci/bin/preferences new file mode 100755 index 0000000..22862f9 --- /dev/null +++ b/ci/bin/preferences @@ -0,0 +1,19 @@ +#!/bin/bash + +if [ "$(type -t dir)" != "function" ] +then + . "$(cd "$(dirname "${BASH_SOURCE[0]}")"; pwd)"/dir +fi + +preferences() { + if [ "$PREFERENCES" == "" ] + then + PREFERENCES="$(dir "$@")/portable/preferences.txt" + fi + echo "$PREFERENCES" +} + +if [[ "${BASH_SOURCE[0]}" == "${0}" ]] +then + preferences "$@" +fi diff --git a/ci/bin/sketchbook b/ci/bin/sketchbook new file mode 100755 index 0000000..374c250 --- /dev/null +++ b/ci/bin/sketchbook @@ -0,0 +1,24 @@ +#!/bin/bash + +if [ "$(type -t dir)" != "function" ] +then + . "$(cd "$(dirname "${BASH_SOURCE[0]}")"; pwd)"/dir +fi + +sketchbook() { + if [ "$SKETCHBOOK" == "" ] + then + SKETCHBOOK="$(dir "$@")/portable/sketchbook" + fi + + if [ ! -d "$SKETCHBOOK" ] + then + mkdir -p "$SKETCHBOOK" + fi + echo "$SKETCHBOOK" +} + +if [[ "${BASH_SOURCE[0]}" == "${0}" ]] +then + sketchbook "$@" +fi diff --git a/ci/bin/versions b/ci/bin/versions new file mode 100755 index 0000000..3690421 --- /dev/null +++ b/ci/bin/versions @@ -0,0 +1,31 @@ +#!/bin/bash + +versions() { + if [ "$VERSIONS" != "" ] + then + echo $VERSIONS + return + fi + + while [ $# -gt 0 ] + do + case "$1" + in + --version=*) VERSIONS="$VERSIONS ${1#--version=}"; shift;; + --*=*) shift;; + --) shift; break;; + *) break;; + esac + done + + if [ "$VERSIONS" = "" ] + then + VERSIONS="1.8.5" + fi + echo $VERSIONS +} + +if [[ "${BASH_SOURCE[0]}" == "${0}" ]] +then + versions "$@" +fi From fa4a7915282d3485931d77fac1d1876361c6a0b4 Mon Sep 17 00:00:00 2001 From: Warren MacEvoy Date: Thu, 3 May 2018 09:00:12 +0545 Subject: [PATCH 12/80] grammer --- examples/advanced/Makefile | 7 ------- examples/continuous/continuous.ino | 28 ---------------------------- guidebook.md | 6 +++--- 3 files changed, 3 insertions(+), 38 deletions(-) delete mode 100644 examples/advanced/Makefile delete mode 100644 examples/continuous/continuous.ino diff --git a/examples/advanced/Makefile b/examples/advanced/Makefile deleted file mode 100644 index a792627..0000000 --- a/examples/advanced/Makefile +++ /dev/null @@ -1,7 +0,0 @@ -ARDUINO_UNIT_SRC_DIR=../../src -ARDUINO_UNIT_SRC=${ARDUINO_UNIT_SRC_DIR}/ArduinoUnitUtility/ArduinoUnitString.cpp ${ARDUINO_UNIT_SRC_DIR}/ArduinoUnitUtility/ArduinoUnit.cpp - -ARDUINO_UNIT_MOCK=${ARDUINO_UNIT_SRC_DIR}/ArduinoUnitUtility/ArduinoUnitMockTime.cpp ${ARDUINO_UNIT_SRC_DIR}/ArduinoUnitUtility/ArduinoUnitMockWString.cpp ${ARDUINO_UNIT_SRC_DIR}/ArduinoUnitUtility/ArduinoUnitMockPrint.cpp ${ARDUINO_UNIT_SRC_DIR}/ArduinoUnitUtility/ArduinoUnitMockPrintable.cpp ${ARDUINO_UNIT_SRC_DIR}/ArduinoUnitUtility/ArduinoUnitMockStream.cpp - -mockAdvanced : mockAdvanced.cpp advanced.ino ${ARDUINO_UNIT_SRC} - g++ -isystem ${ARDUINO_UNIT_SRC_DIR} -std=gnu++11 -o $@ $< ${ARDUINO_UNIT_SRC} ${ARDUINO_UNIT_MOCK} diff --git a/examples/continuous/continuous.ino b/examples/continuous/continuous.ino deleted file mode 100644 index 1a0f5f0..0000000 --- a/examples/continuous/continuous.ino +++ /dev/null @@ -1,28 +0,0 @@ -#line 2 "continuous.ino" -#include - -// test-once test named "once" -test(once) -{ - int x=1; - assertLessOrEqual(x,1); -} - -// test-until-skip-pass-or-fail test named "continuous" -testing(continuous) -{ - unsigned long t = millis(); - assertLessOrEqual(t,100); - if (t >= 100) pass(); -} - -void setup() -{ - Serial.begin(9600); - while(!Serial) {} // Portability for Leonardo/Micro -} - -void loop() -{ - Test::run(); -} diff --git a/guidebook.md b/guidebook.md index 3a288bb..907c29e 100644 --- a/guidebook.md +++ b/guidebook.md @@ -157,7 +157,7 @@ Tests that are completed are removed from the list (this is not a dynamic memory Pejoratives aside, this idea is really useful and we are all idiots most of the time (there are infinitely more things we don't know than we know). It is important to have a thumbs up/thumbs down status so we can at least decide to look more closely. If you or your manager puckers when they see your code, replace `idiot` with `status`. We know what you mean: "Toilet" vs. "Bathroom", it's all the same business. -So lets imagine we are building a controller for a food cart. I'm not going to bother with the implementation, just the tests. By default if a test completes it is a `pass()`. You can put a fail or some simple assertions to see how the output changes. +So let us imagine we are building a controller for a food cart. I'm not going to bother with the implementation, just the tests. By default if a test completes it is a `pass()`. You can put a fail or some simple assertions to see how the output changes. ```c++ #include @@ -451,7 +451,7 @@ void spaceCritical() { } ``` -Note that there is no gaurantee the space can be allocated in one block. The free space list may be fragmented, so you should check the outcome of any dynamic allocation to attempt. Running out of memory is usually a critical failure, so add to your sanity checks: +Note that there is no guarantee the space can be allocated in one block. The free space list may be fragmented, so you should check the outcome of any dynamic allocation to attempt. Running out of memory is usually a critical failure, so add to your sanity checks: ```c++ bool criticalError = false; @@ -572,7 +572,7 @@ Eventually you will be turning your hot dog cart into a taco stand. Trust me ev ### A Journey of 1000 Miles Begins With A Map -Planning every detail ahead of time is a waste of effort. So is just charging into the woods. In software you build the map with tests. If you don't know how to make a thing work, try writing the tests that should pass when it does work. The tests will help solidify what the Thing really is, including a lot about what it does not have to be. +Planning every detail ahead of time is a waste of effort. So is just charging into the woods. In software, you build the map with tests. If you don't know how to make a thing work, try writing the tests that should pass when it does work. The tests will help solidify what the Thing really is, including a lot about what it does not have to be. ### Your Momma Writes Better Tests Than You From 8211a0a07d99b2a97d10a5da20bcab1e3e11d0bf Mon Sep 17 00:00:00 2001 From: Warren MacEvoy Date: Thu, 3 May 2018 12:03:35 +0545 Subject: [PATCH 13/80] vitro example --- examples/vitro/README.md | 37 +++ examples/vitro/au2ju | 541 +++++++++++++++++++++++++++++++++++ examples/vitro/compile | 83 ++++++ examples/vitro/mockVitro.cpp | 42 +++ examples/vitro/test | 44 +++ examples/vitro/vitro.ino | 25 ++ 6 files changed, 772 insertions(+) create mode 100644 examples/vitro/README.md create mode 100755 examples/vitro/au2ju create mode 100755 examples/vitro/compile create mode 100644 examples/vitro/mockVitro.cpp create mode 100755 examples/vitro/test create mode 100644 examples/vitro/vitro.ino diff --git a/examples/vitro/README.md b/examples/vitro/README.md new file mode 100644 index 0000000..15d43dd --- /dev/null +++ b/examples/vitro/README.md @@ -0,0 +1,37 @@ +# En Vitro (Advanced) + +ArduinoUnit can be used to compile sketches "en vitro" on the development system. + +# Who + +You need to be comfortable with compiling using the g++ compiler from the command line, and modifying bash scripts. + +# Why + +If a unit can tested outside of the embedded environment, you can find problems more easily because of the tools available. + +# How + +1. Write a sketch with tests (like `vitro.ino`) +1. Write a `mockVitro.cpp` (any name(s) will do) that creates a "mock" arduino environment where the sketch can run on the dev system + 1. ArduinoUnit provides limited mocking (just enough for ArduinoUnit to work). + 1. Stream -- CppStream(in=cin,out=cout) can be used to make a mock Serial device. + 1. Print + 1. String + 1. F() and __FlashStringHelper + 1. micros and millis + 1. You will probabaly want to mock more things. + 1. `mockVitro.cpp` is a getting started version: + 1. A mock `Serial` connected to stdin and stdout + 1. A `main()` that calls `setup()` then `loop()`s while tests are not done. +1. Compile everything using g++ (`./compile`) +1. Run the program locally (`./vitro`). + +# Continuous Testing + +There are a lot of contiuous testing frameworks. There is an au2ju script converts the ArduinoUnit-style into JUnit style, which is a popular (although unreadable by humans) format for these tools. The `test` script runs the compiled executable and creates such a file. + +```bash +./compile +./test # creates vitro.log & vitro.xml +``` diff --git a/examples/vitro/au2ju b/examples/vitro/au2ju new file mode 100755 index 0000000..5f9d640 --- /dev/null +++ b/examples/vitro/au2ju @@ -0,0 +1,541 @@ +#!/usr/bin/env python + +import os +import re +import sys +import glob +import threading +import xml.etree.cElementTree as xet + +class Test: + _re = re.compile('.*Test (.*) (skipped|passed|failed)\.') + + def __init__(self, result, assertions,stdout,stderr): + if result != None: + self.name = result.group(1) + self.state = result.group(2) + self.stdout = stdout + self.stderr = stderr + else: + self.name = "unknown" + self.state = "unknown" + self.stdout = stdout + self.stderr = stderr + + if assertions != None: + self.assertions = assertions + else: + self.assertions=[] + + def __str__(self): + return "test(name='"+str(self.name)+"',state='"+str(self.state)+"',assertions="+str(self.assertions) + ",stdout=" + str(self.stdout) + ",stderr=" + str(self.stdout)+")" + + def __repr__(self): + return self.__str__() + + +class Assert: + _re = re.compile('.*Assertion (passed|failed): (.*)\.') + _details = re.compile('(.*), file (.*), line ([0-9]+) *(\[(.*)\])?') + + def __init__(self,result): + if result == None: + self.state = None + self.message = None + self.footnote = None + self.file = None + self.line = None + else: + self.state = result.group(1) + details = Assert._details.match(result.group(2)) + if details != None: + self.message = details.group(1) + self.file = details.group(2) + self.line = int(details.group(3)) + if details.group(5) != None: + self.footnote = details.group(5) + else: + self.footnote = None + else: + self.message = result.group(2) + self.file = None + self.line = None + self.footnote = None + + def __str__(self): + return "assert(state='"+str(self.state)+"',message='"+str(self.message)+"',file='"+str(self.file)+"',line="+str(self.line)+",footnote='" + self.footnote + "')" + + def __repr__(self): + return self.__str__() + +class Summary: + _re = re.compile('.*Test summary: (.*) passed, (.*) failed, and (.*) skipped, out of (.*) test\(s\)\.') + + def __init__(self,result): + if result != None: + self.passed = int(result.group(1)) + self.failed = int(result.group(2)) + self.skipped = int(result.group(3)) + self.count = int(result.group(4)) + else: + self.passed = 0 + self.failed = 0 + self.skipped = 0 + self.count = 0 + + def __str__(self): + return 'summary(passed=' + str(self.passed) + ',failed='+str(self.failed)+',skipped='+str(self.skipped)+',count='+str(self.count)+')' + + def __repr__(self): + return self.__str__() + + +class TestSet: + def __init__(self,result,tests,assertions,stdout,stderr): + self.summary = Summary(result) + if tests != None: + self.tests = tests + else: + self.tests = [] + if len(assertions) > 0: + self.tests.append(Test(None,assertions,stdout,stderr)) + + def __str__(self): + return 'testset(tests='+str(self.tests)+',summary='+str(self.summary)+')' + def __repr__(self): + return self.__str__() + +class Processor: + def __init__(self,parser,stream,isStderr): + self.parser = parser + self.stream = stream + self.isStderr=isStderr + + def run(self): + for line in self.stream: + line=line.rstrip() + self.parser.parseLine(line,self.isStderr) + +class Parser: + def __init__(self): + self.reTest = re.compile('.*Test (.*) (skipped|passed|failed)\.') + self.testSets = [] + self.tests = [] + self.assertions = [] + self.stdout = [] + self.stderr = [] + + def end(self): + if len(self.tests) != 0 or len(self.assertions) != 0: + self.testSets.append(TestSet(None,self.tests,self.assertions,self.stdout,self.stderr)) + self.tests=[] + self.assertions=[] + self.stdout = [] + self.stderr = [] + + def parseLine(self,line,stderr=False): + if line == None: + self.end() + return + if (stderr == False): + self.stdout.append(line) + else: + self.stderr.append(line) + + result=Assert._re.match(line) + if result: + self.assertions.append(Assert(result)) + result=Test._re.match(line) + if result: + self.tests.append(Test(result,self.assertions,self.stdout,self.stderr)) + self.assertions=[] + self.stdout=[] + self.stderr=[] + result=Summary._re.match(line) + if result: + self.testSets.append(TestSet(result,self.tests,self.assertions,self.stdout,self.stderr)) + self.tests=[] + self.assertions=[] + self.stdout = [] + self.stderr = [] + + def process(self,inFromStdout=sys.stdin,inFromStderr=None): + self.testSet = [] + self.assertions = [] + self.tests = [] + self.stdin = [] + self.stderr = [] + + workers = [Processor(self,inFromStdout,False)] + if inFromStderr != None: + worders.append(Processor(self,inFromStderr,True)) + threads = [threading.Thread(target=workers[i].run) for i in range(len(workers))] + for thread in threads: + thread.start() + for thread in threads: + thread.join() + self.end() + +class Summary: + _re = re.compile('.*Test summary: (.*) passed, (.*) failed, and (.*) skipped, out of (.*) test\(s\)\.') + + def __init__(self,result): + if result != None: + self.passed = int(result.group(1)) + self.failed = int(result.group(2)) + self.skipped = int(result.group(3)) + self.count = int(result.group(4)) + else: + self.passed = 0 + self.failed = 0 + self.skipped = 0 + self.count = 0 + + def __str__(self): + return 'summary(passed=' + str(self.passed) + ',failed='+str(self.failed)+',skipped='+str(self.skipped)+',count='+str(self.count)+')' + + def __repr__(self): + return self.__str__() + + +class TestSet: + def __init__(self,result,tests,assertions,stdout,stderr): + self.summary = Summary(result) + if tests != None: + self.tests = tests + else: + self.tests = [] + if len(assertions) > 0: + self.tests.append(Test(None,assertions,stdout,stderr)) + + def __str__(self): + return 'testset(tests='+str(self.tests)+',summary='+str(self.summary)+')' + def __repr__(self): + return self.__str__() + +class Processor: + def __init__(self,parser,stream,isStderr): + self.parser = parser + self.stream = stream + self.isStderr=isStderr + + def run(self): + for line in self.stream: + line=line.rstrip() + self.parser.parseLine(line,self.isStderr) + +class Parser: + def __init__(self): + self.reTest = re.compile('.*Test (.*) (skipped|passed|failed)\.') + self.testSets = [] + self.tests = [] + self.assertions = [] + self.stdout = [] + self.stderr = [] + + def end(self): + if len(self.tests) != 0 or len(self.assertions) != 0: + self.testSets.append(TestSet(None,self.tests,self.assertions,self.stdout,self.stderr)) + self.tests=[] + self.assertions=[] + self.stdout = [] + self.stderr = [] + + def parseLine(self,line,stderr=False): + if line == None: + self.end() + return + if (stderr == False): + self.stdout.append(line) + else: + self.stderr.append(line) + + result=Assert._re.match(line) + if result: + self.assertions.append(Assert(result)) + result=Test._re.match(line) + if result: + self.tests.append(Test(result,self.assertions,self.stdout,self.stderr)) + self.assertions=[] + self.stdout=[] + self.stderr=[] + result=Summary._re.match(line) + if result: + self.testSets.append(TestSet(result,self.tests,self.assertions,self.stdout,self.stderr)) + self.tests=[] + self.assertions=[] + self.stdout = [] + self.stderr = [] + + def process(self,inFromStdout=sys.stdin,inFromStderr=None): + self.testSet = [] + self.assertions = [] + self.tests = [] + self.stdin = [] + self.stderr = [] + + workers = [Processor(self,inFromStdout,False)] + if inFromStderr != None: + worders.append(Processor(self,inFromStderr,True)) + threads = [threading.Thread(target=workers[i].run) for i in range(len(workers))] + for thread in threads: + thread.start() + for thread in threads: + thread.join() + self.end() + +class Summary: + _re = re.compile('.*Test summary: (.*) passed, (.*) failed, and (.*) skipped, out of (.*) test\(s\)\.') + + def __init__(self,result): + if result != None: + self.passed = int(result.group(1)) + self.failed = int(result.group(2)) + self.skipped = int(result.group(3)) + self.count = int(result.group(4)) + else: + self.passed = 0 + self.failed = 0 + self.skipped = 0 + self.count = 0 + + def __str__(self): + return 'summary(passed=' + str(self.passed) + ',failed='+str(self.failed)+',skipped='+str(self.skipped)+',count='+str(self.count)+')' + + def __repr__(self): + return self.__str__() + + +class TestSet: + def __init__(self,result,tests,assertions,stdout,stderr): + self.summary = Summary(result) + if tests != None: + self.tests = tests + else: + self.tests = [] + if len(assertions) > 0: + self.tests.append(Test(None,assertions,stdout,stderr)) + + def __str__(self): + return 'testset(tests='+str(self.tests)+',summary='+str(self.summary)+')' + def __repr__(self): + return self.__str__() + +class Processor: + def __init__(self,parser,stream,isStderr): + self.parser = parser + self.stream = stream + self.isStderr=isStderr + + def run(self): + for line in self.stream: + line=line.rstrip() + self.parser.parseLine(line,self.isStderr) + +class Parser: + def __init__(self): + self.reTest = re.compile('.*Test (.*) (skipped|passed|failed)\.') + self.testSets = [] + self.tests = [] + self.assertions = [] + self.stdout = [] + self.stderr = [] + + def end(self): + if len(self.tests) != 0 or len(self.assertions) != 0: + self.testSets.append(TestSet(None,self.tests,self.assertions,self.stdout,self.stderr)) + self.tests=[] + self.assertions=[] + self.stdout = [] + self.stderr = [] + + def parseLine(self,line,stderr=False): + if line == None: + self.end() + return + if (stderr == False): + self.stdout.append(line) + else: + self.stderr.append(line) + + result=Assert._re.match(line) + if result: + self.assertions.append(Assert(result)) + result=Test._re.match(line) + if result: + self.tests.append(Test(result,self.assertions,self.stdout,self.stderr)) + self.assertions=[] + self.stdout=[] + self.stderr=[] + result=Summary._re.match(line) + if result: + self.testSets.append(TestSet(result,self.tests,self.assertions,self.stdout,self.stderr)) + self.tests=[] + self.assertions=[] + self.stdout = [] + self.stderr = [] + + def process(self,inFromStdout=sys.stdin,inFromStderr=None): + self.testSet = [] + self.assertions = [] + self.tests = [] + self.stdin = [] + self.stderr = [] + + workers = [Processor(self,inFromStdout,False)] + if inFromStderr != None: + worders.append(Processor(self,inFromStderr,True)) + threads = [threading.Thread(target=workers[i].run) for i in range(len(workers))] + for thread in threads: + thread.start() + for thread in threads: + thread.join() + self.end() + +class JUnit4: + def __init__(self): + pass + + def indent(self, elem, level=0): + i = "\n" + level*" " + j = "\n" + (level-1)*" " + + if len(elem): + if not elem.text or not elem.text.strip(): + elem.text = i + " " + if not elem.tail or not elem.tail.strip(): + elem.tail = i + for subelem in elem: + self.indent(subelem, level+1) + if not elem.tail or not elem.tail.strip(): + elem.tail = j + else: + if level and (not elem.tail or not elem.tail.strip()): + elem.tail = j + return elem + + def printTestSets(self,testSets,prettyPrint=True): + doc = self.addTestSets(testSets) + xml = xet.ElementTree(doc) + if prettyPrint: + self.indent(doc) + xml.write(sys.stdout, xml_declaration=True, encoding='utf-8') + + def addTestSets(self,testSets,parent=None): + ans = None + if parent != None: + ans =xet.SubElement(parent,"testsuites") + else: + ans =xet.Element("testsuites") + + for testSet in testSets: + self.addTestSet(testSet,ans) + return ans + + def addTestSet(self,testSet,parent=None): + ans = None + if parent != None: + ans = xet.SubElement(parent,"testsuite") + else: + ans = xet.Element("testsuite") + + ans.set("tests",str(len(testSet.tests))) + + for test in testSet.tests: + self.addTest(test,ans) + + return ans + + def addTest(self,test,parent=None): + ans = None + if parent != None: + ans = xet.SubElement(parent,"testcase") + else: + ans = xet.Element("testcase") + + ans.set("name",test.name) + + if test.state == 'skipped': + xet.SubElement(ans,"skipped") + return + + for assertion in test.assertions: + self.addAssertion(assertion,ans) + + self.addStdout(test.stdout,ans) + self.addStderr(test.stderr,ans) + + def addStdout(Self,stdout,parent=None): + if (len(stdout) == 0): + return None + ans = None + if parent != None: + ans = xet.SubElement(parent,"stdout") + else: + ans = xet.Element("stdout") + + ans.text = "\n" + "\n".join(stdout) + "\n" + return ans + + def addStderr(Self,stderr,parent=None): + if (len(stderr) == 0): + return None + ans = None + if parent != None: + ans = xet.SubElement(parent,"stderr") + else: + ans = xet.Element("stderr") + + ans.text = "\n" + "\n".join(stderr) + return ans + + def addAssertion(self,assertion,parent=None): + ans = None + if (assertion.state == 'passed'): + return None + + if parent != None: + ans = xet.SubElement(parent,"failure") + else: + ans = xet.Element("failure") + + message = assertion.file + ":" + str(assertion.line) + " " + assertion.message + ans.set("message",message) + + text = ["\n"] + + if assertion.file != None: + text.append("File \"" + assertion.file + "\"") + else: + text.append("File None") + + if assertion.line != None: + text.append(", line " + str(assertion.line)) + else: + text.append(", line unknown") + if parent != None: + text.append(", in " + parent.get("name") + "\n") + else: + text.append(", in unknown\n") + text.append(" Assertion failed: " + assertion.message) + if assertion.file != None: + text.append(", file " + assertion.file) + if assertion.line != None: + text.append(", line " + str(assertion.line)) + if (assertion.footnote != None): + text.append(" [" + assertion.footnote + "]") + text.append(".") + text.append("\n") + + ans.text = "".join(text) + + return ans + +def main(): + p = Parser() + p.process() + junit4=JUnit4() + junit4.printTestSets(p.testSets) + +if __name__ == '__main__': + main() diff --git a/examples/vitro/compile b/examples/vitro/compile new file mode 100755 index 0000000..c79e8f0 --- /dev/null +++ b/examples/vitro/compile @@ -0,0 +1,83 @@ +#!/bin/bash + +# +# Figure out where arduino libraries are... +# +if [ "$(uname)" = "Darwin" ] +then + ARDUINO_LIBS="$HOME/Documents/Arduino/libraries" +elif [ "$(uname)" = "Linux" ] +then + ARDUINO_LIBS="$HOME/Arduino/libraries" +else + ARDUINO_LIBS="$HOME/My Documents/Arduino/libraries" +fi + +ARDUINO_UNIT_DIR="$ARDUINO_LIBS/ArduinoUnit" + +if [ ! -r "$ARDUINO_UNIT_DIR/src/ArduinoUnit.h" ] +then + echo "Cannot find ArduinoUnit library." + exit 1 +fi + +# +# Figure out what to compile +# +if [ $# -gt 0 ]; then + ARDUINO_TARGET_INO="$1" +else + ARDUINO_TARGET_INO="$(echo *.ino)" +fi + +if [ ! -f "${ARDUINO_TARGET_INO}" ] ; then + echo "must specify ino file" + exit 1 +fi + +ARDUINO_TARGET_DIR=$(dirname "$1") +if [ ! -d "${ARDUINO_TARGET_DIR}" ] ; then + echo "missing directory ${ARDUINO_TARGET_DIR}." + exit 1 +fi + +# +# Make a temp directory to work in (that is removed) +# +if [ "$TMP" = "" ] ; then + TMP="$(mktemp -d)" + trap '{ /bin/rm -rf "${TMP}"; }' EXIT +else + mkdir -p "$TMP" +fi + +# +# copy all source files (.ino, .cpp and .h files) into $TMP/src directory +# +mkdir -p "${TMP}/src" +(cd ${ARDUINO_TARGET_DIR}; tar cf - $(find -E . -iregex '^.*/[A-Za-z0-9]([-_A-Za-z0-9]*[_A-Za-z0-9])*(\.cpp|\.h|\.ino)$')) | tar -C ${TMP}/src -xf - + +# +# copy ArduinoUnit files into $TMP/ArduinoUnit/src directory +# +mkdir -p "${TMP}/ArduinoUnit/src" +(cd "${ARDUINO_UNIT_DIR}/src"; tar cf - $(find -E . -iregex '^.*/[A-Za-z0-9]([-_A-Za-z0-9]*[_A-Za-z0-9])*(\.cpp|\.h|\.ino)$')) | tar -C "${TMP}/ArduinoUnit/src" -xf - + +ARDUINO_TARGET_EXE="${ARDUINO_TARGET_INO%.ino}" + +# +# compile everything in the temp directory, relabeling filenames errors so they look like they came from the right place +# + +/bin/rm -rf "${ARDUINO_TARGET_EXE}" +g++ -g -std=gnu++11 -o "${TMP}/a.out" -isystem "${TMP}/ArduinoUnit/src" $(find "${TMP}/src" -name '*.cpp') $(find "${TMP}/ArduinoUnit/src" -name '*.cpp') 2>&1 | sed -e "s|${TMP}/src/|${ARDUINO_TARGET_DIR}/|g" | sed -e "s|${TMP}/ArduinoUnit/src/|${ARDUINO_UNIT_DIR}/src/|g" + +if [ -x "${TMP}/a.out" ] +then + cp "${TMP}/a.out" "${ARDUINO_TARGET_EXE}" +fi +if [ ! -x "${TMP}/a.out" ] +then + echo "compilation failed." + exit 1 +fi diff --git a/examples/vitro/mockVitro.cpp b/examples/vitro/mockVitro.cpp new file mode 100644 index 0000000..51448a2 --- /dev/null +++ b/examples/vitro/mockVitro.cpp @@ -0,0 +1,42 @@ +// +// The regular arduino build should ignore this file, +// it is only to mock the arduino environment when +// compiled "en vitro" on the dev system. +// +#if !defined(ARDUINO) + +#include "ArduinoUnit.h" + +void setup(); +void loop(); + +// CppIOStream wraps stdin/stdout as a mock Serial device +CppIOStream Serial; + +// you will have to mock any other parts you use, perhaps +// with a more complete mocking library... + +int main(int argc, const char *argv[]) { + int timeLimitMicros = 10000; + + setup(); + + // loop until tests complete + while (Test::remaining() > 0 && micros() < timeLimitMicros) { + loop(); + } + + // abort (fail) any remaining tests + Test::abort(); + + if (Test::getCurrentFailed() == 0) { + return 0; + } else { + return 1; + } +} + +// include the "ino" here... +#include "vitro.ino" + +#endif diff --git a/examples/vitro/test b/examples/vitro/test new file mode 100755 index 0000000..22b8959 --- /dev/null +++ b/examples/vitro/test @@ -0,0 +1,44 @@ +#!/bin/bash + +# +# Figure out what to test +# +if [ $# -gt 0 ]; then + ARDUINO_TARGET_INO="$1" +else + ARDUINO_TARGET_INO="$(echo *.ino)" +fi + +if [ ! -f "${ARDUINO_TARGET_INO}" ] ; then + echo "must specify ino file" + exit 1 +fi + +ARDUINO_TARGET_DIR="$(dirname "$ARDUINO_TARGET_INO")" +ARDUINO_TARGET_BASE="$(basename "$ARDUINO_TARGET_INO")" +ARDUINO_TARGET_FILE="${ARDUINO_TARGET_BASE%.ino}" +ARDUINO_TARGET_EXE="$ARDUINO_TARGET_DIR/$ARDUINO_TARGET_FILE" + +/bin/rm -rf "${ARDUINO_TARGET_EXE}.log" "${ARDUINO_TARGET_EXE}.xml" + +if [ ! -x "${ARDUINO_TARGET_EXE}" ] ; then + echo "missing executable '${ARDUINO_TARGET_EXE}' -- did you compile?" + exit 1 +fi + +if [ "$TMP" = "" ] ; then + TMP="$(mktemp -d)" + trap '{ /bin/rm -rf "${TMP}"; }' EXIT +else + mkdir -p "$TMP" +fi + +( "${ARDUINO_TARGET_EXE}"; echo "$?" > "$TMP/status" ) | tee "${ARDUINO_TARGET_EXE}.log" + +STATUS="$(cat "$TMP/status")" + +if [ -r "${ARDUINO_TARGET_EXE}.log" ] +then + ./au2ju < "${ARDUINO_TARGET_EXE}.log" > "${ARDUINO_TARGET_EXE}.xml" +fi +exit $STATUS diff --git a/examples/vitro/vitro.ino b/examples/vitro/vitro.ino new file mode 100644 index 0000000..51296eb --- /dev/null +++ b/examples/vitro/vitro.ino @@ -0,0 +1,25 @@ +#line 2 "vitro.ino" +#include + +test(correct) +{ + int x=1; + assertEqual(x,1); +} + +test(incorrect) +{ + int x=1; + assertNotEqual(x,1); +} + +void setup() +{ + Serial.begin(9600); + while(!Serial) {} // Portability for Leonardo/Micro +} + +void loop() +{ + Test::run(); +} From e72096f1b95bd90783cb61936b489dca2c80a0f1 Mon Sep 17 00:00:00 2001 From: Warren MacEvoy Date: Thu, 3 May 2018 12:14:46 +0545 Subject: [PATCH 14/80] vitro example --- examples/vitro/README.md | 43 ++++++++++++++++++++++++---------------- 1 file changed, 26 insertions(+), 17 deletions(-) diff --git a/examples/vitro/README.md b/examples/vitro/README.md index 15d43dd..985561c 100644 --- a/examples/vitro/README.md +++ b/examples/vitro/README.md @@ -1,35 +1,44 @@ # En Vitro (Advanced) -ArduinoUnit can be used to compile sketches "en vitro" on the development system. +ArduinoUnit can be used to compile sketches "en vitro" on the development system. -# Who +## Who You need to be comfortable with compiling using the g++ compiler from the command line, and modifying bash scripts. -# Why +## Why If a unit can tested outside of the embedded environment, you can find problems more easily because of the tools available. -# How +## How 1. Write a sketch with tests (like `vitro.ino`) -1. Write a `mockVitro.cpp` (any name(s) will do) that creates a "mock" arduino environment where the sketch can run on the dev system - 1. ArduinoUnit provides limited mocking (just enough for ArduinoUnit to work). - 1. Stream -- CppStream(in=cin,out=cout) can be used to make a mock Serial device. - 1. Print - 1. String - 1. F() and __FlashStringHelper - 1. micros and millis - 1. You will probabaly want to mock more things. - 1. `mockVitro.cpp` is a getting started version: - 1. A mock `Serial` connected to stdin and stdout - 1. A `main()` that calls `setup()` then `loop()`s while tests are not done. +1. Write a `mockVitro.cpp` (any name(s) will do) that creates a "mock" Arduino environment where the sketch can run on the dev system. ArduinoUnit provides limited mocking (just enough for ArduinoUnit to work): + + 1. Stream -- CppStream(in=cin,out=cout) can be used to make a mock Serial device. + 1. Print + 1. String + 1. F() and __FlashStringHelper + 1. micros and millis + 1. You will probably want to mock more things. + +1. `mockVitro.cpp` is a getting started version: + + 1. A mock `Serial` connected to stdin and stdout + 1. A `main()` that calls `setup()` then `loop()`s while tests are not done. + 1. Compile everything using g++ (`./compile`) 1. Run the program locally (`./vitro`). -# Continuous Testing +## Continuous Integration + +There are a lot of continuous testing frameworks. There is an `au2ju` python 2 script that converts the ArduinoUnit-style into JUnit style, which is a popular (although unreadable by humans) format for these tools: + +```bash +./vitro | ./au2ju > vitro.xml +``` -There are a lot of contiuous testing frameworks. There is an au2ju script converts the ArduinoUnit-style into JUnit style, which is a popular (although unreadable by humans) format for these tools. The `test` script runs the compiled executable and creates such a file. +The `test` script runs the compiled executable and creates such a file. Compile returns with an exit code of 1 if the build fails, and test returns with an exit code of 1 if the executable is missing or any test fails. ```bash ./compile From 1b7b6f1546314dcdb4b00591278c5be99b489db6 Mon Sep 17 00:00:00 2001 From: Warren MacEvoy Date: Thu, 3 May 2018 12:20:47 +0545 Subject: [PATCH 15/80] vitro build --- examples/advanced/au2ju | 541 ++++++++++++++++++++++++++++++++ examples/advanced/compile-vitro | 83 +++++ 2 files changed, 624 insertions(+) create mode 100755 examples/advanced/au2ju create mode 100755 examples/advanced/compile-vitro diff --git a/examples/advanced/au2ju b/examples/advanced/au2ju new file mode 100755 index 0000000..5f9d640 --- /dev/null +++ b/examples/advanced/au2ju @@ -0,0 +1,541 @@ +#!/usr/bin/env python + +import os +import re +import sys +import glob +import threading +import xml.etree.cElementTree as xet + +class Test: + _re = re.compile('.*Test (.*) (skipped|passed|failed)\.') + + def __init__(self, result, assertions,stdout,stderr): + if result != None: + self.name = result.group(1) + self.state = result.group(2) + self.stdout = stdout + self.stderr = stderr + else: + self.name = "unknown" + self.state = "unknown" + self.stdout = stdout + self.stderr = stderr + + if assertions != None: + self.assertions = assertions + else: + self.assertions=[] + + def __str__(self): + return "test(name='"+str(self.name)+"',state='"+str(self.state)+"',assertions="+str(self.assertions) + ",stdout=" + str(self.stdout) + ",stderr=" + str(self.stdout)+")" + + def __repr__(self): + return self.__str__() + + +class Assert: + _re = re.compile('.*Assertion (passed|failed): (.*)\.') + _details = re.compile('(.*), file (.*), line ([0-9]+) *(\[(.*)\])?') + + def __init__(self,result): + if result == None: + self.state = None + self.message = None + self.footnote = None + self.file = None + self.line = None + else: + self.state = result.group(1) + details = Assert._details.match(result.group(2)) + if details != None: + self.message = details.group(1) + self.file = details.group(2) + self.line = int(details.group(3)) + if details.group(5) != None: + self.footnote = details.group(5) + else: + self.footnote = None + else: + self.message = result.group(2) + self.file = None + self.line = None + self.footnote = None + + def __str__(self): + return "assert(state='"+str(self.state)+"',message='"+str(self.message)+"',file='"+str(self.file)+"',line="+str(self.line)+",footnote='" + self.footnote + "')" + + def __repr__(self): + return self.__str__() + +class Summary: + _re = re.compile('.*Test summary: (.*) passed, (.*) failed, and (.*) skipped, out of (.*) test\(s\)\.') + + def __init__(self,result): + if result != None: + self.passed = int(result.group(1)) + self.failed = int(result.group(2)) + self.skipped = int(result.group(3)) + self.count = int(result.group(4)) + else: + self.passed = 0 + self.failed = 0 + self.skipped = 0 + self.count = 0 + + def __str__(self): + return 'summary(passed=' + str(self.passed) + ',failed='+str(self.failed)+',skipped='+str(self.skipped)+',count='+str(self.count)+')' + + def __repr__(self): + return self.__str__() + + +class TestSet: + def __init__(self,result,tests,assertions,stdout,stderr): + self.summary = Summary(result) + if tests != None: + self.tests = tests + else: + self.tests = [] + if len(assertions) > 0: + self.tests.append(Test(None,assertions,stdout,stderr)) + + def __str__(self): + return 'testset(tests='+str(self.tests)+',summary='+str(self.summary)+')' + def __repr__(self): + return self.__str__() + +class Processor: + def __init__(self,parser,stream,isStderr): + self.parser = parser + self.stream = stream + self.isStderr=isStderr + + def run(self): + for line in self.stream: + line=line.rstrip() + self.parser.parseLine(line,self.isStderr) + +class Parser: + def __init__(self): + self.reTest = re.compile('.*Test (.*) (skipped|passed|failed)\.') + self.testSets = [] + self.tests = [] + self.assertions = [] + self.stdout = [] + self.stderr = [] + + def end(self): + if len(self.tests) != 0 or len(self.assertions) != 0: + self.testSets.append(TestSet(None,self.tests,self.assertions,self.stdout,self.stderr)) + self.tests=[] + self.assertions=[] + self.stdout = [] + self.stderr = [] + + def parseLine(self,line,stderr=False): + if line == None: + self.end() + return + if (stderr == False): + self.stdout.append(line) + else: + self.stderr.append(line) + + result=Assert._re.match(line) + if result: + self.assertions.append(Assert(result)) + result=Test._re.match(line) + if result: + self.tests.append(Test(result,self.assertions,self.stdout,self.stderr)) + self.assertions=[] + self.stdout=[] + self.stderr=[] + result=Summary._re.match(line) + if result: + self.testSets.append(TestSet(result,self.tests,self.assertions,self.stdout,self.stderr)) + self.tests=[] + self.assertions=[] + self.stdout = [] + self.stderr = [] + + def process(self,inFromStdout=sys.stdin,inFromStderr=None): + self.testSet = [] + self.assertions = [] + self.tests = [] + self.stdin = [] + self.stderr = [] + + workers = [Processor(self,inFromStdout,False)] + if inFromStderr != None: + worders.append(Processor(self,inFromStderr,True)) + threads = [threading.Thread(target=workers[i].run) for i in range(len(workers))] + for thread in threads: + thread.start() + for thread in threads: + thread.join() + self.end() + +class Summary: + _re = re.compile('.*Test summary: (.*) passed, (.*) failed, and (.*) skipped, out of (.*) test\(s\)\.') + + def __init__(self,result): + if result != None: + self.passed = int(result.group(1)) + self.failed = int(result.group(2)) + self.skipped = int(result.group(3)) + self.count = int(result.group(4)) + else: + self.passed = 0 + self.failed = 0 + self.skipped = 0 + self.count = 0 + + def __str__(self): + return 'summary(passed=' + str(self.passed) + ',failed='+str(self.failed)+',skipped='+str(self.skipped)+',count='+str(self.count)+')' + + def __repr__(self): + return self.__str__() + + +class TestSet: + def __init__(self,result,tests,assertions,stdout,stderr): + self.summary = Summary(result) + if tests != None: + self.tests = tests + else: + self.tests = [] + if len(assertions) > 0: + self.tests.append(Test(None,assertions,stdout,stderr)) + + def __str__(self): + return 'testset(tests='+str(self.tests)+',summary='+str(self.summary)+')' + def __repr__(self): + return self.__str__() + +class Processor: + def __init__(self,parser,stream,isStderr): + self.parser = parser + self.stream = stream + self.isStderr=isStderr + + def run(self): + for line in self.stream: + line=line.rstrip() + self.parser.parseLine(line,self.isStderr) + +class Parser: + def __init__(self): + self.reTest = re.compile('.*Test (.*) (skipped|passed|failed)\.') + self.testSets = [] + self.tests = [] + self.assertions = [] + self.stdout = [] + self.stderr = [] + + def end(self): + if len(self.tests) != 0 or len(self.assertions) != 0: + self.testSets.append(TestSet(None,self.tests,self.assertions,self.stdout,self.stderr)) + self.tests=[] + self.assertions=[] + self.stdout = [] + self.stderr = [] + + def parseLine(self,line,stderr=False): + if line == None: + self.end() + return + if (stderr == False): + self.stdout.append(line) + else: + self.stderr.append(line) + + result=Assert._re.match(line) + if result: + self.assertions.append(Assert(result)) + result=Test._re.match(line) + if result: + self.tests.append(Test(result,self.assertions,self.stdout,self.stderr)) + self.assertions=[] + self.stdout=[] + self.stderr=[] + result=Summary._re.match(line) + if result: + self.testSets.append(TestSet(result,self.tests,self.assertions,self.stdout,self.stderr)) + self.tests=[] + self.assertions=[] + self.stdout = [] + self.stderr = [] + + def process(self,inFromStdout=sys.stdin,inFromStderr=None): + self.testSet = [] + self.assertions = [] + self.tests = [] + self.stdin = [] + self.stderr = [] + + workers = [Processor(self,inFromStdout,False)] + if inFromStderr != None: + worders.append(Processor(self,inFromStderr,True)) + threads = [threading.Thread(target=workers[i].run) for i in range(len(workers))] + for thread in threads: + thread.start() + for thread in threads: + thread.join() + self.end() + +class Summary: + _re = re.compile('.*Test summary: (.*) passed, (.*) failed, and (.*) skipped, out of (.*) test\(s\)\.') + + def __init__(self,result): + if result != None: + self.passed = int(result.group(1)) + self.failed = int(result.group(2)) + self.skipped = int(result.group(3)) + self.count = int(result.group(4)) + else: + self.passed = 0 + self.failed = 0 + self.skipped = 0 + self.count = 0 + + def __str__(self): + return 'summary(passed=' + str(self.passed) + ',failed='+str(self.failed)+',skipped='+str(self.skipped)+',count='+str(self.count)+')' + + def __repr__(self): + return self.__str__() + + +class TestSet: + def __init__(self,result,tests,assertions,stdout,stderr): + self.summary = Summary(result) + if tests != None: + self.tests = tests + else: + self.tests = [] + if len(assertions) > 0: + self.tests.append(Test(None,assertions,stdout,stderr)) + + def __str__(self): + return 'testset(tests='+str(self.tests)+',summary='+str(self.summary)+')' + def __repr__(self): + return self.__str__() + +class Processor: + def __init__(self,parser,stream,isStderr): + self.parser = parser + self.stream = stream + self.isStderr=isStderr + + def run(self): + for line in self.stream: + line=line.rstrip() + self.parser.parseLine(line,self.isStderr) + +class Parser: + def __init__(self): + self.reTest = re.compile('.*Test (.*) (skipped|passed|failed)\.') + self.testSets = [] + self.tests = [] + self.assertions = [] + self.stdout = [] + self.stderr = [] + + def end(self): + if len(self.tests) != 0 or len(self.assertions) != 0: + self.testSets.append(TestSet(None,self.tests,self.assertions,self.stdout,self.stderr)) + self.tests=[] + self.assertions=[] + self.stdout = [] + self.stderr = [] + + def parseLine(self,line,stderr=False): + if line == None: + self.end() + return + if (stderr == False): + self.stdout.append(line) + else: + self.stderr.append(line) + + result=Assert._re.match(line) + if result: + self.assertions.append(Assert(result)) + result=Test._re.match(line) + if result: + self.tests.append(Test(result,self.assertions,self.stdout,self.stderr)) + self.assertions=[] + self.stdout=[] + self.stderr=[] + result=Summary._re.match(line) + if result: + self.testSets.append(TestSet(result,self.tests,self.assertions,self.stdout,self.stderr)) + self.tests=[] + self.assertions=[] + self.stdout = [] + self.stderr = [] + + def process(self,inFromStdout=sys.stdin,inFromStderr=None): + self.testSet = [] + self.assertions = [] + self.tests = [] + self.stdin = [] + self.stderr = [] + + workers = [Processor(self,inFromStdout,False)] + if inFromStderr != None: + worders.append(Processor(self,inFromStderr,True)) + threads = [threading.Thread(target=workers[i].run) for i in range(len(workers))] + for thread in threads: + thread.start() + for thread in threads: + thread.join() + self.end() + +class JUnit4: + def __init__(self): + pass + + def indent(self, elem, level=0): + i = "\n" + level*" " + j = "\n" + (level-1)*" " + + if len(elem): + if not elem.text or not elem.text.strip(): + elem.text = i + " " + if not elem.tail or not elem.tail.strip(): + elem.tail = i + for subelem in elem: + self.indent(subelem, level+1) + if not elem.tail or not elem.tail.strip(): + elem.tail = j + else: + if level and (not elem.tail or not elem.tail.strip()): + elem.tail = j + return elem + + def printTestSets(self,testSets,prettyPrint=True): + doc = self.addTestSets(testSets) + xml = xet.ElementTree(doc) + if prettyPrint: + self.indent(doc) + xml.write(sys.stdout, xml_declaration=True, encoding='utf-8') + + def addTestSets(self,testSets,parent=None): + ans = None + if parent != None: + ans =xet.SubElement(parent,"testsuites") + else: + ans =xet.Element("testsuites") + + for testSet in testSets: + self.addTestSet(testSet,ans) + return ans + + def addTestSet(self,testSet,parent=None): + ans = None + if parent != None: + ans = xet.SubElement(parent,"testsuite") + else: + ans = xet.Element("testsuite") + + ans.set("tests",str(len(testSet.tests))) + + for test in testSet.tests: + self.addTest(test,ans) + + return ans + + def addTest(self,test,parent=None): + ans = None + if parent != None: + ans = xet.SubElement(parent,"testcase") + else: + ans = xet.Element("testcase") + + ans.set("name",test.name) + + if test.state == 'skipped': + xet.SubElement(ans,"skipped") + return + + for assertion in test.assertions: + self.addAssertion(assertion,ans) + + self.addStdout(test.stdout,ans) + self.addStderr(test.stderr,ans) + + def addStdout(Self,stdout,parent=None): + if (len(stdout) == 0): + return None + ans = None + if parent != None: + ans = xet.SubElement(parent,"stdout") + else: + ans = xet.Element("stdout") + + ans.text = "\n" + "\n".join(stdout) + "\n" + return ans + + def addStderr(Self,stderr,parent=None): + if (len(stderr) == 0): + return None + ans = None + if parent != None: + ans = xet.SubElement(parent,"stderr") + else: + ans = xet.Element("stderr") + + ans.text = "\n" + "\n".join(stderr) + return ans + + def addAssertion(self,assertion,parent=None): + ans = None + if (assertion.state == 'passed'): + return None + + if parent != None: + ans = xet.SubElement(parent,"failure") + else: + ans = xet.Element("failure") + + message = assertion.file + ":" + str(assertion.line) + " " + assertion.message + ans.set("message",message) + + text = ["\n"] + + if assertion.file != None: + text.append("File \"" + assertion.file + "\"") + else: + text.append("File None") + + if assertion.line != None: + text.append(", line " + str(assertion.line)) + else: + text.append(", line unknown") + if parent != None: + text.append(", in " + parent.get("name") + "\n") + else: + text.append(", in unknown\n") + text.append(" Assertion failed: " + assertion.message) + if assertion.file != None: + text.append(", file " + assertion.file) + if assertion.line != None: + text.append(", line " + str(assertion.line)) + if (assertion.footnote != None): + text.append(" [" + assertion.footnote + "]") + text.append(".") + text.append("\n") + + ans.text = "".join(text) + + return ans + +def main(): + p = Parser() + p.process() + junit4=JUnit4() + junit4.printTestSets(p.testSets) + +if __name__ == '__main__': + main() diff --git a/examples/advanced/compile-vitro b/examples/advanced/compile-vitro new file mode 100755 index 0000000..c79e8f0 --- /dev/null +++ b/examples/advanced/compile-vitro @@ -0,0 +1,83 @@ +#!/bin/bash + +# +# Figure out where arduino libraries are... +# +if [ "$(uname)" = "Darwin" ] +then + ARDUINO_LIBS="$HOME/Documents/Arduino/libraries" +elif [ "$(uname)" = "Linux" ] +then + ARDUINO_LIBS="$HOME/Arduino/libraries" +else + ARDUINO_LIBS="$HOME/My Documents/Arduino/libraries" +fi + +ARDUINO_UNIT_DIR="$ARDUINO_LIBS/ArduinoUnit" + +if [ ! -r "$ARDUINO_UNIT_DIR/src/ArduinoUnit.h" ] +then + echo "Cannot find ArduinoUnit library." + exit 1 +fi + +# +# Figure out what to compile +# +if [ $# -gt 0 ]; then + ARDUINO_TARGET_INO="$1" +else + ARDUINO_TARGET_INO="$(echo *.ino)" +fi + +if [ ! -f "${ARDUINO_TARGET_INO}" ] ; then + echo "must specify ino file" + exit 1 +fi + +ARDUINO_TARGET_DIR=$(dirname "$1") +if [ ! -d "${ARDUINO_TARGET_DIR}" ] ; then + echo "missing directory ${ARDUINO_TARGET_DIR}." + exit 1 +fi + +# +# Make a temp directory to work in (that is removed) +# +if [ "$TMP" = "" ] ; then + TMP="$(mktemp -d)" + trap '{ /bin/rm -rf "${TMP}"; }' EXIT +else + mkdir -p "$TMP" +fi + +# +# copy all source files (.ino, .cpp and .h files) into $TMP/src directory +# +mkdir -p "${TMP}/src" +(cd ${ARDUINO_TARGET_DIR}; tar cf - $(find -E . -iregex '^.*/[A-Za-z0-9]([-_A-Za-z0-9]*[_A-Za-z0-9])*(\.cpp|\.h|\.ino)$')) | tar -C ${TMP}/src -xf - + +# +# copy ArduinoUnit files into $TMP/ArduinoUnit/src directory +# +mkdir -p "${TMP}/ArduinoUnit/src" +(cd "${ARDUINO_UNIT_DIR}/src"; tar cf - $(find -E . -iregex '^.*/[A-Za-z0-9]([-_A-Za-z0-9]*[_A-Za-z0-9])*(\.cpp|\.h|\.ino)$')) | tar -C "${TMP}/ArduinoUnit/src" -xf - + +ARDUINO_TARGET_EXE="${ARDUINO_TARGET_INO%.ino}" + +# +# compile everything in the temp directory, relabeling filenames errors so they look like they came from the right place +# + +/bin/rm -rf "${ARDUINO_TARGET_EXE}" +g++ -g -std=gnu++11 -o "${TMP}/a.out" -isystem "${TMP}/ArduinoUnit/src" $(find "${TMP}/src" -name '*.cpp') $(find "${TMP}/ArduinoUnit/src" -name '*.cpp') 2>&1 | sed -e "s|${TMP}/src/|${ARDUINO_TARGET_DIR}/|g" | sed -e "s|${TMP}/ArduinoUnit/src/|${ARDUINO_UNIT_DIR}/src/|g" + +if [ -x "${TMP}/a.out" ] +then + cp "${TMP}/a.out" "${ARDUINO_TARGET_EXE}" +fi +if [ ! -x "${TMP}/a.out" ] +then + echo "compilation failed." + exit 1 +fi From b8734102a2ddc793056accb119f6b00dd31d8409 Mon Sep 17 00:00:00 2001 From: Warren MacEvoy Date: Thu, 3 May 2018 12:21:56 +0545 Subject: [PATCH 16/80] test vitro --- examples/vitro/test-vitro | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/vitro/test-vitro b/examples/vitro/test-vitro index 22b8959..7bccc2f 100755 --- a/examples/vitro/test-vitro +++ b/examples/vitro/test-vitro @@ -33,7 +33,7 @@ else mkdir -p "$TMP" fi -( "${ARDUINO_TARGET_EXE}"; echo "$?" > "$TMP/status" ) | tee "${ARDUINO_TARGET_EXE}.log" +( "${ARDUINO_TARGET_EXE}" "$@"; echo "$?" > "$TMP/status" ) | tee "${ARDUINO_TARGET_EXE}.log" STATUS="$(cat "$TMP/status")" From a965d42b4d1fcf3cc3b405445d0aced94ef8ec60 Mon Sep 17 00:00:00 2001 From: Warren MacEvoy Date: Thu, 3 May 2018 12:24:59 +0545 Subject: [PATCH 17/80] vitro example --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index b34e228..7982241 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -48,3 +48,4 @@ * assertRelation(args [,message [,retval]]) * assertRelativelyNear(a,b,max[,message]) for float/double * Test::abort() to complete all unresolved tests +* Provide "en vitro" simple example & build scripts From 906c98b9203da16d190f0946e25ec6dfec2d3ceb Mon Sep 17 00:00:00 2001 From: Warren MacEvoy Date: Thu, 3 May 2018 02:14:15 -0600 Subject: [PATCH 18/80] linux build --- Makefile | 2 +- README.md | 4 +- ci/bin/cache_ide | 2 +- ci/bin/os | 2 +- examples/advanced/compile-vitro | 19 +- examples/advanced/mockAdvanced.cpp | 2 + examples/vitro/compile-vitro | 19 +- firmware/au2ju | 541 +++++++++++++++++++++++++++++ firmware/compile-vitro | 96 +++++ firmware/test-vitro | 44 +++ 10 files changed, 720 insertions(+), 11 deletions(-) create mode 100755 firmware/au2ju create mode 100755 firmware/compile-vitro create mode 100755 firmware/test-vitro diff --git a/Makefile b/Makefile index 8b4d42a..d3cdfa7 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ UNAME := $(shell uname) ifeq ($(UNAME), Linux) - ARDUINO_DIR=/usr/share/arduino + ARDUINO_DIR=$(HOME)/Arduino endif ifeq ($(UNAME), Darwin) ARDUINO_DIR=$(HOME)/Documents/Arduino diff --git a/README.md b/README.md index bf811c9..5057602 100644 --- a/README.md +++ b/README.md @@ -62,8 +62,8 @@ The following asserts are supported [with an optional footnote and return value] | Assertion | Description | | --- | --- | | `assertEqual(a,b [,footnote [,retval]])` | `a == b`? | -| `assertNear(a,b,maxerr, [,footnote[,retval]])` | `|b-a|<=maxerr`? | -| `assertRelativelyNear(a,b,maxerr, [,footnote[,retval]])` | `|b-a|/(½(|a|+|b|))<=maxerr`? | +| `assertNear(a,b,maxerr, [,footnote[,retval]])` | `abs(b-a)<=maxerr`? | +| `assertRelativelyNear(a,b,maxerr, [,footnote[,retval]])` | `abs(b-a)/abs(½(abs(a)+abs(b)))<=maxerr`? | | `assertNotEqual(a,b [,footnote[,retval]])` | `a != b`? | | `assertLess(a,b [,footnote[,retval]])` | `a < b`? | | `assertLessOrEqual(a,b [,footnote[,retval]])` | `a <= b`? | diff --git a/ci/bin/cache_ide b/ci/bin/cache_ide index 2a25602..87432d5 100755 --- a/ci/bin/cache_ide +++ b/ci/bin/cache_ide @@ -1,4 +1,4 @@ -#!/bin/bash -x +#!/bin/bash if [ "$(type -t os)" != "function" ] then diff --git a/ci/bin/os b/ci/bin/os index 71356f9..48ba662 100755 --- a/ci/bin/os +++ b/ci/bin/os @@ -54,7 +54,7 @@ os() { then echo "linuxarm" return - elif lscpu | grep "CPU op-modes(s)" | grep -q "64-bit" + elif lscpu | grep "CPU op-mode(s)" | grep -q "64-bit" then echo "linux64" return diff --git a/examples/advanced/compile-vitro b/examples/advanced/compile-vitro index c79e8f0..903d4d4 100755 --- a/examples/advanced/compile-vitro +++ b/examples/advanced/compile-vitro @@ -54,14 +54,27 @@ fi # # copy all source files (.ino, .cpp and .h files) into $TMP/src directory # +sources() { + if [ "$(uname)" = "Darwin" ] + then + find -E "$1" -iregex '^.*/[A-Za-z0-9]([-_A-Za-z0-9]*[_A-Za-z0-9])*(\.cpp|\.h|\.ino)$' + else + find "$1" -iregex '^.*/[A-Za-z0-9]\([-_A-Za-z0-9]*[_A-Za-z0-9]\)*\(\.cpp\|\.h\|\.ino\)$' + fi +} + +cpp_sources() { + sources "$@" | egrep '\.cpp$' +} + mkdir -p "${TMP}/src" -(cd ${ARDUINO_TARGET_DIR}; tar cf - $(find -E . -iregex '^.*/[A-Za-z0-9]([-_A-Za-z0-9]*[_A-Za-z0-9])*(\.cpp|\.h|\.ino)$')) | tar -C ${TMP}/src -xf - +(cd ${ARDUINO_TARGET_DIR}; tar cf - $(sources .)) | tar -C "${TMP}/src" -xf - # # copy ArduinoUnit files into $TMP/ArduinoUnit/src directory # mkdir -p "${TMP}/ArduinoUnit/src" -(cd "${ARDUINO_UNIT_DIR}/src"; tar cf - $(find -E . -iregex '^.*/[A-Za-z0-9]([-_A-Za-z0-9]*[_A-Za-z0-9])*(\.cpp|\.h|\.ino)$')) | tar -C "${TMP}/ArduinoUnit/src" -xf - +(cd "${ARDUINO_UNIT_DIR}/src"; tar cf - $(sources .)) | tar -C "${TMP}/ArduinoUnit/src" -xf - ARDUINO_TARGET_EXE="${ARDUINO_TARGET_INO%.ino}" @@ -70,7 +83,7 @@ ARDUINO_TARGET_EXE="${ARDUINO_TARGET_INO%.ino}" # /bin/rm -rf "${ARDUINO_TARGET_EXE}" -g++ -g -std=gnu++11 -o "${TMP}/a.out" -isystem "${TMP}/ArduinoUnit/src" $(find "${TMP}/src" -name '*.cpp') $(find "${TMP}/ArduinoUnit/src" -name '*.cpp') 2>&1 | sed -e "s|${TMP}/src/|${ARDUINO_TARGET_DIR}/|g" | sed -e "s|${TMP}/ArduinoUnit/src/|${ARDUINO_UNIT_DIR}/src/|g" +g++ -g -std=gnu++11 -o "${TMP}/a.out" -isystem "${TMP}/ArduinoUnit/src" $(cpp_sources "${TMP}/src") $(cpp_sources "${TMP}/ArduinoUnit/src") 2>&1 | sed -e "s|${TMP}/src/|${ARDUINO_TARGET_DIR}/|g" | sed -e "s|${TMP}/ArduinoUnit/src/|${ARDUINO_UNIT_DIR}/src/|g" if [ -x "${TMP}/a.out" ] then diff --git a/examples/advanced/mockAdvanced.cpp b/examples/advanced/mockAdvanced.cpp index 8faffa9..9a26f84 100644 --- a/examples/advanced/mockAdvanced.cpp +++ b/examples/advanced/mockAdvanced.cpp @@ -9,6 +9,8 @@ #include #include #include +#include + #include "ArduinoUnit.h" #include "ArduinoUnitMock.h" diff --git a/examples/vitro/compile-vitro b/examples/vitro/compile-vitro index c79e8f0..903d4d4 100755 --- a/examples/vitro/compile-vitro +++ b/examples/vitro/compile-vitro @@ -54,14 +54,27 @@ fi # # copy all source files (.ino, .cpp and .h files) into $TMP/src directory # +sources() { + if [ "$(uname)" = "Darwin" ] + then + find -E "$1" -iregex '^.*/[A-Za-z0-9]([-_A-Za-z0-9]*[_A-Za-z0-9])*(\.cpp|\.h|\.ino)$' + else + find "$1" -iregex '^.*/[A-Za-z0-9]\([-_A-Za-z0-9]*[_A-Za-z0-9]\)*\(\.cpp\|\.h\|\.ino\)$' + fi +} + +cpp_sources() { + sources "$@" | egrep '\.cpp$' +} + mkdir -p "${TMP}/src" -(cd ${ARDUINO_TARGET_DIR}; tar cf - $(find -E . -iregex '^.*/[A-Za-z0-9]([-_A-Za-z0-9]*[_A-Za-z0-9])*(\.cpp|\.h|\.ino)$')) | tar -C ${TMP}/src -xf - +(cd ${ARDUINO_TARGET_DIR}; tar cf - $(sources .)) | tar -C "${TMP}/src" -xf - # # copy ArduinoUnit files into $TMP/ArduinoUnit/src directory # mkdir -p "${TMP}/ArduinoUnit/src" -(cd "${ARDUINO_UNIT_DIR}/src"; tar cf - $(find -E . -iregex '^.*/[A-Za-z0-9]([-_A-Za-z0-9]*[_A-Za-z0-9])*(\.cpp|\.h|\.ino)$')) | tar -C "${TMP}/ArduinoUnit/src" -xf - +(cd "${ARDUINO_UNIT_DIR}/src"; tar cf - $(sources .)) | tar -C "${TMP}/ArduinoUnit/src" -xf - ARDUINO_TARGET_EXE="${ARDUINO_TARGET_INO%.ino}" @@ -70,7 +83,7 @@ ARDUINO_TARGET_EXE="${ARDUINO_TARGET_INO%.ino}" # /bin/rm -rf "${ARDUINO_TARGET_EXE}" -g++ -g -std=gnu++11 -o "${TMP}/a.out" -isystem "${TMP}/ArduinoUnit/src" $(find "${TMP}/src" -name '*.cpp') $(find "${TMP}/ArduinoUnit/src" -name '*.cpp') 2>&1 | sed -e "s|${TMP}/src/|${ARDUINO_TARGET_DIR}/|g" | sed -e "s|${TMP}/ArduinoUnit/src/|${ARDUINO_UNIT_DIR}/src/|g" +g++ -g -std=gnu++11 -o "${TMP}/a.out" -isystem "${TMP}/ArduinoUnit/src" $(cpp_sources "${TMP}/src") $(cpp_sources "${TMP}/ArduinoUnit/src") 2>&1 | sed -e "s|${TMP}/src/|${ARDUINO_TARGET_DIR}/|g" | sed -e "s|${TMP}/ArduinoUnit/src/|${ARDUINO_UNIT_DIR}/src/|g" if [ -x "${TMP}/a.out" ] then diff --git a/firmware/au2ju b/firmware/au2ju new file mode 100755 index 0000000..5f9d640 --- /dev/null +++ b/firmware/au2ju @@ -0,0 +1,541 @@ +#!/usr/bin/env python + +import os +import re +import sys +import glob +import threading +import xml.etree.cElementTree as xet + +class Test: + _re = re.compile('.*Test (.*) (skipped|passed|failed)\.') + + def __init__(self, result, assertions,stdout,stderr): + if result != None: + self.name = result.group(1) + self.state = result.group(2) + self.stdout = stdout + self.stderr = stderr + else: + self.name = "unknown" + self.state = "unknown" + self.stdout = stdout + self.stderr = stderr + + if assertions != None: + self.assertions = assertions + else: + self.assertions=[] + + def __str__(self): + return "test(name='"+str(self.name)+"',state='"+str(self.state)+"',assertions="+str(self.assertions) + ",stdout=" + str(self.stdout) + ",stderr=" + str(self.stdout)+")" + + def __repr__(self): + return self.__str__() + + +class Assert: + _re = re.compile('.*Assertion (passed|failed): (.*)\.') + _details = re.compile('(.*), file (.*), line ([0-9]+) *(\[(.*)\])?') + + def __init__(self,result): + if result == None: + self.state = None + self.message = None + self.footnote = None + self.file = None + self.line = None + else: + self.state = result.group(1) + details = Assert._details.match(result.group(2)) + if details != None: + self.message = details.group(1) + self.file = details.group(2) + self.line = int(details.group(3)) + if details.group(5) != None: + self.footnote = details.group(5) + else: + self.footnote = None + else: + self.message = result.group(2) + self.file = None + self.line = None + self.footnote = None + + def __str__(self): + return "assert(state='"+str(self.state)+"',message='"+str(self.message)+"',file='"+str(self.file)+"',line="+str(self.line)+",footnote='" + self.footnote + "')" + + def __repr__(self): + return self.__str__() + +class Summary: + _re = re.compile('.*Test summary: (.*) passed, (.*) failed, and (.*) skipped, out of (.*) test\(s\)\.') + + def __init__(self,result): + if result != None: + self.passed = int(result.group(1)) + self.failed = int(result.group(2)) + self.skipped = int(result.group(3)) + self.count = int(result.group(4)) + else: + self.passed = 0 + self.failed = 0 + self.skipped = 0 + self.count = 0 + + def __str__(self): + return 'summary(passed=' + str(self.passed) + ',failed='+str(self.failed)+',skipped='+str(self.skipped)+',count='+str(self.count)+')' + + def __repr__(self): + return self.__str__() + + +class TestSet: + def __init__(self,result,tests,assertions,stdout,stderr): + self.summary = Summary(result) + if tests != None: + self.tests = tests + else: + self.tests = [] + if len(assertions) > 0: + self.tests.append(Test(None,assertions,stdout,stderr)) + + def __str__(self): + return 'testset(tests='+str(self.tests)+',summary='+str(self.summary)+')' + def __repr__(self): + return self.__str__() + +class Processor: + def __init__(self,parser,stream,isStderr): + self.parser = parser + self.stream = stream + self.isStderr=isStderr + + def run(self): + for line in self.stream: + line=line.rstrip() + self.parser.parseLine(line,self.isStderr) + +class Parser: + def __init__(self): + self.reTest = re.compile('.*Test (.*) (skipped|passed|failed)\.') + self.testSets = [] + self.tests = [] + self.assertions = [] + self.stdout = [] + self.stderr = [] + + def end(self): + if len(self.tests) != 0 or len(self.assertions) != 0: + self.testSets.append(TestSet(None,self.tests,self.assertions,self.stdout,self.stderr)) + self.tests=[] + self.assertions=[] + self.stdout = [] + self.stderr = [] + + def parseLine(self,line,stderr=False): + if line == None: + self.end() + return + if (stderr == False): + self.stdout.append(line) + else: + self.stderr.append(line) + + result=Assert._re.match(line) + if result: + self.assertions.append(Assert(result)) + result=Test._re.match(line) + if result: + self.tests.append(Test(result,self.assertions,self.stdout,self.stderr)) + self.assertions=[] + self.stdout=[] + self.stderr=[] + result=Summary._re.match(line) + if result: + self.testSets.append(TestSet(result,self.tests,self.assertions,self.stdout,self.stderr)) + self.tests=[] + self.assertions=[] + self.stdout = [] + self.stderr = [] + + def process(self,inFromStdout=sys.stdin,inFromStderr=None): + self.testSet = [] + self.assertions = [] + self.tests = [] + self.stdin = [] + self.stderr = [] + + workers = [Processor(self,inFromStdout,False)] + if inFromStderr != None: + worders.append(Processor(self,inFromStderr,True)) + threads = [threading.Thread(target=workers[i].run) for i in range(len(workers))] + for thread in threads: + thread.start() + for thread in threads: + thread.join() + self.end() + +class Summary: + _re = re.compile('.*Test summary: (.*) passed, (.*) failed, and (.*) skipped, out of (.*) test\(s\)\.') + + def __init__(self,result): + if result != None: + self.passed = int(result.group(1)) + self.failed = int(result.group(2)) + self.skipped = int(result.group(3)) + self.count = int(result.group(4)) + else: + self.passed = 0 + self.failed = 0 + self.skipped = 0 + self.count = 0 + + def __str__(self): + return 'summary(passed=' + str(self.passed) + ',failed='+str(self.failed)+',skipped='+str(self.skipped)+',count='+str(self.count)+')' + + def __repr__(self): + return self.__str__() + + +class TestSet: + def __init__(self,result,tests,assertions,stdout,stderr): + self.summary = Summary(result) + if tests != None: + self.tests = tests + else: + self.tests = [] + if len(assertions) > 0: + self.tests.append(Test(None,assertions,stdout,stderr)) + + def __str__(self): + return 'testset(tests='+str(self.tests)+',summary='+str(self.summary)+')' + def __repr__(self): + return self.__str__() + +class Processor: + def __init__(self,parser,stream,isStderr): + self.parser = parser + self.stream = stream + self.isStderr=isStderr + + def run(self): + for line in self.stream: + line=line.rstrip() + self.parser.parseLine(line,self.isStderr) + +class Parser: + def __init__(self): + self.reTest = re.compile('.*Test (.*) (skipped|passed|failed)\.') + self.testSets = [] + self.tests = [] + self.assertions = [] + self.stdout = [] + self.stderr = [] + + def end(self): + if len(self.tests) != 0 or len(self.assertions) != 0: + self.testSets.append(TestSet(None,self.tests,self.assertions,self.stdout,self.stderr)) + self.tests=[] + self.assertions=[] + self.stdout = [] + self.stderr = [] + + def parseLine(self,line,stderr=False): + if line == None: + self.end() + return + if (stderr == False): + self.stdout.append(line) + else: + self.stderr.append(line) + + result=Assert._re.match(line) + if result: + self.assertions.append(Assert(result)) + result=Test._re.match(line) + if result: + self.tests.append(Test(result,self.assertions,self.stdout,self.stderr)) + self.assertions=[] + self.stdout=[] + self.stderr=[] + result=Summary._re.match(line) + if result: + self.testSets.append(TestSet(result,self.tests,self.assertions,self.stdout,self.stderr)) + self.tests=[] + self.assertions=[] + self.stdout = [] + self.stderr = [] + + def process(self,inFromStdout=sys.stdin,inFromStderr=None): + self.testSet = [] + self.assertions = [] + self.tests = [] + self.stdin = [] + self.stderr = [] + + workers = [Processor(self,inFromStdout,False)] + if inFromStderr != None: + worders.append(Processor(self,inFromStderr,True)) + threads = [threading.Thread(target=workers[i].run) for i in range(len(workers))] + for thread in threads: + thread.start() + for thread in threads: + thread.join() + self.end() + +class Summary: + _re = re.compile('.*Test summary: (.*) passed, (.*) failed, and (.*) skipped, out of (.*) test\(s\)\.') + + def __init__(self,result): + if result != None: + self.passed = int(result.group(1)) + self.failed = int(result.group(2)) + self.skipped = int(result.group(3)) + self.count = int(result.group(4)) + else: + self.passed = 0 + self.failed = 0 + self.skipped = 0 + self.count = 0 + + def __str__(self): + return 'summary(passed=' + str(self.passed) + ',failed='+str(self.failed)+',skipped='+str(self.skipped)+',count='+str(self.count)+')' + + def __repr__(self): + return self.__str__() + + +class TestSet: + def __init__(self,result,tests,assertions,stdout,stderr): + self.summary = Summary(result) + if tests != None: + self.tests = tests + else: + self.tests = [] + if len(assertions) > 0: + self.tests.append(Test(None,assertions,stdout,stderr)) + + def __str__(self): + return 'testset(tests='+str(self.tests)+',summary='+str(self.summary)+')' + def __repr__(self): + return self.__str__() + +class Processor: + def __init__(self,parser,stream,isStderr): + self.parser = parser + self.stream = stream + self.isStderr=isStderr + + def run(self): + for line in self.stream: + line=line.rstrip() + self.parser.parseLine(line,self.isStderr) + +class Parser: + def __init__(self): + self.reTest = re.compile('.*Test (.*) (skipped|passed|failed)\.') + self.testSets = [] + self.tests = [] + self.assertions = [] + self.stdout = [] + self.stderr = [] + + def end(self): + if len(self.tests) != 0 or len(self.assertions) != 0: + self.testSets.append(TestSet(None,self.tests,self.assertions,self.stdout,self.stderr)) + self.tests=[] + self.assertions=[] + self.stdout = [] + self.stderr = [] + + def parseLine(self,line,stderr=False): + if line == None: + self.end() + return + if (stderr == False): + self.stdout.append(line) + else: + self.stderr.append(line) + + result=Assert._re.match(line) + if result: + self.assertions.append(Assert(result)) + result=Test._re.match(line) + if result: + self.tests.append(Test(result,self.assertions,self.stdout,self.stderr)) + self.assertions=[] + self.stdout=[] + self.stderr=[] + result=Summary._re.match(line) + if result: + self.testSets.append(TestSet(result,self.tests,self.assertions,self.stdout,self.stderr)) + self.tests=[] + self.assertions=[] + self.stdout = [] + self.stderr = [] + + def process(self,inFromStdout=sys.stdin,inFromStderr=None): + self.testSet = [] + self.assertions = [] + self.tests = [] + self.stdin = [] + self.stderr = [] + + workers = [Processor(self,inFromStdout,False)] + if inFromStderr != None: + worders.append(Processor(self,inFromStderr,True)) + threads = [threading.Thread(target=workers[i].run) for i in range(len(workers))] + for thread in threads: + thread.start() + for thread in threads: + thread.join() + self.end() + +class JUnit4: + def __init__(self): + pass + + def indent(self, elem, level=0): + i = "\n" + level*" " + j = "\n" + (level-1)*" " + + if len(elem): + if not elem.text or not elem.text.strip(): + elem.text = i + " " + if not elem.tail or not elem.tail.strip(): + elem.tail = i + for subelem in elem: + self.indent(subelem, level+1) + if not elem.tail or not elem.tail.strip(): + elem.tail = j + else: + if level and (not elem.tail or not elem.tail.strip()): + elem.tail = j + return elem + + def printTestSets(self,testSets,prettyPrint=True): + doc = self.addTestSets(testSets) + xml = xet.ElementTree(doc) + if prettyPrint: + self.indent(doc) + xml.write(sys.stdout, xml_declaration=True, encoding='utf-8') + + def addTestSets(self,testSets,parent=None): + ans = None + if parent != None: + ans =xet.SubElement(parent,"testsuites") + else: + ans =xet.Element("testsuites") + + for testSet in testSets: + self.addTestSet(testSet,ans) + return ans + + def addTestSet(self,testSet,parent=None): + ans = None + if parent != None: + ans = xet.SubElement(parent,"testsuite") + else: + ans = xet.Element("testsuite") + + ans.set("tests",str(len(testSet.tests))) + + for test in testSet.tests: + self.addTest(test,ans) + + return ans + + def addTest(self,test,parent=None): + ans = None + if parent != None: + ans = xet.SubElement(parent,"testcase") + else: + ans = xet.Element("testcase") + + ans.set("name",test.name) + + if test.state == 'skipped': + xet.SubElement(ans,"skipped") + return + + for assertion in test.assertions: + self.addAssertion(assertion,ans) + + self.addStdout(test.stdout,ans) + self.addStderr(test.stderr,ans) + + def addStdout(Self,stdout,parent=None): + if (len(stdout) == 0): + return None + ans = None + if parent != None: + ans = xet.SubElement(parent,"stdout") + else: + ans = xet.Element("stdout") + + ans.text = "\n" + "\n".join(stdout) + "\n" + return ans + + def addStderr(Self,stderr,parent=None): + if (len(stderr) == 0): + return None + ans = None + if parent != None: + ans = xet.SubElement(parent,"stderr") + else: + ans = xet.Element("stderr") + + ans.text = "\n" + "\n".join(stderr) + return ans + + def addAssertion(self,assertion,parent=None): + ans = None + if (assertion.state == 'passed'): + return None + + if parent != None: + ans = xet.SubElement(parent,"failure") + else: + ans = xet.Element("failure") + + message = assertion.file + ":" + str(assertion.line) + " " + assertion.message + ans.set("message",message) + + text = ["\n"] + + if assertion.file != None: + text.append("File \"" + assertion.file + "\"") + else: + text.append("File None") + + if assertion.line != None: + text.append(", line " + str(assertion.line)) + else: + text.append(", line unknown") + if parent != None: + text.append(", in " + parent.get("name") + "\n") + else: + text.append(", in unknown\n") + text.append(" Assertion failed: " + assertion.message) + if assertion.file != None: + text.append(", file " + assertion.file) + if assertion.line != None: + text.append(", line " + str(assertion.line)) + if (assertion.footnote != None): + text.append(" [" + assertion.footnote + "]") + text.append(".") + text.append("\n") + + ans.text = "".join(text) + + return ans + +def main(): + p = Parser() + p.process() + junit4=JUnit4() + junit4.printTestSets(p.testSets) + +if __name__ == '__main__': + main() diff --git a/firmware/compile-vitro b/firmware/compile-vitro new file mode 100755 index 0000000..903d4d4 --- /dev/null +++ b/firmware/compile-vitro @@ -0,0 +1,96 @@ +#!/bin/bash + +# +# Figure out where arduino libraries are... +# +if [ "$(uname)" = "Darwin" ] +then + ARDUINO_LIBS="$HOME/Documents/Arduino/libraries" +elif [ "$(uname)" = "Linux" ] +then + ARDUINO_LIBS="$HOME/Arduino/libraries" +else + ARDUINO_LIBS="$HOME/My Documents/Arduino/libraries" +fi + +ARDUINO_UNIT_DIR="$ARDUINO_LIBS/ArduinoUnit" + +if [ ! -r "$ARDUINO_UNIT_DIR/src/ArduinoUnit.h" ] +then + echo "Cannot find ArduinoUnit library." + exit 1 +fi + +# +# Figure out what to compile +# +if [ $# -gt 0 ]; then + ARDUINO_TARGET_INO="$1" +else + ARDUINO_TARGET_INO="$(echo *.ino)" +fi + +if [ ! -f "${ARDUINO_TARGET_INO}" ] ; then + echo "must specify ino file" + exit 1 +fi + +ARDUINO_TARGET_DIR=$(dirname "$1") +if [ ! -d "${ARDUINO_TARGET_DIR}" ] ; then + echo "missing directory ${ARDUINO_TARGET_DIR}." + exit 1 +fi + +# +# Make a temp directory to work in (that is removed) +# +if [ "$TMP" = "" ] ; then + TMP="$(mktemp -d)" + trap '{ /bin/rm -rf "${TMP}"; }' EXIT +else + mkdir -p "$TMP" +fi + +# +# copy all source files (.ino, .cpp and .h files) into $TMP/src directory +# +sources() { + if [ "$(uname)" = "Darwin" ] + then + find -E "$1" -iregex '^.*/[A-Za-z0-9]([-_A-Za-z0-9]*[_A-Za-z0-9])*(\.cpp|\.h|\.ino)$' + else + find "$1" -iregex '^.*/[A-Za-z0-9]\([-_A-Za-z0-9]*[_A-Za-z0-9]\)*\(\.cpp\|\.h\|\.ino\)$' + fi +} + +cpp_sources() { + sources "$@" | egrep '\.cpp$' +} + +mkdir -p "${TMP}/src" +(cd ${ARDUINO_TARGET_DIR}; tar cf - $(sources .)) | tar -C "${TMP}/src" -xf - + +# +# copy ArduinoUnit files into $TMP/ArduinoUnit/src directory +# +mkdir -p "${TMP}/ArduinoUnit/src" +(cd "${ARDUINO_UNIT_DIR}/src"; tar cf - $(sources .)) | tar -C "${TMP}/ArduinoUnit/src" -xf - + +ARDUINO_TARGET_EXE="${ARDUINO_TARGET_INO%.ino}" + +# +# compile everything in the temp directory, relabeling filenames errors so they look like they came from the right place +# + +/bin/rm -rf "${ARDUINO_TARGET_EXE}" +g++ -g -std=gnu++11 -o "${TMP}/a.out" -isystem "${TMP}/ArduinoUnit/src" $(cpp_sources "${TMP}/src") $(cpp_sources "${TMP}/ArduinoUnit/src") 2>&1 | sed -e "s|${TMP}/src/|${ARDUINO_TARGET_DIR}/|g" | sed -e "s|${TMP}/ArduinoUnit/src/|${ARDUINO_UNIT_DIR}/src/|g" + +if [ -x "${TMP}/a.out" ] +then + cp "${TMP}/a.out" "${ARDUINO_TARGET_EXE}" +fi +if [ ! -x "${TMP}/a.out" ] +then + echo "compilation failed." + exit 1 +fi diff --git a/firmware/test-vitro b/firmware/test-vitro new file mode 100755 index 0000000..7bccc2f --- /dev/null +++ b/firmware/test-vitro @@ -0,0 +1,44 @@ +#!/bin/bash + +# +# Figure out what to test +# +if [ $# -gt 0 ]; then + ARDUINO_TARGET_INO="$1" +else + ARDUINO_TARGET_INO="$(echo *.ino)" +fi + +if [ ! -f "${ARDUINO_TARGET_INO}" ] ; then + echo "must specify ino file" + exit 1 +fi + +ARDUINO_TARGET_DIR="$(dirname "$ARDUINO_TARGET_INO")" +ARDUINO_TARGET_BASE="$(basename "$ARDUINO_TARGET_INO")" +ARDUINO_TARGET_FILE="${ARDUINO_TARGET_BASE%.ino}" +ARDUINO_TARGET_EXE="$ARDUINO_TARGET_DIR/$ARDUINO_TARGET_FILE" + +/bin/rm -rf "${ARDUINO_TARGET_EXE}.log" "${ARDUINO_TARGET_EXE}.xml" + +if [ ! -x "${ARDUINO_TARGET_EXE}" ] ; then + echo "missing executable '${ARDUINO_TARGET_EXE}' -- did you compile?" + exit 1 +fi + +if [ "$TMP" = "" ] ; then + TMP="$(mktemp -d)" + trap '{ /bin/rm -rf "${TMP}"; }' EXIT +else + mkdir -p "$TMP" +fi + +( "${ARDUINO_TARGET_EXE}" "$@"; echo "$?" > "$TMP/status" ) | tee "${ARDUINO_TARGET_EXE}.log" + +STATUS="$(cat "$TMP/status")" + +if [ -r "${ARDUINO_TARGET_EXE}.log" ] +then + ./au2ju < "${ARDUINO_TARGET_EXE}.log" > "${ARDUINO_TARGET_EXE}.xml" +fi +exit $STATUS From 31fb892ec8296b98db7d749fdc3dfceed85564d4 Mon Sep 17 00:00:00 2001 From: Warren MacEvoy Date: Fri, 4 May 2018 00:36:16 +0545 Subject: [PATCH 19/80] leave .hex artifact --- bin/compile-lib-avr | 3 +++ 1 file changed, 3 insertions(+) diff --git a/bin/compile-lib-avr b/bin/compile-lib-avr index d6dd5c7..d835a0c 100644 --- a/bin/compile-lib-avr +++ b/bin/compile-lib-avr @@ -8,6 +8,9 @@ compile() { echo "compile time error: avr." exit 1 fi + + cp "${ARDUINO_TARGET_HEX}" "${ARDUINO_TARGET_INO%.ino}.hex" + if [ "${ARDUINO_TARGET_UPLOAD}" = "true" -a -e "${ARDUINO_TARGET_PORT}" ] ; then if ! ${ARDUINO_DIR}/hardware/tools/avr/bin/avrdude -C${ARDUINO_DIR}/hardware/tools/avr/etc/avrdude.conf -v -p${ARDUINO_TARGET_BOARD##*cpu=} -cwiring -P"${ARDUINO_TARGET_PORT}" -b${ARDUINO_TARGET_BAUD} -D -Uflash:w:"${ARDUINO_TARGET_HEX}":i then From 07a121868310f16f852c83fad91e4f9864ae59ec Mon Sep 17 00:00:00 2001 From: Warren MacEvoy Date: Fri, 4 May 2018 12:02:08 -0600 Subject: [PATCH 20/80] ci --- ci/bin/arduino_dir | 38 +++++++++++++++ ci/bin/avr_bin | 18 +++++++ ci/bin/avr_root | 18 +++++++ ci/bin/cache_simavr | 52 +++++++++++++++++++++ ci/bin/make_simavr_uno | 104 +++++++++++++++++++++++++++++++++++++++++ ci/bin/simavr_uno | 97 ++++++++++++++++++++++++++++++++++++++ 6 files changed, 327 insertions(+) create mode 100755 ci/bin/arduino_dir create mode 100755 ci/bin/avr_bin create mode 100755 ci/bin/avr_root create mode 100755 ci/bin/cache_simavr create mode 100755 ci/bin/make_simavr_uno create mode 100755 ci/bin/simavr_uno diff --git a/ci/bin/arduino_dir b/ci/bin/arduino_dir new file mode 100755 index 0000000..2c22487 --- /dev/null +++ b/ci/bin/arduino_dir @@ -0,0 +1,38 @@ +#!/bin/bash + +if [ "$(type -t dir)" != "function" ] +then + . "$(cd "$(dirname "${BASH_SOURCE[0]}")"; pwd)"/dir +fi + +if [ "$(type -t os)" != "function" ] +then + . "$(cd "$(dirname "${BASH_SOURCE[0]}")"; pwd)"/os +fi + +if [ "$(type -t versions)" != "function" ] +then + . "$(cd "$(dirname "${BASH_SOURCE[0]}")"; pwd)"/versions +fi + +arduino_dir() { + OS="$(os "$@")" + DIR="$(dir "$@")" + VERSIONS="$(versions "$@")" + + for VERSION in $VERSIONS + do + if [ "$OS" = "macosx" ] + then + ARDUINO_DIR="${DIR}/cache/${VERSION}-${OS}/Arduino.app/Contents/Java" + else + ARDUINO_DIR="${DIR}/cache/${VERSION}-${OS}/arduino-${VERSION}" + fi + echo "$ARDUINO_DIR" + done +} + +if [[ "${BASH_SOURCE[0]}" == "${0}" ]] +then + arduino_dir "$@" +fi diff --git a/ci/bin/avr_bin b/ci/bin/avr_bin new file mode 100755 index 0000000..1fb85bf --- /dev/null +++ b/ci/bin/avr_bin @@ -0,0 +1,18 @@ +#!/bin/bash + +if [ "$(type -t arduino_dir)" != "function" ] +then + . "$(cd "$(dirname "${BASH_SOURCE[0]}")"; pwd)"/arduino_dir +fi + +avr_bin() { + arduino_dir "$@" | while read -r dir + do + echo "$dir/hardware/tools/avr/bin" + done +} + +if [[ "${BASH_SOURCE[0]}" == "${0}" ]] +then + avr_bin "$@" +fi diff --git a/ci/bin/avr_root b/ci/bin/avr_root new file mode 100755 index 0000000..afab721 --- /dev/null +++ b/ci/bin/avr_root @@ -0,0 +1,18 @@ +#!/bin/bash + +if [ "$(type -t arduino_dir)" != "function" ] +then + . "$(cd "$(dirname "${BASH_SOURCE[0]}")"; pwd)"/arduino_dir +fi + +avr_root() { + arduino_dir "$@" | while read -r dir + do + echo "$dir/hardware/tools/avr" + done +} + +if [[ "${BASH_SOURCE[0]}" == "${0}" ]] +then + avr_root "$@" +fi diff --git a/ci/bin/cache_simavr b/ci/bin/cache_simavr new file mode 100755 index 0000000..d5c6031 --- /dev/null +++ b/ci/bin/cache_simavr @@ -0,0 +1,52 @@ +#!/bin/bash + +if [ "$(type -t dir)" != "function" ] +then + . "$(cd "$(dirname "${BASH_SOURCE[0]}")"; pwd)"/dir +fi + +cache_simavr() { + DIR="$(dir "$@")" + + while [ $# -gt 0 ] + do + case "$1" + in + --reload=*) RELOAD=${1#--reload=}; shift;; + --*=*) shift;; + --) shift; break;; + *) break;; + esac + done + + mkdir -p "$DIR/cache" + cd "$DIR/cache" + + if [ -d "simavr/.git" -a "$RELOAD" != "true" ] + then + cd simavr + test -d .git && git reset --hard || /bin/rm -rf .git + test -d .git && git checkout master || /bin/rm -rf .git + test -d .git && git reset --hard || /bin/rm -rf .git + test -d .git && git pull || /bin/rm -rf .git + cd .. + fi + + if [ \( ! -d "simavr/.git" \) -o "$RELOAD" = "true" ] + then + /bin/rm -rf simavr + git clone https://github.com/buserror/simavr.git + fi + + if [ ! -d "simavr/.git" ] + then + /bin/rm -rf simavr + echo "could not obtain simavr repository." + exit 1 + fi +} + +if [[ "${BASH_SOURCE[0]}" == "${0}" ]] +then + cache_simavr "$@" +fi diff --git a/ci/bin/make_simavr_uno b/ci/bin/make_simavr_uno new file mode 100755 index 0000000..38c5b14 --- /dev/null +++ b/ci/bin/make_simavr_uno @@ -0,0 +1,104 @@ +#!/bin/bash -x + +if [ "$(type -t dir)" != "function" ] +then + . "$(cd "$(dirname "${BASH_SOURCE[0]}")"; pwd)"/dir +fi + +if [ "$(type -t os)" != "function" ] +then + . "$(cd "$(dirname "${BASH_SOURCE[0]}")"; pwd)"/os +fi + +if [ "$(type -t versions)" != "function" ] +then + . "$(cd "$(dirname "${BASH_SOURCE[0]}")"; pwd)"/versions +fi + +if [ "$(type -t cache_simavr)" != "function" ] +then + . "$(cd "$(dirname "${BASH_SOURCE[0]}")"; pwd)"/cache_simavr +fi + +if [ "$(type -t avr_root)" != "cache_ide" ] +then + . "$(cd "$(dirname "${BASH_SOURCE[0]}")"; pwd)"/cache_ide +fi + +if [ "$(type -t avr_root)" != "avr_root" ] +then + . "$(cd "$(dirname "${BASH_SOURCE[0]}")"; pwd)"/avr_root +fi + +make_simavr_uno() { + DIR="$(dir "$@")" + OS="$(os "$@")" + VERSIONS="$(versions "$@")" + + while [ $# -gt 0 ] + do + case "$1" + in + --reload=*) RELOAD=${1#--reload=}; shift;; + --*=*) shift;; + --) shift; break;; + *) break;; + esac + done + + if [ ! -d "$DIR/cache/simavr" -o "$RELOAD" = "true" ] + then + if ! cache_simavr --dir="$DIR" --reload="$RELOAD" + then + echo "could not cache simavr" + exit 1 + fi + fi + + for VERSION in $VERSIONS + do + if [ -x "$DIR/cache/${VERSION}-${OS}/simavr/uno" -a "$RELOAD" != "true" ] + then + continue + fi + + mkdir -p "$DIR/cache/$VERSION-$OS/simavr" + + AVR_ROOT="$(avr_root --dir="$DIR" --os="$OS" --version="$VERSION")" + if [ ! -d "$AVR_ROOT" ] + then + cache_ide --dir="$DIR" --os="$OS" --version="$VERSION" --reload="$RELOAD" + fi + if [ ! -d "$AVR_ROOT" ] + then + echo "could not access avr_root='$AVR_ROOT'" + exit 1 + fi + + if [ ! -d "$DIR/cache/${VERSION}-${OS}/simavr" -o "$RELOAD" = "true" ] + then + /bin/rm -rf "$DIR/cache/${VERSION}-${OS}/simavr" + mkdir -p "$DIR/cache/${VERSION}-${OS}/simavr/repo" + tar -C "$DIR/cache/simavr" -cf - . | tar -C "$DIR/cache/${VERSION}-${OS}/simavr/repo" -xf - + fi + + mkdir -p "$DIR/cache/${VERSION}-${OS}/simavr" + if PATH="$AVR_ROOT/bin:$PATH" make -B -C "$DIR/cache/${VERSION}-${OS}/simavr/repo" clean build-simavr + then + if PATH="$AVR_ROOT/bin:$PATH" make -B -C "$DIR/cache/${VERSION}-${OS}/simavr/repo/examples/board_simduino" clean all + then + cp "$DIR/cache/${VERSION}-${OS}/simavr/repo/examples/board_simduino/"obj*/simduino.elf "$DIR/cache/${VERSION}-${OS}/simavr/uno" + fi + fi + if [ ! -x "$DIR/cache/${VERSION}-${OS}/simavr/uno" ] + then + echo "build failed." + exit 1 + fi + done +} + +if [[ "${BASH_SOURCE[0]}" == "${0}" ]] +then + make_simavr_uno "$@" +fi diff --git a/ci/bin/simavr_uno b/ci/bin/simavr_uno new file mode 100755 index 0000000..588a0f9 --- /dev/null +++ b/ci/bin/simavr_uno @@ -0,0 +1,97 @@ +#!/bin/bash + +if [ "$(type -t dir)" != "function" ] +then + . "$(cd "$(dirname "${BASH_SOURCE[0]}")"; pwd)"/dir +fi + +if [ "$(type -t os)" != "function" ] +then + . "$(cd "$(dirname "${BASH_SOURCE[0]}")"; pwd)"/os +fi + +if [ "$(type -t versions)" != "function" ] +then + . "$(cd "$(dirname "${BASH_SOURCE[0]}")"; pwd)"/versions +fi + +simavr_uno_exit() { + for PID in $SIMAVR_UNO_PIDS + do + if ps $PID >/dev/null + then + kill $PID + fi + done + +} + +simavr_uno() { + DIR="$(dir "$@")" + OS="$(os "$@")" + VERSIONS="$(versions "$@")" + HEX="" + + while [ $# -gt 0 ] + do + case "$1" + in + --hex=*) HEX="${1#--hex=}"; shift;; + --*=*) shift;; + --) shift; break;; + *) break;; + esac + done + + INPUT=( "$@" ) + + if [ "$HEX" = "" ] + then + HEX="$(echo *.hex)" + fi + + if [ ! -r "${HEX}" ] ; then + echo "must specify hex file" + exit 1 + fi + + SIMAVR_UNO_PIDS="" + trap simavr_uno_exit EXIT + + for VERSION in $VERSIONS + do + PORT="/tmp/simavr-uart0" + "${DIR}/cache/${VERSION}-${OS}/simavr/uno" "${HEX}" & + PID=$! + if [ "$PID" != "" ] + then + SIMAVR_UNO_PIDS="$SIMAVR_UNO_PIDS $PID" + else + echo "could not launch simavr/uno" + exit 1 + fi + + while [ ! -e "$PORT" ] ; do sleep 0.01 ; done + +# (for input in "${INPUT[@]}" ; do echo -n "$input\r\n" ; done) >> "$PORT" & +# PID=$! +# if [ "$PID" != "" ] +# then +# SIMAVR_UNO_PIDS="$SIMAVR_UNO_PIDS $PID" +# fi + + cat "$PORT" 2>/dev/null | while read -r line + do + echo "$line" + if [[ "$line" =~ "Test summary:" ]] + then + simavr_uno_exit + fi + done + done +} + +if [[ "${BASH_SOURCE[0]}" == "${0}" ]] +then + simavr_uno "$@" +fi From 25797be3e702fc53c299bb95563e0270138a3493 Mon Sep 17 00:00:00 2001 From: Warren MacEvoy Date: Sun, 6 May 2018 06:39:26 -0600 Subject: [PATCH 21/80] test ci --- ci/bin/arduino | 64 ++---------- ci/bin/arduino_dir | 22 ++-- ci/bin/arduino_exe | 39 +++---- ci/bin/avr_bin | 5 +- ci/bin/avr_root | 5 +- ci/bin/cache_ide | 193 ++++++++++++++++++----------------- ci/bin/dir | 14 ++- ci/bin/make_simavr_uno | 101 ++++++++++-------- ci/bin/preferences | 48 ++++++++- ci/bin/simavr_uno | 52 ++++------ ci/bin/sketchbook | 54 ++++++++-- ci/bin/{versions => version} | 16 +-- 12 files changed, 329 insertions(+), 284 deletions(-) rename ci/bin/{versions => version} (56%) diff --git a/ci/bin/arduino b/ci/bin/arduino index 60b3883..c607173 100755 --- a/ci/bin/arduino +++ b/ci/bin/arduino @@ -1,20 +1,5 @@ #!/bin/bash -if [ "$(type -t dir)" != "function" ] -then - . "$(cd "$(dirname "${BASH_SOURCE[0]}")"; pwd)"/dir -fi - -if [ "$(type -t os)" != "function" ] -then - . "$(cd "$(dirname "${BASH_SOURCE[0]}")"; pwd)"/os -fi - -if [ "$(type -t versions)" != "function" ] -then - . "$(cd "$(dirname "${BASH_SOURCE[0]}")"; pwd)"/versions -fi - if [ "$(type -t preferences)" != "function" ] then . "$(cd "$(dirname "${BASH_SOURCE[0]}")"; pwd)"/preferences @@ -38,51 +23,20 @@ fi arduino() { OS="$(os "$@")" DIR="$(dir "$@")" - VERSIONS="$(versions "$@")" + VERSION="$(version "$@")" PREFERENCES="$(preferences "$@")" SKETCHBOOK="$(sketchbook "$@")" - - while [ $# -gt 0 ] - do - case "$1" - in - --background=*) BACKGROUND=${1#--background=}; shift;; - --*=*) shift;; - --) shift; break;; - *) break;; - esac - done + ARDUINO_EXE="$(arduino_exe "$@")" - if [ "$BACKGROUND" = "" ] + if [ ! -r "$ARDUINO_EXE" ] then - BACKGROUND=false + echo "Arduido executable $ARDUINO_EXE missing (caching)..." + if ! cache_ide "$@" + then + exit 1 + fi fi - - PIDS="" - OK=true - for VERSION in $VERSIONS - do - ARDUINO_EXE="$(arduino_exe --os="$OS" -- $VERSION)" - - if [ ! -x "$ARDUINO_EXE" ] - then - if [ "$BACKGROUND" = "true" ] - then - cache_ide --os="$OS" --version="$VERSION" && "$ARDUINO_EXE" --preferences-file "$PREFERENCES" --pref sketchbook.path="$SKETCHBOOK" --pref update.check=false "$@" & - PIDS="$PIDS $!" - else - cache_ide --os="$OS" --version="$VERSION" && "$ARDUINO_EXE" --preferences-file "$PREFERENCES" --pref sketchbook.path="$SKETCHBOOK" --pref update.check=false "$@" - fi - else - if [ "$BACKGROUND" = "true" ] - then - "$ARDUINO_EXE" --preferences-file "$PREFERENCES" --pref sketchbook.path="$SKETCHBOOK" --pref update.check=false "$@" & - PIDS="$PIDS $!" - else - "$ARDUINO_EXE" "$@" - fi - fi - done + "$ARDUINO_EXE" --preferences-file "$PREFERENCES" --pref sketchbook.path="$SKETCHBOOK" --pref update.check=false "$@" } if [[ "${BASH_SOURCE[0]}" == "${0}" ]] diff --git a/ci/bin/arduino_dir b/ci/bin/arduino_dir index 2c22487..3b27b61 100755 --- a/ci/bin/arduino_dir +++ b/ci/bin/arduino_dir @@ -10,26 +10,22 @@ then . "$(cd "$(dirname "${BASH_SOURCE[0]}")"; pwd)"/os fi -if [ "$(type -t versions)" != "function" ] +if [ "$(type -t version)" != "function" ] then - . "$(cd "$(dirname "${BASH_SOURCE[0]}")"; pwd)"/versions + . "$(cd "$(dirname "${BASH_SOURCE[0]}")"; pwd)"/version fi arduino_dir() { OS="$(os "$@")" DIR="$(dir "$@")" - VERSIONS="$(versions "$@")" + VERSION="$(version "$@")" - for VERSION in $VERSIONS - do - if [ "$OS" = "macosx" ] - then - ARDUINO_DIR="${DIR}/cache/${VERSION}-${OS}/Arduino.app/Contents/Java" - else - ARDUINO_DIR="${DIR}/cache/${VERSION}-${OS}/arduino-${VERSION}" - fi - echo "$ARDUINO_DIR" - done + if [ "$OS" = "macosx" ] + then + ARDUINO_DIR="${DIR}/cache/${VERSION}-${OS}/Arduino.app/Contents/Java" + else + ARDUINO_DIR="${DIR}/cache/${VERSION}-${OS}/arduino-${VERSION}" + fi } if [[ "${BASH_SOURCE[0]}" == "${0}" ]] diff --git a/ci/bin/arduino_exe b/ci/bin/arduino_exe index b1040a0..7410253 100755 --- a/ci/bin/arduino_exe +++ b/ci/bin/arduino_exe @@ -1,18 +1,18 @@ #!/bin/bash -if [ "$(type -t dir)" != "function" ] +if [ "$(type -t os)" != "function" ] then - . "$(cd "$(dirname "${BASH_SOURCE[0]}")"; pwd)"/dir + . "$(cd "$(dirname "${BASH_SOURCE[0]}")"; pwd)"/os fi -if [ "$(type -t os)" != "function" ] +if [ "$(type -t version)" != "function" ] then - . "$(cd "$(dirname "${BASH_SOURCE[0]}")"; pwd)"/os + . "$(cd "$(dirname "${BASH_SOURCE[0]}")"; pwd)"/version fi -if [ "$(type -t versions)" != "function" ] +if [ "$(type -t dir_cache)" != "function" ] then - . "$(cd "$(dirname "${BASH_SOURCE[0]}")"; pwd)"/versions + . "$(cd "$(dirname "${BASH_SOURCE[0]}")"; pwd)"/dir_cache fi arduino_exe() { @@ -21,24 +21,19 @@ arduino_exe() { echo "$ARDUINO_EXE" return fi - OS="$(os "$@")" - DIR="$(dir "$@")" - VERSIONS="$(versions "$@")" + VERSION="$(version "$@")" + DIR_CACHE="$(dir_cache "$@")" - for VERSION in $VERSIONS - do - if [ "$OS" = "macosx" ] - then - ARDUINO_EXE="${DIR}/cache/${VERSION}-${OS}/Arduino.app/Contents/MacOS/Arduino" - elif [ "$OS" = "windows" ] - then - ARDUINO_EXE="${DIR}/cache/${VERSION}-${OS}/arduino-${VERSION}/arduino.exe" - else - ARDUINO_EXE="${DIR}/cache/${VERSION}-${OS}/arduino-${VERSION}/arduino" - fi - echo "$ARDUINO_EXE" - done + if [ "$OS" = "macosx" ] + then + echo "${DIR_CACHE}/Arduino.app/Contents/MacOS/Arduino" + elif [ "$OS" = "windows" ] + then + echo "${DIR_CACHE}/arduino-${VERSION}/arduino.exe" + else + echo "${DIR_CACHE}/arduino-${VERSION}/arduino" + fi } if [[ "${BASH_SOURCE[0]}" == "${0}" ]] diff --git a/ci/bin/avr_bin b/ci/bin/avr_bin index 1fb85bf..b672b70 100755 --- a/ci/bin/avr_bin +++ b/ci/bin/avr_bin @@ -6,10 +6,7 @@ then fi avr_bin() { - arduino_dir "$@" | while read -r dir - do - echo "$dir/hardware/tools/avr/bin" - done + echo "$(arduino_dir "$@")/hardware/tools/avr/bin" } if [[ "${BASH_SOURCE[0]}" == "${0}" ]] diff --git a/ci/bin/avr_root b/ci/bin/avr_root index afab721..f6d158b 100755 --- a/ci/bin/avr_root +++ b/ci/bin/avr_root @@ -6,10 +6,7 @@ then fi avr_root() { - arduino_dir "$@" | while read -r dir - do - echo "$dir/hardware/tools/avr" - done + echo "$(arduino_dir "$@")/hardware/tools/avr" } if [[ "${BASH_SOURCE[0]}" == "${0}" ]] diff --git a/ci/bin/cache_ide b/ci/bin/cache_ide index 87432d5..13b2c7f 100755 --- a/ci/bin/cache_ide +++ b/ci/bin/cache_ide @@ -1,24 +1,19 @@ #!/bin/bash -if [ "$(type -t os)" != "function" ] -then - . "$(cd "$(dirname "${BASH_SOURCE[0]}")"; pwd)"/os -fi - -if [ "$(type -t dir)" != "function" ] -then - . "$(cd "$(dirname "${BASH_SOURCE[0]}")"; pwd)"/dir -fi - -if [ "$(type -t versions)" != "function" ] -then - . "$(cd "$(dirname "${BASH_SOURCE[0]}")"; pwd)"/versions +for inc in os dir dir_cache version arduino_exe +do + if [ "$(type -t $inc)" != "function" ] + then + . "$(cd "$(dirname "${BASH_SOURCE[0]}")"; pwd)"/$inc + fi fi cache_ide() { OS="$(os "$@")" DIR="$(dir "$@")" - VERSIONS="$(versions "$@")" + CACHE_DIR="$(cache_dir "$@")" + VERSION="$(version "$@")" + ARDUINO_EXE="$(arduino_exe "$@")" while [ $# -gt 0 ] do @@ -34,10 +29,14 @@ cache_ide() { esac done - CACHE="${DIR}/cache" - if [ ! -d "$CACHE" ] + if [ -r "$ARDUINO_EXE" && "${RELOAD}" != "true" ] then - mkdir -p "$CACHE" + exit 0 + fi + + if [ ! -d "$CACHE_DIR" ] + then + mkdir -p "$CACHE_DIR" fi PORTABLE="${DIR}/portable" @@ -75,99 +74,107 @@ cache_ide() { TIMEOUT=10 fi - for VERSION in $VERSIONS - do - ARCHIVE="arduino-${VERSION}-${OS}.${EXTENSION}" - CHECKSUM="arduino-${VERSION}.sha512sum.txt" + ARCHIVE="arduino-${VERSION}-${OS}.${EXTENSION}" + CHECKSUM="arduino-${VERSION}.sha512sum.txt" + + if [ $RELOAD = "true" ] + then + /bin/rm -rf "${CACHE}/${CHECKSUM}" + fi - OK=false - for TRY in $(seq $TRIES) - do - if [ -r "${CACHE}/${CHECKSUM}" ] - then - if grep -q "${ARCHIVE}" "${CACHE}/${CHECKSUM}" - then - OK=true - break - fi - fi - curl --connect-timeout "$TIMEOUT" -o "${CACHE}/${CHECKSUM}" "https://downloads.arduino.cc/${CHECKSUM}" - done - if [ "$OK" != "true" ] + OK=false + for TRY in $(seq $TRIES) + do + if [ -r "${CACHE}/${CHECKSUM}" ] then - echo "Could not download checksum ${CHECKSUM}" - /bin/rm -rf "${CACHE}/${CHECKSUM}" - continue - fi - - grep "${ARCHIVE}" "${CACHE}/${CHECKSUM}" > "${CACHE}/${ARCHIVE}.sha512sum.txt" - - OK=false - for TRY in $(seq $TRIES) - do - if [ -r "${CACHE}/${ARCHIVE}" ] + if grep -q "${ARCHIVE}" "${CACHE}/${CHECKSUM}" then - if cd "$CACHE" && shasum -a512 -c "${ARCHIVE}.sha512sum.txt" > /dev/null - then - OK=true - break - fi + OK=true + break fi - /bin/rm -rf "${CACHE}/${ARCHIVE}" - curl --connect-timeout "$TIMEOUT" -o "${CACHE}/${ARCHIVE}" "https://downloads.arduino.cc/${ARCHIVE}" - done - - if [ "$OK" != "true" ] - then - echo "Could not download archive ${ARCHIVE}" - /bin/rm -rf "${CACHE}/${ARCHIVE}" - /bin/rm -rf "${CACHE}/${VERSION}-${OS}" - continue - fi - - if [ "${RELOAD}" = "true" ] - then - /bin/rm -rf "${CACHE}/${VERSION}-${OS}" fi + curl --connect-timeout "$TIMEOUT" -o "${CACHE}/${CHECKSUM}" "https://downloads.arduino.cc/${CHECKSUM}" + done + + if [ "$OK" != "true" ] + then + echo "Download ${CHECKSUM} failed." + exit 1 + fi - if [ "${EXTENSION}" = "zip" ] + if [ ! grep "${ARCHIVE}" "${CACHE}/${CHECKSUM}" > "${CACHE}/${ARCHIVE}.sha512sum.txt" ] + then + echo "No checksum for $ARCHIVE in $CHECKSUM." + exit 1 + fi + + OK=false + for TRY in $(seq $TRIES) + do + if [ -r "${CACHE}/${ARCHIVE}" ] then - if [ ! -d "${CACHE}/${VERSION}-${OS}" ] + if cd "$CACHE" && shasum -a512 -c "${ARCHIVE}.sha512sum.txt" > /dev/null then - (cd "${CACHE}" && mkdir -p "${VERSION}-${OS}" && unzip -d "${VERSION}-${OS}" -a -o "${ARCHIVE}" > /dev/null) - if [ "${OS}" = "macosx" ] - then - (cd "${CACHE}/${VERSION}-${OS}/Arduino.app/Contents/Java"; ln -s ../../../../../portable portable) - else - (cd "${CACHE}/${VERSION}-${OS}/arduino-${VERSION}"; ln -s ../../../portable portable) - fi - fi - else - if [ ! -d "${CACHE}/${VERSION}-${OS}" ] - then - (cd "${CACHE}" && mkdir -p "${VERSION}-${OS}" && tar -C "${VERSION}-${OS}" -xf "${ARCHIVE}") - (cd "${CACHE}/${VERSION}-${OS}/arduino-${VERSION}"; ln -s ../../../portable portable) + OK=true + break fi fi + /bin/rm -rf "${CACHE}/${ARCHIVE}" + curl --connect-timeout "$TIMEOUT" -o "${CACHE}/${ARCHIVE}" "https://downloads.arduino.cc/${ARCHIVE}" done + + if [ "$OK" != "true" ] + then + echo "Download ${ARCHIVE} failed." + exit 1 + fi + + pushd "$CACHE_DIR" + if [ "${EXTENSION}" = "zip" ] + then + unzip -a -o "${ARCHIVE}" > /dev/null + else + tar -xf "${ARCHIVE}" + fi - OK=true - for VERSION in $VERSIONS - do - if [ ! -d "${CACHE}/${VERSION}-${OS}" ] - then - OK=false - break - fi - done + if [ "${OS}" = "macosx" ] + then + pushd /Arduino.app/Contents/Java + ln -s ../../../../../portable portable + popd + else + pushd arduino-${VERSION} + ln -s ../../../portable portable + popd + fi - if [ "$OK" = "false" ] + popd + + if [ ! -r "$ARDUINO_EXE" ] then - exit 1 + echo "executable $ARDUINO_EXE missing." + exit 1 fi } +cache_ide_self_test() { + for os in macosx windows linux64 linux32 linuxarm + do + if ! cache_ide --os=$os "$@" + then + echo "$os failed." + exit 1 + fi + done +} + if [[ "${BASH_SOURCE[0]}" == "${0}" ]] then - cache_ide "$@" + if [ "$1" == "--self-test" ] + then + shift + cache_ide_self_test "$@" + else + cache_ide "$@" + fi fi diff --git a/ci/bin/dir b/ci/bin/dir index c87dcfd..abc981f 100755 --- a/ci/bin/dir +++ b/ci/bin/dir @@ -24,7 +24,19 @@ dir() { echo "${DIR}" } +dir_self_test() { + if [ "$(dir --dir='test me')" != "test me" ]; then exit 1; fi + if [ "$(dir)" == "test me" ] ; then exit 1; fi + if [ "$(dir)" == "" ] ; then exit 1; fi + echo "dir_self_test: ok" +} + if [[ "${BASH_SOURCE[0]}" == "${0}" ]] then - dir "$@" + if [ "$1" == "--self-test" ] + then + dir_self_test "$@" + else + dir "$@" + fi fi diff --git a/ci/bin/make_simavr_uno b/ci/bin/make_simavr_uno index 38c5b14..123557d 100755 --- a/ci/bin/make_simavr_uno +++ b/ci/bin/make_simavr_uno @@ -30,72 +30,93 @@ then . "$(cd "$(dirname "${BASH_SOURCE[0]}")"; pwd)"/avr_root fi +if [ "$(type -t arduino_exe)" != "function" ] +then + . "$(cd "$(dirname "${BASH_SOURCE[0]}")"; pwd)"/arduino_exe +fi + +if [ "$(type -t cache_simavr)" != "function" ] +then + . "$(cd "$(dirname "${BASH_SOURCE[0]}")"; pwd)"/cache_simavr +fi + make_simavr_uno() { DIR="$(dir "$@")" OS="$(os "$@")" - VERSIONS="$(versions "$@")" + VERSION="$(version "$@")" + ARDUINO_EXE="$(arduino_exe "$@")" + AVR_ROOT="$(avr_root "$@")" while [ $# -gt 0 ] do case "$1" in --reload=*) RELOAD=${1#--reload=}; shift;; + --branch=*) BRANCH=${1#--branch=}; shift;; --*=*) shift;; --) shift; break;; *) break;; esac done - if [ ! -d "$DIR/cache/simavr" -o "$RELOAD" = "true" ] + if [ $BRANCH = "" ] then - if ! cache_simavr --dir="$DIR" --reload="$RELOAD" - then - echo "could not cache simavr" - exit 1 - fi + BRANCH=master fi - - for VERSION in $VERSIONS - do - if [ -x "$DIR/cache/${VERSION}-${OS}/simavr/uno" -a "$RELOAD" != "true" ] - then - continue - fi - mkdir -p "$DIR/cache/$VERSION-$OS/simavr" - - AVR_ROOT="$(avr_root --dir="$DIR" --os="$OS" --version="$VERSION")" - if [ ! -d "$AVR_ROOT" ] - then - cache_ide --dir="$DIR" --os="$OS" --version="$VERSION" --reload="$RELOAD" - fi - if [ ! -d "$AVR_ROOT" ] + if [ -x "$DIR/cache/${VERSION}-${OS}/simavr/uno" -a "$RELOAD" != "true" ] + then + exit 0 + fi + + if [ ! -r "$ARDUINO_EXE" ] + then + echo "Arduido executable $ARDUINO_EXE missing (caching)..." + if ! cache_ide "$@" then - echo "could not access avr_root='$AVR_ROOT'" exit 1 fi + fi - if [ ! -d "$DIR/cache/${VERSION}-${OS}/simavr" -o "$RELOAD" = "true" ] - then - /bin/rm -rf "$DIR/cache/${VERSION}-${OS}/simavr" - mkdir -p "$DIR/cache/${VERSION}-${OS}/simavr/repo" - tar -C "$DIR/cache/simavr" -cf - . | tar -C "$DIR/cache/${VERSION}-${OS}/simavr/repo" -xf - - fi + if [ ! -d "$AVR_ROOT" ] + then + echo "Missing avr tools directory $AVR_ROOT." + exit 1 + fi - mkdir -p "$DIR/cache/${VERSION}-${OS}/simavr" - if PATH="$AVR_ROOT/bin:$PATH" make -B -C "$DIR/cache/${VERSION}-${OS}/simavr/repo" clean build-simavr - then - if PATH="$AVR_ROOT/bin:$PATH" make -B -C "$DIR/cache/${VERSION}-${OS}/simavr/repo/examples/board_simduino" clean all - then - cp "$DIR/cache/${VERSION}-${OS}/simavr/repo/examples/board_simduino/"obj*/simduino.elf "$DIR/cache/${VERSION}-${OS}/simavr/uno" - fi - fi - if [ ! -x "$DIR/cache/${VERSION}-${OS}/simavr/uno" ] + if [ ! -d "$DIR/cache/simavr" -o "$RELOAD" = "true" ] + then + echo "Missing simavr repository (caching)..." + if ! cache_simavr --dir=$DIR --reload=$RELOAD then - echo "build failed." exit 1 fi - done + fi + + /bin/rm -rf "$DIR/cache/${VERSION}-${OS}/simavr/repo" + mkdir -p "$DIR/cache/${VERSION}-${OS}/simavr/repo" + tar -C "$DIR/cache/simavr" -cf - . | tar -C "$DIR/cache/${VERSION}-${OS}/simavr/repo" -xf - + (cd "$DIR/cache/${VERSION}-${OS}/simavr/repo"; git checkout -f "$BRANCH") + + if ! PATH="$AVR_ROOT/bin:$PATH" make -B -C "$DIR/cache/${VERSION}-${OS}/simavr/repo" clean build-simavr + then + echo "build-simavr target failed." + exit 1 + fi + + if ! PATH="$AVR_ROOT/bin:$PATH" make -B -C "$DIR/cache/${VERSION}-${OS}/simavr/repo/examples/board_simduino" clean all + then + echo "build board_simduino target failed." + exit 1 + fi + + cp "$DIR/cache/${VERSION}-${OS}/simavr/repo/examples/board_simduino/"obj*/simduino.elf "$DIR/cache/${VERSION}-${OS}/simavr/uno" + + if [ ! -x "$DIR/cache/${VERSION}-${OS}/simavr/uno" ] + then + echo "build failed." + exit 1 + fi } if [[ "${BASH_SOURCE[0]}" == "${0}" ]] diff --git a/ci/bin/preferences b/ci/bin/preferences index 22862f9..25862be 100755 --- a/ci/bin/preferences +++ b/ci/bin/preferences @@ -1,19 +1,57 @@ #!/bin/bash -if [ "$(type -t dir)" != "function" ] -then - . "$(cd "$(dirname "${BASH_SOURCE[0]}")"; pwd)"/dir +for inc in dir +do + if [ "$(type -t $inc)" != "function" ] + then + . "$(cd "$(dirname "${BASH_SOURCE[0]}")"; pwd)"/$inc + fi fi preferences() { - if [ "$PREFERENCES" == "" ] + DIR="$(dir "$@")" + + while [ $# -gt 0 ] + do + case "$1" + in + --preferences=*) PREFERENCES=${1#--preferences=}; shift;; + --*=*) shift;; + --) shift; break;; + *) break;; + esac + done + + if [ "$PREFERENCES" = "" ] then PREFERENCES="$(dir "$@")/portable/preferences.txt" fi + echo "$PREFERENCES" } +preferences_self_test() { + if [ "$(preferences --preferences='test me')" != "test me" ] + then + echo "test me failed" + exit 1 + fi + + if ! preferences | egrep -q "preferences.txt$" + then + echo "suffix test failed." + exit 1 + fi + echo "preferences_self_test: ok" +} + + if [[ "${BASH_SOURCE[0]}" == "${0}" ]] then - preferences "$@" + if [ "$1" == "--self-test" ] + then + preferences_self_test "$@" + else + preferences "$@" + fi fi diff --git a/ci/bin/simavr_uno b/ci/bin/simavr_uno index 588a0f9..2b0e687 100755 --- a/ci/bin/simavr_uno +++ b/ci/bin/simavr_uno @@ -10,9 +10,9 @@ then . "$(cd "$(dirname "${BASH_SOURCE[0]}")"; pwd)"/os fi -if [ "$(type -t versions)" != "function" ] +if [ "$(type -t version)" != "function" ] then - . "$(cd "$(dirname "${BASH_SOURCE[0]}")"; pwd)"/versions + . "$(cd "$(dirname "${BASH_SOURCE[0]}")"; pwd)"/version fi simavr_uno_exit() { @@ -29,13 +29,15 @@ simavr_uno_exit() { simavr_uno() { DIR="$(dir "$@")" OS="$(os "$@")" - VERSIONS="$(versions "$@")" + VERSION="$(version "$@")" HEX="" while [ $# -gt 0 ] do case "$1" in + --background=*) BACKGROUND=${1#--background=}; shift;; + --ino=*) HEX="${1#--ino=}.hex"; shift;; --hex=*) HEX="${1#--hex=}"; shift;; --*=*) shift;; --) shift; break;; @@ -58,36 +60,26 @@ simavr_uno() { SIMAVR_UNO_PIDS="" trap simavr_uno_exit EXIT - for VERSION in $VERSIONS + PORT="/tmp/simavr-uart0" + "${DIR}/cache/${VERSION}-${OS}/simavr/uno" "${HEX}" & + PID=$! + if [ "$PID" != "" ] + then + SIMAVR_UNO_PIDS="$SIMAVR_UNO_PIDS $PID" + else + echo "could not launch simavr/uno" + exit 1 + fi + + while [ ! -e "$PORT" ] ; do sleep 0.01 ; done + + cat "$PORT" 2>/dev/null | while read -r line do - PORT="/tmp/simavr-uart0" - "${DIR}/cache/${VERSION}-${OS}/simavr/uno" "${HEX}" & - PID=$! - if [ "$PID" != "" ] + echo "$line" + if [[ "$line" =~ "Test summary:" ]] then - SIMAVR_UNO_PIDS="$SIMAVR_UNO_PIDS $PID" - else - echo "could not launch simavr/uno" - exit 1 + simavr_uno_exit fi - - while [ ! -e "$PORT" ] ; do sleep 0.01 ; done - -# (for input in "${INPUT[@]}" ; do echo -n "$input\r\n" ; done) >> "$PORT" & -# PID=$! -# if [ "$PID" != "" ] -# then -# SIMAVR_UNO_PIDS="$SIMAVR_UNO_PIDS $PID" -# fi - - cat "$PORT" 2>/dev/null | while read -r line - do - echo "$line" - if [[ "$line" =~ "Test summary:" ]] - then - simavr_uno_exit - fi - done done } diff --git a/ci/bin/sketchbook b/ci/bin/sketchbook index 374c250..d14998c 100755 --- a/ci/bin/sketchbook +++ b/ci/bin/sketchbook @@ -1,24 +1,60 @@ -#!/bin/bash +#!/bin/bash -x -if [ "$(type -t dir)" != "function" ] -then - . "$(cd "$(dirname "${BASH_SOURCE[0]}")"; pwd)"/dir -fi +for inc in dir +do + if [ "$(type -t $inc)" != "function" ] + then + echo "including $inc" + . "$(cd "$(dirname "${BASH_SOURCE[0]}")"; pwd)"/$inc + fi +done sketchbook() { + DIR="$(dir "$@")" + + while [ $# -gt 0 ] + do + case "$1" + in + --sketchbook=*) SKETCHBOOK=${1#--sketchbook=}; shift;; + --*=*) shift;; + --) shift; break;; + *) break;; + esac + done + if [ "$SKETCHBOOK" == "" ] then SKETCHBOOK="$(dir "$@")/portable/sketchbook" fi - if [ ! -d "$SKETCHBOOK" ] + echo "$SKETCHBOOK" +} + +sketchbook_self_test() { + if [ "$(sketchbook --sketchbook='test me')" != "test me" ] then - mkdir -p "$SKETCHBOOK" + echo "test me failed" + exit 1 fi - echo "$SKETCHBOOK" + + if [ "$(sketchbook)" == "test me" ] + then + echo "default failed." + exit 1 + fi + + echo "sketchbook_self_test: ok" + } if [[ "${BASH_SOURCE[0]}" == "${0}" ]] then - sketchbook "$@" + if [ "$1" == "--self-test" ] + then + shift + sketchbook_self_test "$@" + else + sketchbook "$@" + fi fi diff --git a/ci/bin/versions b/ci/bin/version similarity index 56% rename from ci/bin/versions rename to ci/bin/version index 3690421..db38bf5 100755 --- a/ci/bin/versions +++ b/ci/bin/version @@ -1,9 +1,9 @@ #!/bin/bash -versions() { - if [ "$VERSIONS" != "" ] +version() { + if [ "$VERSION" != "" ] then - echo $VERSIONS + echo $VERSION return fi @@ -11,21 +11,21 @@ versions() { do case "$1" in - --version=*) VERSIONS="$VERSIONS ${1#--version=}"; shift;; + --version=*) VERSION="${1#--version=}"; shift;; --*=*) shift;; --) shift; break;; *) break;; esac done - if [ "$VERSIONS" = "" ] + if [ "$VERSION" = "" ] then - VERSIONS="1.8.5" + VERSION="1.8.5" fi - echo $VERSIONS + echo $VERSION } if [[ "${BASH_SOURCE[0]}" == "${0}" ]] then - versions "$@" + version "$@" fi From 82384d6d82997de02e79ec42d7f771e4790762c7 Mon Sep 17 00:00:00 2001 From: Warren MacEvoy Date: Sun, 6 May 2018 06:46:32 -0600 Subject: [PATCH 22/80] ci_self_test --- ci/bin/ci_self_test | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100755 ci/bin/ci_self_test diff --git a/ci/bin/ci_self_test b/ci/bin/ci_self_test new file mode 100755 index 0000000..f00a2aa --- /dev/null +++ b/ci/bin/ci_self_test @@ -0,0 +1,26 @@ +#!/bin/bash + +CI_SELF_TESTS=(dir preferences sketchbook cache_ide) + +for ci_test in "${CI_SELF_TESTS[@]}" +do + if [ "$(type -t $ci_test)" != "function" ] + then + . "$(cd "$(dirname "${BASH_SOURCE[0]}")"; pwd)"/$ci_test + fi +done + +ci_self_test() { + for ci_test in "${CI_SELF_TESTS[@]}" + do + echo "testing $ci_test." + ${ci_test}_self_test "$@" + done + echo "ci_self_test ok" +} + +if [[ "${BASH_SOURCE[0]}" == "${0}" ]] +then + ci_self_test "$@" +fi + From b9c9abbaf9a672e53cc9ecc01a50f8d3407bd059 Mon Sep 17 00:00:00 2001 From: Warren MacEvoy Date: Sun, 6 May 2018 06:49:04 -0600 Subject: [PATCH 23/80] dir_cache --- ci/bin/dir_cache | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) create mode 100755 ci/bin/dir_cache diff --git a/ci/bin/dir_cache b/ci/bin/dir_cache new file mode 100755 index 0000000..0f2aef9 --- /dev/null +++ b/ci/bin/dir_cache @@ -0,0 +1,29 @@ +#!/bin/bash + +if [ "$(type -t dir)" != "function" ] +then + . "$(cd "$(dirname "${BASH_SOURCE[0]}")"; pwd)"/dir +fi + +if [ "$(type -t os)" != "function" ] +then + . "$(cd "$(dirname "${BASH_SOURCE[0]}")"; pwd)"/os +fi + +if [ "$(type -t version)" != "function" ] +then + . "$(cd "$(dirname "${BASH_SOURCE[0]}")"; pwd)"/version +fi + +dir_cache() { + OS="$(os "$@")" + DIR="$(dir "$@")" + VERSION="$(version "$@")" + + echo "${DIR}/cache/${VERSION}-${OS}" +} + +if [[ "${BASH_SOURCE[0]}" == "${0}" ]] +then + dir_cache "$@" +fi From 92579d3ab5c1c6f27dcb38e9e59b1592c8a93824 Mon Sep 17 00:00:00 2001 From: Warren MacEvoy Date: Sun, 6 May 2018 19:12:17 +0545 Subject: [PATCH 24/80] simpler includes cache_ide --- bin/compile-avr | 21 ---------------- ci/bin/arduino_exe | 43 ++++++++++++++++++--------------- ci/bin/cache_ide | 59 ++++++++++++++++++++++++--------------------- ci/bin/ci_self_test | 2 +- ci/bin/dir | 2 +- ci/bin/dir_cache | 56 ++++++++++++++++++++++++++++++------------ ci/bin/preferences | 5 ++-- ci/bin/sketchbook | 5 ++-- 8 files changed, 102 insertions(+), 91 deletions(-) delete mode 100644 bin/compile-avr diff --git a/bin/compile-avr b/bin/compile-avr deleted file mode 100644 index 9914f62..0000000 --- a/bin/compile-avr +++ /dev/null @@ -1,21 +0,0 @@ -#!/bin/bash -x - -THIS_DIR="$(cd "$(dirname "$0")"; pwd)" -. $THIS_DIR/compile-setup - -compile() { - ${ARDUINO_DIR}/arduino-builder -dump-prefs -logger=machine -hardware ${ARDUINO_DIR}/hardware -hardware ${ARDUINO_PACKAGES} -hardware ${ARDUINO_HARDWARE} -tools ${ARDUINO_DIR}/tools-builder -tools ${ARDUINO_DIR}/hardware/tools/avr -tools ${ARDUINO_PACKAGES} -built-in-libraries ${ARDUINO_DIR}/libraries -libraries ${ARDUINO_LIBS} -fqbn=${ARDUINO_TARGET_BOARD} -ide-version=10802 -build-path ${TMP}/build -warnings=all -build-cache ${TMP}/cache -prefs=build.warn_data_percentage=75 -prefs=runtime.tools.avr-gcc.path=${ARDUINO_DIR}/hardware/tools/avr -prefs=runtime.tools.arduinoOTA.path=${ARDUINO_DIR}/hardware/tools/avr -prefs=runtime.tools.avrdude.path=${ARDUINO_DIR}/hardware/tools/avr -verbose "${TMP}/src/$(basename ${ARDUINO_TARGET_INO})" 2>&1 | sed -e "s|${TMP}/build/sketch/|${ARDUINO_TARGET_DIR}/|g" - - ${ARDUINO_DIR}/arduino-builder -compile -logger=machine -hardware ${ARDUINO_DIR}/hardware -hardware ${ARDUINO_PACKAGES} -hardware ${ARDUINO_HARDWARE} -tools ${ARDUINO_DIR}/tools-builder -tools ${ARDUINO_DIR}/hardware/tools/avr -tools ${ARDUINO_PACKAGES} -built-in-libraries ${ARDUINO_DIR}/libraries -libraries ${ARDUINO_LIBS} -fqbn=${ARDUINO_TARGET_BOARD} -ide-version=10802 -build-path ${TMP}/build -warnings=all -build-cache ${TMP}/cache -prefs=build.warn_data_percentage=75 -prefs=runtime.tools.avr-gcc.path=${ARDUINO_DIR}/hardware/tools/avr -prefs=runtime.tools.arduinoOTA.path=${ARDUINO_DIR}/hardware/tools/avr -prefs=runtime.tools.avrdude.path=${ARDUINO_DIR}/hardware/tools/avr -verbose "${TMP}/src/$(basename ${ARDUINO_TARGET_INO})" 2>&1 | sed -e "s|${TMP}/build/sketch/|${ARDUINO_TARGET_DIR}/|g" - if [ ! -f "${ARDUINO_TARGET_HEX}" ] ; then - echo "compile time error." - exit 1 - fi - if [ "${ARDUINO_TARGET_UPLOAD}" = "true" -a -e "${ARDUINO_TARGET_PORT}" ] ; then - if ! ${ARDUINO_DIR}/hardware/tools/avr/bin/avrdude -C${ARDUINO_DIR}/hardware/tools/avr/etc/avrdude.conf -v -p${ARDUINO_TARGET_BOARD##*cpu=} -cwiring -P"${ARDUINO_TARGET_PORT}" -b${ARDUINO_TARGET_BAUD} -D -Uflash:w:"${ARDUINO_TARGET_HEX}":i - then - echo "upload error." - exit 1 - fi - fi -} diff --git a/ci/bin/arduino_exe b/ci/bin/arduino_exe index 7410253..ad56c0d 100755 --- a/ci/bin/arduino_exe +++ b/ci/bin/arduino_exe @@ -1,26 +1,14 @@ #!/bin/bash -if [ "$(type -t os)" != "function" ] -then - . "$(cd "$(dirname "${BASH_SOURCE[0]}")"; pwd)"/os -fi - -if [ "$(type -t version)" != "function" ] -then - . "$(cd "$(dirname "${BASH_SOURCE[0]}")"; pwd)"/version -fi - -if [ "$(type -t dir_cache)" != "function" ] -then - . "$(cd "$(dirname "${BASH_SOURCE[0]}")"; pwd)"/dir_cache -fi - -arduino_exe() { - if [ "$ARDUINO_EXE" != "" ] +for inc in os dir_cache version +do + if [ "$(type -t $inc)" != "function" ] then - echo "$ARDUINO_EXE" - return + . "$(cd "$(dirname "${BASH_SOURCE[0]}")"; pwd)"/$inc fi +done + +arduino_exe() { OS="$(os "$@")" VERSION="$(version "$@")" DIR_CACHE="$(dir_cache "$@")" @@ -36,7 +24,22 @@ arduino_exe() { fi } +arduino_exe_self_test() { + if ! arduino_exe | egrep -i -q "arduino\.[^.]*$" + then + echo "name test failed." + exit 1 + fi + echo "arduino_exe ok" +} + if [[ "${BASH_SOURCE[0]}" == "${0}" ]] then - arduino_exe "$@" + if [ "$1" == "--self-test" ] + then + shift + arduino_exe_self_test "$@" + else + arduino_exe "$@" + fi fi diff --git a/ci/bin/cache_ide b/ci/bin/cache_ide index 13b2c7f..dc21694 100755 --- a/ci/bin/cache_ide +++ b/ci/bin/cache_ide @@ -1,4 +1,4 @@ -#!/bin/bash +#!/bin/bash -x for inc in os dir dir_cache version arduino_exe do @@ -6,12 +6,12 @@ do then . "$(cd "$(dirname "${BASH_SOURCE[0]}")"; pwd)"/$inc fi -fi +done cache_ide() { OS="$(os "$@")" DIR="$(dir "$@")" - CACHE_DIR="$(cache_dir "$@")" + DIR_CACHE="$(dir_cache "$@")" VERSION="$(version "$@")" ARDUINO_EXE="$(arduino_exe "$@")" @@ -29,28 +29,28 @@ cache_ide() { esac done - if [ -r "$ARDUINO_EXE" && "${RELOAD}" != "true" ] + if [ -r "${ARDUINO_EXE}" -a "${RELOAD}" != "true" ] then exit 0 fi - if [ ! -d "$CACHE_DIR" ] + if [ ! -d "${DIR_CACHE}" ] then - mkdir -p "$CACHE_DIR" + mkdir -p "${DIR_CACHE}" fi PORTABLE="${DIR}/portable" - if [ ! -d "$PORTABLE" ] + if [ ! -d "${PORTABLE}" ] then - mkdir -p "$PORTABLE" + mkdir -p "${PORTABLE}" fi - if [ "$EXTENSION" = "" ] + if [ "${EXTENSION}" = "" ] then - if [ "$OS" = "macosx" -o "$OS" = "windows" ] + if [ "${OS}" = "macosx" -o "${OS}" = "windows" ] then EXTENSION="zip" - elif [ "${OS#linux}" != "$OS" ] + elif [ "${OS#linux}" != "${OS}" ] then EXTENSION="tar.xz" else @@ -59,31 +59,33 @@ cache_ide() { fi fi - if [ "$TRIES" = "" ] + if [ "${TRIES}" = "" ] then TRIES=3 fi - if [ "$RELOAD" = "" ] + if [ "${RELOAD}" = "" ] then RELOAD=false fi - if [ "$TIMEOUT" = "" ] + if [ "${TIMEOUT}" = "" ] then TIMEOUT=10 fi ARCHIVE="arduino-${VERSION}-${OS}.${EXTENSION}" CHECKSUM="arduino-${VERSION}.sha512sum.txt" + CACHE="${DIR}/cache" + mkdir -p "${CACHE}" - if [ $RELOAD = "true" ] + if [ "${RELOAD}" = "true" ] then /bin/rm -rf "${CACHE}/${CHECKSUM}" fi OK=false - for TRY in $(seq $TRIES) + for TRY in $(seq "${TRIES}") do if [ -r "${CACHE}/${CHECKSUM}" ] then @@ -102,44 +104,45 @@ cache_ide() { exit 1 fi - if [ ! grep "${ARCHIVE}" "${CACHE}/${CHECKSUM}" > "${CACHE}/${ARCHIVE}.sha512sum.txt" ] + if ! grep "${ARCHIVE}" "${CACHE}/${CHECKSUM}" > "${CACHE}/${ARCHIVE}.sha512sum.txt" then - echo "No checksum for $ARCHIVE in $CHECKSUM." + echo "No checksum for ${ARCHIVE} in ${CHECKSUM}." exit 1 fi OK=false - for TRY in $(seq $TRIES) + for TRY in $(seq "${TRIES}") do if [ -r "${CACHE}/${ARCHIVE}" ] then - if cd "$CACHE" && shasum -a512 -c "${ARCHIVE}.sha512sum.txt" > /dev/null + if cd "${CACHE}" && shasum -a512 -c "${ARCHIVE}.sha512sum.txt" > /dev/null then OK=true break fi fi /bin/rm -rf "${CACHE}/${ARCHIVE}" - curl --connect-timeout "$TIMEOUT" -o "${CACHE}/${ARCHIVE}" "https://downloads.arduino.cc/${ARCHIVE}" + curl --connect-timeout "${TIMEOUT}" -o "${CACHE}/${ARCHIVE}" "https://downloads.arduino.cc/${ARCHIVE}" done - if [ "$OK" != "true" ] + if [ "${OK}" != "true" ] then echo "Download ${ARCHIVE} failed." exit 1 fi - pushd "$CACHE_DIR" + mkdir -p "${DIR_CACHE}" + pushd "${DIR_CACHE}" if [ "${EXTENSION}" = "zip" ] then - unzip -a -o "${ARCHIVE}" > /dev/null + unzip -a -o "${CACHE}/${ARCHIVE}" > /dev/null else - tar -xf "${ARCHIVE}" + tar -xf "${CACHE}/${ARCHIVE}" fi if [ "${OS}" = "macosx" ] then - pushd /Arduino.app/Contents/Java + pushd Arduino.app/Contents/Java ln -s ../../../../../portable portable popd else @@ -150,9 +153,9 @@ cache_ide() { popd - if [ ! -r "$ARDUINO_EXE" ] + if [ ! -r "${ARDUINO_EXE}" ] then - echo "executable $ARDUINO_EXE missing." + echo "executable ${ARDUINO_EXE} missing." exit 1 fi } diff --git a/ci/bin/ci_self_test b/ci/bin/ci_self_test index f00a2aa..c0ae8f3 100755 --- a/ci/bin/ci_self_test +++ b/ci/bin/ci_self_test @@ -1,6 +1,6 @@ #!/bin/bash -CI_SELF_TESTS=(dir preferences sketchbook cache_ide) +CI_SELF_TESTS=(dir dir_cache preferences sketchbook arduino_exe cache_ide) for ci_test in "${CI_SELF_TESTS[@]}" do diff --git a/ci/bin/dir b/ci/bin/dir index abc981f..3dc66c5 100755 --- a/ci/bin/dir +++ b/ci/bin/dir @@ -28,7 +28,7 @@ dir_self_test() { if [ "$(dir --dir='test me')" != "test me" ]; then exit 1; fi if [ "$(dir)" == "test me" ] ; then exit 1; fi if [ "$(dir)" == "" ] ; then exit 1; fi - echo "dir_self_test: ok" + echo "dir ok" } if [[ "${BASH_SOURCE[0]}" == "${0}" ]] diff --git a/ci/bin/dir_cache b/ci/bin/dir_cache index 0f2aef9..1f65d35 100755 --- a/ci/bin/dir_cache +++ b/ci/bin/dir_cache @@ -1,19 +1,12 @@ #!/bin/bash -if [ "$(type -t dir)" != "function" ] -then - . "$(cd "$(dirname "${BASH_SOURCE[0]}")"; pwd)"/dir -fi - -if [ "$(type -t os)" != "function" ] -then - . "$(cd "$(dirname "${BASH_SOURCE[0]}")"; pwd)"/os -fi - -if [ "$(type -t version)" != "function" ] -then - . "$(cd "$(dirname "${BASH_SOURCE[0]}")"; pwd)"/version -fi +for inc in dir os version +do + if [ "$(type -t $inc)" != "function" ] + then + . "$(cd "$(dirname "${BASH_SOURCE[0]}")"; pwd)"/$inc + fi +done dir_cache() { OS="$(os "$@")" @@ -23,7 +16,40 @@ dir_cache() { echo "${DIR}/cache/${VERSION}-${OS}" } +dir_cache_self_test() { + if [ "$(dir_cache)" = "" ] + then + echo "default failed" + exit 1 + fi + + if [ "$(dir_cache --dir=a)" = "$(dir_cache --dir=b)" ] + then + echo "dir failed" + exit 1 + fi + + if [ "$(dir_cache --os=a)" = "$(dir_cache --os=b)" ] + then + echo "os failed" + exit 1 + fi + + if [ "$(dir_cache --version=a)" = "$(dir_cache --version=b)" ] + then + echo "version failed" + exit 1 + fi + + echo "dir_cache_self_test: ok" +} + if [[ "${BASH_SOURCE[0]}" == "${0}" ]] then - dir_cache "$@" + if [ "$1" == "--self-test" ] + then + dir_cache_self_test "$@" + else + dir_cache "$@" + fi fi diff --git a/ci/bin/preferences b/ci/bin/preferences index 25862be..5b0e52f 100755 --- a/ci/bin/preferences +++ b/ci/bin/preferences @@ -6,7 +6,7 @@ do then . "$(cd "$(dirname "${BASH_SOURCE[0]}")"; pwd)"/$inc fi -fi +done preferences() { DIR="$(dir "$@")" @@ -42,7 +42,7 @@ preferences_self_test() { echo "suffix test failed." exit 1 fi - echo "preferences_self_test: ok" + echo "preferences ok" } @@ -50,6 +50,7 @@ if [[ "${BASH_SOURCE[0]}" == "${0}" ]] then if [ "$1" == "--self-test" ] then + shift preferences_self_test "$@" else preferences "$@" diff --git a/ci/bin/sketchbook b/ci/bin/sketchbook index d14998c..dd7ef01 100755 --- a/ci/bin/sketchbook +++ b/ci/bin/sketchbook @@ -1,10 +1,9 @@ -#!/bin/bash -x +#!/bin/bash for inc in dir do if [ "$(type -t $inc)" != "function" ] then - echo "including $inc" . "$(cd "$(dirname "${BASH_SOURCE[0]}")"; pwd)"/$inc fi done @@ -44,7 +43,7 @@ sketchbook_self_test() { exit 1 fi - echo "sketchbook_self_test: ok" + echo "sketchbook ok" } From 3616ecba887b325e7b2153eae3f64870c6b960b0 Mon Sep 17 00:00:00 2001 From: Warren MacEvoy Date: Sun, 6 May 2018 10:56:54 -0600 Subject: [PATCH 25/80] compile_vitro --- ci/bin/compile_vitro | 96 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 96 insertions(+) create mode 100755 ci/bin/compile_vitro diff --git a/ci/bin/compile_vitro b/ci/bin/compile_vitro new file mode 100755 index 0000000..903d4d4 --- /dev/null +++ b/ci/bin/compile_vitro @@ -0,0 +1,96 @@ +#!/bin/bash + +# +# Figure out where arduino libraries are... +# +if [ "$(uname)" = "Darwin" ] +then + ARDUINO_LIBS="$HOME/Documents/Arduino/libraries" +elif [ "$(uname)" = "Linux" ] +then + ARDUINO_LIBS="$HOME/Arduino/libraries" +else + ARDUINO_LIBS="$HOME/My Documents/Arduino/libraries" +fi + +ARDUINO_UNIT_DIR="$ARDUINO_LIBS/ArduinoUnit" + +if [ ! -r "$ARDUINO_UNIT_DIR/src/ArduinoUnit.h" ] +then + echo "Cannot find ArduinoUnit library." + exit 1 +fi + +# +# Figure out what to compile +# +if [ $# -gt 0 ]; then + ARDUINO_TARGET_INO="$1" +else + ARDUINO_TARGET_INO="$(echo *.ino)" +fi + +if [ ! -f "${ARDUINO_TARGET_INO}" ] ; then + echo "must specify ino file" + exit 1 +fi + +ARDUINO_TARGET_DIR=$(dirname "$1") +if [ ! -d "${ARDUINO_TARGET_DIR}" ] ; then + echo "missing directory ${ARDUINO_TARGET_DIR}." + exit 1 +fi + +# +# Make a temp directory to work in (that is removed) +# +if [ "$TMP" = "" ] ; then + TMP="$(mktemp -d)" + trap '{ /bin/rm -rf "${TMP}"; }' EXIT +else + mkdir -p "$TMP" +fi + +# +# copy all source files (.ino, .cpp and .h files) into $TMP/src directory +# +sources() { + if [ "$(uname)" = "Darwin" ] + then + find -E "$1" -iregex '^.*/[A-Za-z0-9]([-_A-Za-z0-9]*[_A-Za-z0-9])*(\.cpp|\.h|\.ino)$' + else + find "$1" -iregex '^.*/[A-Za-z0-9]\([-_A-Za-z0-9]*[_A-Za-z0-9]\)*\(\.cpp\|\.h\|\.ino\)$' + fi +} + +cpp_sources() { + sources "$@" | egrep '\.cpp$' +} + +mkdir -p "${TMP}/src" +(cd ${ARDUINO_TARGET_DIR}; tar cf - $(sources .)) | tar -C "${TMP}/src" -xf - + +# +# copy ArduinoUnit files into $TMP/ArduinoUnit/src directory +# +mkdir -p "${TMP}/ArduinoUnit/src" +(cd "${ARDUINO_UNIT_DIR}/src"; tar cf - $(sources .)) | tar -C "${TMP}/ArduinoUnit/src" -xf - + +ARDUINO_TARGET_EXE="${ARDUINO_TARGET_INO%.ino}" + +# +# compile everything in the temp directory, relabeling filenames errors so they look like they came from the right place +# + +/bin/rm -rf "${ARDUINO_TARGET_EXE}" +g++ -g -std=gnu++11 -o "${TMP}/a.out" -isystem "${TMP}/ArduinoUnit/src" $(cpp_sources "${TMP}/src") $(cpp_sources "${TMP}/ArduinoUnit/src") 2>&1 | sed -e "s|${TMP}/src/|${ARDUINO_TARGET_DIR}/|g" | sed -e "s|${TMP}/ArduinoUnit/src/|${ARDUINO_UNIT_DIR}/src/|g" + +if [ -x "${TMP}/a.out" ] +then + cp "${TMP}/a.out" "${ARDUINO_TARGET_EXE}" +fi +if [ ! -x "${TMP}/a.out" ] +then + echo "compilation failed." + exit 1 +fi From 7e12acccdc91dd7ddd320884727a295c66aa41ff Mon Sep 17 00:00:00 2001 From: Warren MacEvoy Date: Sun, 6 May 2018 23:48:14 +0545 Subject: [PATCH 26/80] compile --- ci/bin/compile_sources | 56 +++++++++++++ ci/bin/compile_vitro | 178 +++++++++++++++++++++++------------------ 2 files changed, 157 insertions(+), 77 deletions(-) create mode 100755 ci/bin/compile_sources diff --git a/ci/bin/compile_sources b/ci/bin/compile_sources new file mode 100755 index 0000000..2062ea6 --- /dev/null +++ b/ci/bin/compile_sources @@ -0,0 +1,56 @@ +#!/bin/bash + +compile_sources() { + if [ "$(uname)" = "Darwin" ] + then + find -E "$1" -iregex '^.*/[A-Za-z0-9]([-_A-Za-z0-9]*[_A-Za-z0-9])*(\.cpp|\.h|\.ino)$' + else + find "$1" -iregex '^.*/[A-Za-z0-9]\([-_A-Za-z0-9]*[_A-Za-z0-9]\)*\(\.cpp\|\.h\|\.ino\)$' + fi +} + +compile_sources_self_test() { + TMP="$(mktemp -d)" + trap 'rm -rf "$TMP"' EXIT + mkdir -p $TMP/s/x + mkdir -p $TMP/s/x/y + touch $TMP/s/a + touch $TMP/s/a.cpp + touch $TMP/s/._a.cpp + touch $TMP/s/b.ino + touch $TMP/s/c.txt + touch $TMP/s/x/y/c.h + + compile_sources "$TMP/s" > "$TMP/out" + + for has in s/a.cpp s/b.ino s/x/y/c.h + do + if ! grep -q $has "$TMP/out" + then + echo $has + exit 1 + fi + done + + for miss in ._a.cpp c.txt + do + if grep -q $miss "$TMP/out" + then + echo $miss + exit 1 + fi + done + + echo "compile_sources ok" +} + +if [[ "${BASH_SOURCE[0]}" == "${0}" ]] +then + if [ "$1" == "--self-test" ] + then + shift + compile_sources_self_test "$@" + else + compile_sources "$@" + fi +fi diff --git a/ci/bin/compile_vitro b/ci/bin/compile_vitro index 903d4d4..63cfbd9 100755 --- a/ci/bin/compile_vitro +++ b/ci/bin/compile_vitro @@ -1,96 +1,120 @@ #!/bin/bash -# -# Figure out where arduino libraries are... -# -if [ "$(uname)" = "Darwin" ] -then - ARDUINO_LIBS="$HOME/Documents/Arduino/libraries" -elif [ "$(uname)" = "Linux" ] -then - ARDUINO_LIBS="$HOME/Arduino/libraries" -else - ARDUINO_LIBS="$HOME/My Documents/Arduino/libraries" -fi +for inc in dir sketchbook compile_sources +do + if [ "$(type -t $inc)" != "function" ] + then + . "$(cd "$(dirname "${BASH_SOURCE[0]}")"; pwd)"/$inc + fi +done -ARDUINO_UNIT_DIR="$ARDUINO_LIBS/ArduinoUnit" +compile_vitro() { + DIR="$(dir "$@")" + SKETCHBOOK="$(sketchbook "$@")" + while [ $# -gt 0 ] + do + case "$1" + in + --ino=*) INO=${1#--ino=}; shift;; + --tmp=*) TMP=${1#--ino=}; shift;; + --*=*) shift;; + --) shift; break;; + *) break;; + esac + done + ARDUINO_LIBS="${SKETCHBOOK}/libraries" + ARDUINO_UNIT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.."; pwd)" + if [ ! -r "$ARDUINO_UNIT_DIR/src/ArduinoUnit.h" ] + then + echo "Cannot find ArduinoUnit library." + exit 1 + fi -if [ ! -r "$ARDUINO_UNIT_DIR/src/ArduinoUnit.h" ] -then - echo "Cannot find ArduinoUnit library." - exit 1 -fi + if [ "${INO}" = "" ]; then + INO="$(echo *.ino)" + fi + + if [ ! -f "${INO}" ] ; then + echo "must specify ino file" + exit 1 + fi -# -# Figure out what to compile -# -if [ $# -gt 0 ]; then - ARDUINO_TARGET_INO="$1" -else - ARDUINO_TARGET_INO="$(echo *.ino)" -fi + ARDUINO_TARGET_DIR="$(dirname "${INO}")" + if [ ! -d "${ARDUINO_TARGET_DIR}" ] ; then + echo "missing directory ${ARDUINO_TARGET_DIR}." + exit 1 + fi -if [ ! -f "${ARDUINO_TARGET_INO}" ] ; then - echo "must specify ino file" - exit 1 -fi + # + # Make a temp directory to work in (that is removed) + # + if [ "$TMP" = "" ] ; then + TMP="$(mktemp -d)" + EXITS+="/bin/rm -rf '${TMP}'" + trap 'for action in "${EXITS[@]}" ; do $action ; done' EXIT + else + mkdir -p "$TMP" + fi + + + mkdir -p "${TMP}/src" + (cd ${ARDUINO_TARGET_DIR}; tar cf - $(compile_sources .)) | tar -C "${TMP}/src" -xf - -ARDUINO_TARGET_DIR=$(dirname "$1") -if [ ! -d "${ARDUINO_TARGET_DIR}" ] ; then - echo "missing directory ${ARDUINO_TARGET_DIR}." - exit 1 -fi + # + # copy ArduinoUnit files into $TMP/ArduinoUnit/src directory + # + mkdir -p "${TMP}/ArduinoUnit/src" + (cd "${ARDUINO_UNIT_DIR}/src"; tar cf - $(compile_sources .)) | tar -C "${TMP}/ArduinoUnit/src" -xf - -# -# Make a temp directory to work in (that is removed) -# -if [ "$TMP" = "" ] ; then - TMP="$(mktemp -d)" - trap '{ /bin/rm -rf "${TMP}"; }' EXIT -else - mkdir -p "$TMP" -fi + ARDUINO_TARGET_EXE="${ARDUINO_TARGET_INO%.ino}" + + # + # compile everything in the temp directory, relabeling filenames errors so they look like they came from the right place + # + + /bin/rm -rf "${ARDUINO_TARGET_EXE}" + g++ -g -std=gnu++11 -o "${TMP}/a.out" -isystem "${TMP}/ArduinoUnit/src" $(compile_sources "${TMP}/src"|egrep '\.cpp$') $(compile_sources "${TMP}/ArduinoUnit/src" |egrep '\.cpp$') 2>&1 | sed -e "s|${TMP}/src/|${ARDUINO_TARGET_DIR}/|g" | sed -e "s|${TMP}/ArduinoUnit/src/|${ARDUINO_UNIT_DIR}/src/|g" -# -# copy all source files (.ino, .cpp and .h files) into $TMP/src directory -# -sources() { - if [ "$(uname)" = "Darwin" ] + if [ -x "${TMP}/a.out" ] then - find -E "$1" -iregex '^.*/[A-Za-z0-9]([-_A-Za-z0-9]*[_A-Za-z0-9])*(\.cpp|\.h|\.ino)$' - else - find "$1" -iregex '^.*/[A-Za-z0-9]\([-_A-Za-z0-9]*[_A-Za-z0-9]\)*\(\.cpp\|\.h\|\.ino\)$' + cp "${TMP}/a.out" "${ARDUINO_TARGET_EXE}" + fi + if [ ! -x "${TMP}/a.out" ] + then + echo "compilation failed." + exit 1 fi } -cpp_sources() { - sources "$@" | egrep '\.cpp$' -} - -mkdir -p "${TMP}/src" -(cd ${ARDUINO_TARGET_DIR}; tar cf - $(sources .)) | tar -C "${TMP}/src" -xf - - -# -# copy ArduinoUnit files into $TMP/ArduinoUnit/src directory -# -mkdir -p "${TMP}/ArduinoUnit/src" -(cd "${ARDUINO_UNIT_DIR}/src"; tar cf - $(sources .)) | tar -C "${TMP}/ArduinoUnit/src" -xf - +compile_vitro_self_test() { + local TMP="$(mktemp -d)" + EXITS+="/bin/rm -rf '${TMP}'" + trap 'for action in "${EXITS[@]}" ; do $action ; done' EXIT -ARDUINO_TARGET_EXE="${ARDUINO_TARGET_INO%.ino}" + cp -r "$(cd "$(dirname "${BASH_SOURCE[0]}")"; pwd)"/../../examples/vitro "${TMP}" + /bin/rm -rf "$TMP/vitro/*.hex" -# -# compile everything in the temp directory, relabeling filenames errors so they look like they came from the right place -# + if ! compile_vitro --ino="$TMP/vitro/vitro.ino" + then + echo "compile" + exit 1 + fi -/bin/rm -rf "${ARDUINO_TARGET_EXE}" -g++ -g -std=gnu++11 -o "${TMP}/a.out" -isystem "${TMP}/ArduinoUnit/src" $(cpp_sources "${TMP}/src") $(cpp_sources "${TMP}/ArduinoUnit/src") 2>&1 | sed -e "s|${TMP}/src/|${ARDUINO_TARGET_DIR}/|g" | sed -e "s|${TMP}/ArduinoUnit/src/|${ARDUINO_UNIT_DIR}/src/|g" + if ! $TMP/vitro/vitro | grep -q "Test summary:" + then + echo "execute" + exit 1 + fi + echo "compile_vitro ok" +} -if [ -x "${TMP}/a.out" ] +if [[ "${BASH_SOURCE[0]}" == "${0}" ]] then - cp "${TMP}/a.out" "${ARDUINO_TARGET_EXE}" -fi -if [ ! -x "${TMP}/a.out" ] -then - echo "compilation failed." - exit 1 + if [ "$1" == "--self-test" ] + then + shift + compile_vitro_self_test "$@" + else + compile_vitro "$@" + fi fi From 00737e48e5e8a03a9cb23cf3dc2fcdf1d464315c Mon Sep 17 00:00:00 2001 From: Warren MacEvoy Date: Sun, 6 May 2018 23:48:46 +0545 Subject: [PATCH 27/80] ci mac --- ci/bin/arduino | 48 ++++++++++++++----------- ci/bin/arduino_dir | 43 +++++++++++++--------- ci/bin/avr_bin | 26 +++++++++++++- ci/bin/avr_root | 28 ++++++++++++--- ci/bin/cache_ide | 7 ++-- ci/bin/cache_simavr | 34 +++++++++++++++--- ci/bin/ci_self_test | 3 +- ci/bin/make_simavr_uno | 81 +++++++++++++++++++----------------------- ci/bin/simavr_uno | 40 ++++++++++++--------- 9 files changed, 196 insertions(+), 114 deletions(-) diff --git a/ci/bin/arduino b/ci/bin/arduino index c607173..10d58bb 100755 --- a/ci/bin/arduino +++ b/ci/bin/arduino @@ -1,24 +1,12 @@ #!/bin/bash -if [ "$(type -t preferences)" != "function" ] -then - . "$(cd "$(dirname "${BASH_SOURCE[0]}")"; pwd)"/preferences -fi - -if [ "$(type -t sketchbook)" != "function" ] -then - . "$(cd "$(dirname "${BASH_SOURCE[0]}")"; pwd)"/sketchbook -fi - -if [ "$(type -t arduino_exe)" != "function" ] -then - . "$(cd "$(dirname "${BASH_SOURCE[0]}")"; pwd)"/arduino_exe -fi - -if [ "$(type -t cache_ide)" != "function" ] -then - . "$(cd "$(dirname "${BASH_SOURCE[0]}")"; pwd)"/cache_ide -fi +for inc in preferences sketchbook arduino_exe cache_ide +do + if [ "$(type -t $inc)" != "function" ] + then + . "$(cd "$(dirname "${BASH_SOURCE[0]}")"; pwd)"/$inc + fi +done arduino() { OS="$(os "$@")" @@ -39,7 +27,27 @@ arduino() { "$ARDUINO_EXE" --preferences-file "$PREFERENCES" --pref sketchbook.path="$SKETCHBOOK" --pref update.check=false "$@" } +arduino_self_test() { + arduino "$@" & + PID="$!" + if [ "${PID}" = "" ] + then + echo "no launch" + exit 1 + fi + kill $PID + + echo "arduino ok" +} + if [[ "${BASH_SOURCE[0]}" == "${0}" ]] then - arduino "$@" + if [ "$1" == "--self-test" ] + then + shift + arduino_self_test "$@" + else + arduino_ide "$@" + fi fi + diff --git a/ci/bin/arduino_dir b/ci/bin/arduino_dir index 3b27b61..e2fe27f 100755 --- a/ci/bin/arduino_dir +++ b/ci/bin/arduino_dir @@ -1,19 +1,12 @@ #!/bin/bash -if [ "$(type -t dir)" != "function" ] -then - . "$(cd "$(dirname "${BASH_SOURCE[0]}")"; pwd)"/dir -fi - -if [ "$(type -t os)" != "function" ] -then - . "$(cd "$(dirname "${BASH_SOURCE[0]}")"; pwd)"/os -fi - -if [ "$(type -t version)" != "function" ] -then - . "$(cd "$(dirname "${BASH_SOURCE[0]}")"; pwd)"/version -fi +for inc in dir os version +do + if [ "$(type -t $inc)" != "function" ] + then + . "$(cd "$(dirname "${BASH_SOURCE[0]}")"; pwd)"/$inc + fi +done arduino_dir() { OS="$(os "$@")" @@ -22,13 +15,29 @@ arduino_dir() { if [ "$OS" = "macosx" ] then - ARDUINO_DIR="${DIR}/cache/${VERSION}-${OS}/Arduino.app/Contents/Java" + echo "${DIR}/cache/${VERSION}-${OS}/Arduino.app/Contents/Java" else - ARDUINO_DIR="${DIR}/cache/${VERSION}-${OS}/arduino-${VERSION}" + echo "${DIR}/cache/${VERSION}-${OS}/arduino-${VERSION}" + fi +} + +arduino_dir_self_test() { + if [ "$(arduino_dir)" = "" ] + then + echo null + exit 1 fi + + echo "arduino_dir ok" } if [[ "${BASH_SOURCE[0]}" == "${0}" ]] then - arduino_dir "$@" + if [ "$1" == "--self-test" ] + then + shift + arduino_dir_self_test "$@" + else + arduino_dir "$@" + fi fi diff --git a/ci/bin/avr_bin b/ci/bin/avr_bin index b672b70..428fd66 100755 --- a/ci/bin/avr_bin +++ b/ci/bin/avr_bin @@ -1,5 +1,14 @@ #!/bin/bash +for inc in arduino_dir +do + if [ "$(type -t $inc)" != "function" ] + then + . "$(cd "$(dirname "${BASH_SOURCE[0]}")"; pwd)"/$inc + fi +done + + if [ "$(type -t arduino_dir)" != "function" ] then . "$(cd "$(dirname "${BASH_SOURCE[0]}")"; pwd)"/arduino_dir @@ -9,7 +18,22 @@ avr_bin() { echo "$(arduino_dir "$@")/hardware/tools/avr/bin" } +avr_bin_self_test() { + if [ "$(avr_bin)" = "" ] + then + echo null + exit 1 + fi + echo "avr_bin ok" +} + if [[ "${BASH_SOURCE[0]}" == "${0}" ]] then - avr_bin "$@" + if [ "$1" == "--self-test" ] + then + shift + avr_bin_self_test "$@" + else + avr_bin "$@" + fi fi diff --git a/ci/bin/avr_root b/ci/bin/avr_root index f6d158b..0aa1056 100755 --- a/ci/bin/avr_root +++ b/ci/bin/avr_root @@ -1,15 +1,33 @@ #!/bin/bash -if [ "$(type -t arduino_dir)" != "function" ] -then - . "$(cd "$(dirname "${BASH_SOURCE[0]}")"; pwd)"/arduino_dir -fi +for inc in arduino_dir +do + if [ "$(type -t $inc)" != "function" ] + then + . "$(cd "$(dirname "${BASH_SOURCE[0]}")"; pwd)"/$inc + fi +done avr_root() { echo "$(arduino_dir "$@")/hardware/tools/avr" } +avr_root_self_test() { + if [ "$(avr_root)" = "" ] + then + echo null + exit 1 + fi + echo "avr_root ok" +} + if [[ "${BASH_SOURCE[0]}" == "${0}" ]] then - avr_root "$@" + if [ "$1" == "--self-test" ] + then + shift + avr_root_self_test "$@" + else + avr_root "$@" + fi fi diff --git a/ci/bin/cache_ide b/ci/bin/cache_ide index dc21694..d1661fd 100755 --- a/ci/bin/cache_ide +++ b/ci/bin/cache_ide @@ -1,4 +1,4 @@ -#!/bin/bash -x +#!/bin/bash for inc in os dir dir_cache version arduino_exe do @@ -31,7 +31,7 @@ cache_ide() { if [ -r "${ARDUINO_EXE}" -a "${RELOAD}" != "true" ] then - exit 0 + return fi if [ ! -d "${DIR_CACHE}" ] @@ -161,7 +161,7 @@ cache_ide() { } cache_ide_self_test() { - for os in macosx windows linux64 linux32 linuxarm + for os in macosx windows linux64 do if ! cache_ide --os=$os "$@" then @@ -169,6 +169,7 @@ cache_ide_self_test() { exit 1 fi done + echo "cache_ide ok" } if [[ "${BASH_SOURCE[0]}" == "${0}" ]] diff --git a/ci/bin/cache_simavr b/ci/bin/cache_simavr index d5c6031..22529dd 100755 --- a/ci/bin/cache_simavr +++ b/ci/bin/cache_simavr @@ -1,9 +1,12 @@ #!/bin/bash -if [ "$(type -t dir)" != "function" ] -then - . "$(cd "$(dirname "${BASH_SOURCE[0]}")"; pwd)"/dir -fi +for inc in dir +do + if [ "$(type -t $inc)" != "function" ] + then + . "$(cd "$(dirname "${BASH_SOURCE[0]}")"; pwd)"/$inc + fi +done cache_simavr() { DIR="$(dir "$@")" @@ -46,7 +49,28 @@ cache_simavr() { fi } +cache_simavr_self_test() { + if cache_simavr + then + if [ ! -r "$(dir)/cache/simavr/.git/config" ] + then + echo "no git" + exit 1 + fi + else + echo "cache failed." + exit 1 + fi + echo "cache_simavr ok" +} + if [[ "${BASH_SOURCE[0]}" == "${0}" ]] then - cache_simavr "$@" + if [ "$1" == "--self-test" ] + then + shift + cache_simavr_self_test "$@" + else + cache_simavr "$@" + fi fi diff --git a/ci/bin/ci_self_test b/ci/bin/ci_self_test index c0ae8f3..b86fd57 100755 --- a/ci/bin/ci_self_test +++ b/ci/bin/ci_self_test @@ -1,6 +1,6 @@ #!/bin/bash -CI_SELF_TESTS=(dir dir_cache preferences sketchbook arduino_exe cache_ide) +CI_SELF_TESTS=(dir dir_cache preferences sketchbook arduino_exe cache_ide avr_bin avr_root cache_simavr make_simavr_uno simavr_uno compile_sources compile_vitro ) for ci_test in "${CI_SELF_TESTS[@]}" do @@ -23,4 +23,3 @@ if [[ "${BASH_SOURCE[0]}" == "${0}" ]] then ci_self_test "$@" fi - diff --git a/ci/bin/make_simavr_uno b/ci/bin/make_simavr_uno index 123557d..0823feb 100755 --- a/ci/bin/make_simavr_uno +++ b/ci/bin/make_simavr_uno @@ -1,44 +1,12 @@ #!/bin/bash -x -if [ "$(type -t dir)" != "function" ] -then - . "$(cd "$(dirname "${BASH_SOURCE[0]}")"; pwd)"/dir -fi - -if [ "$(type -t os)" != "function" ] -then - . "$(cd "$(dirname "${BASH_SOURCE[0]}")"; pwd)"/os -fi - -if [ "$(type -t versions)" != "function" ] -then - . "$(cd "$(dirname "${BASH_SOURCE[0]}")"; pwd)"/versions -fi - -if [ "$(type -t cache_simavr)" != "function" ] -then - . "$(cd "$(dirname "${BASH_SOURCE[0]}")"; pwd)"/cache_simavr -fi - -if [ "$(type -t avr_root)" != "cache_ide" ] -then - . "$(cd "$(dirname "${BASH_SOURCE[0]}")"; pwd)"/cache_ide -fi - -if [ "$(type -t avr_root)" != "avr_root" ] -then - . "$(cd "$(dirname "${BASH_SOURCE[0]}")"; pwd)"/avr_root -fi - -if [ "$(type -t arduino_exe)" != "function" ] -then - . "$(cd "$(dirname "${BASH_SOURCE[0]}")"; pwd)"/arduino_exe -fi - -if [ "$(type -t cache_simavr)" != "function" ] -then - . "$(cd "$(dirname "${BASH_SOURCE[0]}")"; pwd)"/cache_simavr -fi +for inc in dir os version cache_simavr avr_root arduino_exe +do + if [ "$(type -t $inc)" != "function" ] + then + . "$(cd "$(dirname "${BASH_SOURCE[0]}")"; pwd)"/$inc + fi +done make_simavr_uno() { DIR="$(dir "$@")" @@ -59,14 +27,14 @@ make_simavr_uno() { esac done - if [ $BRANCH = "" ] + if [ "$BRANCH" = "" ] then BRANCH=master fi if [ -x "$DIR/cache/${VERSION}-${OS}/simavr/uno" -a "$RELOAD" != "true" ] then - exit 0 + return fi if [ ! -r "$ARDUINO_EXE" ] @@ -98,13 +66,15 @@ make_simavr_uno() { tar -C "$DIR/cache/simavr" -cf - . | tar -C "$DIR/cache/${VERSION}-${OS}/simavr/repo" -xf - (cd "$DIR/cache/${VERSION}-${OS}/simavr/repo"; git checkout -f "$BRANCH") - if ! PATH="$AVR_ROOT/bin:$PATH" make -B -C "$DIR/cache/${VERSION}-${OS}/simavr/repo" clean build-simavr + export AVR_ROOT + + if ! PATH="$AVR_ROOT/bin:$PATH" make -e -B -C "$DIR/cache/${VERSION}-${OS}/simavr/repo" clean build-simavr then echo "build-simavr target failed." exit 1 fi - if ! PATH="$AVR_ROOT/bin:$PATH" make -B -C "$DIR/cache/${VERSION}-${OS}/simavr/repo/examples/board_simduino" clean all + if ! PATH="$AVR_ROOT/bin:$PATH" make -e -B -C "$DIR/cache/${VERSION}-${OS}/simavr/repo/examples/board_simduino" clean all then echo "build board_simduino target failed." exit 1 @@ -118,8 +88,29 @@ make_simavr_uno() { exit 1 fi } - + +make_simavr_uno_self_test() { + if make_simavr_uno + then + if [ ! -x "$DIR/cache/${VERSION}-${OS}/simavr/uno" ] + then + echo "no uno" + exit 1 + fi + else + echo "make failed." + exit 1 + fi + echo "make_simavr_uno ok" +} + if [[ "${BASH_SOURCE[0]}" == "${0}" ]] then - make_simavr_uno "$@" + if [ "$1" == "--self-test" ] + then + shift + make_simavr_uno_self_test "$@" + else + make_simavr_uno "$@" + fi fi diff --git a/ci/bin/simavr_uno b/ci/bin/simavr_uno index 2b0e687..a831698 100755 --- a/ci/bin/simavr_uno +++ b/ci/bin/simavr_uno @@ -1,19 +1,12 @@ #!/bin/bash -if [ "$(type -t dir)" != "function" ] -then - . "$(cd "$(dirname "${BASH_SOURCE[0]}")"; pwd)"/dir -fi - -if [ "$(type -t os)" != "function" ] -then - . "$(cd "$(dirname "${BASH_SOURCE[0]}")"; pwd)"/os -fi - -if [ "$(type -t version)" != "function" ] -then - . "$(cd "$(dirname "${BASH_SOURCE[0]}")"; pwd)"/version -fi +for inc in dir os version +do + if [ "$(type -t $inc)" != "function" ] + then + . "$(cd "$(dirname "${BASH_SOURCE[0]}")"; pwd)"/$inc + fi +done simavr_uno_exit() { for PID in $SIMAVR_UNO_PIDS @@ -82,8 +75,23 @@ simavr_uno() { fi done } - + +simavr_uno_self_test() { + if ! simavr_uno --hex="$(cd "$(dirname "${BASH_SOURCE[0]}")"; pwd)"/../vitro.hex | grep "Test summary:" + then + echo "vitro test" + exit 1 + fi + echo "simavr_uno ok" +} + if [[ "${BASH_SOURCE[0]}" == "${0}" ]] then - simavr_uno "$@" + if [ "$1" == "--self-test" ] + then + shift + simavr_uno_self_test "$@" + else + simavr_uno "$@" + fi fi From c5fd9ce81685abc7ea75528cc9e043059857689e Mon Sep 17 00:00:00 2001 From: Warren MacEvoy Date: Sun, 6 May 2018 23:49:37 +0545 Subject: [PATCH 28/80] vitro test file --- ci/vitro.hex | 300 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 300 insertions(+) create mode 100644 ci/vitro.hex diff --git a/ci/vitro.hex b/ci/vitro.hex new file mode 100644 index 0000000..b7d8504 --- /dev/null +++ b/ci/vitro.hex @@ -0,0 +1,300 @@ +:100000000C9490000C94B8000C94B8000C94B800B8 +:100010000C94B8000C94B8000C94B8000C94B80080 +:100020000C94B8000C94B8000C94B8000C94B80070 +:100030000C94B8000C94B8000C94B8000C94B80060 +:100040000C9405050C94B8000C9475050C944F05A0 +:100050000C94B8000C94B8000C94B8000C94B80040 +:100060000C94B8000C94B800417373657274696F96 +:100070006E2000706173736564006661696C65640D +:1000800000292000202800292C2066696C652000AA +:100090002C206C696E6520003100213D00780076CF +:1000A0006974726F2E696E6F003D3D00696E636FFB +:1000B00072726563740054657374200020736B69F9 +:1000C000707065642E00207061737365642E00206B +:1000D0006661696C65642E00546573742073756D78 +:1000E0006D6172793A2000207061737365642C2011 +:1000F00000206661696C65642C20616E64200020BC +:10010000736B69707065642C206F7574206F662046 +:100110000020746573742873292E0000A705A307B7 +:1001200011241FBECFEFD8E0DEBFCDBF11E0A0E0AD +:10013000B1E0EAE5F2E102C005900D92A834B10702 +:10014000D9F722E0A8E4B1E001C01D92A431B207C2 +:10015000E1F710E0CFE8D0E004C02197FE010E9453 +:100160000C09CE38D107C9F70E9414060C94200957 +:100170000C940000EF92FF920F931F93CF93DF93A5 +:100180008C017B01C0E0D0E0F701EC0FFD1F649112 +:10019000662361F0D801ED91FC910190F081E02D92 +:1001A000C8010995892B11F02196EECFCE01DF9180 +:1001B000CF911F910F91FF90EF900895CF92DF9212 +:1001C000EF92FF920F931F93CF93DF936C017A010D +:1001D0008B01C0E0D0E0CE15DF0589F0D8016D912C +:1001E0008D01D601ED91FC910190F081E02DC601C9 +:1001F0000995892B11F47E0102C02196ECCFC7012D +:10020000DF91CF911F910F91FF90EF90DF90CF90F2 +:100210000895FC01918D828D981761F0828DDF0128 +:10022000A80FB11D5D968C91928D9F5F9F73928FE9 +:1002300090E008958FEF9FEF0895FC01918D828DDE +:10024000981731F0828DE80FF11D858D90E00895AB +:100250008FEF9FEF0895FC01918D228D892F90E003 +:10026000805C9F4F821B91098F73992708958DE5BC +:1002700091E00E942B0121E0892B09F420E0822FDC +:100280000895FC01848DDF01A80FB11DA35ABF4F53 +:100290002C91848D90E001968F739927848FA68985 +:1002A000B7892C93A089B1898C9180648C93938DAC +:1002B000848D981306C00288F389E02D80818F7D9C +:1002C00080830895EF92FF920F931F93CF93DF9354 +:1002D000EC0181E0888F9B8D8C8D981305C0E88997 +:1002E000F989808185FD24C0F62E0B8D10E00F5F0B +:1002F0001F4F0F731127E02E8C8DE8120CC00FB624 +:1003000007FCFACFE889F989808185FFF5CFCE0116 +:100310000E944101F1CF8B8DFE01E80FF11DE35AE0 +:10032000FF4FF0820B8FEA89FB898081806207C0D2 +:10033000EE89FF896083E889F98980818064808300 +:1003400081E090E0DF91CF911F910F91FF90EF90AE +:100350000895CF93DF93EC01888D8823C9F0EA8953 +:10036000FB89808185FD05C0A889B9898C9186FDAE +:100370000FC00FB607FCF5CF808185FFF2CFA889AB +:10038000B9898C9185FFEDCFCE010E944101E7CF65 +:10039000DF91CF91089580E090E0892B29F00E94B1 +:1003A000370181110C9400000895CF93DF93EC0185 +:1003B000E881F9810084F185E02D09958C818130F7 +:1003C00011F483E08C83DF91CF910895089508950F +:1003D0002EE231E0FC0131832083E0915001F09165 +:1003E0005101A0E5B1E0309771F0E817F90729F461 +:1003F000828193818D939C930895DF0112960280F0 +:10040000F381E02DF0CF08952EE231E0FC0131833D +:100410002083E0915001F0915101A0E5B1E03097C7 +:1004200071F0E817F90729F4828193818D939C93E9 +:100430000895DF0112960280F381E02DF0CF089538 +:10044000FC0181E0DB014D915C91208131814217FB +:10045000530709F480E00895FC0181E0DB014D9130 +:100460005C91208131814217530709F080E00895A3 +:100470000E9412096115710579F0FB0101900020BD +:10048000E9F73197AF01461B570BDC01ED91FC9169 +:100490000280F381E02D099480E090E008954F926E +:1004A0005F926F927F92EF92FF920F931F93CF9381 +:1004B000DF93CDB7DEB7A1970FB6F894DEBF0FBEBE +:1004C000CDBF7C01FA01CB0119A2223008F42AE049 +:1004D0008E010F5D1F4F422E512C612C712CBF01DC +:1004E000A30192010E94EA08F901CA010150110911 +:1004F0006A3014F4605D01C0695CD8016C93232BF1 +:10050000242B252B61F7B801C7010E943A02A1965E +:100510000FB6F894DEBF0FBECDBFDF91CF911F9114 +:100520000F91FF90EF907F906F905F904F900895A4 +:10053000CF92DF92EF92FF920F931F93CF93DF93AF +:100540006B01770FEE08FF08F7FE1FC0EC01E88192 +:10055000F9810190F081E02D6DE209958C0144272D +:100560005527BA014C195D096E097F092AE0CE01B1 +:100570000E944F02800F911FDF91CF911F910F9129 +:10058000FF90EF90DF90CF9008952AE0B701A60189 +:10059000DF91CF911F910F91FF90EF90DF90CF905F +:1005A0000C944F020F931F93CF93DF93EC010E94A3 +:1005B000BA008C0164E471E0CE010E943A02800F1F +:1005C000911FDF91CF911F910F9108952F923F922C +:1005D0004F925F926F927F928F929F92AF92BF9253 +:1005E000CF92DF92EF92FF920F931F93CF93DF93FF +:1005F00000D0CDB7DEB71C017A8369832A013901A7 +:10060000B501C901F7010995F82EE0915201F09169 +:100610005301811109C0309709F482C084E08483BA +:10062000828584FD07C07CC0309709F479C082853B +:1006300085FF76C068E670E08DE591E00E94BA0023 +:10064000FF2009F000C06AE770E08DE591E00E94AC +:10065000BA0064EE70E08DE591E00E94BA0065E8B2 +:1006600070E08DE591E00E94BA00B2018DE591E065 +:100670000E94BA006BE970E08DE591E00E94BA003B +:10068000D3016D917C918DE591E00E94980261E823 +:1006900070E08DE591E00E94BA00B8018DE591E02F +:1006A0000E94BA0064E870E08DE591E00E94BA0013 +:1006B000B6018DE591E00E94BA006BE970E08DE52E +:1006C00091E00E94BA00F501608171818DE591E0B1 +:1006D0000E94980267E870E08DE591E00E94BA0000 +:1006E000B1018DE591E00E94BA0060E970E08DE50E +:1006F00091E00E94BA0089819A81AC0160E070E0CB +:100700002AE08DE591E00E944F02D401ED91FC9129 +:100710008F2D099569E171E08DE591E00E94D2028B +:100720008F2D0F900F90DF91CF911F910F91FF9020 +:10073000EF90DF90CF90BF90AF909F908F907F9081 +:100740006F905F904F903F902F9008958F929F925F +:10075000AF92BF92CF92DF92EF92FF920F931F93CF +:10076000CF93DF9300D000D000D0CDB7DEB781E0CB +:1007700090E09A83898327EE31E03E832D839C832A +:100780008B8328E930E00AE910E04DE950E08FE979 +:1007900090E0BE016B5F7F4F4B01625071095B01BE +:1007A000690120E2E22E22E0F22E9E012F5F3F4FF0 +:1007B0006DE070E00E94E60226960FB6F894DEBF68 +:1007C0000FBECDBFDF91CF911F910F91FF90EF90A2 +:1007D000DF90CF90BF90AF909F908F9008958F92B1 +:1007E0009F92AF92BF92CF92DF92EF92FF920F93C0 +:1007F0001F93CF93DF9300D000D000D0CDB7DEB7EA +:1008000081E090E09A83898327EE31E03E832D8357 +:100810009C838B8328E930E009EA10E04DE950E041 +:100820008FE990E0BE016B5F7F4F4B016250710911 +:100830005B0169012CE2E22E22E0F22E9E012F5F85 +:100840003F4F67E070E00E94E60226960FB6F894EC +:10085000DEBF0FBECDBFDF91CF911F910F91FF90F3 +:10086000EF90DF90CF90BF90AF909F908F900895C2 +:10087000FC01CB0124816281738121110C94BA00A7 +:100880000C943A028F929F92AF92BF92CF92DF92D6 +:10089000EF92FF920F931F93CF93DF93CDB7DEB705 +:1008A00028970FB6F894DEBF0FBECDBF7C01DC01E8 +:1008B00014961C9200E511E0D801ED91FC9130975F +:1008C00009F463C0D70119968C91811103C020E00F +:1008D00030E002C022E030E08185282B578140853E +:1008E000F701878190852130310551F022303105A3 +:1008F00061F0232BB9F4652F742F0E9417090DC0E6 +:10090000652F742F0E94E10808C0BC01852F942F29 +:100910000E94E1089195819591090097B1F10CF041 +:100920005AC033C06C01A52EB42E812CF82DF37063 +:100930009F2EA1F444E050E0B601CE0105960E943E +:10094000D80884E0C80ED11C44E050E0B501CE01C7 +:1009500001960E94D808A4E0AA0EB11C292D30E00F +:10096000E5E0F0E0EC0FFD1FE20FF31F8081E1E016 +:10097000F0E0EC0FFD1FE20FF31F9081891728F0C4 +:10098000981748F183948111D1CFF801808191812A +:10099000D70113969C938E931297F182E0828091F7 +:1009A0004801909149010196909349018093480133 +:1009B00028960FB6F894DEBF0FBECDBFDF91CF9162 +:1009C0001F910F91FF90EF90DF90CF90BF90AF906D +:1009D0009F908F900895F801008111810E5F1F4F45 +:1009E0006BCFCF93DF93EC010E940402CE01DF9125 +:1009F000CF910C944008CF93DF93EC010E94E80163 +:100A0000CE01DF91CF910C9440081F920F920FB648 +:100A10000F9211242F933F938F939F93AF93BF9384 +:100A20008091590190915A01A0915B01B0915C01B4 +:100A30003091580123E0230F2D3720F40196A11D9A +:100A4000B11D05C026E8230F0296A11DB11D2093FC +:100A500058018093590190935A01A0935B01B09380 +:100A60005C018091540190915501A0915601B09183 +:100A700057010196A11DB11D80935401909355011A +:100A8000A0935601B0935701BF91AF919F918F9161 +:100A90003F912F910F900FBE0F901F9018951F92AE +:100AA0000F920FB60F9211242F933F934F935F93A2 +:100AB0006F937F938F939F93AF93BF93EF93FF9326 +:100AC0008DE591E00E944101FF91EF91BF91AF91BF +:100AD0009F918F917F916F915F914F913F912F9156 +:100AE0000F900FBE0F901F9018951F920F920FB688 +:100AF0000F9211242F938F939F93EF93FF93E09185 +:100B00006D01F0916E018081E0917301F0917401AB +:100B100082FD12C09081809176018F5F8F7320914A +:100B20007701821751F0E0917601F0E0E35AFE4F31 +:100B3000958F8093760101C08081FF91EF919F9105 +:100B40008F912F910F900FBE0F901F901895CF92FD +:100B5000DF92EF92FF920F931F93CF93DF93EDE518 +:100B6000F1E01382128288EE93E0A0E0B0E084838B +:100B70009583A683B7838AE091E09183808385EC97 +:100B800090E09587848784EC90E09787868780EC57 +:100B900090E0918B808B81EC90E0938B828B82EC48 +:100BA00090E0958B848B86EC90E0978B868B118EF2 +:100BB000128E138E148E8EEA90E0C5E0D2E02EE203 +:100BC000C22E21E0D22ED982C88238E2E32E31E053 +:100BD000F32EFE82ED8298878F8301E009871FE163 +:100BE0001A87CE010E9442048AE391E099838883A8 +:100BF0008CEA90E0CAEFD1E0D982C882FE82ED8211 +:100C000098878F8309871A87CE010E9442048AE160 +:100C100091E099838883DF91CF911F910F91FF908D +:100C2000EF90DF90CF900895789484B5826084BD72 +:100C300084B5816084BD85B5826085BD85B58160E0 +:100C400085BD80916E00816080936E00109281005E +:100C50008091810082608093810080918100816019 +:100C600080938100809180008160809380008091DA +:100C7000B10084608093B1008091B0008160809366 +:100C8000B00080917A00846080937A0080917A002D +:100C9000826080937A0080917A00816080937A00EC +:100CA00080917A00806880937A001092C100E09170 +:100CB0006D01F0916E0182E08083E0916901F09115 +:100CC0006A011082E0916B01F0916C018FEC8083DE +:100CD00010927501E0917101F091720186E08083BC +:100CE000E0916F01F0917001808180618083E091DB +:100CF0006F01F0917001808188608083E0916F01C5 +:100D0000F0917001808180688083E0916F01F091A3 +:100D1000700180818F7D8083CC24C39480E5E82E90 +:100D200081E0F82EF70180819181009709F4F5C0E8 +:100D30009093530180935201DC0114962C911497E7 +:100D4000213039F4ED91FC910280F381E02D099579 +:100D500011C021110FC0DC01ED91FC910190F081D7 +:100D6000E02D0995E0915201F091530184818111A8 +:100D700001C0C482C0915201D09153018C81D7012E +:100D8000ED91FC911197813009F4C2C08281938169 +:100D90008D939C938C8101E0833009F000E011E099 +:100DA000843009F010E0DD24D394823009F0D12C96 +:100DB000011105C011110EC0D11017C057C080918C +:100DC0004E0190914F01019690934F0180934E01F7 +:100DD000112349F080914C0190914D01019690931F +:100DE0004D0180934C01DD2081F080914A0190916A +:100DF0004B01019690934B0180934A01209709F48F +:100E000035C08A8583FD0AC099C0002309F48CC0CF +:100E1000209709F42BC08A8582FF92C066EB70E0B0 +:100E20008DE591E00E94BA00ED81FE810190F08194 +:100E3000E02D6DE571E0CE0105960995DD2031F0DC +:100E40006CEB70E08DE591E00E94D202002331F05E +:100E500066EC70E08DE591E00E94D202112331F042 +:100E60006FEC70E08DE591E00E94D202809150011C +:100E700090915101892B09F055CF68ED70E08DE517 +:100E800091E00E94BA0040914E0150914F0160E004 +:100E900070E02AE08DE591E00E944F0267EE70E07D +:100EA0008DE591E00E94BA0040914C0150914D01B6 +:100EB00060E070E02AE08DE591E00E944F0261EF72 +:100EC00070E08DE591E00E94BA0040914A01509196 +:100ED0004B0160E070E02AE08DE591E00E944F0256 +:100EE0006FEF70E08DE591E00E94BA0040914801FB +:100EF0005091490160E070E02AE08DE591E00E94A8 +:100F00004F0261E171E08DE591E00E94D2020ACFCB +:100F10007F01B2E0EB0EF11C05CF1092530110924D +:100F200052010E94CB01FACE112309F49FCF2097E2 +:100F300009F49CCF8A8581FF99CF70CF01116BCFC7 +:100F40001111F8CF93CF8AEF91E00E94040285E05F +:100F500092E00C94E801CF93DF938230910510F476 +:100F600082E090E0E0911202F091130220E030E084 +:100F7000C0E0D0E0309711F1408151814817590706 +:100F8000C0F04817590761F482819381209719F0C6 +:100F90009B838A832BC0909313028093120226C0F6 +:100FA0002115310519F04217530718F49A01BE01B3 +:100FB000DF01EF010280F381E02DDCCF2115310547 +:100FC00009F1281B390B2430310590F412968D91CC +:100FD0009C9113976115710521F0FB019383828326 +:100FE00004C09093130280931202FD01329644C014 +:100FF000FD01E20FF31F81939193225031092D934C +:101000003C933AC02091100230911102232B41F4FD +:1010100020910201309103013093110220931002BC +:1010200020910001309101012115310541F42DB7C6 +:101030003EB74091040150910501241B350BE0910E +:101040001002F0911102E217F307A0F42E1B3F0BE0 +:101050002817390778F0AC014E5F5F4F241735072A +:1010600048F04E0F5F1F509311024093100281937E +:10107000919302C0E0E0F0E0CF01DF91CF910895BD +:101080000F931F93CF93DF93009709F48CC0FC015B +:1010900032971382128200911202109113020115ED +:1010A000110581F420813181820F931F209110025C +:1010B000309111022817390779F5F0931102E09366 +:1010C000100271C0D80140E050E0AE17BF0750F4E5 +:1010D00012962D913C911397AD012115310509F11F +:1010E000D901F3CF9D01DA013383228360817181BD +:1010F000860F971F8217930769F4EC0128813981C5 +:10110000260F371F2E5F3F4F318320838A819B81BB +:1011100093838283452B29F4F0931302E093120208 +:1011200042C01396FC93EE931297ED0149915991A9 +:101130009E01240F351FE217F30771F4808191811E +:10114000840F951F029611969C938E9382819381B2 +:1011500013969C938E931297E0E0F0E0D8011296DC +:101160008D919C911397009719F0F8018C01F6CF9F +:101170008D919C9198012E5F3F4F820F931F20917C +:101180001002309111022817390769F4309729F4B9 +:10119000109213021092120202C013821282109354 +:1011A000110200931002DF91CF911F910F910895CA +:1011B000FB01DC0102C005900D9241505040D8F770 +:1011C0000895FB01DC018D91059080190110D9F380 +:1011D000990B0895A1E21A2EAA1BBB1BFD010DC09D +:1011E000AA1FBB1FEE1FFF1FA217B307E407F507D7 +:1011F00020F0A21BB30BE40BF50B661F771F881FB3 +:10120000991F1A9469F760957095809590959B0148 +:10121000AC01BD01CF010895EE0FFF1F0590F491C1 +:10122000E02D099481E090E0F8940C942009FB01F2 +:10123000DC018D91019080190110D9F3990B08956B +:1012400010E0CFE8D0E004C0FE010E940C09219616 +:0A125000C039D107C9F7F894FFCFA9 +:10125A00000014028000000000006201DE002B0181 +:10126A0009011D01A90100000000E601D5010402DF +:10127A00F104A60300000000380400000000E601A3 +:10128A0038020000000000000000E601D501E80174 +:08129A00FB04EF030D0A000044 +:00000001FF From 486ce6d67e8b59e6cdb3b6f29f9525a5755083c5 Mon Sep 17 00:00:00 2001 From: Warren MacEvoy Date: Sun, 6 May 2018 12:18:22 -0600 Subject: [PATCH 29/80] vitro --- ci/bin/compile_vitro | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ci/bin/compile_vitro b/ci/bin/compile_vitro index 63cfbd9..d9e2e45 100755 --- a/ci/bin/compile_vitro +++ b/ci/bin/compile_vitro @@ -1,4 +1,4 @@ -#!/bin/bash +#!/bin/bash -x for inc in dir sketchbook compile_sources do @@ -66,7 +66,7 @@ compile_vitro() { mkdir -p "${TMP}/ArduinoUnit/src" (cd "${ARDUINO_UNIT_DIR}/src"; tar cf - $(compile_sources .)) | tar -C "${TMP}/ArduinoUnit/src" -xf - - ARDUINO_TARGET_EXE="${ARDUINO_TARGET_INO%.ino}" + ARDUINO_TARGET_EXE="${INO%.ino}" # # compile everything in the temp directory, relabeling filenames errors so they look like they came from the right place From eecfe80f576e59d6d67b97d42bfb251872adc969 Mon Sep 17 00:00:00 2001 From: Warren MacEvoy Date: Mon, 7 May 2018 10:34:17 -0600 Subject: [PATCH 30/80] fix arduino_exe --- ci/bin/arduino_exe | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ci/bin/arduino_exe b/ci/bin/arduino_exe index ad56c0d..da56386 100755 --- a/ci/bin/arduino_exe +++ b/ci/bin/arduino_exe @@ -25,7 +25,7 @@ arduino_exe() { } arduino_exe_self_test() { - if ! arduino_exe | egrep -i -q "arduino\.[^.]*$" + if ! arduino_exe | egrep -i -q "arduino(\.exe)?$" then echo "name test failed." exit 1 From 18f218d012714100f765cc0be16889dc51926564 Mon Sep 17 00:00:00 2001 From: Warren MacEvoy Date: Fri, 11 May 2018 08:40:25 -0600 Subject: [PATCH 31/80] ide update --- ci/bin/arduino | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ci/bin/arduino b/ci/bin/arduino index 10d58bb..a21e187 100755 --- a/ci/bin/arduino +++ b/ci/bin/arduino @@ -47,7 +47,7 @@ then shift arduino_self_test "$@" else - arduino_ide "$@" + arduino "$@" fi fi From 41e134c2c047520b935e84625024001e5caa8dc2 Mon Sep 17 00:00:00 2001 From: Warren MacEvoy Date: Fri, 11 May 2018 09:04:07 -0600 Subject: [PATCH 32/80] launch arduino --- ci/bin/arduino | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/ci/bin/arduino b/ci/bin/arduino index a21e187..8d4271b 100755 --- a/ci/bin/arduino +++ b/ci/bin/arduino @@ -9,11 +9,6 @@ do done arduino() { - OS="$(os "$@")" - DIR="$(dir "$@")" - VERSION="$(version "$@")" - PREFERENCES="$(preferences "$@")" - SKETCHBOOK="$(sketchbook "$@")" ARDUINO_EXE="$(arduino_exe "$@")" if [ ! -r "$ARDUINO_EXE" ] @@ -24,7 +19,7 @@ arduino() { exit 1 fi fi - "$ARDUINO_EXE" --preferences-file "$PREFERENCES" --pref sketchbook.path="$SKETCHBOOK" --pref update.check=false "$@" + "$ARDUINO_EXE" "$@" } arduino_self_test() { From 3ca3aa74d67907dc31eab1ab7a3a2d5370732e7e Mon Sep 17 00:00:00 2001 From: Warren MacEvoy Date: Fri, 11 May 2018 10:04:27 -0600 Subject: [PATCH 33/80] compile uno --- ci/bin/compile_avr | 93 ++++++++++++++++++++++++++++++ ci/bin/compile_uno | 46 +++++++++++++++ ci/test-here/faketest/faketest.ino | 13 +++++ 3 files changed, 152 insertions(+) create mode 100755 ci/bin/compile_avr create mode 100755 ci/bin/compile_uno create mode 100644 ci/test-here/faketest/faketest.ino diff --git a/ci/bin/compile_avr b/ci/bin/compile_avr new file mode 100755 index 0000000..55bbb4d --- /dev/null +++ b/ci/bin/compile_avr @@ -0,0 +1,93 @@ +#!/bin/bash -x + +for inc in dir arduino_dir packages sketchbook compile_sources +do + if [ "$(type -t $inc)" != "function" ] + then + . "$(cd "$(dirname "${BASH_SOURCE[0]}")"; pwd)"/$inc + fi +done + +compile_avr() { + DIR="$(dir "$@")" + ARDUINO_DIR="$(arduino_dir "$@")" + SKETCHBOOK="$(sketchbook "$@")" + ARDUINO_PACKAGES="$(packages "$@")" + ARDUINO_HARDWARE="${ARDUINO_DIR}/hardware" + ARDUINO_LIBS="${SKETCHBOOK}/libraries" + BOARD=arduino:avr:uno:cpu=atmega328p + ARDUINO_TARGET_DIR= + while [ $# -gt 0 ] + do + case "$1" + in + --board=*) BOARD=${1#--board=}; shift;; + --ino=*) INO=${1#--ino=}; shift;; + --tmp=*) TMP=${1#--tmp=}; shift;; + --*=*) shift;; + --) shift; break;; + *) break;; + esac + done + + if [ "${INO}" = "" ]; then + INO="$(echo *.ino)" + fi + + if [ ! -f "${INO}" ] ; then + echo "must specify ino file" + exit 1 + fi + ARDUINO_TARGET_DIR="$(dirname "${INO}")" + if [ ! -d "${ARDUINO_TARGET_DIR}" ] ; then + echo "missing directory ${ARDUINO_TARGET_DIR}." + exit 1 + fi + + # + # Make a temp directory to work in (that is removed) + # + if [ "$TMP" = "" ] ; then + TMP="$(mktemp -d)" + EXITS+="/bin/rm -rf '${TMP}'" + trap 'for action in "${EXITS[@]}" ; do $action ; done' EXIT + else + mkdir -p "$TMP" + fi + + TMP_HEX="${TMP}/build/$(basename ${INO}).hex" + HEX="${INO%.ino}".hex + + mkdir -p ${TMP}/build + mkdir -p ${TMP}/cache + mkdir -p ${TMP}/src + + (cd ${ARDUINO_TARGET_DIR}; tar cf - $(compile_sources .)) | tar -C "${TMP}/src" -xf - + + ARDUINO_TARGET_EXE="${INO%.ino}" + + ${ARDUINO_DIR}/arduino-builder -dump-prefs -logger=machine -hardware ${ARDUINO_DIR}/hardware -hardware ${ARDUINO_DIR}/hardware -tools ${ARDUINO_DIR}/tools-builder -tools ${ARDUINO_DIR}/hardware/tools/avr -built-in-libraries ${ARDUINO_DIR}/libraries -libraries ${ARDUINO_LIBS} -fqbn=${BOARD} -ide-version=10802 -build-path ${TMP}/build -warnings=all -build-cache ${TMP}/cache -prefs=build.warn_data_percentage=75 -prefs=runtime.tools.avr-gcc.path=${ARDUINO_DIR}/hardware/tools/avr -prefs=runtime.tools.arduinoOTA.path=${ARDUINO_DIR}/hardware/tools/avr -prefs=runtime.tools.avrdude.path=${ARDUINO_DIR}/hardware/tools/avr -verbose "${TMP}/src/$(basename ${INO})" 2>&1 | sed -e "s|${TMP}/build/sketch/|${ARDUINO_TARGET_DIR}/|g" + + ${ARDUINO_DIR}/arduino-builder -compile -logger=machine -hardware ${ARDUINO_DIR}/hardware -hardware ${ARDUINO_HARDWARE} -tools ${ARDUINO_DIR}/tools-builder -tools ${ARDUINO_DIR}/hardware/tools/avr -built-in-libraries ${ARDUINO_DIR}/libraries -libraries ${ARDUINO_LIBS} -fqbn=${BOARD} -ide-version=10802 -build-path ${TMP}/build -warnings=all -build-cache ${TMP}/cache -prefs=build.warn_data_percentage=75 -prefs=runtime.tools.avr-gcc.path=${ARDUINO_DIR}/hardware/tools/avr -prefs=runtime.tools.arduinoOTA.path=${ARDUINO_DIR}/hardware/tools/avr -prefs=runtime.tools.avrdude.path=${ARDUINO_DIR}/hardware/tools/avr -verbose "${TMP}/src/$(basename ${INO})" 2>&1 | sed -e "s|${TMP}/build/sketch/|${ARDUINO_TARGET_DIR}/|g" + if [ ! -f "${TMP_HEX}" ] ; then + echo "compile time error: avr." + exit 1 + fi + cp "${TMP_HEX}" "${HEX}" +} + +compile_avr_self_test() { + echo "none" + echo "compile_avr ok" +} + +if [[ "${BASH_SOURCE[0]}" == "${0}" ]] +then + if [ "$1" == "--self-test" ] + then + shift + compile_avr_self_test "$@" + else + compile_avr "$@" + fi +fi diff --git a/ci/bin/compile_uno b/ci/bin/compile_uno new file mode 100755 index 0000000..b92deb6 --- /dev/null +++ b/ci/bin/compile_uno @@ -0,0 +1,46 @@ +#!/bin/bash + +for inc in compile_avr simavr_uno +do + if [ "$(type -t $inc)" != "function" ] + then + . "$(cd "$(dirname "${BASH_SOURCE[0]}")"; pwd)"/$inc + fi +done + +compile_uno() { + compile_avr --board=arduino:avr:uno:cpu=atmega328p "$@" +} + +compile_uno_self_test() { + local TMP="$(mktemp -d)" + EXITS+="/bin/rm -rf '${TMP}'" + trap 'for action in "${EXITS[@]}" ; do $action ; done' EXIT + + cp -r "$(cd "$(dirname "${BASH_SOURCE[0]}")"; pwd)"/../test-here/faketest "${TMP}" + /bin/rm -rf "$TMP/faketest/*.hex" + + if ! compile_uno --ino="$TMP/faketest/faketest.ino" + then + echo "compile" + exit 1 + fi + + if ! simavr_uno --hex=$TMP/faketest/faketest.hex | grep -q "Test summary:" + then + echo "execute" + exit 1 + fi + echo "compile_uno ok" +} + +if [[ "${BASH_SOURCE[0]}" == "${0}" ]] +then + if [ "$1" == "--self-test" ] + then + shift + compile_uno_self_test "$@" + else + compile_uno "$@" + fi +fi diff --git a/ci/test-here/faketest/faketest.ino b/ci/test-here/faketest/faketest.ino new file mode 100644 index 0000000..e800dac --- /dev/null +++ b/ci/test-here/faketest/faketest.ino @@ -0,0 +1,13 @@ +void setup() { + Serial.begin(115200L); + while (!Serial) {} + Serial.println("Test summary: 0 passed, 0 failed, and 0 skipped, out of 0 test(s)."); +} + +void loop() { + static uint32_t next = 0; + if (int32_t(millis()-next) >= 0) { + Serial.println("run."); + next += 1000; + } +} From 4a1b88e762df69afb288fae1ccaa9937201a8d82 Mon Sep 17 00:00:00 2001 From: Warren MacEvoy Date: Fri, 11 May 2018 10:13:34 -0600 Subject: [PATCH 34/80] compile uno --- ci/bin/ci_self_test | 2 +- ci/bin/compile_uno | 2 +- ci/bin/compile_vitro | 2 +- ci/{test-here => }/faketest/faketest.ino | 0 4 files changed, 3 insertions(+), 3 deletions(-) rename ci/{test-here => }/faketest/faketest.ino (100%) diff --git a/ci/bin/ci_self_test b/ci/bin/ci_self_test index b86fd57..4e93e4e 100755 --- a/ci/bin/ci_self_test +++ b/ci/bin/ci_self_test @@ -1,6 +1,6 @@ #!/bin/bash -CI_SELF_TESTS=(dir dir_cache preferences sketchbook arduino_exe cache_ide avr_bin avr_root cache_simavr make_simavr_uno simavr_uno compile_sources compile_vitro ) +CI_SELF_TESTS=(dir dir_cache preferences sketchbook arduino_exe cache_ide avr_bin avr_root cache_simavr make_simavr_uno simavr_uno compile_sources compile_vitro compile_uno ) for ci_test in "${CI_SELF_TESTS[@]}" do diff --git a/ci/bin/compile_uno b/ci/bin/compile_uno index b92deb6..d3e9d98 100755 --- a/ci/bin/compile_uno +++ b/ci/bin/compile_uno @@ -17,7 +17,7 @@ compile_uno_self_test() { EXITS+="/bin/rm -rf '${TMP}'" trap 'for action in "${EXITS[@]}" ; do $action ; done' EXIT - cp -r "$(cd "$(dirname "${BASH_SOURCE[0]}")"; pwd)"/../test-here/faketest "${TMP}" + cp -r "$(cd "$(dirname "${BASH_SOURCE[0]}")"; pwd)"/../faketest "${TMP}" /bin/rm -rf "$TMP/faketest/*.hex" if ! compile_uno --ino="$TMP/faketest/faketest.ino" diff --git a/ci/bin/compile_vitro b/ci/bin/compile_vitro index d9e2e45..54024bf 100755 --- a/ci/bin/compile_vitro +++ b/ci/bin/compile_vitro @@ -16,7 +16,7 @@ compile_vitro() { case "$1" in --ino=*) INO=${1#--ino=}; shift;; - --tmp=*) TMP=${1#--ino=}; shift;; + --tmp=*) TMP=${1#--tmp=}; shift;; --*=*) shift;; --) shift; break;; *) break;; diff --git a/ci/test-here/faketest/faketest.ino b/ci/faketest/faketest.ino similarity index 100% rename from ci/test-here/faketest/faketest.ino rename to ci/faketest/faketest.ino From a66593af0fd2a5df4073df301e141c5fd96d8e67 Mon Sep 17 00:00:00 2001 From: Warren MacEvoy Date: Fri, 11 May 2018 10:15:32 -0600 Subject: [PATCH 35/80] compile uno --- ci/bin/compile_avr | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/ci/bin/compile_avr b/ci/bin/compile_avr index 55bbb4d..ce8edb6 100755 --- a/ci/bin/compile_avr +++ b/ci/bin/compile_avr @@ -1,6 +1,6 @@ #!/bin/bash -x -for inc in dir arduino_dir packages sketchbook compile_sources +for inc in dir arduino_dir sketchbook compile_sources do if [ "$(type -t $inc)" != "function" ] then @@ -12,7 +12,6 @@ compile_avr() { DIR="$(dir "$@")" ARDUINO_DIR="$(arduino_dir "$@")" SKETCHBOOK="$(sketchbook "$@")" - ARDUINO_PACKAGES="$(packages "$@")" ARDUINO_HARDWARE="${ARDUINO_DIR}/hardware" ARDUINO_LIBS="${SKETCHBOOK}/libraries" BOARD=arduino:avr:uno:cpu=atmega328p From 2dff44abedcf1fd7305bcc0df2d7012383eb8ca0 Mon Sep 17 00:00:00 2001 From: Warren MacEvoy Date: Fri, 11 May 2018 22:07:58 +0545 Subject: [PATCH 36/80] compile mega --- ci/bin/compile_mega | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) create mode 100755 ci/bin/compile_mega diff --git a/ci/bin/compile_mega b/ci/bin/compile_mega new file mode 100755 index 0000000..1dbfb9c --- /dev/null +++ b/ci/bin/compile_mega @@ -0,0 +1,29 @@ +#!/bin/bash + +for inc in compile_avr +do + if [ "$(type -t $inc)" != "function" ] + then + . "$(cd "$(dirname "${BASH_SOURCE[0]}")"; pwd)"/$inc + fi +done + +compile_mega() { + compile_avr --board=arduino:avr:mega:cpu=atmega2560 "$@" +} + +compile_mega_self_test() { + echo "no test" + echo "compile_mega ok" +} + +if [[ "${BASH_SOURCE[0]}" == "${0}" ]] +then + if [ "$1" == "--self-test" ] + then + shift + compile_mega_self_test "$@" + else + compile_mega "$@" + fi +fi From fbcf1275f6f421cb917861bbb7ccbf804e92869f Mon Sep 17 00:00:00 2001 From: Warren MacEvoy Date: Fri, 11 May 2018 11:20:09 -0600 Subject: [PATCH 37/80] library props --- library.properties | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/library.properties b/library.properties index 484bec0..ce33b7e 100644 --- a/library.properties +++ b/library.properties @@ -1,9 +1,9 @@ name=ArduinoUnit -version=2.3.7-alpha +version=3.0.0 author=Matthew Murdoch maintainer=Matthew Murdoch sentence=Unit test framework for arduino projects. -paragraph=Unit testing framework for arduino projects. Supports Arduino, ESP8266 and ESP32 as well as "en vitro" development system (vs embedded target) testing. +paragraph=Flexible testing framework for arduino-style projects. Supports Arduino, ESP8266 and ESP32 as well as "en vitro" development system (vs embedded target) testing. category=Other url=https://github.com/mmurdoch/arduinounit architectures=* From e192ecd4a79234726e496a3667a7c65f46748795 Mon Sep 17 00:00:00 2001 From: Warren MacEvoy Date: Fri, 11 May 2018 11:24:18 -0600 Subject: [PATCH 38/80] library properties --- library.properties | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/library.properties b/library.properties index 484bec0..b647c6b 100644 --- a/library.properties +++ b/library.properties @@ -1,9 +1,9 @@ name=ArduinoUnit -version=2.3.7-alpha +version=3.0.1 author=Matthew Murdoch maintainer=Matthew Murdoch -sentence=Unit test framework for arduino projects. -paragraph=Unit testing framework for arduino projects. Supports Arduino, ESP8266 and ESP32 as well as "en vitro" development system (vs embedded target) testing. +sentence=Flexible test framework for arduino projects. +paragraph=Flexible testing framework for arduino projects. Supports Arduino, ESP8266 and ESP32 as well as "en vitro" development system (vs embedded target) testing. category=Other url=https://github.com/mmurdoch/arduinounit architectures=* From 907b2c0c0193b42550d80c59fe59021b73f21531 Mon Sep 17 00:00:00 2001 From: Warren MacEvoy Date: Tue, 15 May 2018 00:54:34 +0545 Subject: [PATCH 39/80] upload --- ci/bin/upload_avr | 89 ++++++++++++++++++++++++++++++++++++++++++++++ ci/bin/upload_mega | 29 +++++++++++++++ ci/bin/upload_uno | 29 +++++++++++++++ 3 files changed, 147 insertions(+) create mode 100755 ci/bin/upload_avr create mode 100644 ci/bin/upload_mega create mode 100755 ci/bin/upload_uno diff --git a/ci/bin/upload_avr b/ci/bin/upload_avr new file mode 100755 index 0000000..c779613 --- /dev/null +++ b/ci/bin/upload_avr @@ -0,0 +1,89 @@ +#!/bin/bash -x + +for inc in dir os arduino_dir packages sketchbook compile_sources +do + if [ "$(type -t $inc)" != "function" ] + then + . "$(cd "$(dirname "${BASH_SOURCE[0]}")"; pwd)"/$inc + fi +done + +compile_avr() { + DIR="$(dir "$@")" + OS="$(os "$@")" + ARDUINO_DIR="$(arduino_dir "$@")" + ARDUINO_PACKAGES="$(packages "$@")" + ARDUINO_HARDWARE="${ARDUINO_DIR}/hardware" + ARDUINO_LIBS="${SKETCHBOOK}/libraries" + BOARD=arduino:avr:uno:cpu=atmega328p + ARDUINO_TARGET_DIR= + while [ $# -gt 0 ] + do + case "$1" + in + --board=*) BOARD=${1#--board=}; shift;; + --ino=*) INO=${1#--ino=}; shift;; + --hex=*) HEX=${1#--hex=}; shift;; + --port=*) PORT=${1#--port=}; shift;; + --baud=*) BAUD=${1#--baud=}; shift;; + --*=*) shift;; + --) shift; break;; + *) break;; + esac + done + + if [ "${PORT}" = "" ] ; then + case "${OS}" + in + macosx) PORT=$(echo /dev/cu.usb*);; + linux*) PORT=$(echo /dev/ttyACM*);; + windows*) PORT=com4 + *) echo "unsupported port."; exit 1;; + esac + fi + if [ "${BAUD}" = "" ] ; then + BAUD=115200 + fi + + if [ "${INO}" = "" ]; then + if [ -r "$(echo *.ino)" ] ; then + INO="$(echo *.ino)" + fi + fi + + if [ "${HEX}" = "" -a "${INO}" != "" ] ; then + HEX="${INO%.ino}".hex + fi + + if [ "$HEX" = "" ] + then + HEX="$(echo *.hex)" + fi + + if [ ! -r "${HEX}" ] ; then + echo "must specify hex file" + exit 1 + fi + + if ! ${ARDUINO_DIR}/hardware/tools/avr/bin/avrdude -C${ARDUINO_DIR}/hardware/tools/avr/etc/avrdude.conf -v -p${BOARD##*cpu=} -cwiring -P"${PORT}" -b${BAUD} -D -Uflash:w:"${HEX}":i + then + echo "upload error: avr." + exit 1 + fi +} + +upload_avr_self_test() { + echo "none" + echo "upload_avr ok" +} + +if [[ "${BASH_SOURCE[0]}" == "${0}" ]] +then + if [ "$1" == "--self-test" ] + then + shift + upload_avr_self_test "$@" + else + upload_avr "$@" + fi +fi diff --git a/ci/bin/upload_mega b/ci/bin/upload_mega new file mode 100644 index 0000000..d5de389 --- /dev/null +++ b/ci/bin/upload_mega @@ -0,0 +1,29 @@ +#!/bin/bash -x + +for inc in upload_avr +do + if [ "$(type -t $inc)" != "function" ] + then + . "$(cd "$(dirname "${BASH_SOURCE[0]}")"; pwd)"/$inc + fi +done + +upload_mega() { + upload_avr --board=arduino:avr:mega:cpu=atmega2560 "$@" +} + +upload_mega_self_test() { + echo "none" + echo "upload_mega ok" +} + +if [[ "${BASH_SOURCE[0]}" == "${0}" ]] +then + if [ "$1" == "--self-test" ] + then + shift + upload_mega_self_test "$@" + else + upload_mega "$@" + fi +fi diff --git a/ci/bin/upload_uno b/ci/bin/upload_uno new file mode 100755 index 0000000..02555a0 --- /dev/null +++ b/ci/bin/upload_uno @@ -0,0 +1,29 @@ +#!/bin/bash -x + +for inc in upload_avr +do + if [ "$(type -t $inc)" != "function" ] + then + . "$(cd "$(dirname "${BASH_SOURCE[0]}")"; pwd)"/$inc + fi +done + +upload_uno() { + upload_avr --board=arduino:avr:uno:cpu=atmega328p "$@" +} + +upload_uno_self_test() { + echo "none" + echo "upload_avr ok" +} + +if [[ "${BASH_SOURCE[0]}" == "${0}" ]] +then + if [ "$1" == "--self-test" ] + then + shift + upload_uno_self_test "$@" + else + upload_uno "$@" + fi +fi From 64cf0af69d806b4a92948c6eddf35b4580479916 Mon Sep 17 00:00:00 2001 From: Warren MacEvoy Date: Tue, 15 May 2018 00:55:08 +0545 Subject: [PATCH 40/80] ci self-test --- ci/bin/compile_avr | 1 - ci/bin/dir | 2 ++ ci/bin/dir_cache | 6 +++--- ci/bin/os | 1 + ci/bin/simavr_uno | 12 +++++++++++- ci/bin/sketchbook | 2 +- src/ArduinoUnit.h | 16 ++++++++++++++++ 7 files changed, 34 insertions(+), 6 deletions(-) diff --git a/ci/bin/compile_avr b/ci/bin/compile_avr index 55bbb4d..68a244a 100755 --- a/ci/bin/compile_avr +++ b/ci/bin/compile_avr @@ -12,7 +12,6 @@ compile_avr() { DIR="$(dir "$@")" ARDUINO_DIR="$(arduino_dir "$@")" SKETCHBOOK="$(sketchbook "$@")" - ARDUINO_PACKAGES="$(packages "$@")" ARDUINO_HARDWARE="${ARDUINO_DIR}/hardware" ARDUINO_LIBS="${SKETCHBOOK}/libraries" BOARD=arduino:avr:uno:cpu=atmega328p diff --git a/ci/bin/dir b/ci/bin/dir index 3dc66c5..6ee2fe2 100755 --- a/ci/bin/dir +++ b/ci/bin/dir @@ -1,6 +1,8 @@ #!/bin/bash dir() { + local DIR="" + while [ $# -gt 0 ] do case "$1" diff --git a/ci/bin/dir_cache b/ci/bin/dir_cache index 1f65d35..7c8df71 100755 --- a/ci/bin/dir_cache +++ b/ci/bin/dir_cache @@ -9,9 +9,9 @@ do done dir_cache() { - OS="$(os "$@")" - DIR="$(dir "$@")" - VERSION="$(version "$@")" + local OS="$(os "$@")" + local DIR="$(dir "$@")" + local VERSION="$(version "$@")" echo "${DIR}/cache/${VERSION}-${OS}" } diff --git a/ci/bin/os b/ci/bin/os index 48ba662..43a107c 100755 --- a/ci/bin/os +++ b/ci/bin/os @@ -1,6 +1,7 @@ #!/bin/bash os() { + local OS="" while [ $# -gt 0 ] do case "$1" diff --git a/ci/bin/simavr_uno b/ci/bin/simavr_uno index a831698..248b5fb 100755 --- a/ci/bin/simavr_uno +++ b/ci/bin/simavr_uno @@ -30,7 +30,7 @@ simavr_uno() { case "$1" in --background=*) BACKGROUND=${1#--background=}; shift;; - --ino=*) HEX="${1#--ino=}.hex"; shift;; + --ino=*) INO="${1#--ino=}"; shift;; --hex=*) HEX="${1#--hex=}"; shift;; --*=*) shift;; --) shift; break;; @@ -39,6 +39,16 @@ simavr_uno() { done INPUT=( "$@" ) + + if [ "${INO}" = "" ]; then + if [ -r "$(echo *.ino)" ] ; then + INO="$(echo *.ino)" + fi + fi + + if [ "${HEX}" = "" -a "${INO}" != "" ] ; then + HEX="${INO%.ino}".hex + fi if [ "$HEX" = "" ] then diff --git a/ci/bin/sketchbook b/ci/bin/sketchbook index dd7ef01..d789cec 100755 --- a/ci/bin/sketchbook +++ b/ci/bin/sketchbook @@ -9,7 +9,7 @@ do done sketchbook() { - DIR="$(dir "$@")" + local DIR="$(dir "$@")" while [ $# -gt 0 ] do diff --git a/src/ArduinoUnit.h b/src/ArduinoUnit.h index 89ecb67..08f8148 100644 --- a/src/ArduinoUnit.h +++ b/src/ArduinoUnit.h @@ -830,3 +830,19 @@ is in another file (or defined after the assertion on it). */ assertRelativelyNearMsg(a,b,max,ARDUINO_UNIT_STRING(""),) #define assertRelativelyNear(...) ArduinoUnitMacroChoose5(assertRelativelyNear_, ## __VA_ARGS__)(__VA_ARGS__) + +#if defined(ARDUINO) +#define ARDUINO_UNIT_TESTS \ + void setup() { Serial.begin(115200L); while (!Serial) {}; } \ + void loop() { Test::run(); } +#else +#define ARDUINO_UNIT_TESTS \ + int main(int argc, const char *argv[]) { \ + for (int i=1; i 0); \ + return Test::getCurrentFailed() == 0 ? 0 : 1; \ + } +#endif From cd98350b19fb75df2fa65c745dba75c3d6d3a2f7 Mon Sep 17 00:00:00 2001 From: Warren MacEvoy Date: Tue, 15 May 2018 00:57:09 +0545 Subject: [PATCH 41/80] continuous integration tools. --- ci.md | 125 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 125 insertions(+) create mode 100644 ci.md diff --git a/ci.md b/ci.md new file mode 100644 index 0000000..ce69684 --- /dev/null +++ b/ci.md @@ -0,0 +1,125 @@ +# CI - Continuous Integration + +This is preliminary support for continuous integration. These have been tested in Linux (Ubuntu 16.04) and Mac OSX. These are tool agnostic: you can run them by hand, as part of a commit hook (no server), or using a continuous integration service like Travis CI or Jenkins. They also support en vitro, simulator, and en vivo tests. + +## Install + +There really is nothing to install. The CI tools are bash scripts that can be run from anywhere. They maintain a set of IDE's under the $HOME/.arduino directory so you can test your project with different versions of the IDE and different installed libraries. + +### Prerequisites + +#### macosx + +On a OS X, you will have to install the XCode command line tools, homebrew, libelf and the avr-gcc tools. You will need an internet connection and some time (20 minutes): + +```bash +if ! which git ; then xcode-select --install ; fi # xcode cli +if ! which brew ; then /usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)" ; fi # homebrew +if ! which curl ; then brew install curl ; fi # curl +if ! which avr-gcc ; then brew tap osx-cross/homebrew-avr && brew install avr-gcc ; fi # avr-gcc +if [ -f /usr/local/lib/libelf.a ] ; then brew install libelf ; fi # libelf +``` + +#### linux + +In linux, you need the gcc compiler, make git and curl: + +```bash +sudo apt install -y g++ make git curl +``` + +or similar... + +#### windows + +Install Windows Subsystem for Linux, then Ubuntu under WSL, then follow the linux instructions in a WSL/Ubuntu terminal. I think. + +This has not been tested in windows. I believe using the Windows Subsystem for Linux and installing Ubuntu 16.04 would be a path to success [WSL](https://devtidbits.com/2017/06/08/run-ubuntu-16-04-on-windows-10-creators-update/), although some tweaks may be necessary. __All commands are assumed to be running from a bash shell.___ + +### Setup + +Copy the arduinounit (or at least the ci sub-folder) and its contents to clone this repository in your projects folder, as in: + +```bash +mkdir -p "$HOME/projects" +cd "$HOME/projects" +git clone https://github.com/mmurdoch/arduinounit.git +``` + +Create a bash function to quickly use the CI tools (don't put them in your path, it will be confusing about which versions of tools you are using). This might go in your "$HOME/.profile", for example: + +```bash +au() { + # use your location here. + local AU="$HOME/projects/arduinounit" + local cmd="$1" + shift + "$AU/ci/bin/$cmd" +} +export -f au +``` + +To test (you may have to log out and log back in), try: + +```bash +au dir +au dir_cache +au arduino_dir +au sketchbook +au arduino --pref update.check=true --install-library ArduinoUnit +``` + +In the `examples/basic` arduinounit folder, try, + +```bash +au compile_uno +au simavr_uno +``` + +If you want to see the output in junit format (you really don't, but Jenkins, TravisCI and similar CI tools do), try + +```bash +au simavr_uno | au au2ju +``` + +In the vitro example, you can run tests 3 different ways: on the hardware, on the simulator, or on the dev system: + +```bash +au compile_mock +./vitro +./vitro | au au2ju +au compile_uno +au simavr_uno --hex=vitro.hex +au upload_uno +``` + +You may have to specify --port=[port] to upload, assuming an UNO board is connected. + +These all take `--os=(macosx|linux64|linux32|linuxarm|windows)` and `--version=(arduino_ide_version)` options. + +### Important + +The CI tools do NOT use the standard install location for arduino. This is because tool configuration tests [checking if your project builds with certain version of the IDE or dependent librarie(s)] would be very inconvenient if that required the removal and installation of your standard arduino environment. Instead the IDE and simavr tools are cached in a directory structure: + +```bash +${HOME}/.arduino/ + cache/ + arduino-${VERSION}-${OS}(.zip|.tar.xz) + arduino-${VERSION}-${OS}(.zip|.tar.xz).sha512sum.txt + simavr/ + ... git clone https://github.com/buserror/simavr . + ${VERSION}-${OS}/ + ... + portable/ + sketchbook/ + libraries/ +``` + +The CI tools install the IDE in "portable" mode so they do not use or modify your default IDE. When making a "clean install test", do NOT delete the zip/tar files in the cache. These are checked against the very secure sha512 (and will be re-downloaded if they checksum fails). Downloading these again is very slow and a waste of bandwidth. + +A clean (cached) install can be started with: + +```bash +/bin/rm -rf "$(au dir_cache)" +/bin/rm -rf "$(au dir)/portable" +``` From ce10afbf84b094d77535271dab438e5382866a77 Mon Sep 17 00:00:00 2001 From: Matthijs Kooijman Date: Thu, 17 May 2018 11:16:03 +0200 Subject: [PATCH 42/80] Put mergeable progmem strings in a separate section The `ARDUINO_UNIT_PSTR` macro puts strings in the .progmem.data section, and set the S (contains zero terminated strings) and M (mergeable) attributes. Unlike the normal PROGMEM/PSTR macros, which do not set these attributes, this allows for merging of duplicate or partly overlapping strings. However, when the regular PROGMEM attribute is also used, this will put other variables into the same .progmem.data section, but without these attributes. The compiler complains about this: /tmp/cco2ytva.s: Assembler messages: /tmp/cco2ytva.s:2658: Warning: ignoring changed section attributes for .progmem.data This seems harmless, but effectively causes the SM attributes to be applied to all progmem data, making the linker believe that all progmem data consists of mergeable zero-terminated strings, which can cause problems. For example, when progmem contains any variables with embedded zeroes, these variables will be truncated at the first embedded zero (but the code accessing these variables is unchanged, so these will access data from the next variable instead). For example, the `port_to_output_PGM` variable for the Arduino mega (variants/mega/pins_arduino.h) is one such variable, which contains embedded zeroes and is put into progmem. The following sketch can reproduce this problem: #include void setup() { assertTrue(true); digitalWrite(0, LOW); } void loop() { } After compiling this sketch for the Arduino Mega2560, the generated symbol table looks like this: $ avr-objdump -t sketch.elf --demangle|sort|grep port_to_output_PGM -A 1 00000156 l O .text 0000001a port_to_output_PGM 0000015d l O .text 00000056 digital_pin_to_port_PGM As you can see, the port_to_output_PGM is 0x1a bytes long and should take space up to 0x156+0x1a = 0x170, but the next variable starts at 0x15d already. It seems that for other boards, such as the Arduino Uno, these variables do not contain any embedded zeroes (only leading zeroes, which apparently are not a problem), so the problem does not surface there. To fix this, this commit changes the section name used by the `ARDUINO_UNIT_PSTR` macro to `.progmem.mergeable-strings`, so the section attribute only affects these particular strings, and not other progmem data. The linker scripts used by avr-libc use a wildcard `*(.progmem*)` to include progmem symbols, so any sections starting with `.progmem` are included in the link (checked in avr-libc 1:1.8.0+Atmel3.5.0-1 from Debian that all linker scripts that reference progmem use the wildcard). --- src/ArduinoUnitUtility/Flash.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ArduinoUnitUtility/Flash.h b/src/ArduinoUnitUtility/Flash.h index 9b07dd6..bdf7012 100644 --- a/src/ArduinoUnitUtility/Flash.h +++ b/src/ArduinoUnitUtility/Flash.h @@ -13,7 +13,7 @@ PGM_P ptr; \ asm volatile \ ( \ - ".pushsection .progmem.data, \"SM\", @progbits, 1" "\n\t" \ + ".pushsection .progmem.mergeable-strings, \"SM\", @progbits, 1" "\n\t" \ "0: .string " #str "\n\t" \ ".popsection" "\n\t" \ ); \ From 11517ec1d3584ece495d1a841d13fd17cbb3ddd4 Mon Sep 17 00:00:00 2001 From: Matthijs Kooijman Date: Thu, 17 May 2018 11:24:09 +0200 Subject: [PATCH 43/80] Fix indentation after previous commit This fixes the indentation of the inline assembly, which is messed up by the previous commit. This is a separate commit, to separate the code change from the indentation-only changes. --- src/ArduinoUnitUtility/Flash.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/ArduinoUnitUtility/Flash.h b/src/ArduinoUnitUtility/Flash.h index bdf7012..da3220b 100644 --- a/src/ArduinoUnitUtility/Flash.h +++ b/src/ArduinoUnitUtility/Flash.h @@ -14,13 +14,13 @@ asm volatile \ ( \ ".pushsection .progmem.mergeable-strings, \"SM\", @progbits, 1" "\n\t" \ - "0: .string " #str "\n\t" \ - ".popsection" "\n\t" \ + "0: .string " #str "\n\t" \ + ".popsection" "\n\t" \ ); \ asm volatile \ ( \ - "ldi %A0, lo8(0b)" "\n\t" \ - "ldi %B0, hi8(0b)" "\n\t" \ + "ldi %A0, lo8(0b)" "\n\t" \ + "ldi %B0, hi8(0b)" "\n\t" \ : "=d" (ptr) \ ); \ ptr; \ From 218fbd1132cfb34d25e19d5d553c5de61a601528 Mon Sep 17 00:00:00 2001 From: Warren MacEvoy Date: Mon, 11 Jun 2018 19:54:21 +0545 Subject: [PATCH 44/80] version update --- CHANGELOG.md | 74 ++++++++++++++++++++++++---------------------- library.properties | 2 +- 2 files changed, 40 insertions(+), 36 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7982241..c8b0d77 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,50 +2,54 @@ ## 2.0.0 -* Rewrite + * Rewrite ## 2.1 -* Updated documentation -* Tests for FakeStreamBuffer -* Support for Arduino Due -* Support for Flash Strings (avoid namespace collision with Arduino String) -* Reset of FakeStream + * Updated documentation + * Tests for FakeStreamBuffer + * Support for Arduino Due + * Support for Flash Strings (avoid namespace collision with Arduino String) + * Reset of FakeStream ## 2.1.1 -* Support for Arduino Due (adjust examples) -* Add library.properties file + * Support for Arduino Due (adjust examples) + * Add library.properties file ## 2.2.0 -* Move to Arduino 1.5 compliant library directory structure -* Move utility to ArduinoUnitUtility to avoid conflict with other libraries -* Adjust firmware test to explain basic usage -* Support for comparing various string types in (#iss47) -* Add Compare.h and mkCompare in meta for comparing strings + * Move to Arduino 1.5 compliant library directory structure + * Move utility to ArduinoUnitUtility to avoid conflict with other libraries + * Adjust firmware test to explain basic usage + * Support for comparing various string types in (#iss47) + * Add Compare.h and mkCompare in meta for comparing strings ## 2.3.0 -* Remove support of very old gcc compiler -* Add support for de-duplicaton of flash strings -* Add support for ESP 8266 and ESP 32 -* Use more standard file names (README.md, LICENSE, and CHANGELOG.md) -* Use less likely to fail version of `while (!Serial) {}` in examples and documentation. -* Make Test::TestString ArduinoUnitString, and refactor Compare to leverage that code. -* Add an optional lazy message last argument to every assert. -* Add building outside of arduino environment -* Significant reduction of code implementation and compiled size (Compare.h is now small) -* Add minimal mock builds on dev (in vitro) platform -* Add better mock builds. -* Use type widening to reduce specializations. -* Depricate FakeStream for MockStream and MockPrint -* Resolve a sentence=Flexible test framework for arduino projects. From daa6cc35f6535a953fc6df75dca475591e1913a7 Mon Sep 17 00:00:00 2001 From: Warren MacEvoy Date: Mon, 11 Jun 2018 19:56:40 +0545 Subject: [PATCH 45/80] new macro names --- keywords.txt | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/keywords.txt b/keywords.txt index aa1e93a..9ad4dd8 100644 --- a/keywords.txt +++ b/keywords.txt @@ -5,6 +5,8 @@ assertFalse KEYWORD2 assertLess KEYWORD2 assertLessOrEqual KEYWORD2 assertEqual KEYWORD2 +assertNear KEYWORD2 +assertRelativelyNear KEYWORD2 assertNotEqual KEYWORD2 assertMoreOrEqual KEYWORD2 assertMore KEYWORD2 @@ -24,6 +26,14 @@ checkTestFail KEYWORD2 checkTestNotFail KEYWORD2 checkTestSkip KEYWORD2 checkTestNotSkip KEYWORD2 +checkCurrentTestDone KEYWORD2 +checkCurrentTestNotDone KEYWORD2 +checkCurrentTestPass KEYWORD2 +checkCurrentTestNotPass KEYWORD2 +checkCurrentTestFail KEYWORD2 +checkCurrentTestNotFail KEYWORD2 +checkCurrentTestSkip KEYWORD2 +checkCurrentTestNotSkip KEYWORD2 TEST_VERBOSITY_ALL LITERAL1 TEST_VERBOSITY_NONE LITERAL1 From 0af78db9a2db2c6ab95fae5c48636483c97b8b1b Mon Sep 17 00:00:00 2001 From: per1234 Date: Tue, 17 Jul 2018 02:37:19 -0700 Subject: [PATCH 46/80] Use correct field separator in keywords.txt The Arduino IDE requires the use of a single true tab separator between the keyword name and identifier. When spaces are used rather than a true tab the keyword is not highlighted. Reference: https://github.com/arduino/Arduino/wiki/Arduino-IDE-1.5:-Library-specification#keywords --- keywords.txt | 88 ++++++++++++++++++++++++++-------------------------- 1 file changed, 44 insertions(+), 44 deletions(-) diff --git a/keywords.txt b/keywords.txt index 9ad4dd8..0f0aa3c 100644 --- a/keywords.txt +++ b/keywords.txt @@ -1,49 +1,49 @@ -test KEYWORD1 -testing KEYWORD1 -assertTrue KEYWORD2 -assertFalse KEYWORD2 -assertLess KEYWORD2 -assertLessOrEqual KEYWORD2 -assertEqual KEYWORD2 -assertNear KEYWORD2 -assertRelativelyNear KEYWORD2 -assertNotEqual KEYWORD2 -assertMoreOrEqual KEYWORD2 -assertMore KEYWORD2 -assertTestDone KEYWORD2 -assertTestNotDone KEYWORD2 -assertTestPass KEYWORD2 -assertTestNotPass KEYWORD2 -assertTestFail KEYWORD2 -assertTestNotFail KEYWORD2 -assertTestSkip KEYWORD2 -assertTestNotSkip KEYWORD2 -checkTestDone KEYWORD2 -checkTestNotDone KEYWORD2 -checkTestPass KEYWORD2 -checkTestNotPass KEYWORD2 -checkTestFail KEYWORD2 -checkTestNotFail KEYWORD2 -checkTestSkip KEYWORD2 -checkTestNotSkip KEYWORD2 -checkCurrentTestDone KEYWORD2 -checkCurrentTestNotDone KEYWORD2 -checkCurrentTestPass KEYWORD2 -checkCurrentTestNotPass KEYWORD2 -checkCurrentTestFail KEYWORD2 -checkCurrentTestNotFail KEYWORD2 -checkCurrentTestSkip KEYWORD2 -checkCurrentTestNotSkip KEYWORD2 +test KEYWORD1 +testing KEYWORD1 +assertTrue KEYWORD2 +assertFalse KEYWORD2 +assertLess KEYWORD2 +assertLessOrEqual KEYWORD2 +assertEqual KEYWORD2 +assertNear KEYWORD2 +assertRelativelyNear KEYWORD2 +assertNotEqual KEYWORD2 +assertMoreOrEqual KEYWORD2 +assertMore KEYWORD2 +assertTestDone KEYWORD2 +assertTestNotDone KEYWORD2 +assertTestPass KEYWORD2 +assertTestNotPass KEYWORD2 +assertTestFail KEYWORD2 +assertTestNotFail KEYWORD2 +assertTestSkip KEYWORD2 +assertTestNotSkip KEYWORD2 +checkTestDone KEYWORD2 +checkTestNotDone KEYWORD2 +checkTestPass KEYWORD2 +checkTestNotPass KEYWORD2 +checkTestFail KEYWORD2 +checkTestNotFail KEYWORD2 +checkTestSkip KEYWORD2 +checkTestNotSkip KEYWORD2 +checkCurrentTestDone KEYWORD2 +checkCurrentTestNotDone KEYWORD2 +checkCurrentTestPass KEYWORD2 +checkCurrentTestNotPass KEYWORD2 +checkCurrentTestFail KEYWORD2 +checkCurrentTestNotFail KEYWORD2 +checkCurrentTestSkip KEYWORD2 +checkCurrentTestNotSkip KEYWORD2 -TEST_VERBOSITY_ALL LITERAL1 -TEST_VERBOSITY_NONE LITERAL1 +TEST_VERBOSITY_ALL LITERAL1 +TEST_VERBOSITY_NONE LITERAL1 -TEST_VERBOSITY_TESTS_SUMMARY LITERAL1 -TEST_VERBOSITY_TESTS_PASSED LITERAL1 -TEST_VERBOSITY_TESTS_FAILED LITERAL1 -TEST_VERBOSITY_TESTS_SKIPPED LITERAL1 -TEST_VERBOSITY_TESTS_ALL LITERAL1 +TEST_VERBOSITY_TESTS_SUMMARY LITERAL1 +TEST_VERBOSITY_TESTS_PASSED LITERAL1 +TEST_VERBOSITY_TESTS_FAILED LITERAL1 +TEST_VERBOSITY_TESTS_SKIPPED LITERAL1 +TEST_VERBOSITY_TESTS_ALL LITERAL1 TEST_VERBOSITY_ASSERTIONS_PASSED LITERAL1 TEST_VERBOSITY_ASSERTIONS_FAILED LITERAL1 -TEST_VERBOSITY_ASSERTIONS_ALL LITERAL1 +TEST_VERBOSITY_ASSERTIONS_ALL LITERAL1 From 117e71a61c38db1cc91873bfdf9a2062ff1cf44c Mon Sep 17 00:00:00 2001 From: Warren MacEvoy Date: Sun, 17 Feb 2019 02:52:42 +0000 Subject: [PATCH 47/80] make context script --- ci/context | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 ci/context diff --git a/ci/context b/ci/context new file mode 100644 index 0000000..aab3e99 --- /dev/null +++ b/ci/context @@ -0,0 +1,19 @@ +# find directory of this sourced context + +pushd $(dirname "${BASH_SOURCE[0]}") >/dev/null +arduinounit_ci_bin="$PWD/bin" +popd >/dev/null + +# remove directory from path +PATH=":$PATH:" +while [ "${PATH/:$arduinounit_ci_bin:/:}" != "$PATH" ] ; do PATH="${PATH/:$arduinounit_ci_bin:/:}"; done + +# place directory first +PATH="$arduinounit_ci_bin${PATH%:}" + +# invalidate cache +hash -r + +eval 'au() { local cmd="$1"; shift; "'"$arduinounit_ci_bin"'/$cmd" "$@"; }; export -f au;' + + From 0001840a90cc30aa55ddbcb32cc0e5b2606346df Mon Sep 17 00:00:00 2001 From: Warren MacEvoy Date: Sun, 17 Feb 2019 03:00:11 +0000 Subject: [PATCH 48/80] do not set path --- ci/context | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/ci/context b/ci/context index aab3e99..16b359f 100644 --- a/ci/context +++ b/ci/context @@ -4,16 +4,6 @@ pushd $(dirname "${BASH_SOURCE[0]}") >/dev/null arduinounit_ci_bin="$PWD/bin" popd >/dev/null -# remove directory from path -PATH=":$PATH:" -while [ "${PATH/:$arduinounit_ci_bin:/:}" != "$PATH" ] ; do PATH="${PATH/:$arduinounit_ci_bin:/:}"; done - -# place directory first -PATH="$arduinounit_ci_bin${PATH%:}" - -# invalidate cache -hash -r - eval 'au() { local cmd="$1"; shift; "'"$arduinounit_ci_bin"'/$cmd" "$@"; }; export -f au;' From e840009da9bc8a63a129e137d33c2c0ad7784a28 Mon Sep 17 00:00:00 2001 From: Warren MacEvoy Date: Sun, 17 Feb 2019 03:00:32 +0000 Subject: [PATCH 49/80] move to better name --- ci/{context => au} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename ci/{context => au} (100%) diff --git a/ci/context b/ci/au similarity index 100% rename from ci/context rename to ci/au From 15749d5e63da3f2cd07eebda12dac9cb461e1b9c Mon Sep 17 00:00:00 2001 From: Warren MacEvoy Date: Sun, 17 Feb 2019 05:08:14 +0000 Subject: [PATCH 50/80] build-test on pi --- ci/bin/make_simavr_uno | 15 ++++++++++++--- ci/bin/make_simavr_uno.patch | 36 ++++++++++++++++++++++++++++++++++++ ci/bin/simavr_uno | 13 ++++++++++++- 3 files changed, 60 insertions(+), 4 deletions(-) create mode 100644 ci/bin/make_simavr_uno.patch diff --git a/ci/bin/make_simavr_uno b/ci/bin/make_simavr_uno index 0823feb..7076107 100755 --- a/ci/bin/make_simavr_uno +++ b/ci/bin/make_simavr_uno @@ -1,6 +1,6 @@ #!/bin/bash -x -for inc in dir os version cache_simavr avr_root arduino_exe +for inc in dir os version cache_simavr avr_root arduino_exe package_install do if [ "$(type -t $inc)" != "function" ] then @@ -61,19 +61,28 @@ make_simavr_uno() { fi fi + if [ "$OS" = "macosx" ] + then + package_install libelf + else + package_install libelf-dev || package_install libelf-devel + fi + /bin/rm -rf "$DIR/cache/${VERSION}-${OS}/simavr/repo" mkdir -p "$DIR/cache/${VERSION}-${OS}/simavr/repo" tar -C "$DIR/cache/simavr" -cf - . | tar -C "$DIR/cache/${VERSION}-${OS}/simavr/repo" -xf - - (cd "$DIR/cache/${VERSION}-${OS}/simavr/repo"; git checkout -f "$BRANCH") + (cd "$DIR/cache/${VERSION}-${OS}/simavr/repo"; git checkout -f "$BRANCH"; git apply "$(cd "$(dirname "${BASH_SOURCE[0]}")"; pwd)/make_simavr_uno.patch" ) export AVR_ROOT - + if ! PATH="$AVR_ROOT/bin:$PATH" make -e -B -C "$DIR/cache/${VERSION}-${OS}/simavr/repo" clean build-simavr then echo "build-simavr target failed." exit 1 fi + + if ! PATH="$AVR_ROOT/bin:$PATH" make -e -B -C "$DIR/cache/${VERSION}-${OS}/simavr/repo/examples/board_simduino" clean all then echo "build board_simduino target failed." diff --git a/ci/bin/make_simavr_uno.patch b/ci/bin/make_simavr_uno.patch new file mode 100644 index 0000000..d17beca --- /dev/null +++ b/ci/bin/make_simavr_uno.patch @@ -0,0 +1,36 @@ +diff --git a/examples/board_simduino/Makefile b/examples/board_simduino/Makefile +index b1e970f..c4e8a85 100644 +--- a/examples/board_simduino/Makefile ++++ b/examples/board_simduino/Makefile +@@ -31,7 +31,7 @@ VPATH += ../parts + + LDFLAGS += -lpthread -lutil + +-include ../Makefile.opengl ++# include ../Makefile.opengl + + all: obj ${firmware} ${target} + +diff --git a/examples/board_simduino/simduino.c b/examples/board_simduino/simduino.c +index 007b383..a9c0e0a 100644 +--- a/examples/board_simduino/simduino.c ++++ b/examples/board_simduino/simduino.c +@@ -27,12 +27,12 @@ + #include + #include + +-#if __APPLE__ +-#include +-#else +-#include +-#endif +-#include ++// #if __APPLE__ ++// #include ++// #else ++// #include ++// #endif ++// #include + + #include "sim_avr.h" + #include "avr_ioport.h" diff --git a/ci/bin/simavr_uno b/ci/bin/simavr_uno index 248b5fb..7a6fce3 100755 --- a/ci/bin/simavr_uno +++ b/ci/bin/simavr_uno @@ -1,6 +1,6 @@ #!/bin/bash -for inc in dir os version +for inc in dir os version make_simavr_uno do if [ "$(type -t $inc)" != "function" ] then @@ -60,6 +60,17 @@ simavr_uno() { exit 1 fi + if [ ! -x "${DIR}/cache/${VERSION}-${OS}/simavr/uno" ] + then + make_simavr_uno "$@" + fi + + if [ ! -x "${DIR}/cache/${VERSION}-${OS}/simavr/uno" ] + then + echo "could not make simavr/uno" + exit 1 + fi + SIMAVR_UNO_PIDS="" trap simavr_uno_exit EXIT From 1dd70aa1c90d70568ad2f26c7d1c9da7a997470c Mon Sep 17 00:00:00 2001 From: Warren MacEvoy Date: Sun, 17 Feb 2019 05:25:37 +0000 Subject: [PATCH 51/80] skip slow tests with --fast --- ci/bin/ci_self_test | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/ci/bin/ci_self_test b/ci/bin/ci_self_test index 4e93e4e..0411a75 100755 --- a/ci/bin/ci_self_test +++ b/ci/bin/ci_self_test @@ -2,6 +2,8 @@ CI_SELF_TESTS=(dir dir_cache preferences sketchbook arduino_exe cache_ide avr_bin avr_root cache_simavr make_simavr_uno simavr_uno compile_sources compile_vitro compile_uno ) +CI_SLOW_TESTS=(cache_ide cache_simavr) + for ci_test in "${CI_SELF_TESTS[@]}" do if [ "$(type -t $ci_test)" != "function" ] @@ -11,8 +13,26 @@ do done ci_self_test() { + local fast=false + if [ "$1" == "--fast" ] + then + fast=true + fi + for ci_test in "${CI_SELF_TESTS[@]}" do + if [ $fast = true ] + then + for slow in "${CI_SLOW_TESTS[@]}" + do + if [ "$slow" = "$ci_test" ] + then + echo "skipping slow test $ci_test." + continue 2 + fi + done + fi + echo "testing $ci_test." ${ci_test}_self_test "$@" done From 8a3409a31191ebe96aa715acc3890064648c75e1 Mon Sep 17 00:00:00 2001 From: Warren MacEvoy Date: Sun, 17 Feb 2019 05:53:11 +0000 Subject: [PATCH 52/80] better error reporting --- ci/bin/cache_ide | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ci/bin/cache_ide b/ci/bin/cache_ide index d1661fd..03d4f6a 100755 --- a/ci/bin/cache_ide +++ b/ci/bin/cache_ide @@ -93,6 +93,8 @@ cache_ide() { then OK=true break + else + echo "cannot find ${ARCHIVE} in ${CACHE}/${CHECKSUM} (retry)" fi fi curl --connect-timeout "$TIMEOUT" -o "${CACHE}/${CHECKSUM}" "https://downloads.arduino.cc/${CHECKSUM}" From 799563553358d89cdd4b0620742be4711e941b5e Mon Sep 17 00:00:00 2001 From: Warren MacEvoy Date: Sun, 17 Feb 2019 05:55:46 +0000 Subject: [PATCH 53/80] ci pi+mac! --- ci.md | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/ci.md b/ci.md index ce69684..03c9a7a 100644 --- a/ci.md +++ b/ci.md @@ -41,23 +41,19 @@ This has not been tested in windows. I believe using the Windows Subsystem for Copy the arduinounit (or at least the ci sub-folder) and its contents to clone this repository in your projects folder, as in: ```bash +# the directory is where you keep your projects... mkdir -p "$HOME/projects" cd "$HOME/projects" git clone https://github.com/mmurdoch/arduinounit.git ``` -Create a bash function to quickly use the CI tools (don't put them in your path, it will be confusing about which versions of tools you are using). This might go in your "$HOME/.profile", for example: +To make the tools easier to use, you can define the `au` bash function by sourcing `au` in the `ci` directory (notice the dot with a space): + +``` +. "$HOME/projects/arduinounit/ci/au" -```bash -au() { - # use your location here. - local AU="$HOME/projects/arduinounit" - local cmd="$1" - shift - "$AU/ci/bin/$cmd" -} -export -f au ``` +You can put this in your `.profile` if you like, so it is set every time you log in. To test (you may have to log out and log back in), try: @@ -66,7 +62,7 @@ au dir au dir_cache au arduino_dir au sketchbook -au arduino --pref update.check=true --install-library ArduinoUnit +au arduino --pref update.check=false --install-library ArduinoUnit ``` In the `examples/basic` arduinounit folder, try, From 44b3fe6ea61b565a5ff65037739104233f3a6e5b Mon Sep 17 00:00:00 2001 From: Warren MacEvoy Date: Sun, 17 Feb 2019 06:03:15 +0000 Subject: [PATCH 54/80] package_install script --- ci/bin/package_install | 40 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) create mode 100644 ci/bin/package_install diff --git a/ci/bin/package_install b/ci/bin/package_install new file mode 100644 index 0000000..713e5e5 --- /dev/null +++ b/ci/bin/package_install @@ -0,0 +1,40 @@ +#!/bin/bash + +package_install() { + local package_installer=() + + # https://unix.stackexchange.com/questions/46081/identifying-the-system-package-manager + + if [ -f /etc/debian_version ] + then + package_installer=("sudo" "/usr/bin/apt-get" "-y" "install") + elif [ -f /etc/redhat-release ] + then + package_installer=("sudo" "/usr/bin/yum" "-y" "install") + elif [ -f /etc/SuSE-release ] + then + package_installer=("sudo" "/usr/bin/zypper" "--non-interactive" "install") + elif [ -f /etc/alpine-release ] + then + package_installer=("sudo" "/usr/bin/apk" "add") + elif [ -f /usr/local/bin/brew ] + then + package_installer=("/usr/local/bin/brew" "install") + elif [ -f /opt/local/lib/port ] + then + package_installer=("sudo" "port" "install") + fi + + if [ ${#package_installer[@]} -eq 0 ] + then + echo "could not determine package installer." + exit 1 + fi + + "${package_installer[@]}" "$@" +} + +if [[ "${BASH_SOURCE[0]}" == "${0}" ]] +then + package_install "$@" +fi From 59bf2797836457b2fdb869fb3057c3b9739f37bf Mon Sep 17 00:00:00 2001 From: Warren MacEvoy Date: Sun, 17 Feb 2019 01:06:58 -0500 Subject: [PATCH 55/80] add unzip/tar if commands are missing --- ci/bin/cache_ide | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/ci/bin/cache_ide b/ci/bin/cache_ide index 03d4f6a..0b6efb7 100755 --- a/ci/bin/cache_ide +++ b/ci/bin/cache_ide @@ -1,6 +1,6 @@ #!/bin/bash -for inc in os dir dir_cache version arduino_exe +for inc in os dir dir_cache version arduino_exe package_install do if [ "$(type -t $inc)" != "function" ] then @@ -137,8 +137,16 @@ cache_ide() { pushd "${DIR_CACHE}" if [ "${EXTENSION}" = "zip" ] then + if ! which unzip + then + package_install unzip + fi unzip -a -o "${CACHE}/${ARCHIVE}" > /dev/null else + if ! which tar + then + package_install tar + fi tar -xf "${CACHE}/${ARCHIVE}" fi From ce23585e16ef52bcde1289d717c2168e3421898b Mon Sep 17 00:00:00 2001 From: Warren MacEvoy Date: Sun, 17 Feb 2019 01:09:00 -0500 Subject: [PATCH 56/80] update default version --- ci/bin/version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ci/bin/version b/ci/bin/version index db38bf5..181a72a 100755 --- a/ci/bin/version +++ b/ci/bin/version @@ -20,7 +20,7 @@ version() { if [ "$VERSION" = "" ] then - VERSION="1.8.5" + VERSION="1.8.8" fi echo $VERSION } From 93086a7a076001bab88453be80899a15effeff2b Mon Sep 17 00:00:00 2001 From: Warren MacEvoy Date: Sun, 17 Feb 2019 06:57:51 +0000 Subject: [PATCH 57/80] local vars --- ci/bin/arduino | 4 ++-- ci/bin/arduino_dir | 6 +++--- ci/bin/arduino_exe | 6 +++--- ci/bin/avr_bin | 6 ------ ci/bin/cache_ide | 46 ++++++++++++++++++++++-------------------- ci/bin/cache_simavr | 4 ++-- ci/bin/ci_self_test | 1 + ci/bin/compile_avr | 32 ++++++++++++++--------------- ci/bin/compile_sources | 4 +++- ci/bin/compile_vitro | 20 +++++++++--------- ci/bin/dir | 4 ++-- ci/bin/make_simavr_uno | 22 +++++++++++--------- ci/bin/preferences | 6 +++--- ci/bin/simavr_uno | 46 +++++++++++++++++++++--------------------- ci/bin/sketchbook | 4 ++-- ci/bin/upload_avr | 42 +++++++++++++++++++------------------- ci/bin/version | 4 ++-- 17 files changed, 130 insertions(+), 127 deletions(-) diff --git a/ci/bin/arduino b/ci/bin/arduino index 8d4271b..b21050c 100755 --- a/ci/bin/arduino +++ b/ci/bin/arduino @@ -9,7 +9,7 @@ do done arduino() { - ARDUINO_EXE="$(arduino_exe "$@")" + local ARDUINO_EXE="$(arduino_exe "$@")" if [ ! -r "$ARDUINO_EXE" ] then @@ -24,7 +24,7 @@ arduino() { arduino_self_test() { arduino "$@" & - PID="$!" + local PID="$!" if [ "${PID}" = "" ] then echo "no launch" diff --git a/ci/bin/arduino_dir b/ci/bin/arduino_dir index e2fe27f..1a8cc12 100755 --- a/ci/bin/arduino_dir +++ b/ci/bin/arduino_dir @@ -9,9 +9,9 @@ do done arduino_dir() { - OS="$(os "$@")" - DIR="$(dir "$@")" - VERSION="$(version "$@")" + local OS="$(os "$@")" + local DIR="$(dir "$@")" + local VERSION="$(version "$@")" if [ "$OS" = "macosx" ] then diff --git a/ci/bin/arduino_exe b/ci/bin/arduino_exe index da56386..38b9517 100755 --- a/ci/bin/arduino_exe +++ b/ci/bin/arduino_exe @@ -9,9 +9,9 @@ do done arduino_exe() { - OS="$(os "$@")" - VERSION="$(version "$@")" - DIR_CACHE="$(dir_cache "$@")" + local OS="$(os "$@")" + local VERSION="$(version "$@")" + local DIR_CACHE="$(dir_cache "$@")" if [ "$OS" = "macosx" ] then diff --git a/ci/bin/avr_bin b/ci/bin/avr_bin index 428fd66..5cc1721 100755 --- a/ci/bin/avr_bin +++ b/ci/bin/avr_bin @@ -8,12 +8,6 @@ do fi done - -if [ "$(type -t arduino_dir)" != "function" ] -then - . "$(cd "$(dirname "${BASH_SOURCE[0]}")"; pwd)"/arduino_dir -fi - avr_bin() { echo "$(arduino_dir "$@")/hardware/tools/avr/bin" } diff --git a/ci/bin/cache_ide b/ci/bin/cache_ide index 0b6efb7..6464465 100755 --- a/ci/bin/cache_ide +++ b/ci/bin/cache_ide @@ -9,20 +9,19 @@ do done cache_ide() { - OS="$(os "$@")" - DIR="$(dir "$@")" - DIR_CACHE="$(dir_cache "$@")" - VERSION="$(version "$@")" - ARDUINO_EXE="$(arduino_exe "$@")" + local OS="$(os "$@")" + local DIR="$(dir "$@")" + local DIR_CACHE="$(dir_cache "$@")" + local VERSION="$(version "$@")" + local ARDUINO_EXE="$(arduino_exe "$@")" while [ $# -gt 0 ] do case "$1" in - --extension=*) EXTENSION=${1#--extension=}; shift;; - --tries=*) TRIES=${1#--tries=}; shift;; - --reload=*) RELOAD=${1#--reload=}; shift;; - --timeout=*) TIMEOUT=${1#--timeout=}; shift;; + --tries=*) local TRIES=${1#--tries=}; shift;; + --reload=*) local RELOAD=${1#--reload=}; shift;; + --timeout=*) local TIMEOUT=${1#--timeout=}; shift;; --*=*) shift;; --) shift; break;; *) break;; @@ -39,7 +38,7 @@ cache_ide() { mkdir -p "${DIR_CACHE}" fi - PORTABLE="${DIR}/portable" + local PORTABLE="${DIR}/portable" if [ ! -d "${PORTABLE}" ] then mkdir -p "${PORTABLE}" @@ -49,10 +48,10 @@ cache_ide() { then if [ "${OS}" = "macosx" -o "${OS}" = "windows" ] then - EXTENSION="zip" + local EXTENSION="zip" elif [ "${OS#linux}" != "${OS}" ] then - EXTENSION="tar.xz" + local EXTENSION="tar.xz" else echo "Unsupported architecture." exit 1 @@ -61,22 +60,22 @@ cache_ide() { if [ "${TRIES}" = "" ] then - TRIES=3 + local TRIES=3 fi if [ "${RELOAD}" = "" ] then - RELOAD=false + local RELOAD=false fi if [ "${TIMEOUT}" = "" ] then - TIMEOUT=10 + local TIMEOUT=10 fi - ARCHIVE="arduino-${VERSION}-${OS}.${EXTENSION}" - CHECKSUM="arduino-${VERSION}.sha512sum.txt" - CACHE="${DIR}/cache" + local ARCHIVE="arduino-${VERSION}-${OS}.${EXTENSION}" + local CHECKSUM="arduino-${VERSION}.sha512sum.txt" + local CACHE="${DIR}/cache" mkdir -p "${CACHE}" if [ "${RELOAD}" = "true" ] @@ -84,14 +83,15 @@ cache_ide() { /bin/rm -rf "${CACHE}/${CHECKSUM}" fi - OK=false + local OK=false + local TRY for TRY in $(seq "${TRIES}") do if [ -r "${CACHE}/${CHECKSUM}" ] then if grep -q "${ARCHIVE}" "${CACHE}/${CHECKSUM}" then - OK=true + local OK=true break else echo "cannot find ${ARCHIVE} in ${CACHE}/${CHECKSUM} (retry)" @@ -112,14 +112,15 @@ cache_ide() { exit 1 fi - OK=false + local OK=false + local TRY for TRY in $(seq "${TRIES}") do if [ -r "${CACHE}/${ARCHIVE}" ] then if cd "${CACHE}" && shasum -a512 -c "${ARCHIVE}.sha512sum.txt" > /dev/null then - OK=true + local OK=true break fi fi @@ -171,6 +172,7 @@ cache_ide() { } cache_ide_self_test() { + local os for os in macosx windows linux64 do if ! cache_ide --os=$os "$@" diff --git a/ci/bin/cache_simavr b/ci/bin/cache_simavr index 22529dd..f8b5b82 100755 --- a/ci/bin/cache_simavr +++ b/ci/bin/cache_simavr @@ -9,13 +9,13 @@ do done cache_simavr() { - DIR="$(dir "$@")" + local DIR="$(dir "$@")" while [ $# -gt 0 ] do case "$1" in - --reload=*) RELOAD=${1#--reload=}; shift;; + --reload=*) local RELOAD=${1#--reload=}; shift;; --*=*) shift;; --) shift; break;; *) break;; diff --git a/ci/bin/ci_self_test b/ci/bin/ci_self_test index 0411a75..eaee0c1 100755 --- a/ci/bin/ci_self_test +++ b/ci/bin/ci_self_test @@ -19,6 +19,7 @@ ci_self_test() { fast=true fi + local ci_test for ci_test in "${CI_SELF_TESTS[@]}" do if [ $fast = true ] diff --git a/ci/bin/compile_avr b/ci/bin/compile_avr index ce8edb6..fb58c92 100755 --- a/ci/bin/compile_avr +++ b/ci/bin/compile_avr @@ -9,20 +9,20 @@ do done compile_avr() { - DIR="$(dir "$@")" - ARDUINO_DIR="$(arduino_dir "$@")" - SKETCHBOOK="$(sketchbook "$@")" - ARDUINO_HARDWARE="${ARDUINO_DIR}/hardware" - ARDUINO_LIBS="${SKETCHBOOK}/libraries" - BOARD=arduino:avr:uno:cpu=atmega328p - ARDUINO_TARGET_DIR= + local DIR="$(dir "$@")" + local ARDUINO_DIR="$(arduino_dir "$@")" + local SKETCHBOOK="$(sketchbook "$@")" + local ARDUINO_HARDWARE="${ARDUINO_DIR}/hardware" + local ARDUINO_LIBS="${SKETCHBOOK}/libraries" + local BOARD=arduino:avr:uno:cpu=atmega328p + local ARDUINO_TARGET_DIR= while [ $# -gt 0 ] do case "$1" in - --board=*) BOARD=${1#--board=}; shift;; - --ino=*) INO=${1#--ino=}; shift;; - --tmp=*) TMP=${1#--tmp=}; shift;; + --board=*) local BOARD=${1#--board=}; shift;; + --ino=*) local INO=${1#--ino=}; shift;; + --tmp=*) local TMP=${1#--tmp=}; shift;; --*=*) shift;; --) shift; break;; *) break;; @@ -30,14 +30,14 @@ compile_avr() { done if [ "${INO}" = "" ]; then - INO="$(echo *.ino)" + local INO="$(echo *.ino)" fi if [ ! -f "${INO}" ] ; then echo "must specify ino file" exit 1 fi - ARDUINO_TARGET_DIR="$(dirname "${INO}")" + local ARDUINO_TARGET_DIR="$(dirname "${INO}")" if [ ! -d "${ARDUINO_TARGET_DIR}" ] ; then echo "missing directory ${ARDUINO_TARGET_DIR}." exit 1 @@ -47,15 +47,15 @@ compile_avr() { # Make a temp directory to work in (that is removed) # if [ "$TMP" = "" ] ; then - TMP="$(mktemp -d)" + local TMP="$(mktemp -d)" EXITS+="/bin/rm -rf '${TMP}'" trap 'for action in "${EXITS[@]}" ; do $action ; done' EXIT else mkdir -p "$TMP" fi - TMP_HEX="${TMP}/build/$(basename ${INO}).hex" - HEX="${INO%.ino}".hex + local TMP_HEX="${TMP}/build/$(basename ${INO}).hex" + local HEX="${INO%.ino}".hex mkdir -p ${TMP}/build mkdir -p ${TMP}/cache @@ -63,7 +63,7 @@ compile_avr() { (cd ${ARDUINO_TARGET_DIR}; tar cf - $(compile_sources .)) | tar -C "${TMP}/src" -xf - - ARDUINO_TARGET_EXE="${INO%.ino}" + local ARDUINO_TARGET_EXE="${INO%.ino}" ${ARDUINO_DIR}/arduino-builder -dump-prefs -logger=machine -hardware ${ARDUINO_DIR}/hardware -hardware ${ARDUINO_DIR}/hardware -tools ${ARDUINO_DIR}/tools-builder -tools ${ARDUINO_DIR}/hardware/tools/avr -built-in-libraries ${ARDUINO_DIR}/libraries -libraries ${ARDUINO_LIBS} -fqbn=${BOARD} -ide-version=10802 -build-path ${TMP}/build -warnings=all -build-cache ${TMP}/cache -prefs=build.warn_data_percentage=75 -prefs=runtime.tools.avr-gcc.path=${ARDUINO_DIR}/hardware/tools/avr -prefs=runtime.tools.arduinoOTA.path=${ARDUINO_DIR}/hardware/tools/avr -prefs=runtime.tools.avrdude.path=${ARDUINO_DIR}/hardware/tools/avr -verbose "${TMP}/src/$(basename ${INO})" 2>&1 | sed -e "s|${TMP}/build/sketch/|${ARDUINO_TARGET_DIR}/|g" diff --git a/ci/bin/compile_sources b/ci/bin/compile_sources index 2062ea6..40a83fb 100755 --- a/ci/bin/compile_sources +++ b/ci/bin/compile_sources @@ -10,7 +10,7 @@ compile_sources() { } compile_sources_self_test() { - TMP="$(mktemp -d)" + local TMP="$(mktemp -d)" trap 'rm -rf "$TMP"' EXIT mkdir -p $TMP/s/x mkdir -p $TMP/s/x/y @@ -23,6 +23,7 @@ compile_sources_self_test() { compile_sources "$TMP/s" > "$TMP/out" + local has for has in s/a.cpp s/b.ino s/x/y/c.h do if ! grep -q $has "$TMP/out" @@ -32,6 +33,7 @@ compile_sources_self_test() { fi done + local miss for miss in ._a.cpp c.txt do if grep -q $miss "$TMP/out" diff --git a/ci/bin/compile_vitro b/ci/bin/compile_vitro index 54024bf..fa60497 100755 --- a/ci/bin/compile_vitro +++ b/ci/bin/compile_vitro @@ -9,21 +9,21 @@ do done compile_vitro() { - DIR="$(dir "$@")" - SKETCHBOOK="$(sketchbook "$@")" + local DIR="$(dir "$@")" + local SKETCHBOOK="$(sketchbook "$@")" while [ $# -gt 0 ] do case "$1" in - --ino=*) INO=${1#--ino=}; shift;; - --tmp=*) TMP=${1#--tmp=}; shift;; + --ino=*) local INO=${1#--ino=}; shift;; + --tmp=*) local TMP=${1#--tmp=}; shift;; --*=*) shift;; --) shift; break;; *) break;; esac done - ARDUINO_LIBS="${SKETCHBOOK}/libraries" - ARDUINO_UNIT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.."; pwd)" + local ARDUINO_LIBS="${SKETCHBOOK}/libraries" + local ARDUINO_UNIT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.."; pwd)" if [ ! -r "$ARDUINO_UNIT_DIR/src/ArduinoUnit.h" ] then echo "Cannot find ArduinoUnit library." @@ -31,7 +31,7 @@ compile_vitro() { fi if [ "${INO}" = "" ]; then - INO="$(echo *.ino)" + local INO="$(echo *.ino)" fi if [ ! -f "${INO}" ] ; then @@ -39,7 +39,7 @@ compile_vitro() { exit 1 fi - ARDUINO_TARGET_DIR="$(dirname "${INO}")" + local ARDUINO_TARGET_DIR="$(dirname "${INO}")" if [ ! -d "${ARDUINO_TARGET_DIR}" ] ; then echo "missing directory ${ARDUINO_TARGET_DIR}." exit 1 @@ -49,7 +49,7 @@ compile_vitro() { # Make a temp directory to work in (that is removed) # if [ "$TMP" = "" ] ; then - TMP="$(mktemp -d)" + local TMP="$(mktemp -d)" EXITS+="/bin/rm -rf '${TMP}'" trap 'for action in "${EXITS[@]}" ; do $action ; done' EXIT else @@ -66,7 +66,7 @@ compile_vitro() { mkdir -p "${TMP}/ArduinoUnit/src" (cd "${ARDUINO_UNIT_DIR}/src"; tar cf - $(compile_sources .)) | tar -C "${TMP}/ArduinoUnit/src" -xf - - ARDUINO_TARGET_EXE="${INO%.ino}" + local ARDUINO_TARGET_EXE="${INO%.ino}" # # compile everything in the temp directory, relabeling filenames errors so they look like they came from the right place diff --git a/ci/bin/dir b/ci/bin/dir index 6ee2fe2..1f82d7b 100755 --- a/ci/bin/dir +++ b/ci/bin/dir @@ -7,7 +7,7 @@ dir() { do case "$1" in - --dir=*) DIR=${1#--dir=}; shift;; + --dir=*) local DIR=${1#--dir=}; shift;; --*=*) shift;; --) shift; break;; *) break;; @@ -16,7 +16,7 @@ dir() { if [ "$DIR" = "" ] then - DIR="$HOME/.arduino" + local DIR="$HOME/.arduino" fi if [ ! -d "${DIR}" ] diff --git a/ci/bin/make_simavr_uno b/ci/bin/make_simavr_uno index 7076107..d36ad67 100755 --- a/ci/bin/make_simavr_uno +++ b/ci/bin/make_simavr_uno @@ -1,4 +1,4 @@ -#!/bin/bash -x +#!/bin/bash for inc in dir os version cache_simavr avr_root arduino_exe package_install do @@ -9,18 +9,18 @@ do done make_simavr_uno() { - DIR="$(dir "$@")" - OS="$(os "$@")" - VERSION="$(version "$@")" - ARDUINO_EXE="$(arduino_exe "$@")" - AVR_ROOT="$(avr_root "$@")" + local DIR="$(dir "$@")" + local OS="$(os "$@")" + local VERSION="$(version "$@")" + local ARDUINO_EXE="$(arduino_exe "$@")" + local AVR_ROOT="$(avr_root "$@")" while [ $# -gt 0 ] do case "$1" in - --reload=*) RELOAD=${1#--reload=}; shift;; - --branch=*) BRANCH=${1#--branch=}; shift;; + --reload=*) local RELOAD=${1#--reload=}; shift;; + --branch=*) local BRANCH=${1#--branch=}; shift;; --*=*) shift;; --) shift; break;; *) break;; @@ -29,7 +29,7 @@ make_simavr_uno() { if [ "$BRANCH" = "" ] then - BRANCH=master + local BRANCH=master fi if [ -x "$DIR/cache/${VERSION}-${OS}/simavr/uno" -a "$RELOAD" != "true" ] @@ -99,6 +99,10 @@ make_simavr_uno() { } make_simavr_uno_self_test() { + local DIR="$(dir "$@")" + local OS="$(os "$@")" + local VERSION="$(version "$@")" + if make_simavr_uno then if [ ! -x "$DIR/cache/${VERSION}-${OS}/simavr/uno" ] diff --git a/ci/bin/preferences b/ci/bin/preferences index 5b0e52f..51bbaa4 100755 --- a/ci/bin/preferences +++ b/ci/bin/preferences @@ -9,13 +9,13 @@ do done preferences() { - DIR="$(dir "$@")" + local DIR="$(dir "$@")" while [ $# -gt 0 ] do case "$1" in - --preferences=*) PREFERENCES=${1#--preferences=}; shift;; + --preferences=*) local PREFERENCES=${1#--preferences=}; shift;; --*=*) shift;; --) shift; break;; *) break;; @@ -24,7 +24,7 @@ preferences() { if [ "$PREFERENCES" = "" ] then - PREFERENCES="$(dir "$@")/portable/preferences.txt" + local PREFERENCES="$(dir "$@")/portable/preferences.txt" fi echo "$PREFERENCES" diff --git a/ci/bin/simavr_uno b/ci/bin/simavr_uno index 7a6fce3..a9da63d 100755 --- a/ci/bin/simavr_uno +++ b/ci/bin/simavr_uno @@ -9,50 +9,50 @@ do done simavr_uno_exit() { - for PID in $SIMAVR_UNO_PIDS - do - if ps $PID >/dev/null - then - kill $PID - fi - done - + local PID + for PID in $SIMAVR_UNO_PIDS + do + if ps $PID >/dev/null + then + kill $PID + fi + done } simavr_uno() { - DIR="$(dir "$@")" - OS="$(os "$@")" - VERSION="$(version "$@")" - HEX="" + local DIR="$(dir "$@")" + local OS="$(os "$@")" + local VERSION="$(version "$@")" + local HEX="" while [ $# -gt 0 ] do case "$1" in - --background=*) BACKGROUND=${1#--background=}; shift;; - --ino=*) INO="${1#--ino=}"; shift;; - --hex=*) HEX="${1#--hex=}"; shift;; + --background=*) local BACKGROUND=${1#--background=}; shift;; + --ino=*) local INO="${1#--ino=}"; shift;; + --hex=*) local HEX="${1#--hex=}"; shift;; --*=*) shift;; --) shift; break;; *) break;; esac done - INPUT=( "$@" ) + local INPUT=( "$@" ) if [ "${INO}" = "" ]; then if [ -r "$(echo *.ino)" ] ; then - INO="$(echo *.ino)" + local INO="$(echo *.ino)" fi fi if [ "${HEX}" = "" -a "${INO}" != "" ] ; then - HEX="${INO%.ino}".hex + local HEX="${INO%.ino}".hex fi if [ "$HEX" = "" ] then - HEX="$(echo *.hex)" + local HEX="$(echo *.hex)" fi if [ ! -r "${HEX}" ] ; then @@ -71,15 +71,15 @@ simavr_uno() { exit 1 fi - SIMAVR_UNO_PIDS="" + local SIMAVR_UNO_PIDS="" trap simavr_uno_exit EXIT - PORT="/tmp/simavr-uart0" + local PORT="/tmp/simavr-uart0" "${DIR}/cache/${VERSION}-${OS}/simavr/uno" "${HEX}" & - PID=$! + local PID=$! if [ "$PID" != "" ] then - SIMAVR_UNO_PIDS="$SIMAVR_UNO_PIDS $PID" + local SIMAVR_UNO_PIDS="$SIMAVR_UNO_PIDS $PID" else echo "could not launch simavr/uno" exit 1 diff --git a/ci/bin/sketchbook b/ci/bin/sketchbook index d789cec..429f477 100755 --- a/ci/bin/sketchbook +++ b/ci/bin/sketchbook @@ -15,7 +15,7 @@ sketchbook() { do case "$1" in - --sketchbook=*) SKETCHBOOK=${1#--sketchbook=}; shift;; + --sketchbook=*) local SKETCHBOOK=${1#--sketchbook=}; shift;; --*=*) shift;; --) shift; break;; *) break;; @@ -24,7 +24,7 @@ sketchbook() { if [ "$SKETCHBOOK" == "" ] then - SKETCHBOOK="$(dir "$@")/portable/sketchbook" + local SKETCHBOOK="$(dir "$@")/portable/sketchbook" fi echo "$SKETCHBOOK" diff --git a/ci/bin/upload_avr b/ci/bin/upload_avr index c779613..9923cf0 100755 --- a/ci/bin/upload_avr +++ b/ci/bin/upload_avr @@ -8,24 +8,24 @@ do fi done -compile_avr() { - DIR="$(dir "$@")" - OS="$(os "$@")" - ARDUINO_DIR="$(arduino_dir "$@")" - ARDUINO_PACKAGES="$(packages "$@")" - ARDUINO_HARDWARE="${ARDUINO_DIR}/hardware" - ARDUINO_LIBS="${SKETCHBOOK}/libraries" - BOARD=arduino:avr:uno:cpu=atmega328p - ARDUINO_TARGET_DIR= +upload_avr() { + local DIR="$(dir "$@")" + local OS="$(os "$@")" + local ARDUINO_DIR="$(arduino_dir "$@")" + local ARDUINO_PACKAGES="$(packages "$@")" + local ARDUINO_HARDWARE="${ARDUINO_DIR}/hardware" + local ARDUINO_LIBS="${SKETCHBOOK}/libraries" + local BOARD=arduino:avr:uno:cpu=atmega328p + local ARDUINO_TARGET_DIR= while [ $# -gt 0 ] do case "$1" in - --board=*) BOARD=${1#--board=}; shift;; - --ino=*) INO=${1#--ino=}; shift;; - --hex=*) HEX=${1#--hex=}; shift;; - --port=*) PORT=${1#--port=}; shift;; - --baud=*) BAUD=${1#--baud=}; shift;; + --board=*) local BOARD=${1#--board=}; shift;; + --ino=*) local INO=${1#--ino=}; shift;; + --hex=*) local HEX=${1#--hex=}; shift;; + --port=*) local PORT=${1#--port=}; shift;; + --baud=*) local BAUD=${1#--baud=}; shift;; --*=*) shift;; --) shift; break;; *) break;; @@ -35,29 +35,29 @@ compile_avr() { if [ "${PORT}" = "" ] ; then case "${OS}" in - macosx) PORT=$(echo /dev/cu.usb*);; - linux*) PORT=$(echo /dev/ttyACM*);; - windows*) PORT=com4 + macosx) local PORT=$(echo /dev/cu.usb*);; + linux*) local PORT=$(echo /dev/ttyACM*);; + windows*) local PORT=com4 *) echo "unsupported port."; exit 1;; esac fi if [ "${BAUD}" = "" ] ; then - BAUD=115200 + local BAUD=115200 fi if [ "${INO}" = "" ]; then if [ -r "$(echo *.ino)" ] ; then - INO="$(echo *.ino)" + local INO="$(echo *.ino)" fi fi if [ "${HEX}" = "" -a "${INO}" != "" ] ; then - HEX="${INO%.ino}".hex + local HEX="${INO%.ino}".hex fi if [ "$HEX" = "" ] then - HEX="$(echo *.hex)" + local HEX="$(echo *.hex)" fi if [ ! -r "${HEX}" ] ; then diff --git a/ci/bin/version b/ci/bin/version index 181a72a..a357471 100755 --- a/ci/bin/version +++ b/ci/bin/version @@ -11,7 +11,7 @@ version() { do case "$1" in - --version=*) VERSION="${1#--version=}"; shift;; + --version=*) local VERSION="${1#--version=}"; shift;; --*=*) shift;; --) shift; break;; *) break;; @@ -20,7 +20,7 @@ version() { if [ "$VERSION" = "" ] then - VERSION="1.8.8" + local VERSION="1.8.8" fi echo $VERSION } From 2230a5ae54092a485b2ae8f12ba62cd14ad0b8f4 Mon Sep 17 00:00:00 2001 From: Warren MacEvoy Date: Sun, 17 Feb 2019 01:27:30 -0700 Subject: [PATCH 58/80] build simavr on mac --- ci/bin/cache_simavr | 2 +- ci/bin/make_simavr_uno | 13 ++++--------- 2 files changed, 5 insertions(+), 10 deletions(-) diff --git a/ci/bin/cache_simavr b/ci/bin/cache_simavr index f8b5b82..55449ea 100755 --- a/ci/bin/cache_simavr +++ b/ci/bin/cache_simavr @@ -38,7 +38,7 @@ cache_simavr() { if [ \( ! -d "simavr/.git" \) -o "$RELOAD" = "true" ] then /bin/rm -rf simavr - git clone https://github.com/buserror/simavr.git + git clone https://github.com/wmacevoy/simavr.git fi if [ ! -d "simavr/.git" ] diff --git a/ci/bin/make_simavr_uno b/ci/bin/make_simavr_uno index d36ad67..f11a3f1 100755 --- a/ci/bin/make_simavr_uno +++ b/ci/bin/make_simavr_uno @@ -52,13 +52,9 @@ make_simavr_uno() { exit 1 fi - if [ ! -d "$DIR/cache/simavr" -o "$RELOAD" = "true" ] + if ! cache_simavr --dir=$DIR --reload=$RELOAD then - echo "Missing simavr repository (caching)..." - if ! cache_simavr --dir=$DIR --reload=$RELOAD - then - exit 1 - fi + exit 1 fi if [ "$OS" = "macosx" ] @@ -71,9 +67,10 @@ make_simavr_uno() { /bin/rm -rf "$DIR/cache/${VERSION}-${OS}/simavr/repo" mkdir -p "$DIR/cache/${VERSION}-${OS}/simavr/repo" tar -C "$DIR/cache/simavr" -cf - . | tar -C "$DIR/cache/${VERSION}-${OS}/simavr/repo" -xf - - (cd "$DIR/cache/${VERSION}-${OS}/simavr/repo"; git checkout -f "$BRANCH"; git apply "$(cd "$(dirname "${BASH_SOURCE[0]}")"; pwd)/make_simavr_uno.patch" ) + git -C "$DIR/cache/${VERSION}-${OS}/simavr/repo" checkout -f "$BRANCH" export AVR_ROOT + echo "AVR_ROOT=$AVR_ROOT" if ! PATH="$AVR_ROOT/bin:$PATH" make -e -B -C "$DIR/cache/${VERSION}-${OS}/simavr/repo" clean build-simavr then @@ -81,8 +78,6 @@ make_simavr_uno() { exit 1 fi - - if ! PATH="$AVR_ROOT/bin:$PATH" make -e -B -C "$DIR/cache/${VERSION}-${OS}/simavr/repo/examples/board_simduino" clean all then echo "build board_simduino target failed." From bfc15a9937a63c4a501019c05ebd4dc1e17a2197 Mon Sep 17 00:00:00 2001 From: Warren MacEvoy Date: Sun, 17 Feb 2019 01:37:26 -0700 Subject: [PATCH 59/80] create lib dir for osx --- ci/bin/compile_avr | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ci/bin/compile_avr b/ci/bin/compile_avr index fb58c92..32c28c8 100755 --- a/ci/bin/compile_avr +++ b/ci/bin/compile_avr @@ -65,6 +65,8 @@ compile_avr() { local ARDUINO_TARGET_EXE="${INO%.ino}" + mkdir -p "${ARDUINO_LIBS}" + ${ARDUINO_DIR}/arduino-builder -dump-prefs -logger=machine -hardware ${ARDUINO_DIR}/hardware -hardware ${ARDUINO_DIR}/hardware -tools ${ARDUINO_DIR}/tools-builder -tools ${ARDUINO_DIR}/hardware/tools/avr -built-in-libraries ${ARDUINO_DIR}/libraries -libraries ${ARDUINO_LIBS} -fqbn=${BOARD} -ide-version=10802 -build-path ${TMP}/build -warnings=all -build-cache ${TMP}/cache -prefs=build.warn_data_percentage=75 -prefs=runtime.tools.avr-gcc.path=${ARDUINO_DIR}/hardware/tools/avr -prefs=runtime.tools.arduinoOTA.path=${ARDUINO_DIR}/hardware/tools/avr -prefs=runtime.tools.avrdude.path=${ARDUINO_DIR}/hardware/tools/avr -verbose "${TMP}/src/$(basename ${INO})" 2>&1 | sed -e "s|${TMP}/build/sketch/|${ARDUINO_TARGET_DIR}/|g" ${ARDUINO_DIR}/arduino-builder -compile -logger=machine -hardware ${ARDUINO_DIR}/hardware -hardware ${ARDUINO_HARDWARE} -tools ${ARDUINO_DIR}/tools-builder -tools ${ARDUINO_DIR}/hardware/tools/avr -built-in-libraries ${ARDUINO_DIR}/libraries -libraries ${ARDUINO_LIBS} -fqbn=${BOARD} -ide-version=10802 -build-path ${TMP}/build -warnings=all -build-cache ${TMP}/cache -prefs=build.warn_data_percentage=75 -prefs=runtime.tools.avr-gcc.path=${ARDUINO_DIR}/hardware/tools/avr -prefs=runtime.tools.arduinoOTA.path=${ARDUINO_DIR}/hardware/tools/avr -prefs=runtime.tools.avrdude.path=${ARDUINO_DIR}/hardware/tools/avr -verbose "${TMP}/src/$(basename ${INO})" 2>&1 | sed -e "s|${TMP}/build/sketch/|${ARDUINO_TARGET_DIR}/|g" From 7476ba7f70f0043dfa93e9ff46c778c42c95f4ca Mon Sep 17 00:00:00 2001 From: Warren MacEvoy Date: Sun, 17 Feb 2019 02:15:37 -0700 Subject: [PATCH 60/80] ci notes and easy reset --- ci.md | 19 +++++++------------ ci/bin/reset | 20 ++++++++++++++++++++ 2 files changed, 27 insertions(+), 12 deletions(-) create mode 100755 ci/bin/reset diff --git a/ci.md b/ci.md index 03c9a7a..d2c86ec 100644 --- a/ci.md +++ b/ci.md @@ -10,26 +10,21 @@ There really is nothing to install. The CI tools are bash scripts that can be r #### macosx -On a OS X, you will have to install the XCode command line tools, homebrew, libelf and the avr-gcc tools. You will need an internet connection and some time (20 minutes): +On a OS X, you will have to install the XCode command line tools and homebrew: ```bash if ! which git ; then xcode-select --install ; fi # xcode cli if ! which brew ; then /usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)" ; fi # homebrew -if ! which curl ; then brew install curl ; fi # curl -if ! which avr-gcc ; then brew tap osx-cross/homebrew-avr && brew install avr-gcc ; fi # avr-gcc -if [ -f /usr/local/lib/libelf.a ] ; then brew install libelf ; fi # libelf ``` #### linux -In linux, you need the gcc compiler, make git and curl: +In linux, you need git make g++ unzip and curl: ```bash -sudo apt install -y g++ make git curl +sudo apt install -y git make g++ unzip curl ``` -or similar... - #### windows Install Windows Subsystem for Linux, then Ubuntu under WSL, then follow the linux instructions in a WSL/Ubuntu terminal. I think. @@ -49,10 +44,11 @@ git clone https://github.com/mmurdoch/arduinounit.git To make the tools easier to use, you can define the `au` bash function by sourcing `au` in the `ci` directory (notice the dot with a space): -``` +```bash . "$HOME/projects/arduinounit/ci/au" ``` + You can put this in your `.profile` if you like, so it is set every time you log in. To test (you may have to log out and log back in), try: @@ -113,9 +109,8 @@ ${HOME}/.arduino/ The CI tools install the IDE in "portable" mode so they do not use or modify your default IDE. When making a "clean install test", do NOT delete the zip/tar files in the cache. These are checked against the very secure sha512 (and will be re-downloaded if they checksum fails). Downloading these again is very slow and a waste of bandwidth. -A clean (cached) install can be started with: +A clean (except the ide cache which is pointless and slow) install can be started with: ```bash -/bin/rm -rf "$(au dir_cache)" -/bin/rm -rf "$(au dir)/portable" +au reset ``` diff --git a/ci/bin/reset b/ci/bin/reset new file mode 100755 index 0000000..09aa2a0 --- /dev/null +++ b/ci/bin/reset @@ -0,0 +1,20 @@ +#!/bin/bash + +for inc in dir +do + if [ "$(type -t $inc)" != "function" ] + then + . "$(cd "$(dirname "${BASH_SOURCE[0]}")"; pwd)"/$inc + fi +done + +reset() { + local DIR="$(dir "$@")" + find "${DIR}/cache" -mindepth 1 -maxdepth 1 -type d -o -size -1M -exec /bin/rm -rf {} \; + /bin/rm -rf "${DIR}/portable" +} + +if [[ "${BASH_SOURCE[0]}" == "${0}" ]] +then + reset "$@" +fi From 6ab81912c937976b9afe46018717298b8d6439c1 Mon Sep 17 00:00:00 2001 From: Warren MacEvoy Date: Sun, 17 Feb 2019 02:23:55 -0700 Subject: [PATCH 61/80] better reset --- ci/bin/reset | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ci/bin/reset b/ci/bin/reset index 09aa2a0..49f45e8 100755 --- a/ci/bin/reset +++ b/ci/bin/reset @@ -10,7 +10,7 @@ done reset() { local DIR="$(dir "$@")" - find "${DIR}/cache" -mindepth 1 -maxdepth 1 -type d -o -size -1M -exec /bin/rm -rf {} \; + find "${DIR}/cache" -mindepth 1 -maxdepth 1 \( -type d -o -size -1M \) -exec /bin/rm -rf {} \; /bin/rm -rf "${DIR}/portable" } From e4f7a65dbf51d5c995eb1c5aa7a9d60f0105199c Mon Sep 17 00:00:00 2001 From: Warren MacEvoy Date: Sun, 17 Feb 2019 10:16:42 +0000 Subject: [PATCH 62/80] fix ci upload --- ci.md | 2 +- ci/bin/upload_avr | 10 ++++++++-- ci/bin/upload_mega | 0 3 files changed, 9 insertions(+), 3 deletions(-) mode change 100644 => 100755 ci/bin/upload_mega diff --git a/ci.md b/ci.md index d2c86ec..4b49178 100644 --- a/ci.md +++ b/ci.md @@ -77,7 +77,7 @@ au simavr_uno | au au2ju In the vitro example, you can run tests 3 different ways: on the hardware, on the simulator, or on the dev system: ```bash -au compile_mock +au compile_vitro ./vitro ./vitro | au au2ju au compile_uno diff --git a/ci/bin/upload_avr b/ci/bin/upload_avr index 9923cf0..c6743a9 100755 --- a/ci/bin/upload_avr +++ b/ci/bin/upload_avr @@ -37,7 +37,7 @@ upload_avr() { in macosx) local PORT=$(echo /dev/cu.usb*);; linux*) local PORT=$(echo /dev/ttyACM*);; - windows*) local PORT=com4 + windows*) local PORT=com4;; *) echo "unsupported port."; exit 1;; esac fi @@ -65,7 +65,13 @@ upload_avr() { exit 1 fi - if ! ${ARDUINO_DIR}/hardware/tools/avr/bin/avrdude -C${ARDUINO_DIR}/hardware/tools/avr/etc/avrdude.conf -v -p${BOARD##*cpu=} -cwiring -P"${PORT}" -b${BAUD} -D -Uflash:w:"${HEX}":i + local PROGRAMMER_ID=arduino + case "${BOARD}" + in + arduino:avr:mega:*) local PROGRAMMER_ID=wiring;; + esac + + if ! ${ARDUINO_DIR}/hardware/tools/avr/bin/avrdude -C${ARDUINO_DIR}/hardware/tools/avr/etc/avrdude.conf -v -p${BOARD##*cpu=} -c${PROGRAMMER_ID} -P"${PORT}" -b${BAUD} -D -Uflash:w:"${HEX}":i then echo "upload error: avr." exit 1 diff --git a/ci/bin/upload_mega b/ci/bin/upload_mega old mode 100644 new mode 100755 From 4ad93a14440b1dc30607b6f0a10ea063157b8195 Mon Sep 17 00:00:00 2001 From: Warren MacEvoy Date: Sun, 17 Feb 2019 04:18:23 -0700 Subject: [PATCH 63/80] not quite reproducing the bug --- tests/bug86/reproduce | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 tests/bug86/reproduce diff --git a/tests/bug86/reproduce b/tests/bug86/reproduce new file mode 100644 index 0000000..1b23b80 --- /dev/null +++ b/tests/bug86/reproduce @@ -0,0 +1,21 @@ +#!/bin/bash + +pushd $(dirname "${BASH_SOURCE[0]}") >/dev/null +this_dir="$PWD" +popd >/dev/null + +. $this_dir/../../ci/au + +au arduino --pref update.check=false --install-boards arduino:avr:1.6.21 +au arduino --pref update.check=false --install-library ArduinoUnit:3.0.2 +cd $this_dir/../../examples/basic +au compile_uno +echo "should be ok:" +au simavr_uno + +au arduino --pref update.check=false --install-boards arduino:avr:1.6.22 +au arduino --pref update.check=false --install-library ArduinoUnit:3.0.2 +cd $this_dir/../../examples/basic +au compile_uno +echo "should NOT be ok:" +au simavr_uno From e0710c74960e3f8d6d92ab63d837525bdc4f5e63 Mon Sep 17 00:00:00 2001 From: Shawn Silverman Date: Sun, 17 Mar 2019 12:59:23 -0700 Subject: [PATCH 64/80] Fix for TEENSYDUINO not having the protected String::concat(const char *, unsigned int); it has String::append instead. --- src/ArduinoUnitUtility/ArduinoUnitMockPrint.cpp | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/ArduinoUnitUtility/ArduinoUnitMockPrint.cpp b/src/ArduinoUnitUtility/ArduinoUnitMockPrint.cpp index bf3f9a4..bffe126 100644 --- a/src/ArduinoUnitUtility/ArduinoUnitMockPrint.cpp +++ b/src/ArduinoUnitUtility/ArduinoUnitMockPrint.cpp @@ -133,5 +133,12 @@ MockPrint::MockPrint(const String &_initial) : String(_initial) {} MockPrint::~MockPrint() {} size_t MockPrint::write(uint8_t x) { concat((char) x); return 1; } -size_t MockPrint::write(const uint8_t *buffer, size_t size) { concat((const char *)buffer,size); return size; } +size_t MockPrint::write(const uint8_t *buffer, size_t size) { +#ifdef TEENSYDUINO + append((const char *)buffer, size); +#else + concat((const char *)buffer, size); +#endif // TEENSYDUINO + return size; +} int MockPrint::availableForWrite() { return INT_MAX; } From 306e0b51e662b3d3bc19ae86441573e9fc2a4edc Mon Sep 17 00:00:00 2001 From: Warren MacEvoy Date: Sun, 8 Sep 2019 12:49:32 -0600 Subject: [PATCH 65/80] teensy support --- CHANGELOG.md | 2 ++ README.md | 2 ++ library.properties | 8 ++++---- 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c8b0d77..bbea552 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -53,3 +53,5 @@ * Provide preliminary Continuous Integration Testing support (ci) ## 3.0.2 * Data deduplication bug fix patch. +## 3.0.3 + * Support for Teensy (#87) diff --git a/README.md b/README.md index 5057602..394fb1a 100644 --- a/README.md +++ b/README.md @@ -466,6 +466,8 @@ Note that `Test::run()` only calls the active unresolved tests. * The `assertCurrentTestXXXX([,footnote [,retval])` macros do not compile on ESP8266 boards with no footnote. Use an empty footnote `assertCurrentTestXXXX("")`, or use `assertCurrentTestXXXX_0()` for no footnote. You do not have to specify a return value. +* The current release prints "skipped" for all tests, although assertions are correctly reported. (#86) + ## FAQ Q. The line number of the asserts do not match the source file. diff --git a/library.properties b/library.properties index 4251216..a1c554e 100644 --- a/library.properties +++ b/library.properties @@ -1,9 +1,9 @@ name=ArduinoUnit -version=3.0.2 -author=Matthew Murdoch -maintainer=Matthew Murdoch +version=3.0.3 +author=Warren MacEvoy +maintainer=Warren MacEvoy sentence=Flexible test framework for arduino projects. -paragraph=Flexible testing framework for arduino projects. Supports Arduino, ESP8266 and ESP32 as well as "en vitro" development system (vs embedded target) testing. +paragraph=Flexible testing framework for arduino projects. Supports Arduino, ESP8266 and ESP32 as well as "en vitro" development system (vs embedded target) testing. Based on Arduino Unit 1.0 by Matthew Murdoch. category=Other url=https://github.com/mmurdoch/arduinounit architectures=* From 6b9060cad8574fa83517d7c8e76d2c1b19b9b45c Mon Sep 17 00:00:00 2001 From: Warren MacEvoy Date: Sun, 8 Sep 2019 13:27:56 -0600 Subject: [PATCH 66/80] add debug flag (-g) to compile_avr --- ci/bin/compile_avr | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ci/bin/compile_avr b/ci/bin/compile_avr index 32c28c8..fac7b19 100755 --- a/ci/bin/compile_avr +++ b/ci/bin/compile_avr @@ -67,9 +67,9 @@ compile_avr() { mkdir -p "${ARDUINO_LIBS}" - ${ARDUINO_DIR}/arduino-builder -dump-prefs -logger=machine -hardware ${ARDUINO_DIR}/hardware -hardware ${ARDUINO_DIR}/hardware -tools ${ARDUINO_DIR}/tools-builder -tools ${ARDUINO_DIR}/hardware/tools/avr -built-in-libraries ${ARDUINO_DIR}/libraries -libraries ${ARDUINO_LIBS} -fqbn=${BOARD} -ide-version=10802 -build-path ${TMP}/build -warnings=all -build-cache ${TMP}/cache -prefs=build.warn_data_percentage=75 -prefs=runtime.tools.avr-gcc.path=${ARDUINO_DIR}/hardware/tools/avr -prefs=runtime.tools.arduinoOTA.path=${ARDUINO_DIR}/hardware/tools/avr -prefs=runtime.tools.avrdude.path=${ARDUINO_DIR}/hardware/tools/avr -verbose "${TMP}/src/$(basename ${INO})" 2>&1 | sed -e "s|${TMP}/build/sketch/|${ARDUINO_TARGET_DIR}/|g" + ${ARDUINO_DIR}/arduino-builder -dump-prefs -logger=machine -hardware ${ARDUINO_DIR}/hardware -hardware ${ARDUINO_DIR}/hardware -tools ${ARDUINO_DIR}/tools-builder -tools ${ARDUINO_DIR}/hardware/tools/avr -built-in-libraries ${ARDUINO_DIR}/libraries -libraries ${ARDUINO_LIBS} -fqbn=${BOARD} -ide-version=10802 -build-path ${TMP}/build -warnings=all -build-cache ${TMP}/cache -prefs=build.warn_data_percentage=75 -prefs=runtime.tools.avr-gcc.path=${ARDUINO_DIR}/hardware/tools/avr -prefs=runtime.tools.arduinoOTA.path=${ARDUINO_DIR}/hardware/tools/avr -prefs=runtime.tools.avrdude.path=${ARDUINO_DIR}/hardware/tools/avr -prefs="compiler.cpp.extra_flags=-g" -verbose "${TMP}/src/$(basename ${INO})" 2>&1 | sed -e "s|${TMP}/build/sketch/|${ARDUINO_TARGET_DIR}/|g" - ${ARDUINO_DIR}/arduino-builder -compile -logger=machine -hardware ${ARDUINO_DIR}/hardware -hardware ${ARDUINO_HARDWARE} -tools ${ARDUINO_DIR}/tools-builder -tools ${ARDUINO_DIR}/hardware/tools/avr -built-in-libraries ${ARDUINO_DIR}/libraries -libraries ${ARDUINO_LIBS} -fqbn=${BOARD} -ide-version=10802 -build-path ${TMP}/build -warnings=all -build-cache ${TMP}/cache -prefs=build.warn_data_percentage=75 -prefs=runtime.tools.avr-gcc.path=${ARDUINO_DIR}/hardware/tools/avr -prefs=runtime.tools.arduinoOTA.path=${ARDUINO_DIR}/hardware/tools/avr -prefs=runtime.tools.avrdude.path=${ARDUINO_DIR}/hardware/tools/avr -verbose "${TMP}/src/$(basename ${INO})" 2>&1 | sed -e "s|${TMP}/build/sketch/|${ARDUINO_TARGET_DIR}/|g" + ${ARDUINO_DIR}/arduino-builder -compile -logger=machine -hardware ${ARDUINO_DIR}/hardware -hardware ${ARDUINO_HARDWARE} -tools ${ARDUINO_DIR}/tools-builder -tools ${ARDUINO_DIR}/hardware/tools/avr -built-in-libraries ${ARDUINO_DIR}/libraries -libraries ${ARDUINO_LIBS} -fqbn=${BOARD} -ide-version=10802 -build-path ${TMP}/build -warnings=all -build-cache ${TMP}/cache -prefs=build.warn_data_percentage=75 -prefs=runtime.tools.avr-gcc.path=${ARDUINO_DIR}/hardware/tools/avr -prefs=runtime.tools.arduinoOTA.path=${ARDUINO_DIR}/hardware/tools/avr -prefs=runtime.tools.avrdude.path=${ARDUINO_DIR}/hardware/tools/avr -prefs="compiler.cpp.extra_flags=-g" -verbose "${TMP}/src/$(basename ${INO})" 2>&1 | sed -e "s|${TMP}/build/sketch/|${ARDUINO_TARGET_DIR}/|g" if [ ! -f "${TMP_HEX}" ] ; then echo "compile time error: avr." exit 1 From 7266d16b0e897c707dd9795c936ec0f1667e090b Mon Sep 17 00:00:00 2001 From: Warren MacEvoy Date: Sun, 8 Sep 2019 20:47:09 -0700 Subject: [PATCH 67/80] debug hack on ubuntu --- ci.md | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/ci.md b/ci.md index 4b49178..f2e6319 100644 --- a/ci.md +++ b/ci.md @@ -114,3 +114,24 @@ A clean (except the ide cache which is pointless and slow) install can be starte ```bash au reset ``` + +## debug + +~Warning~ this is a hack. But stepping through code is amazingly useful. I have only tested it on Ubuntu; but should work on + +1. Install simavr (sudo apt install simavr). This should also install avr-gcc. +1. Install this toolset in in Ubunutu: run `au arduino` to spin up the basic working cache of the ide. +1. Create and set the TMP environment variable so the system does not build and erase a temporary file. I used "/tmpdir" and made that folder. +1. Compile the project with `au compile_avr` in the project directory. The build residue should be in TMP. +1. Look in the TMP directory, and find the build folder. +1. Open two terminals here; one to run the program and one to debug from. +1. In your run terminal, type `simavr simavr -g -m atmega328p -f 16000000 basic.ino.elf` +1. In your debug terminal, type `avr-gdb` to start the avr debugger, then in th prompts type +```bash +enable tui +file basic.ino.elf +target remote :1234 +b setup +c +s +``` From 60840b85adbedb40bce08b3fce836c8d2186c6cf Mon Sep 17 00:00:00 2001 From: Warren MacEvoy Date: Sun, 8 Sep 2019 22:54:36 -0700 Subject: [PATCH 68/80] not all skipped. --- ci.md | 7 ++-- src/ArduinoUnitUtility/ArduinoUnit.cpp | 46 ++++++++++++++++---------- src/ArduinoUnitUtility/Flash.h | 6 ++-- 3 files changed, 37 insertions(+), 22 deletions(-) diff --git a/ci.md b/ci.md index f2e6319..88193ac 100644 --- a/ci.md +++ b/ci.md @@ -125,10 +125,13 @@ au reset 1. Compile the project with `au compile_avr` in the project directory. The build residue should be in TMP. 1. Look in the TMP directory, and find the build folder. 1. Open two terminals here; one to run the program and one to debug from. -1. In your run terminal, type `simavr simavr -g -m atmega328p -f 16000000 basic.ino.elf` +1. In your run terminal, type +```bash +simavr -g -m atmega328p -f 16000000 basic.ino.elf +``` 1. In your debug terminal, type `avr-gdb` to start the avr debugger, then in th prompts type ```bash -enable tui +tui enable file basic.ino.elf target remote :1234 b setup diff --git a/src/ArduinoUnitUtility/ArduinoUnit.cpp b/src/ArduinoUnitUtility/ArduinoUnit.cpp index 62bdc50..4d789ea 100644 --- a/src/ArduinoUnitUtility/ArduinoUnit.cpp +++ b/src/ArduinoUnitUtility/ArduinoUnit.cpp @@ -29,6 +29,19 @@ static CppStreamPrint Serial; Print* Test::out = &Serial; +#if ARDUINO_UNIT_USE_FLASH > 0 +#define ARDUINO_UNIT_PROGMEM PROGMEM +#else +#define ARDUINO_UNIT_PROGMEM +#endif + +const char CONST_SKIPPED[] ARDUINO_UNIT_PROGMEM = "skipped"; +const char CONST_PASSED[] ARDUINO_UNIT_PROGMEM = "passed"; +const char CONST_FAILED[] ARDUINO_UNIT_PROGMEM = "failed"; + +ARDUINO_UNIT_DECLARE_STRING SKIPPED = (ARDUINO_UNIT_DECLARE_STRING) CONST_SKIPPED; +ARDUINO_UNIT_DECLARE_STRING PASSED = (ARDUINO_UNIT_DECLARE_STRING) CONST_PASSED; +ARDUINO_UNIT_DECLARE_STRING FAILED = (ARDUINO_UNIT_DECLARE_STRING) CONST_FAILED; void Test::noMessage(bool ok) { (void) ok; } @@ -38,11 +51,12 @@ void Test::resolve() bool fail = state==DONE_FAIL; bool skip = state==DONE_SKIP; bool done = (pass || fail || skip); + ARDUINO_UNIT_DECLARE_STRING message = 0; if (done) { - if (pass) ++Test::passed; - if (fail) ++Test::failed; - if (skip) ++Test::skipped; + if (pass) { message=PASSED; ++Test::passed; } + if (fail) { message=FAILED; ++Test::failed; } + if (skip) { message=SKIPPED; ++Test::skipped; } #if TEST_VERBOSITY_EXISTS(TESTS_SKIPPED) || TEST_VERBOSITY_EXISTS(TESTS_PASSED) || TEST_VERBOSITY_EXISTS(TESTS_FAILED) @@ -55,17 +69,9 @@ void Test::resolve() if (output) { Test::out->print(ARDUINO_UNIT_STRING("Test ")); Test::out->print(name); -#if TEST_VERBOSITY_EXISTS(TESTS_SKIPPED) - if (skip) { Test::out->println(ARDUINO_UNIT_STRING(" skipped.")); } -#endif - -#if TEST_VERBOSITY_EXISTS(TESTS_PASSED) - if (pass) { Test::out->println(ARDUINO_UNIT_STRING(" passed.")); } -#endif - -#if TEST_VERBOSITY_EXISTS(TESTS_FAILED) - if (fail) { Test::out->println(ARDUINO_UNIT_STRING(" failed.")); } -#endif + Test::out->print(' '); + Test::out->print(message); + Test::out->println(); } #endif } @@ -73,11 +79,17 @@ void Test::resolve() if (root == 0 && TEST_VERBOSITY(TESTS_SUMMARY)) { Test::out->print(ARDUINO_UNIT_STRING("Test summary: ")); Test::out->print(passed); - Test::out->print(ARDUINO_UNIT_STRING(" passed, ")); + Test::out->print(' '); + Test::out->print(PASSED); + Test::out->print(ARDUINO_UNIT_STRING(", ")); Test::out->print(failed); - Test::out->print(ARDUINO_UNIT_STRING(" failed, and ")); + Test::out->print(' '); + Test::out->print(FAILED); + Test::out->print(ARDUINO_UNIT_STRING(", ")); Test::out->print(skipped); - Test::out->print(ARDUINO_UNIT_STRING(" skipped, out of ")); + Test::out->print(' '); + Test::out->print(SKIPPED); + Test::out->print(ARDUINO_UNIT_STRING(", out of ")); Test::out->print(count); Test::out->println(ARDUINO_UNIT_STRING(" test(s).")); } diff --git a/src/ArduinoUnitUtility/Flash.h b/src/ArduinoUnitUtility/Flash.h index da3220b..04f6792 100644 --- a/src/ArduinoUnitUtility/Flash.h +++ b/src/ArduinoUnitUtility/Flash.h @@ -10,7 +10,7 @@ // # define ARDUINO_UNIT_PSTR(str) \ (__extension__({ \ - PGM_P ptr; \ + PGM_P ptr ## __COUNTER__; \ asm volatile \ ( \ ".pushsection .progmem.mergeable-strings, \"SM\", @progbits, 1" "\n\t" \ @@ -21,9 +21,9 @@ ( \ "ldi %A0, lo8(0b)" "\n\t" \ "ldi %B0, hi8(0b)" "\n\t" \ - : "=d" (ptr) \ + : "=d" (ptr ## __COUNTER__) \ ); \ - ptr; \ + ptr ## __COUNTER__ ; \ })) # define ARDUINO_UNIT_STRING(STR) (reinterpret_cast(ARDUINO_UNIT_PSTR(STR))) # define ARDUINO_UNIT_DECLARE_STRING const __FlashStringHelper * From 9dbd3cec22f4fc7afca11f93b28f0ec8c953962c Mon Sep 17 00:00:00 2001 From: Warren MacEvoy Date: Mon, 9 Sep 2019 08:01:45 -0700 Subject: [PATCH 69/80] resolve #86 - finally! --- CHANGELOG.md | 4 ++++ library.properties | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index bbea552..72619cb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -55,3 +55,7 @@ * Data deduplication bug fix patch. ## 3.0.3 * Support for Teensy (#87) +## 3.0.4 + * Skipped message bug fixed (#86) + * Debug (alpha) documented for simavr/avr-gdb (ci.md) + diff --git a/library.properties b/library.properties index a1c554e..2c20ce8 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=ArduinoUnit -version=3.0.3 +version=3.0.4 author=Warren MacEvoy maintainer=Warren MacEvoy sentence=Flexible test framework for arduino projects. From 2453376e366a9c905985c47bcd2caa45a2da5fd8 Mon Sep 17 00:00:00 2001 From: Warren MacEvoy Date: Mon, 9 Sep 2019 09:07:04 -0600 Subject: [PATCH 70/80] remove skipped from known bug list --- README.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/README.md b/README.md index 394fb1a..5057602 100644 --- a/README.md +++ b/README.md @@ -466,8 +466,6 @@ Note that `Test::run()` only calls the active unresolved tests. * The `assertCurrentTestXXXX([,footnote [,retval])` macros do not compile on ESP8266 boards with no footnote. Use an empty footnote `assertCurrentTestXXXX("")`, or use `assertCurrentTestXXXX_0()` for no footnote. You do not have to specify a return value. -* The current release prints "skipped" for all tests, although assertions are correctly reported. (#86) - ## FAQ Q. The line number of the asserts do not match the source file. From 7e8095f84eea59a8dc0a4a9f5b0766d06e8cffc9 Mon Sep 17 00:00:00 2001 From: Warren MacEvoy Date: Mon, 9 Sep 2019 09:11:00 -0600 Subject: [PATCH 71/80] edit --- ci.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ci.md b/ci.md index 88193ac..09439ab 100644 --- a/ci.md +++ b/ci.md @@ -117,7 +117,7 @@ au reset ## debug -~Warning~ this is a hack. But stepping through code is amazingly useful. I have only tested it on Ubuntu; but should work on +*Warning* this is a hack. But stepping through code is amazingly useful. I have only worked out steps on Ubuntu 18.04, and depends on the simavr tool, which gives no uart output. Still it is better than nothging. 1. Install simavr (sudo apt install simavr). This should also install avr-gcc. 1. Install this toolset in in Ubunutu: run `au arduino` to spin up the basic working cache of the ide. From b687ea4e797654c8270c751c9fb22352028a6a15 Mon Sep 17 00:00:00 2001 From: Warren MacEvoy Date: Mon, 9 Sep 2019 09:12:47 -0600 Subject: [PATCH 72/80] edit --- ci.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ci.md b/ci.md index 09439ab..1752bdd 100644 --- a/ci.md +++ b/ci.md @@ -117,7 +117,7 @@ au reset ## debug -*Warning* this is a hack. But stepping through code is amazingly useful. I have only worked out steps on Ubuntu 18.04, and depends on the simavr tool, which gives no uart output. Still it is better than nothging. +*Warning* this is a hack. But stepping through code is amazingly useful. I have only worked out steps on Ubuntu 18.04, and depends on the simavr tool, which gives no uart output. Still it is better than nothing. 1. Install simavr (sudo apt install simavr). This should also install avr-gcc. 1. Install this toolset in in Ubunutu: run `au arduino` to spin up the basic working cache of the ide. From 72da5425e904aa7d28d50172dddf0c430eb23177 Mon Sep 17 00:00:00 2001 From: Matthijs Kooijman Date: Sat, 30 Jan 2021 17:48:38 +0100 Subject: [PATCH 73/80] Fix incorrect merging of PROGMEM strings This fixes the ARDUINO_UNIT_PSTR macro to not reference the wrong string. In particular, this makes failing macros not output "passed" instead of "failed". The same problem was seemingly the subject of commit 60840b8 (not all skipped.). That commit fixed the problem for test status by not using the ARDUINO_UNIT_PSTR macro, and seems to contain a half fix for ARDUINO_UNIT_PSTR using __COUNTER__, but the way it was used, __COUNTER__ was never actually expanded, so that did not help (also, it tried to apply __COUNTER__ in the wrong place). The actual problem *seems* to be that the `0:` label used to reference the string constant is not actually unique. It should not need to be, since the `0b` reference should just reference the nearest label 0, going backwards, but I suspect that gcc ends up reordering asm blocks and thus messes up the reference. Using a unique (but still numerical so local) label seems to fix this. See e.g. this thread about reordering of asm blocks: https://gcc.gnu.org/legacy-ml/gcc-help/2017-10/msg00061.html So, this commit reverts the __COUNTER__ bit from that commit, just using the plain `ptr` name again (which does not need to be unique, since it is local the the __extension__ block). It also reverts the changes around the test status, so these now use ARDUINO_UNIT_STRING again as originally. Then, it applies a two-layer macro wrapper for ARDUINO_UNIT_PSTR, that ensures that __COUNTER__ is actually expanded before being used (which is needed when using a macro as part of a stringification or concatenation) and ensures that __COUNTER__ is only expanded once, with one value, rather than with different values in all three places. Finally, this commit uses this expanded counter value to generate unique labels, which seems to prevent this problem from occuring. --- src/ArduinoUnitUtility/ArduinoUnit.cpp | 46 ++++++++++---------------- src/ArduinoUnitUtility/Flash.h | 23 +++++++++---- 2 files changed, 33 insertions(+), 36 deletions(-) diff --git a/src/ArduinoUnitUtility/ArduinoUnit.cpp b/src/ArduinoUnitUtility/ArduinoUnit.cpp index 4d789ea..ae1d04d 100644 --- a/src/ArduinoUnitUtility/ArduinoUnit.cpp +++ b/src/ArduinoUnitUtility/ArduinoUnit.cpp @@ -29,19 +29,6 @@ static CppStreamPrint Serial; Print* Test::out = &Serial; -#if ARDUINO_UNIT_USE_FLASH > 0 -#define ARDUINO_UNIT_PROGMEM PROGMEM -#else -#define ARDUINO_UNIT_PROGMEM -#endif - -const char CONST_SKIPPED[] ARDUINO_UNIT_PROGMEM = "skipped"; -const char CONST_PASSED[] ARDUINO_UNIT_PROGMEM = "passed"; -const char CONST_FAILED[] ARDUINO_UNIT_PROGMEM = "failed"; - -ARDUINO_UNIT_DECLARE_STRING SKIPPED = (ARDUINO_UNIT_DECLARE_STRING) CONST_SKIPPED; -ARDUINO_UNIT_DECLARE_STRING PASSED = (ARDUINO_UNIT_DECLARE_STRING) CONST_PASSED; -ARDUINO_UNIT_DECLARE_STRING FAILED = (ARDUINO_UNIT_DECLARE_STRING) CONST_FAILED; void Test::noMessage(bool ok) { (void) ok; } @@ -51,12 +38,11 @@ void Test::resolve() bool fail = state==DONE_FAIL; bool skip = state==DONE_SKIP; bool done = (pass || fail || skip); - ARDUINO_UNIT_DECLARE_STRING message = 0; if (done) { - if (pass) { message=PASSED; ++Test::passed; } - if (fail) { message=FAILED; ++Test::failed; } - if (skip) { message=SKIPPED; ++Test::skipped; } + if (pass) ++Test::passed; + if (fail) ++Test::failed; + if (skip) ++Test::skipped; #if TEST_VERBOSITY_EXISTS(TESTS_SKIPPED) || TEST_VERBOSITY_EXISTS(TESTS_PASSED) || TEST_VERBOSITY_EXISTS(TESTS_FAILED) @@ -69,9 +55,17 @@ void Test::resolve() if (output) { Test::out->print(ARDUINO_UNIT_STRING("Test ")); Test::out->print(name); - Test::out->print(' '); - Test::out->print(message); - Test::out->println(); +#if TEST_VERBOSITY_EXISTS(TESTS_SKIPPED) + if (skip) { Test::out->println(ARDUINO_UNIT_STRING(" skipped.")); } +#endif + +#if TEST_VERBOSITY_EXISTS(TESTS_PASSED) + if (pass) { Test::out->println(ARDUINO_UNIT_STRING(" passed.")); } +#endif + +#if TEST_VERBOSITY_EXISTS(TESTS_FAILED) + if (fail) { Test::out->println(ARDUINO_UNIT_STRING(" failed.")); } +#endif } #endif } @@ -79,17 +73,11 @@ void Test::resolve() if (root == 0 && TEST_VERBOSITY(TESTS_SUMMARY)) { Test::out->print(ARDUINO_UNIT_STRING("Test summary: ")); Test::out->print(passed); - Test::out->print(' '); - Test::out->print(PASSED); - Test::out->print(ARDUINO_UNIT_STRING(", ")); + Test::out->print(ARDUINO_UNIT_STRING(" passed, ")); Test::out->print(failed); - Test::out->print(' '); - Test::out->print(FAILED); - Test::out->print(ARDUINO_UNIT_STRING(", ")); + Test::out->print(ARDUINO_UNIT_STRING(" failed, and ")); Test::out->print(skipped); - Test::out->print(' '); - Test::out->print(SKIPPED); - Test::out->print(ARDUINO_UNIT_STRING(", out of ")); + Test::out->print(ARDUINO_UNIT_STRING(" skipped, out of ")); Test::out->print(count); Test::out->println(ARDUINO_UNIT_STRING(" test(s).")); } diff --git a/src/ArduinoUnitUtility/Flash.h b/src/ArduinoUnitUtility/Flash.h index 04f6792..2ca0cbf 100644 --- a/src/ArduinoUnitUtility/Flash.h +++ b/src/ArduinoUnitUtility/Flash.h @@ -8,23 +8,32 @@ // // http://michael-buschbeck.github.io/arduino/2013/10/22/string-merging-pstr-percent-codes/ // -# define ARDUINO_UNIT_PSTR(str) \ +// This additionally uses __COUNTER__ for generating unique labels, +// since backreferencing a fixed label 0 as suggested in the above url +// breaks (probably in recent compiler version, probably because it +// reorders asm blocks). + +# define ARDUINO_UNIT_PSTR2(str, counter) \ (__extension__({ \ - PGM_P ptr ## __COUNTER__; \ + PGM_P ptr; \ asm volatile \ ( \ ".pushsection .progmem.mergeable-strings, \"SM\", @progbits, 1" "\n\t" \ - "0: .string " #str "\n\t" \ + #counter ": .string " #str "\n\t" \ ".popsection" "\n\t" \ ); \ asm volatile \ ( \ - "ldi %A0, lo8(0b)" "\n\t" \ - "ldi %B0, hi8(0b)" "\n\t" \ - : "=d" (ptr ## __COUNTER__) \ + "ldi %A0, lo8(" #counter "b)" "\n\t" \ + "ldi %B0, hi8(" #counter "b)" "\n\t" \ + : "=d" (ptr) \ ); \ - ptr ## __COUNTER__ ; \ + ptr; \ })) +// Use a three-layer macro to ensure that __COUNTER__ is expanded before +// stringification above. +# define ARDUINO_UNIT_PSTR1(str, counter) ARDUINO_UNIT_PSTR2(str, counter) +# define ARDUINO_UNIT_PSTR(str) ARDUINO_UNIT_PSTR1(str, __COUNTER__) # define ARDUINO_UNIT_STRING(STR) (reinterpret_cast(ARDUINO_UNIT_PSTR(STR))) # define ARDUINO_UNIT_DECLARE_STRING const __FlashStringHelper * # define ARDUINO_UNIT_USE_FLASH 1 From bf4effc3cff3916a7d0cb9082d9a2137bd69d51c Mon Sep 17 00:00:00 2001 From: Matthijs Kooijman Date: Fri, 13 Apr 2018 13:07:35 +0200 Subject: [PATCH 74/80] Introduce a new "done" list of tests When a test is completed (including failed and skipped), it was already removed from the "root" list but it is now added to the "done" list. --- src/ArduinoUnit.h | 3 +++ src/ArduinoUnitUtility/ArduinoUnit.cpp | 9 +++++++++ 2 files changed, 12 insertions(+) diff --git a/src/ArduinoUnit.h b/src/ArduinoUnit.h index 08f8148..7bd5e40 100644 --- a/src/ArduinoUnit.h +++ b/src/ArduinoUnit.h @@ -293,6 +293,9 @@ class Test private: // linked list structure for active tests static Test* root; + // linked list structure for done tests. This includes skipped tests, + // though they are only moved after Test::run() finds them. + static Test* done; Test *next; // static statistics for tests diff --git a/src/ArduinoUnitUtility/ArduinoUnit.cpp b/src/ArduinoUnitUtility/ArduinoUnit.cpp index ae1d04d..475c846 100644 --- a/src/ArduinoUnitUtility/ArduinoUnit.cpp +++ b/src/ArduinoUnitUtility/ArduinoUnit.cpp @@ -14,6 +14,7 @@ const uint8_t Test::DONE_FAIL = 4; Test* Test::root = 0; +Test* Test::done = 0; Test* Test::current = 0; uint16_t Test::count = 0; @@ -146,7 +147,13 @@ void Test::run() } if (current->state != LOOPING) { + // Remove from root list (*p)=((*p)->next); + + // Add to done list + current->next = done; + done = current; + current->resolve(); } else { p=&((*p)->next); @@ -170,6 +177,8 @@ void Test::abort() Test::out->print(__LINE__); Test::out->println(ARDUINO_UNIT_STRING(".")); root=root->next; + current->next = done; + done = current; current->resolve(); } current=0; From 9b1ce8baf0b8282b65d8b5f3db638e7843358aa4 Mon Sep 17 00:00:00 2001 From: Matthijs Kooijman Date: Thu, 17 May 2018 18:03:35 +0200 Subject: [PATCH 75/80] Increment count in constructor instead of insert() This allows reusing insert() later to move tests from the done list back into the active list, without affecting the count. --- src/ArduinoUnitUtility/ArduinoUnit.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/ArduinoUnitUtility/ArduinoUnit.cpp b/src/ArduinoUnitUtility/ArduinoUnit.cpp index 475c846..525ded5 100644 --- a/src/ArduinoUnitUtility/ArduinoUnit.cpp +++ b/src/ArduinoUnitUtility/ArduinoUnit.cpp @@ -99,12 +99,14 @@ Test::Test(const __FlashStringHelper *_name, uint8_t _verbosity) : name(_name), verbosity(_verbosity) { insert(); + ++Test::count; } Test::Test(const char *_name, uint8_t _verbosity) : name(_name), verbosity(_verbosity) { insert(); + ++Test::count; } void Test::insert() @@ -119,7 +121,6 @@ void Test::insert() next=(*p); (*p)=this; } - ++Test::count; } void Test::pass() { if (current != 0) current->state = DONE_PASS; } From 63108e8d24eda9fa8d772a7b328c7e8e35c0cf6a Mon Sep 17 00:00:00 2001 From: Matthijs Kooijman Date: Wed, 26 Jul 2017 17:04:23 +0200 Subject: [PATCH 76/80] Add Test::resetDoneTest() to re-run completed tests --- src/ArduinoUnit.h | 10 ++++++++++ src/ArduinoUnitUtility/ArduinoUnit.cpp | 11 +++++++++++ 2 files changed, 21 insertions(+) diff --git a/src/ArduinoUnit.h b/src/ArduinoUnit.h index 7bd5e40..56c8998 100644 --- a/src/ArduinoUnit.h +++ b/src/ArduinoUnit.h @@ -430,6 +430,16 @@ class Test /** Run a test. Test::loop() will be called on each Test::run() until a pass(), fail() or skip(). */ virtual void loop() = 0; + /** + * Reset all done tests (including skipped tests), so they can be run + * again, and reset the counters to reflect this. Any tests that are + * not completed are unaffected. + * + * Should never be called from inside a test, but only between calls + * to Test::run() (and typically only when all tests are done). + */ + static void resetDoneTests(); + /** include (use) currently excluded (skipped) tests that match some wildcard (*) pattern like, diff --git a/src/ArduinoUnitUtility/ArduinoUnit.cpp b/src/ArduinoUnitUtility/ArduinoUnit.cpp index 525ded5..1b602fd 100644 --- a/src/ArduinoUnitUtility/ArduinoUnit.cpp +++ b/src/ArduinoUnitUtility/ArduinoUnit.cpp @@ -190,6 +190,17 @@ Test::~Test() remove(); } +void Test::resetDoneTests() { + Test::passed = Test::failed = Test::skipped = 0; + Test *p = done; + while (p != 0) { + Test *next = p->next; + p->insert(); + p = next; + } + done = 0; +} + void Test::include(const char *pattern) { for (Test *p = root; p != 0; p=p->next) { From 9b144935b508681169700b114af2f781868f7793 Mon Sep 17 00:00:00 2001 From: Matthijs Kooijman Date: Thu, 17 May 2018 18:09:05 +0200 Subject: [PATCH 77/80] Add Test::runUntilDone() This simply calls Test::run() until all tests are done. --- src/ArduinoUnit.h | 3 +++ src/ArduinoUnitUtility/ArduinoUnit.cpp | 5 +++++ 2 files changed, 8 insertions(+) diff --git a/src/ArduinoUnit.h b/src/ArduinoUnit.h index 56c8998..242233c 100644 --- a/src/ArduinoUnit.h +++ b/src/ArduinoUnit.h @@ -489,6 +489,9 @@ void loop() { */ static void run(); + /** Repeatedly call run until all tests are done */ + static void runUntilDone(); + /** number of tests that have are not done (skipped, passed, or failed) */ static int remaining(); diff --git a/src/ArduinoUnitUtility/ArduinoUnit.cpp b/src/ArduinoUnitUtility/ArduinoUnit.cpp index 1b602fd..56ae64f 100644 --- a/src/ArduinoUnitUtility/ArduinoUnit.cpp +++ b/src/ArduinoUnitUtility/ArduinoUnit.cpp @@ -167,6 +167,11 @@ void Test::run() current = 0; } +void Test::runUntilDone() { + while (Test::root != 0) + Test::run(); +} + void Test::abort() { while (root != 0) { From c96d03d405dea4be713768287070e64fa676ccbb Mon Sep 17 00:00:00 2001 From: Matthijs Kooijman Date: Thu, 17 May 2018 17:52:11 +0200 Subject: [PATCH 78/80] Document resetDoneTests() and runUntilDone() --- README.md | 49 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) diff --git a/README.md b/README.md index 5057602..38493bf 100644 --- a/README.md +++ b/README.md @@ -137,6 +137,55 @@ void setup() } ``` +## Re-running tests (advanced) +Typically, you just want to run all tests once and then show the result. +If so, you can skip this section. + +In more advanced situations, you might want to run the entire test suite +multiple times (for example if your tests can be configured with +different parameters). To facilitate this, you can use the +`Test::resetDoneTests()` function. + +Calling this function will reset all completed tests (passed, failed or +skipped) back to their initial state. For tests that define a `setup` +method, this will be run again on the next `Test::run()`. If any tests +were not completed yet, these are unaffected. The statistics (number of +passed, failed and skipped tests) are also reset to 0. + +Note that excluded tests (using `Test::exclude()`) are treated as +skipped tests, so these are also re-run (you will need to call +`Test::exclude()` again after `resetDoneTests()` if you want keep these +tests excluded). Tests removed with their `remove()` method are really +removed, so not re-run when using `resetDoneTests()`. + +Typically, you would use this after all tests are completed (but if you +call `resetDoneTests()` when some tests are still pending, those +tests are unaffected). You must never call `resetDoneTests()` from +inside a test, only between calls to `Test::run()`. + +Below is an example that runs all tests once, then changes a global +variable and runs all tests again. To have a bit more direct control +over running the tests, this example does not call `Test::run()` +infinitely in the `loop()`, but instead uses `Test:runUntilDone()` which +repeatedly calls `Test::run()` until all tests are completed. + +``` +bool some_global_setting = false; + +void setup() { + Serial.begin(9600); + while(!Serial) {} // Portability for Leonardo/Micro + + Test::runUntilDone(); + + some_global_setting = true; + Test::resetDoneTests(); + Test::runUntilDone(); +} + +void loop() { } +``` + # Output The `Test::out` value is the *shared* value for all tests describing where output for all tests goes. The default is From e9dacf474395ead60c81c802f0beb13fde3fc2de Mon Sep 17 00:00:00 2001 From: Warren MacEvoy Date: Tue, 23 May 2023 14:57:25 -0600 Subject: [PATCH 79/80] reset script --- tester/resetArduinoFromRPi | 75 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 75 insertions(+) create mode 100755 tester/resetArduinoFromRPi diff --git a/tester/resetArduinoFromRPi b/tester/resetArduinoFromRPi new file mode 100755 index 0000000..a507884 --- /dev/null +++ b/tester/resetArduinoFromRPi @@ -0,0 +1,75 @@ +#!/bin/bash + +# +# If you connect a gpio pin (see pinout command) to the reset pin of an arduino, +# this script sets that pin low for 10 ms, then back to input mode. +# +# This should reset the corresponding device. +# +# (connect top right pin of RPi to reset pin on Arduino board) +# Ex: resetArduinoFromRPi 40 +# + +pins2gpios() { + if [ -z "$PINOUT" ] + then + PINOUT="$(pinout)" + fi + + local -a gpios=() + local gpio + + for pin in "$@" + do + if [ $(($pin % 2)) -eq 0 ] + then + gpio=$(echo "$PINOUT" | egrep "\($pin\) *GPIO" | sed -e "s/^.*(\($pin\)) *GPIO\([0-9]*\).*$/\2/") + else + gpio=$(echo "$PINOUT" | egrep "GPIO[0-9]+ *\($pin\)" | sed -e "s/^.*GPIO\([0-9]*\) *(\($pin\)).*$/\1/") + fi + if [[ "$gpio" =~ ^[0-9]+$ ]] + then + gpios+=($gpio) + else + gpios+=("-") + fi + done + + echo ${gpios[@]} +} + +exportPin() +{ + if [ ! -e /sys/class/gpio/gpio$1 ] + then + echo "$1" > /sys/class/gpio/export + fi +} + +setOutput() +{ + exportPin $1 + echo "out" > /sys/class/gpio/gpio$1/direction + echo $2 > /sys/class/gpio/gpio$1/value +} + +setInput() +{ + exportPin $1 + echo "in" > /sys/class/gpio/gpio$1/direction +} + +declare -a gpios=() +gpios=$(pins2gpios "$@") + +for gpio in ${gpios[@]} +do + setOutput $gpio 0 +done + +sleep 0.010 + +for gpio in ${gpios[@]} +do + setInput $gpio +done From 6e7e6dd923508732561152686148b980105e7fcd Mon Sep 17 00:00:00 2001 From: Warren MacEvoy Date: Wed, 24 May 2023 08:51:12 -0600 Subject: [PATCH 80/80] cleaner factored script --- tester/gpio | 53 +++++++++++++++++++++++ tester/pins2gpios | 54 ++++++++++++++++++++++++ tester/resetArduinoFromRPi | 86 ++++++++++---------------------------- 3 files changed, 128 insertions(+), 65 deletions(-) create mode 100755 tester/gpio create mode 100755 tester/pins2gpios diff --git a/tester/gpio b/tester/gpio new file mode 100755 index 0000000..64e6dfe --- /dev/null +++ b/tester/gpio @@ -0,0 +1,53 @@ +gpio_export() +{ + if [ ! -e /sys/class/gpio/gpio$1 ] + then + echo "$1" > /sys/class/gpio/export + fi +} + +gpio_set() +{ + gpio_export $1 + echo "out" > /sys/class/gpio/gpio$1/direction + echo $2 > /sys/class/gpio/gpio$1/value +} + +gpio_get() +{ + gpio_export $1 + echo "in" > /sys/class/gpio/gpio$1/direction + cat /sys/class/gpio/gpio$1/value +} + +gpio() +{ + while [ $# -gt 0 ] + do + case $1 + in + set) + pin=$2; value=$3; shift; shift; shift; + gpio_set $pin $value; + ;; + get) + pin=$2; shift; shift; + gpio_get $pin; + ;; + delay) + secs=$2; shift; shift; + sleep $secs; + ;; + *) + echo "unknown argument $1"; + exit 1; + ;; + esac + done +} + +if [ "$(basename $0)" == "gpio" ] +then + gpio "$@" +fi + diff --git a/tester/pins2gpios b/tester/pins2gpios new file mode 100755 index 0000000..f71ac20 --- /dev/null +++ b/tester/pins2gpios @@ -0,0 +1,54 @@ +#!/bin/bash + +# +# This maps the physical pin to gpio pin. For RPi 3 & RPi 4, the header is +# like so (looking down from the top of the board +# +# +------------------------------+ +# |O O +--- +# | 1111122222333334 |USB +# | 24680246802468024680 +--- +# | |||||||||||||||||||| | +# | [oooooooooooooooooooo] +--- +# | [oooooooooooooooooooo] |USB +# | |||||||||||||||||||| +--- +# | 111112222233333 | +# | 13579135791357913579 | +# | | +# +# +# Not all pins are connected to gpio. For such pins this reports "-" +# + +pins2gpios() { + if [ -z "$PINS2GPIOS_PINOUT" ] + then + PINS2GPIOS_PINOUT="$(pinout)" + fi + + local -a gpios=() + local gpio + + for pin in "$@" + do + if [ $(($pin % 2)) -eq 0 ] + then + gpio=$(echo "$PINS2GPIOS_PINOUT" | egrep "\($pin\) *GPIO" | sed -e "s/^.*(\($pin\)) *GPIO\([0-9]*\).*$/\2/") + else + gpio=$(echo "$PINS2GPIOS_PINOUT" | egrep "GPIO[0-9]+ *\($pin\)" | sed -e "s/^.*GPIO\([0-9]*\) *(\($pin\)).*$/\1/") + fi + if [[ "$gpio" =~ ^[0-9]+$ ]] + then + gpios+=($gpio) + else + gpios+=("-") + fi + done + + echo ${gpios[@]} +} + +if [ "$(basename $0)" == "pins2gpios" ] +then + pins2gpios "$@" +fi diff --git a/tester/resetArduinoFromRPi b/tester/resetArduinoFromRPi index a507884..966e5f8 100755 --- a/tester/resetArduinoFromRPi +++ b/tester/resetArduinoFromRPi @@ -1,75 +1,31 @@ #!/bin/bash -# -# If you connect a gpio pin (see pinout command) to the reset pin of an arduino, -# this script sets that pin low for 10 ms, then back to input mode. -# -# This should reset the corresponding device. -# -# (connect top right pin of RPi to reset pin on Arduino board) -# Ex: resetArduinoFromRPi 40 -# +for inc in pins2gpios gpio +do + if [ "$(type -t $inc)" != "function" ] + then + . "$(cd "$(dirname "${BASH_SOURCE[0]}")"; pwd)"/$inc + fi +done -pins2gpios() { - if [ -z "$PINOUT" ] - then - PINOUT="$(pinout)" - fi +resetArduinoFromRPi() { + declare -a gpios=() + gpios=$(pins2gpios "$@") - local -a gpios=() - local gpio - - for pin in "$@" + for gpio_pin in ${gpios[@]} do - if [ $(($pin % 2)) -eq 0 ] - then - gpio=$(echo "$PINOUT" | egrep "\($pin\) *GPIO" | sed -e "s/^.*(\($pin\)) *GPIO\([0-9]*\).*$/\2/") - else - gpio=$(echo "$PINOUT" | egrep "GPIO[0-9]+ *\($pin\)" | sed -e "s/^.*GPIO\([0-9]*\) *(\($pin\)).*$/\1/") - fi - if [[ "$gpio" =~ ^[0-9]+$ ]] - then - gpios+=($gpio) - else - gpios+=("-") - fi + gpio_set $gpio_pin 0 done - - echo ${gpios[@]} -} -exportPin() -{ - if [ ! -e /sys/class/gpio/gpio$1 ] - then - echo "$1" > /sys/class/gpio/export - fi -} + sleep 0.010 -setOutput() -{ - exportPin $1 - echo "out" > /sys/class/gpio/gpio$1/direction - echo $2 > /sys/class/gpio/gpio$1/value -} - -setInput() -{ - exportPin $1 - echo "in" > /sys/class/gpio/gpio$1/direction + for gpio_pin in ${gpios[@]} + do + unused=$(gpio_get $gpio_pin) + done } -declare -a gpios=() -gpios=$(pins2gpios "$@") - -for gpio in ${gpios[@]} -do - setOutput $gpio 0 -done - -sleep 0.010 - -for gpio in ${gpios[@]} -do - setInput $gpio -done +if [ "$(basename $0)" == "resetArduinoFromRPi" ] +then + resetArduinoFromRPi "$@" +fi