/* * Copyright (C) 2010 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License version 3 as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * Authored by * Neil Jagdish Patel * Mikkel Kamstrup Erlandsen * Michal Hruby * */ #include #include #include #include typedef struct { DeeModel *model; } RowsFixture; static void seq_rows_setup (RowsFixture *fix, gconstpointer data); static void seq_rows_teardown (RowsFixture *fix, gconstpointer data); static void proxy_rows_setup (RowsFixture *fix, gconstpointer data); static void proxy_rows_teardown (RowsFixture *fix, gconstpointer data); static void txn_rows_setup (RowsFixture *fix, gconstpointer data); static void txn_rows_teardown (RowsFixture *fix, gconstpointer data); static void seq_rows_asv_setup (RowsFixture *fix, gconstpointer data); static void proxy_rows_asv_setup (RowsFixture *fix, gconstpointer data); static void txn_rows_asv_setup (RowsFixture *fix, gconstpointer data); static void test_rows_allocation (RowsFixture *fix, gconstpointer data); static void test_rows_clear (RowsFixture *fix, gconstpointer data); static void test_insert_at_pos (RowsFixture *fix, gconstpointer data); static void test_insert_at_iter (RowsFixture *fix, gconstpointer data); static void test_prepend (RowsFixture *fix, gconstpointer data); static void test_append (RowsFixture *fix, gconstpointer data); static void test_get_value (RowsFixture *fix, gconstpointer data); static void test_no_transfer (RowsFixture *fix, gconstpointer data); static void test_iter_backwards (RowsFixture *fix, gconstpointer data); static void test_illegal_access (RowsFixture *fix, gconstpointer data); static void test_sorted (RowsFixture *fix, gconstpointer data); static void test_sort_stable (RowsFixture *fix, gconstpointer data); static void test_sorted_with_sizes (RowsFixture *fix, gconstpointer data); static void test_named_cols_append (RowsFixture *fix, gconstpointer data); static void test_named_cols_fields (RowsFixture *fix, gconstpointer data); static void test_named_cols_duplicated_fields (RowsFixture *fix, gconstpointer data); static void test_named_cols_error (RowsFixture *fix, gconstpointer data); static void test_model_iter_copy (RowsFixture *fix, gconstpointer data); static void test_model_iter_free (RowsFixture *fix, gconstpointer data); void test_model_rows_create_suite (void) { #define ITER_DOMAIN "/ModelIter/Boxing" #define SEQ_DOMAIN "/Model/Sequence/Rows" #define PROXY_DOMAIN "/Model/Proxy/Rows" #define TXN_DOMAIN "/Model/Transaction/Rows" g_test_add (ITER_DOMAIN"/Copy", RowsFixture, 0, seq_rows_setup, test_model_iter_copy, seq_rows_teardown); g_test_add (ITER_DOMAIN"/Free", RowsFixture, 0, seq_rows_setup, test_model_iter_free, seq_rows_teardown); g_test_add (SEQ_DOMAIN"/Allocation", RowsFixture, 0, seq_rows_setup, test_rows_allocation, seq_rows_teardown); g_test_add (PROXY_DOMAIN"/Allocation", RowsFixture, 0, proxy_rows_setup, test_rows_allocation, proxy_rows_teardown); g_test_add (TXN_DOMAIN"/Allocation", RowsFixture, 0, txn_rows_setup, test_rows_allocation, txn_rows_teardown); g_test_add (SEQ_DOMAIN"/Clear", RowsFixture, 0, seq_rows_setup, test_rows_clear, seq_rows_teardown); g_test_add (PROXY_DOMAIN"/Clear", RowsFixture, 0, proxy_rows_setup, test_rows_clear, proxy_rows_teardown); g_test_add (TXN_DOMAIN"/Clear", RowsFixture, 0, txn_rows_setup, test_rows_clear, txn_rows_teardown); g_test_add (SEQ_DOMAIN"/InsertAtPos", RowsFixture, 0, seq_rows_setup, test_insert_at_pos, seq_rows_teardown); g_test_add (PROXY_DOMAIN"/InsertAtPos", RowsFixture, 0, proxy_rows_setup, test_insert_at_pos, proxy_rows_teardown); g_test_add (TXN_DOMAIN"/InsertAtPos", RowsFixture, 0, txn_rows_setup, test_insert_at_pos, txn_rows_teardown); g_test_add (SEQ_DOMAIN"/InsertAtIter", RowsFixture, 0, seq_rows_setup, test_insert_at_iter, seq_rows_teardown); g_test_add (PROXY_DOMAIN"/InsertAtIter", RowsFixture, 0, proxy_rows_setup, test_insert_at_iter, proxy_rows_teardown); g_test_add (TXN_DOMAIN"/InsertAtIter", RowsFixture, 0, txn_rows_setup, test_insert_at_iter, txn_rows_teardown); g_test_add (SEQ_DOMAIN"/Prepend", RowsFixture, 0, seq_rows_setup, test_prepend, seq_rows_teardown); g_test_add (PROXY_DOMAIN"/Prepend", RowsFixture, 0, proxy_rows_setup, test_prepend, proxy_rows_teardown); g_test_add (TXN_DOMAIN"/Prepend", RowsFixture, 0, txn_rows_setup, test_prepend, txn_rows_teardown); g_test_add (SEQ_DOMAIN"/Append", RowsFixture, 0, seq_rows_setup, test_append, seq_rows_teardown); g_test_add (PROXY_DOMAIN"/Append", RowsFixture, 0, proxy_rows_setup, test_append, proxy_rows_teardown); g_test_add (TXN_DOMAIN"/Append", RowsFixture, 0, txn_rows_setup, test_append, txn_rows_teardown); g_test_add (SEQ_DOMAIN"/GetValue", RowsFixture, 0, seq_rows_setup, test_get_value, seq_rows_teardown); g_test_add (PROXY_DOMAIN"/GetValue", RowsFixture, 0, proxy_rows_setup, test_get_value, proxy_rows_teardown); g_test_add (TXN_DOMAIN"/GetValue", RowsFixture, 0, txn_rows_setup, test_get_value, txn_rows_teardown); g_test_add (SEQ_DOMAIN"/NoTransfer", RowsFixture, 0, seq_rows_setup, test_no_transfer, seq_rows_teardown); g_test_add (PROXY_DOMAIN"/NoTransfer", RowsFixture, 0, proxy_rows_setup, test_no_transfer, proxy_rows_teardown); g_test_add (TXN_DOMAIN"/NoTransfer", RowsFixture, 0, txn_rows_setup, test_no_transfer, txn_rows_teardown); g_test_add (SEQ_DOMAIN"/IterBackwards", RowsFixture, 0, seq_rows_setup, test_iter_backwards, seq_rows_teardown); g_test_add (PROXY_DOMAIN"/IterBackwards", RowsFixture, 0, proxy_rows_setup, test_iter_backwards, proxy_rows_teardown); g_test_add (TXN_DOMAIN"/IterBackwards", RowsFixture, 0, txn_rows_setup, test_iter_backwards, txn_rows_teardown); g_test_add (SEQ_DOMAIN"/IllegalAccess", RowsFixture, 0, seq_rows_setup, test_illegal_access, seq_rows_teardown); g_test_add (PROXY_DOMAIN"/IllegalAccess", RowsFixture, 0, proxy_rows_setup, test_illegal_access, proxy_rows_teardown); g_test_add (TXN_DOMAIN"/IllegalAccess", RowsFixture, 0, txn_rows_setup, test_illegal_access, txn_rows_teardown); g_test_add (SEQ_DOMAIN"/Sorted", RowsFixture, 0, seq_rows_setup, test_sorted, seq_rows_teardown); g_test_add (PROXY_DOMAIN"/Sorted", RowsFixture, 0, proxy_rows_setup, test_sorted, proxy_rows_teardown); g_test_add (TXN_DOMAIN"/Sorted", RowsFixture, 0, txn_rows_setup, test_sorted, txn_rows_teardown); g_test_add (SEQ_DOMAIN"/Sorted/WithSizes", RowsFixture, 0, seq_rows_setup, test_sorted_with_sizes, seq_rows_teardown); g_test_add (PROXY_DOMAIN"/Sorted/WithSizes", RowsFixture, 0, proxy_rows_setup, test_sorted_with_sizes, proxy_rows_teardown); g_test_add (TXN_DOMAIN"/Sorted/WithSizes", RowsFixture, 0, txn_rows_setup, test_sorted_with_sizes, txn_rows_teardown); g_test_add (SEQ_DOMAIN"/StableSorted", RowsFixture, 0, seq_rows_setup, test_sort_stable, seq_rows_teardown); g_test_add (PROXY_DOMAIN"/StableSorted", RowsFixture, 0, proxy_rows_setup, test_sort_stable, proxy_rows_teardown); g_test_add (TXN_DOMAIN"/StableSorted", RowsFixture, 0, txn_rows_setup, test_sort_stable, txn_rows_teardown); g_test_add (SEQ_DOMAIN"/NamedColumns/Append", RowsFixture, 0, seq_rows_setup, test_named_cols_append, seq_rows_teardown); g_test_add (PROXY_DOMAIN"/NamedColumns/Append", RowsFixture, 0, proxy_rows_setup, test_named_cols_append, proxy_rows_teardown); g_test_add (TXN_DOMAIN"/NamedColumns/Append", RowsFixture, 0, txn_rows_setup, test_named_cols_append, txn_rows_teardown); g_test_add (SEQ_DOMAIN"/NamedColumns/Fields", RowsFixture, 0, seq_rows_asv_setup, test_named_cols_fields, seq_rows_teardown); g_test_add (PROXY_DOMAIN"/NamedColumns/Fields", RowsFixture, 0, proxy_rows_asv_setup, test_named_cols_fields, proxy_rows_teardown); g_test_add (TXN_DOMAIN"/NamedColumns/Fields", RowsFixture, 0, txn_rows_asv_setup, test_named_cols_fields, txn_rows_teardown); g_test_add (SEQ_DOMAIN"/NamedColumns/DuplicatedFields", RowsFixture, 0, seq_rows_asv_setup, test_named_cols_duplicated_fields, seq_rows_teardown); g_test_add (PROXY_DOMAIN"/NamedColumns/DuplicatedFields", RowsFixture, 0, proxy_rows_asv_setup, test_named_cols_duplicated_fields, proxy_rows_teardown); g_test_add (TXN_DOMAIN"/NamedColumns/DuplicatedFields", RowsFixture, 0, txn_rows_asv_setup, test_named_cols_duplicated_fields, txn_rows_teardown); g_test_add (SEQ_DOMAIN"/NamedColumns/Invalid", RowsFixture, 0, seq_rows_setup, test_named_cols_error, seq_rows_teardown); g_test_add (PROXY_DOMAIN"/NamedColumns/Invalid", RowsFixture, 0, proxy_rows_setup, test_named_cols_error, proxy_rows_teardown); g_test_add (TXN_DOMAIN"/NamedColumns/Invalid", RowsFixture, 0, txn_rows_setup, test_named_cols_error, txn_rows_teardown); } /* setup & teardown functions */ static void seq_rows_setup (RowsFixture *fix, gconstpointer data) { fix->model = dee_sequence_model_new (); dee_model_set_schema (fix->model, "i", "s", NULL); g_assert (DEE_IS_SEQUENCE_MODEL (fix->model)); } static void seq_rows_teardown (RowsFixture *fix, gconstpointer data) { g_object_unref (fix->model); fix->model = NULL; } static void proxy_rows_setup (RowsFixture *fix, gconstpointer data) { seq_rows_setup (fix, data); fix->model = g_object_new (DEE_TYPE_PROXY_MODEL, "back-end", fix->model, NULL); g_assert (DEE_IS_PROXY_MODEL (fix->model)); } static void proxy_rows_teardown (RowsFixture *fix, gconstpointer data) { g_object_unref (fix->model); fix->model = NULL; } static void txn_rows_setup (RowsFixture *fix, gconstpointer data) { seq_rows_setup (fix, data); fix->model = dee_transaction_new (fix->model); g_assert (DEE_IS_TRANSACTION (fix->model)); } static void txn_rows_teardown (RowsFixture *fix, gconstpointer data) { g_object_unref (fix->model); fix->model = NULL; } static void seq_rows_asv_setup (RowsFixture *fix, gconstpointer data) { fix->model = dee_sequence_model_new (); dee_model_set_schema (fix->model, "i", "s", "a{sv}", "a{sv}", NULL); dee_model_set_column_names (fix->model, "count", "name", "hints", "hints2", NULL); g_assert (DEE_IS_SEQUENCE_MODEL (fix->model)); } static void proxy_rows_asv_setup (RowsFixture *fix, gconstpointer data) { seq_rows_asv_setup (fix, data); fix->model = g_object_new (DEE_TYPE_PROXY_MODEL, "back-end", fix->model, NULL); g_assert (DEE_IS_PROXY_MODEL (fix->model)); } static void txn_rows_asv_setup (RowsFixture *fix, gconstpointer data) { seq_rows_asv_setup (fix, data); fix->model = dee_transaction_new (fix->model); g_assert (DEE_IS_TRANSACTION (fix->model)); } /* test cases */ static void test_model_iter_copy (RowsFixture *fix, gconstpointer data) { DeeModelIter *iter, *copied; iter = dee_model_append (fix->model, 10, "Rooney"); copied = g_boxed_copy (DEE_TYPE_MODEL_ITER, iter); g_assert (iter == copied); } static void test_model_iter_free (RowsFixture *fix, gconstpointer data) { DeeModelIter *iter; gint i; iter = dee_model_append (fix->model, 10, "Rooney"); g_boxed_free (DEE_TYPE_MODEL_ITER, iter); /* And since it's supposed to be a no-op we can do this */ for (i = 0; i < 100; i++) g_boxed_free (DEE_TYPE_MODEL_ITER, iter); /* Didn't crash? Good! */ } static void test_rows_allocation (RowsFixture *fix, gconstpointer data) { g_assert (DEE_IS_MODEL (fix->model)); } static gint n_clear_sigs = 0; static void on_clear_row_removed (DeeModel *model, DeeModelIter *iter) { n_clear_sigs++; } static void test_rows_clear (RowsFixture *fix, gconstpointer data) { gint i; for (i = 0; i < 1000; i++) { dee_model_append (fix->model, 10, "Rooney"); } g_assert_cmpint (1000, ==, dee_model_get_n_rows (fix->model)); g_signal_connect (fix->model, "row-removed", G_CALLBACK (on_clear_row_removed), NULL); n_clear_sigs = 0; dee_model_clear (fix->model); g_assert_cmpint (0, ==, dee_model_get_n_rows (fix->model)); g_assert_cmpint (1000, ==, n_clear_sigs); } static void test_insert_at_pos (RowsFixture *fix, gconstpointer data) { DeeModelIter *iter; gint i; gchar *str; dee_model_append (fix->model, 10, "Rooney"); dee_model_append (fix->model, 10, "Rooney"); g_assert_cmpint (2, ==, dee_model_get_n_rows (fix->model)); dee_model_insert (fix->model, 1, 27, "Not Rooney"); g_assert_cmpint (3, ==, dee_model_get_n_rows (fix->model)); iter = dee_model_get_first_iter (fix->model); g_assert (dee_model_is_first (fix->model, iter)); dee_model_get (fix->model, iter, &i, &str); g_assert_cmpint (10, ==, i); g_assert_cmpstr (str, ==, "Rooney"); iter = dee_model_next (fix->model, iter); dee_model_get (fix->model, iter, &i, &str); g_assert_cmpint (27, ==, i); g_assert_cmpstr (str, ==, "Not Rooney"); iter = dee_model_next (fix->model, iter); dee_model_get (fix->model, iter, &i, &str); g_assert_cmpint (10, ==, i); g_assert_cmpstr (str, ==, "Rooney"); iter = dee_model_next (fix->model, iter); g_assert (dee_model_is_last (fix->model, iter)); } static void test_insert_at_iter (RowsFixture *fix, gconstpointer data) { DeeModelIter *iter; gint i; gchar *str; dee_model_append (fix->model, 10, "Rooney"); dee_model_append (fix->model, 10, "Rooney"); g_assert_cmpint (2, ==, dee_model_get_n_rows (fix->model)); iter = dee_model_get_first_iter (fix->model); iter = dee_model_next (fix->model, iter); dee_model_insert_before (fix->model, iter, 27, "Not Rooney"); g_assert_cmpint (3, ==, dee_model_get_n_rows (fix->model)); iter = dee_model_get_first_iter (fix->model); dee_model_get (fix->model, iter, &i, &str); g_assert_cmpint (10, ==, i); g_assert_cmpstr (str, ==, "Rooney"); iter = dee_model_next (fix->model, iter); dee_model_get (fix->model, iter, &i, &str); g_assert_cmpint (27, ==, i); g_assert_cmpstr (str, ==, "Not Rooney"); iter = dee_model_next (fix->model, iter); dee_model_get (fix->model, iter, &i, &str); g_assert_cmpint (10, ==, i); g_assert_cmpstr (str, ==, "Rooney"); iter = dee_model_next (fix->model, iter); g_assert (dee_model_is_last (fix->model, iter)); } static void test_prepend (RowsFixture *fix, gconstpointer data) { DeeModelIter *iter; gint i; gchar *str; dee_model_prepend (fix->model, 11, "Mid"); dee_model_append (fix->model, 12, "Last"); dee_model_prepend (fix->model, 10, "First"); g_assert_cmpint (3, ==, dee_model_get_n_rows (fix->model)); iter = dee_model_get_first_iter (fix->model); dee_model_get (fix->model, iter, &i, &str); g_assert_cmpint (10, ==, i); g_assert_cmpstr (str, ==, "First"); iter = dee_model_next (fix->model, iter); dee_model_get (fix->model, iter, &i, &str); g_assert_cmpint (11, ==, i); g_assert_cmpstr (str, ==, "Mid"); iter = dee_model_next (fix->model, iter); dee_model_get (fix->model, iter, &i, &str); g_assert_cmpint (12, ==, i); g_assert_cmpstr (str, ==, "Last"); iter = dee_model_next (fix->model, iter); g_assert (dee_model_is_last (fix->model, iter)); } static void test_append (RowsFixture *fix, gconstpointer data) { DeeModelIter *iter; gint i; gchar *str; dee_model_append (fix->model, 11, "First"); dee_model_append (fix->model, 12, "Mid"); dee_model_append (fix->model, 10, "Last"); g_assert_cmpint (3, ==, dee_model_get_n_rows (fix->model)); iter = dee_model_get_first_iter (fix->model); dee_model_get (fix->model, iter, &i, &str); g_assert_cmpint (11, ==, i); g_assert_cmpstr (str, ==, "First"); iter = dee_model_next (fix->model, iter); dee_model_get (fix->model, iter, &i, &str); g_assert_cmpint (12, ==, i); g_assert_cmpstr (str, ==, "Mid"); iter = dee_model_next (fix->model, iter); dee_model_get (fix->model, iter, &i, &str); g_assert_cmpint (10, ==, i); g_assert_cmpstr (str, ==, "Last"); iter = dee_model_next (fix->model, iter); g_assert (dee_model_is_last (fix->model, iter)); } static void test_get_value (RowsFixture *fix, gconstpointer data) { DeeModelIter *iter; GVariant *variant; dee_model_set_column_names (fix->model, "count", "name", NULL); dee_model_append (fix->model, 11, "First"); dee_model_append (fix->model, 12, "Mid"); dee_model_append (fix->model, 10, "Last"); g_assert_cmpint (3, ==, dee_model_get_n_rows (fix->model)); iter = dee_model_get_first_iter (fix->model); variant = dee_model_get_value (fix->model, iter, 0); g_assert_cmpint (g_variant_get_int32 (variant), ==, 11); g_variant_unref (variant); iter = dee_model_next (fix->model, iter); variant = dee_model_get_value (fix->model, iter, 1); g_assert_cmpstr (g_variant_get_string (variant, NULL), ==, "Mid"); g_variant_unref (variant); iter = dee_model_next (fix->model, iter); variant = dee_model_get_value_by_name (fix->model, iter, "count"); g_assert_cmpint (g_variant_get_int32 (variant), ==, 10); g_variant_unref (variant); iter = dee_model_next (fix->model, iter); g_assert (dee_model_is_last (fix->model, iter)); } static void test_iter_backwards (RowsFixture *fix, gconstpointer data) { DeeModelIter *iter; gint i; gchar *str; dee_model_append (fix->model, 11, "First"); dee_model_append (fix->model, 12, "Mid"); dee_model_append (fix->model, 10, "Last"); g_assert_cmpint (3, ==, dee_model_get_n_rows (fix->model)); iter = dee_model_get_last_iter (fix->model); g_assert (dee_model_is_last (fix->model, iter)); iter = dee_model_prev (fix->model, iter); dee_model_get (fix->model, iter, &i, &str); g_assert_cmpint (10, ==, i); g_assert_cmpstr (str, ==, "Last"); iter = dee_model_prev (fix->model, iter); dee_model_get (fix->model, iter, &i, &str); g_assert_cmpint (12, ==, i); g_assert_cmpstr (str, ==, "Mid"); iter = dee_model_prev (fix->model, iter); dee_model_get (fix->model, iter, &i, &str); g_assert_cmpint (11, ==, i); g_assert_cmpstr (str, ==, "First"); g_assert (dee_model_is_first (fix->model, iter)); } /* Make sure the the memory allocated for strings is not reffed inside * the model. Also checks that strings are returned as const pointers */ static void test_no_transfer (RowsFixture *fix, gconstpointer data) { DeeModelIter *iter; gchar *orig, *str1, *str2; orig = g_strdup ("test"); dee_model_append (fix->model, 1, orig); g_assert_cmpint (1, ==, dee_model_get_n_rows (fix->model)); /* This should work, of course */ iter = dee_model_get_first_iter (fix->model); dee_model_get (fix->model, iter, NULL, &str1); g_assert_cmpstr (str1, ==, "test"); /* Assert that we get a const pointer to the string back. * Strings should behave like that */ dee_model_get (fix->model, iter, NULL, &str2); g_assert (str1 == str2); /* Modify orig in place and assert it doesn't affect the model */ orig[0] = 'P'; dee_model_get (fix->model, iter, NULL, &str1, -1); g_assert_cmpstr (str1, ==, "test"); /* Now free orig and make sure we can still read from the model */ g_free (orig); dee_model_get (fix->model, iter, NULL, &str1, -1); g_assert_cmpstr (str1, ==, "test"); } /* Try to get and set values from a removed row */ static void test_illegal_access (RowsFixture *fix, gconstpointer data) { DeeModelIter *iter; dee_model_append (fix->model, 1, "Hello"); iter = dee_model_append (fix->model, 1, "Mary"); dee_model_append (fix->model, 1, "Lou"); dee_model_remove (fix->model, iter); if (g_test_trap_fork (0, G_TEST_TRAP_SILENCE_STDOUT | G_TEST_TRAP_SILENCE_STDERR)) { g_assert_cmpstr (dee_model_get_string (fix->model, iter, 1), ==, "Mary"); exit (0); /* successful test run */ } g_test_trap_assert_failed (); if (g_test_trap_fork (0, G_TEST_TRAP_SILENCE_STDOUT | G_TEST_TRAP_SILENCE_STDERR)) { dee_model_set (fix->model, iter, 27, "Marie"); exit (0); /* successful test run */ } g_test_trap_assert_failed (); } static gint cmp_constant (GVariant **row1, GVariant **row2, gpointer user_data) { g_assert_cmpstr (user_data, ==, "test-user-data"); return 0; } static gint cmp_col_0 (GVariant **row1, GVariant **row2, gpointer user_data) { g_assert_cmpstr (user_data, ==, "test-user-data"); //g_debug ("CMP %i %i", g_variant_get_int32 (row1[0]), g_variant_get_int32 (row2[0])); return g_variant_get_int32 (row2[0]) - g_variant_get_int32 (row1[0]); } static void test_sorted (RowsFixture *fix, gconstpointer data) { DeeModelIter *hter, *iter, *jter, *kter; gboolean was_found; /* FINAL MODEL: [(28,s), (27,s), (26,s), (25,s)] * ~= [hter, iter, jter, kter] */ /* Test find() with an empty model. With NULL was_found arg */ iter = dee_model_find_sorted (fix->model, cmp_col_0, "test-user-data", NULL, 0, ""); g_assert (iter == dee_model_get_last_iter (fix->model)); /* Test find() with an empty model. With non-NULL was_found arg */ was_found = TRUE; iter = dee_model_find_sorted (fix->model, cmp_col_0, "test-user-data", &was_found, 0, ""); g_assert (!was_found); g_assert (iter == dee_model_get_last_iter (fix->model)); /* Insert the first row */ iter = dee_model_insert_sorted (fix->model, cmp_col_0, "test-user-data", 27, "Sorta sorted"); g_assert (iter != dee_model_get_last_iter (fix->model)); g_assert (iter == dee_model_get_first_iter (fix->model)); /* Test append */ kter = dee_model_insert_sorted (fix->model, cmp_col_0, "test-user-data", 25, "Sorta sorted"); g_assert (kter != dee_model_get_last_iter (fix->model)); g_assert (kter != dee_model_get_first_iter (fix->model)); g_assert (iter == dee_model_get_first_iter (fix->model)); g_assert (kter != iter); g_assert_cmpint (2, ==, dee_model_get_n_rows (fix->model)); g_assert (kter == dee_model_next (fix->model, iter)); /* Test insert in between rows */ jter = dee_model_insert_sorted (fix->model, cmp_col_0, "test-user-data", 26, "Sorta sorted"); g_assert (jter != dee_model_get_last_iter (fix->model)); g_assert (jter != dee_model_get_first_iter (fix->model)); g_assert (iter == dee_model_get_first_iter (fix->model)); g_assert (jter != iter); g_assert (jter != kter); g_assert (jter == dee_model_next (fix->model, iter)); g_assert (kter == dee_model_next (fix->model, jter)); g_assert (dee_model_get_last_iter (fix->model) == dee_model_next (fix->model, kter)); /* Test prepend */ hter = dee_model_insert_sorted (fix->model, cmp_col_0, "test-user-data", 28, "Sorta sorted"); g_assert (hter == dee_model_get_first_iter (fix->model)); g_assert (iter == dee_model_next (fix->model, hter)); g_assert_cmpint (4, ==, dee_model_get_n_rows (fix->model)); /* Test find() again now that we have data in the model */ DeeModelIter *result; result = dee_model_find_sorted (fix->model, cmp_col_0, "test-user-data", NULL, 24, ""); g_assert (result == dee_model_get_last_iter (fix->model)); result = dee_model_find_sorted (fix->model, cmp_col_0, "test-user-data", NULL, 28, ""); g_assert (result == hter); /* Test find(). With non-NULL was_found arg */ was_found = TRUE; result = dee_model_find_sorted (fix->model, cmp_col_0, "test-user-data", &was_found, 24, ""); g_assert (result == dee_model_get_last_iter (fix->model)); result = dee_model_find_sorted (fix->model, cmp_col_0, "test-user-data", &was_found, 28, ""); g_assert (was_found); g_assert (result == hter); } static void test_sort_stable (RowsFixture *fix, gconstpointer data) { DeeModelIter *hter, *iter, *jter, *kter; /* FINAL MODEL: [(25,s), (26,s), (27,s), (28,s)] * ~= [hter, iter, jter, kter] */ /* Insert the first row */ iter = dee_model_insert_sorted (fix->model, cmp_constant, "test-user-data", 25, "Stable"); g_assert (iter != dee_model_get_last_iter (fix->model)); g_assert (iter == dee_model_get_first_iter (fix->model)); /* Second row */ kter = dee_model_insert_sorted (fix->model, cmp_constant, "test-user-data", 26, "Stable"); g_assert (kter != dee_model_get_last_iter (fix->model)); g_assert (kter != dee_model_get_first_iter (fix->model)); g_assert (iter == dee_model_get_first_iter (fix->model)); g_assert (kter != iter); g_assert_cmpint (2, ==, dee_model_get_n_rows (fix->model)); g_assert (kter == dee_model_next (fix->model, iter)); /* Third row */ jter = dee_model_insert_sorted (fix->model, cmp_constant, "test-user-data", 27, "Stable"); g_assert (jter != dee_model_get_last_iter (fix->model)); g_assert (jter != dee_model_get_first_iter (fix->model)); g_assert (iter == dee_model_get_first_iter (fix->model)); g_assert (jter != iter); g_assert (jter != kter); g_assert (jter == dee_model_next (fix->model, kter)); g_assert (dee_model_get_last_iter (fix->model) == dee_model_next (fix->model, jter)); /* Fourth row */ hter = dee_model_insert_sorted (fix->model, cmp_constant, "test-user-data", 28, "Stable"); g_assert (hter == dee_model_next (fix->model, jter)); g_assert_cmpint (4, ==, dee_model_get_n_rows (fix->model)); } static gint sized_cmp_col_0 (GVariant **row1, guint row1_length, GVariant **row2, guint row2_length, gpointer user_data) { g_assert_cmpstr (user_data, ==, "test-user-data"); g_assert_cmpuint (row1_length, ==, 2); g_assert_cmpuint (row2_length, ==, 2); g_assert_cmpuint (row1_length, ==, row2_length); return g_variant_get_int32 (row2[0]) - g_variant_get_int32 (row1[0]); } static void test_sorted_with_sizes (RowsFixture *fix, gconstpointer data) { DeeModelIter *hter, *iter, *jter, *kter; gboolean was_found; GVariant *row_spec[2]; /* FINAL MODEL: [(28,s), (27,s), (26,s), (25,s)] * ~= [hter, iter, jter, kter] */ row_spec[0] = g_variant_new_int32 (0); row_spec[1] = g_variant_new_string (""); /* Test find() with an empty model. With NULL was_found arg */ iter = dee_model_find_row_sorted_with_sizes (fix->model, row_spec, sized_cmp_col_0, "test-user-data", NULL); g_assert (iter == dee_model_get_last_iter (fix->model)); /* Test find() with an empty model. With non-NULL was_found arg */ was_found = TRUE; iter = dee_model_find_row_sorted_with_sizes (fix->model, row_spec, sized_cmp_col_0, "test-user-data", &was_found); g_assert (!was_found); g_assert (iter == dee_model_get_last_iter (fix->model)); /* Insert the first row */ row_spec[0] = g_variant_new_int32 (27); row_spec[1] = g_variant_new_string ("Sorta sorted"); iter = dee_model_insert_row_sorted_with_sizes (fix->model, row_spec, sized_cmp_col_0, "test-user-data"); g_assert (iter != dee_model_get_last_iter (fix->model)); g_assert (iter == dee_model_get_first_iter (fix->model)); /* Test append */ row_spec[0] = g_variant_new_int32 (25); row_spec[1] = g_variant_new_string ("Sorta sorted"); kter = dee_model_insert_row_sorted_with_sizes (fix->model, row_spec, sized_cmp_col_0, "test-user-data"); g_assert (kter != dee_model_get_last_iter (fix->model)); g_assert (kter != dee_model_get_first_iter (fix->model)); g_assert (iter == dee_model_get_first_iter (fix->model)); g_assert (kter != iter); g_assert_cmpint (2, ==, dee_model_get_n_rows (fix->model)); g_assert (kter == dee_model_next (fix->model, iter)); /* Test insert in between rows */ row_spec[0] = g_variant_new_int32 (26); row_spec[1] = g_variant_new_string ("Sorta sorted"); jter = dee_model_insert_row_sorted_with_sizes (fix->model, row_spec, sized_cmp_col_0, "test-user-data"); g_assert (jter != dee_model_get_last_iter (fix->model)); g_assert (jter != dee_model_get_first_iter (fix->model)); g_assert (iter == dee_model_get_first_iter (fix->model)); g_assert (jter != iter); g_assert (jter != kter); g_assert (jter == dee_model_next (fix->model, iter)); g_assert (kter == dee_model_next (fix->model, jter)); g_assert (dee_model_get_last_iter (fix->model) == dee_model_next (fix->model, kter)); /* Test prepend */ row_spec[0] = g_variant_new_int32 (28); row_spec[1] = g_variant_new_string ("Sorta sorted"); hter = dee_model_insert_row_sorted_with_sizes (fix->model, row_spec, sized_cmp_col_0, "test-user-data"); g_assert (hter == dee_model_get_first_iter (fix->model)); g_assert (iter == dee_model_next (fix->model, hter)); g_assert_cmpint (4, ==, dee_model_get_n_rows (fix->model)); /* Test find() again now that we have data in the model */ DeeModelIter *result; row_spec[0] = g_variant_new_int32 (24); row_spec[1] = g_variant_new_string (""); result = dee_model_find_row_sorted_with_sizes (fix->model, row_spec, sized_cmp_col_0, "test-user-data", NULL); g_assert (result == dee_model_get_last_iter (fix->model)); row_spec[0] = g_variant_new_int32 (28); row_spec[1] = g_variant_new_string (""); result = dee_model_find_row_sorted_with_sizes (fix->model, row_spec, sized_cmp_col_0, "test-user-data", NULL); g_assert (result == hter); /* Test find(). With non-NULL was_found arg */ was_found = FALSE; row_spec[0] = g_variant_new_int32 (24); row_spec[1] = g_variant_new_string (""); result = dee_model_find_row_sorted_with_sizes (fix->model, row_spec, sized_cmp_col_0, "test-user-data", &was_found); g_assert (result == dee_model_get_last_iter (fix->model)); row_spec[0] = g_variant_new_int32 (28); row_spec[1] = g_variant_new_string (""); result = dee_model_find_row_sorted_with_sizes (fix->model, row_spec, sized_cmp_col_0, "test-user-data", &was_found); g_assert (was_found); g_assert (result == hter); } static void test_named_cols_append (RowsFixture *fix, gconstpointer data) { DeeModelIter *iter; gint i; gchar *str; GVariant *row_members[2]; dee_model_set_column_names (fix->model, "count", "name", NULL); dee_model_build_named_row (fix->model, row_members, "count", 11, "name", "First", NULL); dee_model_append_row (fix->model, row_members); dee_model_build_named_row (fix->model, row_members, "name", "Mid", "count", 12, NULL); dee_model_append_row (fix->model, row_members); dee_model_build_named_row (fix->model, row_members, "count", 10, "name", "Last", NULL); dee_model_append_row (fix->model, row_members); g_assert_cmpint (3, ==, dee_model_get_n_rows (fix->model)); iter = dee_model_get_first_iter (fix->model); dee_model_get (fix->model, iter, &i, &str); g_assert_cmpint (11, ==, i); g_assert_cmpstr (str, ==, "First"); iter = dee_model_next (fix->model, iter); dee_model_get (fix->model, iter, &i, &str); g_assert_cmpint (12, ==, i); g_assert_cmpstr (str, ==, "Mid"); iter = dee_model_next (fix->model, iter); dee_model_get (fix->model, iter, &i, &str); g_assert_cmpint (10, ==, i); g_assert_cmpstr (str, ==, "Last"); iter = dee_model_next (fix->model, iter); g_assert (dee_model_is_last (fix->model, iter)); } static void test_named_cols_fields (RowsFixture *fix, gconstpointer data) { DeeModelIter *iter; gint i; gchar *str; GVariant *row_members[4]; GVariant *dict, *dummy; GHashTable *fields_schemas; fields_schemas = g_hash_table_new (g_str_hash, g_str_equal); g_hash_table_insert (fields_schemas, "object-path", "o"); g_hash_table_insert (fields_schemas, "id", "i"); dee_model_register_vardict_schema (fix->model, 2, fields_schemas); g_hash_table_unref (fields_schemas); dee_model_build_named_row (fix->model, row_members, "count", 11, "name", "First", NULL); dee_model_append_row (fix->model, row_members); dee_model_build_named_row (fix->model, row_members, "name", "Mid", "count", 12, "object-path", "/org/example", "hints::id", 8123, NULL); dee_model_append_row (fix->model, row_members); dee_model_build_named_row (fix->model, row_members, "count", 10, "name", "Last", "id", 90, NULL); dee_model_append_row (fix->model, row_members); /* Commence checks */ g_assert_cmpint (3, ==, dee_model_get_n_rows (fix->model)); iter = dee_model_get_first_iter (fix->model); dee_model_get (fix->model, iter, &i, &str, &dict, &dummy); g_assert_cmpint (11, ==, i); g_assert_cmpstr (str, ==, "First"); g_assert_cmpuint (0, ==, g_variant_n_children (dict)); g_assert (dee_model_get_value_by_name (fix->model, iter, "object-path") == NULL); iter = dee_model_next (fix->model, iter); dee_model_get (fix->model, iter, &i, &str, &dict, &dummy); g_assert_cmpint (12, ==, i); g_assert_cmpstr (str, ==, "Mid"); g_assert_cmpuint (2, ==, g_variant_n_children (dict)); g_assert_cmpstr ("/org/example", ==, g_variant_get_string (g_variant_lookup_value (dict, "object-path", G_VARIANT_TYPE_OBJECT_PATH), NULL)); g_assert_cmpint (8123, ==, g_variant_get_int32 (dee_model_get_value_by_name (fix->model, iter, "id"))); iter = dee_model_next (fix->model, iter); dee_model_get (fix->model, iter, &i, &str, &dict, &dummy); g_assert_cmpint (10, ==, i); g_assert_cmpstr (str, ==, "Last"); g_assert_cmpuint (1, ==, g_variant_n_children (dict)); g_assert_cmpint (90, ==, g_variant_get_int32 (dee_model_get_value_by_name (fix->model, iter, "id"))); iter = dee_model_next (fix->model, iter); g_assert (dee_model_is_last (fix->model, iter)); } static gboolean expected_error_handler (const gchar *log_domain, GLogLevelFlags log_level, const gchar *msg, gpointer user_data) { return FALSE; } static void ignore_error_handler (const gchar *log_domain, GLogLevelFlags log_level, const gchar *msg, gpointer user_data) { } static void test_named_cols_duplicated_fields (RowsFixture *fix, gconstpointer data) { DeeModelIter *iter; gint i; guint handler_id; gchar *str; GVariant *row_members[4]; GVariant *dict1, *dict2; GHashTable *fields_schemas; g_test_log_set_fatal_handler (expected_error_handler, NULL); handler_id = g_log_set_handler ("dee", G_LOG_LEVEL_WARNING | G_LOG_FLAG_FATAL, ignore_error_handler, NULL); fields_schemas = g_hash_table_new (g_str_hash, g_str_equal); g_hash_table_insert (fields_schemas, "id", "i"); dee_model_register_vardict_schema (fix->model, 2, fields_schemas); g_hash_table_insert (fields_schemas, "id", "s"); g_hash_table_insert (fields_schemas, "extra-id", "i"); dee_model_register_vardict_schema (fix->model, 3, fields_schemas); g_hash_table_unref (fields_schemas); dee_model_build_named_row (fix->model, row_members, "count", 11, "name", "First", NULL); dee_model_append_row (fix->model, row_members); dee_model_build_named_row (fix->model, row_members, "name", "Mid", "count", 12, "hints::id", 8123, "hints2::id", "8123", NULL); dee_model_append_row (fix->model, row_members); dee_model_build_named_row (fix->model, row_members, "count", 10, "name", "Last", "hints2::id", "foo", NULL); dee_model_append_row (fix->model, row_members); /* Commence checks */ g_assert_cmpint (3, ==, dee_model_get_n_rows (fix->model)); iter = dee_model_get_first_iter (fix->model); dee_model_get (fix->model, iter, &i, &str, &dict1, &dict2); g_assert_cmpint (11, ==, i); g_assert_cmpstr (str, ==, "First"); g_assert_cmpuint (0, ==, g_variant_n_children (dict1)); g_assert_cmpuint (0, ==, g_variant_n_children (dict2)); g_assert (dee_model_get_value_by_name (fix->model, iter, "hints::id") == NULL); iter = dee_model_next (fix->model, iter); dee_model_get (fix->model, iter, &i, &str, &dict1, &dict2); g_assert_cmpint (12, ==, i); g_assert_cmpstr (str, ==, "Mid"); g_assert_cmpuint (1, ==, g_variant_n_children (dict1)); g_assert_cmpuint (1, ==, g_variant_n_children (dict2)); g_assert_cmpint (8123, ==, g_variant_get_int32 (dee_model_get_value_by_name (fix->model, iter, "hints::id"))); g_assert_cmpstr ("8123", ==, g_variant_get_string (dee_model_get_value_by_name (fix->model, iter, "hints2::id"), NULL)); iter = dee_model_next (fix->model, iter); dee_model_get (fix->model, iter, &i, &str, &dict1, &dict2); g_assert_cmpint (10, ==, i); g_assert_cmpstr (str, ==, "Last"); g_assert_cmpuint (0, ==, g_variant_n_children (dict1)); g_assert_cmpuint (1, ==, g_variant_n_children (dict2)); g_assert_cmpstr ("foo", ==, g_variant_get_string (dee_model_get_value_by_name (fix->model, iter, "hints2::id"), NULL)); iter = dee_model_next (fix->model, iter); g_assert (dee_model_is_last (fix->model, iter)); g_log_remove_handler ("dee", handler_id); } static void test_named_cols_error (RowsFixture *fix, gconstpointer data) { GVariant *row_members[2]; GVariant **result; guint handler_id; dee_model_set_column_names (fix->model, "count", "name", NULL); g_test_log_set_fatal_handler (expected_error_handler, NULL); handler_id = g_log_set_handler ("dee", G_LOG_LEVEL_CRITICAL | G_LOG_LEVEL_WARNING | G_LOG_FLAG_FATAL, ignore_error_handler, NULL); /* Only first col set */ result = dee_model_build_named_row (fix->model, row_members, "name", "First", NULL); g_assert (result == NULL); /* Only second col set */ result = dee_model_build_named_row (fix->model, row_members, "count", 12, NULL); g_assert (result == NULL); /* Unregistered cols set */ result = dee_model_build_named_row (fix->model, row_members, "nm", "Foo", "cnt", 12, NULL); g_assert (result == NULL); g_log_remove_handler ("dee", handler_id); }