r20103 - gnucash/trunk/src/libqof/qof - Add a read-only attribute to QofBook and check of same to

John Ralls jralls at code.gnucash.org
Fri Jan 14 18:25:28 EST 2011


Author: jralls
Date: 2011-01-14 18:25:27 -0500 (Fri, 14 Jan 2011)
New Revision: 20103
Trac: http://svn.gnucash.org/trac/changeset/20103

Added:
   gnucash/trunk/src/libqof/qof/test/
   gnucash/trunk/src/libqof/qof/test/Makefile.am
   gnucash/trunk/src/libqof/qof/test/test-qof.c
   gnucash/trunk/src/libqof/qof/test/test-qofbackend.c
   gnucash/trunk/src/libqof/qof/test/test-qofbook.c
   gnucash/trunk/src/libqof/qof/test/test-qofinstance.c
   gnucash/trunk/src/libqof/qof/test/test-qofsession.c
Modified:
   gnucash/trunk/src/libqof/qof/Makefile.am
   gnucash/trunk/src/libqof/qof/qofbackend-p.h
   gnucash/trunk/src/libqof/qof/qofbackend.c
   gnucash/trunk/src/libqof/qof/qofbackend.h
   gnucash/trunk/src/libqof/qof/qofbook.c
   gnucash/trunk/src/libqof/qof/qofbook.h
   gnucash/trunk/src/libqof/qof/qofinstance.c
   gnucash/trunk/src/libqof/qof/qofsession.c
   gnucash/trunk/src/libqof/qof/qofsession.h
Log:
Add a read-only attribute to QofBook and check of same to 
qof_instance_begin_edit. Add qof_session_safe_save. Add unit tests for 
these changes.

QofBook read-only attribute is to prevent starting an edit when the 
version of Gnucash which created a dataset is newer than the one 
currently running. This is to prevent writing records of an old format 
into an existing data set. The user can use File>Save As to create a new 
QofSession which will write a completely new dataset in the current 
format. This is an important safety feature for future versions of 
Gnucash which will not bring all of a dataset into memory, instead 
loading only what is immediately needed.

Safe-save is the Qof access to allow writing out a dataset to an 
existing server database (i.e., postgresql or mysql) while maintaining 
the ability to both transaction-protect saving individual records while 
maintaining the ability to rollback the entire save if something goes 
wrong.

The unit test framework is added to enable testing these components. 
More tests will be added in a later commit.



Modified: gnucash/trunk/src/libqof/qof/Makefile.am
===================================================================
--- gnucash/trunk/src/libqof/qof/Makefile.am	2011-01-14 22:03:56 UTC (rev 20102)
+++ gnucash/trunk/src/libqof/qof/Makefile.am	2011-01-14 23:25:27 UTC (rev 20103)
@@ -1,3 +1,5 @@
+SUBDIRS = test
+
 lib_LTLIBRARIES = libgnc-qof.la
 
 libgnc_qof_la_LDFLAGS= -version-info $(LIBQOF_LIBRARY_VERSION)

Modified: gnucash/trunk/src/libqof/qof/qofbackend-p.h
===================================================================
--- gnucash/trunk/src/libqof/qof/qofbackend-p.h	2011-01-14 22:03:56 UTC (rev 20102)
+++ gnucash/trunk/src/libqof/qof/qofbackend-p.h	2011-01-14 23:25:27 UTC (rev 20103)
@@ -311,6 +311,7 @@
     void (*run_query) (QofBackend *, gpointer);
 
     void (*sync) (QofBackend *, /*@ dependent @*/ QofBook *);
+    void (*safe_sync) (QofBackend *, /*@ dependent @*/ QofBook *);
     void (*load_config) (QofBackend *, KvpFrame *);
     /*@ observer @*/
     KvpFrame* (*get_config) (QofBackend *);

