You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mynewt.apache.org by st...@apache.org on 2016/09/29 01:34:11 UTC
[04/49] incubator-mynewt-core git commit: directory re-org
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/6a7432f4/sys/stats/pkg.yml
----------------------------------------------------------------------
diff --git a/sys/stats/pkg.yml b/sys/stats/pkg.yml
index bde92c8..67c95fd 100644
--- a/sys/stats/pkg.yml
+++ b/sys/stats/pkg.yml
@@ -25,10 +25,10 @@ pkg.keywords:
- statistics
pkg.deps:
- - libs/os
+ - kernel/os
- libs/util
pkg.deps.STATS_CLI:
- - libs/shell
+ - sys/shell
pkg.req_apis.STATS_NEWTMGR:
- newtmgr
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/6a7432f4/sys/sysinit/pkg.yml
----------------------------------------------------------------------
diff --git a/sys/sysinit/pkg.yml b/sys/sysinit/pkg.yml
index e728ccf..e6f8225 100644
--- a/sys/sysinit/pkg.yml
+++ b/sys/sysinit/pkg.yml
@@ -25,7 +25,7 @@ pkg.keywords:
- init
pkg.deps:
- - libs/os
+ - kernel/os
- libs/util
pkg.syscfg_defs:
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/6a7432f4/test/crash_test/include/crash_test/crash_test.h
----------------------------------------------------------------------
diff --git a/test/crash_test/include/crash_test/crash_test.h b/test/crash_test/include/crash_test/crash_test.h
new file mode 100644
index 0000000..73135fd
--- /dev/null
+++ b/test/crash_test/include/crash_test/crash_test.h
@@ -0,0 +1,27 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+#ifndef __CRASH_TEST_H__
+#define __CRASH_TEST_H__
+
+/*
+ * Adds the crash commands to your shell/newtmgr.
+ */
+int crash_test_init(void);
+
+#endif /* __CRASH_TEST_H__ */
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/6a7432f4/test/crash_test/pkg.yml
----------------------------------------------------------------------
diff --git a/test/crash_test/pkg.yml b/test/crash_test/pkg.yml
new file mode 100644
index 0000000..75afa8c
--- /dev/null
+++ b/test/crash_test/pkg.yml
@@ -0,0 +1,42 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+pkg.name: test/crash_test
+pkg.description: Generate different kinds of faults
+pkg.homepage: "http://mynewt.apache.org/"
+pkg.keywords:
+
+pkg.deps.CRASH_TEST_CLI:
+ - sys/shell
+pkg.req_apis.CRASH_TEST_CLI:
+ - console
+pkg.req_apis.CRASH_TEST_NEWTMGR:
+ - newtmgr
+
+pkg.deps.CRASH_TEST_NEWTMGR:
+ - libs/newtmgr
+ - encoding/json
+
+pkg.syscfg_defs:
+ CRASH_TEST_CLI:
+ description: 'TBD'
+ value: 1
+ CRASH_TEST_NEWTMGR:
+ description: 'TBD'
+ value: 1
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/6a7432f4/test/crash_test/src/crash_cli.c
----------------------------------------------------------------------
diff --git a/test/crash_test/src/crash_cli.c b/test/crash_test/src/crash_cli.c
new file mode 100644
index 0000000..4d49bef
--- /dev/null
+++ b/test/crash_test/src/crash_cli.c
@@ -0,0 +1,49 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#include "syscfg/syscfg.h"
+
+#if MYNEWT_VAL(CRASH_TEST_CLI)
+#include <inttypes.h>
+#include <os/os.h>
+#include <console/console.h>
+#include <shell/shell.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "crash_test/crash_test.h"
+#include "crash_test_priv.h"
+
+static int crash_cli_cmd(int argc, char **argv);
+struct shell_cmd crash_cmd_struct = {
+ .sc_cmd = "crash",
+ .sc_cmd_func = crash_cli_cmd
+};
+
+static int
+crash_cli_cmd(int argc, char **argv)
+{
+ if (argc >= 2 && crash_device(argv[1]) == 0) {
+ return 0;
+ }
+ console_printf("Usage crash [div0|jump0|ref0|assert]\n");
+ return 0;
+}
+
+#endif /* MYNEWT_VAL(CRASH_TEST_CLI) */
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/6a7432f4/test/crash_test/src/crash_nmgr.c
----------------------------------------------------------------------
diff --git a/test/crash_test/src/crash_nmgr.c b/test/crash_test/src/crash_nmgr.c
new file mode 100644
index 0000000..d9bf4b0
--- /dev/null
+++ b/test/crash_test/src/crash_nmgr.c
@@ -0,0 +1,75 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#include "syscfg/syscfg.h"
+
+#if MYNEWT_VAL(CRASH_TEST_NEWTMGR)
+
+#include <string.h>
+
+#include "newtmgr/newtmgr.h"
+#include "json/json.h"
+#include "console/console.h"
+
+#include "crash_test/crash_test.h"
+#include "crash_test_priv.h"
+
+static int crash_test_nmgr_write(struct nmgr_jbuf *);
+
+static const struct nmgr_handler crash_test_nmgr_handler[] = {
+ [0] = { crash_test_nmgr_write, crash_test_nmgr_write }
+};
+
+struct nmgr_group crash_test_nmgr_group = {
+ .ng_handlers = (struct nmgr_handler *)crash_test_nmgr_handler,
+ .ng_handlers_count = 1,
+ .ng_group_id = NMGR_GROUP_ID_CRASH
+};
+
+static int
+crash_test_nmgr_write(struct nmgr_jbuf *njb)
+{
+ char tmp_str[64];
+ const struct json_attr_t attr[2] = {
+ [0] = {
+ .attribute = "t",
+ .type = t_string,
+ .addr.string = tmp_str,
+ .len = sizeof(tmp_str)
+ },
+ [1] = {
+ .attribute = NULL
+ }
+ };
+ int rc;
+
+ rc = json_read_object(&njb->njb_buf, attr);
+ if (rc) {
+ rc = NMGR_ERR_EINVAL;
+ } else {
+ rc = crash_device(tmp_str);
+ if (rc) {
+ rc = NMGR_ERR_EINVAL;
+ }
+ }
+ nmgr_jbuf_setoerr(njb, rc);
+ return 0;
+}
+
+#endif /* MYNEWT_VAL(CRASH_TEST_NEWTMGR) */
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/6a7432f4/test/crash_test/src/crash_test.c
----------------------------------------------------------------------
diff --git a/test/crash_test/src/crash_test.c b/test/crash_test/src/crash_test.c
new file mode 100644
index 0000000..a6e2ea2
--- /dev/null
+++ b/test/crash_test/src/crash_test.c
@@ -0,0 +1,72 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+#include <inttypes.h>
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+
+#include "syscfg/syscfg.h"
+#include "os/os.h"
+#include "console/console.h"
+
+#include "crash_test/crash_test.h"
+#include "crash_test_priv.h"
+
+#if MYNEWT_VAL(CRASH_TEST_CLI)
+#include "shell/shell.h"
+#endif
+#if MYNEWT_VAL(CRASH_TEST_NEWTMGR)
+#include "newtmgr/newtmgr.h"
+#endif
+
+int
+crash_device(char *how)
+{
+ volatile int val1, val2, val3;
+
+ if (!strcmp(how, "div0")) {
+
+ val1 = 42;
+ val2 = 0;
+
+ val3 = val1 / val2;
+ console_printf("42/0 = %d\n", val3);
+ } else if (!strcmp(how, "jump0")) {
+ ((void (*)(void))0)();
+ } else if (!strcmp(how, "ref0")) {
+ val1 = *(int *)0;
+ } else if (!strcmp(how, "assert")) {
+ assert(0);
+ } else {
+ return -1;
+ }
+ return 0;
+}
+
+int
+crash_test_init(void)
+{
+#if MYNEWT_VAL(CRASH_TEST_CLI)
+ shell_cmd_register(&crash_cmd_struct);
+#endif
+#if MYNEWT_VAL(CRASH_TEST_NEWTMGR)
+ nmgr_group_register(&crash_test_nmgr_group);
+#endif
+ return 0;
+}
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/6a7432f4/test/crash_test/src/crash_test_priv.h
----------------------------------------------------------------------
diff --git a/test/crash_test/src/crash_test_priv.h b/test/crash_test/src/crash_test_priv.h
new file mode 100644
index 0000000..09dc5a3
--- /dev/null
+++ b/test/crash_test/src/crash_test_priv.h
@@ -0,0 +1,31 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+#ifndef __CRASH_TEST_PRIV_H__
+#define __CRASH_TEST_PRIV_H__
+
+#if MYNEWT_VAL(CRASH_TEST_CLI)
+extern struct shell_cmd crash_cmd_struct;
+#endif
+#if MYNEWT_VAL(CRASH_TEST_NEWTMGR)
+extern struct nmgr_group crash_test_nmgr_group;
+#endif
+
+int crash_device(char *how);
+
+#endif /* __CRASH_TEST_PRIV_H__ */
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/6a7432f4/test/flash_test/include/flash_test/flash_test.h
----------------------------------------------------------------------
diff --git a/test/flash_test/include/flash_test/flash_test.h b/test/flash_test/include/flash_test/flash_test.h
new file mode 100644
index 0000000..f38f48c
--- /dev/null
+++ b/test/flash_test/include/flash_test/flash_test.h
@@ -0,0 +1,27 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+#ifndef __FLASH_TEST_H__
+#define __FLASH_TEST_H__
+
+/**
+ * adds the flash test commands to your shell */
+int
+flash_test_init(void);
+
+#endif /* __FLASH_TEST_H__ */
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/6a7432f4/test/flash_test/pkg.yml
----------------------------------------------------------------------
diff --git a/test/flash_test/pkg.yml b/test/flash_test/pkg.yml
new file mode 100644
index 0000000..365705c
--- /dev/null
+++ b/test/flash_test/pkg.yml
@@ -0,0 +1,30 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+pkg.name: test/flash_test
+pkg.description: flash HAL tester
+pkg.homepage: "http://mynewt.apache.org/"
+pkg.keywords:
+
+pkg.deps:
+ - kernel/os
+ - libs/util
+ - hw/hal
+pkg.req_apis:
+ - console
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/6a7432f4/test/flash_test/src/flash_test/flash_test.c
----------------------------------------------------------------------
diff --git a/test/flash_test/src/flash_test/flash_test.c b/test/flash_test/src/flash_test/flash_test.c
new file mode 100644
index 0000000..980cbba
--- /dev/null
+++ b/test/flash_test/src/flash_test/flash_test.c
@@ -0,0 +1,155 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+#include <inttypes.h>
+#include <os/os.h>
+#include <console/console.h>
+#include <flash_test/flash_test.h>
+#include <hal/hal_bsp.h>
+#include <hal/hal_flash.h>
+#include <hal/hal_flash_int.h>
+#include <shell/shell.h>
+#include <stdio.h>
+#include <string.h>
+
+static int flash_cli_cmd(int argc, char **argv);
+static struct shell_cmd flash_cmd_struct = {
+ .sc_cmd = "flash",
+ .sc_cmd_func = flash_cli_cmd
+};
+
+static int
+flash_cli_cmd(int argc, char **argv)
+{
+ const struct hal_flash *hf;
+ uint32_t off = 0;
+ uint32_t sz = 1;
+ int sec_cnt;
+ int i;
+ int soff;
+ char *eptr;
+ char tmp_buf[8];
+ char pr_str[80];
+
+ hf = bsp_flash_dev(0);
+ if (!hf) {
+ console_printf("No flash device present\n");
+ return 0;
+ }
+ if (argc == 1) {
+ /*
+ * print status
+ */
+ console_printf("Flash at 0x%lx size 0x%lx with %d sectors,"
+ "alignment req %d bytes\n",
+ (long unsigned int) hf->hf_base_addr,
+ (long unsigned int) hf->hf_size,
+ hf->hf_sector_cnt,
+ hf->hf_align);
+ sec_cnt = hf->hf_sector_cnt;
+ if (sec_cnt > 32) {
+ sec_cnt = 32;
+ }
+ for (i = 0; i < sec_cnt; i++) {
+ console_printf(" %d: %lx\n", i,
+ (long unsigned int) hal_flash_sector_size(hf, i));
+ }
+ if (sec_cnt != hf->hf_sector_cnt) {
+ console_printf("... %d: %lx\n", hf->hf_sector_cnt - 1,
+ (long unsigned int) hal_flash_sector_size(hf, hf->hf_sector_cnt - 1));
+ }
+ return 0;
+ }
+ if (argc > 2) {
+ off = strtoul(argv[2], &eptr, 0);
+ if (*eptr != '\0') {
+ console_printf("Invalid offset %s\n", argv[2]);
+ goto err;
+ }
+ }
+ if (argc > 3) {
+ sz = strtoul(argv[3], &eptr, 0);
+ if (*eptr != '\0') {
+ console_printf("Invalid size %s\n", argv[3]);
+ goto err;
+ }
+ }
+ if (!strcmp(argv[1], "erase")) {
+ console_printf("Erase 0x%lx + %lx\n",
+ (long unsigned int) off, (long unsigned int) sz);
+
+ if (hal_flash_erase(0, off, sz)) {
+ console_printf("Flash erase failed\n");
+ }
+ console_printf("Done!\n");
+ } else if (!strcmp(argv[1], "read")) {
+ console_printf("Read 0x%lx + %lx\n",
+ (long unsigned int) off, (long unsigned int) sz);
+ sz += off;
+ while (off < sz) {
+ sec_cnt = min(sizeof(tmp_buf), sz - off);
+ if (hal_flash_read(0, off, tmp_buf, sec_cnt)) {
+ console_printf("flash read failure at %lx\n",
+ (long unsigned int) off);
+ break;
+ }
+ for (i = 0, soff = 0; i < sec_cnt; i++) {
+ soff += snprintf(pr_str + soff, sizeof(pr_str) - soff,
+ "0x%02x ", tmp_buf[i] & 0xff);
+ }
+ console_printf(" 0x%lx: %s\n",
+ (long unsigned int) off, pr_str);
+ off += sec_cnt;
+ }
+ } else if (!strcmp(argv[1], "write")) {
+ console_printf("Write 0x%lx + %lx\n",
+ (long unsigned int) off, (long unsigned int) sz);
+
+ sz += off;
+ for (i = 0; i < sizeof(tmp_buf); i++) {
+ tmp_buf[i] = i + 1;
+ }
+
+ while (off < sz) {
+ sec_cnt = min(sizeof(tmp_buf), sz - off);
+ if (hal_flash_write(0, off, tmp_buf, sec_cnt)) {
+ console_printf("flash write failure at %lx\n",
+ (long unsigned int) off);
+ }
+ off += sec_cnt;
+ }
+ console_printf("Done!\n");
+ } else if ( !strcmp(argv[1], "?") || !strcmp(argv[1], "help"))
+ {
+ console_printf("Commands Available\n");
+ console_printf("flash -- dumps sector map \n");
+ console_printf("flash read <offset> <size> -- reads bytes from flash \n");
+ console_printf("flash write <offset> <size> -- writes incrementing data pattern 0-8 to flash \n");
+ console_printf("flash erase <offset> <size> -- erases flash \n");
+ }
+ return 0;
+err:
+ return -1;
+}
+
+
+int
+flash_test_init(void) {
+ shell_cmd_register(&flash_cmd_struct);
+ return 0;
+}
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/6a7432f4/test/testreport/include/testreport/testreport.h
----------------------------------------------------------------------
diff --git a/test/testreport/include/testreport/testreport.h b/test/testreport/include/testreport/testreport.h
new file mode 100644
index 0000000..7a0d3e4
--- /dev/null
+++ b/test/testreport/include/testreport/testreport.h
@@ -0,0 +1,34 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#ifndef H_TESTREPORT_
+#define H_TESTREPORT_
+
+struct nffs_area_desc;
+
+struct tr_config {
+ const char *tc_base_path;
+ const struct nffs_area_desc *tc_area_descs;
+};
+
+extern struct tr_config tr_config;
+
+int tr_init(void);
+
+#endif
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/6a7432f4/test/testreport/pkg.yml
----------------------------------------------------------------------
diff --git a/test/testreport/pkg.yml b/test/testreport/pkg.yml
new file mode 100644
index 0000000..42e8482
--- /dev/null
+++ b/test/testreport/pkg.yml
@@ -0,0 +1,30 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+pkg.name: test/testreport
+pkg.description: Library for recording unit test results to flash.
+pkg.author: "Apache Mynewt <de...@mynewt.incubator.apache.org>"
+pkg.homepage: "http://mynewt.apache.org/"
+pkg.keywords:
+ - unit
+ - test
+
+pkg.deps:
+ - fs/nffs
+ - test/testutil
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/6a7432f4/test/testreport/src/arch/cortex_m4/io.c
----------------------------------------------------------------------
diff --git a/test/testreport/src/arch/cortex_m4/io.c b/test/testreport/src/arch/cortex_m4/io.c
new file mode 100644
index 0000000..fd27585
--- /dev/null
+++ b/test/testreport/src/arch/cortex_m4/io.c
@@ -0,0 +1,91 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#include <stddef.h>
+#include "nffs/nffs.h"
+#include "nffs/nffsutil.h"
+#include "testreport_priv.h"
+
+int
+tr_io_write(const char *path, const void *contents, size_t len)
+{
+ int rc;
+
+ rc = nffsutil_write_file(path, contents, len);
+ if (rc != 0) {
+ return -1;
+ }
+
+ return 0;
+}
+
+int
+tr_io_mkdir(const char *path)
+{
+ int rc;
+
+ rc = nffs_mkdir(path);
+ if (rc != 0 && rc != NFFS_EEXIST) {
+ return -1;
+ }
+
+ return 0;
+}
+
+int
+tr_io_rmdir(const char *path)
+{
+ int rc;
+
+ rc = nffs_unlink(path);
+ if (rc != 0 && rc != NFFS_ENOENT) {
+ return -1;
+ }
+
+ return 0;
+}
+
+int
+tr_io_read(const char *path, void *out_data, size_t len, size_t *out_len)
+{
+ uint32_t u32;
+ int rc;
+
+ rc = nffsutil_read_file(path, 0, len, out_data, &u32);
+ if (rc != 0) {
+ return -1;
+ }
+
+ *out_len = u32;
+
+ return 0;
+}
+
+int
+tr_io_delete(const char *path)
+{
+ int rc;
+
+ rc = nffs_unlink(path);
+ if (rc != 0 && rc != NFFS_ENOENT) {
+ return -1;
+ }
+
+ return 0;
+}
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/6a7432f4/test/testreport/src/arch/sim/io.c
----------------------------------------------------------------------
diff --git a/test/testreport/src/arch/sim/io.c b/test/testreport/src/arch/sim/io.c
new file mode 100644
index 0000000..a5233e5
--- /dev/null
+++ b/test/testreport/src/arch/sim/io.c
@@ -0,0 +1,140 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <unistd.h>
+#include <sys/stat.h>
+#include "testreport_priv.h"
+
+static char tr_io_buf[1024];
+
+int
+tr_io_write(const char *path, const void *contents, size_t len)
+{
+ FILE *fp;
+ int rc;
+
+ fp = NULL;
+
+ fp = fopen(path, "w+");
+ if (fp == NULL) {
+ rc = -1;
+ goto done;
+ }
+
+ if (contents != NULL && len > 0) {
+ rc = fwrite(contents, len, 1, fp);
+ if (rc != 1) {
+ rc = -1;
+ goto done;
+ }
+ }
+
+ rc = 0;
+
+done:
+ if (fp != NULL) {
+ fclose(fp);
+ }
+
+ return rc;
+}
+
+int
+tr_io_mkdir(const char *path)
+{
+ int rc;
+
+ rc = mkdir(path, 0755);
+ if (rc == -1 && errno != EEXIST) {
+ return -1;
+ }
+
+ return 0;
+}
+
+/* XXX security risk, not portable, blah blah blah */
+int
+tr_io_rmdir(const char *path)
+{
+ int rc;
+
+ rc = snprintf(tr_io_buf, sizeof tr_io_buf,
+ "rm -rf '%s'", path);
+ if (rc >= sizeof tr_io_buf) {
+ return -1;
+ }
+
+ rc = system(tr_io_buf);
+ if (rc != 0) {
+ return rc;
+ }
+
+ return 0;
+}
+
+int
+tr_io_read(const char *path, void *out_data, size_t len, size_t *out_len)
+{
+ FILE *fp;
+ uint8_t *dst;
+ int rc;
+ int i;
+
+ fp = NULL;
+
+ fp = fopen(path, "rb");
+ if (fp == NULL) {
+ rc = -1;
+ goto done;
+ }
+
+ dst = out_data;
+ for (i = 0; i < len; i++) {
+ rc = getc(fp);
+ if (rc == EOF) {
+ rc = -1;
+ goto done;
+ }
+
+ dst[i] = rc;
+ }
+
+ *out_len = i;
+ rc = 0;
+
+done:
+ if (fp != NULL) {
+ fclose(fp);
+ }
+
+ return rc;
+}
+
+int
+tr_io_delete(const char *path)
+{
+ int rc;
+
+ rc = remove(path);
+
+ return rc;
+}
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/6a7432f4/test/testreport/src/results.c
----------------------------------------------------------------------
diff --git a/test/testreport/src/results.c b/test/testreport/src/results.c
new file mode 100644
index 0000000..77b26c2
--- /dev/null
+++ b/test/testreport/src/results.c
@@ -0,0 +1,190 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#include <stdio.h>
+#include "testutil/testutil.h"
+#include "testreport/testreport.h"
+#include "testreport_priv.h"
+
+#define TU_REPORT_META_DIR ".meta"
+#define TU_REPORT_STATUS_FILENAME "status"
+
+static char tr_report_buf[1024];
+
+int
+tr_report_rmdir_results(void)
+{
+ if (tr_config.tc_base_path == NULL) {
+ return 0;
+ }
+
+ return tr_io_rmdir(tr_config.tc_base_path);
+}
+
+int
+tr_report_mkdir_results(void)
+{
+ int rc;
+
+ if (tr_config.tc_base_path == NULL) {
+ return 0;
+ }
+
+ rc = snprintf(tr_report_buf, sizeof tr_report_buf,
+ "%s", tr_config.tc_base_path);
+ if (rc >= sizeof tr_report_buf) {
+ return -1;
+ }
+ return tr_io_mkdir(tr_report_buf);
+}
+
+int
+tr_report_mkdir_meta(void)
+{
+ int rc;
+
+ if (tr_config.tc_base_path == NULL) {
+ return 0;
+ }
+
+ rc = snprintf(tr_report_buf, sizeof tr_report_buf,
+ "%s/" TU_REPORT_META_DIR, tr_config.tc_base_path);
+ if (rc >= sizeof tr_report_buf) {
+ return -1;
+ }
+ return tr_io_mkdir(tr_report_buf);
+}
+
+int
+tr_report_mkdir_suite(void)
+{
+ int rc;
+
+ if (tr_config.tc_base_path == NULL) {
+ return 0;
+ }
+
+ rc = snprintf(tr_report_buf, sizeof tr_report_buf,
+ "%s/%s", tr_config.tc_base_path,
+ tu_suite_name);
+ if (rc >= sizeof tr_report_buf) {
+ return -1;
+ }
+
+ rc = tr_io_mkdir(tr_report_buf);
+ if (rc != 0) {
+ return rc;
+ }
+
+ return 0;
+}
+
+int
+tr_report_mkdir_case(void)
+{
+ int rc;
+
+ if (tr_config.tc_base_path == NULL) {
+ return 0;
+ }
+
+ rc = snprintf(tr_report_buf, sizeof tr_report_buf,
+ "%s/%s/%s", tr_config.tc_base_path,
+ tu_suite_name, tu_case_name);
+ if (rc >= sizeof tr_report_buf) {
+ return -1;
+ }
+
+ rc = tr_io_mkdir(tr_report_buf);
+ if (rc != 0) {
+ return rc;
+ }
+
+ return 0;
+}
+
+int
+tr_report_write_file(const char *filename, const uint8_t *data,
+ size_t data_len)
+{
+ int rc;
+
+ if (tr_config.tc_base_path == NULL) {
+ return 0;
+ }
+
+ rc = snprintf(tr_report_buf, sizeof tr_report_buf,
+ "%s/%s/%s/%s", tr_config.tc_base_path,
+ tu_suite_name, tu_case_name, filename);
+ if (rc >= sizeof tr_report_buf) {
+ return -1;
+ }
+
+ rc = tr_io_write(tr_report_buf, data, data_len);
+ if (rc != 0) {
+ return rc;
+ }
+
+ return 0;
+}
+
+int
+tr_report_read_status(void)
+{
+ size_t bytes_read;
+ int rc;
+
+ rc = snprintf(tr_report_buf, sizeof tr_report_buf,
+ "%s/%s/%s", tr_config.tc_base_path,
+ TU_REPORT_META_DIR, TU_REPORT_STATUS_FILENAME);
+ if (rc >= sizeof tr_report_buf) {
+ return -1;
+ }
+
+ rc = tr_io_read(tr_report_buf, &tu_first_idx, sizeof tu_first_idx,
+ &bytes_read);
+ if (rc != 0 || bytes_read != sizeof tu_first_idx) {
+ return -1;
+ }
+
+ tr_io_delete(tr_report_buf);
+
+ return 0;
+}
+
+int
+tr_report_write_status(void)
+{
+ int rc;
+
+ rc = snprintf(tr_report_buf, sizeof tr_report_buf,
+ "%s/%s/%s", tr_config.tc_base_path,
+ TU_REPORT_META_DIR, TU_REPORT_STATUS_FILENAME);
+ if (rc >= sizeof tr_report_buf) {
+ return -1;
+ }
+
+ rc = tr_io_write(tr_report_buf, &tu_first_idx, sizeof tu_first_idx);
+ if (rc != 0) {
+ return -1;
+ }
+
+ return 0;
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/6a7432f4/test/testreport/src/testreport.c
----------------------------------------------------------------------
diff --git a/test/testreport/src/testreport.c b/test/testreport/src/testreport.c
new file mode 100644
index 0000000..c29221b
--- /dev/null
+++ b/test/testreport/src/testreport.c
@@ -0,0 +1,131 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#include <assert.h>
+#include <stdio.h>
+#include "hal/hal_flash.h"
+#include "fs/fs.h"
+#include "nffs/nffs.h"
+#include "testutil/testutil.h"
+#include "testreport/testreport.h"
+#include "testreport_priv.h"
+
+struct tr_config tr_config;
+
+static int tr_case_fail_idx;
+
+static void
+tr_case_init(void *unused)
+{
+ int rc;
+
+ rc = tr_results_mkdir_case();
+ assert(rc == 0);
+}
+
+static void
+tr_case_fail(char *msg, int msg_len, void *unused)
+{
+ char filename[14];
+ int rc;
+
+ rc = snprintf(filename, sizeof filename, "fail-%04d.txt",
+ tr_case_fail_idx);
+ assert(rc < sizeof filename);
+
+ rc = tr_results_write_file(filename, (uint8_t *)msg, msg_len);
+ assert(rc == 0);
+
+ tr_case_fail_idx++;
+}
+
+static void
+tr_case_pass(char *msg, int msg_len, void *unused)
+{
+ int rc;
+
+ rc = tr_results_write_file("pass.txt", (uint8_t *)msg, msg_len);
+ assert(rc == 0);
+}
+
+static void
+tr_suite_init(void *unused)
+{
+ int rc;
+
+ rc = tr_results_mkdir_suite();
+ assert(rc == 0);
+}
+
+static void
+tr_restart(void *unused)
+{
+ tr_results_write_status();
+}
+
+int
+tr_init(void)
+{
+ int rc;
+
+ if (tr_config.tc_base_path != NULL) {
+ if (tr_config.tc_area_descs != NULL) {
+ rc = hal_flash_init();
+ if (rc != 0) {
+ return -1;
+ }
+
+ rc = nffs_init();
+ if (rc != 0) {
+ return -1;
+ }
+
+ rc = nffs_detect(tr_config.tc_area_descs);
+ if (rc == FS_ECORRUPT) {
+ rc = nffs_format(tr_config.tc_area_descs);
+ }
+ if (rc != 0) {
+ return -1;
+ }
+ }
+
+ rc = tr_results_read_status();
+ if (rc != 0) {
+ tr_results_rmdir_results();
+ }
+
+ rc = tr_results_mkdir_results();
+ if (rc != 0) {
+ return -1;
+ }
+
+ rc = tr_results_mkdir_meta();
+ if (rc != 0) {
+ return -1;
+ }
+ }
+
+ tu_config.tc_case_init_cb = tr_case_init;
+ tu_config.tc_case_fail_cb = tr_case_fail;
+ tu_config.tc_case_pass_cb = tr_case_pass;
+ tu_config.tc_suite_init_cb = tr_suite_init;
+ tu_config.tc_restart_cb = tr_restart;
+
+ return 0;
+}
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/6a7432f4/test/testreport/src/testreport_priv.h
----------------------------------------------------------------------
diff --git a/test/testreport/src/testreport_priv.h b/test/testreport/src/testreport_priv.h
new file mode 100644
index 0000000..88576b6
--- /dev/null
+++ b/test/testreport/src/testreport_priv.h
@@ -0,0 +1,48 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#ifndef H_TESTREPORT_PRIV_
+#define H_TESTREPORT_PRIV_
+
+#include <stddef.h>
+#include <inttypes.h>
+
+int tr_results_mkdir_results(void);
+int tr_results_rmdir_results(void);
+
+int tr_results_mkdir_meta(void);
+
+int tr_results_mkdir_suite(void);
+int tr_results_mkdir_case(void);
+
+int tr_results_write_file(const char *filename, const uint8_t *data,
+ size_t data_len);
+
+int tr_results_read_status(void);
+int tr_results_write_status(void);
+
+int tr_io_read(const char *path, void *out_data, size_t len, size_t *out_len);
+int tr_io_write(const char *path, const void *contents, size_t len);
+
+int tr_io_delete(const char *path);
+
+int tr_io_mkdir(const char *path);
+int tr_io_rmdir(const char *path);
+
+#endif
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/6a7432f4/test/testutil/design.txt
----------------------------------------------------------------------
diff --git a/test/testutil/design.txt b/test/testutil/design.txt
new file mode 100644
index 0000000..a1dfd9b
--- /dev/null
+++ b/test/testutil/design.txt
@@ -0,0 +1,476 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+****** TEST AUTOMATION
+
+*** HISTORY
+Rev. Date Changes
+2 2015/09/07 Addition of tu_restart(); clarification of exported
+ preprocessor symbols.
+1 2015/08/28
+
+
+*** SUMMARY
+
+Automated testing can be done in either of two ways:
+ 1. Testing a set of packages on embedded hardware or a simulated
+ environment.
+ 2. Testing an individual package in a simulated environment.
+
+
+***** PACKAGE SET TESTING
+
+Automated testing of package sets consists of two components:
+ 1. "PC software" which administers tests and manages results.
+ 2. Test images which run on the units under test (UUTs).
+
+
+**** PC SOFTWARE
+
+The PC software will need to perform the following tasks:
+ 1. Connect to UUT (e.g., via JTAG and OpenOCD) (if embedded).
+ 2. Upload test image (if embedded).
+ 3. Run test image.
+ 4. Read test results from UUT.
+ 5. Generate test report.
+
+If any of these tasks fail, a fatal error would need to be logged to the test
+report.
+
+The details of the PC software are TBD, and are not discussed further here.
+
+
+**** TEST IMAGES
+
+Test images are build using the stack tool. The user will need to create a
+separate stack tool target for each platform under test. In addition, there
+will be a single stack tool project which contains code to call the appropriate
+test code. Each test image typically consists of the following:
+ 1. The test cases from all relevant packages.
+ 2. Some "glue code" from a special test project.
+
+
+*** PACKAGE TEST CASES
+
+A package may optionally contain a set of test cases. Test cases are not
+normally compiled and linked when a package is built; they are only included
+when the "test" identity is specified. All of a
+package's test code goes in its 'src/test' directory. For example, the ffs
+package's test code is located in the following directory:
+
+ libs/ffs/src/test/
+
+This directory contains the source and header files that implement the ffs test
+code.
+
+The test code has access to all the header files in the following directories:
+ * src
+ * src/arch/<target-arch>
+ * include
+ * src/test
+ * src/test/arch/<target-arch>
+ * include directories of all package dependencies
+
+Package test code typically depends on the testutil package, described later in
+this document. If a package's test code uses testutil, then the package itself
+needs to have testutil in its dependency list.
+
+Some test cases or test initialization code may be platform-specific. In such
+cases, the platform-specific function definitions are placed in arch
+subdirectories within the package test directory.
+
+When test code is built (i.e., when the "test" identity is specified), the
+stack tool defines the "TEST" macro. This macro is defined during complilation
+of all C source files in all projects and packages..
+
+
+***** TESTUTIL
+
+The testutil package is a test framework that provides facilities for
+specifying test cases and recording test results.
+
+
+*** TEST STRUCTURE
+
+Tests are structures according to the following hierarchy:
+
+ [test]
+ / \
+ [suite] [suite]
+ / \ / \
+ [case] [case] [case] [case]
+
+
+I.e., a test consists of test suites, and a test suite consits of test cases.
+
+The test code uses testutil to define test suites and test cases.
+
+
+*** TESTUTIL EXAMPLE
+
+The following example demonstrates how to create a simple test suite.
+
+ TEST_CASE(test_addition)
+ {
+ int sum;
+
+ sum = 5 + 10;
+ TEST_ASSERT(sum == 15, "actual value: %d", sum);
+ }
+
+ TEST_CASE(test_times_0)
+ {
+ TEST_ASSERT(3 * 0 == 0);
+ TEST_ASSERT(4 * 0 == 0);
+ TEST_ASSERT(712 * 0 == 0);
+ }
+
+ TEST_SUITE(test_suite_arithmetic)
+ {
+ test_addition();
+ test_times_0();
+ }
+
+The test suite would then be executed via a call to test_suite_arithmetic().
+
+
+*** TEST RESULTS
+
+The testutil package optionally writes test results to a file system residing
+on the UUT. The contents of the file system can then be retrieved from the UUT
+by the PC software. When run in an embedded environment, the results are
+written to an ffs file system. When run in a simulated environment, the
+results are written to the native file system.
+
+Results directory structure:
+ /
+ \u2514\u2500\u2500 test-results
+ \u251c\u2500\u2500 <test-suite-1>
+ | \u251c\u2500\u2500 <test-case-1>
+ | \u2502�� \u251c\u2500\u2500 <result-1>.txt
+ | \u2502�� \u251c\u2500\u2500 [<result-2>.txt]
+ | \u2502�� \u251c\u2500\u2500 [...]
+ | \u2502�� \u2514\u2500\u2500 [other-data-files]
+ | \u251c\u2500\u2500 <test-case-2>
+ | \u2502�� \u251c\u2500\u2500 <result-1>.txt
+ | \u2502�� \u251c\u2500\u2500 [<result-2>.txt]
+ | \u2502�� \u251c\u2500\u2500 [...]
+ | \u2502�� \u2514\u2500\u2500 [other-data-files]
+ | \u2514\u2500\u2500 [...]
+ \u251c\u2500\u2500 <test-suite-2>
+ | \u2514\u2500\u2500 [...]
+ \u2514\u2500\u2500 [...]
+
+The name of the top-level directory is configurable. This document uses
+'test-results' in its examples.
+
+Each test case directory contains a set of result files, and optionally
+contains data files containing information collected during the test. Result
+files are named according to one of the following templates:
+
+ * pass.txt
+ * fail-xxxx.txt
+
+Where "xxxx" is a numeric index automatically generated by testutil. If a test
+passes, its results directory is populated with a single 'pass' file and no
+'fail' files. If a test fails, its results directory is populated with one or
+more 'fail' files and no 'pass' files. A result file (pass or fail) optionally
+contains a text string.
+
+In addition, a results directory can contains data files containing information
+collected during the test. For example, a test case may record timing
+information or statistics. Test case code specifies the name and contents of a
+data file when it writes one. Data files can be written during a test case
+regardless of the test outcome. There are no restrictions on the size or
+contents of data files, but their filenames should be distinct from the test
+result naming scheme described above. There is no limit to the number of data
+files that a particular test case can write.
+
+Returning to the earlier arithmetic test suite example, suppose the test suite
+completed with the following results:
+
+ * test_addition: 1 assertion success, 0 assertion failures
+ * test_times_0: 1 assertion success, 2 assertion failures
+
+Such a test run would produce the following directory tree:
+
+ /
+ \u2514\u2500\u2500 test-results
+ \u2514\u2500\u2500 test_suite_arithmetic
+ \u251c\u2500\u2500 test_addition
+ \u2502�� \u2514\u2500\u2500 pass.txt
+ \u2514\u2500\u2500 test_times_0
+ \u251c\u2500\u2500 fail-0000.txt
+ \u2514\u2500\u2500 fail-0001.txt
+
+Each 'fail' file would contain a string describing the failure.
+
+
+*** TESTUTIL API
+
+struct tu_config {
+ /** If nonzero, test results are printed to stdout. */
+ int tc_print_results;
+
+ /**
+ * Name of the base results directory (e.g., "test-results"). If null,
+ * results are not written to disk.
+ */
+ const char *tc_results_path;
+
+ /**
+ * Array of flash areas where an ffs file system should be located. Unused
+ * if run in a simulated environment. This array must be terminated with a
+ * zero-length area.
+ */
+ const struct ffs_area_desc *tc_area_descs;
+};
+extern struct tu_config tu_config;
+
+Description:
+ The global tu_config struct contains all the testutil package's settings.
+ The struct must be populated before tu_init() is called.
+
+-
+
+int tu_init(void)
+
+Description:
+ Initializes the test framework according to the contents of the tu_config
+ struct. If run in an embedded environment and the
+ tu_config.tc_results_path and tu_config.tc_area_descs fields are non-null,
+ this function ensures an ffs file system is present within the specified
+ flash areas. If testutil is using an ffs file system, and no valid ffs
+ file system is detected in the specified region of flash, the region is
+ formatted with a new file system. This function must be called before any
+ tests are run.
+
+ If, immediately prior to a call to tu_init(), the UUT was restarted via a
+ call to tu_restart(), this function skips all the test cases that have
+ already been executed. See tu_restart() for details.
+
+ Returns 0 on success; nonzero on failure.
+
+-
+
+TEST_ASSERT(expression)
+TEST_ASSERT(expression, fail_msg, ...)
+
+Description:
+ Asserts that the specified condition is true. If the expression is true,
+ nothing gets reported. The expression argument is mandatory; the rest are
+ optional. The fail_msg argument is a printf format string which specifies
+ how the remaining arguments are parsed.
+
+ If the expression is false, testutil reports the following message:
+
+ |<file>:<line-number>| failed assertion: <expression>
+ <fail_msg>
+
+ If no fail_msg is specified, only the first line gets reported.
+
+ The test case proceeds as normal after this macro is invoked.
+
+Example:
+ TEST_ASSERT(num_blocks == 1024,
+ "expected: 1024 blocks; got: %d", num_blocks);
+
+ On failure, the above assertion would result in a report like the
+ following:
+
+ |ffs_test.c:426| failed assertion: num_blocks == 1024
+ expected: 1024 blocks; got 12
+
+-
+
+TEST_ASSERT_FATAL(expression)
+TEST_ASSERT_FATAL(expression, fail_msg, ...)
+
+Description:
+ These are identical to their TEST_ASSERT counterparts, except that a
+ failure causes the current test case to be aborted.
+
+-
+
+TEST_PASS(msg, ...)
+
+Description:
+ Reports a success result for the current test. This function is not
+ normally needed, as all successful tests automatically write an empty pass
+ result at completion. This function is only needed when the success result
+ report should contain text. The msg argument is a printf format string
+ which specifies how the remaining arguments are parsed. The result file
+ produced by this function contains the following text:
+
+ |<file>:<line-number>| manual pass
+ <msg>
+
+ After this function is called, the remainder of the test case is not
+ executed. If the current test has already failed when this macro is
+ invoked, the macro has no effect.
+
+-
+
+testutil_write_data(const char *filename, const uint8_t *data, size_t data_len)
+
+Description:
+ Writes a data file to the current test results directory. The file's
+ contents are fully specified by the data and data_len arguments. If a file
+ with the specified name already exists, it is overwritten. After this
+ function is called, the test case proceeds as normal.
+
+ Data does not get written to stdout; it only gets written to disk. This
+ function has no effect if testutil is configured to not write results to
+ disk.
+
+-
+
+TEST_CASE(test_case_name) { /* test case code */ }
+
+Description:
+ Defines a test case function with the following type:
+
+ int test_case_name(void)
+
+ The return value is 0 if the test case passed; nonzero if it failed.
+ Generally, the return code is not used.
+
+
+-
+
+TEST_SUITE(test_suite_name) { /* test suite code */ }
+
+Description:
+ Defines a test suite function with the following type:
+
+ int test_suite_name(void)
+
+ The return value is 0 if the test suite passed; nonzero if it failed.
+ Generally, the return code is not used.
+
+-
+
+void tu_restart(void)
+
+Description:
+ This function is used when a system reset is necessary to proceed with
+ testing. For example, the OS is designed to run forever once started, so a
+ test which creates several OS tasks and then starts the OS has no means of
+ completing. This function, when called from such a test, gracefully ends
+ the current test case and proceeds to the next test case.
+
+ The particulars of this function depend on whether it is called from a
+ simulated environment. In a simulated environment, this function uses a
+ longjmp() call to break out of the current test case.
+
+ In a non-simulated environment, this function performs the following
+ procedure:
+
+ 1. Record the current test status to the file system.
+ 2. Perform a software reset of the UUT.
+ 3. Read test status and delete it from the file system.
+ 4. Skip all previously completed test cases.
+
+ If this function is called before any results have been reported for the
+ current test case, a "pass" result gets reported.
+
+ Note: after this function performs a software reset, the UUT may not be
+ fully initialized, depending on the test environment. For example, if the
+ UUT has been set up to run the test image from RAM via JTAG, variables in
+ the .data section will not get properly initialized by the software reset.
+ Proper initialization in this case would require that data be re-read from
+ the image file via an additional run of the JTAG script.
+
+-
+
+ASSERT_IF_TEST(cond)
+
+Description:
+ The effect of this macro depends on whether the TEST macro is defined:
+
+ If defined: expands to assert().
+ If not defined: expands to nothing.
+
+ This macro is not intended for use within test cases. Instead, it should
+ be used in normal non-test code to perform computationally-expensive
+ checks. In non-test builds, the checks do not get performed.
+
+
+***** INDIVIDUAL PACKAGE TESTING
+
+Testing individual packages is performed via the "target test" stack tool
+command. When testing is done in this manner, the stack tool automatically
+runs the test code on the host machine. There is no need for an extra stack
+project for producing a test image.
+
+Testing a package in this manner requires a special target that is specific to
+the package. The target specifies the package to test via the "pkg"
+configuration variable. The target must not specify a project, or the test
+command will fail.
+
+Below is an example target called testffs that tests the ffs package:
+
+ testffs
+ compiler: sim
+ compiler_def: debug
+ pkg: libs/ffs
+ bsp: hw/bsp/native
+ arch: sim
+ name: testffs
+
+The target specifies the "native" bsp. This is necessary so that the ffs test
+code can link with the appropriate implementations of the hal functions that it
+depends on.
+
+The test is run by specifying the following stack arguments:
+
+ target test testffs
+
+When the "target test" command is used, the PKG_TEST macro is defined during
+compilation of the package under test. This is in addition to the TEST macro,
+which is defined during compilation of all packages.
+
+
+***** ISSUES / QUESTIONS
+
+* For individual package tests, the requirement for a separate target for each
+ package may become unwieldy. Perhaps the stack tool should be modified to
+ allow arbitrary key-value pairs to be specified on the command line. That
+ way, the target's "pkg" variable could be unset, and the user would specify
+ the package to test when he executes the test command. This would allow the
+ same target to be used for all packages, e.g.,
+
+ target test testtarget pkg=libs/ffs
+ target test testtarget pkg=libs/os
+
+* Most test frameworks define a lot of extra assertions (e.g., assert_equal(),
+ assert_not_null(), assert_false(), etc). These don't seem particularly
+ useful to me, so I did not add them. Typing TEST_ASSERT(x == 5) is no more
+ difficult than TEST_ASSERT_EQUAL(x, 5). The benefit of the more specific
+ assertions is that they can automatically produce more helpful failure
+ messages. For example, if TEST_ASSERT_EQUAL(x, 5) fails, the failure message
+ can contain the actual value of x in most cases, whereas a plain
+ TEST_ASSERT() won't automatically log that information. This didn't seem
+ useful enough to me to justify growing the interface, but I am interested in
+ hearing what others think.
+
+* During testing on embedded devices, the PC software will need some
+ notification when testing is complete, so that it knows when to retrieve the
+ test results. The testutil package should expose some state that the PC
+ software can poll for this purpose.
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/6a7432f4/test/testutil/include/testutil/testutil.h
----------------------------------------------------------------------
diff --git a/test/testutil/include/testutil/testutil.h b/test/testutil/include/testutil/testutil.h
new file mode 100644
index 0000000..de61394
--- /dev/null
+++ b/test/testutil/include/testutil/testutil.h
@@ -0,0 +1,174 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#ifndef H_TESTUTIL_
+#define H_TESTUTIL_
+
+#include <inttypes.h>
+#include <setjmp.h>
+
+#include "syscfg/syscfg.h"
+
+/*****************************************************************************
+ * Public declarations *
+ *****************************************************************************/
+
+typedef void tu_case_init_fn_t(void *arg);
+typedef void tu_case_report_fn_t(char *msg, int msg_len, void *arg);
+typedef void tu_suite_init_fn_t(void *arg);
+typedef void tu_restart_fn_t(void *arg);
+
+struct tu_config {
+ int tc_print_results;
+ int tc_system_assert;
+
+ tu_case_init_fn_t *tc_case_init_cb;
+ void *tc_case_init_arg;
+
+ tu_case_report_fn_t *tc_case_fail_cb;
+ void *tc_case_fail_arg;
+
+ tu_case_report_fn_t *tc_case_pass_cb;
+ void *tc_case_pass_arg;
+
+ tu_suite_init_fn_t *tc_suite_init_cb;
+ void *tc_suite_init_arg;
+
+ tu_restart_fn_t *tc_restart_cb;
+ void *tc_restart_arg;
+};
+
+extern struct tu_config tu_config;
+extern const char *tu_suite_name;
+extern const char *tu_case_name;
+extern int tu_first_idx;
+
+typedef void tu_post_test_fn_t(void *arg);
+
+void tu_suite_set_post_test_cb(tu_post_test_fn_t *cb, void *cb_arg);
+int tu_parse_args(int argc, char **argv);
+int tu_init(void);
+void tu_restart(void);
+
+/*****************************************************************************
+ * Private declarations *
+ *****************************************************************************/
+
+void tu_suite_complete(void);
+void tu_suite_init(const char *name);
+
+void tu_case_init(const char *name);
+void tu_case_complete(void);
+void tu_case_fail_assert(int fatal, const char *file, int line,
+ const char *expr, const char *format, ...);
+void tu_case_write_pass_auto(void);
+void tu_case_pass_manual(const char *file, int line,
+ const char *format, ...);
+void tu_case_post_test(void);
+
+extern int tu_any_failed;
+extern int tu_suite_failed;
+extern int tu_case_reported;
+extern int tu_case_failed;
+extern int tu_case_idx;
+extern jmp_buf tu_case_jb;
+
+#define TEST_SUITE(suite_name) \
+ static void TEST_SUITE_##suite_name(void); \
+ \
+ int \
+ suite_name(void) \
+ { \
+ tu_suite_init(#suite_name); \
+ TEST_SUITE_##suite_name(); \
+ tu_suite_complete(); \
+ \
+ return tu_suite_failed; \
+ } \
+ \
+ static void \
+ TEST_SUITE_##suite_name(void)
+
+/* for creating multiple files with test cases all belonging to the same
+ * suite */
+#define TEST_CASE_DECL(case_name) int case_name(void);
+
+#define TEST_CASE(case_name) \
+ static void TEST_CASE_##case_name(void); \
+ \
+ int \
+ case_name(void) \
+ { \
+ if (tu_case_idx >= tu_first_idx) { \
+ tu_case_init(#case_name); \
+ \
+ if (setjmp(tu_case_jb) == 0) { \
+ TEST_CASE_##case_name(); \
+ tu_case_post_test(); \
+ tu_case_write_pass_auto(); \
+ } \
+ } \
+ \
+ tu_case_complete(); \
+ \
+ return tu_case_failed; \
+ } \
+ \
+ static void \
+ TEST_CASE_##case_name(void)
+
+#define FIRST_AUX(first, ...) first
+#define FIRST(...) FIRST_AUX(__VA_ARGS__, _)
+
+#define NUM(...) ARG10(__VA_ARGS__, N, N, N, N, N, N, N, N, 1, _)
+#define ARG10(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, ...) a10
+
+#define REST_OR_0(...) REST_OR_0_AUX(NUM(__VA_ARGS__), __VA_ARGS__)
+#define REST_OR_0_AUX(qty, ...) REST_OR_0_AUX_INNER(qty, __VA_ARGS__)
+#define REST_OR_0_AUX_INNER(qty, ...) REST_OR_0_AUX_##qty(__VA_ARGS__)
+#define REST_OR_0_AUX_1(first) 0
+#define REST_OR_0_AUX_N(first, ...) __VA_ARGS__
+
+#define XSTR(s) STR(s)
+#define STR(s) #s
+
+#define TEST_ASSERT_FULL(fatal, expr, ...) do \
+{ \
+ if (!(expr)) { \
+ tu_case_fail_assert((fatal), __FILE__, __LINE__, XSTR(expr), \
+ __VA_ARGS__); \
+ } \
+} while (0)
+
+#define TEST_ASSERT(...) \
+ TEST_ASSERT_FULL(0, FIRST(__VA_ARGS__), REST_OR_0(__VA_ARGS__))
+
+#define TEST_ASSERT_FATAL(...) \
+ TEST_ASSERT_FULL(1, FIRST(__VA_ARGS__), REST_OR_0(__VA_ARGS__))
+
+#define TEST_PASS(...) \
+ tu_case_pass_manual(__FILE__, __LINE__, __VA_ARGS__);
+
+#if MYNEWT_VAL(TEST)
+#define ASSERT_IF_TEST(expr) assert(expr)
+#else
+#define ASSERT_IF_TEST(expr)
+#endif
+
+#endif
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/6a7432f4/test/testutil/pkg.yml
----------------------------------------------------------------------
diff --git a/test/testutil/pkg.yml b/test/testutil/pkg.yml
new file mode 100644
index 0000000..be8274e
--- /dev/null
+++ b/test/testutil/pkg.yml
@@ -0,0 +1,30 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+pkg.name: test/testutil
+pkg.description: Support library for implementing unit tests.
+pkg.author: "Apache Mynewt <de...@mynewt.incubator.apache.org>"
+pkg.homepage: "http://mynewt.apache.org/"
+pkg.keywords:
+ - unit
+ - test
+
+pkg.deps:
+ - hw/hal
+ - kernel/os
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/6a7432f4/test/testutil/src/arch/cortex_m4/testutil_arch_arm.c
----------------------------------------------------------------------
diff --git a/test/testutil/src/arch/cortex_m4/testutil_arch_arm.c b/test/testutil/src/arch/cortex_m4/testutil_arch_arm.c
new file mode 100644
index 0000000..52ace63
--- /dev/null
+++ b/test/testutil/src/arch/cortex_m4/testutil_arch_arm.c
@@ -0,0 +1,27 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#include "hal/hal_system.h"
+#include "testutil_priv.h"
+
+void
+tu_arch_restart(void)
+{
+ system_reset();
+}
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/6a7432f4/test/testutil/src/arch/sim/testutil_arch_sim.c
----------------------------------------------------------------------
diff --git a/test/testutil/src/arch/sim/testutil_arch_sim.c b/test/testutil/src/arch/sim/testutil_arch_sim.c
new file mode 100644
index 0000000..2d90501
--- /dev/null
+++ b/test/testutil/src/arch/sim/testutil_arch_sim.c
@@ -0,0 +1,30 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#include "os/os.h"
+#include "os/os_arch.h"
+#include "os/os_test.h"
+#include "testutil_priv.h"
+
+void
+tu_arch_restart(void)
+{
+ os_arch_os_stop();
+ tu_case_abort();
+}
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/6a7432f4/test/testutil/src/arch/sim/tu_args.c
----------------------------------------------------------------------
diff --git a/test/testutil/src/arch/sim/tu_args.c b/test/testutil/src/arch/sim/tu_args.c
new file mode 100644
index 0000000..75a2900
--- /dev/null
+++ b/test/testutil/src/arch/sim/tu_args.c
@@ -0,0 +1,23 @@
+#include <errno.h>
+#include <unistd.h>
+
+#include "testutil/testutil.h"
+
+int
+tu_parse_args(int argc, char **argv)
+{
+ int ch;
+
+ while ((ch = getopt(argc, argv, "s")) != -1) {
+ switch (ch) {
+ case 's':
+ tu_config.tc_system_assert = 1;
+ break;
+
+ default:
+ return EINVAL;
+ }
+ }
+
+ return 0;
+}
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/6a7432f4/test/testutil/src/case.c
----------------------------------------------------------------------
diff --git a/test/testutil/src/case.c b/test/testutil/src/case.c
new file mode 100644
index 0000000..614b142
--- /dev/null
+++ b/test/testutil/src/case.c
@@ -0,0 +1,255 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#include <assert.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdarg.h>
+#include "testutil/testutil.h"
+#include "testutil_priv.h"
+
+jmp_buf tu_case_jb;
+int tu_case_reported;
+int tu_case_failed;
+int tu_case_idx;
+
+const char *tu_case_name;
+tu_post_test_fn_t *tu_case_post_test_cb;
+void *tu_case_post_test_cb_arg;
+
+#define TU_CASE_BUF_SZ 1024
+
+static char tu_case_buf[TU_CASE_BUF_SZ];
+static int tu_case_buf_len;
+
+void
+tu_case_abort(void)
+{
+ tu_case_write_pass_auto();
+ longjmp(tu_case_jb, 1);
+}
+
+static int
+tu_case_vappend_buf(const char *format, va_list ap)
+{
+ char *dst;
+ int maxlen;
+ int rc;
+
+ dst = tu_case_buf + tu_case_buf_len;
+ maxlen = TU_CASE_BUF_SZ - tu_case_buf_len;
+
+ rc = vsnprintf(dst, maxlen, format, ap);
+ tu_case_buf_len += rc;
+ if (tu_case_buf_len >= TU_CASE_BUF_SZ) {
+ tu_case_buf_len = TU_CASE_BUF_SZ - 1;
+ return -1;
+ }
+
+ return 0;
+}
+
+static int
+tu_case_append_buf(const char *format, ...)
+{
+ va_list ap;
+ int rc;
+
+ va_start(ap, format);
+ rc = tu_case_vappend_buf(format, ap);
+ va_end(ap);
+
+ return rc;
+}
+
+static void
+tu_case_set_name(const char *name)
+{
+ tu_case_name = name;
+}
+
+void
+tu_case_init(const char *name)
+{
+ tu_case_reported = 0;
+ tu_case_failed = 0;
+
+ tu_case_set_name(name);
+
+ if (tu_config.tc_case_init_cb != NULL) {
+ tu_config.tc_case_init_cb(tu_config.tc_case_init_arg);
+ }
+}
+
+void
+tu_case_complete(void)
+{
+ tu_case_idx++;
+}
+
+void
+tu_case_post_test(void)
+{
+ if (tu_case_post_test_cb != NULL) {
+ tu_case_post_test_cb(tu_case_post_test_cb_arg);
+ }
+}
+
+static void
+tu_case_write_fail_buf(void)
+{
+ tu_case_reported = 1;
+ tu_case_failed = 1;
+ tu_suite_failed = 1;
+ tu_any_failed = 1;
+
+ if (tu_config.tc_print_results) {
+ printf("[FAIL] %s/%s %s", tu_suite_name, tu_case_name, tu_case_buf);
+ fflush(stdout);
+ }
+
+ if (tu_config.tc_case_fail_cb != NULL) {
+ tu_config.tc_case_fail_cb(tu_case_buf, tu_case_buf_len,
+ tu_config.tc_case_fail_arg);
+ }
+}
+
+static void
+tu_case_append_file_info(const char *file, int line)
+{
+ int rc;
+
+ rc = tu_case_append_buf("|%s:%d| ", file, line);
+ assert(rc == 0);
+}
+
+static void
+tu_case_append_assert_msg(const char *expr)
+{
+ int rc;
+
+ rc = tu_case_append_buf("failed assertion: %s", expr);
+ assert(rc == 0);
+}
+
+static void
+tu_case_write_pass_buf(void)
+{
+ if (tu_config.tc_print_results) {
+ printf("[pass] %s/%s\n", tu_suite_name, tu_case_name);
+ if (tu_case_buf_len > 0) {
+ printf("%s", tu_case_buf);
+ }
+ fflush(stdout);
+ }
+
+ tu_case_reported = 1;
+
+ if (tu_config.tc_case_pass_cb != NULL) {
+ tu_config.tc_case_pass_cb(tu_case_buf, tu_case_buf_len,
+ tu_config.tc_case_pass_arg);
+ }
+}
+
+static void
+tu_case_append_manual_pass_msg(void)
+{
+ int rc;
+
+ rc = tu_case_append_buf("manual pass");
+ assert(rc == 0);
+}
+
+void
+tu_case_write_pass_auto(void)
+{
+ if (!tu_case_reported) {
+ tu_case_buf_len = 0;
+ tu_case_write_pass_buf();
+ }
+}
+
+void
+tu_case_fail_assert(int fatal, const char *file, int line,
+ const char *expr, const char *format, ...)
+{
+ va_list ap;
+ int rc;
+
+ if (tu_config.tc_system_assert) {
+ assert(0);
+ }
+
+ tu_case_buf_len = 0;
+
+ tu_case_append_file_info(file, line);
+ tu_case_append_assert_msg(expr);
+
+ if (format != NULL) {
+ rc = tu_case_append_buf("\n");
+ assert(rc == 0);
+
+ va_start(ap, format);
+ rc = tu_case_vappend_buf(format, ap);
+ assert(rc == 0);
+ va_end(ap);
+ }
+
+ rc = tu_case_append_buf("\n");
+ assert(rc == 0);
+
+ tu_case_write_fail_buf();
+
+ if (fatal) {
+ tu_case_abort();
+ }
+}
+
+void
+tu_case_pass_manual(const char *file, int line, const char *format, ...)
+{
+ va_list ap;
+ int rc;
+
+ if (tu_case_reported) {
+ return;
+ }
+
+ tu_case_buf_len = 0;
+
+ tu_case_append_file_info(file, line);
+ tu_case_append_manual_pass_msg();
+
+ if (format != NULL) {
+ rc = tu_case_append_buf("\n");
+ assert(rc == 0);
+
+ va_start(ap, format);
+ rc = tu_case_vappend_buf(format, ap);
+ assert(rc == 0);
+ va_end(ap);
+ }
+
+ rc = tu_case_append_buf("\n");
+ assert(rc == 0);
+
+ tu_case_write_pass_buf();
+
+ tu_case_abort();
+}
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/6a7432f4/test/testutil/src/suite.c
----------------------------------------------------------------------
diff --git a/test/testutil/src/suite.c b/test/testutil/src/suite.c
new file mode 100644
index 0000000..93ca639
--- /dev/null
+++ b/test/testutil/src/suite.c
@@ -0,0 +1,67 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#include <assert.h>
+#include "testutil/testutil.h"
+#include "testutil_priv.h"
+
+const char *tu_suite_name = 0;
+int tu_suite_failed = 0;
+
+static void
+tu_suite_set_name(const char *name)
+{
+ tu_suite_name = name;
+}
+
+/**
+ * Configures a callback that gets executed at the end of each test case in the
+ * current suite. This is useful when there are some checks that should be
+ * performed at the end of each test (e.g., verify no memory leaks). This
+ * callback is cleared when the current suite completes.
+ *
+ * @param cb The callback to execute at the end of each test
+ * case.
+ * @param cb_arg An optional argument that gets passed to the
+ * callback.
+ */
+void
+tu_suite_set_post_test_cb(tu_post_test_fn_t *cb, void *cb_arg)
+{
+ tu_case_post_test_cb = cb;
+ tu_case_post_test_cb_arg = cb_arg;
+}
+
+void
+tu_suite_complete(void)
+{
+ tu_suite_set_post_test_cb(NULL, NULL);
+}
+
+void
+tu_suite_init(const char *name)
+{
+ tu_suite_failed = 0;
+
+ tu_suite_set_name(name);
+
+ if (tu_config.tc_suite_init_cb != NULL) {
+ tu_config.tc_suite_init_cb(tu_config.tc_suite_init_arg);
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/6a7432f4/test/testutil/src/testutil.c
----------------------------------------------------------------------
diff --git a/test/testutil/src/testutil.c b/test/testutil/src/testutil.c
new file mode 100644
index 0000000..032a32c
--- /dev/null
+++ b/test/testutil/src/testutil.c
@@ -0,0 +1,50 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#include <assert.h>
+#include "os/os.h"
+#include "hal/hal_flash.h"
+#include "testutil/testutil.h"
+#include "testutil_priv.h"
+
+struct tu_config tu_config;
+int tu_any_failed;
+int tu_first_idx;
+
+int
+tu_init(void)
+{
+ os_init();
+
+ return 0;
+}
+
+void
+tu_restart(void)
+{
+ tu_case_write_pass_auto();
+
+ tu_first_idx = tu_case_idx + 1;
+
+ if (tu_config.tc_restart_cb != NULL) {
+ tu_config.tc_restart_cb(tu_config.tc_restart_arg);
+ }
+
+ tu_arch_restart();
+}
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/6a7432f4/test/testutil/src/testutil_priv.h
----------------------------------------------------------------------
diff --git a/test/testutil/src/testutil_priv.h b/test/testutil/src/testutil_priv.h
new file mode 100644
index 0000000..3f8cb2d
--- /dev/null
+++ b/test/testutil/src/testutil_priv.h
@@ -0,0 +1,34 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#ifndef H_TESTUTIL_PRIV_
+#define H_TESTUTIL_PRIV_
+
+#include <stddef.h>
+#include <inttypes.h>
+
+#include "testutil/testutil.h"
+
+void tu_arch_restart(void);
+void tu_case_abort(void);
+
+extern tu_post_test_fn_t *tu_case_post_test_cb;
+extern void *tu_case_post_test_cb_arg;
+
+#endif