You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mynewt.apache.org by cc...@apache.org on 2016/09/13 03:41:55 UTC

[02/41] incubator-mynewt-core git commit: syscfg / sysinit

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/d98ddc1c/sys/config/test/src/conf_test.c
----------------------------------------------------------------------
diff --git a/sys/config/test/src/conf_test.c b/sys/config/test/src/conf_test.c
new file mode 100644
index 0000000..3c432c4
--- /dev/null
+++ b/sys/config/test/src/conf_test.c
@@ -0,0 +1,953 @@
+/**
+ * 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 <string.h>
+
+#include <os/os.h>
+#include <testutil/testutil.h>
+#include <nffs/nffs.h>
+#include <fs/fs.h>
+#include <fs/fsutil.h>
+#include <fcb/fcb.h>
+#include "config/config.h"
+#include "config/config_file.h"
+#include "config/config_fcb.h"
+#include "config_test.h"
+#include "config_priv.h"
+
+static uint8_t val8;
+int c2_var_count = 1;
+static char val_string[64][CONF_MAX_VAL_LEN];
+
+static uint32_t val32;
+
+static int test_get_called;
+static int test_set_called;
+static int test_commit_called;
+static int test_export_block;
+
+static char *ctest_handle_get(int argc, char **argv, char *val,
+  int val_len_max);
+static int ctest_handle_set(int argc, char **argv, char *val);
+static int ctest_handle_commit(void);
+static int ctest_handle_export(void (*cb)(char *name, char *value),
+  enum conf_export_tgt tgt);
+static char *c2_handle_get(int argc, char **argv, char *val,
+  int val_len_max);
+static int c2_handle_set(int argc, char **argv, char *val);
+static int c2_handle_export(void (*cb)(char *name, char *value),
+  enum conf_export_tgt tgt);
+static char *c3_handle_get(int argc, char **argv, char *val,
+  int val_len_max);
+static int c3_handle_set(int argc, char **argv, char *val);
+static int c3_handle_export(void (*cb)(char *name, char *value),
+  enum conf_export_tgt tgt);
+
+struct conf_handler config_test_handler = {
+    .ch_name = "myfoo",
+    .ch_get = ctest_handle_get,
+    .ch_set = ctest_handle_set,
+    .ch_commit = ctest_handle_commit,
+    .ch_export = ctest_handle_export
+};
+
+static char *
+ctest_handle_get(int argc, char **argv, char *val, int val_len_max)
+{
+    test_get_called = 1;
+    if (argc == 1 && !strcmp(argv[0], "mybar")) {
+        return conf_str_from_value(CONF_INT8, &val8, val, val_len_max);
+    }
+    return NULL;
+}
+
+static int
+ctest_handle_set(int argc, char **argv, char *val)
+{
+    uint8_t newval;
+    int rc;
+
+    test_set_called = 1;
+    if (argc == 1 && !strcmp(argv[0], "mybar")) {
+        rc = CONF_VALUE_SET(val, CONF_INT8, newval);
+        TEST_ASSERT(rc == 0);
+        val8 = newval;
+        return 0;
+    }
+    return OS_ENOENT;
+}
+
+static int
+ctest_handle_commit(void)
+{
+    test_commit_called = 1;
+    return 0;
+}
+
+static int
+ctest_handle_export(void (*cb)(char *name, char *value),
+  enum conf_export_tgt tgt)
+{
+    char value[32];
+
+    if (test_export_block) {
+        return 0;
+    }
+    conf_str_from_value(CONF_INT8, &val8, value, sizeof(value));
+    cb("myfoo/mybar", value);
+
+    return 0;
+}
+
+struct conf_handler c2_test_handler = {
+    .ch_name = "2nd",
+    .ch_get = c2_handle_get,
+    .ch_set = c2_handle_set,
+    .ch_commit = NULL,
+    .ch_export = c2_handle_export
+};
+
+char *
+c2_var_find(char *name)
+{
+    int idx = 0;
+    int len;
+    char *eptr;
+
+    len = strlen(name);
+    TEST_ASSERT(!strncmp(name, "string", 6));
+    TEST_ASSERT(len > 6);
+
+    idx = strtoul(&name[6], &eptr, 10);
+    TEST_ASSERT(*eptr == '\0');
+    TEST_ASSERT(idx < c2_var_count);
+    return val_string[idx];
+}
+
+static char *
+c2_handle_get(int argc, char **argv, char *val, int val_len_max)
+{
+    int len;
+    char *valptr;
+
+    if (argc == 1) {
+        valptr = c2_var_find(argv[0]);
+        if (!valptr) {
+            return NULL;
+        }
+        len = strlen(val_string[0]);
+        if (len > val_len_max) {
+            len = val_len_max;
+        }
+        strncpy(val, valptr, len);
+    }
+    return NULL;
+}
+
+static int
+c2_handle_set(int argc, char **argv, char *val)
+{
+    char *valptr;
+
+    if (argc == 1) {
+        valptr = c2_var_find(argv[0]);
+        if (!valptr) {
+            return OS_ENOENT;
+        }
+        if (val) {
+            strncpy(valptr, val, sizeof(val_string[0]));
+        } else {
+            memset(valptr, 0, sizeof(val_string[0]));
+        }
+        return 0;
+    }
+    return OS_ENOENT;
+}
+
+static int
+c2_handle_export(void (*cb)(char *name, char *value),
+  enum conf_export_tgt tgt)
+{
+    int i;
+    char name[32];
+
+    for (i = 0; i < c2_var_count; i++) {
+        snprintf(name, sizeof(name), "2nd/string%d", i);
+        cb(name, val_string[i]);
+    }
+    return 0;
+}
+
+struct conf_handler c3_test_handler = {
+    .ch_name = "3",
+    .ch_get = c3_handle_get,
+    .ch_set = c3_handle_set,
+    .ch_commit = NULL,
+    .ch_export = c3_handle_export
+};
+
+static char *
+c3_handle_get(int argc, char **argv, char *val, int val_len_max)
+{
+    if (argc == 1 && !strcmp(argv[0], "v")) {
+        return conf_str_from_value(CONF_INT32, &val32, val, val_len_max);
+    }
+    return NULL;
+}
+
+static int
+c3_handle_set(int argc, char **argv, char *val)
+{
+    uint32_t newval;
+    int rc;
+
+    if (argc == 1 && !strcmp(argv[0], "v")) {
+        rc = CONF_VALUE_SET(val, CONF_INT32, newval);
+        TEST_ASSERT(rc == 0);
+        val32 = newval;
+        return 0;
+    }
+    return OS_ENOENT;
+}
+
+static int
+c3_handle_export(void (*cb)(char *name, char *value),
+  enum conf_export_tgt tgt)
+{
+    char value[32];
+
+    conf_str_from_value(CONF_INT32, &val32, value, sizeof(value));
+    cb("3/v", value);
+
+    return 0;
+}
+
+static void
+ctest_clear_call_state(void)
+{
+    test_get_called = 0;
+    test_set_called = 0;
+    test_commit_called = 0;
+}
+
+static int
+ctest_get_call_state(void)
+{
+    return test_get_called + test_set_called + test_commit_called;
+}
+
+TEST_CASE(config_empty_lookups)
+{
+    int rc;
+    char name[80];
+    char tmp[64], *str;
+
+    strcpy(name, "foo/bar");
+    rc = conf_set_value(name, "tmp");
+    TEST_ASSERT(rc != 0);
+
+    strcpy(name, "foo/bar");
+    str = conf_get_value(name, tmp, sizeof(tmp));
+    TEST_ASSERT(str == NULL);
+}
+
+TEST_CASE(config_test_insert)
+{
+    int rc;
+
+    rc = conf_register(&config_test_handler);
+    TEST_ASSERT(rc == 0);
+}
+
+TEST_CASE(config_test_insert2)
+{
+    int rc;
+
+    rc = conf_register(&c2_test_handler);
+    TEST_ASSERT(rc == 0);
+}
+
+TEST_CASE(config_test_getset_unknown)
+{
+    char name[80];
+    char tmp[64], *str;
+    int rc;
+
+    strcpy(name, "foo/bar");
+    rc = conf_set_value(name, "tmp");
+    TEST_ASSERT(rc != 0);
+    TEST_ASSERT(ctest_get_call_state() == 0);
+
+    strcpy(name, "foo/bar");
+    str = conf_get_value(name, tmp, sizeof(tmp));
+    TEST_ASSERT(str == NULL);
+    TEST_ASSERT(ctest_get_call_state() == 0);
+
+    strcpy(name, "myfoo/bar");
+    rc = conf_set_value(name, "tmp");
+    TEST_ASSERT(rc == OS_ENOENT);
+    TEST_ASSERT(test_set_called == 1);
+    ctest_clear_call_state();
+
+    strcpy(name, "myfoo/bar");
+    str = conf_get_value(name, tmp, sizeof(tmp));
+    TEST_ASSERT(str == NULL);
+    TEST_ASSERT(test_get_called == 1);
+    ctest_clear_call_state();
+}
+
+TEST_CASE(config_test_getset_int)
+{
+    char name[80];
+    char tmp[64], *str;
+    int rc;
+
+    strcpy(name, "myfoo/mybar");
+    rc = conf_set_value(name, "42");
+    TEST_ASSERT(rc == 0);
+    TEST_ASSERT(test_set_called == 1);
+    TEST_ASSERT(val8 == 42);
+    ctest_clear_call_state();
+
+    strcpy(name, "myfoo/mybar");
+    str = conf_get_value(name, tmp, sizeof(tmp));
+    TEST_ASSERT(str);
+    TEST_ASSERT(test_get_called == 1);
+    TEST_ASSERT(!strcmp("42", tmp));
+    ctest_clear_call_state();
+}
+
+TEST_CASE(config_test_getset_bytes)
+{
+    char orig[32];
+    char bytes[32];
+    char str[48];
+    char *ret;
+    int j, i;
+    int tmp;
+    int rc;
+
+    for (j = 1; j < sizeof(orig); j++) {
+        for (i = 0; i < j; i++) {
+            orig[i] = i + j + 1;
+        }
+        ret = conf_str_from_bytes(orig, j, str, sizeof(str));
+        TEST_ASSERT(ret);
+        tmp = strlen(str);
+        TEST_ASSERT(tmp < sizeof(str));
+
+        memset(bytes, 0, sizeof(bytes));
+        tmp = sizeof(bytes);
+
+        tmp = sizeof(bytes);
+        rc = conf_bytes_from_str(str, bytes, &tmp);
+        TEST_ASSERT(rc == 0);
+        TEST_ASSERT(tmp == j);
+        TEST_ASSERT(!memcmp(orig, bytes, j));
+    }
+}
+
+TEST_CASE(config_test_commit)
+{
+    char name[80];
+    int rc;
+
+    strcpy(name, "bar");
+    rc = conf_commit(name);
+    TEST_ASSERT(rc);
+    TEST_ASSERT(ctest_get_call_state() == 0);
+
+    rc = conf_commit(NULL);
+    TEST_ASSERT(rc == 0);
+    TEST_ASSERT(test_commit_called == 1);
+    ctest_clear_call_state();
+
+    strcpy(name, "myfoo");
+    rc = conf_commit(name);
+    TEST_ASSERT(rc == 0);
+    TEST_ASSERT(test_commit_called == 1);
+    ctest_clear_call_state();
+}
+
+static const struct nffs_area_desc config_nffs[] = {
+    { 0x00000000, 16 * 1024 },
+    { 0x00004000, 16 * 1024 },
+    { 0x00008000, 16 * 1024 },
+    { 0x0000c000, 16 * 1024 },
+    { 0, 0 }
+};
+
+TEST_CASE(config_setup_nffs)
+{
+    int rc;
+
+    rc = nffs_init();
+    TEST_ASSERT_FATAL(rc == 0);
+    rc = nffs_format(config_nffs);
+    TEST_ASSERT_FATAL(rc == 0);
+}
+
+static void config_wipe_srcs(void)
+{
+    SLIST_INIT(&conf_load_srcs);
+    conf_save_dst = NULL;
+}
+
+static void config_wipe_fcb(struct flash_area *fa, int cnt)
+{
+    int i;
+
+    for (i = 0; i < cnt; i++) {
+        flash_area_erase(&fa[i], 0, fa[i].fa_size);
+    }
+}
+
+TEST_CASE(config_test_empty_file)
+{
+    int rc;
+    struct conf_file cf_mfg;
+    struct conf_file cf_running;
+    const char cf_mfg_test[] = "";
+    const char cf_running_test[] = "\n\n";
+
+    config_wipe_srcs();
+
+    cf_mfg.cf_name = "/config/mfg";
+    cf_running.cf_name = "/config/running";
+
+    rc = conf_file_src(&cf_mfg);
+    TEST_ASSERT(rc == 0);
+    rc = conf_file_src(&cf_running);
+
+    /*
+     * No files
+     */
+    conf_load();
+
+    rc = fs_mkdir("/config");
+    TEST_ASSERT(rc == 0);
+
+    rc = fsutil_write_file("/config/mfg", cf_mfg_test, sizeof(cf_mfg_test));
+    TEST_ASSERT(rc == 0);
+
+    rc = fsutil_write_file("/config/running", cf_running_test,
+      sizeof(cf_running_test));
+    TEST_ASSERT(rc == 0);
+
+    conf_load();
+    config_wipe_srcs();
+    ctest_clear_call_state();
+}
+
+TEST_CASE(config_test_small_file)
+{
+    int rc;
+    struct conf_file cf_mfg;
+    struct conf_file cf_running;
+    const char cf_mfg_test[] = "myfoo/mybar=1";
+    const char cf_running_test[] = " myfoo/mybar = 8 ";
+
+    config_wipe_srcs();
+
+    cf_mfg.cf_name = "/config/mfg";
+    cf_running.cf_name = "/config/running";
+
+    rc = conf_file_src(&cf_mfg);
+    TEST_ASSERT(rc == 0);
+    rc = conf_file_src(&cf_running);
+
+    rc = fsutil_write_file("/config/mfg", cf_mfg_test, sizeof(cf_mfg_test));
+    TEST_ASSERT(rc == 0);
+
+    conf_load();
+    TEST_ASSERT(test_set_called);
+    TEST_ASSERT(val8 == 1);
+
+    ctest_clear_call_state();
+
+    rc = fsutil_write_file("/config/running", cf_running_test,
+      sizeof(cf_running_test));
+    TEST_ASSERT(rc == 0);
+
+    conf_load();
+    TEST_ASSERT(test_set_called);
+    TEST_ASSERT(val8 == 8);
+
+    ctest_clear_call_state();
+}
+
+TEST_CASE(config_test_multiple_in_file)
+{
+    int rc;
+    struct conf_file cf_mfg;
+    const char cf_mfg_test1[] =
+      "myfoo/mybar=1\n"
+      "myfoo/mybar=14";
+    const char cf_mfg_test2[] =
+      "myfoo/mybar=1\n"
+      "myfoo/mybar=15\n"
+      "\n";
+
+    config_wipe_srcs();
+
+    cf_mfg.cf_name = "/config/mfg";
+    rc = conf_file_src(&cf_mfg);
+    TEST_ASSERT(rc == 0);
+
+    rc = fsutil_write_file("/config/mfg", cf_mfg_test1, sizeof(cf_mfg_test1));
+    TEST_ASSERT(rc == 0);
+
+    conf_load();
+    TEST_ASSERT(test_set_called);
+    TEST_ASSERT(val8 == 14);
+
+    rc = fsutil_write_file("/config/mfg", cf_mfg_test2, sizeof(cf_mfg_test2));
+    TEST_ASSERT(rc == 0);
+
+    conf_load();
+    TEST_ASSERT(test_set_called);
+    TEST_ASSERT(val8 == 15);
+}
+
+int
+conf_test_file_strstr(const char *fname, char *string)
+{
+    int rc;
+    uint32_t len;
+    uint32_t rlen;
+    char *buf;
+    struct fs_file *file;
+
+    rc = fs_open(fname, FS_ACCESS_READ, &file);
+    if (rc) {
+        return rc;
+    }
+    rc = fs_filelen(file, &len);
+    fs_close(file);
+    if (rc) {
+        return rc;
+    }
+
+    buf = (char *)malloc(len + 1);
+    TEST_ASSERT(buf);
+
+    rc = fsutil_read_file(fname, 0, len, buf, &rlen);
+    TEST_ASSERT(rc == 0);
+    TEST_ASSERT(rlen == len);
+    buf[rlen] = '\0';
+
+    if (strstr(buf, string)) {
+        return 0;
+    } else {
+        return -1;
+    }
+}
+
+TEST_CASE(config_test_save_in_file)
+{
+    int rc;
+    struct conf_file cf;
+
+    config_wipe_srcs();
+
+    rc = fs_mkdir("/config");
+    TEST_ASSERT(rc == 0 || rc == FS_EEXIST);
+
+    cf.cf_name = "/config/blah";
+    rc = conf_file_src(&cf);
+    TEST_ASSERT(rc == 0);
+    rc = conf_file_dst(&cf);
+    TEST_ASSERT(rc == 0);
+
+    val8 = 8;
+    rc = conf_save();
+    TEST_ASSERT(rc == 0);
+
+    rc = conf_test_file_strstr(cf.cf_name, "myfoo/mybar=8\n");
+    TEST_ASSERT(rc == 0);
+
+    val8 = 43;
+    rc = conf_save();
+    TEST_ASSERT(rc == 0);
+
+    rc = conf_test_file_strstr(cf.cf_name, "myfoo/mybar=43\n");
+    TEST_ASSERT(rc == 0);
+}
+
+TEST_CASE(config_test_save_one_file)
+{
+    int rc;
+    struct conf_file cf;
+
+    config_wipe_srcs();
+    rc = fs_mkdir("/config");
+    TEST_ASSERT(rc == 0 || rc == FS_EEXIST);
+
+    cf.cf_name = "/config/blah";
+    rc = conf_file_src(&cf);
+    TEST_ASSERT(rc == 0);
+    rc = conf_file_dst(&cf);
+    TEST_ASSERT(rc == 0);
+
+    val8 = 33;
+    rc = conf_save();
+    TEST_ASSERT(rc == 0);
+
+    rc = conf_save_one("myfoo/mybar", "42");
+    TEST_ASSERT(rc == 0);
+
+    rc = conf_load();
+    TEST_ASSERT(rc == 0);
+    TEST_ASSERT(val8 == 42);
+
+    rc = conf_save_one("myfoo/mybar", "44");
+    TEST_ASSERT(rc == 0);
+
+    rc = conf_load();
+    TEST_ASSERT(rc == 0);
+    TEST_ASSERT(val8 == 44);
+}
+
+struct flash_area fcb_areas[] = {
+    [0] = {
+        .fa_off = 0x00000000,
+        .fa_size = 16 * 1024
+    },
+    [1] = {
+        .fa_off = 0x00004000,
+        .fa_size = 16 * 1024
+    },
+    [2] = {
+        .fa_off = 0x00008000,
+        .fa_size = 16 * 1024
+    },
+    [3] = {
+        .fa_off = 0x0000c000,
+        .fa_size = 16 * 1024
+    }
+};
+
+TEST_CASE(config_test_empty_fcb)
+{
+    int rc;
+    struct conf_fcb cf;
+
+    config_wipe_srcs();
+    config_wipe_fcb(fcb_areas, sizeof(fcb_areas) / sizeof(fcb_areas[0]));
+
+    cf.cf_fcb.f_sectors = fcb_areas;
+    cf.cf_fcb.f_sector_cnt = sizeof(fcb_areas) / sizeof(fcb_areas[0]);
+
+    rc = conf_fcb_src(&cf);
+    TEST_ASSERT(rc == 0);
+
+    /*
+     * No values
+     */
+    conf_load();
+
+    config_wipe_srcs();
+    ctest_clear_call_state();
+}
+
+TEST_CASE(config_test_save_1_fcb)
+{
+    int rc;
+    struct conf_fcb cf;
+
+    config_wipe_srcs();
+
+    cf.cf_fcb.f_sectors = fcb_areas;
+    cf.cf_fcb.f_sector_cnt = sizeof(fcb_areas) / sizeof(fcb_areas[0]);
+
+    rc = conf_fcb_src(&cf);
+    TEST_ASSERT(rc == 0);
+
+    rc = conf_fcb_dst(&cf);
+    TEST_ASSERT(rc == 0);
+
+    val8 = 33;
+    rc = conf_save();
+    TEST_ASSERT(rc == 0);
+
+    val8 = 0;
+
+    rc = conf_load();
+    TEST_ASSERT(rc == 0);
+    TEST_ASSERT(val8 == 33);
+}
+
+static void config_test_fill_area(char test_value[64][CONF_MAX_VAL_LEN],
+  int iteration)
+{
+      int i, j;
+
+      for (j = 0; j < 64; j++) {
+          for (i = 0; i < CONF_MAX_VAL_LEN; i++) {
+              test_value[j][i] = ((j * 2) + i + iteration) % 10 + '0';
+          }
+          test_value[j][sizeof(test_value[j]) - 1] = '\0';
+      }
+}
+
+TEST_CASE(config_test_save_2_fcb)
+{
+    int rc;
+    struct conf_fcb cf;
+    char test_value[64][CONF_MAX_VAL_LEN];
+    int i;
+
+    config_wipe_srcs();
+
+    cf.cf_fcb.f_sectors = fcb_areas;
+    cf.cf_fcb.f_sector_cnt = sizeof(fcb_areas) / sizeof(fcb_areas[0]);
+
+    rc = conf_fcb_src(&cf);
+    TEST_ASSERT(rc == 0);
+
+    rc = conf_fcb_dst(&cf);
+    TEST_ASSERT(rc == 0);
+
+    config_test_fill_area(test_value, 0);
+    memcpy(val_string, test_value, sizeof(val_string));
+
+    val8 = 42;
+    rc = conf_save();
+    TEST_ASSERT(rc == 0);
+
+    val8 = 0;
+    memset(val_string[0], 0, sizeof(val_string[0]));
+    rc = conf_load();
+    TEST_ASSERT(rc == 0);
+    TEST_ASSERT(val8 == 42);
+    TEST_ASSERT(!strcmp(val_string[0], test_value[0]));
+    test_export_block = 1;
+
+    /*
+     * Now add the number of settings to max. Keep adjusting the test_data,
+     * check that rollover happens when it's supposed to.
+     */
+    c2_var_count = 64;
+
+    for (i = 0; i < 32; i++) {
+        config_test_fill_area(test_value, i);
+        memcpy(val_string, test_value, sizeof(val_string));
+
+        rc = conf_save();
+        TEST_ASSERT(rc == 0);
+
+        memset(val_string, 0, sizeof(val_string));
+
+        val8 = 0;
+        rc = conf_load();
+        TEST_ASSERT(rc == 0);
+        TEST_ASSERT(!memcmp(val_string, test_value, sizeof(val_string)));
+        TEST_ASSERT(val8 == 42);
+    }
+    c2_var_count = 0;
+}
+
+TEST_CASE(config_test_insert3)
+{
+    int rc;
+
+    rc = conf_register(&c3_test_handler);
+    TEST_ASSERT(rc == 0);
+}
+
+TEST_CASE(config_test_save_3_fcb)
+{
+    int rc;
+    struct conf_fcb cf;
+    int i;
+
+    config_wipe_srcs();
+    config_wipe_fcb(fcb_areas, sizeof(fcb_areas) / sizeof(fcb_areas[0]));
+
+    cf.cf_fcb.f_sectors = fcb_areas;
+    cf.cf_fcb.f_sector_cnt = 4;
+
+    rc = conf_fcb_src(&cf);
+    TEST_ASSERT(rc == 0);
+
+    rc = conf_fcb_dst(&cf);
+    TEST_ASSERT(rc == 0);
+
+    for (i = 0; i < 4096; i++) {
+        val32 = i;
+
+        rc = conf_save();
+        TEST_ASSERT(rc == 0);
+
+        val32 = 0;
+
+        rc = conf_load();
+        TEST_ASSERT(rc == 0);
+        TEST_ASSERT(val32 == i);
+    }
+}
+
+TEST_CASE(config_test_compress_reset)
+{
+    int rc;
+    struct conf_fcb cf;
+    struct flash_area *fa;
+    char test_value[64][CONF_MAX_VAL_LEN];
+    int elems[4];
+    int i;
+
+    config_wipe_srcs();
+    config_wipe_fcb(fcb_areas, sizeof(fcb_areas) / sizeof(fcb_areas[0]));
+
+    cf.cf_fcb.f_sectors = fcb_areas;
+    cf.cf_fcb.f_sector_cnt = sizeof(fcb_areas) / sizeof(fcb_areas[0]);
+
+    rc = conf_fcb_src(&cf);
+    TEST_ASSERT(rc == 0);
+
+    rc = conf_fcb_dst(&cf);
+    TEST_ASSERT(rc == 0);
+
+    c2_var_count = 1;
+    memset(elems, 0, sizeof(elems));
+
+    for (i = 0; ; i++) {
+        config_test_fill_area(test_value, i);
+        memcpy(val_string, test_value, sizeof(val_string));
+
+        rc = conf_save();
+        TEST_ASSERT(rc == 0);
+
+        if (cf.cf_fcb.f_active.fe_area == &fcb_areas[2]) {
+            /*
+             * Started using space just before scratch.
+             */
+            break;
+        }
+        memset(val_string, 0, sizeof(val_string));
+
+        rc = conf_load();
+        TEST_ASSERT(rc == 0);
+        TEST_ASSERT(!memcmp(val_string, test_value, CONF_MAX_VAL_LEN));
+    }
+
+    fa = cf.cf_fcb.f_active.fe_area;
+    rc = fcb_append_to_scratch(&cf.cf_fcb);
+    TEST_ASSERT(rc == 0);
+    TEST_ASSERT(fcb_free_sector_cnt(&cf.cf_fcb) == 0);
+    TEST_ASSERT(fa != cf.cf_fcb.f_active.fe_area);
+
+    config_wipe_srcs();
+
+    memset(&cf, 0, sizeof(cf));
+
+    cf.cf_fcb.f_sectors = fcb_areas;
+    cf.cf_fcb.f_sector_cnt = sizeof(fcb_areas) / sizeof(fcb_areas[0]);
+
+    rc = conf_fcb_src(&cf);
+    TEST_ASSERT(rc == 0);
+
+    rc = conf_fcb_dst(&cf);
+    TEST_ASSERT(rc == 0);
+
+    TEST_ASSERT(fcb_free_sector_cnt(&cf.cf_fcb) == 1);
+    TEST_ASSERT(fa == cf.cf_fcb.f_active.fe_area);
+
+    c2_var_count = 0;
+}
+
+TEST_CASE(config_test_save_one_fcb)
+{
+    int rc;
+    struct conf_fcb cf;
+
+    config_wipe_srcs();
+    config_wipe_fcb(fcb_areas, sizeof(fcb_areas) / sizeof(fcb_areas[0]));
+
+    cf.cf_fcb.f_sectors = fcb_areas;
+    cf.cf_fcb.f_sector_cnt = sizeof(fcb_areas) / sizeof(fcb_areas[0]);
+
+    rc = conf_fcb_src(&cf);
+    TEST_ASSERT(rc == 0);
+
+    rc = conf_fcb_dst(&cf);
+    TEST_ASSERT(rc == 0);
+
+    val8 = 33;
+    rc = conf_save();
+    TEST_ASSERT(rc == 0);
+
+    rc = conf_save_one("myfoo/mybar", "42");
+    TEST_ASSERT(rc == 0);
+
+    rc = conf_load();
+    TEST_ASSERT(rc == 0);
+    TEST_ASSERT(val8 == 42);
+
+    rc = conf_save_one("myfoo/mybar", "44");
+    TEST_ASSERT(rc == 0);
+
+    rc = conf_load();
+    TEST_ASSERT(rc == 0);
+    TEST_ASSERT(val8 == 44);
+}
+
+TEST_SUITE(config_test_all)
+{
+    /*
+     * Config tests.
+     */
+    config_empty_lookups();
+    config_test_insert();
+    config_test_getset_unknown();
+    config_test_getset_int();
+    config_test_getset_bytes();
+
+    config_test_commit();
+
+    /*
+     * NFFS as backing storage.
+     */
+    config_setup_nffs();
+    config_test_empty_file();
+    config_test_small_file();
+    config_test_multiple_in_file();
+
+    config_test_save_in_file();
+
+    config_test_save_one_file();
+
+    /*
+     * FCB as backing storage.
+     */
+    config_test_empty_fcb();
+    config_test_save_1_fcb();
+
+    config_test_insert2();
+
+    config_test_save_2_fcb();
+
+    config_test_insert3();
+    config_test_save_3_fcb();
+
+    config_test_compress_reset();
+
+    config_test_save_one_fcb();
+}
+

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/d98ddc1c/sys/config/test/src/conf_test.h
----------------------------------------------------------------------
diff --git a/sys/config/test/src/conf_test.h b/sys/config/test/src/conf_test.h
new file mode 100644
index 0000000..b50ff2f
--- /dev/null
+++ b/sys/config/test/src/conf_test.h
@@ -0,0 +1,25 @@
+/**
+ * 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 _CONF_TEST_H_
+#define _CONF_TEST_H_
+
+void config_test_all(void);
+
+#endif /* _CONF_TEST_H_ */

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/d98ddc1c/sys/config/test/src/conf_test_suite.c
----------------------------------------------------------------------
diff --git a/sys/config/test/src/conf_test_suite.c b/sys/config/test/src/conf_test_suite.c
new file mode 100644
index 0000000..65360c3
--- /dev/null
+++ b/sys/config/test/src/conf_test_suite.c
@@ -0,0 +1,40 @@
+/**
+ * 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"
+#include "os/os.h"
+#include "testutil/testutil.h"
+#include "config/config.h"
+#include "config_test.h"
+
+#if MYNEWT_VAL(SELFTEST)
+
+int
+main(int argc, char **argv)
+{
+    tu_config.tc_print_results = 1;
+    tu_init();
+
+    conf_init();
+    config_test_all();
+
+    return tu_any_failed;
+}
+
+#endif

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/d98ddc1c/sys/config/test/src/config_test.h
----------------------------------------------------------------------
diff --git a/sys/config/test/src/config_test.h b/sys/config/test/src/config_test.h
new file mode 100644
index 0000000..da531af
--- /dev/null
+++ b/sys/config/test/src/config_test.h
@@ -0,0 +1,24 @@
+/**
+ * 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 _CONFIG_TEST_H_
+#define _CONFIG_TEST_H_
+
+int config_test_all();
+
+#endif

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/d98ddc1c/sys/coredump/pkg.yml
----------------------------------------------------------------------
diff --git a/sys/coredump/pkg.yml b/sys/coredump/pkg.yml
index b4f05a0..3da1277 100644
--- a/sys/coredump/pkg.yml
+++ b/sys/coredump/pkg.yml
@@ -28,5 +28,3 @@ pkg.deps:
     - hw/hal
     - libs/bootutil
     - libs/imgmgr
-pkg.features:
-    - COREDUMP

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/d98ddc1c/sys/fcb/pkg.yml
----------------------------------------------------------------------
diff --git a/sys/fcb/pkg.yml b/sys/fcb/pkg.yml
index 6cbfb28..bba5355 100644
--- a/sys/fcb/pkg.yml
+++ b/sys/fcb/pkg.yml
@@ -26,6 +26,3 @@ pkg.keywords:
 
 pkg.deps:
     - libs/os
-    - libs/testutil
-pkg.features:
-    - FCB

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/d98ddc1c/sys/fcb/src/test/fcb_test.c
----------------------------------------------------------------------
diff --git a/sys/fcb/src/test/fcb_test.c b/sys/fcb/src/test/fcb_test.c
deleted file mode 100644
index b0de576..0000000
--- a/sys/fcb/src/test/fcb_test.c
+++ /dev/null
@@ -1,671 +0,0 @@
-/**
- * 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 <string.h>
-
-#include <os/os.h>
-#include <testutil/testutil.h>
-
-#include "fcb/fcb.h"
-#include "fcb/../../src/fcb_priv.h"
-
-static struct fcb test_fcb;
-
-static struct flash_area test_fcb_area[] = {
-    [0] = {
-        .fa_flash_id = 0,
-        .fa_off = 0,
-        .fa_size = 0x4000, /* 16K */
-    },
-    [1] = {
-        .fa_flash_id = 0,
-        .fa_off = 0x4000,
-        .fa_size = 0x4000
-    },
-    [2] = {
-        .fa_flash_id = 0,
-        .fa_off = 0x8000,
-        .fa_size = 0x4000
-    },
-    [3] = {
-        .fa_flash_id = 0,
-        .fa_off = 0xc000,
-        .fa_size = 0x4000
-    }
-};
-
-static void
-fcb_test_wipe(void)
-{
-    int i;
-    int rc;
-    struct flash_area *fap;
-
-    for (i = 0; i < sizeof(test_fcb_area) / sizeof(test_fcb_area[0]); i++) {
-        fap = &test_fcb_area[i];
-        rc = flash_area_erase(fap, 0, fap->fa_size);
-        TEST_ASSERT(rc == 0);
-    }
-}
-
-TEST_CASE(fcb_test_len)
-{
-    uint8_t buf[3];
-    uint16_t len;
-    uint16_t len2;
-    int rc;
-
-    for (len = 0; len < FCB_MAX_LEN; len++) {
-        rc = fcb_put_len(buf, len);
-        TEST_ASSERT(rc == 1 || rc == 2);
-
-        rc = fcb_get_len(buf, &len2);
-        TEST_ASSERT(rc == 1 || rc == 2);
-
-        TEST_ASSERT(len == len2);
-    }
-}
-
-TEST_CASE(fcb_test_init)
-{
-    int rc;
-    struct fcb *fcb;
-
-    fcb = &test_fcb;
-    memset(fcb, 0, sizeof(*fcb));
-
-    rc = fcb_init(fcb);
-    TEST_ASSERT(rc == FCB_ERR_ARGS);
-
-    fcb->f_sectors = test_fcb_area;
-
-    rc = fcb_init(fcb);
-    TEST_ASSERT(rc == FCB_ERR_ARGS);
-
-    fcb->f_sector_cnt = 2;
-    rc = fcb_init(fcb);
-    TEST_ASSERT(rc == 0);
-}
-
-static int
-fcb_test_empty_walk_cb(struct fcb_entry *loc, void *arg)
-{
-    TEST_ASSERT(0);
-    return 0;
-}
-
-TEST_CASE(fcb_test_empty_walk)
-{
-    int rc;
-    struct fcb *fcb;
-
-    fcb_test_wipe();
-    fcb = &test_fcb;
-    memset(fcb, 0, sizeof(*fcb));
-
-    fcb->f_sector_cnt = 2;
-    fcb->f_sectors = test_fcb_area;
-
-    rc = fcb_init(fcb);
-    TEST_ASSERT(rc == 0);
-
-    rc = fcb_walk(fcb, 0, fcb_test_empty_walk_cb, NULL);
-    TEST_ASSERT(rc == 0);
-}
-
-static uint8_t
-fcb_test_append_data(int msg_len, int off)
-{
-    return (msg_len ^ off);
-}
-
-static int
-fcb_test_data_walk_cb(struct fcb_entry *loc, void *arg)
-{
-    uint16_t len;
-    uint8_t test_data[128];
-    int rc;
-    int i;
-    int *var_cnt = (int *)arg;
-
-    len = loc->fe_data_len;
-
-    TEST_ASSERT(len == *var_cnt);
-
-    rc = flash_area_read(loc->fe_area, loc->fe_data_off, test_data, len);
-    TEST_ASSERT(rc == 0);
-
-    for (i = 0; i < len; i++) {
-        TEST_ASSERT(test_data[i] == fcb_test_append_data(len, i));
-    }
-    (*var_cnt)++;
-    return 0;
-}
-
-TEST_CASE(fcb_test_append)
-{
-    int rc;
-    struct fcb *fcb;
-    struct fcb_entry loc;
-    uint8_t test_data[128];
-    int i;
-    int j;
-    int var_cnt;
-
-    fcb_test_wipe();
-    fcb = &test_fcb;
-    memset(fcb, 0, sizeof(*fcb));
-    fcb->f_sector_cnt = 2;
-    fcb->f_sectors = test_fcb_area;
-
-    rc = fcb_init(fcb);
-    TEST_ASSERT(rc == 0);
-
-    for (i = 0; i < sizeof(test_data); i++) {
-        for (j = 0; j < i; j++) {
-            test_data[j] = fcb_test_append_data(i, j);
-        }
-        rc = fcb_append(fcb, i, &loc);
-        TEST_ASSERT_FATAL(rc == 0);
-        rc = flash_area_write(loc.fe_area, loc.fe_data_off, test_data, i);
-        TEST_ASSERT(rc == 0);
-        rc = fcb_append_finish(fcb, &loc);
-        TEST_ASSERT(rc == 0);
-    }
-
-    var_cnt = 0;
-    rc = fcb_walk(fcb, 0, fcb_test_data_walk_cb, &var_cnt);
-    TEST_ASSERT(rc == 0);
-    TEST_ASSERT(var_cnt == sizeof(test_data));
-}
-
-TEST_CASE(fcb_test_append_too_big)
-{
-    struct fcb *fcb;
-    int rc;
-    int len;
-    struct fcb_entry elem_loc;
-
-    fcb_test_wipe();
-    fcb = &test_fcb;
-    memset(fcb, 0, sizeof(*fcb));
-    fcb->f_sector_cnt = 2;
-    fcb->f_sectors = test_fcb_area;
-
-    rc = fcb_init(fcb);
-    TEST_ASSERT(rc == 0);
-
-    /*
-     * Max element which fits inside sector is
-     * sector size - (disk header + crc + 1-2 bytes of length).
-     */
-    len = fcb->f_active.fe_area->fa_size;
-
-    rc = fcb_append(fcb, len, &elem_loc);
-    TEST_ASSERT(rc != 0);
-
-    len--;
-    rc = fcb_append(fcb, len, &elem_loc);
-    TEST_ASSERT(rc != 0);
-
-    len -= sizeof(struct fcb_disk_area);
-    rc = fcb_append(fcb, len, &elem_loc);
-    TEST_ASSERT(rc != 0);
-
-    len = fcb->f_active.fe_area->fa_size -
-      (sizeof(struct fcb_disk_area) + 1 + 2);
-    rc = fcb_append(fcb, len, &elem_loc);
-    TEST_ASSERT(rc == 0);
-
-    rc = fcb_append_finish(fcb, &elem_loc);
-    TEST_ASSERT(rc == 0);
-
-    rc = fcb_elem_info(fcb, &elem_loc);
-    TEST_ASSERT(rc == 0);
-    TEST_ASSERT(elem_loc.fe_data_len == len);
-}
-
-struct append_arg {
-    int *elem_cnts;
-};
-
-static int
-fcb_test_cnt_elems_cb(struct fcb_entry *loc, void *arg)
-{
-    struct append_arg *aa = (struct append_arg *)arg;
-    int idx;
-
-    idx = loc->fe_area - &test_fcb_area[0];
-    aa->elem_cnts[idx]++;
-    return 0;
-}
-
-TEST_CASE(fcb_test_append_fill)
-{
-    struct fcb *fcb;
-    int rc;
-    int i;
-    struct fcb_entry loc;
-    uint8_t test_data[128];
-    int elem_cnts[2] = {0, 0};
-    int aa_together_cnts[2];
-    struct append_arg aa_together = {
-        .elem_cnts = aa_together_cnts
-    };
-    int aa_separate_cnts[2];
-    struct append_arg aa_separate = {
-        .elem_cnts = aa_separate_cnts
-    };
-
-    fcb_test_wipe();
-    fcb = &test_fcb;
-    memset(fcb, 0, sizeof(*fcb));
-    fcb->f_sector_cnt = 2;
-    fcb->f_sectors = test_fcb_area;
-
-    rc = fcb_init(fcb);
-    TEST_ASSERT(rc == 0);
-
-    for (i = 0; i < sizeof(test_data); i++) {
-        test_data[i] = fcb_test_append_data(sizeof(test_data), i);
-    }
-
-    while (1) {
-        rc = fcb_append(fcb, sizeof(test_data), &loc);
-        if (rc == FCB_ERR_NOSPACE) {
-            break;
-        }
-        if (loc.fe_area == &test_fcb_area[0]) {
-            elem_cnts[0]++;
-        } else if (loc.fe_area == &test_fcb_area[1]) {
-            elem_cnts[1]++;
-        } else {
-            TEST_ASSERT(0);
-        }
-
-        rc = flash_area_write(loc.fe_area, loc.fe_data_off, test_data,
-          sizeof(test_data));
-        TEST_ASSERT(rc == 0);
-
-        rc = fcb_append_finish(fcb, &loc);
-        TEST_ASSERT(rc == 0);
-    }
-    TEST_ASSERT(elem_cnts[0] > 0);
-    TEST_ASSERT(elem_cnts[0] == elem_cnts[1]);
-
-    memset(&aa_together_cnts, 0, sizeof(aa_together_cnts));
-    rc = fcb_walk(fcb, NULL, fcb_test_cnt_elems_cb, &aa_together);
-    TEST_ASSERT(rc == 0);
-    TEST_ASSERT(aa_together.elem_cnts[0] == elem_cnts[0]);
-    TEST_ASSERT(aa_together.elem_cnts[1] == elem_cnts[1]);
-
-    memset(&aa_separate_cnts, 0, sizeof(aa_separate_cnts));
-    rc = fcb_walk(fcb, &test_fcb_area[0], fcb_test_cnt_elems_cb,
-      &aa_separate);
-    TEST_ASSERT(rc == 0);
-    rc = fcb_walk(fcb, &test_fcb_area[1], fcb_test_cnt_elems_cb,
-      &aa_separate);
-    TEST_ASSERT(rc == 0);
-    TEST_ASSERT(aa_separate.elem_cnts[0] == elem_cnts[0]);
-    TEST_ASSERT(aa_separate.elem_cnts[1] == elem_cnts[1]);
-
-}
-
-TEST_CASE(fcb_test_reset)
-{
-    struct fcb *fcb;
-    int rc;
-    int i;
-    struct fcb_entry loc;
-    uint8_t test_data[128];
-    int var_cnt;
-
-    fcb_test_wipe();
-    fcb = &test_fcb;
-    memset(fcb, 0, sizeof(*fcb));
-    fcb->f_sector_cnt = 2;
-    fcb->f_sectors = test_fcb_area;
-
-    rc = fcb_init(fcb);
-    TEST_ASSERT(rc == 0);
-
-    var_cnt = 0;
-    rc = fcb_walk(fcb, 0, fcb_test_data_walk_cb, &var_cnt);
-    TEST_ASSERT(rc == 0);
-    TEST_ASSERT(var_cnt == 0);
-
-    rc = fcb_append(fcb, 32, &loc);
-    TEST_ASSERT(rc == 0);
-
-    /*
-     * No ready ones yet. CRC should not match.
-     */
-    var_cnt = 0;
-    rc = fcb_walk(fcb, 0, fcb_test_data_walk_cb, &var_cnt);
-    TEST_ASSERT(rc == 0);
-    TEST_ASSERT(var_cnt == 0);
-
-    for (i = 0; i < sizeof(test_data); i++) {
-        test_data[i] = fcb_test_append_data(32, i);
-    }
-    rc = flash_area_write(loc.fe_area, loc.fe_data_off, test_data, 32);
-    TEST_ASSERT(rc == 0);
-
-    rc = fcb_append_finish(fcb, &loc);
-    TEST_ASSERT(rc == 0);
-
-    /*
-     * one entry
-     */
-    var_cnt = 32;
-    rc = fcb_walk(fcb, 0, fcb_test_data_walk_cb, &var_cnt);
-    TEST_ASSERT(rc == 0);
-    TEST_ASSERT(var_cnt == 33);
-
-    /*
-     * Pretend reset
-     */
-    memset(fcb, 0, sizeof(*fcb));
-    fcb->f_sector_cnt = 2;
-    fcb->f_sectors = test_fcb_area;
-
-    rc = fcb_init(fcb);
-    TEST_ASSERT(rc == 0);
-
-    var_cnt = 32;
-    rc = fcb_walk(fcb, 0, fcb_test_data_walk_cb, &var_cnt);
-    TEST_ASSERT(rc == 0);
-    TEST_ASSERT(var_cnt == 33);
-
-    rc = fcb_append(fcb, 33, &loc);
-    TEST_ASSERT(rc == 0);
-
-    for (i = 0; i < sizeof(test_data); i++) {
-        test_data[i] = fcb_test_append_data(33, i);
-    }
-    rc = flash_area_write(loc.fe_area, loc.fe_data_off, test_data, 33);
-    TEST_ASSERT(rc == 0);
-
-    rc = fcb_append_finish(fcb, &loc);
-    TEST_ASSERT(rc == 0);
-
-    var_cnt = 32;
-    rc = fcb_walk(fcb, 0, fcb_test_data_walk_cb, &var_cnt);
-    TEST_ASSERT(rc == 0);
-    TEST_ASSERT(var_cnt == 34);
-
-    /*
-     * Add partial one, make sure that we survive reset then.
-     */
-    rc = fcb_append(fcb, 34, &loc);
-    TEST_ASSERT(rc == 0);
-
-    memset(fcb, 0, sizeof(*fcb));
-    fcb->f_sector_cnt = 2;
-    fcb->f_sectors = test_fcb_area;
-
-    rc = fcb_init(fcb);
-    TEST_ASSERT(rc == 0);
-
-    /*
-     * Walk should skip that.
-     */
-    var_cnt = 32;
-    rc = fcb_walk(fcb, 0, fcb_test_data_walk_cb, &var_cnt);
-    TEST_ASSERT(rc == 0);
-    TEST_ASSERT(var_cnt == 34);
-
-    /* Add a 3rd one, should go behind corrupt entry */
-    rc = fcb_append(fcb, 34, &loc);
-    TEST_ASSERT(rc == 0);
-
-    for (i = 0; i < sizeof(test_data); i++) {
-        test_data[i] = fcb_test_append_data(34, i);
-    }
-    rc = flash_area_write(loc.fe_area, loc.fe_data_off, test_data, 34);
-    TEST_ASSERT(rc == 0);
-
-    rc = fcb_append_finish(fcb, &loc);
-    TEST_ASSERT(rc == 0);
-
-    /*
-     * Walk should skip corrupt entry, but report the next one.
-     */
-    var_cnt = 32;
-    rc = fcb_walk(fcb, 0, fcb_test_data_walk_cb, &var_cnt);
-    TEST_ASSERT(rc == 0);
-    TEST_ASSERT(var_cnt == 35);
-}
-
-TEST_CASE(fcb_test_rotate)
-{
-    struct fcb *fcb;
-    int rc;
-    int old_id;
-    struct fcb_entry loc;
-    uint8_t test_data[128];
-    int elem_cnts[2] = {0, 0};
-    int cnts[2];
-    struct append_arg aa_arg = {
-        .elem_cnts = cnts
-    };
-
-    fcb_test_wipe();
-    fcb = &test_fcb;
-    memset(fcb, 0, sizeof(*fcb));
-    fcb->f_sector_cnt = 2;
-    fcb->f_sectors = test_fcb_area;
-
-    rc = fcb_init(fcb);
-    TEST_ASSERT(rc == 0);
-
-    old_id = fcb->f_active_id;
-    rc = fcb_rotate(fcb);
-    TEST_ASSERT(rc == 0);
-    TEST_ASSERT(fcb->f_active_id == old_id + 1);
-
-    /*
-     * Now fill up the
-     */
-    while (1) {
-        rc = fcb_append(fcb, sizeof(test_data), &loc);
-        if (rc == FCB_ERR_NOSPACE) {
-            break;
-        }
-        if (loc.fe_area == &test_fcb_area[0]) {
-            elem_cnts[0]++;
-        } else if (loc.fe_area == &test_fcb_area[1]) {
-            elem_cnts[1]++;
-        } else {
-            TEST_ASSERT(0);
-        }
-
-        rc = flash_area_write(loc.fe_area, loc.fe_data_off, test_data,
-          sizeof(test_data));
-        TEST_ASSERT(rc == 0);
-
-        rc = fcb_append_finish(fcb, &loc);
-        TEST_ASSERT(rc == 0);
-    }
-    TEST_ASSERT(elem_cnts[0] > 0 && elem_cnts[0] == elem_cnts[1]);
-
-    old_id = fcb->f_active_id;
-    rc = fcb_rotate(fcb);
-    TEST_ASSERT(rc == 0);
-    TEST_ASSERT(fcb->f_active_id == old_id); /* no new area created */
-
-    memset(cnts, 0, sizeof(cnts));
-    rc = fcb_walk(fcb, NULL, fcb_test_cnt_elems_cb, &aa_arg);
-    TEST_ASSERT(rc == 0);
-    TEST_ASSERT(aa_arg.elem_cnts[0] == elem_cnts[0] ||
-      aa_arg.elem_cnts[1] == elem_cnts[1]);
-    TEST_ASSERT(aa_arg.elem_cnts[0] == 0 || aa_arg.elem_cnts[1] == 0);
-
-    /*
-     * One sector is full. The other one should have one entry in it.
-     */
-    rc = fcb_append(fcb, sizeof(test_data), &loc);
-    TEST_ASSERT(rc == 0);
-
-    rc = flash_area_write(loc.fe_area, loc.fe_data_off, test_data,
-      sizeof(test_data));
-    TEST_ASSERT(rc == 0);
-
-    rc = fcb_append_finish(fcb, &loc);
-    TEST_ASSERT(rc == 0);
-
-    old_id = fcb->f_active_id;
-    rc = fcb_rotate(fcb);
-    TEST_ASSERT(rc == 0);
-    TEST_ASSERT(fcb->f_active_id == old_id);
-
-    memset(cnts, 0, sizeof(cnts));
-    rc = fcb_walk(fcb, NULL, fcb_test_cnt_elems_cb, &aa_arg);
-    TEST_ASSERT(rc == 0);
-    TEST_ASSERT(aa_arg.elem_cnts[0] == 1 || aa_arg.elem_cnts[1] == 1);
-    TEST_ASSERT(aa_arg.elem_cnts[0] == 0 || aa_arg.elem_cnts[1] == 0);
-}
-
-TEST_CASE(fcb_test_multiple_scratch)
-{
-    struct fcb *fcb;
-    int rc;
-    struct fcb_entry loc;
-    uint8_t test_data[128];
-    int elem_cnts[4];
-    int idx;
-    int cnts[4];
-    struct append_arg aa_arg = {
-        .elem_cnts = cnts
-    };
-
-    fcb_test_wipe();
-    fcb = &test_fcb;
-    memset(fcb, 0, sizeof(*fcb));
-    fcb->f_sector_cnt = 4;
-    fcb->f_scratch_cnt = 1;
-    fcb->f_sectors = test_fcb_area;
-
-    rc = fcb_init(fcb);
-    TEST_ASSERT(rc == 0);
-
-    /*
-     * Now fill up everything. We should be able to get 3 of the sectors
-     * full.
-     */
-    memset(elem_cnts, 0, sizeof(elem_cnts));
-    while (1) {
-        rc = fcb_append(fcb, sizeof(test_data), &loc);
-        if (rc == FCB_ERR_NOSPACE) {
-            break;
-        }
-        idx = loc.fe_area - &test_fcb_area[0];
-        elem_cnts[idx]++;
-
-        rc = flash_area_write(loc.fe_area, loc.fe_data_off, test_data,
-          sizeof(test_data));
-        TEST_ASSERT(rc == 0);
-
-        rc = fcb_append_finish(fcb, &loc);
-        TEST_ASSERT(rc == 0);
-    }
-
-    TEST_ASSERT(elem_cnts[0] > 0);
-    TEST_ASSERT(elem_cnts[0] == elem_cnts[1] && elem_cnts[0] == elem_cnts[2]);
-    TEST_ASSERT(elem_cnts[3] == 0);
-
-    /*
-     * Ask to use scratch block, then fill it up.
-     */
-    rc = fcb_append_to_scratch(fcb);
-    TEST_ASSERT(rc == 0);
-
-    while (1) {
-        rc = fcb_append(fcb, sizeof(test_data), &loc);
-        if (rc == FCB_ERR_NOSPACE) {
-            break;
-        }
-        idx = loc.fe_area - &test_fcb_area[0];
-        elem_cnts[idx]++;
-
-        rc = flash_area_write(loc.fe_area, loc.fe_data_off, test_data,
-          sizeof(test_data));
-        TEST_ASSERT(rc == 0);
-
-        rc = fcb_append_finish(fcb, &loc);
-        TEST_ASSERT(rc == 0);
-    }
-    TEST_ASSERT(elem_cnts[3] == elem_cnts[0]);
-
-    /*
-     * Rotate
-     */
-    rc = fcb_rotate(fcb);
-    TEST_ASSERT(rc == 0);
-
-    memset(&cnts, 0, sizeof(cnts));
-    rc = fcb_walk(fcb, NULL, fcb_test_cnt_elems_cb, &aa_arg);
-    TEST_ASSERT(rc == 0);
-
-    TEST_ASSERT(cnts[0] == 0);
-    TEST_ASSERT(cnts[1] > 0);
-    TEST_ASSERT(cnts[1] == cnts[2] && cnts[1] == cnts[3]);
-
-    rc = fcb_append_to_scratch(fcb);
-    TEST_ASSERT(rc == 0);
-    rc = fcb_append_to_scratch(fcb);
-    TEST_ASSERT(rc != 0);
-}
-
-TEST_SUITE(fcb_test_all)
-{
-    fcb_test_len();
-
-    fcb_test_init();
-
-    fcb_test_empty_walk();
-
-    fcb_test_append();
-
-    fcb_test_append_too_big();
-
-    fcb_test_append_fill();
-
-    fcb_test_reset();
-
-    fcb_test_rotate();
-
-    fcb_test_multiple_scratch();
-}
-
-#ifdef MYNEWT_SELFTEST
-
-int
-main(int argc, char **argv)
-{
-    tu_config.tc_print_results = 1;
-    tu_init();
-
-    fcb_test_all();
-
-    return tu_any_failed;
-}
-#endif
-

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/d98ddc1c/sys/fcb/test/pkg.yml
----------------------------------------------------------------------
diff --git a/sys/fcb/test/pkg.yml b/sys/fcb/test/pkg.yml
new file mode 100644
index 0000000..31a8669
--- /dev/null
+++ b/sys/fcb/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: sys/fcb/test
+pkg.type: unittest
+pkg.description: "FCB unit tests."
+pkg.author: "Apache Mynewt <de...@mynewt.incubator.apache.org>"
+pkg.homepage: "http://mynewt.apache.org/"
+pkg.keywords:
+
+pkg.deps: 
+    - libs/testutil
+    - sys/fcb
+
+pkg.deps.SELFTEST:
+    - libs/console/stub

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/d98ddc1c/sys/fcb/test/src/fcb_test.c
----------------------------------------------------------------------
diff --git a/sys/fcb/test/src/fcb_test.c b/sys/fcb/test/src/fcb_test.c
new file mode 100644
index 0000000..b172eb0
--- /dev/null
+++ b/sys/fcb/test/src/fcb_test.c
@@ -0,0 +1,672 @@
+/**
+ * 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 <string.h>
+
+#include "syscfg/syscfg.h"
+#include "os/os.h"
+#include "testutil/testutil.h"
+
+#include "fcb/fcb.h"
+#include "fcb/../../src/fcb_priv.h"
+
+static struct fcb test_fcb;
+
+static struct flash_area test_fcb_area[] = {
+    [0] = {
+        .fa_flash_id = 0,
+        .fa_off = 0,
+        .fa_size = 0x4000, /* 16K */
+    },
+    [1] = {
+        .fa_flash_id = 0,
+        .fa_off = 0x4000,
+        .fa_size = 0x4000
+    },
+    [2] = {
+        .fa_flash_id = 0,
+        .fa_off = 0x8000,
+        .fa_size = 0x4000
+    },
+    [3] = {
+        .fa_flash_id = 0,
+        .fa_off = 0xc000,
+        .fa_size = 0x4000
+    }
+};
+
+static void
+fcb_test_wipe(void)
+{
+    int i;
+    int rc;
+    struct flash_area *fap;
+
+    for (i = 0; i < sizeof(test_fcb_area) / sizeof(test_fcb_area[0]); i++) {
+        fap = &test_fcb_area[i];
+        rc = flash_area_erase(fap, 0, fap->fa_size);
+        TEST_ASSERT(rc == 0);
+    }
+}
+
+TEST_CASE(fcb_test_len)
+{
+    uint8_t buf[3];
+    uint16_t len;
+    uint16_t len2;
+    int rc;
+
+    for (len = 0; len < FCB_MAX_LEN; len++) {
+        rc = fcb_put_len(buf, len);
+        TEST_ASSERT(rc == 1 || rc == 2);
+
+        rc = fcb_get_len(buf, &len2);
+        TEST_ASSERT(rc == 1 || rc == 2);
+
+        TEST_ASSERT(len == len2);
+    }
+}
+
+TEST_CASE(fcb_test_init)
+{
+    int rc;
+    struct fcb *fcb;
+
+    fcb = &test_fcb;
+    memset(fcb, 0, sizeof(*fcb));
+
+    rc = fcb_init(fcb);
+    TEST_ASSERT(rc == FCB_ERR_ARGS);
+
+    fcb->f_sectors = test_fcb_area;
+
+    rc = fcb_init(fcb);
+    TEST_ASSERT(rc == FCB_ERR_ARGS);
+
+    fcb->f_sector_cnt = 2;
+    rc = fcb_init(fcb);
+    TEST_ASSERT(rc == 0);
+}
+
+static int
+fcb_test_empty_walk_cb(struct fcb_entry *loc, void *arg)
+{
+    TEST_ASSERT(0);
+    return 0;
+}
+
+TEST_CASE(fcb_test_empty_walk)
+{
+    int rc;
+    struct fcb *fcb;
+
+    fcb_test_wipe();
+    fcb = &test_fcb;
+    memset(fcb, 0, sizeof(*fcb));
+
+    fcb->f_sector_cnt = 2;
+    fcb->f_sectors = test_fcb_area;
+
+    rc = fcb_init(fcb);
+    TEST_ASSERT(rc == 0);
+
+    rc = fcb_walk(fcb, 0, fcb_test_empty_walk_cb, NULL);
+    TEST_ASSERT(rc == 0);
+}
+
+static uint8_t
+fcb_test_append_data(int msg_len, int off)
+{
+    return (msg_len ^ off);
+}
+
+static int
+fcb_test_data_walk_cb(struct fcb_entry *loc, void *arg)
+{
+    uint16_t len;
+    uint8_t test_data[128];
+    int rc;
+    int i;
+    int *var_cnt = (int *)arg;
+
+    len = loc->fe_data_len;
+
+    TEST_ASSERT(len == *var_cnt);
+
+    rc = flash_area_read(loc->fe_area, loc->fe_data_off, test_data, len);
+    TEST_ASSERT(rc == 0);
+
+    for (i = 0; i < len; i++) {
+        TEST_ASSERT(test_data[i] == fcb_test_append_data(len, i));
+    }
+    (*var_cnt)++;
+    return 0;
+}
+
+TEST_CASE(fcb_test_append)
+{
+    int rc;
+    struct fcb *fcb;
+    struct fcb_entry loc;
+    uint8_t test_data[128];
+    int i;
+    int j;
+    int var_cnt;
+
+    fcb_test_wipe();
+    fcb = &test_fcb;
+    memset(fcb, 0, sizeof(*fcb));
+    fcb->f_sector_cnt = 2;
+    fcb->f_sectors = test_fcb_area;
+
+    rc = fcb_init(fcb);
+    TEST_ASSERT(rc == 0);
+
+    for (i = 0; i < sizeof(test_data); i++) {
+        for (j = 0; j < i; j++) {
+            test_data[j] = fcb_test_append_data(i, j);
+        }
+        rc = fcb_append(fcb, i, &loc);
+        TEST_ASSERT_FATAL(rc == 0);
+        rc = flash_area_write(loc.fe_area, loc.fe_data_off, test_data, i);
+        TEST_ASSERT(rc == 0);
+        rc = fcb_append_finish(fcb, &loc);
+        TEST_ASSERT(rc == 0);
+    }
+
+    var_cnt = 0;
+    rc = fcb_walk(fcb, 0, fcb_test_data_walk_cb, &var_cnt);
+    TEST_ASSERT(rc == 0);
+    TEST_ASSERT(var_cnt == sizeof(test_data));
+}
+
+TEST_CASE(fcb_test_append_too_big)
+{
+    struct fcb *fcb;
+    int rc;
+    int len;
+    struct fcb_entry elem_loc;
+
+    fcb_test_wipe();
+    fcb = &test_fcb;
+    memset(fcb, 0, sizeof(*fcb));
+    fcb->f_sector_cnt = 2;
+    fcb->f_sectors = test_fcb_area;
+
+    rc = fcb_init(fcb);
+    TEST_ASSERT(rc == 0);
+
+    /*
+     * Max element which fits inside sector is
+     * sector size - (disk header + crc + 1-2 bytes of length).
+     */
+    len = fcb->f_active.fe_area->fa_size;
+
+    rc = fcb_append(fcb, len, &elem_loc);
+    TEST_ASSERT(rc != 0);
+
+    len--;
+    rc = fcb_append(fcb, len, &elem_loc);
+    TEST_ASSERT(rc != 0);
+
+    len -= sizeof(struct fcb_disk_area);
+    rc = fcb_append(fcb, len, &elem_loc);
+    TEST_ASSERT(rc != 0);
+
+    len = fcb->f_active.fe_area->fa_size -
+      (sizeof(struct fcb_disk_area) + 1 + 2);
+    rc = fcb_append(fcb, len, &elem_loc);
+    TEST_ASSERT(rc == 0);
+
+    rc = fcb_append_finish(fcb, &elem_loc);
+    TEST_ASSERT(rc == 0);
+
+    rc = fcb_elem_info(fcb, &elem_loc);
+    TEST_ASSERT(rc == 0);
+    TEST_ASSERT(elem_loc.fe_data_len == len);
+}
+
+struct append_arg {
+    int *elem_cnts;
+};
+
+static int
+fcb_test_cnt_elems_cb(struct fcb_entry *loc, void *arg)
+{
+    struct append_arg *aa = (struct append_arg *)arg;
+    int idx;
+
+    idx = loc->fe_area - &test_fcb_area[0];
+    aa->elem_cnts[idx]++;
+    return 0;
+}
+
+TEST_CASE(fcb_test_append_fill)
+{
+    struct fcb *fcb;
+    int rc;
+    int i;
+    struct fcb_entry loc;
+    uint8_t test_data[128];
+    int elem_cnts[2] = {0, 0};
+    int aa_together_cnts[2];
+    struct append_arg aa_together = {
+        .elem_cnts = aa_together_cnts
+    };
+    int aa_separate_cnts[2];
+    struct append_arg aa_separate = {
+        .elem_cnts = aa_separate_cnts
+    };
+
+    fcb_test_wipe();
+    fcb = &test_fcb;
+    memset(fcb, 0, sizeof(*fcb));
+    fcb->f_sector_cnt = 2;
+    fcb->f_sectors = test_fcb_area;
+
+    rc = fcb_init(fcb);
+    TEST_ASSERT(rc == 0);
+
+    for (i = 0; i < sizeof(test_data); i++) {
+        test_data[i] = fcb_test_append_data(sizeof(test_data), i);
+    }
+
+    while (1) {
+        rc = fcb_append(fcb, sizeof(test_data), &loc);
+        if (rc == FCB_ERR_NOSPACE) {
+            break;
+        }
+        if (loc.fe_area == &test_fcb_area[0]) {
+            elem_cnts[0]++;
+        } else if (loc.fe_area == &test_fcb_area[1]) {
+            elem_cnts[1]++;
+        } else {
+            TEST_ASSERT(0);
+        }
+
+        rc = flash_area_write(loc.fe_area, loc.fe_data_off, test_data,
+          sizeof(test_data));
+        TEST_ASSERT(rc == 0);
+
+        rc = fcb_append_finish(fcb, &loc);
+        TEST_ASSERT(rc == 0);
+    }
+    TEST_ASSERT(elem_cnts[0] > 0);
+    TEST_ASSERT(elem_cnts[0] == elem_cnts[1]);
+
+    memset(&aa_together_cnts, 0, sizeof(aa_together_cnts));
+    rc = fcb_walk(fcb, NULL, fcb_test_cnt_elems_cb, &aa_together);
+    TEST_ASSERT(rc == 0);
+    TEST_ASSERT(aa_together.elem_cnts[0] == elem_cnts[0]);
+    TEST_ASSERT(aa_together.elem_cnts[1] == elem_cnts[1]);
+
+    memset(&aa_separate_cnts, 0, sizeof(aa_separate_cnts));
+    rc = fcb_walk(fcb, &test_fcb_area[0], fcb_test_cnt_elems_cb,
+      &aa_separate);
+    TEST_ASSERT(rc == 0);
+    rc = fcb_walk(fcb, &test_fcb_area[1], fcb_test_cnt_elems_cb,
+      &aa_separate);
+    TEST_ASSERT(rc == 0);
+    TEST_ASSERT(aa_separate.elem_cnts[0] == elem_cnts[0]);
+    TEST_ASSERT(aa_separate.elem_cnts[1] == elem_cnts[1]);
+
+}
+
+TEST_CASE(fcb_test_reset)
+{
+    struct fcb *fcb;
+    int rc;
+    int i;
+    struct fcb_entry loc;
+    uint8_t test_data[128];
+    int var_cnt;
+
+    fcb_test_wipe();
+    fcb = &test_fcb;
+    memset(fcb, 0, sizeof(*fcb));
+    fcb->f_sector_cnt = 2;
+    fcb->f_sectors = test_fcb_area;
+
+    rc = fcb_init(fcb);
+    TEST_ASSERT(rc == 0);
+
+    var_cnt = 0;
+    rc = fcb_walk(fcb, 0, fcb_test_data_walk_cb, &var_cnt);
+    TEST_ASSERT(rc == 0);
+    TEST_ASSERT(var_cnt == 0);
+
+    rc = fcb_append(fcb, 32, &loc);
+    TEST_ASSERT(rc == 0);
+
+    /*
+     * No ready ones yet. CRC should not match.
+     */
+    var_cnt = 0;
+    rc = fcb_walk(fcb, 0, fcb_test_data_walk_cb, &var_cnt);
+    TEST_ASSERT(rc == 0);
+    TEST_ASSERT(var_cnt == 0);
+
+    for (i = 0; i < sizeof(test_data); i++) {
+        test_data[i] = fcb_test_append_data(32, i);
+    }
+    rc = flash_area_write(loc.fe_area, loc.fe_data_off, test_data, 32);
+    TEST_ASSERT(rc == 0);
+
+    rc = fcb_append_finish(fcb, &loc);
+    TEST_ASSERT(rc == 0);
+
+    /*
+     * one entry
+     */
+    var_cnt = 32;
+    rc = fcb_walk(fcb, 0, fcb_test_data_walk_cb, &var_cnt);
+    TEST_ASSERT(rc == 0);
+    TEST_ASSERT(var_cnt == 33);
+
+    /*
+     * Pretend reset
+     */
+    memset(fcb, 0, sizeof(*fcb));
+    fcb->f_sector_cnt = 2;
+    fcb->f_sectors = test_fcb_area;
+
+    rc = fcb_init(fcb);
+    TEST_ASSERT(rc == 0);
+
+    var_cnt = 32;
+    rc = fcb_walk(fcb, 0, fcb_test_data_walk_cb, &var_cnt);
+    TEST_ASSERT(rc == 0);
+    TEST_ASSERT(var_cnt == 33);
+
+    rc = fcb_append(fcb, 33, &loc);
+    TEST_ASSERT(rc == 0);
+
+    for (i = 0; i < sizeof(test_data); i++) {
+        test_data[i] = fcb_test_append_data(33, i);
+    }
+    rc = flash_area_write(loc.fe_area, loc.fe_data_off, test_data, 33);
+    TEST_ASSERT(rc == 0);
+
+    rc = fcb_append_finish(fcb, &loc);
+    TEST_ASSERT(rc == 0);
+
+    var_cnt = 32;
+    rc = fcb_walk(fcb, 0, fcb_test_data_walk_cb, &var_cnt);
+    TEST_ASSERT(rc == 0);
+    TEST_ASSERT(var_cnt == 34);
+
+    /*
+     * Add partial one, make sure that we survive reset then.
+     */
+    rc = fcb_append(fcb, 34, &loc);
+    TEST_ASSERT(rc == 0);
+
+    memset(fcb, 0, sizeof(*fcb));
+    fcb->f_sector_cnt = 2;
+    fcb->f_sectors = test_fcb_area;
+
+    rc = fcb_init(fcb);
+    TEST_ASSERT(rc == 0);
+
+    /*
+     * Walk should skip that.
+     */
+    var_cnt = 32;
+    rc = fcb_walk(fcb, 0, fcb_test_data_walk_cb, &var_cnt);
+    TEST_ASSERT(rc == 0);
+    TEST_ASSERT(var_cnt == 34);
+
+    /* Add a 3rd one, should go behind corrupt entry */
+    rc = fcb_append(fcb, 34, &loc);
+    TEST_ASSERT(rc == 0);
+
+    for (i = 0; i < sizeof(test_data); i++) {
+        test_data[i] = fcb_test_append_data(34, i);
+    }
+    rc = flash_area_write(loc.fe_area, loc.fe_data_off, test_data, 34);
+    TEST_ASSERT(rc == 0);
+
+    rc = fcb_append_finish(fcb, &loc);
+    TEST_ASSERT(rc == 0);
+
+    /*
+     * Walk should skip corrupt entry, but report the next one.
+     */
+    var_cnt = 32;
+    rc = fcb_walk(fcb, 0, fcb_test_data_walk_cb, &var_cnt);
+    TEST_ASSERT(rc == 0);
+    TEST_ASSERT(var_cnt == 35);
+}
+
+TEST_CASE(fcb_test_rotate)
+{
+    struct fcb *fcb;
+    int rc;
+    int old_id;
+    struct fcb_entry loc;
+    uint8_t test_data[128];
+    int elem_cnts[2] = {0, 0};
+    int cnts[2];
+    struct append_arg aa_arg = {
+        .elem_cnts = cnts
+    };
+
+    fcb_test_wipe();
+    fcb = &test_fcb;
+    memset(fcb, 0, sizeof(*fcb));
+    fcb->f_sector_cnt = 2;
+    fcb->f_sectors = test_fcb_area;
+
+    rc = fcb_init(fcb);
+    TEST_ASSERT(rc == 0);
+
+    old_id = fcb->f_active_id;
+    rc = fcb_rotate(fcb);
+    TEST_ASSERT(rc == 0);
+    TEST_ASSERT(fcb->f_active_id == old_id + 1);
+
+    /*
+     * Now fill up the
+     */
+    while (1) {
+        rc = fcb_append(fcb, sizeof(test_data), &loc);
+        if (rc == FCB_ERR_NOSPACE) {
+            break;
+        }
+        if (loc.fe_area == &test_fcb_area[0]) {
+            elem_cnts[0]++;
+        } else if (loc.fe_area == &test_fcb_area[1]) {
+            elem_cnts[1]++;
+        } else {
+            TEST_ASSERT(0);
+        }
+
+        rc = flash_area_write(loc.fe_area, loc.fe_data_off, test_data,
+          sizeof(test_data));
+        TEST_ASSERT(rc == 0);
+
+        rc = fcb_append_finish(fcb, &loc);
+        TEST_ASSERT(rc == 0);
+    }
+    TEST_ASSERT(elem_cnts[0] > 0 && elem_cnts[0] == elem_cnts[1]);
+
+    old_id = fcb->f_active_id;
+    rc = fcb_rotate(fcb);
+    TEST_ASSERT(rc == 0);
+    TEST_ASSERT(fcb->f_active_id == old_id); /* no new area created */
+
+    memset(cnts, 0, sizeof(cnts));
+    rc = fcb_walk(fcb, NULL, fcb_test_cnt_elems_cb, &aa_arg);
+    TEST_ASSERT(rc == 0);
+    TEST_ASSERT(aa_arg.elem_cnts[0] == elem_cnts[0] ||
+      aa_arg.elem_cnts[1] == elem_cnts[1]);
+    TEST_ASSERT(aa_arg.elem_cnts[0] == 0 || aa_arg.elem_cnts[1] == 0);
+
+    /*
+     * One sector is full. The other one should have one entry in it.
+     */
+    rc = fcb_append(fcb, sizeof(test_data), &loc);
+    TEST_ASSERT(rc == 0);
+
+    rc = flash_area_write(loc.fe_area, loc.fe_data_off, test_data,
+      sizeof(test_data));
+    TEST_ASSERT(rc == 0);
+
+    rc = fcb_append_finish(fcb, &loc);
+    TEST_ASSERT(rc == 0);
+
+    old_id = fcb->f_active_id;
+    rc = fcb_rotate(fcb);
+    TEST_ASSERT(rc == 0);
+    TEST_ASSERT(fcb->f_active_id == old_id);
+
+    memset(cnts, 0, sizeof(cnts));
+    rc = fcb_walk(fcb, NULL, fcb_test_cnt_elems_cb, &aa_arg);
+    TEST_ASSERT(rc == 0);
+    TEST_ASSERT(aa_arg.elem_cnts[0] == 1 || aa_arg.elem_cnts[1] == 1);
+    TEST_ASSERT(aa_arg.elem_cnts[0] == 0 || aa_arg.elem_cnts[1] == 0);
+}
+
+TEST_CASE(fcb_test_multiple_scratch)
+{
+    struct fcb *fcb;
+    int rc;
+    struct fcb_entry loc;
+    uint8_t test_data[128];
+    int elem_cnts[4];
+    int idx;
+    int cnts[4];
+    struct append_arg aa_arg = {
+        .elem_cnts = cnts
+    };
+
+    fcb_test_wipe();
+    fcb = &test_fcb;
+    memset(fcb, 0, sizeof(*fcb));
+    fcb->f_sector_cnt = 4;
+    fcb->f_scratch_cnt = 1;
+    fcb->f_sectors = test_fcb_area;
+
+    rc = fcb_init(fcb);
+    TEST_ASSERT(rc == 0);
+
+    /*
+     * Now fill up everything. We should be able to get 3 of the sectors
+     * full.
+     */
+    memset(elem_cnts, 0, sizeof(elem_cnts));
+    while (1) {
+        rc = fcb_append(fcb, sizeof(test_data), &loc);
+        if (rc == FCB_ERR_NOSPACE) {
+            break;
+        }
+        idx = loc.fe_area - &test_fcb_area[0];
+        elem_cnts[idx]++;
+
+        rc = flash_area_write(loc.fe_area, loc.fe_data_off, test_data,
+          sizeof(test_data));
+        TEST_ASSERT(rc == 0);
+
+        rc = fcb_append_finish(fcb, &loc);
+        TEST_ASSERT(rc == 0);
+    }
+
+    TEST_ASSERT(elem_cnts[0] > 0);
+    TEST_ASSERT(elem_cnts[0] == elem_cnts[1] && elem_cnts[0] == elem_cnts[2]);
+    TEST_ASSERT(elem_cnts[3] == 0);
+
+    /*
+     * Ask to use scratch block, then fill it up.
+     */
+    rc = fcb_append_to_scratch(fcb);
+    TEST_ASSERT(rc == 0);
+
+    while (1) {
+        rc = fcb_append(fcb, sizeof(test_data), &loc);
+        if (rc == FCB_ERR_NOSPACE) {
+            break;
+        }
+        idx = loc.fe_area - &test_fcb_area[0];
+        elem_cnts[idx]++;
+
+        rc = flash_area_write(loc.fe_area, loc.fe_data_off, test_data,
+          sizeof(test_data));
+        TEST_ASSERT(rc == 0);
+
+        rc = fcb_append_finish(fcb, &loc);
+        TEST_ASSERT(rc == 0);
+    }
+    TEST_ASSERT(elem_cnts[3] == elem_cnts[0]);
+
+    /*
+     * Rotate
+     */
+    rc = fcb_rotate(fcb);
+    TEST_ASSERT(rc == 0);
+
+    memset(&cnts, 0, sizeof(cnts));
+    rc = fcb_walk(fcb, NULL, fcb_test_cnt_elems_cb, &aa_arg);
+    TEST_ASSERT(rc == 0);
+
+    TEST_ASSERT(cnts[0] == 0);
+    TEST_ASSERT(cnts[1] > 0);
+    TEST_ASSERT(cnts[1] == cnts[2] && cnts[1] == cnts[3]);
+
+    rc = fcb_append_to_scratch(fcb);
+    TEST_ASSERT(rc == 0);
+    rc = fcb_append_to_scratch(fcb);
+    TEST_ASSERT(rc != 0);
+}
+
+TEST_SUITE(fcb_test_all)
+{
+    fcb_test_len();
+
+    fcb_test_init();
+
+    fcb_test_empty_walk();
+
+    fcb_test_append();
+
+    fcb_test_append_too_big();
+
+    fcb_test_append_fill();
+
+    fcb_test_reset();
+
+    fcb_test_rotate();
+
+    fcb_test_multiple_scratch();
+}
+
+#if MYNEWT_VAL(SELFTEST)
+
+int
+main(int argc, char **argv)
+{
+    tu_config.tc_print_results = 1;
+    tu_init();
+
+    fcb_test_all();
+
+    return tu_any_failed;
+}
+#endif
+

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/d98ddc1c/sys/id/include/id/id.h
----------------------------------------------------------------------
diff --git a/sys/id/include/id/id.h b/sys/id/include/id/id.h
index 228d324..b1da40b 100644
--- a/sys/id/include/id/id.h
+++ b/sys/id/include/id/id.h
@@ -28,6 +28,6 @@
 /*
  * Initialize manufacturing info storage/reporting.
  */
