more randomized testing
diff --git a/tests/tests-randomized/check-bundles.sh b/tests/tests-randomized/check-bundles.sh
index 30944f2..f9e2b4d 100755
--- a/tests/tests-randomized/check-bundles.sh
+++ b/tests/tests-randomized/check-bundles.sh
@@ -8,7 +8,6 @@
 
 set -e
 
-
 usage() {
     echo "Usage:"
     echo "  $0 -h"
@@ -21,8 +20,15 @@
     exit 1
 }
 
+RNDTEMP=.tmp.random
+
+srcdir="${srcdir:-.}"
+abs_top_srcdir="${abs_top_srcdir:-$(pwd)/../../}"
+abs_top_builddir="${abs_top_builddir:-$(pwd)/../../}"
+
 tests_succeeded=0
 tests_failed=0
+stop_after_failed=1  # We stop after 3 failures.
 
 # Get all the type-bearding lines in file and process them individually
 verify_asn_types_in_file() {
@@ -42,6 +48,10 @@
             continue;
         fi
         verify_asn_type "$asn" "in $filename $line"
+        if [ "${tests_failed}" = "${stop_after_failed}" ]; then
+            echo "STOP after ${tests_failed} failures, OK ${tests_succeeded}"
+            exit 1
+        fi
     done < "$filename"
 }
 
@@ -55,8 +65,8 @@
     fi
     echo "Testing [$asn] ${where}"
 
-    mkdir -p .tmp.random
-    if (cd .tmp.random && compile_and_test "$asn" "$@"); then
+    mkdir -p ${RNDTEMP}
+    if (cd ${RNDTEMP} && compile_and_test "$asn" "$@"); then
         echo "OK [$asn] ${where}"
         tests_succeeded=$((tests_succeeded+1))
     else
@@ -77,20 +87,29 @@
     rm -f random-test-driver.o
     rm -f random-test-driver
     if ! make -j4; then
-        echo "Cannot compile C for $asn in .tmp.random"
+        echo "Cannot compile C for $asn in ${RNDTEMP}"
         return 2
     fi
 
     echo "Checking random data encode-decode"
     if ! eval ${ASAN_ENV_FLAGS} ./random-test-driver -c; then
+        echo "RETRY:"
+        echo "(cd ${RNDTEMP} && CC=${CC} CFLAGS=\"${LIBFUZZER_CFLAGS} ${CFLAGS}\" make && ${ASAN_ENV_FLAGS} ./random-test-driver -c)"
         return 3
     fi
 
+    echo "Generating new random data"
+    rm -rf random-data
+    cmd="${ASAN_ENV_FLAGS} UBSAN_OPTIONS=print_stacktrace=1"
+    cmd+=" ./random-test-driver -g random-data"
+    if ! eval "$cmd" ; then
+        echo "RETRY:"
+        echo "(cd ${RNDTEMP} && $cmd)"
+        return 4
+    fi
+
     # If LIBFUZZER_CFLAGS are properly defined, do the fuzz test as well
     if echo "${LIBFUZZER_CFLAGS}" | grep -qi "[a-z]"; then
-        echo "Generating new random data"
-        rm -rf random-data
-        ./random-test-driver -g random-data
 
         echo "Recompiling for fuzzing..."
         rm -f random-test-driver.o
@@ -99,23 +118,35 @@
 
         # Do a LibFuzzer based testing
         fuzz_time=10