Modified: gnucash/trunk/src/libqof/qof/qofbackend.c
===================================================================
--- gnucash/trunk/src/libqof/qof/qofbackend.c	2011-01-14 22:03:56 UTC (rev 20102)
+++ gnucash/trunk/src/libqof/qof/qofbackend.c	2011-01-14 23:25:27 UTC (rev 20103)
@@ -129,6 +129,7 @@
     be->run_query = NULL;
 
     be->sync = NULL;
+    be->safe_sync = NULL;
     be->load_config = NULL;
 
     be->events_pending = NULL;

Modified: gnucash/trunk/src/libqof/qof/qofbackend.h
===================================================================
--- gnucash/trunk/src/libqof/qof/qofbackend.h	2011-01-14 22:03:56 UTC (rev 20102)
+++ gnucash/trunk/src/libqof/qof/qofbackend.h	2011-01-14 23:25:27 UTC (rev 20103)
@@ -107,6 +107,7 @@
     /* database errors */
     ERR_SQL_MISSING_DATA = 3000,  /**< database doesn't contain expected data */
     ERR_SQL_DB_TOO_OLD,           /**< database is old and needs upgrading */
+    ERR_SQL_DB_TOO_NEW,		  /**< database is newer, we can't write to it */
     ERR_SQL_DB_BUSY,              /**< database is busy, cannot upgrade version */
 
     /* RPC errors */

Modified: gnucash/trunk/src/libqof/qof/qofbook.c
===================================================================
--- gnucash/trunk/src/libqof/qof/qofbook.c	2011-01-14 22:03:56 UTC (rev 20102)
+++ gnucash/trunk/src/libqof/qof/qofbook.c	2011-01-14 23:25:27 UTC (rev 20103)
@@ -76,6 +76,7 @@
     book->data_table_finalizers = g_hash_table_new (g_str_hash, g_str_equal);
 
     book->book_open = 'y';
+    book->read_only = FALSE;
     book->version = 0;
 }
 
@@ -302,7 +303,21 @@
 }
 
 /* ====================================================================== */
+gboolean
+qof_book_is_readonly(const QofBook *book)
+{
+    g_return_val_if_fail( book != NULL, TRUE );
+    return book->read_only;
+}
 
+void
+qof_book_mark_readonly(QofBook *book)
+{
+    g_return_if_fail( book != NULL );
+    book->read_only = TRUE;
+}
+/* ====================================================================== */
+
 QofCollection *
 qof_book_get_collection (const QofBook *book, QofIdType entity_type)
 {

Modified: gnucash/trunk/src/libqof/qof/qofbook.h
===================================================================
--- gnucash/trunk/src/libqof/qof/qofbook.h	2011-01-14 22:03:56 UTC (rev 20102)
+++ gnucash/trunk/src/libqof/qof/qofbook.h	2011-01-14 23:25:27 UTC (rev 20103)
@@ -96,6 +96,12 @@
     /* Hash table of destroy callbacks for the data table. */
     GHashTable *data_table_finalizers;
 
+    /* Boolean indicates whether book is safe to write to (true means
+     * that it isn't. The usual reason will be a database version
+     * mismatch with the running instance of Gnucash.
+     */
+    gboolean read_only;
+
     /* state flag: 'y' means 'open for editing',
      * 'n' means 'book is closed'
      * xxxxx shouldn't this be replaced by the instance editlevel ???
@@ -221,6 +227,12 @@
 /** Retrieves arbitrary pointers to structs stored by qof_book_set_data. */
 gpointer qof_book_get_data (const QofBook *book, const gchar *key);
 
+/** Return whether the book is read only. */
+gboolean qof_book_is_readonly(const QofBook *book);
+
+/** Mark the book as read only. */
+void qof_book_mark_readonly(QofBook *book);
+
 #endif /* SWIG */
 
 /** Returns flag indicating whether this book uses trading accounts */

Modified: gnucash/trunk/src/libqof/qof/qofinstance.c
===================================================================
--- gnucash/trunk/src/libqof/qof/qofinstance.c	2011-01-14 22:03:56 UTC (rev 20102)
+++ gnucash/trunk/src/libqof/qof/qofinstance.c	2011-01-14 23:25:27 UTC (rev 20103)
@@ -1055,6 +1055,7 @@
     if (!inst) return FALSE;
 
     priv = GET_PRIVATE(inst);
+    if (qof_book_is_readonly(priv->book)) return FALSE;
     priv->editlevel++;
     if (1 < priv->editlevel) return FALSE;
     if (0 >= priv->editlevel)

Modified: gnucash/trunk/src/libqof/qof/qofsession.c
===================================================================
--- gnucash/trunk/src/libqof/qof/qofsession.c	2011-01-14 22:03:56 UTC (rev 20102)
+++ gnucash/trunk/src/libqof/qof/qofsession.c	2011-01-14 23:25:27 UTC (rev 20103)
@@ -1250,9 +1250,10 @@
     */
     err = qof_session_get_error(session);
     if ((err != ERR_BACKEND_NO_ERR) &&
-            (err != ERR_FILEIO_FILE_TOO_OLD) &&
-            (err != ERR_FILEIO_NO_ENCODING) &&
-            (err != ERR_SQL_DB_TOO_OLD))
+	(err != ERR_FILEIO_FILE_TOO_OLD) &&
+	(err != ERR_FILEIO_NO_ENCODING) &&
+	(err != ERR_SQL_DB_TOO_OLD) &&
+	(err != ERR_SQL_DB_TOO_NEW))
     {
         /* Something broke, put back the old stuff */
         qof_book_set_backend (newbook, NULL);
@@ -1262,7 +1263,6 @@
         LEAVE("error from backend %d", qof_session_get_error(session));
         return;
     }
