From: Nick Bowler Date: Fri, 4 May 2012 00:24:48 +0000 (-0400) Subject: tests: Test some corner cases of upkg_decode_index. X-Git-Url: https://git.draconx.ca/gitweb/upkg.git/commitdiff_plain/ebcf9b833bc750ce81951a3278065bbb86ecbdce tests: Test some corner cases of upkg_decode_index. It turns out that upkg_decode_index does not fail when there is not a complete index encoding in the available data. Add a test case (which currently does not pass) to verify that the function fails in that situation. --- diff --git a/.gitignore b/.gitignore index 4bc0076..d0c3877 100644 --- a/.gitignore +++ b/.gitignore @@ -26,3 +26,4 @@ lib warn-on-use.h arg-nonnull.h c++defs.h +/test-suite.log diff --git a/Makefile.am b/Makefile.am index f5c126c..eb605df 100644 --- a/Makefile.am +++ b/Makefile.am @@ -4,8 +4,11 @@ # This is free software: you are free to do what the fuck you want to. # There is NO WARRANTY, to the extent permitted by law. +AUTOMAKE_OPTIONS = parallel-tests color-tests ACLOCAL_AMFLAGS = -I m4 +AM_CPPFLAGS = -I$(top_srcdir)/src + EXTRA_DIST = m4/gnulib-cache.m4 dist_man_MANS = doc/man/upkg.1 @@ -18,3 +21,13 @@ SUBDIRS += libltdl endif SUBDIRS += src + +check_PROGRAMS = test/decodeindex +test_decodeindex_LDADD = src/libupkg.la lib/libgnu.la + +TESTS_ENVIRONMENT = SHELL='$(SHELL)' EXEEXT='$(EXEEXT)' +TEST_EXTENSIONS = .sh +SH_LOG_COMPILER = $(SHELL) + +TESTS = tests/libupkg-index-decode.sh +EXTRA_DIST += $(TESTS) diff --git a/test/.gitignore b/test/.gitignore new file mode 100644 index 0000000..cd79e46 --- /dev/null +++ b/test/.gitignore @@ -0,0 +1 @@ +decodeindex diff --git a/test/decodeindex.c b/test/decodeindex.c new file mode 100644 index 0000000..bbe15f4 --- /dev/null +++ b/test/decodeindex.c @@ -0,0 +1,165 @@ +/* + * Tool for decoding compact index values for testing. + * Copyright © 2012 Nick Bowler + * + * 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 . + */ + +#include +#include +#include +#include +#include + +#include + +#define PROGNAME "decodeindex" +static const char *progname = PROGNAME; +static const unsigned char sopts[] = "VH"; +static const struct option lopts[] = { + { "version", 0, NULL, 'V' }, + { "help", 0, NULL, 'H' }, + { 0 } +}; + +/* + * Decode a hexadecimal string into a sequence of bytes. If there are an + * odd number of nibbles, treat the first character as the least significant + * nibble of the first byte. The result is written to the buffer specified by + * buf. At most n bytes are written to the buffer. + * + * Returns the number of bytes that would be written provided that n was large + * enough, or (size_t)-1 if the input is not valid. + */ +static size_t decode_hex(const char *hex, unsigned char *buf, size_t n) +{ + size_t len, count = 0; + char tmp[] = "00"; + + for (len = 0; hex[len]; len++) { + if (!isxdigit(hex[len])) + return -1; + } + + if (!len) + return 0; + + switch (len % 2) { + while (len > 0) { + case 0: tmp[0] = *hex++; len--; + case 1: tmp[1] = *hex++; len--; + + if (count < n) + buf[count] = strtoul(tmp, NULL, 16); + count++; + } + } + + return count; +} + +static void print_usage(FILE *f) +{ + fprintf(f, "Usage: %s [options] index [index ...]\n", progname); +} + +static void print_version(void) +{ + printf("%s (%s) %s\n", PROGNAME, PACKAGE_NAME, PACKAGE_VERSION); + puts("Copyright (C) 2012 Nick Bowler."); + puts("License GPLv3+: GNU GPL version 3 or later ."); + puts("This is free software: you are free to change and redistribute it."); + puts("There is NO WARRANTY, to the extent permitted by law."); +} + +static void print_bytes(FILE *f, int indent, void *buf, size_t n) +{ + fprintf(f, "%*s", indent, ""); + for (size_t i = 0; i < n; i++) + fprintf(f, "%*s%.2hhx", i != 0, "", ((unsigned char *)buf)[i]); + putc('\n', f); +} + +static int print_index(const char *hex) +{ + unsigned char buf[32]; + long index = 0; + size_t n, rc; + int ret = -1; + + n = decode_hex(hex, buf, sizeof buf); + if (n == -1) { + fprintf(stderr, "%s: invalid hex sequence: %s\n", + progname, hex); + goto out; + } else if (n == 0) { + fprintf(stderr, "%s: empty argument\n", progname); + goto out; + } else if (n > sizeof buf) { + fprintf(stderr, "%s: hex sequence too long: %s\n", + progname, hex); + goto out; + } + + rc = upkg_decode_index(&index, buf, n); + if (rc == 0) { + fprintf(stderr, "%s: invalid index encoding:\n", progname); + print_bytes(stderr, 4, buf, n); + goto out; + } else if (rc < n) { + fprintf(stderr, "%s: trailing bytes in argument:\n", progname); + print_bytes(stderr, 4, buf+rc, n-rc); + /* Non-fatal */ + } + + ret = 0; +out: + printf("%ld\n", index); + return ret; +} + +int main(int argc, char **argv) +{ + int opt, ret = EXIT_SUCCESS; + + if (argc > 0) + progname = argv[0]; + + while ((opt = getopt_long(argc, argv, sopts, lopts, NULL)) != -1) { + switch (opt) { + case 'V': + print_version(); + return EXIT_SUCCESS; + case 'H': + print_usage(stdout); + return EXIT_SUCCESS; + default: + print_usage(stderr); + return EXIT_FAILURE; + } + } + + if (!argv[optind]) { + print_usage(stderr); + return EXIT_FAILURE; + } + + for (int i = optind; i < argc; i++) { + if (print_index(argv[i]) != 0) { + ret = EXIT_FAILURE; + } + } + + return ret; +} diff --git a/tests/.gitignore b/tests/.gitignore new file mode 100644 index 0000000..397b4a7 --- /dev/null +++ b/tests/.gitignore @@ -0,0 +1 @@ +*.log diff --git a/tests/libupkg-index-decode.sh b/tests/libupkg-index-decode.sh new file mode 100644 index 0000000..b82bbc9 --- /dev/null +++ b/tests/libupkg-index-decode.sh @@ -0,0 +1,54 @@ +#!/bin/sh +# +# Check various corner cases of upkg_decode_index. +# Copyright © 2012 Nick Bowler +# +# License WTFPL2: Do What The Fuck You Want To Public License, version 2. +# This is free software: you are free to do what the fuck you want to. +# There is NO WARRANTY, to the extent permitted by law. + +decodeindex=test/decodeindex$EXEEXT +scriptname=$0 + +test_index() { + decode_cmd=`exec 3>&1 + { $decodeindex "$1" 3>&- + echo decode_status=$? >&3 + } | { read val 3>&- + echo decode_val=$val >&3 + }` + eval "$decode_cmd" + + case $# in + 2) + (exit $decode_status) || return 1 + if test x"$decode_val" != x"$2"; then + printf '%s: result (%d) does not match expected (%d)\n' \ + "$scriptname" "$decode_val" "$2" + return 1 + fi + ;; + 1) + if (exit $decode_status); then + printf '%s: false positive on (%s), got (%d)\n' \ + "$scriptname" "$1" "$decode_val" + return 1 + fi + ;; + esac +} + +test_index 00 0 +test_index 4000 0 +test_index 408000 0 +test_index 40808000 0 +test_index 4080808000 0 + +# False positives +test_index '' +test_index 40 +test_index 4080 +test_index 408080 +test_index 40808080 +test_index 4080808080 +test_index 408080808000