diff --git a/libfprint/fpi-print.c b/libfprint/fpi-print.c index b0f5eab4..7d1ead2a 100644 --- a/libfprint/fpi-print.c +++ b/libfprint/fpi-print.c @@ -363,3 +363,68 @@ fpi_print_fill_from_user_id (FpPrint *print, const char *user_id) return FALSE; } + +/** + * fpi_print_match: + * @self: First #FpPrint + * @other: Second #FpPrint + * + * Tests whether the prints are matching. + * This is like fp_print_equal() for %FPI_PRINT_RAW prints, + * while for %FPI_PRINT_NBIS prints ensures that at least one + * sub-print minutiae matches. + * + * Returns: %TRUE if the prints are matching + */ +gboolean +fpi_print_match (FpPrint *self, FpPrint *other) +{ + g_return_val_if_fail (FP_IS_PRINT (self), FALSE); + g_return_val_if_fail (FP_IS_PRINT (other), FALSE); + g_return_val_if_fail (self->type != FPI_PRINT_UNDEFINED, FALSE); + g_return_val_if_fail (other->type != FPI_PRINT_UNDEFINED, FALSE); + + if (self == other) + return TRUE; + + switch (self->type) + { + case FPI_PRINT_RAW: + return fp_print_equal (self, other); + + case FPI_PRINT_NBIS: + { + if (other->type != FPI_PRINT_NBIS) + return FALSE; + + if (g_strcmp0 (self->driver, other->driver) != 0) + return FALSE; + + if (g_strcmp0 (self->device_id, other->device_id) != 0) + return FALSE; + + if (self->prints->len == 0 || other->prints->len == 0) + return self->prints->len == other->prints->len; + + for (guint i = 0; i < self->prints->len; i++) + { + struct xyt_struct *a = g_ptr_array_index (self->prints, i); + + for (guint j = 0; j < other->prints->len; j++) + { + struct xyt_struct *b = g_ptr_array_index (other->prints, j); + + if (memcmp (a, b, sizeof (struct xyt_struct)) == 0) + return TRUE; + } + } + + return FALSE; + } + + case FPI_PRINT_UNDEFINED: + g_assert_not_reached (); + } + + g_return_val_if_reached (FALSE); +} diff --git a/libfprint/fpi-print.h b/libfprint/fpi-print.h index 2b4b6b39..192f0a91 100644 --- a/libfprint/fpi-print.h +++ b/libfprint/fpi-print.h @@ -35,6 +35,10 @@ void fpi_print_add_print (FpPrint *print, void fpi_print_set_type (FpPrint *print, FpiPrintType type); + +gboolean fpi_print_match (FpPrint *self, + FpPrint *other); + void fpi_print_set_device_stored (FpPrint *print, gboolean device_stored); diff --git a/tests/test-fpi-device.c b/tests/test-fpi-device.c index deee5c26..df258502 100644 --- a/tests/test-fpi-device.c +++ b/tests/test-fpi-device.c @@ -3907,6 +3907,170 @@ test_fp_print_equal_different_types (void) g_assert_false (fp_print_equal (print_b, print_a)); } +static void +test_fpi_print_match_same (void) +{ + g_autoptr(FpDevice) device = g_object_new (FPI_TYPE_DEVICE_FAKE, NULL); + g_autoptr(FpPrint) print_a = NULL; + g_autoptr(FpPrint) print_b = NULL; + + print_a = make_fake_print (device, g_variant_new_string ("test")); + print_b = make_fake_print (device, g_variant_new_string ("test")); + + g_assert_true (fpi_print_match (print_a, print_b)); + g_assert_true (fpi_print_match (print_a, print_a)); + g_assert_true (fpi_print_match (print_b, print_b)); +} + +static void +test_fpi_print_match_different (void) +{ + g_autoptr(FpDevice) device = g_object_new (FPI_TYPE_DEVICE_FAKE, NULL); + g_autoptr(FpPrint) print_a = NULL; + g_autoptr(FpPrint) print_b = NULL; + + print_a = make_fake_print (device, g_variant_new_string ("test")); + print_b = make_fake_print (device, g_variant_new_string ("other")); + + g_assert_false (fpi_print_match (print_a, print_b)); +} + +static void +test_fpi_print_match_nbis_empty (void) +{ + g_autoptr(FpDevice) device = g_object_new (FPI_TYPE_DEVICE_FAKE, NULL); + g_autoptr(FpPrint) print_a = NULL; + g_autoptr(FpPrint) print_b = NULL; + + print_a = make_fake_nbis_print (device); + print_b = make_fake_nbis_print (device); + + g_assert_true (fpi_print_match (print_a, print_b)); + g_assert_true (fpi_print_match (print_a, print_a)); + g_assert_true (fpi_print_match (print_b, print_b)); +} + +static void +test_fpi_print_match_nbis_one_empty (void) +{ + g_autoptr(FpDevice) device = g_object_new (FPI_TYPE_DEVICE_FAKE, NULL); + g_autoptr(FpPrint) print_a = NULL; + g_autoptr(FpPrint) print_b = NULL; + gint xvals[] = { 10, 20 }; + gint yvals[] = { 30, 40 }; + gint tvals[] = { 50, 60 }; + + print_a = make_fake_nbis_print_filled (device, xvals, yvals, tvals, 2, 1); + print_b = make_fake_nbis_print (device); + + g_assert_false (fpi_print_match (print_a, print_b)); + g_assert_false (fpi_print_match (print_b, print_a)); +} + +static void +test_fpi_print_match_nbis_equal (void) +{ + g_autoptr(FpDevice) device = g_object_new (FPI_TYPE_DEVICE_FAKE, NULL); + g_autoptr(FpPrint) print_a = NULL; + g_autoptr(FpPrint) print_b = NULL; + gint xvals[] = { 10, 20 }; + gint yvals[] = { 30, 40 }; + gint tvals[] = { 50, 60 }; + + print_a = make_fake_nbis_print_filled (device, xvals, yvals, tvals, 2, 1); + print_b = make_fake_nbis_print_filled (device, xvals, yvals, tvals, 2, 1); + + g_assert_true (fpi_print_match (print_a, print_b)); +} + +static void +test_fpi_print_match_nbis_different (void) +{ + g_autoptr(FpDevice) device = g_object_new (FPI_TYPE_DEVICE_FAKE, NULL); + g_autoptr(FpPrint) print_a = NULL; + g_autoptr(FpPrint) print_b = NULL; + gint xvals_a[] = { 10, 20 }; + gint yvals_a[] = { 30, 40 }; + gint tvals_a[] = { 50, 60 }; + gint xvals_b[] = { 99, 88 }; + gint yvals_b[] = { 77, 66 }; + gint tvals_b[] = { 55, 44 }; + + print_a = make_fake_nbis_print_filled (device, xvals_a, yvals_a, tvals_a, 2, 1); + print_b = make_fake_nbis_print_filled (device, xvals_b, yvals_b, tvals_b, 2, 1); + + g_assert_false (fpi_print_match (print_a, print_b)); +} + +static void +test_fpi_print_match_nbis_template_scanned (void) +{ + g_autoptr(FpDevice) device = g_object_new (FPI_TYPE_DEVICE_FAKE, NULL); + gint xvals[] = { 10, 20 }; + gint yvals[] = { 30, 40 }; + gint tvals[] = { 50, 60 }; + g_autoptr(FpPrint) template = NULL; + g_autoptr(FpPrint) scanned = NULL; + + template = make_fake_nbis_print_filled (device, xvals, yvals, tvals, 2, 5); + scanned = make_fake_nbis_print_filled (device, xvals, yvals, tvals, 2, 1); + + g_assert_true (fpi_print_match (template, scanned)); + g_assert_true (fpi_print_match (scanned, template)); +} + +static void +test_fpi_print_match_nbis_template_scanned_no_match (void) +{ + g_autoptr(FpDevice) device = g_object_new (FPI_TYPE_DEVICE_FAKE, NULL); + gint xvals_t[] = { 10, 20 }; + gint yvals_t[] = { 30, 40 }; + gint tvals_t[] = { 50, 60 }; + gint xvals_s[] = { 99, 88 }; + gint yvals_s[] = { 77, 66 }; + gint tvals_s[] = { 55, 44 }; + g_autoptr(FpPrint) template = NULL; + g_autoptr(FpPrint) scanned = NULL; + + template = make_fake_nbis_print_filled (device, xvals_t, yvals_t, tvals_t, 2, 5); + scanned = make_fake_nbis_print_filled (device, xvals_s, yvals_s, tvals_s, 2, 1); + + g_assert_false (fpi_print_match (template, scanned)); + g_assert_false (fpi_print_match (scanned, template)); +} + +static void +test_fpi_print_match_nbis_match_any_position (void) +{ + g_autoptr(FpDevice) device = g_object_new (FPI_TYPE_DEVICE_FAKE, NULL); + g_autoptr(FpPrint) print_a = NULL; + g_autoptr(FpPrint) print_b = NULL; + gint xvals_a[] = { 10, 20 }; + gint yvals_a[] = { 30, 40 }; + gint tvals_a[] = { 50, 60 }; + gint xvals_b[] = { 99, 88 }; + gint yvals_b[] = { 77, 66 }; + gint tvals_b[] = { 55, 44 }; + gint xvals_match[] = { 10, 20 }; + gint yvals_match[] = { 30, 40 }; + gint tvals_match[] = { 50, 60 }; + struct xyt_struct *xyt_match = g_new0 (struct xyt_struct, 1); + + print_a = make_fake_nbis_print_filled (device, xvals_a, yvals_a, tvals_a, 2, 1); + print_b = make_fake_nbis_print_filled (device, xvals_b, yvals_b, tvals_b, 2, 1); + + xyt_match->nrows = 2; + xyt_match->xcol[0] = xvals_match[0]; + xyt_match->ycol[0] = yvals_match[0]; + xyt_match->thetacol[0] = tvals_match[0]; + xyt_match->xcol[1] = xvals_match[1]; + xyt_match->ycol[1] = yvals_match[1]; + xyt_match->thetacol[1] = tvals_match[1]; + g_ptr_array_add (print_b->prints, xyt_match); + + g_assert_true (fpi_print_match (print_a, print_b)); +} + int main (int argc, char *argv[]) { @@ -4041,5 +4205,17 @@ main (int argc, char *argv[]) g_test_add_func ("/print/equal/different_types", test_fp_print_equal_different_types); + g_test_add_func ("/print/match/same", test_fpi_print_match_same); + g_test_add_func ("/print/match/different", test_fpi_print_match_different); + g_test_add_func ("/print/match/nbis_empty", test_fpi_print_match_nbis_empty); + g_test_add_func ("/print/match/nbis_one_empty", test_fpi_print_match_nbis_one_empty); + g_test_add_func ("/print/match/nbis_equal", test_fpi_print_match_nbis_equal); + g_test_add_func ("/print/match/nbis_different", test_fpi_print_match_nbis_different); + g_test_add_func ("/print/match/nbis_template_scanned", test_fpi_print_match_nbis_template_scanned); + g_test_add_func ("/print/match/nbis_template_scanned_no_match", + test_fpi_print_match_nbis_template_scanned_no_match); + g_test_add_func ("/print/match/nbis_match_any_position", + test_fpi_print_match_nbis_match_any_position); + return g_test_run (); }