-
     for (node = oldbooks; node; node = node->next)
     {
         ob = node->data;
@@ -1450,6 +1450,27 @@
     return;
 }
 
+void
+qof_session_safe_save(QofSession *session, QofPercentageFunc percentage_func)
+{
+    QofBackend *be = session->backend;
+    gint err;
+    char *msg = NULL;
+    g_return_if_fail( be != NULL );
+    g_return_if_fail( be->safe_sync != NULL );
+    be->percentage = percentage_func;
+    (be->safe_sync)( be, qof_session_get_book( session ));
+    err = qof_backend_get_error(session->backend);
+    msg = qof_backend_get_message(session->backend);
+    if (err != ERR_BACKEND_NO_ERR)
+    {
+	g_free(session->book_id);
+	session->book_id = NULL;
+	qof_session_push_error (session, err, msg);
+    }
+}
+
+
 /* ====================================================================== */
 gboolean
 qof_session_save_in_progress(const QofSession *session)

Modified: gnucash/trunk/src/libqof/qof/qofsession.h
===================================================================
--- gnucash/trunk/src/libqof/qof/qofsession.h	2011-01-14 22:03:56 UTC (rev 20102)
+++ gnucash/trunk/src/libqof/qof/qofsession.h	2011-01-14 23:25:27 UTC (rev 20103)
@@ -234,7 +234,18 @@
  */
 void     qof_session_save (QofSession *session,
                            QofPercentageFunc percentage_func);
