|
@@ -1,473 +0,0 @@
|
|
|
-Subject: Add tests for key manipulation functions
|
|
|
-Origin: v7-7-gc71df1d <https://github.com/latchset/tang/commit/v7-7-gc71df1d>
|
|
|
-Upstream-Author: Sergio Correia <scorreia@redhat.com>
|
|
|
-Date: Fri Nov 27 09:42:38 2020 -0300
|
|
|
-
|
|
|
- In this commit we add tests for the key manipulation functions added in
|
|
|
- src/keys.{c|h}.
|
|
|
-
|
|
|
---- /dev/null
|
|
|
-+++ b/tests/keys/-bWkGaJi0Zdvxaj4DCp28umLcRA.jwk
|
|
|
-@@ -0,0 +1 @@
|
|
|
-+{"alg":"ECMR","crv":"P-521","d":"AQ3u1g0L__GIGSJRX1LtjSArwJxxQz0kWXIi-X4PqwoheoeY57cw36pmWmyVsn43jDEZ6SAsiNeIw9sHDkFZe1VV","key_ops":["deriveKey"],"kty":"EC","x":"AcfowrKEKteg_jKX1CiR2RQfbUGJ73KXlcl8AgIDAgN7R6yNKWpKhZNBmV2tAxxMCQcIksqQl17UXwemvH2j2fem","y":"ACrb-y4ZhLIGX-41QYgJhniiZ85qkjILbkVUcC8gBYxOAnKWIpMGLsjrT3AYhM6jk6puwnNYbEM28s2caAEogUcA"}
|
|
|
---- /dev/null
|
|
|
-+++ b/tests/keys/.r4E2wG1u_YyKUo0N0rIK7jJF5Xg.jwk
|
|
|
-@@ -0,0 +1 @@
|
|
|
-+{"alg":"ES512","crv":"P-521","d":"Af5SfYh_4LmBDF9dCGDQRDA52yzqnzDeo-GZU05hpnLr6bsIBTFpc8rdcCm95mhZ59ngC-6WNtmAF_nLCDcHKg0A","key_ops":["sign","verify"],"kty":"EC","x":"AUxS3DXdoONUB-6-nyzdd3V42iD7obGTJ1m40t3V6jzXfABWp_gtTidwiKyDJQXxhEzMSToo-V0RGq6Qz2XTOgPe","y":"AFrkJfkLGJz_2v-k3-wdydckVcBXql2NR66HaF0U9NlcfGLezQau7XihArm4GE3-sHoQLsRa-HvYET9zyd9Syh5y"}
|
|
|
---- /dev/null
|
|
|
-+++ b/tests/keys/.uZ0s8YTXcGcuWduWWBSiR2OjOVg.jwk
|
|
|
-@@ -0,0 +1 @@
|
|
|
-+{"alg":"ECMR","crv":"P-521","d":"Acuk66sHvSS5TN-p0XhwHhVKyifYr-ecur-7zfgQZMzSq9SeBJjuX6Ttav-7AbnVvXU_S55BgtGL5iymXGuMguCp","key_ops":["deriveKey"],"kty":"EC","x":"AEz9EwBOIrLeV4in6M1oWVnOWVR7ubkFB0R0-AwyIL7u5-7G3u2tvPIJRQY-l1Wttn7Ar4DhflcMhnb3rk5hT5yh","y":"AZt35wqOhNsnEi-GLAgyCaiW_c6h6Zyo4xwjuvXzmQMDwh9MtdaUigFuBOTlfRj1uri_YBqdpI09nYrqqgx97Ca6"}
|
|
|
---- /dev/null
|
|
|
-+++ b/tests/keys/another-bad-file
|
|
|
-@@ -0,0 +1 @@
|
|
|
-+foobar
|
|
|
---- /dev/null
|
|
|
-+++ b/tests/keys/invalid.jwk
|
|
|
-@@ -0,0 +1 @@
|
|
|
-+foo
|
|
|
---- /dev/null
|
|
|
-+++ b/tests/keys/qgmqJSo6AEEuVQY7zVlklqdTMqY.jwk
|
|
|
-@@ -0,0 +1 @@
|
|
|
-+{"alg":"ES512","crv":"P-521","d":"AUQpuWtoSqURl0OuWQ-I9i4X1F3sDak0Hbf9Ixj7uwjA20A0ABJdCHbai1Ai0t3yoxWKPYi6t2XjjeRzHIKyhXbf","key_ops":["sign","verify"],"kty":"EC","x":"ACbYnvh1EtLePkM5jCtuxLpMroOUNRfv-wQdXgT5AQ5bhSLv6wkrBzh1rwymo-fmCNWzrcTflzqWf-wXAd00lokM","y":"AEaDByxXfbee4TlPXgPRg5S4MVOqgObjX6_JJkySTudSfOygcx7dujsf32dOEI25d8bNKUgdjQt8lc5XtHeWXH3a"}
|
|
|
---- a/tests/meson.build
|
|
|
-+++ b/tests/meson.build
|
|
|
-@@ -1,22 +1,42 @@
|
|
|
-+incdir = include_directories(
|
|
|
-+ join_paths('..', 'src')
|
|
|
-+)
|
|
|
-+
|
|
|
-+test_data = configuration_data()
|
|
|
-+test_data.set('testjwkdir', join_paths(meson.source_root(), 'tests','keys'))
|
|
|
-+
|
|
|
-+test_keys_c = configure_file(
|
|
|
-+ input: 'test-keys.c.in',
|
|
|
-+ output: 'test-keys.c',
|
|
|
-+ configuration: test_data
|
|
|
-+)
|
|
|
-+
|
|
|
-+test_keys = executable('test-keys',
|
|
|
-+ test_keys_c,
|
|
|
-+ 'test-util.c',
|
|
|
-+ dependencies: [jose],
|
|
|
-+ include_directories: incdir
|
|
|
-+)
|
|
|
-+
|
|
|
- sd_activate = find_program(
|
|
|
- 'systemd-socket-activate',
|
|
|
- 'systemd-activate',
|
|
|
- required: false
|
|
|
- )
|
|
|
-
|
|
|
-+env = environment()
|
|
|
-+env.prepend('PATH',
|
|
|
-+ join_paths(meson.source_root(), 'src'),
|
|
|
-+ join_paths(meson.build_root(), 'src'),
|
|
|
-+ separator: ':'
|
|
|
-+)
|
|
|
-+
|
|
|
- if sd_activate.found()
|
|
|
-- env = environment()
|
|
|
-- env.prepend('PATH',
|
|
|
-- join_paths(meson.source_root(), 'src'),
|
|
|
-- join_paths(meson.build_root(), 'src'),
|
|
|
-- separator: ':'
|
|
|
-- )
|
|
|
- env.set('SD_ACTIVATE', sd_activate.path() + ' --inetd')
|
|
|
-
|
|
|
-- test('adv', find_program('adv'), env: env)
|
|
|
-+ test('adv', find_program('adv'), env: env, timeout: 60)
|
|
|
- test('rec', find_program('rec'), env: env)
|
|
|
--else
|
|
|
-- warning('Will not run the tests due to missing dependencies!')
|
|
|
- endif
|
|
|
-+test('test-keys', test_keys, env: env, timeout: 60)
|
|
|
-
|
|
|
- # vim:set ts=2 sw=2 et:
|
|
|
---- /dev/null
|
|
|
-+++ b/tests/test-keys.c.in
|
|
|
-@@ -0,0 +1,257 @@
|
|
|
-+/* vim: set tabstop=8 shiftwidth=4 softtabstop=4 expandtab smarttab colorcolumn=80: */
|
|
|
-+/*
|
|
|
-+ * Copyright (c) 2020 Red Hat, Inc.
|
|
|
-+ * Author: Sergio Correia <scorreia@redhat.com>
|
|
|
-+ *
|
|
|
-+ * This program is free software: you can redistribute it and/or modify
|
|
|
-+ * it under the terms of the GNU General Public License as published by
|
|
|
-+ * the Free Software Foundation, either version 3 of the License, or
|
|
|
-+ * (at your option) any later version.
|
|
|
-+ *
|
|
|
-+ * This program is distributed in the hope that it will be useful,
|
|
|
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
-+ * GNU General Public License for more details.
|
|
|
-+ *
|
|
|
-+ * You should have received a copy of the GNU General Public License
|
|
|
-+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
-+ */
|
|
|
-+
|
|
|
-+#include "keys.c"
|
|
|
-+#include "test-util.h"
|
|
|
-+
|
|
|
-+const char* jwkdir = "@testjwkdir@";
|
|
|
-+
|
|
|
-+struct thp_result {
|
|
|
-+ const char* thp;
|
|
|
-+ int valid;
|
|
|
-+};
|
|
|
-+
|
|
|
-+struct test_result_int {
|
|
|
-+ const char* data;
|
|
|
-+ int expected;
|
|
|
-+};
|
|
|
-+
|
|
|
-+static void
|
|
|
-+test_create_new_keys(void)
|
|
|
-+{
|
|
|
-+ __attribute__((cleanup(cleanup_str))) char* newdir = create_tempdir();
|
|
|
-+ ASSERT(newdir);
|
|
|
-+ __attribute__((cleanup(cleanup_tang_keys_info))) struct tang_keys_info* tki = read_keys(newdir);
|
|
|
-+ ASSERT(tki);
|
|
|
-+ ASSERT(tki->m_keys_count == 2);
|
|
|
-+ remove_tempdir(newdir);
|
|
|
-+}
|
|
|
-+
|
|
|
-+
|
|
|
-+static void
|
|
|
-+test_is_hash(void)
|
|
|
-+{
|
|
|
-+ const struct test_result_int test_data[] = {
|
|
|
-+ {NULL, 0},
|
|
|
-+ {"", 0},
|
|
|
-+ {"ES512", 0},
|
|
|
-+ {"ECMR", 0},
|
|
|
-+ {"foobar", 0},
|
|
|
-+ {"{", 0},
|
|
|
-+ {"[}", 0},
|
|
|
-+ {"[]", 0},
|
|
|
-+ {"S1", 1},
|
|
|
-+ {"S224", 1},
|
|
|
-+ {"S256", 1},
|
|
|
-+ {"S384", 1},
|
|
|
-+ {"S512", 1},
|
|
|
-+ {"S42", 0}
|
|
|
-+ };
|
|
|
-+ for (int i = 0, len = ARRAY_COUNT(test_data); i < len; i++) {
|
|
|
-+ int ret = is_hash(test_data[i].data);
|
|
|
-+ ASSERT_WITH_MSG(ret == test_data[i].expected, "i = %d, alg = %s", i, test_data[i].data);
|
|
|
-+ };
|
|
|
-+
|
|
|
-+}
|
|
|
-+
|
|
|
-+static void
|
|
|
-+test_jwk_generate(void)
|
|
|
-+{
|
|
|
-+ const struct test_result_int test_data[] = {
|
|
|
-+ {NULL, 0},
|
|
|
-+ {"", 0},
|
|
|
-+ {"ES512", 1},
|
|
|
-+ {"ECMR", 1},
|
|
|
-+ {"foobar", 0},
|
|
|
-+ {"{", 0},
|
|
|
-+ {"[}", 0},
|
|
|
-+ {"[]", 0}
|
|
|
-+ };
|
|
|
-+
|
|
|
-+ for (int i = 0, len = ARRAY_COUNT(test_data); i < len; i++) {
|
|
|
-+ json_auto_t* jwk = jwk_generate(test_data[i].data);
|
|
|
-+ ASSERT_WITH_MSG(!!jwk == test_data[i].expected, "i = %d, alg = %s", i, test_data[i].data);
|
|
|
-+ };
|
|
|
-+}
|
|
|
-+
|
|
|
-+static void
|
|
|
-+test_find_jws(void)
|
|
|
-+{
|
|
|
-+ const struct thp_result test_data[] = {
|
|
|
-+ {"00BUQM4A7NYxbOrBR9QDfkzGVGj3k57Fs4jCbJxcLYAgRFHu5B7jtbL97x1T7stQ", 1},
|
|
|
-+ {"dd5qbN1lQ6UWdZszbfx2oIcH34ShklzFL1SUQg", 1},
|
|
|
-+ {"dOZkUtZ_gLDUP53GIlyAxHMNuyrk8vdY-XXND32GccqNbT_MKpqGC-13-GNEye48", 1},
|
|
|
-+ {"DZrlBQvfvlwPQlvH_IieBdc_KpesEramLygVL_rFr7g", 1},
|
|
|
-+ {"FL_Zt5fFadUL4syeMMpUnss8aKdCrPGFy3102JGR3EE", 1},
|
|
|
-+ {"qgmqJSo6AEEuVQY7zVlklqdTMqY", 1},
|
|
|
-+ {"r4E2wG1u_YyKUo0N0rIK7jJF5Xg", 1},
|
|
|
-+ {"ugJ4Ula-YABQIiJ-0g3B_jpFpF2nl3W-DNpfLdXArhTusV0QCcd1vtgDeGHEPzpm7jEsyC7VYYSSOkZicK22mw", 1},
|
|
|
-+ {"up0Z4fRhpd4O5QwBaMCXDTlrvxCmZacU0MD8kw", 1},
|
|
|
-+ {"vllHS-M0aQFCo2yUCcAahMU4TAtXACyeuRf-zbmmTPBg7V0Pb-RRFGo5C6MnpzdirK8B3ORLOsN8RyXClvtjxA", 1},
|
|
|
-+ {NULL, 1},
|
|
|
-+ {"a", 0},
|
|
|
-+ {"foo", 0},
|
|
|
-+ {"bar", 0},
|
|
|
-+ {"XXXXXXXXXXXXXXXXXX", 0}
|
|
|
-+ };
|
|
|
-+
|
|
|
-+ __attribute__((cleanup(cleanup_tang_keys_info))) struct tang_keys_info* tki = read_keys(jwkdir);
|
|
|
-+ for (int i = 0, len = ARRAY_COUNT(test_data); i < len; i++) {
|
|
|
-+ json_auto_t* jws = find_jws(tki, test_data[i].thp);
|
|
|
-+ ASSERT_WITH_MSG(!!jws == test_data[i].valid, "i = %d, thp = %s", i, test_data[i].thp);
|
|
|
-+ }
|
|
|
-+
|
|
|
-+ /* Passing NULL to find_jws should return the default advertisement */
|
|
|
-+ json_auto_t* adv = find_jws(tki, NULL);
|
|
|
-+ ASSERT(adv);
|
|
|
-+
|
|
|
-+
|
|
|
-+ /*
|
|
|
-+ * The default set of signing keys are the signing keys that are not
|
|
|
-+ * rotated. The payload is made of deriving keys that are also not
|
|
|
-+ * rotated. The default advertisement should be signed by this set of
|
|
|
-+ * default signing keys.
|
|
|
-+ */
|
|
|
-+ ASSERT(jose_jws_ver(NULL, adv, NULL, tki->m_sign, 1));
|
|
|
-+
|
|
|
-+ /* find_jws should be able to respond to thumbprints of keys using any
|
|
|
-+ * of jose supported hash algorithms. */
|
|
|
-+ const char** hashes = supported_hashes();
|
|
|
-+ size_t idx;
|
|
|
-+ json_t* jwk;
|
|
|
-+
|
|
|
-+ /* Let's put together all the keys, including rotated ones. */
|
|
|
-+ json_auto_t* keys = json_deep_copy(tki->m_keys);
|
|
|
-+ ASSERT(keys);
|
|
|
-+ ASSERT(json_array_extend(keys, tki->m_rotated_keys) == 0);
|
|
|
-+ ASSERT(json_array_size(keys) == (size_t)tki->m_keys_count);
|
|
|
-+
|
|
|
-+ for (int i = 0; hashes[i]; i++) {
|
|
|
-+ json_array_foreach(keys, idx, jwk) {
|
|
|
-+ if (!jwk_valid_for_signing(jwk)) {
|
|
|
-+ continue;
|
|
|
-+ }
|
|
|
-+ __attribute__((cleanup(cleanup_str))) char* thp = jwk_thumbprint(jwk, hashes[i]);
|
|
|
-+ ASSERT_WITH_MSG(thp, "i = %d, hash = %s, key idx = %d", i, hashes[i], idx);
|
|
|
-+ json_auto_t* jws = find_jws(tki, thp);
|
|
|
-+ ASSERT_WITH_MSG(jws, "i = %d, hash = %s, key idx = %d, thp = %s", i, hashes[i], idx, thp);
|
|
|
-+
|
|
|
-+ /* Signing keys should sign the payload, in addition to the
|
|
|
-+ * default set of signing keys. */
|
|
|
-+ json_auto_t* sign = json_deep_copy(tki->m_sign);
|
|
|
-+ ASSERT_WITH_MSG(sign, "i = %d, hash = %s, key idx = %d, thp = %s", i, hashes[i], idx, thp);
|
|
|
-+ ASSERT_WITH_MSG(json_array_append(sign, jwk) == 0, "i = %d, hash = %s, key idx = %d, thp = %s", i, hashes[i], idx, thp);
|
|
|
-+ ASSERT_WITH_MSG(jose_jws_ver(NULL, jws, NULL, sign, 1), "i = %d, hash = %s, key idx = %d, thp = %s", i, hashes[i], idx, thp);
|
|
|
-+ }
|
|
|
-+ }
|
|
|
-+}
|
|
|
-+
|
|
|
-+static void
|
|
|
-+test_find_jwk(void)
|
|
|
-+{
|
|
|
-+ const struct thp_result test_data[] = {
|
|
|
-+ {"1HdF3XKRSsuZdkpXNurBPoL_pvxdvCOlHuhB4DP-4xWFqbZ51zo29kR4fSiT3BGy9UrHVJ26JMBLOA1vKq3lxA", 1},
|
|
|
-+ {"9U8qgy_YjyY6Isuq6QuiKEiYZgNJShcGgJx5FJzCu6m3N6zFaIPy_HDkxkVqAZ9E", 1},
|
|
|
-+ {"-bWkGaJi0Zdvxaj4DCp28umLcRA", 1},
|
|
|
-+ {"Cy73glFjs6B6RU7wy6vWxAc-2bJy5VJOT9LyK80eKgZ8k27wXZ-3rjsuNU5tua_yHWtluyoSYtjoKXfI0E8ESw", 1},
|
|
|
-+ {"kfjbqx_b3BsgPC87HwlOWL9daGMMHBzxcFLClw", 1},
|
|
|
-+ {"L4xg2tZXTEVbsK39bzOZM1jGWn3HtOxF5gh6F9YVf5Q", 1},
|
|
|
-+ {"LsVAV2ig5LlfstM8TRSf-c7IAkLpNYbIysNuRCVlxocRCGqAh6-f9PklM4nU4N-J", 1},
|
|
|
-+ {"OkAcDxYHNlo7-tul8OubYuWXB8CPEhAkcacCmhTclMU", 1},
|
|
|
-+ {"uZ0s8YTXcGcuWduWWBSiR2OjOVg", 1},
|
|
|
-+ {"WEpfFyeoNKkE2-TosN_bP-gd9UgRvQCZpVasZQ", 1},
|
|
|
-+ {NULL, 0},
|
|
|
-+ {"a", 0},
|
|
|
-+ {"foo", 0},
|
|
|
-+ {"bar", 0},
|
|
|
-+ {"XXXXXXXXXXXXXXXXXX", 0},
|
|
|
-+ };
|
|
|
-+
|
|
|
-+ __attribute__((cleanup(cleanup_tang_keys_info))) struct tang_keys_info* tki = read_keys(jwkdir);
|
|
|
-+
|
|
|
-+ for (int i = 0, len = ARRAY_COUNT(test_data); i < len; i++) {
|
|
|
-+ json_auto_t* tjwk = find_jwk(tki, test_data[i].thp);
|
|
|
-+ ASSERT_WITH_MSG(!!tjwk == test_data[i].valid, "i = %d, thp = %s", i, test_data[i].thp);
|
|
|
-+ }
|
|
|
-+ /* Passing NULL to find_jwk should fail */
|
|
|
-+ json_auto_t* bad_jwk = find_jwk(tki, NULL);
|
|
|
-+ ASSERT(bad_jwk == NULL);
|
|
|
-+
|
|
|
-+ /* find_jwk should be able to respond to thumbprints of keys using any
|
|
|
-+ * of jose supported hash algorithms. */
|
|
|
-+ const char** hashes = supported_hashes();
|
|
|
-+ size_t idx;
|
|
|
-+ json_t* jwk;
|
|
|
-+
|
|
|
-+ /* Let's put together all the keys, including rotated ones. */
|
|
|
-+ json_auto_t* keys = json_deep_copy(tki->m_keys);
|
|
|
-+ ASSERT(keys);
|
|
|
-+ ASSERT(json_array_extend(keys, tki->m_rotated_keys) == 0);
|
|
|
-+ ASSERT(json_array_size(keys) == (size_t)tki->m_keys_count);
|
|
|
-+
|
|
|
-+ for (int i = 0; hashes[i]; i++) {
|
|
|
-+ json_array_foreach(keys, idx, jwk) {
|
|
|
-+ if (!jwk_valid_for_deriving_keys(jwk)) {
|
|
|
-+ continue;
|
|
|
-+ }
|
|
|
-+ __attribute__((cleanup(cleanup_str))) char* thp = jwk_thumbprint(jwk, hashes[i]);
|
|
|
-+ json_auto_t* tjwk = find_jwk(tki, thp);
|
|
|
-+ ASSERT_WITH_MSG(tjwk, "i = %d, hash = %s, key idx = %d, thp = %s", i, hashes[i], idx, thp);
|
|
|
-+ }
|
|
|
-+ }
|
|
|
-+}
|
|
|
-+
|
|
|
-+static void
|
|
|
-+test_read_keys(void)
|
|
|
-+{
|
|
|
-+ __attribute__((cleanup(cleanup_tang_keys_info))) struct tang_keys_info* tki = read_keys(jwkdir);
|
|
|
-+ ASSERT(tki);
|
|
|
-+
|
|
|
-+ /*
|
|
|
-+ * Keys in tests/keys:
|
|
|
-+ * - .uZ0s8YTXcGcuWduWWBSiR2OjOVg.jwk
|
|
|
-+ * - .r4E2wG1u_YyKUo0N0rIK7jJF5Xg.jwk
|
|
|
-+ * - qgmqJSo6AEEuVQY7zVlklqdTMqY.jwk
|
|
|
-+ * - -bWkGaJi0Zdvxaj4DCp28umLcRA.jwk
|
|
|
-+ */
|
|
|
-+ ASSERT(tki->m_keys_count == 4);
|
|
|
-+ ASSERT(json_array_size(tki->m_keys) == 2);
|
|
|
-+ ASSERT(json_array_size(tki->m_rotated_keys) == 2);
|
|
|
-+
|
|
|
-+ const char* invalid_jwkdir = "foobar";
|
|
|
-+ __attribute__((cleanup(cleanup_tang_keys_info))) struct tang_keys_info* tki2 = read_keys(invalid_jwkdir);
|
|
|
-+ ASSERT(tki2 == NULL);
|
|
|
-+}
|
|
|
-+
|
|
|
-+static void
|
|
|
-+run_tests(void)
|
|
|
-+{
|
|
|
-+ test_read_keys();
|
|
|
-+ test_find_jwk();
|
|
|
-+ test_find_jws();
|
|
|
-+ test_jwk_generate();
|
|
|
-+ test_is_hash();
|
|
|
-+ test_create_new_keys();
|
|
|
-+}
|
|
|
-+
|
|
|
-+int main(int argc, char** argv)
|
|
|
-+{
|
|
|
-+ run_tests();
|
|
|
-+ return 0;
|
|
|
-+}
|
|
|
---- /dev/null
|
|
|
-+++ b/tests/test-util.c
|
|
|
-@@ -0,0 +1,75 @@
|
|
|
-+/* vim: set tabstop=8 shiftwidth=4 softtabstop=4 expandtab smarttab colorcolumn=80: */
|
|
|
-+/*
|
|
|
-+ * Copyright (c) 2020 Red Hat, Inc.
|
|
|
-+ * Author: Sergio Correia <scorreia@redhat.com>
|
|
|
-+ *
|
|
|
-+ * This program is free software: you can redistribute it and/or modify
|
|
|
-+ * it under the terms of the GNU General Public License as published by
|
|
|
-+ * the Free Software Foundation, either version 3 of the License, or
|
|
|
-+ * (at your option) any later version.
|
|
|
-+ *
|
|
|
-+ * This program is distributed in the hope that it will be useful,
|
|
|
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
-+ * GNU General Public License for more details.
|
|
|
-+ *
|
|
|
-+ * You should have received a copy of the GNU General Public License
|
|
|
-+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
-+ */
|
|
|
-+
|
|
|
-+#define _XOPEN_SOURCE 500L
|
|
|
-+
|
|
|
-+#include <stdarg.h>
|
|
|
-+#include <stdlib.h>
|
|
|
-+#include <string.h>
|
|
|
-+#include <unistd.h>
|
|
|
-+#include <stdio.h>
|
|
|
-+#include <ftw.h>
|
|
|
-+
|
|
|
-+#include "test-util.h"
|
|
|
-+
|
|
|
-+void
|
|
|
-+assert_func(const char* filename,
|
|
|
-+ int lineno,
|
|
|
-+ const char* funcname,
|
|
|
-+ const char* expr,
|
|
|
-+ const char* fmt,
|
|
|
-+ ...)
|
|
|
-+{
|
|
|
-+ char buffer[MAX_BUF_LEN] = {};
|
|
|
-+ if (fmt) {
|
|
|
-+ va_list ap;
|
|
|
-+ va_start(ap, fmt);
|
|
|
-+ vsnprintf(buffer, MAX_BUF_LEN, fmt, ap);
|
|
|
-+ va_end(ap);
|
|
|
-+ buffer[strcspn(buffer, "\r\n")] = '\0';
|
|
|
-+ }
|
|
|
-+ fprintf(stderr, "%s:%d: assertion '%s' failed in %s(). %s\n", filename,
|
|
|
-+ lineno,
|
|
|
-+ expr,
|
|
|
-+ funcname,
|
|
|
-+ buffer);
|
|
|
-+ abort();
|
|
|
-+}
|
|
|
-+
|
|
|
-+static int
|
|
|
-+nftw_remove_callback(const char* path, const struct stat* stat,
|
|
|
-+ int type, struct FTW* ftw)
|
|
|
-+{
|
|
|
-+ return remove(path);
|
|
|
-+}
|
|
|
-+
|
|
|
-+char*
|
|
|
-+create_tempdir(void)
|
|
|
-+{
|
|
|
-+ char template[] = "/tmp/tang.test.XXXXXX";
|
|
|
-+ char *tmpdir = mkdtemp(template);
|
|
|
-+ return strdup(tmpdir);
|
|
|
-+}
|
|
|
-+
|
|
|
-+int
|
|
|
-+remove_tempdir(const char* path)
|
|
|
-+{
|
|
|
-+ return nftw(path, nftw_remove_callback, FOPEN_MAX, FTW_DEPTH|FTW_MOUNT|FTW_PHYS);
|
|
|
-+}
|
|
|
-+
|
|
|
---- /dev/null
|
|
|
-+++ b/tests/test-util.h
|
|
|
-@@ -0,0 +1,46 @@
|
|
|
-+/* vim: set tabstop=8 shiftwidth=4 softtabstop=4 expandtab smarttab colorcolumn=80: */
|
|
|
-+/*
|
|
|
-+ * Copyright (c) 2020 Red Hat, Inc.
|
|
|
-+ * Author: Sergio Correia <scorreia@redhat.com>
|
|
|
-+ *
|
|
|
-+ * This program is free software: you can redistribute it and/or modify
|
|
|
-+ * it under the terms of the GNU General Public License as published by
|
|
|
-+ * the Free Software Foundation, either version 3 of the License, or
|
|
|
-+ * (at your option) any later version.
|
|
|
-+ *
|
|
|
-+ * This program is distributed in the hope that it will be useful,
|
|
|
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
-+ * GNU General Public License for more details.
|
|
|
-+ *
|
|
|
-+ * You should have received a copy of the GNU General Public License
|
|
|
-+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
-+ */
|
|
|
-+
|
|
|
-+#pragma once
|
|
|
-+
|
|
|
-+#include <stdarg.h>
|
|
|
-+
|
|
|
-+#define ARRAY_COUNT(arr) (sizeof(arr)/sizeof(0[arr]))
|
|
|
-+#define MAX_BUF_LEN 2048
|
|
|
-+
|
|
|
-+void
|
|
|
-+assert_func(const char* /* filename */,
|
|
|
-+ int /* line number */,
|
|
|
-+ const char* /* function name */,
|
|
|
-+ const char* /* expression */,
|
|
|
-+ const char* /* format */,
|
|
|
-+ ...);
|
|
|
-+
|
|
|
-+#define ASSERT_WITH_MSG(expr, fmt, ...) \
|
|
|
-+ if (!(expr)) \
|
|
|
-+ assert_func(__FILE__, __LINE__, __FUNCTION__, #expr, fmt, ##__VA_ARGS__)
|
|
|
-+
|
|
|
-+#define ASSERT(expr) \
|
|
|
-+ ASSERT_WITH_MSG(expr, NULL)
|
|
|
-+
|
|
|
-+char*
|
|
|
-+create_tempdir(void);
|
|
|
-+
|
|
|
-+int
|
|
|
-+remove_tempdir(const char* /* path */);
|