LCOV - code coverage report
Current view: top level - pkcs11/gnome2-store - test-gnome2-storage.c (source / functions) Coverage Total Hit
Test: coverage.info Lines: 52.6 % 190 100
Test Date: 2024-12-15 20:37:51 Functions: 78.6 % 14 11

            Line data    Source code
       1              : /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
       2              : /* unit-test-file-store.c: Test file store functionality
       3              : 
       4              :    Copyright (C) 2008 Stefan Walter
       5              : 
       6              :    The Gnome Keyring Library is free software; you can redistribute it and/or
       7              :    modify it under the terms of the GNU Library General Public License as
       8              :    published by the Free Software Foundation; either version 2 of the
       9              :    License, or (at your option) any later version.
      10              : 
      11              :    The Gnome Keyring Library is distributed in the hope that it will be useful,
      12              :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      13              :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      14              :    Library General Public License for more details.
      15              : 
      16              :    You should have received a copy of the GNU Library General Public
      17              :    License along with the Gnome Library; see the file COPYING.LIB.  If not,
      18              :    <http://www.gnu.org/licenses/>.
      19              : 
      20              :    Author: Stef Walter <stef@memberwebs.com>
      21              : */
      22              : 
      23              : #include "config.h"
      24              : 
      25              : #include "mock-gnome2-module.h"
      26              : 
      27              : #include "gnome2-store/gkm-gnome2-storage.h"
      28              : 
      29              : #include "gkm/gkm-certificate.h"
      30              : #include "gkm/gkm-module.h"
      31              : #include "gkm/gkm-serializable.h"
      32              : #include "gkm/gkm-test.h"
      33              : 
      34              : #include "egg/egg-libgcrypt.h"
      35              : #include "egg/egg-testing.h"
      36              : 
      37              : #include <glib/gstdio.h>
      38              : 
      39              : #include <sys/types.h>
      40              : #include <sys/wait.h>
      41              : #include <fcntl.h>
      42              : #include <stdlib.h>
      43              : #include <string.h>
      44              : #include <unistd.h>
      45              : 
      46              : typedef struct {
      47              :         gchar *directory;
      48              :         GkmModule *module;
      49              :         GkmGnome2Storage *storage;
      50              :         GkmObject *new_object;
      51              :         gchar *new_filename;
      52              :         GkmObject *old_object;
      53              : } Test;
      54              : 
      55              : #define MSEC(x) ((x) * 1000)
      56              : 
      57              : static void
      58            4 : setup_directory (Test *test,
      59              :                  gconstpointer unused)
      60              : {
      61            4 :         test->directory = egg_tests_create_scratch_directory (
      62              :                 SRCDIR "/pkcs11/gnome2-store/fixtures/Thawte_Personal_Premium_CA.cer",
      63              :                 SRCDIR "/pkcs11/gnome2-store/fixtures/user.keystore",
      64              :                 NULL);
      65            4 : }
      66              : 
      67              : static void
      68            4 : setup_module (Test *test,
      69              :               gconstpointer unused)
      70              : {
      71            4 :         CK_ATTRIBUTE url = { CKA_URL, NULL, 0 };
      72              :         gchar *contents;
      73              :         gsize length;
      74              :         GBytes *bytes;
      75              :         GkmManager *manager;
      76            4 :         GError *error = NULL;
      77              :         GkmSession *session;
      78              :         CK_ATTRIBUTE attr;
      79              :         CK_OBJECT_CLASS klass;
      80              :         CK_RV rv;
      81              : 
      82            4 :         g_assert (test->directory != NULL);
      83              : 
      84            4 :         test->module = mock_gnome2_module_initialize_and_enter ();
      85            4 :         manager = gkm_module_get_manager (test->module);
      86            4 :         session = mock_gnome2_module_open_session (TRUE);
      87              : 
      88            4 :         test->storage = gkm_gnome2_storage_new (test->module, test->directory);
      89            4 :         rv = gkm_gnome2_storage_refresh (test->storage);
      90            4 :         gkm_assert_cmprv (rv, ==, CKR_OK);
      91            4 :         g_object_add_weak_pointer (G_OBJECT (test->storage), (gpointer *)&test->storage);
      92              : 
      93              :         /* We already have the CKA_LABEL attribute */
      94            4 :         gkm_store_register_schema (GKM_STORE (test->storage), &url, NULL, 0);
      95              : 
      96              :         /*
      97              :          * Create a new object that hasn't yet been stored in the storage.
      98              :          * It's a certificate because that's easiest.
      99              :          */
     100            4 :         test->new_object = g_object_new (GKM_TYPE_CERTIFICATE,
     101              :                                          "unique", "test.cer",
     102              :                                          "module", test->module,
     103              :                                          "manager", manager,
     104              :                                          NULL);
     105            4 :         g_file_get_contents (SRCDIR "/pkcs11/gnome2-store/fixtures/test-certificate.cer", &contents, &length, &error);
     106            4 :         g_assert_no_error (error);
     107              : 
     108            4 :         bytes = g_bytes_new_take (contents, length);
     109            4 :         if (!gkm_serializable_load (GKM_SERIALIZABLE (test->new_object), NULL, bytes))
     110            0 :                 g_assert_not_reached ();
     111            4 :         g_bytes_unref (bytes);
     112              : 
     113              :         /* We happen to know this certificate will get named */
     114            4 :         test->new_filename = g_build_filename (test->directory, "CA_Cert_Signing_Authority.cer", NULL);
     115              : 
     116              :         /*
     117              :          * Find the object stored in the storage, it's a certificate, and we happen to
     118              :          * know there's only one
     119              :          */
     120            4 :         klass = CKO_CERTIFICATE;
     121            4 :         attr.type = CKA_CLASS;
     122            4 :         attr.pValue = &klass;
     123            4 :         attr.ulValueLen = sizeof (klass);
     124            4 :         test->old_object = gkm_manager_find_one_by_attributes (manager, session, &attr, 1);
     125            4 :         g_assert (GKM_IS_OBJECT (test->old_object));
     126            4 :         g_object_ref (test->old_object);
     127            4 : }
     128              : 
     129              : static void
     130            4 : setup_all (Test *test,
     131              :            gconstpointer unused)
     132              : {
     133            4 :         setup_directory (test, unused);
     134            4 :         setup_module (test, unused);
     135            4 : }
     136              : 
     137              : static void
     138            4 : teardown_directory (Test *test,
     139              :                     gconstpointer unused)
     140              : {
     141            4 :         egg_tests_remove_scratch_directory (test->directory);
     142            4 :         g_free (test->directory);
     143            4 : }
     144              : 
     145              : static void
     146            4 : teardown_module (Test *test,
     147              :                  gconstpointer unused)
     148              : {
     149            4 :         g_assert (test->directory);
     150              : 
     151            4 :         g_object_unref (test->new_object);
     152            4 :         g_object_unref (test->old_object);
     153            4 :         g_object_unref (test->storage);
     154            4 :         g_assert (test->storage == NULL);
     155              : 
     156            4 :         mock_gnome2_module_leave_and_finalize ();
     157              : 
     158            4 :         g_free (test->new_filename);
     159            4 : }
     160              : 
     161              : static void
     162            4 : teardown_all (Test *test,
     163              :               gconstpointer unused)
     164              : {
     165            4 :         teardown_module (test, unused);
     166            4 :         teardown_directory (test, unused);
     167            4 : }
     168              : 
     169              : static void
     170            1 : test_create (Test *test,
     171              :              gconstpointer unused)
     172              : {
     173              :         GkmTransaction *transaction;
     174              : 
     175            1 :         transaction = gkm_transaction_new ();
     176              : 
     177            1 :         gkm_gnome2_storage_create (test->storage, transaction, test->new_object);
     178            1 :         gkm_assert_cmprv (gkm_transaction_get_result (transaction), ==, CKR_OK);
     179              : 
     180            1 :         gkm_transaction_complete_and_unref (transaction);
     181              : 
     182            1 :         g_assert (g_file_test (test->new_filename, G_FILE_TEST_EXISTS));
     183            1 : }
     184              : 
     185              : static void
     186            1 : test_create_and_fail (Test *test,
     187              :                       gconstpointer unused)
     188              : {
     189              :         GkmTransaction *transaction;
     190              : 
     191            1 :         transaction = gkm_transaction_new ();
     192              : 
     193            1 :         gkm_gnome2_storage_create (test->storage, transaction, test->new_object);
     194            1 :         gkm_assert_cmprv (gkm_transaction_get_result (transaction), ==, CKR_OK);
     195              : 
     196            1 :         gkm_transaction_fail (transaction, CKR_FUNCTION_FAILED);
     197            1 :         gkm_transaction_complete_and_unref (transaction);
     198              : 
     199            1 :         g_assert (!g_file_test (test->new_filename, G_FILE_TEST_EXISTS));
     200            1 : }
     201              : 
     202              : static void
     203            1 : test_write_value (Test *test,
     204              :                   gconstpointer unused)
     205              : {
     206            1 :         CK_ATTRIBUTE label = { CKA_LABEL, "Hello", 5 };
     207            1 :         CK_ATTRIBUTE url = { CKA_URL, "http://example.com", 18 };
     208              :         GkmTransaction *transaction;
     209              :         gchar *string;
     210              : 
     211            1 :         transaction = gkm_transaction_new ();
     212              : 
     213            1 :         gkm_store_write_value (GKM_STORE (test->storage), transaction,
     214              :                                test->old_object, &label);
     215            1 :         gkm_assert_cmprv (gkm_transaction_get_result (transaction), ==, CKR_OK);
     216              : 
     217            1 :         gkm_store_write_value (GKM_STORE (test->storage), transaction,
     218              :                                test->old_object, &url);
     219            1 :         gkm_assert_cmprv (gkm_transaction_get_result (transaction), ==, CKR_OK);
     220              : 
     221            1 :         gkm_transaction_complete_and_unref (transaction);
     222              : 
     223            1 :         string = gkm_store_read_string (GKM_STORE (test->storage), test->old_object, CKA_URL);
     224            1 :         g_assert_cmpstr (string, ==, "http://example.com");
     225            1 :         g_free (string);
     226              : 
     227            1 :         string = gkm_store_read_string (GKM_STORE (test->storage), test->old_object, CKA_LABEL);
     228            1 :         g_assert_cmpstr (string, ==, "Hello");
     229            1 :         g_free (string);
     230              : 
     231            1 : }
     232              : 
     233              : static void
     234            0 : test_locking_transaction (Test *test,
     235              :                           gconstpointer unused)
     236              : {
     237            0 :         guint iterations = 30;
     238              :         guint i;
     239              :         pid_t pid;
     240              : 
     241              :         /* Fork before setting up the model, as it may start threads */
     242            0 :         pid = fork ();
     243            0 :         g_assert (pid >= 0);
     244              : 
     245              :         /*
     246              :          * This is the child. It initializes, writes a value, waits 100 ms,
     247              :          * writes a second value, and then writes another value.
     248              :          */
     249            0 :         if (pid == 0) {
     250              :                 CK_ATTRIBUTE attr;
     251              :                 GkmTransaction *transaction;
     252              :                 gchar *string;
     253              : 
     254            0 :                 setup_module (test, unused);
     255              : 
     256            0 :                 for (i = 0; i < iterations; i++) {
     257            0 :                         g_printerr ("c");
     258              : 
     259            0 :                         transaction = gkm_transaction_new ();
     260              : 
     261            0 :                         string = g_strdup_printf ("%d", i);
     262              : 
     263            0 :                         attr.type = CKA_LABEL;
     264            0 :                         attr.pValue = string;
     265            0 :                         attr.ulValueLen = strlen (string);
     266              : 
     267            0 :                         gkm_store_write_value (GKM_STORE (test->storage), transaction,
     268              :                                                test->old_object, &attr);
     269            0 :                         gkm_assert_cmprv (gkm_transaction_get_result (transaction), ==, CKR_OK);
     270              : 
     271            0 :                         g_usleep (100 * 1000);
     272              : 
     273            0 :                         attr.type = CKA_URL;
     274            0 :                         attr.pValue = string;
     275            0 :                         attr.ulValueLen = strlen (string);
     276              : 
     277            0 :                         gkm_store_write_value (GKM_STORE (test->storage), transaction,
     278              :                                                test->old_object, &attr);
     279            0 :                         gkm_assert_cmprv (gkm_transaction_get_result (transaction), ==, CKR_OK);
     280              : 
     281            0 :                         g_free (string);
     282              : 
     283            0 :                         gkm_transaction_complete_and_unref (transaction);
     284              : 
     285            0 :                         g_usleep (10 * 1000);
     286              :                 }
     287              : 
     288            0 :                 teardown_module (test, unused);
     289            0 :                 _exit (0);
     290              :                 g_assert_not_reached ();
     291              : 
     292              :         /*
     293              :          * This is the parent. it initializes, waits 100 ms, writes a value that
     294              :          * should override the one from the child, because the file is locked
     295              :          * when it tries to write, so it waits for the child to finish. The other
     296              :          * attribute from the child (the label) should come through.
     297              :          */
     298              :         } else {
     299              :                 gchar *string1;
     300              :                 gchar *string2;
     301              :                 pid_t wpid;
     302              :                 int status;
     303              :                 CK_RV rv;
     304              : 
     305            0 :                 g_assert (pid != -1);
     306              : 
     307            0 :                 setup_module (test, unused);
     308              : 
     309            0 :                 for (i = 0; i < iterations; i++) {
     310            0 :                         g_printerr ("p");
     311              : 
     312            0 :                         string1 = gkm_store_read_string (GKM_STORE (test->storage), test->old_object, CKA_URL);
     313              : 
     314            0 :                         g_usleep (g_random_int_range (1, 200) * 1000);
     315              : 
     316            0 :                         string2 = gkm_store_read_string (GKM_STORE (test->storage), test->old_object, CKA_LABEL);
     317              : 
     318            0 :                         g_assert_cmpstr (string1, ==, string2);
     319            0 :                         g_free (string1);
     320            0 :                         g_free (string2);
     321              : 
     322            0 :                         rv = gkm_gnome2_storage_refresh (test->storage);
     323            0 :                         gkm_assert_cmprv (rv, ==, CKR_OK);
     324              :                 }
     325              : 
     326              :                 /* wait for the child to finish */
     327            0 :                 wpid = waitpid (pid, &status, 0);
     328            0 :                 g_assert_cmpint (wpid, ==, pid);
     329            0 :                 g_assert_cmpint (status, ==, 0);
     330              : 
     331            0 :                 teardown_module (test, unused);
     332              :         }
     333            0 : }
     334              : 
     335              : static void
     336            0 : test_lock_writes (Test *test,
     337              :                   gconstpointer unused)
     338              : {
     339              :         pid_t pid;
     340              : 
     341              :         /* Fork before setting up the model, as it may start threads */
     342            0 :         pid = fork ();
     343            0 :         g_assert (pid >= 0);
     344              : 
     345              :         /*
     346              :          * This is the child. It initializes, writes a value, waits 100 ms,
     347              :          * writes a second value, and then writes another value.
     348              :          */
     349            0 :         if (pid == 0) {
     350            0 :                 CK_ATTRIBUTE label = { CKA_LABEL, "Hello from child", 16 };
     351            0 :                 CK_ATTRIBUTE url = { CKA_URL, "http://child.example.com", 24 };
     352              :                 GkmTransaction *transaction;
     353              : 
     354            0 :                 setup_module (test, unused);
     355              : 
     356            0 :                 transaction = gkm_transaction_new ();
     357              : 
     358            0 :                 gkm_store_write_value (GKM_STORE (test->storage), transaction,
     359              :                                        test->old_object, &label);
     360            0 :                 gkm_assert_cmprv (gkm_transaction_get_result (transaction), ==, CKR_OK);
     361              : 
     362            0 :                 g_usleep (MSEC (100));
     363              : 
     364            0 :                 gkm_store_write_value (GKM_STORE (test->storage), transaction,
     365              :                                        test->old_object, &url);
     366            0 :                 gkm_assert_cmprv (gkm_transaction_get_result (transaction), ==, CKR_OK);
     367              : 
     368            0 :                 gkm_transaction_complete_and_unref (transaction);
     369              : 
     370            0 :                 teardown_module (test, unused);
     371            0 :                 _exit (0);
     372              :                 g_assert_not_reached ();
     373              : 
     374              :         /*
     375              :          * This is the parent. it initializes, waits 100 ms, writes a value that
     376              :          * should override the one from the child, because the file is locked
     377              :          * when it tries to write, so it waits for the child to finish. The other
     378              :          * attribute from the child (the label) should come through.
     379              :          */
     380              :         } else {
     381            0 :                 CK_ATTRIBUTE url = { CKA_URL, "http://parent.example.com", 25 };
     382              :                 GkmTransaction *transaction;
     383              :                 gchar *string;
     384              :                 pid_t wpid;
     385              :                 int status;
     386              :                 CK_RV rv;
     387              : 
     388            0 :                 g_assert (pid != -1);
     389              : 
     390            0 :                 setup_module (test, unused);
     391              : 
     392              :                 /* Refresh the store, and check values are not set */
     393            0 :                 string = gkm_store_read_string (GKM_STORE (test->storage), test->old_object, CKA_URL);
     394            0 :                 g_assert (string == NULL);
     395              : 
     396            0 :                 string = gkm_store_read_string (GKM_STORE (test->storage), test->old_object, CKA_LABEL);
     397            0 :                 g_assert (string == NULL);
     398              : 
     399            0 :                 g_usleep (MSEC (1000));
     400              : 
     401            0 :                 transaction = gkm_transaction_new ();
     402              : 
     403            0 :                 gkm_store_write_value (GKM_STORE (test->storage), transaction,
     404              :                                        test->old_object, &url);
     405            0 :                 gkm_assert_cmprv (gkm_transaction_get_result (transaction), ==, CKR_OK);
     406              : 
     407              :                 /* wait for the child to finish */
     408            0 :                 wpid = waitpid (pid, &status, 0);
     409            0 :                 g_assert_cmpint (wpid, ==, pid);
     410            0 :                 g_assert_cmpint (status, ==, 0);
     411              : 
     412            0 :                 gkm_transaction_complete_and_unref (transaction);
     413              : 
     414            0 :                 g_usleep (MSEC (1000));
     415              : 
     416            0 :                 rv = gkm_gnome2_storage_refresh (test->storage);
     417            0 :                 gkm_assert_cmprv (rv, ==, CKR_OK);
     418              : 
     419            0 :                 string = gkm_store_read_string (GKM_STORE (test->storage), test->old_object, CKA_URL);
     420            0 :                 g_assert_cmpstr (string, ==, "http://parent.example.com");
     421            0 :                 g_free (string);
     422              : 
     423            0 :                 string = gkm_store_read_string (GKM_STORE (test->storage), test->old_object, CKA_LABEL);
     424            0 :                 g_assert_cmpstr (string, ==, "Hello from child");
     425            0 :                 g_free (string);
     426              : 
     427            0 :                 teardown_module (test, unused);
     428              :         }
     429            0 : }
     430              : 
     431              : static void
     432            1 : test_relock (Test *test,
     433              :              gconstpointer unused)
     434              : {
     435              :         GkmTransaction *transaction;
     436              :         GkmSecret *old_login;
     437              :         GkmSecret *new_login;
     438              : 
     439            1 :         transaction = gkm_transaction_new ();
     440              : 
     441            1 :         old_login = NULL;
     442            1 :         new_login = gkm_secret_new_from_password ("blah");
     443              : 
     444            1 :         gkm_gnome2_storage_relock (test->storage, transaction, old_login, new_login);
     445            1 :         gkm_assert_cmprv (gkm_transaction_complete_and_unref (transaction), ==, CKR_OK);
     446              : 
     447            1 :         g_object_unref (new_login);
     448            1 : }
     449              : 
     450              : static void
     451            0 : null_log_handler (const gchar *log_domain,
     452              :                   GLogLevelFlags log_level,
     453              :                   const gchar *message,
     454              :                   gpointer user_data)
     455              : {
     456              : 
     457            0 : }
     458              : 
     459              : int
     460            1 : main (int argc, char **argv)
     461              : {
     462              : #if !GLIB_CHECK_VERSION(2,35,0)
     463              :         g_type_init ();
     464              : #endif
     465            1 :         g_test_init (&argc, &argv, NULL);
     466              : 
     467            1 :         egg_libgcrypt_initialize ();
     468              : 
     469              :         /* Suppress these messages in tests */
     470            1 :         g_log_set_handler (G_LOG_DOMAIN, G_LOG_LEVEL_MESSAGE,
     471              :                            null_log_handler, NULL);
     472              : 
     473            1 :         g_test_add ("/gnome2-store/storage/create", Test, NULL,
     474              :                     setup_all, test_create, teardown_all);
     475            1 :         g_test_add ("/gnome2-store/storage/create_and_fail", Test, NULL,
     476              :                     setup_all, test_create_and_fail, teardown_all);
     477            1 :         g_test_add ("/gnome2-store/storage/write_value", Test, NULL,
     478              :                     setup_all, test_write_value, teardown_all);
     479            1 :         g_test_add ("/gnome2-store/storage/relock", Test, NULL,
     480              :                     setup_all, test_relock, teardown_all);
     481              : 
     482            1 :         if (!g_test_quick ()) {
     483            0 :                 g_test_add ("/gnome2-store/storage/locking_transaction", Test, NULL,
     484              :                             setup_directory, test_locking_transaction, teardown_directory);
     485            0 :                 g_test_add ("/gnome2-store/storage/lock_writes", Test, NULL,
     486              :                             setup_directory, test_lock_writes, teardown_directory);
     487              :         }
     488              : 
     489            1 :         return g_test_run ();
     490              : }
        

Generated by: LCOV version 2.0-1