+
 /**
+ * A special version of save used in the sql backend which moves the
+ * existing tables aside, then saves everything to new tables, then
+ * deletes the old tables after the save is completed without
+ * error. If there are errors, it removes the old tables and renames
+ * the new tables back.
+ */
+void     qof_session_safe_save (QofSession *session,
+				QofPercentageFunc percentage_func);
+
+/**
  * The qof_session_end() method will release the session lock. For the
  *    file backend, it will *not* save the data to a file. Thus,
  *    this method acts as an "abort" or "rollback" primitive.  However,

Added: gnucash/trunk/src/libqof/qof/test/Makefile.am
===================================================================
--- gnucash/trunk/src/libqof/qof/test/Makefile.am	                        (rev 0)
+++ gnucash/trunk/src/libqof/qof/test/Makefile.am	2011-01-14 23:25:27 UTC (rev 20103)
@@ -0,0 +1,34 @@
+# A template Makefile.am for GLib g_test-based test directories.
+# Copyright 2011 John Ralls <jralls at ceridwen.us>
+
+include $(top_srcdir)/test-templates/Makefile.decl
+
+
+#You will only need one of these: It points to the module directory
+#after $(top_srcdir) or $(top_builddir):
+MODULEPATH = src/libqof/qof
+
+test_qof_SOURCES = \
+	test-qof.c \
+	test-qofbook.c \
+	test-qofinstance.c \
+	test-qofsession.c
+
+test_qof_HEADERSS = \
+	$(top_srcdir)/${MODULEPATH}/qofbook.h \
+	$(top_srcdir)/${MODULEPATH}/qofinstance.h \
+	$(top_srcdir)/${MODULEPATH/}qofsession.h
+
+TEST_PROGS += test-qof
+
+noinst_PROGRAMS = ${TEST_PROGS}
+
+#The tests might require more libraries, but try to keep them
+#as independent as possible.
+test_qof_LDADD = ${top_builddir}/${MODULEPATH}/libgnc-qof.la
+
+test_qof_CFLAGS = \
+	${DEFAULT_INCLUDES} \
+	-I$(top_srcdir)/${MODULEPATH}/ \
+	-DTESTPROG=test_qof \
+	${GLIB_CFLAGS}

Added: gnucash/trunk/src/libqof/qof/test/test-qof.c
===================================================================
--- gnucash/trunk/src/libqof/qof/test/test-qof.c	                        (rev 0)
+++ gnucash/trunk/src/libqof/qof/test/test-qof.c	2011-01-14 23:25:27 UTC (rev 20103)
@@ -0,0 +1,45 @@
+/********************************************************************
+ * testmain.c: GLib g_test test execution file.			    *
+ * Copyright 2011 John Ralls <jralls at ceridwen.us>		    *
+ *                                                                  *
+ * This program is free software; you can redistribute it and/or    *
+ * modify it under the terms of the GNU General Public License as   *
+ * published by the Free Software Foundation; either version 2 of   *
+ * the License, or (at your option) any later version.              *
+ *                                                                  *
+ * 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, contact:                        *
+ *                                                                  *
+ * Free Software Foundation           Voice:  +1-617-542-5942       *
+ * 51 Franklin Street, Fifth Floor    Fax:    +1-617-542-2652       *
+ * Boston, MA  02110-1301,  USA       gnu at gnu.org                   *
+\********************************************************************/
+
+
+#include <glib.h>
+
+extern void test_suite_qofbook();
+extern void test_suite_qofinstance();
+extern void test_suite_qofsession();
+
+int
+main (int   argc,
+      char *argv[])
+{
+    g_type_init(); 			/* Initialize the GObject system */
+    g_test_init ( &argc, &argv ); 		/* initialize test program */
+    qof_log_init_filename_special("/dev/null"); /* Init the log system */
+
+    test_suite_qofbook();
+    test_suite_qofinstance();
+    test_suite_qofsession();
+
+    return g_test_run( );
+}
+
+

Added: gnucash/trunk/src/libqof/qof/test/test-qofbackend.c
===================================================================
--- gnucash/trunk/src/libqof/qof/test/test-qofbackend.c	                        (rev 0)
+++ gnucash/trunk/src/libqof/qof/test/test-qofbackend.c	2011-01-14 23:25:27 UTC (rev 20103)
@@ -0,0 +1,31 @@
+/********************************************************************
+ * test_qofbackend.c: GLib g_test test suite for qofbackend.	    *
+ * Copyright 2011 John Ralls <jralls at ceridwen.us>		    *
+ *                                                                  *
+ * This program is free software; you can redistribute it and/or    *
+ * modify it under the terms of the GNU General Public License as   *
+ * published by the Free Software Foundation; either version 2 of   *
+ * the License, or (at your option) any later version.              *
+ *                                                                  *
+ * 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, contact:                        *
+ *                                                                  *
+ * Free Software Foundation           Voice:  +1-617-542-5942       *
+ * 51 Franklin Street, Fifth Floor    Fax:    +1-617-542-2652       *
+ * Boston, MA  02110-1301,  USA       gnu at gnu.org                   *
+\********************************************************************/
+
+#include <glib/glib.h>
+
+static const gchar *suitename = "qof/qofbackend";
+
+GTestSuite*
+test_suite_qofbackend ( void )
+{
+ 
+}

