From 9ba3de6ea19a7c86f7ecd9ceefabbf732949e662 Mon Sep 17 00:00:00 2001 From: Damien George Date: Wed, 15 Nov 2017 12:46:08 +1100 Subject: tools/mpy-tool.py: Implement freezing of Ellipsis const object. --- tools/mpy-tool.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'tools') diff --git a/tools/mpy-tool.py b/tools/mpy-tool.py index ac7b2c1cc..eeb760a5f 100755 --- a/tools/mpy-tool.py +++ b/tools/mpy-tool.py @@ -287,7 +287,9 @@ class RawCode: # generate constant objects for i, obj in enumerate(self.objs): obj_name = 'const_obj_%s_%u' % (self.escaped_name, i) - if is_str_type(obj) or is_bytes_type(obj): + if obj is Ellipsis: + print('#define %s mp_const_ellipsis_obj' % obj_name) + elif is_str_type(obj) or is_bytes_type(obj): if is_str_type(obj): obj = bytes_cons(obj, 'utf8') obj_type = 'mp_type_str' @@ -328,7 +330,6 @@ class RawCode: print('STATIC const mp_obj_complex_t %s = {{&mp_type_complex}, %.16g, %.16g};' % (obj_name, obj.real, obj.imag)) else: - # TODO raise FreezeError(self, 'freezing of object %r is not implemented' % (obj,)) # generate constant table, if it has any entries -- cgit v1.2.3 From 7cf446f3daa820b15f0027d3468f1b78be17fec7 Mon Sep 17 00:00:00 2001 From: Damien George Date: Tue, 28 Nov 2017 10:50:32 +1100 Subject: tools/gen-cpydiff.py: Update executable paths to point to new ports dir. --- tools/gen-cpydiff.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'tools') diff --git a/tools/gen-cpydiff.py b/tools/gen-cpydiff.py index aff5b56e7..8aef37514 100644 --- a/tools/gen-cpydiff.py +++ b/tools/gen-cpydiff.py @@ -39,10 +39,10 @@ from collections import namedtuple # to the correct executable. if os.name == 'nt': CPYTHON3 = os.getenv('MICROPY_CPYTHON3', 'python3.exe') - MICROPYTHON = os.getenv('MICROPY_MICROPYTHON', '../windows/micropython.exe') + MICROPYTHON = os.getenv('MICROPY_MICROPYTHON', '../ports/windows/micropython.exe') else: CPYTHON3 = os.getenv('MICROPY_CPYTHON3', 'python3') - MICROPYTHON = os.getenv('MICROPY_MICROPYTHON', '../unix/micropython') + MICROPYTHON = os.getenv('MICROPY_MICROPYTHON', '../ports/unix/micropython') TESTPATH = '../tests/cpydiff/' DOCPATH = '../docs/genrst/' -- cgit v1.2.3 From e9d29c9ba997ae0f00f16f3a21dffce7c763a3d4 Mon Sep 17 00:00:00 2001 From: Paul Sokolovsky Date: Fri, 8 Dec 2017 19:26:15 +0200 Subject: lib/tinytest: Move from tools/tinytest. Tinytest library was misplaced under tools/. By convention, any target libraries belong to lib/, while tools/ contains host-side tools. --- lib/tinytest/README | 18 ++ lib/tinytest/tinytest.c | 474 +++++++++++++++++++++++++++++++++++++++ lib/tinytest/tinytest.h | 98 ++++++++ lib/tinytest/tinytest_macros.h | 184 +++++++++++++++ ports/qemu-arm/Makefile | 6 +- tools/tinytest/README | 18 -- tools/tinytest/tinytest.c | 474 --------------------------------------- tools/tinytest/tinytest.h | 98 -------- tools/tinytest/tinytest_macros.h | 184 --------------- 9 files changed, 778 insertions(+), 776 deletions(-) create mode 100644 lib/tinytest/README create mode 100644 lib/tinytest/tinytest.c create mode 100644 lib/tinytest/tinytest.h create mode 100644 lib/tinytest/tinytest_macros.h delete mode 100644 tools/tinytest/README delete mode 100644 tools/tinytest/tinytest.c delete mode 100644 tools/tinytest/tinytest.h delete mode 100644 tools/tinytest/tinytest_macros.h (limited to 'tools') diff --git a/lib/tinytest/README b/lib/tinytest/README new file mode 100644 index 000000000..902c4a2e0 --- /dev/null +++ b/lib/tinytest/README @@ -0,0 +1,18 @@ +Tinytest is a tiny little test framework written in C by Nick Mathewson. + +It is distributed under the 3-clause BSD license. You can use it in +your own programs so long as you follow the license's conditions. + +It's been tested on Windows, Mac, and many of the free Unixes. + +It knows how to fork before running certain tests, and it makes +text-mode output in a format I like. + +For info on how to use it, check out tinytest_demo.c. + +You can get the latest version using Git, by pulling from + git://github.com/nmathewson/tinytest.git + +Patches are welcome. Patches that turn this from tinytest to hugetest +will not be applied. If you want a huge test framework, use CUnit. + diff --git a/lib/tinytest/tinytest.c b/lib/tinytest/tinytest.c new file mode 100644 index 000000000..1ef957d31 --- /dev/null +++ b/lib/tinytest/tinytest.c @@ -0,0 +1,474 @@ +/* tinytest.c -- Copyright 2009-2012 Nick Mathewson + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#ifdef TINYTEST_LOCAL +#include "tinytest_local.h" +#endif + +#include +#include +#include +#include + +#ifndef NO_FORKING + +#ifdef _WIN32 +#include +#else +#include +#include +#include +#endif + +#if defined(__APPLE__) && defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) +#if (__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ >= 1060 && \ + __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ < 1070) +/* Workaround for a stupid bug in OSX 10.6 */ +#define FORK_BREAKS_GCOV +#include +#endif +#endif + +#endif /* !NO_FORKING */ + +#ifndef __GNUC__ +#define __attribute__(x) +#endif + +#include "tinytest.h" +#include "tinytest_macros.h" + +#define LONGEST_TEST_NAME 16384 + +static int in_tinytest_main = 0; /**< true if we're in tinytest_main().*/ +static int n_ok = 0; /**< Number of tests that have passed */ +static int n_bad = 0; /**< Number of tests that have failed. */ +static int n_skipped = 0; /**< Number of tests that have been skipped. */ + +static int opt_forked = 0; /**< True iff we're called from inside a win32 fork*/ +static int opt_nofork = 0; /**< Suppress calls to fork() for debugging. */ +static int opt_verbosity = 1; /**< -==quiet,0==terse,1==normal,2==verbose */ +const char *verbosity_flag = ""; + +const struct testlist_alias_t *cfg_aliases=NULL; + +enum outcome { SKIP=2, OK=1, FAIL=0 }; +static enum outcome cur_test_outcome = 0; +const char *cur_test_prefix = NULL; /**< prefix of the current test group */ +/** Name of the current test, if we haven't logged is yet. Used for --quiet */ +const char *cur_test_name = NULL; + +#ifdef _WIN32 +/* Copy of argv[0] for win32. */ +static char commandname[MAX_PATH+1]; +#endif + +static void usage(struct testgroup_t *groups, int list_groups) + __attribute__((noreturn)); +static int process_test_option(struct testgroup_t *groups, const char *test); + +static enum outcome +testcase_run_bare_(const struct testcase_t *testcase) +{ + void *env = NULL; + int outcome; + if (testcase->setup) { + env = testcase->setup->setup_fn(testcase); + if (!env) + return FAIL; + else if (env == (void*)TT_SKIP) + return SKIP; + } + + cur_test_outcome = OK; + testcase->fn(env); + outcome = cur_test_outcome; + + if (testcase->setup) { + if (testcase->setup->cleanup_fn(testcase, env) == 0) + outcome = FAIL; + } + + return outcome; +} + +#define MAGIC_EXITCODE 42 + +#ifndef NO_FORKING + +static enum outcome +testcase_run_forked_(const struct testgroup_t *group, + const struct testcase_t *testcase) +{ +#ifdef _WIN32 + /* Fork? On Win32? How primitive! We'll do what the smart kids do: + we'll invoke our own exe (whose name we recall from the command + line) with a command line that tells it to run just the test we + want, and this time without forking. + + (No, threads aren't an option. The whole point of forking is to + share no state between tests.) + */ + int ok; + char buffer[LONGEST_TEST_NAME+256]; + STARTUPINFOA si; + PROCESS_INFORMATION info; + DWORD exitcode; + + if (!in_tinytest_main) { + printf("\nERROR. On Windows, testcase_run_forked_ must be" + " called from within tinytest_main.\n"); + abort(); + } + if (opt_verbosity>0) + printf("[forking] "); + + snprintf(buffer, sizeof(buffer), "%s --RUNNING-FORKED %s %s%s", + commandname, verbosity_flag, group->prefix, testcase->name); + + memset(&si, 0, sizeof(si)); + memset(&info, 0, sizeof(info)); + si.cb = sizeof(si); + + ok = CreateProcessA(commandname, buffer, NULL, NULL, 0, + 0, NULL, NULL, &si, &info); + if (!ok) { + printf("CreateProcess failed!\n"); + return 0; + } + WaitForSingleObject(info.hProcess, INFINITE); + GetExitCodeProcess(info.hProcess, &exitcode); + CloseHandle(info.hProcess); + CloseHandle(info.hThread); + if (exitcode == 0) + return OK; + else if (exitcode == MAGIC_EXITCODE) + return SKIP; + else + return FAIL; +#else + int outcome_pipe[2]; + pid_t pid; + (void)group; + + if (pipe(outcome_pipe)) + perror("opening pipe"); + + if (opt_verbosity>0) + printf("[forking] "); + pid = fork(); +#ifdef FORK_BREAKS_GCOV + vproc_transaction_begin(0); +#endif + if (!pid) { + /* child. */ + int test_r, write_r; + char b[1]; + close(outcome_pipe[0]); + test_r = testcase_run_bare_(testcase); + assert(0<=(int)test_r && (int)test_r<=2); + b[0] = "NYS"[test_r]; + write_r = (int)write(outcome_pipe[1], b, 1); + if (write_r != 1) { + perror("write outcome to pipe"); + exit(1); + } + exit(0); + return FAIL; /* unreachable */ + } else { + /* parent */ + int status, r; + char b[1]; + /* Close this now, so that if the other side closes it, + * our read fails. */ + close(outcome_pipe[1]); + r = (int)read(outcome_pipe[0], b, 1); + if (r == 0) { + printf("[Lost connection!] "); + return 0; + } else if (r != 1) { + perror("read outcome from pipe"); + } + waitpid(pid, &status, 0); + close(outcome_pipe[0]); + return b[0]=='Y' ? OK : (b[0]=='S' ? SKIP : FAIL); + } +#endif +} + +#endif /* !NO_FORKING */ + +int +testcase_run_one(const struct testgroup_t *group, + const struct testcase_t *testcase) +{ + enum outcome outcome; + + if (testcase->flags & (TT_SKIP|TT_OFF_BY_DEFAULT)) { + if (opt_verbosity>0) + printf("%s%s: %s\n", + group->prefix, testcase->name, + (testcase->flags & TT_SKIP) ? "SKIPPED" : "DISABLED"); + ++n_skipped; + return SKIP; + } + + if (opt_verbosity>0 && !opt_forked) { + printf("%s%s: ", group->prefix, testcase->name); + } else { + if (opt_verbosity==0) printf("."); + cur_test_prefix = group->prefix; + cur_test_name = testcase->name; + } + +#ifndef NO_FORKING + if ((testcase->flags & TT_FORK) && !(opt_forked||opt_nofork)) { + outcome = testcase_run_forked_(group, testcase); + } else { +#else + { +#endif + outcome = testcase_run_bare_(testcase); + } + + if (outcome == OK) { + ++n_ok; + if (opt_verbosity>0 && !opt_forked) + puts(opt_verbosity==1?"OK":""); + } else if (outcome == SKIP) { + ++n_skipped; + if (opt_verbosity>0 && !opt_forked) + puts("SKIPPED"); + } else { + ++n_bad; + if (!opt_forked) + printf("\n [%s FAILED]\n", testcase->name); + } + + if (opt_forked) { + exit(outcome==OK ? 0 : (outcome==SKIP?MAGIC_EXITCODE : 1)); + return 1; /* unreachable */ + } else { + return (int)outcome; + } +} + +int +tinytest_set_flag_(struct testgroup_t *groups, const char *arg, int set, unsigned long flag) +{ + int i, j; + size_t length = LONGEST_TEST_NAME; + char fullname[LONGEST_TEST_NAME]; + int found=0; + if (strstr(arg, "..")) + length = strstr(arg,"..")-arg; + for (i=0; groups[i].prefix; ++i) { + for (j=0; groups[i].cases[j].name; ++j) { + struct testcase_t *testcase = &groups[i].cases[j]; + snprintf(fullname, sizeof(fullname), "%s%s", + groups[i].prefix, testcase->name); + if (!flag) { /* Hack! */ + printf(" %s", fullname); + if (testcase->flags & TT_OFF_BY_DEFAULT) + puts(" (Off by default)"); + else if (testcase->flags & TT_SKIP) + puts(" (DISABLED)"); + else + puts(""); + } + if (!strncmp(fullname, arg, length)) { + if (set) + testcase->flags |= flag; + else + testcase->flags &= ~flag; + ++found; + } + } + } + return found; +} + +static void +usage(struct testgroup_t *groups, int list_groups) +{ + puts("Options are: [--verbose|--quiet|--terse] [--no-fork]"); + puts(" Specify tests by name, or using a prefix ending with '..'"); + puts(" To skip a test, prefix its name with a colon."); + puts(" To enable a disabled test, prefix its name with a plus."); + puts(" Use --list-tests for a list of tests."); + if (list_groups) { + puts("Known tests are:"); + tinytest_set_flag_(groups, "..", 1, 0); + } + exit(0); +} + +static int +process_test_alias(struct testgroup_t *groups, const char *test) +{ + int i, j, n, r; + for (i=0; cfg_aliases && cfg_aliases[i].name; ++i) { + if (!strcmp(cfg_aliases[i].name, test)) { + n = 0; + for (j = 0; cfg_aliases[i].tests[j]; ++j) { + r = process_test_option(groups, cfg_aliases[i].tests[j]); + if (r<0) + return -1; + n += r; + } + return n; + } + } + printf("No such test alias as @%s!",test); + return -1; +} + +static int +process_test_option(struct testgroup_t *groups, const char *test) +{ + int flag = TT_ENABLED_; + int n = 0; + if (test[0] == '@') { + return process_test_alias(groups, test + 1); + } else if (test[0] == ':') { + ++test; + flag = TT_SKIP; + } else if (test[0] == '+') { + ++test; + ++n; + if (!tinytest_set_flag_(groups, test, 0, TT_OFF_BY_DEFAULT)) { + printf("No such test as %s!\n", test); + return -1; + } + } else { + ++n; + } + if (!tinytest_set_flag_(groups, test, 1, flag)) { + printf("No such test as %s!\n", test); + return -1; + } + return n; +} + +void +tinytest_set_aliases(const struct testlist_alias_t *aliases) +{ + cfg_aliases = aliases; +} + +int +tinytest_main(int c, const char **v, struct testgroup_t *groups) +{ + int i, j, n=0; + +#ifdef _WIN32 + const char *sp = strrchr(v[0], '.'); + const char *extension = ""; + if (!sp || stricmp(sp, ".exe")) + extension = ".exe"; /* Add an exe so CreateProcess will work */ + snprintf(commandname, sizeof(commandname), "%s%s", v[0], extension); + commandname[MAX_PATH]='\0'; +#endif + for (i=1; i= 1) + printf("%d tests ok. (%d skipped)\n", n_ok, n_skipped); + + return (n_bad == 0) ? 0 : 1; +} + +int +tinytest_get_verbosity_(void) +{ + return opt_verbosity; +} + +void +tinytest_set_test_failed_(void) +{ + if (opt_verbosity <= 0 && cur_test_name) { + if (opt_verbosity==0) puts(""); + printf("%s%s: ", cur_test_prefix, cur_test_name); + cur_test_name = NULL; + } + cur_test_outcome = 0; +} + +void +tinytest_set_test_skipped_(void) +{ + if (cur_test_outcome==OK) + cur_test_outcome = SKIP; +} + diff --git a/lib/tinytest/tinytest.h b/lib/tinytest/tinytest.h new file mode 100644 index 000000000..dff440e31 --- /dev/null +++ b/lib/tinytest/tinytest.h @@ -0,0 +1,98 @@ +/* tinytest.h -- Copyright 2009-2012 Nick Mathewson + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef TINYTEST_H_INCLUDED_ +#define TINYTEST_H_INCLUDED_ + +/** Flag for a test that needs to run in a subprocess. */ +#define TT_FORK (1<<0) +/** Runtime flag for a test we've decided to skip. */ +#define TT_SKIP (1<<1) +/** Internal runtime flag for a test we've decided to run. */ +#define TT_ENABLED_ (1<<2) +/** Flag for a test that's off by default. */ +#define TT_OFF_BY_DEFAULT (1<<3) +/** If you add your own flags, make them start at this point. */ +#define TT_FIRST_USER_FLAG (1<<4) + +typedef void (*testcase_fn)(void *); + +struct testcase_t; + +/** Functions to initialize/teardown a structure for a testcase. */ +struct testcase_setup_t { + /** Return a new structure for use by a given testcase. */ + void *(*setup_fn)(const struct testcase_t *); + /** Clean/free a structure from setup_fn. Return 1 if ok, 0 on err. */ + int (*cleanup_fn)(const struct testcase_t *, void *); +}; + +/** A single test-case that you can run. */ +struct testcase_t { + const char *name; /**< An identifier for this case. */ + testcase_fn fn; /**< The function to run to implement this case. */ + unsigned long flags; /**< Bitfield of TT_* flags. */ + const struct testcase_setup_t *setup; /**< Optional setup/cleanup fns*/ + void *setup_data; /**< Extra data usable by setup function */ +}; +#define END_OF_TESTCASES { NULL, NULL, 0, NULL, NULL } + +/** A group of tests that are selectable together. */ +struct testgroup_t { + const char *prefix; /**< Prefix to prepend to testnames. */ + struct testcase_t *cases; /** Array, ending with END_OF_TESTCASES */ +}; +#define END_OF_GROUPS { NULL, NULL} + +struct testlist_alias_t { + const char *name; + const char **tests; +}; +#define END_OF_ALIASES { NULL, NULL } + +/** Implementation: called from a test to indicate failure, before logging. */ +void tinytest_set_test_failed_(void); +/** Implementation: called from a test to indicate that we're skipping. */ +void tinytest_set_test_skipped_(void); +/** Implementation: return 0 for quiet, 1 for normal, 2 for loud. */ +int tinytest_get_verbosity_(void); +/** Implementation: Set a flag on tests matching a name; returns number + * of tests that matched. */ +int tinytest_set_flag_(struct testgroup_t *, const char *, int set, unsigned long); + +/** Set all tests in 'groups' matching the name 'named' to be skipped. */ +#define tinytest_skip(groups, named) \ + tinytest_set_flag_(groups, named, 1, TT_SKIP) + +/** Run a single testcase in a single group. */ +int testcase_run_one(const struct testgroup_t *,const struct testcase_t *); + +void tinytest_set_aliases(const struct testlist_alias_t *aliases); + +/** Run a set of testcases from an END_OF_GROUPS-terminated array of groups, + as selected from the command line. */ +int tinytest_main(int argc, const char **argv, struct testgroup_t *groups); + +#endif diff --git a/lib/tinytest/tinytest_macros.h b/lib/tinytest/tinytest_macros.h new file mode 100644 index 000000000..9ff69b1d5 --- /dev/null +++ b/lib/tinytest/tinytest_macros.h @@ -0,0 +1,184 @@ +/* tinytest_macros.h -- Copyright 2009-2012 Nick Mathewson + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef TINYTEST_MACROS_H_INCLUDED_ +#define TINYTEST_MACROS_H_INCLUDED_ + +/* Helpers for defining statement-like macros */ +#define TT_STMT_BEGIN do { +#define TT_STMT_END } while (0) + +/* Redefine this if your test functions want to abort with something besides + * "goto end;" */ +#ifndef TT_EXIT_TEST_FUNCTION +#define TT_EXIT_TEST_FUNCTION TT_STMT_BEGIN goto end; TT_STMT_END +#endif + +/* Redefine this if you want to note success/failure in some different way. */ +#ifndef TT_DECLARE +#define TT_DECLARE(prefix, args) \ + TT_STMT_BEGIN \ + printf("\n %s %s:%d: ",prefix,__FILE__,__LINE__); \ + printf args ; \ + TT_STMT_END +#endif + +/* Announce a failure. Args are parenthesized printf args. */ +#define TT_GRIPE(args) TT_DECLARE("FAIL", args) + +/* Announce a non-failure if we're verbose. */ +#define TT_BLATHER(args) \ + TT_STMT_BEGIN \ + if (tinytest_get_verbosity_()>1) TT_DECLARE(" OK", args); \ + TT_STMT_END + +#define TT_DIE(args) \ + TT_STMT_BEGIN \ + tinytest_set_test_failed_(); \ + TT_GRIPE(args); \ + TT_EXIT_TEST_FUNCTION; \ + TT_STMT_END + +#define TT_FAIL(args) \ + TT_STMT_BEGIN \ + tinytest_set_test_failed_(); \ + TT_GRIPE(args); \ + TT_STMT_END + +/* Fail and abort the current test for the reason in msg */ +#define tt_abort_printf(msg) TT_DIE(msg) +#define tt_abort_perror(op) TT_DIE(("%s: %s [%d]",(op),strerror(errno), errno)) +#define tt_abort_msg(msg) TT_DIE(("%s", msg)) +#define tt_abort() TT_DIE(("%s", "(Failed.)")) + +/* Fail but do not abort the current test for the reason in msg. */ +#define tt_failprint_f(msg) TT_FAIL(msg) +#define tt_fail_perror(op) TT_FAIL(("%s: %s [%d]",(op),strerror(errno), errno)) +#define tt_fail_msg(msg) TT_FAIL(("%s", msg)) +#define tt_fail() TT_FAIL(("%s", "(Failed.)")) + +/* End the current test, and indicate we are skipping it. */ +#define tt_skip() \ + TT_STMT_BEGIN \ + tinytest_set_test_skipped_(); \ + TT_EXIT_TEST_FUNCTION; \ + TT_STMT_END + +#define tt_want_(b, msg, fail) \ + TT_STMT_BEGIN \ + if (!(b)) { \ + tinytest_set_test_failed_(); \ + TT_GRIPE(("%s",msg)); \ + fail; \ + } else { \ + TT_BLATHER(("%s",msg)); \ + } \ + TT_STMT_END + +/* Assert b, but do not stop the test if b fails. Log msg on failure. */ +#define tt_want_msg(b, msg) \ + tt_want_(b, msg, ); + +/* Assert b and stop the test if b fails. Log msg on failure. */ +#define tt_assert_msg(b, msg) \ + tt_want_(b, msg, TT_EXIT_TEST_FUNCTION); + +/* Assert b, but do not stop the test if b fails. */ +#define tt_want(b) tt_want_msg( (b), "want("#b")") +/* Assert b, and stop the test if b fails. */ +#define tt_assert(b) tt_assert_msg((b), "assert("#b")") + +#define tt_assert_test_fmt_type(a,b,str_test,type,test,printf_type,printf_fmt, \ + setup_block,cleanup_block,die_on_fail) \ + TT_STMT_BEGIN \ + type val1_ = (type)(a); \ + type val2_ = (type)(b); \ + int tt_status_ = (test); \ + if (!tt_status_ || tinytest_get_verbosity_()>1) { \ + printf_type print_; \ + printf_type print1_; \ + printf_type print2_; \ + type value_ = val1_; \ + setup_block; \ + print1_ = print_; \ + value_ = val2_; \ + setup_block; \ + print2_ = print_; \ + TT_DECLARE(tt_status_?" OK":"FAIL", \ + ("assert(%s): "printf_fmt" vs "printf_fmt, \ + str_test, print1_, print2_)); \ + print_ = print1_; \ + cleanup_block; \ + print_ = print2_; \ + cleanup_block; \ + if (!tt_status_) { \ + tinytest_set_test_failed_(); \ + die_on_fail ; \ + } \ + } \ + TT_STMT_END + +#define tt_assert_test_type(a,b,str_test,type,test,fmt,die_on_fail) \ + tt_assert_test_fmt_type(a,b,str_test,type,test,type,fmt, \ + {print_=value_;},{},die_on_fail) + +/* Helper: assert that a op b, when cast to type. Format the values with + * printf format fmt on failure. */ +#define tt_assert_op_type(a,op,b,type,fmt) \ + tt_assert_test_type(a,b,#a" "#op" "#b,type,(val1_ op val2_),fmt, \ + TT_EXIT_TEST_FUNCTION) + +#define tt_int_op(a,op,b) \ + tt_assert_test_type(a,b,#a" "#op" "#b,long,(val1_ op val2_), \ + "%ld",TT_EXIT_TEST_FUNCTION) + +#define tt_uint_op(a,op,b) \ + tt_assert_test_type(a,b,#a" "#op" "#b,unsigned long, \ + (val1_ op val2_),"%lu",TT_EXIT_TEST_FUNCTION) + +#define tt_ptr_op(a,op,b) \ + tt_assert_test_type(a,b,#a" "#op" "#b,void*, \ + (val1_ op val2_),"%p",TT_EXIT_TEST_FUNCTION) + +#define tt_str_op(a,op,b) \ + tt_assert_test_type(a,b,#a" "#op" "#b,const char *, \ + (strcmp(val1_,val2_) op 0),"<%s>",TT_EXIT_TEST_FUNCTION) + +#define tt_want_int_op(a,op,b) \ + tt_assert_test_type(a,b,#a" "#op" "#b,long,(val1_ op val2_),"%ld",(void)0) + +#define tt_want_uint_op(a,op,b) \ + tt_assert_test_type(a,b,#a" "#op" "#b,unsigned long, \ + (val1_ op val2_),"%lu",(void)0) + +#define tt_want_ptr_op(a,op,b) \ + tt_assert_test_type(a,b,#a" "#op" "#b,void*, \ + (val1_ op val2_),"%p",(void)0) + +#define tt_want_str_op(a,op,b) \ + tt_assert_test_type(a,b,#a" "#op" "#b,const char *, \ + (strcmp(val1_,val2_) op 0),"<%s>",(void)0) + +#endif diff --git a/ports/qemu-arm/Makefile b/ports/qemu-arm/Makefile index 39e13853f..c0d257a3e 100644 --- a/ports/qemu-arm/Makefile +++ b/ports/qemu-arm/Makefile @@ -9,10 +9,12 @@ include $(TOP)/py/py.mk CROSS_COMPILE = arm-none-eabi- +TINYTEST = $(TOP)/lib/tinytest + INC += -I. INC += -I$(TOP) INC += -I$(BUILD) -INC += -I$(TOP)/tools/tinytest/ +INC += -I$(TINYTEST) CFLAGS_CORTEX_M3 = -mthumb -mcpu=cortex-m3 -mfloat-abi=soft CFLAGS = $(INC) -Wall -Wpointer-arith -Werror -std=gnu99 $(CFLAGS_CORTEX_M3) $(COPT) \ @@ -101,7 +103,7 @@ $(BUILD)/genhdr/tests.h: $(Q)echo "Generating $@";(cd $(TOP)/tests; ../tools/tinytest-codegen.py) > $@ $(BUILD)/tinytest.o: - $(Q)$(CC) $(CFLAGS) -DNO_FORKING -o $@ -c $(TOP)/tools/tinytest/tinytest.c + $(Q)$(CC) $(CFLAGS) -DNO_FORKING -o $@ -c $(TINYTEST)/tinytest.c ## `$(LD)` doesn't seem to like `--specs` for some reason, but we can just use `$(CC)` here. $(BUILD)/firmware.elf: $(OBJ_COMMON) $(OBJ_RUN) diff --git a/tools/tinytest/README b/tools/tinytest/README deleted file mode 100644 index 902c4a2e0..000000000 --- a/tools/tinytest/README +++ /dev/null @@ -1,18 +0,0 @@ -Tinytest is a tiny little test framework written in C by Nick Mathewson. - -It is distributed under the 3-clause BSD license. You can use it in -your own programs so long as you follow the license's conditions. - -It's been tested on Windows, Mac, and many of the free Unixes. - -It knows how to fork before running certain tests, and it makes -text-mode output in a format I like. - -For info on how to use it, check out tinytest_demo.c. - -You can get the latest version using Git, by pulling from - git://github.com/nmathewson/tinytest.git - -Patches are welcome. Patches that turn this from tinytest to hugetest -will not be applied. If you want a huge test framework, use CUnit. - diff --git a/tools/tinytest/tinytest.c b/tools/tinytest/tinytest.c deleted file mode 100644 index 1ef957d31..000000000 --- a/tools/tinytest/tinytest.c +++ /dev/null @@ -1,474 +0,0 @@ -/* tinytest.c -- Copyright 2009-2012 Nick Mathewson - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -#ifdef TINYTEST_LOCAL -#include "tinytest_local.h" -#endif - -#include -#include -#include -#include - -#ifndef NO_FORKING - -#ifdef _WIN32 -#include -#else -#include -#include -#include -#endif - -#if defined(__APPLE__) && defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) -#if (__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ >= 1060 && \ - __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ < 1070) -/* Workaround for a stupid bug in OSX 10.6 */ -#define FORK_BREAKS_GCOV -#include -#endif -#endif - -#endif /* !NO_FORKING */ - -#ifndef __GNUC__ -#define __attribute__(x) -#endif - -#include "tinytest.h" -#include "tinytest_macros.h" - -#define LONGEST_TEST_NAME 16384 - -static int in_tinytest_main = 0; /**< true if we're in tinytest_main().*/ -static int n_ok = 0; /**< Number of tests that have passed */ -static int n_bad = 0; /**< Number of tests that have failed. */ -static int n_skipped = 0; /**< Number of tests that have been skipped. */ - -static int opt_forked = 0; /**< True iff we're called from inside a win32 fork*/ -static int opt_nofork = 0; /**< Suppress calls to fork() for debugging. */ -static int opt_verbosity = 1; /**< -==quiet,0==terse,1==normal,2==verbose */ -const char *verbosity_flag = ""; - -const struct testlist_alias_t *cfg_aliases=NULL; - -enum outcome { SKIP=2, OK=1, FAIL=0 }; -static enum outcome cur_test_outcome = 0; -const char *cur_test_prefix = NULL; /**< prefix of the current test group */ -/** Name of the current test, if we haven't logged is yet. Used for --quiet */ -const char *cur_test_name = NULL; - -#ifdef _WIN32 -/* Copy of argv[0] for win32. */ -static char commandname[MAX_PATH+1]; -#endif - -static void usage(struct testgroup_t *groups, int list_groups) - __attribute__((noreturn)); -static int process_test_option(struct testgroup_t *groups, const char *test); - -static enum outcome -testcase_run_bare_(const struct testcase_t *testcase) -{ - void *env = NULL; - int outcome; - if (testcase->setup) { - env = testcase->setup->setup_fn(testcase); - if (!env) - return FAIL; - else if (env == (void*)TT_SKIP) - return SKIP; - } - - cur_test_outcome = OK; - testcase->fn(env); - outcome = cur_test_outcome; - - if (testcase->setup) { - if (testcase->setup->cleanup_fn(testcase, env) == 0) - outcome = FAIL; - } - - return outcome; -} - -#define MAGIC_EXITCODE 42 - -#ifndef NO_FORKING - -static enum outcome -testcase_run_forked_(const struct testgroup_t *group, - const struct testcase_t *testcase) -{ -#ifdef _WIN32 - /* Fork? On Win32? How primitive! We'll do what the smart kids do: - we'll invoke our own exe (whose name we recall from the command - line) with a command line that tells it to run just the test we - want, and this time without forking. - - (No, threads aren't an option. The whole point of forking is to - share no state between tests.) - */ - int ok; - char buffer[LONGEST_TEST_NAME+256]; - STARTUPINFOA si; - PROCESS_INFORMATION info; - DWORD exitcode; - - if (!in_tinytest_main) { - printf("\nERROR. On Windows, testcase_run_forked_ must be" - " called from within tinytest_main.\n"); - abort(); - } - if (opt_verbosity>0) - printf("[forking] "); - - snprintf(buffer, sizeof(buffer), "%s --RUNNING-FORKED %s %s%s", - commandname, verbosity_flag, group->prefix, testcase->name); - - memset(&si, 0, sizeof(si)); - memset(&info, 0, sizeof(info)); - si.cb = sizeof(si); - - ok = CreateProcessA(commandname, buffer, NULL, NULL, 0, - 0, NULL, NULL, &si, &info); - if (!ok) { - printf("CreateProcess failed!\n"); - return 0; - } - WaitForSingleObject(info.hProcess, INFINITE); - GetExitCodeProcess(info.hProcess, &exitcode); - CloseHandle(info.hProcess); - CloseHandle(info.hThread); - if (exitcode == 0) - return OK; - else if (exitcode == MAGIC_EXITCODE) - return SKIP; - else - return FAIL; -#else - int outcome_pipe[2]; - pid_t pid; - (void)group; - - if (pipe(outcome_pipe)) - perror("opening pipe"); - - if (opt_verbosity>0) - printf("[forking] "); - pid = fork(); -#ifdef FORK_BREAKS_GCOV - vproc_transaction_begin(0); -#endif - if (!pid) { - /* child. */ - int test_r, write_r; - char b[1]; - close(outcome_pipe[0]); - test_r = testcase_run_bare_(testcase); - assert(0<=(int)test_r && (int)test_r<=2); - b[0] = "NYS"[test_r]; - write_r = (int)write(outcome_pipe[1], b, 1); - if (write_r != 1) { - perror("write outcome to pipe"); - exit(1); - } - exit(0); - return FAIL; /* unreachable */ - } else { - /* parent */ - int status, r; - char b[1]; - /* Close this now, so that if the other side closes it, - * our read fails. */ - close(outcome_pipe[1]); - r = (int)read(outcome_pipe[0], b, 1); - if (r == 0) { - printf("[Lost connection!] "); - return 0; - } else if (r != 1) { - perror("read outcome from pipe"); - } - waitpid(pid, &status, 0); - close(outcome_pipe[0]); - return b[0]=='Y' ? OK : (b[0]=='S' ? SKIP : FAIL); - } -#endif -} - -#endif /* !NO_FORKING */ - -int -testcase_run_one(const struct testgroup_t *group, - const struct testcase_t *testcase) -{ - enum outcome outcome; - - if (testcase->flags & (TT_SKIP|TT_OFF_BY_DEFAULT)) { - if (opt_verbosity>0) - printf("%s%s: %s\n", - group->prefix, testcase->name, - (testcase->flags & TT_SKIP) ? "SKIPPED" : "DISABLED"); - ++n_skipped; - return SKIP; - } - - if (opt_verbosity>0 && !opt_forked) { - printf("%s%s: ", group->prefix, testcase->name); - } else { - if (opt_verbosity==0) printf("."); - cur_test_prefix = group->prefix; - cur_test_name = testcase->name; - } - -#ifndef NO_FORKING - if ((testcase->flags & TT_FORK) && !(opt_forked||opt_nofork)) { - outcome = testcase_run_forked_(group, testcase); - } else { -#else - { -#endif - outcome = testcase_run_bare_(testcase); - } - - if (outcome == OK) { - ++n_ok; - if (opt_verbosity>0 && !opt_forked) - puts(opt_verbosity==1?"OK":""); - } else if (outcome == SKIP) { - ++n_skipped; - if (opt_verbosity>0 && !opt_forked) - puts("SKIPPED"); - } else { - ++n_bad; - if (!opt_forked) - printf("\n [%s FAILED]\n", testcase->name); - } - - if (opt_forked) { - exit(outcome==OK ? 0 : (outcome==SKIP?MAGIC_EXITCODE : 1)); - return 1; /* unreachable */ - } else { - return (int)outcome; - } -} - -int -tinytest_set_flag_(struct testgroup_t *groups, const char *arg, int set, unsigned long flag) -{ - int i, j; - size_t length = LONGEST_TEST_NAME; - char fullname[LONGEST_TEST_NAME]; - int found=0; - if (strstr(arg, "..")) - length = strstr(arg,"..")-arg; - for (i=0; groups[i].prefix; ++i) { - for (j=0; groups[i].cases[j].name; ++j) { - struct testcase_t *testcase = &groups[i].cases[j]; - snprintf(fullname, sizeof(fullname), "%s%s", - groups[i].prefix, testcase->name); - if (!flag) { /* Hack! */ - printf(" %s", fullname); - if (testcase->flags & TT_OFF_BY_DEFAULT) - puts(" (Off by default)"); - else if (testcase->flags & TT_SKIP) - puts(" (DISABLED)"); - else - puts(""); - } - if (!strncmp(fullname, arg, length)) { - if (set) - testcase->flags |= flag; - else - testcase->flags &= ~flag; - ++found; - } - } - } - return found; -} - -static void -usage(struct testgroup_t *groups, int list_groups) -{ - puts("Options are: [--verbose|--quiet|--terse] [--no-fork]"); - puts(" Specify tests by name, or using a prefix ending with '..'"); - puts(" To skip a test, prefix its name with a colon."); - puts(" To enable a disabled test, prefix its name with a plus."); - puts(" Use --list-tests for a list of tests."); - if (list_groups) { - puts("Known tests are:"); - tinytest_set_flag_(groups, "..", 1, 0); - } - exit(0); -} - -static int -process_test_alias(struct testgroup_t *groups, const char *test) -{ - int i, j, n, r; - for (i=0; cfg_aliases && cfg_aliases[i].name; ++i) { - if (!strcmp(cfg_aliases[i].name, test)) { - n = 0; - for (j = 0; cfg_aliases[i].tests[j]; ++j) { - r = process_test_option(groups, cfg_aliases[i].tests[j]); - if (r<0) - return -1; - n += r; - } - return n; - } - } - printf("No such test alias as @%s!",test); - return -1; -} - -static int -process_test_option(struct testgroup_t *groups, const char *test) -{ - int flag = TT_ENABLED_; - int n = 0; - if (test[0] == '@') { - return process_test_alias(groups, test + 1); - } else if (test[0] == ':') { - ++test; - flag = TT_SKIP; - } else if (test[0] == '+') { - ++test; - ++n; - if (!tinytest_set_flag_(groups, test, 0, TT_OFF_BY_DEFAULT)) { - printf("No such test as %s!\n", test); - return -1; - } - } else { - ++n; - } - if (!tinytest_set_flag_(groups, test, 1, flag)) { - printf("No such test as %s!\n", test); - return -1; - } - return n; -} - -void -tinytest_set_aliases(const struct testlist_alias_t *aliases) -{ - cfg_aliases = aliases; -} - -int -tinytest_main(int c, const char **v, struct testgroup_t *groups) -{ - int i, j, n=0; - -#ifdef _WIN32 - const char *sp = strrchr(v[0], '.'); - const char *extension = ""; - if (!sp || stricmp(sp, ".exe")) - extension = ".exe"; /* Add an exe so CreateProcess will work */ - snprintf(commandname, sizeof(commandname), "%s%s", v[0], extension); - commandname[MAX_PATH]='\0'; -#endif - for (i=1; i= 1) - printf("%d tests ok. (%d skipped)\n", n_ok, n_skipped); - - return (n_bad == 0) ? 0 : 1; -} - -int -tinytest_get_verbosity_(void) -{ - return opt_verbosity; -} - -void -tinytest_set_test_failed_(void) -{ - if (opt_verbosity <= 0 && cur_test_name) { - if (opt_verbosity==0) puts(""); - printf("%s%s: ", cur_test_prefix, cur_test_name); - cur_test_name = NULL; - } - cur_test_outcome = 0; -} - -void -tinytest_set_test_skipped_(void) -{ - if (cur_test_outcome==OK) - cur_test_outcome = SKIP; -} - diff --git a/tools/tinytest/tinytest.h b/tools/tinytest/tinytest.h deleted file mode 100644 index dff440e31..000000000 --- a/tools/tinytest/tinytest.h +++ /dev/null @@ -1,98 +0,0 @@ -/* tinytest.h -- Copyright 2009-2012 Nick Mathewson - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef TINYTEST_H_INCLUDED_ -#define TINYTEST_H_INCLUDED_ - -/** Flag for a test that needs to run in a subprocess. */ -#define TT_FORK (1<<0) -/** Runtime flag for a test we've decided to skip. */ -#define TT_SKIP (1<<1) -/** Internal runtime flag for a test we've decided to run. */ -#define TT_ENABLED_ (1<<2) -/** Flag for a test that's off by default. */ -#define TT_OFF_BY_DEFAULT (1<<3) -/** If you add your own flags, make them start at this point. */ -#define TT_FIRST_USER_FLAG (1<<4) - -typedef void (*testcase_fn)(void *); - -struct testcase_t; - -/** Functions to initialize/teardown a structure for a testcase. */ -struct testcase_setup_t { - /** Return a new structure for use by a given testcase. */ - void *(*setup_fn)(const struct testcase_t *); - /** Clean/free a structure from setup_fn. Return 1 if ok, 0 on err. */ - int (*cleanup_fn)(const struct testcase_t *, void *); -}; - -/** A single test-case that you can run. */ -struct testcase_t { - const char *name; /**< An identifier for this case. */ - testcase_fn fn; /**< The function to run to implement this case. */ - unsigned long flags; /**< Bitfield of TT_* flags. */ - const struct testcase_setup_t *setup; /**< Optional setup/cleanup fns*/ - void *setup_data; /**< Extra data usable by setup function */ -}; -#define END_OF_TESTCASES { NULL, NULL, 0, NULL, NULL } - -/** A group of tests that are selectable together. */ -struct testgroup_t { - const char *prefix; /**< Prefix to prepend to testnames. */ - struct testcase_t *cases; /** Array, ending with END_OF_TESTCASES */ -}; -#define END_OF_GROUPS { NULL, NULL} - -struct testlist_alias_t { - const char *name; - const char **tests; -}; -#define END_OF_ALIASES { NULL, NULL } - -/** Implementation: called from a test to indicate failure, before logging. */ -void tinytest_set_test_failed_(void); -/** Implementation: called from a test to indicate that we're skipping. */ -void tinytest_set_test_skipped_(void); -/** Implementation: return 0 for quiet, 1 for normal, 2 for loud. */ -int tinytest_get_verbosity_(void); -/** Implementation: Set a flag on tests matching a name; returns number - * of tests that matched. */ -int tinytest_set_flag_(struct testgroup_t *, const char *, int set, unsigned long); - -/** Set all tests in 'groups' matching the name 'named' to be skipped. */ -#define tinytest_skip(groups, named) \ - tinytest_set_flag_(groups, named, 1, TT_SKIP) - -/** Run a single testcase in a single group. */ -int testcase_run_one(const struct testgroup_t *,const struct testcase_t *); - -void tinytest_set_aliases(const struct testlist_alias_t *aliases); - -/** Run a set of testcases from an END_OF_GROUPS-terminated array of groups, - as selected from the command line. */ -int tinytest_main(int argc, const char **argv, struct testgroup_t *groups); - -#endif diff --git a/tools/tinytest/tinytest_macros.h b/tools/tinytest/tinytest_macros.h deleted file mode 100644 index 9ff69b1d5..000000000 --- a/tools/tinytest/tinytest_macros.h +++ /dev/null @@ -1,184 +0,0 @@ -/* tinytest_macros.h -- Copyright 2009-2012 Nick Mathewson - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef TINYTEST_MACROS_H_INCLUDED_ -#define TINYTEST_MACROS_H_INCLUDED_ - -/* Helpers for defining statement-like macros */ -#define TT_STMT_BEGIN do { -#define TT_STMT_END } while (0) - -/* Redefine this if your test functions want to abort with something besides - * "goto end;" */ -#ifndef TT_EXIT_TEST_FUNCTION -#define TT_EXIT_TEST_FUNCTION TT_STMT_BEGIN goto end; TT_STMT_END -#endif - -/* Redefine this if you want to note success/failure in some different way. */ -#ifndef TT_DECLARE -#define TT_DECLARE(prefix, args) \ - TT_STMT_BEGIN \ - printf("\n %s %s:%d: ",prefix,__FILE__,__LINE__); \ - printf args ; \ - TT_STMT_END -#endif - -/* Announce a failure. Args are parenthesized printf args. */ -#define TT_GRIPE(args) TT_DECLARE("FAIL", args) - -/* Announce a non-failure if we're verbose. */ -#define TT_BLATHER(args) \ - TT_STMT_BEGIN \ - if (tinytest_get_verbosity_()>1) TT_DECLARE(" OK", args); \ - TT_STMT_END - -#define TT_DIE(args) \ - TT_STMT_BEGIN \ - tinytest_set_test_failed_(); \ - TT_GRIPE(args); \ - TT_EXIT_TEST_FUNCTION; \ - TT_STMT_END - -#define TT_FAIL(args) \ - TT_STMT_BEGIN \ - tinytest_set_test_failed_(); \ - TT_GRIPE(args); \ - TT_STMT_END - -/* Fail and abort the current test for the reason in msg */ -#define tt_abort_printf(msg) TT_DIE(msg) -#define tt_abort_perror(op) TT_DIE(("%s: %s [%d]",(op),strerror(errno), errno)) -#define tt_abort_msg(msg) TT_DIE(("%s", msg)) -#define tt_abort() TT_DIE(("%s", "(Failed.)")) - -/* Fail but do not abort the current test for the reason in msg. */ -#define tt_failprint_f(msg) TT_FAIL(msg) -#define tt_fail_perror(op) TT_FAIL(("%s: %s [%d]",(op),strerror(errno), errno)) -#define tt_fail_msg(msg) TT_FAIL(("%s", msg)) -#define tt_fail() TT_FAIL(("%s", "(Failed.)")) - -/* End the current test, and indicate we are skipping it. */ -#define tt_skip() \ - TT_STMT_BEGIN \ - tinytest_set_test_skipped_(); \ - TT_EXIT_TEST_FUNCTION; \ - TT_STMT_END - -#define tt_want_(b, msg, fail) \ - TT_STMT_BEGIN \ - if (!(b)) { \ - tinytest_set_test_failed_(); \ - TT_GRIPE(("%s",msg)); \ - fail; \ - } else { \ - TT_BLATHER(("%s",msg)); \ - } \ - TT_STMT_END - -/* Assert b, but do not stop the test if b fails. Log msg on failure. */ -#define tt_want_msg(b, msg) \ - tt_want_(b, msg, ); - -/* Assert b and stop the test if b fails. Log msg on failure. */ -#define tt_assert_msg(b, msg) \ - tt_want_(b, msg, TT_EXIT_TEST_FUNCTION); - -/* Assert b, but do not stop the test if b fails. */ -#define tt_want(b) tt_want_msg( (b), "want("#b")") -/* Assert b, and stop the test if b fails. */ -#define tt_assert(b) tt_assert_msg((b), "assert("#b")") - -#define tt_assert_test_fmt_type(a,b,str_test,type,test,printf_type,printf_fmt, \ - setup_block,cleanup_block,die_on_fail) \ - TT_STMT_BEGIN \ - type val1_ = (type)(a); \ - type val2_ = (type)(b); \ - int tt_status_ = (test); \ - if (!tt_status_ || tinytest_get_verbosity_()>1) { \ - printf_type print_; \ - printf_type print1_; \ - printf_type print2_; \ - type value_ = val1_; \ - setup_block; \ - print1_ = print_; \ - value_ = val2_; \ - setup_block; \ - print2_ = print_; \ - TT_DECLARE(tt_status_?" OK":"FAIL", \ - ("assert(%s): "printf_fmt" vs "printf_fmt, \ - str_test, print1_, print2_)); \ - print_ = print1_; \ - cleanup_block; \ - print_ = print2_; \ - cleanup_block; \ - if (!tt_status_) { \ - tinytest_set_test_failed_(); \ - die_on_fail ; \ - } \ - } \ - TT_STMT_END - -#define tt_assert_test_type(a,b,str_test,type,test,fmt,die_on_fail) \ - tt_assert_test_fmt_type(a,b,str_test,type,test,type,fmt, \ - {print_=value_;},{},die_on_fail) - -/* Helper: assert that a op b, when cast to type. Format the values with - * printf format fmt on failure. */ -#define tt_assert_op_type(a,op,b,type,fmt) \ - tt_assert_test_type(a,b,#a" "#op" "#b,type,(val1_ op val2_),fmt, \ - TT_EXIT_TEST_FUNCTION) - -#define tt_int_op(a,op,b) \ - tt_assert_test_type(a,b,#a" "#op" "#b,long,(val1_ op val2_), \ - "%ld",TT_EXIT_TEST_FUNCTION) - -#define tt_uint_op(a,op,b) \ - tt_assert_test_type(a,b,#a" "#op" "#b,unsigned long, \ - (val1_ op val2_),"%lu",TT_EXIT_TEST_FUNCTION) - -#define tt_ptr_op(a,op,b) \ - tt_assert_test_type(a,b,#a" "#op" "#b,void*, \ - (val1_ op val2_),"%p",TT_EXIT_TEST_FUNCTION) - -#define tt_str_op(a,op,b) \ - tt_assert_test_type(a,b,#a" "#op" "#b,const char *, \ - (strcmp(val1_,val2_) op 0),"<%s>",TT_EXIT_TEST_FUNCTION) - -#define tt_want_int_op(a,op,b) \ - tt_assert_test_type(a,b,#a" "#op" "#b,long,(val1_ op val2_),"%ld",(void)0) - -#define tt_want_uint_op(a,op,b) \ - tt_assert_test_type(a,b,#a" "#op" "#b,unsigned long, \ - (val1_ op val2_),"%lu",(void)0) - -#define tt_want_ptr_op(a,op,b) \ - tt_assert_test_type(a,b,#a" "#op" "#b,void*, \ - (val1_ op val2_),"%p",(void)0) - -#define tt_want_str_op(a,op,b) \ - tt_assert_test_type(a,b,#a" "#op" "#b,const char *, \ - (strcmp(val1_,val2_) op 0),"<%s>",(void)0) - -#endif -- cgit v1.2.3 From 48e931e1d33d008c2622d3fbc5ab7e4a49296bf2 Mon Sep 17 00:00:00 2001 From: Paul Sokolovsky Date: Mon, 11 Dec 2017 19:52:06 +0200 Subject: tools/tinytest-codegen.py: Generate code for upytesthelper. The way tinytest was used in qemu-arm test target is that it didn't test much. MicroPython tests are based on matching the test output against reference output, but qemu-arm's implementation didn't do that, it effectively tested just that there was no exception during test execution. "upytesthelper" wrapper was introduce to fix it, and so test generator is now switched to generate test code for it. Also, fix PEP8 and other codestyle issues. --- tools/tinytest-codegen.py | 48 ++++++++++++++++++++++++++--------------------- 1 file changed, 27 insertions(+), 21 deletions(-) (limited to 'tools') diff --git a/tools/tinytest-codegen.py b/tools/tinytest-codegen.py index dadfea1cc..062a00935 100755 --- a/tools/tinytest-codegen.py +++ b/tools/tinytest-codegen.py @@ -1,32 +1,38 @@ -#! /usr/bin/env python3 +#!/usr/bin/env python3 import os, sys from glob import glob from re import sub def escape(s): - lookup = { - '\0': '\\0', - '\t': '\\t', - '\n': '\\n\"\n\"', - '\r': '\\r', - '\\': '\\\\', - '\"': '\\\"', - } - return "\"\"\n\"{}\"".format(''.join([lookup[x] if x in lookup else x for x in s])) + s = s.decode() + lookup = { + '\0': '\\0', + '\t': '\\t', + '\n': '\\n\"\n\"', + '\r': '\\r', + '\\': '\\\\', + '\"': '\\\"', + } + return "\"\"\n\"{}\"".format(''.join([lookup[x] if x in lookup else x for x in s])) def chew_filename(t): - return { 'func': "test_{}_fn".format(sub(r'/|\.|-', '_', t)), 'desc': t.split('/')[1] } + return { 'func': "test_{}_fn".format(sub(r'/|\.|-', '_', t)), 'desc': t.split('/')[1] } -def script_to_map(t): - r = { 'name': chew_filename(t)['func'] } - with open(t) as f: r['script'] = escape(''.join(f.readlines())) - return r +def script_to_map(test_file): + r = {"name": chew_filename(test_file)["func"]} + with open(test_file, "rb") as f: + r["script"] = escape(f.read()) + with open(test_file + ".exp", "rb") as f: + r["output"] = escape(f.read()) + return r test_function = ( "void {name}(void* data) {{\n" - " const char * pystr = {script};\n" - " do_str(pystr);\n" + " static const char pystr[] = {script};\n" + " static const char exp[] = {output};\n" + " upytest_set_expected_output(exp, sizeof(exp) - 1);\n" + " upytest_execute_test(pystr);\n" "}}" ) @@ -57,10 +63,10 @@ exclude_tests = ( output = [] for group in test_dirs: - tests = [test for test in glob('{}/*.py'.format(group)) if test not in exclude_tests] - output.extend([test_function.format(**script_to_map(test)) for test in tests]) - testcase_members = [testcase_member.format(**chew_filename(test)) for test in tests] - output.append(testcase_struct.format(name=group, body='\n'.join(testcase_members))) + tests = [test for test in glob('{}/*.py'.format(group)) if test not in exclude_tests] + output.extend([test_function.format(**script_to_map(test)) for test in tests]) + testcase_members = [testcase_member.format(**chew_filename(test)) for test in tests] + output.append(testcase_struct.format(name=group, body='\n'.join(testcase_members))) testgroup_members = [testgroup_member.format(name=group) for group in test_dirs] -- cgit v1.2.3 From 4db6a7adbe25ba2a096cd70ec4072c168fdb4bd4 Mon Sep 17 00:00:00 2001 From: Paul Sokolovsky Date: Mon, 11 Dec 2017 19:59:11 +0200 Subject: tools/tinytest-codegen: Wrap lines of exclude_tests. So it was manageable and extensible. --- tools/tinytest-codegen.py | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) (limited to 'tools') diff --git a/tools/tinytest-codegen.py b/tools/tinytest-codegen.py index 062a00935..6744446ea 100755 --- a/tools/tinytest-codegen.py +++ b/tools/tinytest-codegen.py @@ -54,10 +54,16 @@ testgroup_member = ( # currently these tests are selected because they pass on qemu-arm test_dirs = ('basics', 'micropython', 'float', 'extmod', 'inlineasm') # 'import', 'io', 'misc') exclude_tests = ( - 'float/float2int_doubleprec_intbig.py', # requires double precision floating point to work - 'inlineasm/asmfpaddsub.py', 'inlineasm/asmfpcmp.py', 'inlineasm/asmfpldrstr.py', 'inlineasm/asmfpmuldiv.py', 'inlineasm/asmfpsqrt.py', - 'extmod/ticks_diff.py', 'extmod/time_ms_us.py', 'extmod/uheapq_timeq.py', - 'extmod/vfs_fat_ramdisk.py', 'extmod/vfs_fat_fileio.py', 'extmod/vfs_fat_fsusermount.py', 'extmod/vfs_fat_oldproto.py', + 'extmod/ticks_diff.py', + 'extmod/time_ms_us.py', + 'extmod/uheapq_timeq.py', + 'extmod/vfs_fat_ramdisk.py', 'extmod/vfs_fat_fileio.py', + 'extmod/vfs_fat_fsusermount.py', 'extmod/vfs_fat_oldproto.py', + # requires double precision floating point to work + 'float/float2int_doubleprec_intbig.py', + # inline asm tests + 'inlineasm/asmfpaddsub.py', 'inlineasm/asmfpcmp.py', 'inlineasm/asmfpldrstr.py', + 'inlineasm/asmfpmuldiv.py','inlineasm/asmfpsqrt.py', ) output = [] -- cgit v1.2.3 From e6f0d547ab16096d7a2c24824c6e398c082c0d50 Mon Sep 17 00:00:00 2001 From: Paul Sokolovsky Date: Mon, 11 Dec 2017 20:00:25 +0200 Subject: tools/tinytest-codegen: More excludes after enabling expected output match. --- tools/tinytest-codegen.py | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) (limited to 'tools') diff --git a/tools/tinytest-codegen.py b/tools/tinytest-codegen.py index 6744446ea..d7761cd5a 100755 --- a/tools/tinytest-codegen.py +++ b/tools/tinytest-codegen.py @@ -54,16 +54,31 @@ testgroup_member = ( # currently these tests are selected because they pass on qemu-arm test_dirs = ('basics', 'micropython', 'float', 'extmod', 'inlineasm') # 'import', 'io', 'misc') exclude_tests = ( + # pattern matching in .exp + 'basics/bytes_compare3.py', 'extmod/ticks_diff.py', 'extmod/time_ms_us.py', 'extmod/uheapq_timeq.py', + # unicode char issue + 'extmod/ujson_loads.py', + # doesn't output to python stdout + 'extmod/ure_debug.py', + 'extmod/vfs_basic.py', 'extmod/vfs_fat_ramdisk.py', 'extmod/vfs_fat_fileio.py', 'extmod/vfs_fat_fsusermount.py', 'extmod/vfs_fat_oldproto.py', + # rounding issues + 'float/float_divmod.py', # requires double precision floating point to work 'float/float2int_doubleprec_intbig.py', - # inline asm tests + 'float/float_parse_doubleprec.py', + # inline asm FP tests (require Cortex-M4) 'inlineasm/asmfpaddsub.py', 'inlineasm/asmfpcmp.py', 'inlineasm/asmfpldrstr.py', 'inlineasm/asmfpmuldiv.py','inlineasm/asmfpsqrt.py', + # different filename in output + 'micropython/emg_exc.py', + 'micropython/heapalloc_traceback.py', + # pattern matching in .exp + 'micropython/meminfo.py', ) output = [] -- cgit v1.2.3 From 43141ddb55c715e90b60d2fa2d9d5e01cc66b511 Mon Sep 17 00:00:00 2001 From: Paul Sokolovsky Date: Wed, 13 Dec 2017 18:32:25 +0200 Subject: tools/tinytest-codegen: Take --target= option for test set selection. Gets passed to run-tests --list-tests to get actual list of tests to use. If --target= is not given, legacy set hardcoded in tinytest-codegen itself is used. Also, get rid of tinytest test groups - they aren't really used for anything, and only complicate processing. Besides, one of the next step is to limit number of tests per a generated file to control the binary size, which also will require "flat" list of tests. --- tools/tinytest-codegen.py | 28 ++++++++++++++++++++-------- 1 file changed, 20 insertions(+), 8 deletions(-) (limited to 'tools') diff --git a/tools/tinytest-codegen.py b/tools/tinytest-codegen.py index d7761cd5a..c6ba1867a 100755 --- a/tools/tinytest-codegen.py +++ b/tools/tinytest-codegen.py @@ -3,6 +3,8 @@ import os, sys from glob import glob from re import sub +import argparse + def escape(s): s = s.decode() @@ -17,7 +19,7 @@ def escape(s): return "\"\"\n\"{}\"".format(''.join([lookup[x] if x in lookup else x for x in s])) def chew_filename(t): - return { 'func': "test_{}_fn".format(sub(r'/|\.|-', '_', t)), 'desc': t.split('/')[1] } + return { 'func': "test_{}_fn".format(sub(r'/|\.|-', '_', t)), 'desc': t } def script_to_map(test_file): r = {"name": chew_filename(test_file)["func"]} @@ -47,7 +49,7 @@ testgroup_struct = ( "struct testgroup_t groups[] = {{\n{body}\n END_OF_GROUPS\n}};" ) testgroup_member = ( - " {{ \"{name}/\", {name}_tests }}," + " {{ \"{name}\", {name}_tests }}," ) ## XXX: may be we could have `--without ` argument... @@ -82,14 +84,24 @@ exclude_tests = ( ) output = [] +tests = [] + +argparser = argparse.ArgumentParser(description='Convert native MicroPython tests to tinytest/upytesthelper C code') +argparser.add_argument('--target', help='the target platform') +args = argparser.parse_args() + +if not args.target: + for group in test_dirs: + tests += [test for test in glob('{}/*.py'.format(group)) if test not in exclude_tests] +else: + for l in os.popen("./run-tests --list-tests --target=%s" % args.target, "r"): + tests.append(l.rstrip()) -for group in test_dirs: - tests = [test for test in glob('{}/*.py'.format(group)) if test not in exclude_tests] - output.extend([test_function.format(**script_to_map(test)) for test in tests]) - testcase_members = [testcase_member.format(**chew_filename(test)) for test in tests] - output.append(testcase_struct.format(name=group, body='\n'.join(testcase_members))) +output.extend([test_function.format(**script_to_map(test)) for test in tests]) +testcase_members = [testcase_member.format(**chew_filename(test)) for test in tests] +output.append(testcase_struct.format(name="", body='\n'.join(testcase_members))) -testgroup_members = [testgroup_member.format(name=group) for group in test_dirs] +testgroup_members = [testgroup_member.format(name=group) for group in [""]] output.append(testgroup_struct.format(body='\n'.join(testgroup_members))) -- cgit v1.2.3 From bb516af1eb97d0c24fa12b00bfde196b3db94c66 Mon Sep 17 00:00:00 2001 From: Damien George Date: Thu, 14 Dec 2017 10:08:37 +1100 Subject: tools/pydfu.py: Call set_configuration() on fresh USB device object. This call is required before using the device (some operating systems don't need it but others do). Fixes issue #3476. --- tools/pydfu.py | 1 + 1 file changed, 1 insertion(+) (limited to 'tools') diff --git a/tools/pydfu.py b/tools/pydfu.py index 8c0220de8..4296f07bf 100755 --- a/tools/pydfu.py +++ b/tools/pydfu.py @@ -81,6 +81,7 @@ def init(): if len(devices) > 1: raise ValueError("Multiple DFU devices found") __dev = devices[0] + __dev.set_configuration() # Claim DFU interface usb.util.claim_interface(__dev, __DFU_INTERFACE) -- cgit v1.2.3 From 325d0fc74ba9634f89f6535210944ccdd635a995 Mon Sep 17 00:00:00 2001 From: Paul Sokolovsky Date: Thu, 14 Dec 2017 12:26:59 +0200 Subject: tools/tinytest-codegen: Add --stdin switch instead of recently added --target. Instead of passing thru more and more options from tinytest-codegen to run-tests --list-tests, pipe output of run-tests --list-tests into tinytest-codegen. --- tools/tinytest-codegen.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'tools') diff --git a/tools/tinytest-codegen.py b/tools/tinytest-codegen.py index c6ba1867a..5339972cd 100755 --- a/tools/tinytest-codegen.py +++ b/tools/tinytest-codegen.py @@ -87,14 +87,14 @@ output = [] tests = [] argparser = argparse.ArgumentParser(description='Convert native MicroPython tests to tinytest/upytesthelper C code') -argparser.add_argument('--target', help='the target platform') +argparser.add_argument('--stdin', action="store_true", help='read list of tests from stdin') args = argparser.parse_args() -if not args.target: +if not args.stdin: for group in test_dirs: tests += [test for test in glob('{}/*.py'.format(group)) if test not in exclude_tests] else: - for l in os.popen("./run-tests --list-tests --target=%s" % args.target, "r"): + for l in sys.stdin: tests.append(l.rstrip()) output.extend([test_function.format(**script_to_map(test)) for test in tests]) -- cgit v1.2.3 From 4475f324202e15b98f2f365e33078aebcf0bc5a5 Mon Sep 17 00:00:00 2001 From: Paul Sokolovsky Date: Fri, 15 Dec 2017 11:37:32 +0200 Subject: tools/tinytest-codegen: Ignore system locale, write output in UTF-8. Way to reproduce a UnicodeEncodeError without this patch: LC_ALL=C tinytest-codegen.py ... --- tools/tinytest-codegen.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'tools') diff --git a/tools/tinytest-codegen.py b/tools/tinytest-codegen.py index 5339972cd..ad3b3bbec 100755 --- a/tools/tinytest-codegen.py +++ b/tools/tinytest-codegen.py @@ -106,4 +106,5 @@ testgroup_members = [testgroup_member.format(name=group) for group in [""]] output.append(testgroup_struct.format(body='\n'.join(testgroup_members))) ## XXX: may be we could have `--output ` argument... -print('\n\n'.join(output)) +# Don't depend on what system locale is set, use utf8 encoding. +sys.stdout.buffer.write('\n\n'.join(output).encode('utf8')) -- cgit v1.2.3 From f7be5f9bfa61a07a8256aaae8f22d151f6b8ad81 Mon Sep 17 00:00:00 2001 From: Damien George Date: Mon, 23 Apr 2018 16:11:27 +1000 Subject: tools/upip: Upgrade upip to 1.2.4. Uses new pypi.org URL, and now creates a socket with the address parameters returned by getaddrinfo(). --- tools/bootstrap_upip.sh | 2 +- tools/upip.py | 17 ++++++++++++----- 2 files changed, 13 insertions(+), 6 deletions(-) (limited to 'tools') diff --git a/tools/bootstrap_upip.sh b/tools/bootstrap_upip.sh index 667d0845a..2891775d7 100755 --- a/tools/bootstrap_upip.sh +++ b/tools/bootstrap_upip.sh @@ -17,7 +17,7 @@ fi # Remove any stale old version rm -rf micropython-upip-* -wget -nd -r -l1 https://pypi.python.org/pypi/micropython-upip/ --accept-regex ".*pypi.python.org/packages/source/.*.gz" --reject=html +wget -nd -rH -l1 -D files.pythonhosted.org https://pypi.org/project/micropython-upip/ --reject=html tar xfz micropython-upip-*.tar.gz tmpd="$PWD" diff --git a/tools/upip.py b/tools/upip.py index 411da49e8..a400c3174 100644 --- a/tools/upip.py +++ b/tools/upip.py @@ -1,3 +1,10 @@ +# +# upip - Package manager for MicroPython +# +# Copyright (c) 2015-2018 Paul Sokolovsky +# +# Licensed under the MIT license. +# import sys import gc import uos as os @@ -110,16 +117,16 @@ def url_open(url): proto, _, host, urlpath = url.split('/', 3) try: - ai = usocket.getaddrinfo(host, 443) + ai = usocket.getaddrinfo(host, 443, 0, usocket.SOCK_STREAM) except OSError as e: fatal("Unable to resolve %s (no Internet?)" % host, e) #print("Address infos:", ai) - addr = ai[0][4] + ai = ai[0] - s = usocket.socket(ai[0][0]) + s = usocket.socket(ai[0], ai[1], ai[2]) try: #print("Connect address:", addr) - s.connect(addr) + s.connect(ai[-1]) if proto == "https:": s = ussl.wrap_socket(s, server_hostname=host) @@ -149,7 +156,7 @@ def url_open(url): def get_pkg_metadata(name): - f = url_open("https://pypi.python.org/pypi/%s/json" % name) + f = url_open("https://pypi.org/pypi/%s/json" % name) try: return json.load(f) finally: -- cgit v1.2.3 From 3ea0862a6e3c97f6224548c41a225f270df4d205 Mon Sep 17 00:00:00 2001 From: Keith Wiley Date: Thu, 17 May 2018 22:30:35 -0700 Subject: tools/pydfu.py: Fix typo in comments. --- tools/pydfu.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'tools') diff --git a/tools/pydfu.py b/tools/pydfu.py index 4296f07bf..3f11de067 100755 --- a/tools/pydfu.py +++ b/tools/pydfu.py @@ -5,7 +5,7 @@ # details. """This module implements enough functionality to program the STM32F4xx over -DFU, without requiringdfu-util. +DFU, without requiring dfu-util. See app note AN3156 for a description of the DFU protocol. See document UM0391 for a dscription of the DFuse file. -- cgit v1.2.3 From 8fb95d652066b38e0dbb4fa5433de49eb601bdfe Mon Sep 17 00:00:00 2001 From: Damien George Date: Fri, 8 Jun 2018 15:32:49 +1000 Subject: tools/pydfu.py: Increase download packet size to full 2048 bytes. The ST DFU bootloader supports a transfer size up to 2048 bytes, so send that much data on each download (to device) packet. This almost halves total download time. --- tools/pydfu.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'tools') diff --git a/tools/pydfu.py b/tools/pydfu.py index 3f11de067..a33e49712 100755 --- a/tools/pydfu.py +++ b/tools/pydfu.py @@ -168,7 +168,7 @@ def write_memory(addr, buf, progress=None, progress_addr=0, progress_size=0): print ("Addr 0x%x %dKBs/%dKBs..." % (xfer_base + xfer_bytes, xfer_bytes // 1024, xfer_total // 1024)) - if progress and xfer_count % 256 == 0: + if progress and xfer_count % 2 == 0: progress(progress_addr, xfer_base + xfer_bytes - progress_addr, progress_size) @@ -176,7 +176,9 @@ def write_memory(addr, buf, progress=None, progress_addr=0, progress_size=0): set_address(xfer_base+xfer_bytes) # Send DNLOAD with fw data - chunk = min(64, xfer_total-xfer_bytes) + # the "2048" is the DFU transfer size supported by the ST DFU bootloader + # TODO: this number should be extracted from the USB config descriptor + chunk = min(2048, xfer_total-xfer_bytes) __dev.ctrl_transfer(0x21, __DFU_DNLOAD, 2, __DFU_INTERFACE, buf[xfer_bytes:xfer_bytes + chunk], __TIMEOUT) -- cgit v1.2.3 From 92667dc2e57420a9960f80c80da7d3c49c8c7fd6 Mon Sep 17 00:00:00 2001 From: Damien George Date: Fri, 22 Jun 2018 15:32:32 +1000 Subject: tools/pydfu.py: Add support for multiple memory segments. Segments are separated by / and begin with the memory address. This follows how the ST DFU tool works. --- tools/pydfu.py | 35 ++++++++++++++++++----------------- 1 file changed, 18 insertions(+), 17 deletions(-) (limited to 'tools') diff --git a/tools/pydfu.py b/tools/pydfu.py index a33e49712..a7adda37c 100755 --- a/tools/pydfu.py +++ b/tools/pydfu.py @@ -394,24 +394,25 @@ def get_memory_layout(device): intf = cfg[(0, 0)] mem_layout_str = get_string(device, intf.iInterface) mem_layout = mem_layout_str.split('/') - addr = int(mem_layout[1], 0) - segments = mem_layout[2].split(',') - seg_re = re.compile(r'(\d+)\*(\d+)(.)(.)') result = [] - for segment in segments: - seg_match = seg_re.match(segment) - num_pages = int(seg_match.groups()[0], 10) - page_size = int(seg_match.groups()[1], 10) - multiplier = seg_match.groups()[2] - if multiplier == 'K': - page_size *= 1024 - if multiplier == 'M': - page_size *= 1024 * 1024 - size = num_pages * page_size - last_addr = addr + size - 1 - result.append(named((addr, last_addr, size, num_pages, page_size), - "addr last_addr size num_pages page_size")) - addr += size + for mem_layout_index in range(1, len(mem_layout), 2): + addr = int(mem_layout[mem_layout_index], 0) + segments = mem_layout[mem_layout_index + 1].split(',') + seg_re = re.compile(r'(\d+)\*(\d+)(.)(.)') + for segment in segments: + seg_match = seg_re.match(segment) + num_pages = int(seg_match.groups()[0], 10) + page_size = int(seg_match.groups()[1], 10) + multiplier = seg_match.groups()[2] + if multiplier == 'K': + page_size *= 1024 + if multiplier == 'M': + page_size *= 1024 * 1024 + size = num_pages * page_size + last_addr = addr + size - 1 + result.append(named((addr, last_addr, size, num_pages, page_size), + "addr last_addr size num_pages page_size")) + addr += size return result -- cgit v1.2.3