-int id_init(void);
+void id_init(void);
 
 #endif

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/d98ddc1c/sys/id/pkg.yml
----------------------------------------------------------------------
diff --git a/sys/id/pkg.yml b/sys/id/pkg.yml
index c76cf14..2795d49 100644
--- a/sys/id/pkg.yml
+++ b/sys/id/pkg.yml
@@ -31,8 +31,15 @@ pkg.deps:
     - libs/os
     - libs/util
     - sys/config
-pkg.deps.SHELL:
+pkg.deps.ID_CLI:
     - libs/shell
-pkg.req_apis.SHELL:
+pkg.req_apis.ID_CLI:
     - console
-pkg.cflags.SHELL: -DSHELL_PRESENT
+
+pkg.init_function: id_init
+pkg.init_stage: 5
+
+pkg.syscfg_defs:
+    ID_CLI:
+        description: 'TBD'
+        value: 1

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/d98ddc1c/sys/id/src/id.c
----------------------------------------------------------------------
diff --git a/sys/id/src/id.c b/sys/id/src/id.c
index 3d2acc3..36eac5a 100644
--- a/sys/id/src/id.c
+++ b/sys/id/src/id.c
@@ -19,11 +19,13 @@
 #include <inttypes.h>
 #include <string.h>
 #include <stdio.h>