Added: gnucash/trunk/src/libqof/qof/test/test-qofbook.c
===================================================================
--- gnucash/trunk/src/libqof/qof/test/test-qofbook.c	                        (rev 0)
+++ gnucash/trunk/src/libqof/qof/test/test-qofbook.c	2011-01-14 23:25:27 UTC (rev 20103)
@@ -0,0 +1,59 @@
+/********************************************************************
+ * test_qofbook.c: GLib g_test test suite for qofbook.		    *
+ * Copyright 2011 John Ralls <jralls at ceridwen.us>		    *
+ *                                                                  *
+ * This program is free software; you can redistribute it and/or    *
+ * modify it under the terms of the GNU General Public License as   *
+ * published by the Free Software Foundation; either version 2 of   *
+ * the License, or (at your option) any later version.              *
+ *                                                                  *
+ * 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, contact:                        *
+ *                                                                  *
+ * Free Software Foundation           Voice:  +1-617-542-5942       *
+ * 51 Franklin Street, Fifth Floor    Fax:    +1-617-542-2652       *
+ * Boston, MA  02110-1301,  USA       gnu at gnu.org                   *
+\********************************************************************/
+#include <config.h>
+#include <string.h>
+#include <glib.h>
+#include <qof.h>
+
+static const gchar *suitename = "/qof/qofbook";
+
+typedef struct
+{
+    QofBook *book;
+} Fixture;
+
+static void
+setup( Fixture *fixture, gconstpointer pData )
+{
+    fixture->book = qof_book_new();
+}
+
+static void
+teardown( Fixture *fixture, gconstpointer pData )
+{
+    qof_book_destroy( fixture->book );
+}
+
+static void
+test_book_readonly( Fixture *fixture, gconstpointer pData )
+{
+    g_assert( fixture->book != NULL );
+    g_assert( !qof_book_is_readonly( fixture->book ) );
+    qof_book_mark_readonly( fixture->book );
+    g_assert( qof_book_is_readonly( fixture->book ) );
+}
+
+void
+test_suite_qofbook ( void )
+{
+    g_test_add( suitename, Fixture, NULL, setup, test_book_readonly, teardown );
+}

Added: gnucash/trunk/src/libqof/qof/test/test-qofinstance.c
===================================================================
--- gnucash/trunk/src/libqof/qof/test/test-qofinstance.c	                        (rev 0)
+++ gnucash/trunk/src/libqof/qof/test/test-qofinstance.c	2011-01-14 23:25:27 UTC (rev 20103)
@@ -0,0 +1,63 @@
+/********************************************************************
+ * test_qofinstance.c: GLib g_test test suite for qofinstance.	    *
+ * Copyright 2011 John Ralls <jralls at ceridwen.us>		    *
+ *                                                                  *
+ * This program is free software; you can redistribute it and/or    *
+ * modify it under the terms of the GNU General Public License as   *
+ * published by the Free Software Foundation; either version 2 of   *
+ * the License, or (at your option) any later version.              *
+ *                                                                  *
+ * 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, contact:                        *
+ *                                                                  *
+ * Free Software Foundation           Voice:  +1-617-542-5942       *
+ * 51 Franklin Street, Fifth Floor    Fax:    +1-617-542-2652       *
+ * Boston, MA  02110-1301,  USA       gnu at gnu.org                   *
+\********************************************************************/
+#include <config.h>
+#include <glib.h>
+#include <qof.h>
+
+static const gchar *suitename = "/qof/qofinstance";
+
+typedef struct
+{
+    QofInstance *instance;
+} Fixture;
+
+static void
+setup( Fixture *fixture, gconstpointer pData )
+{
+    fixture->instance = g_object_new(QOF_TYPE_INSTANCE, NULL);
+    qof_instance_set_book( fixture->instance, qof_book_new() );
+}
+
+static void
+teardown( Fixture *fixture, gconstpointer pData )
+{
+    qof_book_destroy( qof_instance_get_book( fixture->instance ) );
+    g_object_unref(fixture->instance);
+}
+
+static void
+test_book_readonly( Fixture *fixture, gconstpointer pData )
+{
+    QofBook *book = qof_instance_get_book( fixture->instance );
+    g_assert( !qof_book_is_readonly( book ) );
+    qof_book_mark_readonly( book );
+    g_assert( qof_book_is_readonly( book ) );
+    g_assert( !qof_begin_edit( fixture->instance ) );
+}
+
+
+void
+test_suite_qofinstance ( void )
+{
+    g_test_add( suitename, Fixture, NULL, setup, test_book_readonly, teardown );
+
+}

