Browse Source
With the recent qemu (pull/15788/headd9a0fdda9a
and0426934969
) and zephyr (05cad7b56f
) changes to how their tests are run, two things became unused: - The tinytest framework, which embedded a set of tests and their expected output within firmware, so these tests could be run stand-alone. - The `--write-exp` and `--list-tests` options to `tests/run-tests.py`, which were needed primarily to generated the expected test output for tinytest (also the associated `tests/run-tests-exp.py/.sh` scripts are now unused). This commit removes the tinytest component and all its helper code. This eliminates a maintenance burden. Signed-off-by: Damien George <damien@micropython.org>
Damien George
2 months ago
9 changed files with 0 additions and 1103 deletions
@ -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. |
|||
|
@ -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 <stdio.h> |
|||
#include <stdlib.h> |
|||
#include <string.h> |
|||
#include <assert.h> |
|||
|
|||
#ifndef NO_FORKING |
|||
|
|||
#ifdef _WIN32 |
|||
#include <windows.h> |
|||
#else |
|||
#include <sys/types.h> |
|||
#include <sys/wait.h> |
|||
#include <unistd.h> |
|||
#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 <vproc.h> |
|||
#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<c; ++i) { |
|||
if (v[i][0] == '-') { |
|||
if (!strcmp(v[i], "--RUNNING-FORKED")) { |
|||
opt_forked = 1; |
|||
} else if (!strcmp(v[i], "--no-fork")) { |
|||
opt_nofork = 1; |
|||
} else if (!strcmp(v[i], "--quiet")) { |
|||
opt_verbosity = -1; |
|||
verbosity_flag = "--quiet"; |
|||
} else if (!strcmp(v[i], "--verbose")) { |
|||
opt_verbosity = 2; |
|||
verbosity_flag = "--verbose"; |
|||
} else if (!strcmp(v[i], "--terse")) { |
|||
opt_verbosity = 0; |
|||
verbosity_flag = "--terse"; |
|||
} else if (!strcmp(v[i], "--help")) { |
|||
usage(groups, 0); |
|||
} else if (!strcmp(v[i], "--list-tests")) { |
|||
usage(groups, 1); |
|||
} else { |
|||
printf("Unknown option %s. Try --help\n",v[i]); |
|||
return -1; |
|||
} |
|||
} else { |
|||
int r = process_test_option(groups, v[i]); |
|||
if (r<0) |
|||
return -1; |
|||
n += r; |
|||
} |
|||
} |
|||
if (!n) |
|||
tinytest_set_flag_(groups, "..", 1, TT_ENABLED_); |
|||
|
|||
#ifdef _IONBF |
|||
setvbuf(stdout, NULL, _IONBF, 0); |
|||
#endif |
|||
|
|||
++in_tinytest_main; |
|||
for (i=0; groups[i].prefix; ++i) |
|||
for (j=0; groups[i].cases[j].name; ++j) |
|||
if (groups[i].cases[j].flags & TT_ENABLED_) |
|||
testcase_run_one(&groups[i], |
|||
&groups[i].cases[j]); |
|||
|
|||
--in_tinytest_main; |
|||
|
|||
if (opt_verbosity==0) |
|||
puts(""); |
|||
|
|||
if (n_bad) |
|||
printf("%d/%d TESTS FAILED. (%d skipped)\n", n_bad, |
|||
n_bad+n_ok,n_skipped); |
|||
else if (opt_verbosity >= 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; |
|||
} |
|||
|
@ -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 |
@ -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 |
@ -1,137 +0,0 @@ |
|||
/*
|
|||
* This file is part of the MicroPython project, http://micropython.org/
|
|||
* |
|||
* The MIT License (MIT) |
|||
* |
|||
* Copyright (c) 2017 Linaro Limited |
|||
* |
|||
* Permission is hereby granted, free of charge, to any person obtaining a copy |
|||
* of this software and associated documentation files (the "Software"), to deal |
|||
* in the Software without restriction, including without limitation the rights |
|||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
|||
* copies of the Software, and to permit persons to whom the Software is |
|||
* furnished to do so, subject to the following conditions: |
|||
* |
|||
* The above copyright notice and this permission notice shall be included in |
|||
* all copies or substantial portions of the Software. |
|||
* |
|||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
|||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
|||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
|||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
|||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
|||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN |
|||
* THE SOFTWARE. |
|||
*/ |
|||
#include <string.h> |
|||
|
|||
#include "py/mphal.h" |
|||
#include "py/gc.h" |
|||
#include "py/runtime.h" |
|||
#include "py/compile.h" |
|||
#include "upytesthelper.h" |
|||
|
|||
#if !MICROPY_PY_SYS_PATH |
|||
#error "upytesthelper requires MICROPY_PY_SYS_PATH=1" |
|||
#endif |
|||
|
|||
#if !MICROPY_PY_SYS_ARGV |
|||
#error "upytesthelper requires MICROPY_PY_SYS_ARGV=1" |
|||
#endif |
|||
|
|||
static const char *test_exp_output; |
|||
static int test_exp_output_len, test_rem_output_len; |
|||
static int test_failed; |
|||
static void *heap_start, *heap_end; |
|||
|
|||
void upytest_set_heap(void *start, void *end) { |
|||
heap_start = start; |
|||
heap_end = end; |
|||
} |
|||
|
|||
void upytest_set_expected_output(const char *output, unsigned len) { |
|||
test_exp_output = output; |
|||
test_exp_output_len = test_rem_output_len = len; |
|||
test_failed = false; |
|||
} |
|||
|
|||
bool upytest_is_failed(void) { |
|||
if (test_failed) { |
|||
return true; |
|||
} |
|||
#if 0 |
|||
if (test_rem_output_len != 0) { |
|||
printf("remaining len: %d\n", test_rem_output_len); |
|||
} |
|||
#endif |
|||
return test_rem_output_len != 0; |
|||
} |
|||
|
|||
// MP_PLAT_PRINT_STRN() should be redirected to this function.
|
|||
// It will pass-through any content to mp_hal_stdout_tx_strn_cooked()
|
|||
// (the default value of MP_PLAT_PRINT_STRN), but will also match
|
|||
// it to the expected output as set by upytest_set_expected_output().
|
|||
// If mismatch happens, upytest_is_failed() returns true.
|
|||
void upytest_output(const char *str, mp_uint_t len) { |
|||
if (!test_failed) { |
|||
if (len > test_rem_output_len) { |
|||
test_failed = true; |
|||
} else { |
|||
test_failed = memcmp(test_exp_output, str, len); |
|||
#if 0 |
|||
if (test_failed) { |
|||
printf("failed after char %u, within %d chars, res: %d\n", |
|||
test_exp_output_len - test_rem_output_len, (int)len, test_failed); |
|||
for (int i = 0; i < len; i++) { |
|||
if (str[i] != test_exp_output[i]) { |
|||
printf("%d %02x %02x\n", i, str[i], test_exp_output[i]); |
|||
} |
|||
} |
|||
} |
|||
#endif |
|||
test_exp_output += len; |
|||
test_rem_output_len -= len; |
|||
} |
|||
} |
|||
mp_hal_stdout_tx_strn_cooked(str, len); |
|||
} |
|||
|
|||
void upytest_execute_test(const char *src) { |
|||
// To provide clean room for each test, interpreter and heap are
|
|||
// reinitialized before running each.
|
|||
gc_init(heap_start, heap_end); |
|||
mp_init(); |
|||
mp_sys_path = mp_obj_new_list(0, NULL); |
|||
#if MICROPY_MODULE_FROZEN |
|||
mp_obj_list_append(mp_sys_path, MP_OBJ_NEW_QSTR(MP_QSTR__dot_frozen)); |
|||
#endif |
|||
mp_obj_list_init(mp_sys_argv, 0); |
|||
|
|||
nlr_buf_t nlr; |
|||
if (nlr_push(&nlr) == 0) { |
|||
mp_lexer_t *lex = mp_lexer_new_from_str_len(MP_QSTR__lt_stdin_gt_, src, strlen(src), 0); |
|||
qstr source_name = lex->source_name; |
|||
mp_parse_tree_t parse_tree = mp_parse(lex, MP_PARSE_FILE_INPUT); |
|||
mp_obj_t module_fun = mp_compile(&parse_tree, source_name, false); |
|||
mp_call_function_0(module_fun); |
|||
nlr_pop(); |
|||
} else { |
|||
mp_obj_t exc = (mp_obj_t)nlr.ret_val; |
|||
if (mp_obj_is_subclass_fast(mp_obj_get_type(exc), &mp_type_SystemExit)) { |
|||
// Assume that sys.exit() is called to skip the test.
|
|||
// TODO: That can be always true, we should set up convention to
|
|||
// use specific exit code as skip indicator.
|
|||
tinytest_set_test_skipped_(); |
|||
goto end; |
|||
} |
|||
mp_obj_print_exception(&mp_plat_print, exc); |
|||
tt_abort_msg("Uncaught exception\n"); |
|||
} |
|||
|
|||
if (upytest_is_failed()) { |
|||
tinytest_set_test_failed_(); |
|||
} |
|||
|
|||
end: |
|||
mp_deinit(); |
|||
} |
@ -1,37 +0,0 @@ |
|||
/*
|
|||
* This file is part of the MicroPython project, http://micropython.org/
|
|||
* |
|||
* The MIT License (MIT) |
|||
* |
|||
* Copyright (c) 2017 Linaro Limited |
|||
* |
|||
* Permission is hereby granted, free of charge, to any person obtaining a copy |
|||
* of this software and associated documentation files (the "Software"), to deal |
|||
* in the Software without restriction, including without limitation the rights |
|||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
|||
* copies of the Software, and to permit persons to whom the Software is |
|||
* furnished to do so, subject to the following conditions: |
|||
* |
|||
* The above copyright notice and this permission notice shall be included in |
|||
* all copies or substantial portions of the Software. |
|||
* |
|||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
|||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
|||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
|||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
|||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
|||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN |
|||
* THE SOFTWARE. |
|||
*/ |
|||
|
|||
#include <stdbool.h> |
|||
#include <stdio.h> |
|||
#include "py/mpconfig.h" |
|||
#include "lib/tinytest/tinytest.h" |
|||
#include "lib/tinytest/tinytest_macros.h" |
|||
|
|||
void upytest_set_heap(void *start, void *end); |
|||
void upytest_set_expected_output(const char *output, unsigned len); |
|||
void upytest_execute_test(const char *src); |
|||
void upytest_output(const char *str, mp_uint_t len); |
|||
bool upytest_is_failed(void); |
@ -1,8 +0,0 @@ |
|||
tinytest/.gitignore |
|||
tinytest/.travis.yml |
|||
tinytest/Makefile |
|||
tinytest/Makefile.arm-cortex-m3-qemu |
|||
tinytest/Makefile.avr |
|||
tinytest/TODO |
|||
tinytest/portable_demo.c |
|||
tinytest/tinytest_demo.c |
@ -1,146 +0,0 @@ |
|||
#!/usr/bin/env python3 |
|||
|
|||
import os, sys |
|||
from glob import glob |
|||
from re import sub |
|||
import argparse |
|||
|
|||
|
|||
def escape(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} |
|||
|
|||
|
|||
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 |
|||
|
|||
|
|||
def load_profile(profile_file, test_dirs, exclude_tests): |
|||
profile_globals = {"test_dirs": test_dirs, "exclude_tests": exclude_tests} |
|||
exec(profile_file.read(), profile_globals) |
|||
return profile_globals["test_dirs"], profile_globals["exclude_tests"] |
|||
|
|||
|
|||
test_function = ( |
|||
"void {name}(void* data) {{\n" |
|||
" static const char pystr[] = {script};\n" |
|||
" static const char exp[] = {output};\n" |
|||
' printf("\\n");\n' |
|||
" upytest_set_expected_output(exp, sizeof(exp) - 1);\n" |
|||
" upytest_execute_test(pystr);\n" |
|||
' printf("result: ");\n' |
|||
"}}" |
|||
) |
|||
|
|||
testcase_struct = "struct testcase_t {name}_tests[] = {{\n{body}\n END_OF_TESTCASES\n}};" |
|||
testcase_member = ' {{ "{desc}", {func}, TT_ENABLED_, 0, 0 }},' |
|||
|
|||
testgroup_struct = "struct testgroup_t groups[] = {{\n{body}\n END_OF_GROUPS\n}};" |
|||
testgroup_member = ' {{ "{name}", {name}_tests }},' |
|||
|
|||
## XXX: may be we could have `--without <groups>` argument... |
|||
|
|||
test_dirs = set( |
|||
( |
|||
"basics", |
|||
"extmod", |
|||
"float", |
|||
"micropython", |
|||
"misc", |
|||
) |
|||
) |
|||
|
|||
exclude_tests = set( |
|||
( |
|||
# pattern matching in .exp |
|||
"basics/bytes_compare3.py", |
|||
"extmod/ticks_diff.py", |
|||
"extmod/time_ms_us.py", |
|||
# unicode char issue |
|||
"extmod/json_loads.py", |
|||
# doesn't output to python stdout |
|||
"extmod/re_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", |
|||
"float/float_format_ints_doubleprec.py", |
|||
"float/float_parse_doubleprec.py", |
|||
# different filename in output |
|||
"micropython/emg_exc.py", |
|||
"micropython/heapalloc_traceback.py", |
|||
# don't have emergency exception buffer |
|||
"micropython/heapalloc_exc_compressed_emg_exc.py", |
|||
# pattern matching in .exp |
|||
"micropython/meminfo.py", |
|||
# needs sys stdfiles |
|||
"misc/print_exception.py", |
|||
# settrace .exp files are too large |
|||
"misc/sys_settrace_loop.py", |
|||
"misc/sys_settrace_generator.py", |
|||
"misc/sys_settrace_features.py", |
|||
# don't have f-string |
|||
"basics/string_fstring.py", |
|||
"basics/string_fstring_debug.py", |
|||
) |
|||
) |
|||
|
|||
output = [] |
|||
tests = [] |
|||
|
|||
argparser = argparse.ArgumentParser( |
|||
description="Convert native MicroPython tests to tinytest/upytesthelper C code" |
|||
) |
|||
argparser.add_argument("--stdin", action="store_true", help="read list of tests from stdin") |
|||
argparser.add_argument("--exclude", action="append", help="exclude test by name") |
|||
argparser.add_argument( |
|||
"--profile", |
|||
type=argparse.FileType("rt", encoding="utf-8"), |
|||
help="optional profile file providing test directories and exclusion list", |
|||
) |
|||
args = argparser.parse_args() |
|||
|
|||
if not args.stdin: |
|||
if args.profile: |
|||
test_dirs, exclude_tests = load_profile(args.profile, test_dirs, exclude_tests) |
|||
if args.exclude: |
|||
exclude_tests = exclude_tests.union(args.exclude) |
|||
for group in test_dirs: |
|||
tests += [test for test in glob("{}/*.py".format(group)) if test not in exclude_tests] |
|||
else: |
|||
for l in sys.stdin: |
|||
tests.append(l.rstrip()) |
|||
|
|||
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 [""]] |
|||
|
|||
output.append(testgroup_struct.format(body="\n".join(testgroup_members))) |
|||
|
|||
## XXX: may be we could have `--output <filename>` argument... |
|||
# Don't depend on what system locale is set, use utf8 encoding. |
|||
sys.stdout.buffer.write("\n\n".join(output).encode("utf8")) |
Loading…
Reference in new issue