+#include <assert.h>
 
-#include <hal/hal_bsp.h>
-#include <os/os.h>
-#include <config/config.h>
-#include <util/base64.h>
+#include "sysinit/sysinit.h"
+#include "hal/hal_bsp.h"
+#include "os/os.h"
+#include "config/config.h"
+#include "util/base64.h"
 
 #include "id/id.h"
 
@@ -108,8 +110,11 @@ id_conf_export(void (*export_func)(char *name, char *val),
     return 0;
 }
 
-int
+void
 id_init(void)
 {
-    return conf_register(&id_conf);
+    int rc;
+
+    rc = conf_register(&id_conf);
+    SYSINIT_PANIC_ASSERT(rc == 0);
 }

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/d98ddc1c/sys/log/include/log/log.h
----------------------------------------------------------------------
diff --git a/sys/log/include/log/log.h b/sys/log/include/log/log.h
index f5772aa..1dc2a7e 100644
--- a/sys/log/include/log/log.h
+++ b/sys/log/include/log/log.h
@@ -19,6 +19,7 @@
 #ifndef __LOG_H__
 #define __LOG_H__
 
+#include "syscfg/syscfg.h"
 #include "log/ignore.h"
 #include "util/cbmem.h"
 
@@ -111,40 +112,35 @@ struct log_entry_hdr {
 
 #define LOG_NAME_MAX_LEN    (64)
 
-/* Compile in Log Debug by default */
-#ifndef LOG_LEVEL
-#define LOG_LEVEL LOG_LEVEL_DEBUG
-#endif
-
-#if LOG_LEVEL <= LOG_LEVEL_DEBUG
+#if MYNEWT_VAL(LOG_LEVEL) <= LOG_LEVEL_DEBUG
 #define LOG_DEBUG(__l, __mod, __msg, ...) log_printf(__l, __mod, \
         LOG_LEVEL_DEBUG, __msg, ##__VA_ARGS__)
 #else
 #define LOG_DEBUG(__l, __mod, ...) IGNORE(__VA_ARGS__)
 #endif
 
-#if LOG_LEVEL <= LOG_LEVEL_INFO
+#if MYNEWT_VAL(LOG_LEVEL) <= LOG_LEVEL_INFO
 #define LOG_INFO(__l, __mod, __msg, ...) log_printf(__l, __mod, \
         LOG_LEVEL_INFO, __msg, ##__VA_ARGS__)
 #else
 #define LOG_INFO(__l, __mod, ...) IGNORE(__VA_ARGS__)
 #endif
 
-#if LOG_LEVEL <= LOG_LEVEL_INFO
+#if MYNEWT_VAL(LOG_LEVEL) <= LOG_LEVEL_INFO
 #define LOG_WARN(__l, __mod, __msg, ...) log_printf(__l, __mod, \
         LOG_LEVEL_WARN, __msg, ##__VA_ARGS__)
 #else
 #define LOG_WARN(__l, __mod, ...) IGNORE(__VA_ARGS__)
 #endif
 
-#if LOG_LEVEL <= LOG_LEVEL_ERROR
+#if MYNEWT_VAL(LOG_LEVEL) <= LOG_LEVEL_ERROR
 #define LOG_ERROR(__l, __mod, __msg, ...) log_printf(__l, __mod, \
         LOG_LEVEL_ERROR, __msg, ##__VA_ARGS__)
 #else
 #define LOG_ERROR(__l, __mod, ...) IGNORE(__VA_ARGS__)
 #endif
 
-#if LOG_LEVEL <= LOG_LEVEL_CRITICAL
+#if MYNEWT_VAL(LOG_LEVEL) <= LOG_LEVEL_CRITICAL
 #define LOG_CRITICAL(__l, __mod, __msg, ...) log_printf(__l, __mod, \
         LOG_LEVEL_CRITICAL, __msg, ##__VA_ARGS__)
 #else
@@ -166,7 +162,7 @@ struct log {
 #define LOGS_NMGR_OP_LOGS_LIST    (5)
 
 /* Log system level functions (for all logs.) */
-int log_init(void);
+void log_init(void);
 struct log *log_list_get_next(struct log *);
 
 /* Log functions, manipulate a single log */
@@ -192,7 +188,7 @@ int log_fcb_handler_init(struct log_handler *, struct fcb *,
                          uint8_t entries);
 
 /* Private */
-#ifdef NEWTMGR_PRESENT
+#if MYNEWT_VAL(LOG_NEWTMGR)
 int log_nmgr_register_group(void);
 #endif
 

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/d98ddc1c/sys/log/pkg.yml
----------------------------------------------------------------------
diff --git a/sys/log/pkg.yml b/sys/log/pkg.yml
index 2bf5036..dc84d2f 100644
--- a/sys/log/pkg.yml
+++ b/sys/log/pkg.yml
@@ -27,18 +27,30 @@ pkg.keywords:
 pkg.deps:
     - libs/os
     - libs/util
-    - libs/testutil
-pkg.deps.SHELL:
-    - libs/shell
-pkg.deps.NEWTMGR:
+pkg.deps.LOG_NEWTMGR:
     - libs/newtmgr
-pkg.deps.FCB:
+pkg.deps.LOG_FCB:
     - hw/hal
     - sys/fcb
-pkg.deps.TEST:
-    - sys/fcb
-pkg.req_apis.SHELL:
-    - console
-pkg.cflags.SHELL: -DSHELL_PRESENT
-pkg.cflags.NEWTMGR: -DNEWTMGR_PRESENT
-pkg.cflags.FCB: -DFCB_PRESENT
+pkg.deps.LOG_CLI:
+    - libs/shell
+
+pkg.init_function: log_init
+pkg.init_stage: 1
+
+pkg.syscfg_defs:
+    LOG_LEVEL:
+        description: 'TBD'
+        value: 0
+
+    LOG_FCB:
+        description: 'TBD'
+        value: 'MYNEWT_PKG_SYS_FCB'
+
+    LOG_CLI:
+        description: 'TBD'
+        value: 'MYNEWT_PKG_LIBS_SHELL'
+
+    LOG_NEWTMGR:
+        description: 'TBD'
+        value: 'MYNEWT_PKG_LIBS_NEWTMGR'

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/d98ddc1c/sys/log/src/log.c
----------------------------------------------------------------------
diff --git a/sys/log/src/log.c b/sys/log/src/log.c
index 22c1159..eb841e7 100644
--- a/sys/log/src/log.c
+++ b/sys/log/src/log.c
@@ -17,26 +17,25 @@
  * under the License.
  */
 
-#include <os/os.h>
-#include "os/os_time.h"
-
+#include <assert.h>
 #include <string.h>
-
-#include <util/cbmem.h>
-
-#include "log/log.h"
-
 #include <stdio.h>
 #include <stdarg.h>
 
-#ifdef SHELL_PRESENT
-#include <shell/shell.h>
+#include "sysinit/sysinit.h"
+#include "syscfg/syscfg.h"
+#include "os/os.h"
+#include "util/cbmem.h"
+#include "log/log.h"
+
+#if MYNEWT_VAL(LOG_CLI)
+#include "shell/shell.h"
 #endif
 
 static STAILQ_HEAD(, log) g_log_list = STAILQ_HEAD_INITIALIZER(g_log_list);
 static uint8_t log_inited;
 
-#ifdef SHELL_PRESENT
+#if MYNEWT_VAL(LOG_CLI)
 int shell_log_dump_all_cmd(int, char **);
 struct shell_cmd g_shell_log_cmd = {
     .sc_cmd = "log",
@@ -44,30 +43,26 @@ struct shell_cmd g_shell_log_cmd = {
 };
 #endif
 
-int
+void
 log_init(void)
 {
-#ifdef NEWTMGR_PRESENT
     int rc;
-#endif
+
+    (void)rc;
 
     if (log_inited) {
-        return (0);
+        return;
     }
     log_inited = 1;
 
-#ifdef SHELL_PRESENT
+#if MYNEWT_VAL(LOG_CLI)
     shell_cmd_register(&g_shell_log_cmd);
 #endif
 
-#ifdef NEWTMGR_PRESENT
+#if MYNEWT_VAL(LOG_NEWTMGR)
     rc = log_nmgr_register_group();
-    if (rc != 0) {
-        return (rc);
-    }
-#endif /* NEWTMGR_PRESENT */
-
-    return (0);
+    SYSINIT_PANIC_ASSERT(rc == 0);
+#endif
 }
 
 struct log *

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/d98ddc1c/sys/log/src/log_fcb.c
----------------------------------------------------------------------
diff --git a/sys/log/src/log_fcb.c b/sys/log/src/log_fcb.c
index 3bfde04..d150a68 100644
--- a/sys/log/src/log_fcb.c
+++ b/sys/log/src/log_fcb.c
@@ -16,13 +16,17 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-#ifdef FCB_PRESENT
+
+#include "syscfg/syscfg.h"
+
+#if MYNEWT_VAL(LOG_FCB)
+
 #include <string.h>
 
-#include <os/os.h>
+#include "os/os.h"
 
-#include <hal/flash_map.h>
-#include <fcb/fcb.h>
+#include "hal/flash_map.h"
+#include "fcb/fcb.h"
 
 #include "log/log.h"
 

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/d98ddc1c/sys/log/src/log_nmgr.c
----------------------------------------------------------------------
diff --git a/sys/log/src/log_nmgr.c b/sys/log/src/log_nmgr.c
index b1e90a0..9b2d711 100644
--- a/sys/log/src/log_nmgr.c
+++ b/sys/log/src/log_nmgr.c
@@ -18,12 +18,12 @@
  */
 
 #include <os/os.h>
-
 #include <string.h>
-
 #include <stdio.h>
 
-#ifdef NEWTMGR_PRESENT
+#include "syscfg/syscfg.h"
+
+#if MYNEWT_VAL(LOG_NEWTMGR)
 
 #include "newtmgr/newtmgr.h"
 #include "json/json.h"
@@ -498,4 +498,4 @@ err:
     return (rc);
 }
 
-#endif /* NEWTMGR_PRESENT */
+#endif

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/d98ddc1c/sys/log/src/log_shell.c
----------------------------------------------------------------------
diff --git a/sys/log/src/log_shell.c b/sys/log/src/log_shell.c
index 3f67ed7..7188b5d 100644
--- a/sys/log/src/log_shell.c
+++ b/sys/log/src/log_shell.c
@@ -17,24 +17,22 @@
  * under the License.
  */
 
+#include "syscfg/syscfg.h"
+
 /* This whole file is conditionally compiled based on whether the 
- * SHELL_PRESENT identity is provided.
+ * log package is configured to use the shell (MYNEWT_VAL(LOG_CLI)).
  */
 
-#ifdef SHELL_PRESENT
-
-#include <os/os.h>
+#if MYNEWT_VAL(LOG_CLI)
 
+#include <stdio.h>
 #include <string.h>
 
-#include <util/cbmem.h>
-
+#include "os/os.h"
+#include "util/cbmem.h"
 #include "log/log.h"
-
-#include <stdio.h>
-
-#include <shell/shell.h>
-#include <console/console.h> 
+#include "shell/shell.h"
+#include "console/console.h"
 
 static int 
 shell_log_dump_entry(struct log *log, void *arg, void *dptr, uint16_t len) 

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/d98ddc1c/sys/log/src/test/log_test.c
----------------------------------------------------------------------
diff --git a/sys/log/src/test/log_test.c b/sys/log/src/test/log_test.c
deleted file mode 100644
index 7230686..0000000
--- a/sys/log/src/test/log_test.c
+++ /dev/null
@@ -1,162 +0,0 @@
-/**
- * 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 <string.h>
-
-#include <os/os.h>
-#include <testutil/testutil.h>
-#include <fcb/fcb.h>
-#include "log/log.h"
-
-static struct flash_area fcb_areas[] = {
-    [0] = {
-        .fa_off = 0x00000000,
-        .fa_size = 16 * 1024
-    },
-    [1] = {
-        .fa_off = 0x00004000,
-        .fa_size = 16 * 1024
-    }
-};
-static struct log_handler log_fcb_handler;
-static struct fcb log_fcb;
-static struct log my_log;
-
-static char *str_logs[] = {
-    "testdata",
-    "1testdata2",
-    NULL
-};
-static int str_idx = 0;
-static int str_max_idx = 0;
-
-TEST_CASE(log_setup_fcb)
-{
-    int rc;
-    int i;
-
-    log_fcb.f_sectors = fcb_areas;
-    log_fcb.f_sector_cnt = sizeof(fcb_areas) / sizeof(fcb_areas[0]);
-    log_fcb.f_magic = 0x7EADBADF;
-    log_fcb.f_version = 0;
-
-    for (i = 0; i < log_fcb.f_sector_cnt; i++) {
-        rc = flash_area_erase(&fcb_areas[i], 0, fcb_areas[i].fa_size);
-        TEST_ASSERT(rc == 0);
-    }
-    rc = fcb_init(&log_fcb);
-    TEST_ASSERT(rc == 0);
-    rc = log_fcb_handler_init(&log_fcb_handler, &log_fcb, 0);
-    TEST_ASSERT(rc == 0);
-
-    log_register("log", &my_log, &log_fcb_handler);
-}
-
-TEST_CASE(log_append_fcb)
-{
-    char *str;
-
-    while (1) {
-        str = str_logs[str_max_idx];
-        if (!str) {
-            break;
-        }
-        log_printf(&my_log, 0, 0, str, strlen(str));
-        str_max_idx++;
-    }
-}
-
-static int
-log_test_walk1(struct log *log, void *arg, void *dptr, uint16_t len)
-{
-    int rc;
-    struct log_entry_hdr ueh;
-    char data[128];
-    int dlen;
-
-    TEST_ASSERT(str_idx < str_max_idx);
-
-    rc = log_read(log, dptr, &ueh, 0, sizeof(ueh));
-    TEST_ASSERT(rc == sizeof(ueh));
-
-    dlen = len - sizeof(ueh);
-    TEST_ASSERT(dlen < sizeof(data));
-
-    rc = log_read(log, dptr, data, sizeof(ueh), dlen);
-    TEST_ASSERT(rc == dlen);
-
-    data[rc] = '\0';
-
-    TEST_ASSERT(strlen(str_logs[str_idx]) == dlen);
-    TEST_ASSERT(!memcmp(str_logs[str_idx], data, dlen));
-    str_idx++;
-
-    return 0;
-}
-
-TEST_CASE(log_walk_fcb)
-{
-    int rc;
-
-    str_idx = 0;
-
-    rc = log_walk(&my_log, log_test_walk1, NULL);
-    TEST_ASSERT(rc == 0);
-}
-
-static int
-log_test_walk2(struct log *log, void *arg, void *dptr, uint16_t len)
-{
-    TEST_ASSERT(0);
-    return 0;
-}
-
-TEST_CASE(log_flush_fcb)
-{
-    int rc;
-
-    rc = log_flush(&my_log);
-    TEST_ASSERT(rc == 0);
-
-    rc = log_walk(&my_log, log_test_walk2, NULL);
-    TEST_ASSERT(rc == 0);
-}
-
-TEST_SUITE(log_test_all)
-{
-    log_setup_fcb();
-    log_append_fcb();
-    log_walk_fcb();
-    log_flush_fcb();
-}
-
-#ifdef MYNEWT_SELFTEST
-
-int
-main(int argc, char **argv)
-{
-    tu_config.tc_print_results = 1;
-    tu_init();
-
-    log_init();
-    log_test_all();
-
-    return tu_any_failed;
-}
-
-#endif

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/d98ddc1c/sys/log/test/pkg.yml
----------------------------------------------------------------------
diff --git a/sys/log/test/pkg.yml b/sys/log/test/pkg.yml
new file mode 100644
index 0000000..f3d094a
--- /dev/null
+++ b/sys/log/test/pkg.yml
@@ -0,0 +1,33 @@
+# 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: sys/log/test
+pkg.type: unittest
+pkg.description: "Log unit tests."
+pkg.author: "Apache Mynewt <de...@mynewt.incubator.apache.org>"
+pkg.homepage: "http://mynewt.apache.org/"
+pkg.keywords:
+
+pkg.deps: 
+    - libs/testutil
+    - sys/log
+
+pkg.deps.SELFTEST:
+    - libs/console/stub
+
+pkg.syscfg_vals:
+    LOG_FCB: 1

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/d98ddc1c/sys/log/test/src/log_test.c
----------------------------------------------------------------------
diff --git a/sys/log/test/src/log_test.c b/sys/log/test/src/log_test.c
new file mode 100644
index 0000000..6f83c57
--- /dev/null
+++ b/sys/log/test/src/log_test.c
@@ -0,0 +1,163 @@
+/**
+ * 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 <string.h>
+
+#include "syscfg/syscfg.h"
+#include "os/os.h"
+#include "testutil/testutil.h"
+#include "fcb/fcb.h"
+#include "log/log.h"
+
+static struct flash_area fcb_areas[] = {
+    [0] = {
+        .fa_off = 0x00000000,
+        .fa_size = 16 * 1024
+    },
+    [1] = {
+        .fa_off = 0x00004000,
+        .fa_size = 16 * 1024
+    }
+};
+static struct log_handler log_fcb_handler;
+static struct fcb log_fcb;
+static struct log my_log;
+
+static char *str_logs[] = {
+    "testdata",
+    "1testdata2",
+    NULL
+};
+static int str_idx = 0;
+static int str_max_idx = 0;
+
+TEST_CASE(log_setup_fcb)
+{
+    int rc;
+    int i;
+
+    log_fcb.f_sectors = fcb_areas;
+    log_fcb.f_sector_cnt = sizeof(fcb_areas) / sizeof(fcb_areas[0]);
+    log_fcb.f_magic = 0x7EADBADF;
+    log_fcb.f_version = 0;
+
+    for (i = 0; i < log_fcb.f_sector_cnt; i++) {
+        rc = flash_area_erase(&fcb_areas[i], 0, fcb_areas[i].fa_size);
+        TEST_ASSERT(rc == 0);
+    }
+    rc = fcb_init(&log_fcb);
+    TEST_ASSERT(rc == 0);
+    rc = log_fcb_handler_init(&log_fcb_handler, &log_fcb, 0);
+    TEST_ASSERT(rc == 0);
+
+    log_register("log", &my_log, &log_fcb_handler);
+}
+
+TEST_CASE(log_append_fcb)
+{
+    char *str;
+
+    while (1) {
+        str = str_logs[str_max_idx];
+        if (!str) {
+            break;
+        }
+        log_printf(&my_log, 0, 0, str, strlen(str));
+        str_max_idx++;
+    }
+}
+
+static int
+log_test_walk1(struct log *log, void *arg, void *dptr, uint16_t len)
+{
+    int rc;
+    struct log_entry_hdr ueh;
+    char data[128];
+    int dlen;
+
+    TEST_ASSERT(str_idx < str_max_idx);
+
+    rc = log_read(log, dptr, &ueh, 0, sizeof(ueh));
+    TEST_ASSERT(rc == sizeof(ueh));
+
+    dlen = len - sizeof(ueh);
+    TEST_ASSERT(dlen < sizeof(data));
+
+    rc = log_read(log, dptr, data, sizeof(ueh), dlen);
+    TEST_ASSERT(rc == dlen);
+
+    data[rc] = '\0';
+
+    TEST_ASSERT(strlen(str_logs[str_idx]) == dlen);
+    TEST_ASSERT(!memcmp(str_logs[str_idx], data, dlen));
+    str_idx++;
+
+    return 0;
+}
+
+TEST_CASE(log_walk_fcb)
+{
+    int rc;
+
+    str_idx = 0;
+
+    rc = log_walk(&my_log, log_test_walk1, NULL);
+    TEST_ASSERT(rc == 0);
+}
+
+static int
+log_test_walk2(struct log *log, void *arg, void *dptr, uint16_t len)
+{
+    TEST_ASSERT(0);
+    return 0;
+}
+
+TEST_CASE(log_flush_fcb)
+{
+    int rc;
+
+    rc = log_flush(&my_log);
+    TEST_ASSERT(rc == 0);
+
+    rc = log_walk(&my_log, log_test_walk2, NULL);
+    TEST_ASSERT(rc == 0);
+}
+
+TEST_SUITE(log_test_all)
+{
+    log_setup_fcb();
+    log_append_fcb();
+    log_walk_fcb();
+    log_flush_fcb();
+}
+
+#if MYNEWT_VAL(SELFTEST)
+
+int
+main(int argc, char **argv)
+{
+    tu_config.tc_print_results = 1;
+    tu_init();
+
+    log_init();
+    log_test_all();
+
+    return tu_any_failed;
+}
+
+#endif

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/d98ddc1c/sys/mn_socket/pkg.yml
----------------------------------------------------------------------
diff --git a/sys/mn_socket/pkg.yml b/sys/mn_socket/pkg.yml
index 0c9c064..4242b46 100644
--- a/sys/mn_socket/pkg.yml
+++ b/sys/mn_socket/pkg.yml
@@ -28,4 +28,3 @@ pkg.keywords:
 pkg.deps:
     - libs/os
     - libs/util
-    - libs/testutil

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/d98ddc1c/sys/mn_socket/src/test/mn_sock_test.c
----------------------------------------------------------------------
diff --git a/sys/mn_socket/src/test/mn_sock_test.c b/sys/mn_socket/src/test/mn_sock_test.c
deleted file mode 100644
index a8d9cc2..0000000
--- a/sys/mn_socket/src/test/mn_sock_test.c
+++ /dev/null
@@ -1,82 +0,0 @@
-/**
- * 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 <string.h>
-
-#include <os/os.h>
-#include <testutil/testutil.h>
-
-#include "mn_socket/mn_socket.h"
-
-TEST_CASE(inet_pton_test)
-{
-    int rc;
-    uint8_t addr[8];
-    struct test_vec {
-        char *str;
-        uint8_t cmp[4];
-    };
-    struct test_vec ok_vec[] = {
-        { "1.1.1.1", { 1, 1, 1, 1 } },
-        { "1.2.3.4", { 1, 2, 3, 4 } },
-        { "010.001.255.255", { 10, 1, 255, 255 } },
-        { "001.002.005.006", { 1, 2, 5, 6 } }
-    };
-    struct test_vec invalid_vec[] = {
-        { "a.b.c.d" },
-        { "1a.b3.4.2" },
-        { "1.3.4.2a" },
-        { "1111.3.4.2" },
-        { "3.256.1.0" },
-    };
-    int i;
-
-    for (i = 0; i < sizeof(ok_vec) / sizeof(ok_vec[0]); i++) {
-        memset(addr, 0xa5, sizeof(addr));
-        rc = mn_inet_pton(MN_PF_INET, ok_vec[i].str, addr);
-        TEST_ASSERT(rc == 1);
-        TEST_ASSERT(!memcmp(ok_vec[i].cmp, addr, sizeof(uint32_t)));
-        TEST_ASSERT(addr[5] == 0xa5);
-    }
-    for (i = 0; i < sizeof(invalid_vec) / sizeof(invalid_vec[0]); i++) {
-        rc = mn_inet_pton(MN_PF_INET, invalid_vec[i].str, addr);
-        TEST_ASSERT(rc == 0);
-    }
-}
-
-TEST_SUITE(mn_socket_test_all)
-{
-    inet_pton_test();
-}
-
-#ifdef MYNEWT_SELFTEST
-
-int
-main(int argc, char **argv)
-{
-    tu_config.tc_print_results = 1;
-    tu_init();
-
-    mn_socket_test_all();
-
-    return tu_any_failed;
-}
-#endif
-

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/d98ddc1c/sys/mn_socket/test/pkg.yml
----------------------------------------------------------------------
diff --git a/sys/mn_socket/test/pkg.yml b/sys/mn_socket/test/pkg.yml
new file mode 100644
index 0000000..b46d24c
--- /dev/null
+++ b/sys/mn_socket/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: sys/mn_socket/test
+pkg.type: unittest
+pkg.description: "Mynewt socket unit tests."
+pkg.author: "Apache Mynewt <de...@mynewt.incubator.apache.org>"
+pkg.homepage: "http://mynewt.apache.org/"
+pkg.keywords:
+
+pkg.deps: 
+    - libs/testutil
+    - sys/mn_socket
+
+pkg.deps.SELFTEST:
+    - libs/console/stub

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/d98ddc1c/sys/mn_socket/test/src/mn_sock_test.c
----------------------------------------------------------------------
diff --git a/sys/mn_socket/test/src/mn_sock_test.c b/sys/mn_socket/test/src/mn_sock_test.c
new file mode 100644
index 0000000..4babb33
--- /dev/null
+++ b/sys/mn_socket/test/src/mn_sock_test.c
@@ -0,0 +1,83 @@
+/**
+ * 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 <string.h>
+
+#include "syscfg/syscfg.h"
+#include "os/os.h"
+#include "testutil/testutil.h"
+
+#include "mn_socket/mn_socket.h"
+
+TEST_CASE(inet_pton_test)
+{
+    int rc;
+    uint8_t addr[8];
+    struct test_vec {
+        char *str;
+        uint8_t cmp[4];
+    };
+    struct test_vec ok_vec[] = {
+        { "1.1.1.1", { 1, 1, 1, 1 } },
+        { "1.2.3.4", { 1, 2, 3, 4 } },
+        { "010.001.255.255", { 10, 1, 255, 255 } },
+        { "001.002.005.006", { 1, 2, 5, 6 } }
+    };
+    struct test_vec invalid_vec[] = {
+        { "a.b.c.d" },
+        { "1a.b3.4.2" },
+        { "1.3.4.2a" },
+        { "1111.3.4.2" },
+        { "3.256.1.0" },
+    };
+    int i;
+
+    for (i = 0; i < sizeof(ok_vec) / sizeof(ok_vec[0]); i++) {
+        memset(addr, 0xa5, sizeof(addr));
+        rc = mn_inet_pton(MN_PF_INET, ok_vec[i].str, addr);
+        TEST_ASSERT(rc == 1);
+        TEST_ASSERT(!memcmp(ok_vec[i].cmp, addr, sizeof(uint32_t)));
+        TEST_ASSERT(addr[5] == 0xa5);
+    }
+    for (i = 0; i < sizeof(invalid_vec) / sizeof(invalid_vec[0]); i++) {
+        rc = mn_inet_pton(MN_PF_INET, invalid_vec[i].str, addr);
+        TEST_ASSERT(rc == 0);
+    }
+}
+
+TEST_SUITE(mn_socket_test_all)
+{
+    inet_pton_test();
+}
+
+#if MYNEWT_VAL(SELFTEST)
+
+int
+main(int argc, char **argv)
+{
+    tu_config.tc_print_results = 1;
+    tu_init();
+
+    mn_socket_test_all();
+
+    return tu_any_failed;
+}
+#endif
+

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/d98ddc1c/sys/reboot/pkg.yml
----------------------------------------------------------------------
diff --git a/sys/reboot/pkg.yml b/sys/reboot/pkg.yml
index 45fba7d..f55397b 100644
--- a/sys/reboot/pkg.yml
+++ b/sys/reboot/pkg.yml
@@ -28,9 +28,19 @@ pkg.keywords:
 pkg.deps:
     - libs/os
     - libs/util
-    - libs/testutil
     - sys/fcb
     - sys/log
     - libs/imgmgr
 pkg.req_apis:
     - console
+
+pkg.init_function: log_reboot_pkg_init
+pkg.init_stage: 2
+
+pkg.syscfg_defs:
+    REBOOT_LOG_0_TYPE:
+        description: 'TBD'
+        value:  LOG_TYPE_STORAGE
+    REBOOT_LOG_0_ENTRY_COUNT:
+        description: 'TBD'
+        value:  10