--- /dev/null
+#!/bin/sh
+
+test_description="Various generic tests"
+. $SHARNESS_TEST_SRCDIR/sharness.sh
+root=$(realpath ../..)
+SCHEMA_VALIDATE=${SCHEMA_VALIDATE:-schema-validate}
+export TCLLIBPATH=$root
+
+cat >schema.tcl <<EOF
+e {{field . {str bin}}}
+EOF
+$root/schema.tcl schema.tcl | xxd -r -p >schema.keks
+$root/keks.tcl >data.keks.hex <<EOF
+STR ok
+EOF
+xxd -r -p <data.keks.hex >data.keks
+test_expect_success "type ok" "$SCHEMA_VALIDATE schema.keks e <data.keks"
+
+$root/keks.tcl >data.keks.hex <<EOF
+BIN ok
+EOF
+xxd -r -p <data.keks.hex >data.keks
+test_expect_success "type ok" "$SCHEMA_VALIDATE schema.keks e <data.keks"
+
+$root/keks.tcl >data.keks.hex <<EOF
+INT 123
+EOF
+xxd -r -p <data.keks.hex >data.keks
+test_expect_success "type !ok" "! $SCHEMA_VALIDATE schema.keks e <data.keks"
+
+########################################################################
+
+cat >schema.tcl <<EOF
+e {{field . {set}}}
+EOF
+$root/schema.tcl schema.tcl | xxd -r -p >schema.keks
+$root/keks.tcl >data.keks.hex <<EOF
+MAP {foo NIL bar NIL baz NIL}
+EOF
+xxd -r -p <data.keks.hex >data.keks
+test_expect_success "set ok" "$SCHEMA_VALIDATE schema.keks e <data.keks"
+
+$root/keks.tcl >data.keks.hex <<EOF
+MAP {foo NIL bar NIL baz {INT 123}}
+EOF
+xxd -r -p <data.keks.hex >data.keks
+test_expect_success "set !ok" "! $SCHEMA_VALIDATE schema.keks e <data.keks"
+
+$root/keks.tcl >data.keks.hex <<EOF
+SET {foo bar baz}
+EOF
+xxd -r -p <data.keks.hex >data.keks
+test_expect_success "set macro" "$SCHEMA_VALIDATE schema.keks e <data.keks"
+
+########################################################################
+
+cat >schema.tcl <<EOF
+e {{field . {map}}}
+EOF
+$root/schema.tcl schema.tcl | xxd -r -p >schema.keks
+$root/keks.tcl >data.keks.hex <<EOF
+MAP {foo {INT 123} bar {STR hello}}
+EOF
+xxd -r -p <data.keks.hex >data.keks
+test_expect_success "map various" "$SCHEMA_VALIDATE schema.keks e <data.keks"
+
+cat >schema.tcl <<EOF
+e {{field . {map} {of int}}}
+EOF
+$root/schema.tcl schema.tcl | xxd -r -p >schema.keks
+$root/keks.tcl >data.keks.hex <<EOF
+MAP {foo {INT 123} bar {STR hello}}
+EOF
+xxd -r -p <data.keks.hex >data.keks
+test_expect_success "map !of int" "! $SCHEMA_VALIDATE schema.keks e <data.keks"
+
+$root/keks.tcl >data.keks.hex <<EOF
+MAP {foo {INT 123} bar {INT 234}}
+EOF
+xxd -r -p <data.keks.hex >data.keks
+test_expect_success "map of int" "$SCHEMA_VALIDATE schema.keks e <data.keks"
+
+cat >schema.tcl <<EOF
+v {{field . {int}}}
+e {{field . {map} {of v}}}
+EOF
+$root/schema.tcl schema.tcl | xxd -r -p >schema.keks
+$root/keks.tcl >data.keks.hex <<EOF
+MAP {foo {INT 123} bar {INT 234}}
+EOF
+xxd -r -p <data.keks.hex >data.keks
+test_expect_success "map of int schema" "$SCHEMA_VALIDATE schema.keks e <data.keks"
+
+########################################################################
+
+cat >schema.tcl <<EOF
+e {{field . {list}}}
+EOF
+$root/schema.tcl schema.tcl | xxd -r -p >schema.keks
+$root/keks.tcl >data.keks.hex <<EOF
+LIST {{INT 123} {STR hello}}
+EOF
+xxd -r -p <data.keks.hex >data.keks
+test_expect_success "list various" "$SCHEMA_VALIDATE schema.keks e <data.keks"
+
+cat >schema.tcl <<EOF
+e {{field . {list} {of int}}}
+EOF
+$root/schema.tcl schema.tcl | xxd -r -p >schema.keks
+$root/keks.tcl >data.keks.hex <<EOF
+LIST {{INT 123} {STR hello}}
+EOF
+xxd -r -p <data.keks.hex >data.keks
+test_expect_success "list !of int" "! $SCHEMA_VALIDATE schema.keks e <data.keks"
+
+$root/keks.tcl >data.keks.hex <<EOF
+LIST {{INT 123} {INT 234}}
+EOF
+xxd -r -p <data.keks.hex >data.keks
+test_expect_success "list of int" "$SCHEMA_VALIDATE schema.keks e <data.keks"
+
+cat >schema.tcl <<EOF
+v {{field . {int}}}
+e {{field . {list} {of v}}}
+EOF
+$root/schema.tcl schema.tcl | xxd -r -p >schema.keks
+$root/keks.tcl >data.keks.hex <<EOF
+LIST {{INT 123} {INT 234}}
+EOF
+xxd -r -p <data.keks.hex >data.keks
+test_expect_success "list of int schema" "$SCHEMA_VALIDATE schema.keks e <data.keks"
+
+########################################################################
+
+cat >schema.tcl <<EOF
+v {{field . {int}}}
+e {{field . {with v}}}
+EOF
+$root/schema.tcl schema.tcl | xxd -r -p >schema.keks
+$root/keks.tcl >data.keks.hex <<EOF
+STR foo
+EOF
+xxd -r -p <data.keks.hex >data.keks
+test_expect_success "!only schema" "! $SCHEMA_VALIDATE schema.keks e <data.keks"
+
+$root/keks.tcl >data.keks.hex <<EOF
+INT -123
+EOF
+xxd -r -p <data.keks.hex >data.keks
+test_expect_success "only schema" "$SCHEMA_VALIDATE schema.keks e <data.keks"
+
+########################################################################
+
+cat >schema.tcl <<EOF
+e {{field bar {int}}}
+EOF
+$root/schema.tcl schema.tcl | xxd -r -p >schema.keks
+$root/keks.tcl >data.keks.hex <<EOF
+MAP {foo NIL bar {INT 0}}
+EOF
+xxd -r -p <data.keks.hex >data.keks
+test_expect_success "map exists" "$SCHEMA_VALIDATE schema.keks e <data.keks"
+
+$root/keks.tcl >data.keks.hex <<EOF
+MAP {foo NIL baz {INT 0}}
+EOF
+xxd -r -p <data.keks.hex >data.keks
+test_expect_success "map !exists" "! $SCHEMA_VALIDATE schema.keks e <data.keks"
+
+cat >schema.tcl <<EOF
+e {{field bar {int} optional}}
+EOF
+$root/schema.tcl schema.tcl | xxd -r -p >schema.keks
+$root/keks.tcl >data.keks.hex <<EOF
+MAP {foo NIL bar {INT 0}}
+EOF
+xxd -r -p <data.keks.hex >data.keks
+test_expect_success "map optional" "$SCHEMA_VALIDATE schema.keks e <data.keks"
+
+$root/keks.tcl >data.keks.hex <<EOF
+MAP {foo NIL baz {INT 0}}
+EOF
+xxd -r -p <data.keks.hex >data.keks
+test_expect_success "map optional !exists" "$SCHEMA_VALIDATE schema.keks e <data.keks"
+
+$root/keks.tcl >data.keks.hex <<EOF
+MAP {foo NIL bar NIL}
+EOF
+xxd -r -p <data.keks.hex >data.keks
+test_expect_success "map optional bad type" "! $SCHEMA_VALIDATE schema.keks e <data.keks"
+
+cat >schema.tcl <<EOF
+e {{field bar {} !exists}}
+EOF
+$root/schema.tcl schema.tcl | xxd -r -p >schema.keks
+$root/keks.tcl >data.keks.hex <<EOF
+MAP {foo NIL bar {INT 0}}
+EOF
+xxd -r -p <data.keks.hex >data.keks
+test_expect_success "map !!exists" "! $SCHEMA_VALIDATE schema.keks e <data.keks"
+
+$root/keks.tcl >data.keks.hex <<EOF
+MAP {foo NIL baz {INT 0}}
+EOF
+xxd -r -p <data.keks.hex >data.keks
+test_expect_success "map !exists" "$SCHEMA_VALIDATE schema.keks e <data.keks"
+
+########################################################################
+
+cat >schema.tcl <<EOF
+e {{field . {int} >0}}
+EOF
+$root/schema.tcl schema.tcl | xxd -r -p >schema.keks
+$root/keks.tcl >data.keks.hex <<EOF
+INT 0
+EOF
+xxd -r -p <data.keks.hex >data.keks
+test_expect_success "int !>0" "! $SCHEMA_VALIDATE schema.keks e <data.keks"
+
+$root/keks.tcl >data.keks.hex <<EOF
+INT 1
+EOF
+xxd -r -p <data.keks.hex >data.keks
+test_expect_success "int >0" "$SCHEMA_VALIDATE schema.keks e <data.keks"
+
+cat >schema.tcl <<EOF
+e {{field . {int} >-1000}}
+EOF
+$root/schema.tcl schema.tcl | xxd -r -p >schema.keks
+$root/keks.tcl >data.keks.hex <<EOF
+INT -1000
+EOF
+xxd -r -p <data.keks.hex >data.keks
+test_expect_success "int !>-999" "! $SCHEMA_VALIDATE schema.keks e <data.keks"
+
+$root/keks.tcl >data.keks.hex <<EOF
+INT -999
+EOF
+xxd -r -p <data.keks.hex >data.keks
+test_expect_success "int >-999" "$SCHEMA_VALIDATE schema.keks e <data.keks"
+
+########################################################################
+
+cat >schema.tcl <<EOF
+e {{field . {str} >0}}
+EOF
+$root/schema.tcl schema.tcl | xxd -r -p >schema.keks
+$root/keks.tcl >data.keks.hex <<EOF
+STR ""
+EOF
+xxd -r -p <data.keks.hex >data.keks
+test_expect_success "str !>0" "! $SCHEMA_VALIDATE schema.keks e <data.keks"
+
+$root/keks.tcl >data.keks.hex <<EOF
+STR "a"
+EOF
+xxd -r -p <data.keks.hex >data.keks
+test_expect_success "str >0" "$SCHEMA_VALIDATE schema.keks e <data.keks"
+
+########################################################################
+
+cat >schema.tcl <<EOF
+e {{field . {list} >0}}
+EOF
+$root/schema.tcl schema.tcl | xxd -r -p >schema.keks
+$root/keks.tcl >data.keks.hex <<EOF
+LIST {}
+EOF
+xxd -r -p <data.keks.hex >data.keks
+test_expect_success "list !>0" "! $SCHEMA_VALIDATE schema.keks e <data.keks"
+
+$root/keks.tcl >data.keks.hex <<EOF
+LIST {NIL}
+EOF
+xxd -r -p <data.keks.hex >data.keks
+test_expect_success "list >0" "$SCHEMA_VALIDATE schema.keks e <data.keks"
+
+########################################################################
+
+cat >schema.tcl <<EOF
+e {{field . {map} >0}}
+EOF
+$root/schema.tcl schema.tcl | xxd -r -p >schema.keks
+$root/keks.tcl >data.keks.hex <<EOF
+MAP {}
+EOF
+xxd -r -p <data.keks.hex >data.keks
+test_expect_success "map !>0" "! $SCHEMA_VALIDATE schema.keks e <data.keks"
+
+$root/keks.tcl >data.keks.hex <<EOF
+SET {a}
+EOF
+xxd -r -p <data.keks.hex >data.keks
+test_expect_success "map >0" "$SCHEMA_VALIDATE schema.keks e <data.keks"
+
+########################################################################
+
+cat >schema.tcl <<EOF
+e {{field . {map} len=0}}
+EOF
+$root/schema.tcl schema.tcl | xxd -r -p >schema.keks
+$root/keks.tcl >data.keks.hex <<EOF
+MAP {}
+EOF
+xxd -r -p <data.keks.hex >data.keks
+test_expect_success "map len=0" "$SCHEMA_VALIDATE schema.keks e <data.keks"
+
+cat >schema.tcl <<EOF
+e {{field . {list} len=0}}
+EOF
+$root/schema.tcl schema.tcl | xxd -r -p >schema.keks
+$root/keks.tcl >data.keks.hex <<EOF
+LIST {}
+EOF
+xxd -r -p <data.keks.hex >data.keks
+test_expect_success "list len=0" "$SCHEMA_VALIDATE schema.keks e <data.keks"
+
+cat >schema.tcl <<EOF
+e {{field . {str} len=0}}
+EOF
+$root/schema.tcl schema.tcl | xxd -r -p >schema.keks
+$root/keks.tcl >data.keks.hex <<EOF
+STR ""
+EOF
+xxd -r -p <data.keks.hex >data.keks
+test_expect_success "str len=0" "$SCHEMA_VALIDATE schema.keks e <data.keks"
+
+cat >schema.tcl <<EOF
+e {{field . {int} len=0}}
+EOF
+$root/schema.tcl schema.tcl | xxd -r -p >schema.keks
+$root/keks.tcl >data.keks.hex <<EOF
+INT 0
+EOF
+xxd -r -p <data.keks.hex >data.keks
+test_expect_success "int len=0" "$SCHEMA_VALIDATE schema.keks e <data.keks"
+
+########################################################################
+
+cat >schema.tcl <<EOF
+e {{field . {map} len=3}}
+EOF
+$root/schema.tcl schema.tcl | xxd -r -p >schema.keks
+$root/keks.tcl >data.keks.hex <<EOF
+SET {a b c}
+EOF
+xxd -r -p <data.keks.hex >data.keks
+test_expect_success "map len=3" "$SCHEMA_VALIDATE schema.keks e <data.keks"
+
+cat >schema.tcl <<EOF
+e {{field . {list} len=3}}
+EOF
+$root/schema.tcl schema.tcl | xxd -r -p >schema.keks
+$root/keks.tcl >data.keks.hex <<EOF
+LIST {NIL NIL NIL}
+EOF
+xxd -r -p <data.keks.hex >data.keks
+test_expect_success "list len=3" "$SCHEMA_VALIDATE schema.keks e <data.keks"
+
+cat >schema.tcl <<EOF
+e {{field . {str} len=3}}
+EOF
+$root/schema.tcl schema.tcl | xxd -r -p >schema.keks
+$root/keks.tcl >data.keks.hex <<EOF
+STR foo
+EOF
+xxd -r -p <data.keks.hex >data.keks
+test_expect_success "str len=3" "$SCHEMA_VALIDATE schema.keks e <data.keks"
+
+cat >schema.tcl <<EOF
+e {{field . {int} len=3}}
+EOF
+$root/schema.tcl schema.tcl | xxd -r -p >schema.keks
+$root/keks.tcl >data.keks.hex <<EOF
+INT 3
+EOF
+xxd -r -p <data.keks.hex >data.keks
+test_expect_success "int len=0" "$SCHEMA_VALIDATE schema.keks e <data.keks"
+
+########################################################################
+
+cat >schema.tcl <<EOF
+fpr {{field . {bin} len=4}}
+e {
+ {field . {map}}
+ {field fpr {with fpr} optional}
+}
+EOF
+$root/schema.tcl schema.tcl | xxd -r -p >schema.keks
+$root/keks.tcl >data.keks.hex <<EOF
+MAP {}
+EOF
+xxd -r -p <data.keks.hex >data.keks
+test_expect_success "fpr !exists" "$SCHEMA_VALIDATE schema.keks e <data.keks"
+
+$root/keks.tcl >data.keks.hex <<EOF
+MAP {fpr {STR 1234}}
+EOF
+xxd -r -p <data.keks.hex >data.keks
+test_expect_success "fpr bad type" "! $SCHEMA_VALIDATE schema.keks e <data.keks"
+
+$root/keks.tcl >data.keks.hex <<EOF
+MAP {fpr {BIN 1234}}
+EOF
+xxd -r -p <data.keks.hex >data.keks
+test_expect_success "fpr ok" "$SCHEMA_VALIDATE schema.keks e <data.keks"
+
+########################################################################
+
+cat >schema.tcl <<EOF
+e {{field . {tai}}}
+EOF
+$root/schema.tcl schema.tcl | xxd -r -p >schema.keks
+$root/keks.tcl >data.keks.hex <<EOF
+TAI64 123 123 123
+EOF
+xxd -r -p <data.keks.hex >data.keks
+test_expect_success "tai64 ok" "$SCHEMA_VALIDATE schema.keks e <data.keks"
+
+$root/keks.tcl >data.keks.hex <<EOF
+TAI64 [expr 0x586846A4]
+EOF
+xxd -r -p <data.keks.hex >data.keks
+test_expect_success "tai64 !utc" "$SCHEMA_VALIDATE schema.keks e <data.keks"
+
+cat >schema.tcl <<EOF
+e {{field . {tai} utc}}
+EOF
+$root/schema.tcl schema.tcl | xxd -r -p >schema.keks
+$root/keks.tcl >data.keks.hex <<EOF
+TAI64 [expr 0x586846A4]
+EOF
+xxd -r -p <data.keks.hex >data.keks
+test_expect_success "tai64 !!utc" "! $SCHEMA_VALIDATE schema.keks e <data.keks"
+
+########################################################################
+
+cat >schema.tcl <<EOF
+e {{field . {tai} prec=s}}
+EOF
+$root/schema.tcl schema.tcl | xxd -r -p >schema.keks
+$root/keks.tcl >data.keks.hex <<EOF
+TAI64 123
+EOF
+xxd -r -p <data.keks.hex >data.keks
+test_expect_success "tai64 prec=s" "$SCHEMA_VALIDATE schema.keks e <data.keks"
+
+$root/keks.tcl >data.keks.hex <<EOF
+TAI64 123 123
+EOF
+xxd -r -p <data.keks.hex >data.keks
+test_expect_success "tai64 !prec=s" "! $SCHEMA_VALIDATE schema.keks e <data.keks"
+
+cat >schema.tcl <<EOF
+e {{field . {tai} prec=ms}}
+EOF
+$root/schema.tcl schema.tcl | xxd -r -p >schema.keks
+$root/keks.tcl >data.keks.hex <<EOF
+TAI64 123 123000000
+EOF
+xxd -r -p <data.keks.hex >data.keks
+test_expect_success "tai64 prec=ms" "$SCHEMA_VALIDATE schema.keks e <data.keks"
+
+$root/keks.tcl >data.keks.hex <<EOF
+TAI64 123 123000
+EOF
+xxd -r -p <data.keks.hex >data.keks
+test_expect_success "tai64 !prec=ms" "! $SCHEMA_VALIDATE schema.keks e <data.keks"
+
+cat >schema.tcl <<EOF
+e {{field . {tai} prec=us}}
+EOF
+$root/schema.tcl schema.tcl | xxd -r -p >schema.keks
+$root/keks.tcl >data.keks.hex <<EOF
+TAI64 123 123000
+EOF
+xxd -r -p <data.keks.hex >data.keks
+test_expect_success "tai64 prec=us" "$SCHEMA_VALIDATE schema.keks e <data.keks"
+
+$root/keks.tcl >data.keks.hex <<EOF
+TAI64 123 123
+EOF
+xxd -r -p <data.keks.hex >data.keks
+test_expect_success "tai64 !prec=us" "! $SCHEMA_VALIDATE schema.keks e <data.keks"
+
+cat >schema.tcl <<EOF
+e {{field . {tai} prec=ns}}
+EOF
+$root/schema.tcl schema.tcl | xxd -r -p >schema.keks
+$root/keks.tcl >data.keks.hex <<EOF
+TAI64 123 123
+EOF
+xxd -r -p <data.keks.hex >data.keks
+test_expect_success "tai64 prec=ns" "$SCHEMA_VALIDATE schema.keks e <data.keks"
+$root/keks.tcl >data.keks.hex <<EOF
+TAI64 123
+EOF
+xxd -r -p <data.keks.hex >data.keks
+test_expect_success "tai64 prec=ns" "$SCHEMA_VALIDATE schema.keks e <data.keks"
+
+$root/keks.tcl >data.keks.hex <<EOF
+TAI64 123 123 123
+EOF
+xxd -r -p <data.keks.hex >data.keks
+test_expect_success "tai64 !prec=ns" "! $SCHEMA_VALIDATE schema.keks e <data.keks"
+
+cat >schema.tcl <<EOF
+e {{field . {tai} prec=ps}}
+EOF
+$root/schema.tcl schema.tcl | xxd -r -p >schema.keks
+$root/keks.tcl >data.keks.hex <<EOF
+TAI64 123 123 123000000
+EOF
+xxd -r -p <data.keks.hex >data.keks
+test_expect_success "tai64 prec=ps" "$SCHEMA_VALIDATE schema.keks e <data.keks"
+$root/keks.tcl >data.keks.hex <<EOF
+TAI64 123 123
+EOF
+xxd -r -p <data.keks.hex >data.keks
+test_expect_success "tai64 prec=ps" "$SCHEMA_VALIDATE schema.keks e <data.keks"
+
+$root/keks.tcl >data.keks.hex <<EOF
+TAI64 123 123 123000
+EOF
+xxd -r -p <data.keks.hex >data.keks
+test_expect_success "tai64 !prec=ps" "! $SCHEMA_VALIDATE schema.keks e <data.keks"
+
+cat >schema.tcl <<EOF
+e {{field . {tai} prec=fs}}
+EOF
+$root/schema.tcl schema.tcl | xxd -r -p >schema.keks
+$root/keks.tcl >data.keks.hex <<EOF
+TAI64 123 123 123000
+EOF
+xxd -r -p <data.keks.hex >data.keks
+test_expect_success "tai64 prec=fs" "$SCHEMA_VALIDATE schema.keks e <data.keks"
+
+$root/keks.tcl >data.keks.hex <<EOF
+TAI64 123 123 123
+EOF
+xxd -r -p <data.keks.hex >data.keks
+test_expect_success "tai64 !prec=fs" "! $SCHEMA_VALIDATE schema.keks e <data.keks"
+
+cat >schema.tcl <<EOF
+e {{field . {tai}}}
+EOF
+$root/schema.tcl schema.tcl | xxd -r -p >schema.keks
+$root/keks.tcl >data.keks.hex <<EOF
+TAI64 123 123 123
+EOF
+xxd -r -p <data.keks.hex >data.keks
+test_expect_success "tai64 prec=fs" "$SCHEMA_VALIDATE schema.keks e <data.keks"
+
+########################################################################
+
+$root/keks.tcl >schema.keks.hex <<EOF
+MAGIC schema
+MAP {e {LIST {
+ {LIST {{STR .} {STR .}}}
+ {LIST {{STR T} {STR LIST}}}
+ {LIST {{STR *}}}
+ {LIST {{STR T} {STR INT}}}
+ {LIST {{STR >} {INT 100}}}
+ {LIST {{STR <} {INT 300}}}
+}}}
+EOF
+xxd -r -p <schema.keks.hex >schema.keks
+$root/keks.tcl >data.keks.hex <<EOF
+LIST {{INT 123} {INT 234}}
+EOF
+xxd -r -p <data.keks.hex >data.keks
+test_expect_success "manual int ranges" "$SCHEMA_VALIDATE schema.keks e <data.keks"
+
+test_done