Added: gnucash/trunk/src/libqof/qof/test/test-qofsession.c
===================================================================
--- gnucash/trunk/src/libqof/qof/test/test-qofsession.c	                        (rev 0)
+++ gnucash/trunk/src/libqof/qof/test/test-qofsession.c	2011-01-14 23:25:27 UTC (rev 20103)
@@ -0,0 +1,76 @@
+/********************************************************************
+ * test_qofsession.c: GLib g_test test suite for qofsession.	    *
+ * Copyright 2011 John Ralls <jralls at ceridwen.us>		    *
+ *                                                                  *
+ * This program is free software; you can redistribute it and/or    *
+ * modify it under the terms of the GNU General Public License as   *
+ * published by the Free Software Foundation; either version 2 of   *
+ * the License, or (at your option) any later version.              *
+ *                                                                  *
+ * 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, contact:                        *
+ *                                                                  *
+ * Free Software Foundation           Voice:  +1-617-542-5942       *
+ * 51 Franklin Street, Fifth Floor    Fax:    +1-617-542-2652       *
+ * Boston, MA  02110-1301,  USA       gnu at gnu.org                   *
+\********************************************************************/
+
+#include <config.h>
+#include <glib.h>
+#include <qof.h>
+#include <qofbackend-p.h>
+#include <qofsession-p.h>
+
+static const gchar *suitename = "/qof/qofsession";
+
+typedef struct
+{
+    QofSession *session;
+} Fixture;
+
+static void
+safe_sync( QofBackend *be, QofBook *book )
+{
+    qof_backend_set_error( be, ERR_BACKEND_DATA_CORRUPT );
+    qof_backend_set_message( be, "Just Kidding!" );
+}
+
+static void
+percentage_fn ( const char* message, double percent )
+{
+    g_print( "%s %f complete", message, percent );
+}
+
+static void
+setup( Fixture *fixture, gconstpointer pData )
+{
+    fixture->session = qof_session_new();
+    fixture->session->backend = g_new0( QofBackend, 1 );
+    fixture->session->backend->safe_sync = safe_sync;
+}
+
+static void
+teardown( Fixture *fixture, gconstpointer pData )
+{
+    qof_session_destroy( fixture->session );
+}
+
+static void
+test_session_safe_save( Fixture *fixture, gconstpointer pData )
+{
+    qof_session_safe_save( fixture->session, percentage_fn );
+    g_assert_cmpint( ERR_BACKEND_DATA_CORRUPT, ==,
+		     qof_session_get_error( fixture->session ));
+    g_assert( NULL == qof_session_get_url( fixture->session ));
+}
+
+GTestSuite*
+test_suite_qofsession ( void )
+{
+    g_test_add( suitename, Fixture, NULL, setup, test_session_safe_save, teardown );
+}



More information about the gnucash-changes mailing list