# 81-libmaxminddb.test — libmaxminddb 1.4.3 (MaxMind DB reader) on wasm32-hwjs. # # The subject is a library, and mmdblookup(1) is how a target shell reaches it: # every case below is MMDB_open -> MMDB_lookup_string -> MMDB_get_value -> # MMDB_get_entry_data_list driven from argv, against upstream's OWN test # databases (data/maxminddb-*.mmdb, copied verbatim out of the MaxMind-DB # repository vendored in the release tarball at t/maxmind-db/test-data; # CC BY-SA 3.0, (c) MaxMind Inc.). Every expected value below was measured from # a native x86_64 control build of the same 1.4.3 release, not read off a spec. # # THIS SUITE IS ALSO THE VIRTIOFS mmap PROBE, and that is why it is arranged the # way it is. MMDB_open maps the whole database -- mmap(NULL, size, PROT_READ, # MAP_SHARED, fd, 0), unconditionally, with no read() fallback -- so a mapping # that succeeds but hands back zero pages decodes as a corrupt database rather # than as an I/O error. That failure shape is documented on this platform # (BRINTOS-38, libmagic's compiled DB) and every probe since has been run under # ${TMPDIR:-/tmp}: logrotate's MAP_PRIVATE config reader, libowfat's RT07-RT09, # lmdb. All of them measured TMPFS. libowfat's test-plan entry says so and calls # the virtiofs root still unmeasured. # # $BST_DATA is on the virtiofs root, so this suite closes that gap by reading # the SAME database twice -- in place, and from a copy under ${TMPDIR:-/tmp} -- # and asserting the two agree byte for byte. Read the three cases together: # # vfs-* red, tmpfs-* green -> mmap on virtiofs, not libmaxminddb # both red -> file-backed mmap generally # both green -> virtiofs mmap works; this suite is the witness # # The identity/packaging cases run FIRST and touch no database at all, so a red # in the decode block is attributable rather than ambiguous. . "$BST_LIB" require mmdblookup libmaxminddb/present DEC="$BST_DATA/maxminddb-decoder.mmdb" # every MMDB data type, at 1.1.1.0 V4="$BST_DATA/maxminddb-ipv4-24.mmdb" # IPv4 tree, 24-bit records V6="$BST_DATA/maxminddb-ipv6-32.mmdb" # IPv6 tree, 32-bit records CITY="$BST_DATA/maxminddb-city.mmdb" # GeoIP2-City shaped record BADPTR="$BST_DATA/maxminddb-broken-pointers.mmdb" BADMETA="$BST_DATA/maxminddb-invalid-metadata.mmdb" # --- identity and packaging (no database is opened here) ---------------------- check_out libmaxminddb/version "mmdblookup version 1.4.3" mmdblookup --version check_out libmaxminddb/help "--file" mmdblookup --help check_eq libmaxminddb/resolves-to-port /usr/bin/mmdblookup "$(command -v mmdblookup)" if busybox mmdblookup --help >/dev/null 2>&1; then bst_notok libmaxminddb/no-busybox-applet "busybox provides an mmdblookup applet; the port is being shadowed" else bst_ok libmaxminddb/no-busybox-applet fi check libmaxminddb/staticlib test -f /usr/lib/libmaxminddb.a check libmaxminddb/header test -f /usr/include/maxminddb.h check libmaxminddb/pkgconfig test -f /usr/lib/pkgconfig/libmaxminddb.pc # Static-only is a distro invariant, so assert the ABSENCE directly rather than # inferring it from the presence of the archive. if [ -e /usr/lib/libmaxminddb.so ] || [ -n "$(echo /usr/lib/libmaxminddb.so.* 2>/dev/null | grep -v '\*')" ]; then bst_notok libmaxminddb/no-sharedlib "a libmaxminddb.so* exists on a static-only image" else bst_ok libmaxminddb/no-sharedlib fi # --- the mmap answer: same database, virtiofs root vs tmpfs ------------------- check_out libmaxminddb/vfs-open "Database metadata" mmdblookup --file "$DEC" --ip 1.1.1.0 uint32 --verbose check_out libmaxminddb/vfs-decode "268435456" mmdblookup --file "$DEC" --ip 1.1.1.0 uint32 TMP=${TMPDIR:-/tmp}/bst-mmdb.$$ mkdir -p "$TMP" if cp "$DEC" "$TMP/decoder.mmdb" 2>/dev/null; then check_out libmaxminddb/tmpfs-open "Database metadata" mmdblookup --file "$TMP/decoder.mmdb" --ip 1.1.1.0 uint32 --verbose check_out libmaxminddb/tmpfs-decode "268435456" mmdblookup --file "$TMP/decoder.mmdb" --ip 1.1.1.0 uint32 vfs_out=$(mmdblookup --file "$DEC" --ip 1.1.1.0 utf8_string 2>&1) tmp_out=$(mmdblookup --file "$TMP/decoder.mmdb" --ip 1.1.1.0 utf8_string 2>&1) check_eq libmaxminddb/vfs-matches-tmpfs "$tmp_out" "$vfs_out" else bst_notok libmaxminddb/tmpfs-open "could not stage a tmpfs copy of $DEC" bst_notok libmaxminddb/tmpfs-decode "could not stage a tmpfs copy of $DEC" bst_notok libmaxminddb/vfs-matches-tmpfs "could not stage a tmpfs copy of $DEC" fi # --- metadata (read from the head of the mapping) ----------------------------- check_out libmaxminddb/meta-node-count "Node count: 395" mmdblookup --file "$DEC" --ip 1.1.1.0 uint32 --verbose check_out libmaxminddb/meta-record-size "Record size: 24 bits" mmdblookup --file "$DEC" --ip 1.1.1.0 uint32 --verbose check_out libmaxminddb/meta-ip-version "IP version: IPv6" mmdblookup --file "$DEC" --ip 1.1.1.0 uint32 --verbose check_out libmaxminddb/meta-type "Type: MaxMind DB Decoder Test" mmdblookup --file "$DEC" --ip 1.1.1.0 uint32 --verbose check_out libmaxminddb/meta-build-epoch "1494631301" mmdblookup --file "$DEC" --ip 1.1.1.0 uint32 --verbose # The bracketed form of that epoch is gmtime(3)+strftime(3) on the target, not # libmaxminddb -- a separate case so a broken time conversion is not read as a # broken metadata decode. check_out libmaxminddb/meta-epoch-formatted "(2017-05-12 23:21:41 UTC)" mmdblookup --file "$DEC" --ip 1.1.1.0 uint32 --verbose # --- every MMDB data type, decoded from the shipped corpus -------------------- check_out libmaxminddb/type-utf8-string "unicode! ☯ - ♫" mmdblookup --file "$DEC" --ip 1.1.1.0 utf8_string check_out libmaxminddb/type-boolean "true" mmdblookup --file "$DEC" --ip 1.1.1.0 boolean check_out libmaxminddb/type-uint16 "100" mmdblookup --file "$DEC" --ip 1.1.1.0 uint16 check_out libmaxminddb/type-uint32 "268435456" mmdblookup --file "$DEC" --ip 1.1.1.0 uint32 check_out libmaxminddb/type-int32 "-268435456" mmdblookup --file "$DEC" --ip 1.1.1.0 int32 check_out libmaxminddb/type-uint64 "1152921504606846976" mmdblookup --file "$DEC" --ip 1.1.1.0 uint64 # uint128 is a 16-byte quantity printed as hex; on a 32-bit target it exercises # whichever of MMDB_UINT128_IS_BYTE_ARRAY / __int128 configure selected. check_out libmaxminddb/type-uint128 "0x01000000000000000000000000000000" mmdblookup --file "$DEC" --ip 1.1.1.0 uint128 check_out libmaxminddb/type-bytes "0000002A" mmdblookup --file "$DEC" --ip 1.1.1.0 bytes # double/float are IEEE-754 formatted through printf; wasm has the arithmetic # but the formatting is glibc's. check_out libmaxminddb/type-double "42.123456" mmdblookup --file "$DEC" --ip 1.1.1.0 double check_out libmaxminddb/type-float "1.100000" mmdblookup --file "$DEC" --ip 1.1.1.0 float check_out libmaxminddb/type-array-index "2" mmdblookup --file "$DEC" --ip 1.1.1.0 array 1 check_out libmaxminddb/type-map-nested "hello" mmdblookup --file "$DEC" --ip 1.1.1.0 map mapX utf8_stringX # --- the search tree ---------------------------------------------------------- check_out libmaxminddb/ipv4-lookup "1.1.1.1" mmdblookup --file "$V4" --ip 1.1.1.1 check_out libmaxminddb/ipv6-lookup "::2:0:0" mmdblookup --file "$V6" --ip ::2:0:1 check_rc libmaxminddb/ipv4-not-found 6 mmdblookup --file "$V4" --ip 9.9.9.9 check_out libmaxminddb/city-country "GB" mmdblookup --file "$CITY" --ip 2.125.160.216 country iso_code check_out libmaxminddb/city-name "Boxford" mmdblookup --file "$CITY" --ip 2.125.160.216 city names en # --- negative paths: each must be REFUSED, and refused distinguishably -------- check_rc libmaxminddb/missing-file 2 mmdblookup --file /nonexistent.mmdb --ip 1.1.1.1 check_rc libmaxminddb/bad-ip 3 mmdblookup --file "$DEC" --ip not-an-ip check_rc libmaxminddb/broken-pointers 4 mmdblookup --file "$BADPTR" --ip 1.1.1.32 check_rc libmaxminddb/invalid-metadata 2 mmdblookup --file "$BADMETA" --ip 2.125.160.216 # The refusal must name the reason, not just fail: a zero-filled mapping would # also refuse this database, and with a DIFFERENT message. check_out cannot be # used because the command is expected to exit non-zero. bad_out=$(mmdblookup --file "$BADMETA" --ip 2.125.160.216 2>&1) case "$bad_out" in *"invalid metadata"*) bst_ok libmaxminddb/invalid-metadata-msg ;; *) bst_notok libmaxminddb/invalid-metadata-msg "want:'invalid metadata' got:'$(_bst_1line "$bad_out")'" ;; esac rm -rf "$TMP" # A file that dies partway through simply gets smaller, and a smaller suite reads # as a passing one in a summary that only counts cases. This sentinel is the last # line, so its absence is the truncation. bst_ok libmaxminddb/suite-complete