-        echo "Fuzzing will take $fuzz_time seconds..."
-        set -x
-        eval ${ASAN_ENV_FLAGS} UBSAN_OPTIONS=print_stacktrace=1 \
-        ./random-test-driver \
-        -timeout=3 -max_total_time=${fuzz_time} -max_len=128
+        for data_dir in random-data/*; do
+            echo "Fuzzing $data_dir will take $fuzz_time seconds..."
+            local cmd="${ASAN_ENV_FLAGS} UBSAN_OPTIONS=print_stacktrace=1"
+            cmd+=" ASN1_DATA_DIR=$data_dir" # Dir for our code
+            cmd+=" ./random-test-driver"
+            cmd+=" -timeout=3 -max_total_time=${fuzz_time} -max_len=128"
+            cmd+=" $data_dir"               # Dir for LLVM fuzzer driver
+            echo "$cmd"
+            if ! eval "$cmd" ; then
+                echo "RETRY $data_dir:"
+                echo "(cd ${RNDTEMP} && CC=${CC} CFLAGS=\"${LIBFUZZER_CFLAGS} ${CFLAGS}\" make && $cmd)"
+                return 5
+            fi
+        done
     fi
 
     return 0;
 }
 
-srcdir="${srcdir:-.}"
-abs_top_srcdir="${abs_top_srcdir:-$(pwd)/../../}"
-abs_top_builddir="${abs_top_builddir:-$(pwd)/../../}"
-
 asn_compile() {
     local asn="$1"
     shift
+
+    # Create "INTEGER (1..2)" from "T ::= INTEGER (1..2) -- Comment"
+    local short_asn=$(echo "$asn" | sed -e 's/ *--.*//')
+    if [ $(echo "$short_asn" | grep -c "::=") = 1 ]; then
+        short_asn=$(echo "$short_asn" | sed -e 's/.*::= *//')
+    fi
+
     test ! -f Makefile.am   # Protection from accidental clobbering
     echo "Test DEFINITIONS ::= BEGIN $asn" > test.asn1
     echo "END" >> test.asn1
@@ -123,8 +154,9 @@
         -gen-OER -gen-PER test.asn1
     rm -f converter-example.c
     ln -sf ../random-test-driver.c || cp ../random-test-driver.c .
+    echo "CFLAGS+= -DASN1_TEXT='$short_asn'" > Makefile
     sed -e 's/converter-example/random-test-driver/' \
-        < Makefile.am.example > Makefile
+        < Makefile.am.example >> Makefile
     echo "Makefile.am.example -> Makefile"
 }
 
diff --git a/tests/tests-randomized/random-test-driver.c b/tests/tests-randomized/random-test-driver.c
index dade655..1e2a863 100644
--- a/tests/tests-randomized/random-test-driver.c
+++ b/tests/tests-randomized/random-test-driver.c
@@ -6,12 +6,72 @@
 #include <sys/stat.h>
 #include <sysexits.h>
 
+#ifdef ASN1_TEXT
+#define STRINGIFY(x)    #x
+#define ASN1_STR    STRINGIFY(ASN1_TEXT)
+#else
+#define ASN1_STR    "T"
+#endif
+
+static const struct encoding_map {
+    const char *name;
+    const char *dir_name;
+    enum asn_transfer_syntax syntax;
+} encodings[] = {
+    {"DER", "der", ATS_DER},
+    {"OER", "oer", ATS_CANONICAL_OER},
+    {"UPER", "uper", ATS_UNALIGNED_CANONICAL_PER},
+    {"XER", "xer", ATS_CANONICAL_XER},
+};
+
+static enum asn_transfer_syntax
+lookup_syntax(const char *name) {
+    if(name) {
+        for(size_t i = 0; i < sizeof(encodings) / sizeof(encodings[0]); i++) {
+            struct encoding_map enc = encodings[i];
+            if(strcasecmp(name, enc.name) == 0) {
+                return enc.syntax;
+            }
+        }
+    }
+    return ATS_INVALID;
+}
+
+
 #ifdef  ENABLE_LIBFUZZER
 
+static int initialized;
+static enum asn_transfer_syntax syntax;
+static void __attribute__((constructor)) initialize() {
+    initialized = 1;
+    const char *data_dir = getenv("ASN1_DATA_DIR");
+    if(data_dir && strrchr(data_dir, '/')) {
+        data_dir = strrchr(data_dir, '/') + 1;
+    }
+    syntax = lookup_syntax(data_dir);
+    if(syntax == ATS_INVALID) {
+        fprintf(stderr,
+                "Expected ASN1_DATA_DIR={der,oer,uper,xer} environment "
+                "variable.\n");
+        exit(EX_UNAVAILABLE);
+    }
+}
+
 int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size);
 
 int
 LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
+    if(!initialized) exit(0);
+
+    /*
+     * Try to decode whatever garbage that comes in Data/Size.
+     * The idea is that we should not crash, and we should not leak memory,
+     * no matter what garbage we're dealing with.
+     */
+    T_t *structure = 0;
+    (void)asn_decode(0, syntax, &asn_DEF_T, (void **)&structure, Data, Size);
+    ASN_STRUCT_FREE(asn_DEF_T, structure);
+
     return 0;
 }
 
