/* * Unit tests for validity database operations * * Copyright (C) 2024 libfprint contributors * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. */ #include #include #include "fpi-byte-utils.h" #include "drivers/validity/validity_db.h" #include "drivers/validity/vcsfw_protocol.h" /* ================================================================ * T6.1: test_cmd_db_info * * Verify cmd 0x45 (DB info) is a single-byte command. * ================================================================ */ static void test_cmd_db_info (void) { gsize len; g_autofree guint8 *cmd = validity_db_build_cmd_info (&len); g_assert_nonnull (cmd); g_assert_cmpuint (len, ==, 1); g_assert_cmpuint (cmd[0], ==, VCSFW_CMD_DB_INFO); } /* ================================================================ * T6.2: test_cmd_get_user_storage * * Verify cmd 0x4B format with a known storage name. * ================================================================ */ static void test_cmd_get_user_storage (void) { gsize len; const gchar *name = "StgWindsor"; gsize name_len = strlen (name) + 1; /* includes NUL */ g_autofree guint8 *cmd = validity_db_build_cmd_get_user_storage (name, &len); g_assert_nonnull (cmd); g_assert_cmpuint (len, ==, 1 + 2 + 2 + name_len); /* cmd + dbid + name_len + name */ g_assert_cmpuint (cmd[0], ==, VCSFW_CMD_GET_USER_STORAGE); g_assert_cmpuint (FP_READ_UINT16_LE (&cmd[1]), ==, 0); /* dbid = 0 → lookup by name */ g_assert_cmpuint (FP_READ_UINT16_LE (&cmd[3]), ==, name_len); g_assert_cmpmem (&cmd[5], name_len, name, name_len); } /* ================================================================ * T6.3: test_cmd_get_user_storage_null_name * * When name is NULL, should produce a command with zero name_len. * ================================================================ */ static void test_cmd_get_user_storage_null_name (void) { gsize len; g_autofree guint8 *cmd = validity_db_build_cmd_get_user_storage (NULL, &len); g_assert_nonnull (cmd); g_assert_cmpuint (len, ==, 5); /* cmd(1) + dbid(2) + name_len(2) */ g_assert_cmpuint (cmd[0], ==, VCSFW_CMD_GET_USER_STORAGE); g_assert_cmpuint (FP_READ_UINT16_LE (&cmd[3]), ==, 0); /* name_len = 0 */ } /* ================================================================ * T6.4: test_cmd_get_user * * Verify cmd 0x4A format for get-by-dbid. * ================================================================ */ static void test_cmd_get_user (void) { gsize len; g_autofree guint8 *cmd = validity_db_build_cmd_get_user (0x1234, &len); g_assert_nonnull (cmd); g_assert_cmpuint (len, ==, 7); g_assert_cmpuint (cmd[0], ==, VCSFW_CMD_GET_USER); g_assert_cmpuint (FP_READ_UINT16_LE (&cmd[1]), ==, 0x1234); g_assert_cmpuint (FP_READ_UINT16_LE (&cmd[3]), ==, 0); g_assert_cmpuint (FP_READ_UINT16_LE (&cmd[5]), ==, 0); } /* ================================================================ * T6.5: test_cmd_lookup_user * * Verify cmd 0x4A format for lookup-by-identity. * ================================================================ */ static void test_cmd_lookup_user (void) { gsize len; guint8 identity[] = { 0x01, 0x02, 0x03, 0x04 }; g_autofree guint8 *cmd = validity_db_build_cmd_lookup_user ( 0x0003, identity, sizeof (identity), &len); g_assert_nonnull (cmd); g_assert_cmpuint (len, ==, 7 + sizeof (identity)); g_assert_cmpuint (cmd[0], ==, VCSFW_CMD_GET_USER); g_assert_cmpuint (FP_READ_UINT16_LE (&cmd[1]), ==, 0); /* dbid = 0 */ g_assert_cmpuint (FP_READ_UINT16_LE (&cmd[3]), ==, 0x0003); /* storage */ g_assert_cmpuint (FP_READ_UINT16_LE (&cmd[5]), ==, sizeof (identity)); g_assert_cmpmem (&cmd[7], sizeof (identity), identity, sizeof (identity)); } /* ================================================================ * T6.6: test_cmd_new_record * * Verify cmd 0x47 format. * ================================================================ */ static void test_cmd_new_record (void) { gsize len; guint8 data[] = { 0xAA, 0xBB }; g_autofree guint8 *cmd = validity_db_build_cmd_new_record ( 0x0003, 0x0005, 0x0003, data, sizeof (data), &len); g_assert_nonnull (cmd); g_assert_cmpuint (len, ==, 9 + sizeof (data)); g_assert_cmpuint (cmd[0], ==, VCSFW_CMD_NEW_RECORD); g_assert_cmpuint (FP_READ_UINT16_LE (&cmd[1]), ==, 0x0003); /* parent */ g_assert_cmpuint (FP_READ_UINT16_LE (&cmd[3]), ==, 0x0005); /* type */ g_assert_cmpuint (FP_READ_UINT16_LE (&cmd[5]), ==, 0x0003); /* storage */ g_assert_cmpuint (FP_READ_UINT16_LE (&cmd[7]), ==, sizeof (data)); g_assert_cmpmem (&cmd[9], sizeof (data), data, sizeof (data)); } /* ================================================================ * T6.7: test_cmd_del_record * * Verify cmd 0x48 format. * ================================================================ */ static void test_cmd_del_record (void) { gsize len; g_autofree guint8 *cmd = validity_db_build_cmd_del_record (0xABCD, &len); g_assert_nonnull (cmd); g_assert_cmpuint (len, ==, 3); g_assert_cmpuint (cmd[0], ==, VCSFW_CMD_DEL_RECORD); g_assert_cmpuint (FP_READ_UINT16_LE (&cmd[1]), ==, 0xABCD); } /* ================================================================ * T6.8: test_cmd_create_enrollment * * Verify cmd 0x69 start and end variants. * ================================================================ */ static void test_cmd_create_enrollment (void) { gsize len; /* Start enrollment */ g_autofree guint8 *cmd_start = validity_db_build_cmd_create_enrollment (TRUE, &len); g_assert_nonnull (cmd_start); g_assert_cmpuint (len, ==, 5); g_assert_cmpuint (cmd_start[0], ==, VCSFW_CMD_CREATE_ENROLLMENT); g_assert_cmpuint (FP_READ_UINT32_LE (&cmd_start[1]), ==, 1); /* End enrollment */ g_autofree guint8 *cmd_end = validity_db_build_cmd_create_enrollment (FALSE, &len); g_assert_nonnull (cmd_end); g_assert_cmpuint (len, ==, 5); g_assert_cmpuint (cmd_end[0], ==, VCSFW_CMD_CREATE_ENROLLMENT); g_assert_cmpuint (FP_READ_UINT32_LE (&cmd_end[1]), ==, 0); } /* ================================================================ * T6.9: test_cmd_enrollment_update_start * * Verify cmd 0x68 format. * ================================================================ */ static void test_cmd_enrollment_update_start (void) { gsize len; g_autofree guint8 *cmd = validity_db_build_cmd_enrollment_update_start (0x12345678, &len); g_assert_nonnull (cmd); g_assert_cmpuint (len, ==, 9); g_assert_cmpuint (cmd[0], ==, VCSFW_CMD_ENROLLMENT_UPDATE_START); g_assert_cmpuint (FP_READ_UINT32_LE (&cmd[1]), ==, 0x12345678); g_assert_cmpuint (FP_READ_UINT32_LE (&cmd[5]), ==, 0); } /* ================================================================ * T6.10: test_cmd_match_finger * * Verify cmd 0x5E format (13 bytes per python-validity). * ================================================================ */ static void test_cmd_match_finger (void) { gsize len; g_autofree guint8 *cmd = validity_db_build_cmd_match_finger (&len); g_assert_nonnull (cmd); g_assert_cmpuint (len, ==, 13); g_assert_cmpuint (cmd[0], ==, VCSFW_CMD_MATCH_FINGER); g_assert_cmpuint (cmd[1], ==, 0x02); g_assert_cmpuint (cmd[2], ==, 0xFF); g_assert_cmpuint (FP_READ_UINT16_LE (&cmd[3]), ==, 0); g_assert_cmpuint (FP_READ_UINT16_LE (&cmd[5]), ==, 0); g_assert_cmpuint (FP_READ_UINT16_LE (&cmd[7]), ==, 1); g_assert_cmpuint (FP_READ_UINT16_LE (&cmd[9]), ==, 0); g_assert_cmpuint (FP_READ_UINT16_LE (&cmd[11]), ==, 0); } /* ================================================================ * T6.11: test_cmd_get_match_result * * Verify cmd 0x60 format. * ================================================================ */ static void test_cmd_get_match_result (void) { gsize len; g_autofree guint8 *cmd = validity_db_build_cmd_get_match_result (&len); g_assert_nonnull (cmd); g_assert_cmpuint (len, ==, 5); g_assert_cmpuint (cmd[0], ==, VCSFW_CMD_GET_MATCH_RESULT); /* remaining bytes should be 0 */ g_assert_cmpuint (cmd[1], ==, 0); g_assert_cmpuint (cmd[2], ==, 0); g_assert_cmpuint (cmd[3], ==, 0); g_assert_cmpuint (cmd[4], ==, 0); } /* ================================================================ * T6.12: test_cmd_match_cleanup * * Verify cmd 0x62 format. * ================================================================ */ static void test_cmd_match_cleanup (void) { gsize len; g_autofree guint8 *cmd = validity_db_build_cmd_match_cleanup (&len); g_assert_nonnull (cmd); g_assert_cmpuint (len, ==, 5); g_assert_cmpuint (cmd[0], ==, VCSFW_CMD_MATCH_CLEANUP); } /* ================================================================ * T6.13: test_cmd_get_prg_status * * Verify cmd 0x51 both normal and extended variant. * ================================================================ */ static void test_cmd_get_prg_status (void) { gsize len; g_autofree guint8 *normal = validity_db_build_cmd_get_prg_status (FALSE, &len); g_assert_cmpuint (len, ==, 5); g_assert_cmpuint (normal[0], ==, VCSFW_CMD_GET_PRG_STATUS); /* Normal: 00000000 */ g_assert_cmpuint (normal[1], ==, 0); g_assert_cmpuint (normal[2], ==, 0); g_assert_cmpuint (normal[3], ==, 0); g_assert_cmpuint (normal[4], ==, 0); g_autofree guint8 *ext = validity_db_build_cmd_get_prg_status (TRUE, &len); g_assert_cmpuint (len, ==, 5); g_assert_cmpuint (ext[0], ==, VCSFW_CMD_GET_PRG_STATUS); /* Extended: 00200000 LE */ g_assert_cmpuint (ext[1], ==, 0x00); g_assert_cmpuint (ext[2], ==, 0x20); g_assert_cmpuint (ext[3], ==, 0x00); g_assert_cmpuint (ext[4], ==, 0x00); } /* ================================================================ * T6.14: test_cmd_capture_stop * * Verify cmd 0x04 format. * ================================================================ */ static void test_cmd_capture_stop (void) { gsize len; g_autofree guint8 *cmd = validity_db_build_cmd_capture_stop (&len); g_assert_nonnull (cmd); g_assert_cmpuint (len, ==, 1); g_assert_cmpuint (cmd[0], ==, VCSFW_CMD_CAPTURE_STOP); } /* ================================================================ * T6.15: test_cmd_call_cleanups * * Verify cmd 0x1a format. * ================================================================ */ static void test_cmd_call_cleanups (void) { gsize len; g_autofree guint8 *cmd = validity_db_build_cmd_call_cleanups (&len); g_assert_nonnull (cmd); g_assert_cmpuint (len, ==, 1); g_assert_cmpuint (cmd[0], ==, 0x1a); } /* ================================================================ * T6.16: test_parse_db_info * * Construct a known db_info binary response and verify parsing. * ================================================================ */ static void test_parse_db_info (void) { guint8 data[0x1C]; /* 24 bytes header + 4 bytes for 2 roots */ ValidityDbInfo info; memset (data, 0, sizeof (data)); /* Header: unknown1=1, unknown0=0, total=65536, used=1024, free=64512, records=10, n_roots=2 */ FP_WRITE_UINT32_LE (&data[0], 1); /* unknown1 */ FP_WRITE_UINT32_LE (&data[4], 0); /* unknown0 */ FP_WRITE_UINT32_LE (&data[8], 65536); /* total */ FP_WRITE_UINT32_LE (&data[12], 1024); /* used */ FP_WRITE_UINT32_LE (&data[16], 64512); /* free */ FP_WRITE_UINT16_LE (&data[20], 10); /* records */ FP_WRITE_UINT16_LE (&data[22], 2); /* n_roots */ FP_WRITE_UINT16_LE (&data[24], 0x0001); /* root[0] */ FP_WRITE_UINT16_LE (&data[26], 0x0003); /* root[1] */ g_assert_true (validity_db_parse_info (data, sizeof (data), &info)); g_assert_cmpuint (info.unknown1, ==, 1); g_assert_cmpuint (info.unknown0, ==, 0); g_assert_cmpuint (info.total, ==, 65536); g_assert_cmpuint (info.used, ==, 1024); g_assert_cmpuint (info.free_space, ==, 64512); g_assert_cmpuint (info.records, ==, 10); g_assert_cmpuint (info.n_roots, ==, 2); g_assert_nonnull (info.roots); g_assert_cmpuint (info.roots[0], ==, 1); g_assert_cmpuint (info.roots[1], ==, 3); validity_db_info_clear (&info); } /* ================================================================ * T6.17: test_parse_db_info_too_short * * A response shorter than 24 bytes should fail. * ================================================================ */ static void test_parse_db_info_too_short (void) { guint8 data[20] = { 0 }; ValidityDbInfo info; g_assert_false (validity_db_parse_info (data, sizeof (data), &info)); } /* ================================================================ * T6.18: test_parse_user_storage * * Construct a user storage response with 2 users and verify. * ================================================================ */ static void test_parse_user_storage (void) { /* Header: dbid=3, user_count=2, name_sz=11, unknown=0 * User table: {dbid=10, val_sz=100}, {dbid=11, val_sz=200} * Name: "StgWindsor\0" */ gsize name_len = strlen ("StgWindsor") + 1; gsize total = 8 + 2 * 4 + name_len; g_autofree guint8 *data = g_new0 (guint8, total); FP_WRITE_UINT16_LE (&data[0], 3); /* dbid */ FP_WRITE_UINT16_LE (&data[2], 2); /* user_count */ FP_WRITE_UINT16_LE (&data[4], name_len); /* name_sz */ FP_WRITE_UINT16_LE (&data[6], 0); /* unknown */ FP_WRITE_UINT16_LE (&data[8], 10); /* user[0].dbid */ FP_WRITE_UINT16_LE (&data[10], 100); /* user[0].val_sz */ FP_WRITE_UINT16_LE (&data[12], 11); /* user[1].dbid */ FP_WRITE_UINT16_LE (&data[14], 200); /* user[1].val_sz */ memcpy (&data[16], "StgWindsor", name_len); ValidityUserStorage storage; g_assert_true (validity_db_parse_user_storage (data, total, &storage)); g_assert_cmpuint (storage.dbid, ==, 3); g_assert_cmpuint (storage.user_count, ==, 2); g_assert_cmpstr (storage.name, ==, "StgWindsor"); g_assert_nonnull (storage.user_dbids); g_assert_cmpuint (storage.user_dbids[0], ==, 10); g_assert_cmpuint (storage.user_dbids[1], ==, 11); g_assert_cmpuint (storage.user_val_sizes[0], ==, 100); g_assert_cmpuint (storage.user_val_sizes[1], ==, 200); validity_user_storage_clear (&storage); } /* ================================================================ * T6.19: test_parse_user * * Construct a user response with one finger and verify. * ================================================================ */ static void test_parse_user (void) { guint8 identity_bytes[] = { 0xDE, 0xAD, 0xBE, 0xEF }; /* Header: dbid=10, finger_count=1, unknown=0, identity_sz=4 * Finger: dbid=20, subtype=2, storage=3, value_size=500 * Identity: 4 bytes */ gsize total = 8 + 8 + sizeof (identity_bytes); g_autofree guint8 *data = g_new0 (guint8, total); FP_WRITE_UINT16_LE (&data[0], 10); /* dbid */ FP_WRITE_UINT16_LE (&data[2], 1); /* finger_count */ FP_WRITE_UINT16_LE (&data[4], 0); /* unknown */ FP_WRITE_UINT16_LE (&data[6], sizeof (identity_bytes)); /* identity_sz */ /* Finger entry */ FP_WRITE_UINT16_LE (&data[8], 20); /* finger.dbid */ FP_WRITE_UINT16_LE (&data[10], 2); /* finger.subtype = right index */ FP_WRITE_UINT16_LE (&data[12], 3); /* finger.storage */ FP_WRITE_UINT16_LE (&data[14], 500); /* finger.value_size */ memcpy (&data[16], identity_bytes, sizeof (identity_bytes)); ValidityUser user; g_assert_true (validity_db_parse_user (data, total, &user)); g_assert_cmpuint (user.dbid, ==, 10); g_assert_cmpuint (user.finger_count, ==, 1); g_assert_nonnull (user.fingers); g_assert_cmpuint (user.fingers[0].dbid, ==, 20); g_assert_cmpuint (user.fingers[0].subtype, ==, 2); g_assert_cmpuint (user.fingers[0].storage, ==, 3); g_assert_cmpuint (user.fingers[0].value_size, ==, 500); g_assert_nonnull (user.identity); g_assert_cmpuint (user.identity_len, ==, sizeof (identity_bytes)); g_assert_cmpmem (user.identity, user.identity_len, identity_bytes, sizeof (identity_bytes)); validity_user_clear (&user); } /* ================================================================ * T6.20: test_parse_new_record_id * * Verify parsing of new_record response (cmd 0x47). * ================================================================ */ static void test_parse_new_record_id (void) { guint16 record_id; guint8 data[] = { 0x42, 0x00 }; g_assert_true (validity_db_parse_new_record_id (data, sizeof (data), &record_id)); g_assert_cmpuint (record_id, ==, 0x0042); } /* ================================================================ * T6.21: test_parse_new_record_id_too_short * * A 1-byte response should fail. * ================================================================ */ static void test_parse_new_record_id_too_short (void) { guint16 record_id; guint8 data[] = { 0x42 }; g_assert_false (validity_db_parse_new_record_id (data, sizeof (data), &record_id)); } /* ================================================================ * T6.22: test_build_identity * * Build a UUID identity and verify structure. * ================================================================ */ static void test_build_identity (void) { gsize len; const gchar *uuid = "550e8400-e29b-41d4-a716-446655440000"; g_autofree guint8 *id = validity_db_build_identity (uuid, &len); g_assert_nonnull (id); /* Minimum size enforced */ g_assert_cmpuint (len, >=, VALIDITY_IDENTITY_MIN_SIZE); /* type = SID (3) */ g_assert_cmpuint (FP_READ_UINT32_LE (&id[0]), ==, VALIDITY_IDENTITY_TYPE_SID); /* len field = UUID string length */ gsize uuid_len = strlen (uuid); g_assert_cmpuint (FP_READ_UINT32_LE (&id[4]), ==, uuid_len); /* UUID payload */ g_assert_cmpmem (&id[8], uuid_len, uuid, uuid_len); /* Remaining bytes should be zero-padded */ for (gsize i = 8 + uuid_len; i < len; i++) g_assert_cmpuint (id[i], ==, 0); } /* ================================================================ * T6.23: test_build_finger_data * * Build finger data and verify the tagged format. * ================================================================ */ static void test_build_finger_data (void) { gsize len; guint8 template[] = { 0x11, 0x22, 0x33 }; guint8 tid[] = { 0xAA, 0xBB }; g_autofree guint8 *fd = validity_db_build_finger_data ( 2, template, sizeof (template), tid, sizeof (tid), &len); g_assert_nonnull (fd); /* Check header: subtype(2) | flags=3(2) | tinfo_len(2) | 0x20(2) */ g_assert_cmpuint (FP_READ_UINT16_LE (&fd[0]), ==, 2); /* subtype */ g_assert_cmpuint (FP_READ_UINT16_LE (&fd[2]), ==, 3); /* flags */ gsize expected_tinfo_len = 4 + sizeof (template) + 4 + sizeof (tid); g_assert_cmpuint (FP_READ_UINT16_LE (&fd[4]), ==, expected_tinfo_len); g_assert_cmpuint (FP_READ_UINT16_LE (&fd[6]), ==, 0x20); /* Tag 1 (template) at offset 8 */ g_assert_cmpuint (FP_READ_UINT16_LE (&fd[8]), ==, 1); g_assert_cmpuint (FP_READ_UINT16_LE (&fd[10]), ==, sizeof (template)); g_assert_cmpmem (&fd[12], sizeof (template), template, sizeof (template)); /* Tag 2 (tid) at offset 12+3 = 15 */ gsize tid_offset = 12 + sizeof (template); g_assert_cmpuint (FP_READ_UINT16_LE (&fd[tid_offset]), ==, 2); g_assert_cmpuint (FP_READ_UINT16_LE (&fd[tid_offset + 2]), ==, sizeof (tid)); g_assert_cmpmem (&fd[tid_offset + 4], sizeof (tid), tid, sizeof (tid)); /* Total should be header(8) + tinfo + 0x20 padding */ gsize expected_total = 8 + expected_tinfo_len + 0x20; g_assert_cmpuint (len, ==, expected_total); } /* ================================================================ * T6.24: test_db_write_enable_blob * * Verify db_write_enable blob accessor returns a valid blob. * ================================================================ */ static void test_db_write_enable_blob (void) { gsize len; const guint8 *blob = validity_db_get_write_enable_blob (&len); g_assert_nonnull (blob); g_assert_cmpuint (len, >, 0); /* The 009a blob is 3621 bytes */ g_assert_cmpuint (len, ==, 3621); } /* ================================================================ * T6.25: test_parse_record_value * * Construct a record value response and verify parsing. * ================================================================ */ static void test_parse_record_value (void) { guint8 value[] = { 0x01, 0x02, 0x03 }; /* Format: dbid(2) type(2) storage(2) sz(2) pad(2) value */ gsize total = 10 + sizeof (value); g_autofree guint8 *data = g_new0 (guint8, total); FP_WRITE_UINT16_LE (&data[0], 42); /* dbid */ FP_WRITE_UINT16_LE (&data[2], 8); /* type = DATA */ FP_WRITE_UINT16_LE (&data[4], 3); /* storage */ FP_WRITE_UINT16_LE (&data[6], sizeof (value)); /* sz */ FP_WRITE_UINT16_LE (&data[8], 0); /* pad */ memcpy (&data[10], value, sizeof (value)); ValidityDbRecord record; g_assert_true (validity_db_parse_record_value (data, total, &record)); g_assert_cmpuint (record.dbid, ==, 42); g_assert_cmpuint (record.type, ==, 8); g_assert_cmpuint (record.storage, ==, 3); g_assert_nonnull (record.value); g_assert_cmpuint (record.value_len, ==, sizeof (value)); g_assert_cmpmem (record.value, record.value_len, value, sizeof (value)); validity_db_record_clear (&record); } /* ================================================================ * T6.26: test_parse_record_children * * Construct a record children response and verify parsing. * ================================================================ */ static void test_parse_record_children (void) { /* Format: dbid(2) type(2) storage(2) sz(2) cnt(2) pad(2) * children[cnt * 4: dbid(2) type(2)] */ gsize total = 12 + 2 * 4; g_autofree guint8 *data = g_new0 (guint8, total); FP_WRITE_UINT16_LE (&data[0], 3); /* dbid */ FP_WRITE_UINT16_LE (&data[2], 4); /* type = STORAGE */ FP_WRITE_UINT16_LE (&data[4], 3); /* storage */ FP_WRITE_UINT16_LE (&data[6], 0); /* sz */ FP_WRITE_UINT16_LE (&data[8], 2); /* child_count */ FP_WRITE_UINT16_LE (&data[10], 0); /* pad */ /* Children */ FP_WRITE_UINT16_LE (&data[12], 10); /* child[0].dbid */ FP_WRITE_UINT16_LE (&data[14], 5); /* child[0].type = USER */ FP_WRITE_UINT16_LE (&data[16], 11); /* child[1].dbid */ FP_WRITE_UINT16_LE (&data[18], 5); /* child[1].type = USER */ ValidityRecordChildren children; g_assert_true (validity_db_parse_record_children (data, total, &children)); g_assert_cmpuint (children.dbid, ==, 3); g_assert_cmpuint (children.type, ==, 4); g_assert_cmpuint (children.storage, ==, 3); g_assert_cmpuint (children.child_count, ==, 2); g_assert_nonnull (children.children); g_assert_cmpuint (children.children[0].dbid, ==, 10); g_assert_cmpuint (children.children[0].type, ==, 5); g_assert_cmpuint (children.children[1].dbid, ==, 11); g_assert_cmpuint (children.children[1].type, ==, 5); validity_record_children_clear (&children); } /* ================================================================ * T6.27: test_cmd_enrollment_update * * Verify cmd 0x6B format with template data. * ================================================================ */ static void test_cmd_enrollment_update (void) { gsize len; guint8 prev[] = { 0xDE, 0xAD, 0xBE, 0xEF }; g_autofree guint8 *cmd = validity_db_build_cmd_enrollment_update ( prev, sizeof (prev), &len); g_assert_nonnull (cmd); g_assert_cmpuint (len, ==, 1 + sizeof (prev)); g_assert_cmpuint (cmd[0], ==, VCSFW_CMD_ENROLLMENT_UPDATE); g_assert_cmpmem (&cmd[1], sizeof (prev), prev, sizeof (prev)); } /* ================================================================ * T6.28: test_cmd_get_record_value * * Verify cmd 0x49 format. * ================================================================ */ static void test_cmd_get_record_value (void) { gsize len; g_autofree guint8 *cmd = validity_db_build_cmd_get_record_value (0x5678, &len); g_assert_nonnull (cmd); g_assert_cmpuint (len, ==, 3); g_assert_cmpuint (cmd[0], ==, VCSFW_CMD_GET_RECORD_VALUE); g_assert_cmpuint (FP_READ_UINT16_LE (&cmd[1]), ==, 0x5678); } /* ================================================================ * T6.29: test_cmd_get_record_children * * Verify cmd 0x46 format. * ================================================================ */ static void test_cmd_get_record_children (void) { gsize len; g_autofree guint8 *cmd = validity_db_build_cmd_get_record_children (0x1234, &len); g_assert_nonnull (cmd); g_assert_cmpuint (len, ==, 3); g_assert_cmpuint (cmd[0], ==, VCSFW_CMD_GET_RECORD_CHILDREN); g_assert_cmpuint (FP_READ_UINT16_LE (&cmd[1]), ==, 0x1234); } int main (int argc, char *argv[]) { g_test_init (&argc, &argv, NULL); /* Command builder tests */ g_test_add_func ("/validity/db/cmd_db_info", test_cmd_db_info); g_test_add_func ("/validity/db/cmd_get_user_storage", test_cmd_get_user_storage); g_test_add_func ("/validity/db/cmd_get_user_storage_null_name", test_cmd_get_user_storage_null_name); g_test_add_func ("/validity/db/cmd_get_user", test_cmd_get_user); g_test_add_func ("/validity/db/cmd_lookup_user", test_cmd_lookup_user); g_test_add_func ("/validity/db/cmd_new_record", test_cmd_new_record); g_test_add_func ("/validity/db/cmd_del_record", test_cmd_del_record); g_test_add_func ("/validity/db/cmd_create_enrollment", test_cmd_create_enrollment); g_test_add_func ("/validity/db/cmd_enrollment_update_start", test_cmd_enrollment_update_start); g_test_add_func ("/validity/db/cmd_enrollment_update", test_cmd_enrollment_update); g_test_add_func ("/validity/db/cmd_match_finger", test_cmd_match_finger); g_test_add_func ("/validity/db/cmd_get_match_result", test_cmd_get_match_result); g_test_add_func ("/validity/db/cmd_match_cleanup", test_cmd_match_cleanup); g_test_add_func ("/validity/db/cmd_get_prg_status", test_cmd_get_prg_status); g_test_add_func ("/validity/db/cmd_capture_stop", test_cmd_capture_stop); g_test_add_func ("/validity/db/cmd_call_cleanups", test_cmd_call_cleanups); g_test_add_func ("/validity/db/cmd_get_record_value", test_cmd_get_record_value); g_test_add_func ("/validity/db/cmd_get_record_children", test_cmd_get_record_children); /* Response parser tests */ g_test_add_func ("/validity/db/parse_info", test_parse_db_info); g_test_add_func ("/validity/db/parse_info_too_short", test_parse_db_info_too_short); g_test_add_func ("/validity/db/parse_user_storage", test_parse_user_storage); g_test_add_func ("/validity/db/parse_user", test_parse_user); g_test_add_func ("/validity/db/parse_new_record_id", test_parse_new_record_id); g_test_add_func ("/validity/db/parse_new_record_id_too_short", test_parse_new_record_id_too_short); g_test_add_func ("/validity/db/parse_record_value", test_parse_record_value); g_test_add_func ("/validity/db/parse_record_children", test_parse_record_children); /* Identity and finger data tests */ g_test_add_func ("/validity/db/build_identity", test_build_identity); g_test_add_func ("/validity/db/build_finger_data", test_build_finger_data); /* Blob accessor test */ g_test_add_func ("/validity/db/write_enable_blob", test_db_write_enable_blob); return g_test_run (); }