@@ -35,27 +95,6 @@
             progname);
 }
 
-static const struct encoding_map {
-    const char *name;
-    enum asn_transfer_syntax syntax;
-} encodings[] = {
-    {"der", ATS_DER},
-    {"oer", ATS_CANONICAL_OER},
-    {"uper", ATS_UNALIGNED_CANONICAL_PER},
-    {"xer", ATS_CANONICAL_XER},
-};
-
-static enum asn_transfer_syntax
-lookup_encoding(const char *name) {
-    for(size_t i = 0; i < sizeof(encodings)/sizeof(encodings[0]); i++) {
-        struct encoding_map enc = encodings[i];
-        if(strcasecmp(name, enc.name) == 0) {
-            return enc.syntax;
-        }
-    }
-    return ATS_INVALID;
-}
-
 static int
 file_write_cb(const void *data, size_t size, void *key) {
     return fwrite(data, 1, size, (FILE *)key) == size ? 0 : -1;
@@ -71,7 +110,7 @@
         struct encoding_map enc = encodings[i];
         if(enc.syntax == syntax) {
             int r = snprintf(dirname, sizeof(dirname), "%s/%s", top_dirname,
-                             enc.name);
+                             enc.dir_name);
             if(r >= sizeof(dirname) - sizeof("filename.bin")) {
                 fprintf(stderr, "Too long filenames\n");
                 exit(EX_SOFTWARE);
@@ -172,6 +211,14 @@
         for(;;) {
             er = asn_encode_to_buffer(
                 0, syntax, &asn_DEF_T, structure, buffer, buffer_size);
+            if(er.encoded == -1) {
+                fprintf(stderr, "Encoded T into %zd bytes\n", er.encoded);
+                fprintf(stderr, "Structure %s:\n",
+                        sizeof(ASN1_STR) > 60 ? "T" : ASN1_STR);
+                asn_fprint(stderr, &asn_DEF_T, structure);
+                assert(er.encoded >= 0);
+                exit(EX_SOFTWARE);
+            }
             if(er.encoded > buffer_size && buffer == tmp_buffer) {
                 buffer = malloc(er.encoded + 1);
                 assert(buffer);
@@ -187,8 +234,15 @@
             asn_decode(0, syntax, &asn_DEF_T, (void **)&decoded_structure,
                        buffer, er.encoded);
         if(rval.code == RC_OK) {
-            assert(rval.consumed == er.encoded);
-            /* Everything's cool */
+            /* Everything's cool... or is it? Expecting a proper consumed */
+            if(rval.consumed != er.encoded) {
+                fprintf(stderr, "Encoded into %zd, yet consumed %zu",
+                        er.encoded, rval.consumed);
+                fprintf(stderr, "Structure:\n");
+                asn_fprint(stderr, &asn_DEF_T, structure);
+                assert(rval.consumed == er.encoded);
+                exit(EX_SOFTWARE);
+            }
         } else {
             fprintf(stderr,
                     "Decoding %zu bytes of T yielded %s after byte %zu\n",
@@ -199,6 +253,20 @@
             exit(EX_SOFTWARE);
         }
 
+        /*
+         * Confirm that we decoded the same data.
+         */
+        int cmp = asn_DEF_T.op->compare_struct(&asn_DEF_T, structure,
+                                               decoded_structure);
+        if(cmp != 0) {
+            fprintf(stderr, "Random %s value:\n", ASN1_STR);
+            asn_fprint(stderr, &asn_DEF_T, structure);
+            fprintf(stderr, "Decoded %s value:\n", ASN1_STR);
+            asn_fprint(stderr, &asn_DEF_T, decoded_structure);
+            assert(cmp == 0);
+        }
+        ASN_STRUCT_FREE(asn_DEF_T, structure);
+        ASN_STRUCT_FREE(asn_DEF_T, decoded_structure);
 
         if(buffer != tmp_buffer) {
             free(buffer);
@@ -235,7 +303,7 @@
             mode = MODE_CHECK_RANDOM_ROUNDTRIP;
             break;
         case 'e':
-            enabled_encodings |= 1 << lookup_encoding(optarg);
+            enabled_encodings |= 1 << lookup_syntax(optarg);
             if(enabled_encodings & (1 << ATS_INVALID)) {
                 fprintf(stderr, "-e %s: Unknown (unsupported?) encoding\n",
                         optarg);