gnucash/libgnucash/engine/test/test-qofinstance.cpp
John Ralls 7a7c26f87e Move glib and gtk includes out of extern C for tests.
Needed to compile with glib 2.67 and later.
2021-02-16 13:23:48 -08:00

1007 lines
38 KiB
C++

/********************************************************************
* test_qofinstance.c: GLib g_test test suite for qofinstance. *
* Copyright 2011 John Ralls <jralls@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@gnu.org *
\********************************************************************/
#include <glib.h>
#include <guid.hpp>
extern "C"
{
#include <config.h>
#include <unittest-support.h>
#include "../qof.h"
}
#include "../qof-backend.hpp"
#include "../kvp-frame.hpp"
static const gchar *suitename = "/qof/qofinstance";
extern "C" void test_suite_qofinstance ( void );
static gchar* error_message;
static gboolean is_called;
static struct
{
QofInstance *m_inst = nullptr;
QofBackend *m_be = nullptr;
bool m_commit_called = false;
bool m_commit_with_err_called = false;
bool m_on_error_called = false;
bool m_on_free_called = false;
bool m_on_done_called = false;
QofBackendError m_err = ERR_BACKEND_NO_ERR;
} commit_test;
class QofInstMockBackend : public QofBackend
{
public:
QofInstMockBackend() : m_qof_error{ERR_BACKEND_NO_ERR} {
commit_test.m_be = this;
}
void session_begin(QofSession* sess, const char* uri,
SessionOpenMode mode) override {}
void session_end() override {}
void load(QofBook*, QofBackendLoadType) override {}
void sync(QofBook* book) override {}
void safe_sync(QofBook* book) override {}
void begin(QofInstance* inst) override {
g_assert(inst);
g_assert(QOF_IS_INSTANCE(inst));
commit_test.m_inst = inst;
}
void set_error(QofBackendError err) {
QofBackend::set_error(err);
commit_test.m_err = err;
}
void commit(QofInstance* inst) override {
g_assert( inst );
g_assert( QOF_IS_INSTANCE( inst ) );
g_assert( commit_test.m_inst == inst );
g_assert( commit_test.m_be == this );
commit_test.m_commit_called = true;
if (qof_instance_is_dirty(inst))
qof_instance_mark_clean(inst);
set_error(m_qof_error);
}
void rollback(QofInstance* inst) override {}
void inject_error(QofBackendError err) {
m_qof_error = err;
}
private:
QofBackendError m_qof_error;
};
typedef struct
{
QofInstance *inst;
} Fixture;
static void
on_error(QofInstance* inst, QofBackendError err) {
g_assert( inst );
g_assert( QOF_IS_INSTANCE( inst ) );
g_assert( commit_test.m_err == err );
commit_test.m_on_error_called = true;
}
static void
on_done(QofInstance* inst) {
g_assert( inst );
g_assert( QOF_IS_INSTANCE( inst ) );
g_assert( commit_test.m_inst == inst );
commit_test.m_on_done_called = true;
}
static void
on_free(QofInstance* inst) {
g_assert( inst );
g_assert( QOF_IS_INSTANCE( inst ) );
g_assert(commit_test.m_inst == inst );
commit_test.m_on_free_called = true;
}
/* use g_free on error_message after this function been called */
static gboolean
fatal_handler ( const char * log_domain,
GLogLevelFlags log_level,
const gchar *msg,
gpointer user_data)
{
error_message = (gchar *) g_strdup( msg );
return FALSE;
}
static void
setup( Fixture *fixture, gconstpointer pData )
{
fixture->inst = static_cast<QofInstance*>(g_object_new(QOF_TYPE_INSTANCE, NULL));
}
static void
teardown( Fixture *fixture, gconstpointer pData )
{
g_object_unref(fixture->inst);
}
static void
test_instance_set_get_book( Fixture *fixture, gconstpointer pData )
{
QofBook *book;
/* set up */
book = qof_book_new();
g_assert( QOF_IS_INSTANCE( fixture->inst ) );
g_test_message( "Setting and getting book" );
qof_instance_set_book( fixture->inst, book );
g_assert( book == qof_instance_get_book( fixture->inst ) );
g_test_message( "Getting book when instance is null" );
g_assert( qof_instance_get_book( NULL ) == NULL );
/* Clean up */
qof_book_destroy( book );
}
static void
test_instance_set_get_guid( Fixture *fixture, gconstpointer pData )
{
GncGUID *gncGuid;
/* on null instance deprecated getter returns empty guid
* while instance_get_guid returns null
*/
g_assert( !qof_instance_get_guid( NULL ) );
g_assert( qof_entity_get_guid( NULL ) == guid_null() );
/* set up */
gncGuid = guid_new();
g_assert( QOF_IS_INSTANCE( fixture->inst ) );
g_assert( gncGuid );
/* guid already exists after instance init */
g_test_message( "Setting new guid" );
g_assert( qof_instance_get_guid( fixture->inst ) );
g_assert( !guid_equal( gncGuid, qof_instance_get_guid( fixture->inst ) ) );
qof_instance_set_guid( fixture->inst, gncGuid );
g_assert( guid_equal( gncGuid, qof_instance_get_guid( fixture->inst ) ) );
g_assert( guid_equal( gncGuid, qof_entity_get_guid( fixture->inst ) ) );
/* Clean up */
guid_free( gncGuid );
}
static void
test_instance_new_destroy( void )
{
/* qofinstance var */
QofInstance *inst;
QofInstanceClass *klass;
/* test var */
Time64 *time_priv;
const char *msg1 = "qof_instance_get_collection: assertion 'QOF_IS_INSTANCE(ptr)' failed";
const char *msg2 = "qof_instance_get_editlevel: assertion 'QOF_IS_INSTANCE(ptr)' failed";
const char *msg3 = "qof_instance_get_destroying: assertion 'QOF_IS_INSTANCE(ptr)' failed";
const char *msg4 = "qof_instance_get_dirty_flag: assertion 'QOF_IS_INSTANCE(ptr)' failed";
const char *log_domain = "qof";
auto loglevel = static_cast<GLogLevelFlags>(G_LOG_LEVEL_CRITICAL | G_LOG_FLAG_FATAL);
auto check = test_error_struct_new(log_domain, loglevel, msg1);
g_test_message( "Testing qofinstance object initialization" );
inst = static_cast<QofInstance*>(g_object_new(QOF_TYPE_INSTANCE, NULL));
g_assert( QOF_IS_INSTANCE( inst ) );
/* test class fields */
klass = QOF_INSTANCE_GET_CLASS( inst );
g_assert( QOF_IS_INSTANCE_CLASS( klass ) );
g_assert( klass->get_display_name == NULL );
g_assert( klass->refers_to_object == NULL );
g_assert( klass->get_typed_referring_object_list == NULL );
/* testing initial values */
g_assert( qof_instance_get_guid( inst ) );
g_assert( !qof_instance_get_collection( inst ) );
g_assert( qof_instance_get_book( inst ) == NULL );
g_assert( inst->kvp_data );
g_object_get( inst, "last-update", &time_priv, NULL);
g_assert_cmpint( time_priv->t, == , 0 );
g_assert_cmpint( qof_instance_get_editlevel( inst ), == , 0 );
g_assert( !qof_instance_get_destroying( inst ) );
g_assert( !qof_instance_get_dirty_flag( inst ) );
g_assert( qof_instance_get_infant( inst ) );
g_assert_cmpint( qof_instance_get_version( inst ), == , 0 );
g_assert_cmpint( qof_instance_get_version_check( inst ), == , 0 );
g_assert_cmpint( qof_instance_get_idata( inst ), == , 0 );
g_test_message( "Testing object destruction" );
g_object_unref( inst );
g_free( error_message );
test_error_struct_free(check);
}
static void
test_instance_init_data( void )
{
QofInstance *inst;
QofIdType test_type = "test type";
QofBook *book;
QofCollection *col;
const GncGUID *gncguid;
char guid_id_before[GUID_ENCODING_LENGTH + 1];
char guid_id_after[GUID_ENCODING_LENGTH + 1];
/* set up */
inst = static_cast<QofInstance*>(g_object_new( QOF_TYPE_INSTANCE, NULL ));
g_assert( QOF_IS_INSTANCE( inst ) );
book = qof_book_new();
g_assert( QOF_IS_BOOK( book ) );
/* set fatal handler */
g_test_log_set_fatal_handler ( ( GTestLogFatalFunc )fatal_handler, NULL );
g_test_message( "Running test with correct initial data" );
gncguid = qof_instance_get_guid( inst );
g_assert( gncguid );
guid_to_string_buff( gncguid, guid_id_before );
g_assert( qof_instance_get_book( inst ) == NULL );
g_assert( qof_instance_get_collection( inst ) == NULL );
/* run init */
qof_instance_init_data( inst, test_type, book );
g_assert( qof_instance_get_book( inst ) == book );
guid_to_string_buff( gncguid, guid_id_after );
g_assert_cmpstr( guid_id_before, != , guid_id_after );
g_assert( qof_instance_get_collection( inst ) != NULL );
col = qof_book_get_collection( book, test_type );
g_assert( col );
g_assert( col == qof_instance_get_collection( inst ) );
g_assert_cmpstr( inst->e_type, == , test_type );
g_assert( qof_collection_lookup_entity( qof_instance_get_collection( inst ), gncguid ) == inst );
/* clean up */
g_object_unref( inst );
qof_book_destroy( book );
}
static void
test_instance_get_set_slots( Fixture *fixture, gconstpointer pData )
{
KvpFrame *kvp_frame, *kvp_frame2;
/* set up */
g_assert( fixture->inst );
kvp_frame = qof_instance_get_slots( fixture->inst );
g_assert( kvp_frame );
g_test_message( "Test when kvp frame is the same" );
qof_instance_set_slots( fixture->inst, kvp_frame );
g_assert( kvp_frame == qof_instance_get_slots( fixture->inst ) );
g_assert( qof_instance_get_dirty_flag( fixture->inst ) );
g_test_message( "Test when kvp frame is not the same" );
kvp_frame2 = new KvpFrame;
g_assert( kvp_frame != kvp_frame2 );
qof_instance_set_slots( fixture->inst, kvp_frame2 );
g_assert( kvp_frame2 == qof_instance_get_slots( fixture->inst ) );
g_assert( qof_instance_get_dirty_flag( fixture->inst ) );
g_test_message( "Test when kvp frame is null" );
qof_instance_set_slots( fixture->inst, NULL );
g_assert( NULL == qof_instance_get_slots( fixture->inst ) );
g_assert( qof_instance_get_dirty_flag( fixture->inst ) );
}
static void
test_instance_version_cmp( void )
{
QofInstance *left, *right;
int result;
time64 time_left = 0, time_right = 1;
/* set up*/
left = static_cast<QofInstance*>(g_object_new( QOF_TYPE_INSTANCE, NULL ));
right = static_cast<QofInstance*>(g_object_new( QOF_TYPE_INSTANCE, NULL ));
g_test_message( "Test both null" );
result = qof_instance_version_cmp( NULL, NULL );
g_assert_cmpint( result, == , 0 );
g_test_message( "Test left null" );
result = qof_instance_version_cmp( NULL, right );
g_assert_cmpint( result, == , -1 );
g_test_message( "Test right null" );
result = qof_instance_version_cmp( left, NULL );
g_assert_cmpint( result, == , 1 );
g_test_message( "Test left tv_sec lesser than right" );
qof_instance_set_last_update( left, time_left );
qof_instance_set_last_update( right, time_right );
result = qof_instance_version_cmp( left, right );
g_assert_cmpint( result, == , -1 );
g_test_message( "Test right tv_sec lesser than left" );
time_left = 1;
time_right = 0;
qof_instance_set_last_update( left, time_left );
qof_instance_set_last_update( right, time_right );
result = qof_instance_version_cmp( left, right );
g_assert_cmpint( result, == , 1 );
g_test_message( "Test both equal" );
time_left = 1;
time_right = 1;
qof_instance_set_last_update( left, time_left );
qof_instance_set_last_update( right, time_right );
result = qof_instance_version_cmp( left, right );
g_assert_cmpint( result, == , 0 );
/* clear */
g_object_unref( left );
g_object_unref( right );
}
static void
test_instance_get_set_dirty( Fixture *fixture, gconstpointer pData )
{
QofIdType type = "test type";
QofCollection *col;
/* setup */
col = qof_collection_new ( type );
qof_instance_set_collection( fixture->inst, col );
g_assert( qof_instance_get_collection( fixture->inst ) );
g_test_message( "Test get_dirty on empty instance returns false" );
g_assert( qof_instance_get_dirty( NULL ) == FALSE );
g_test_message( "Test dirty" );
g_assert( !qof_instance_get_dirty_flag( fixture->inst ) );
g_assert( !qof_collection_is_dirty( col ) );
g_assert( !qof_instance_get_dirty( fixture->inst ) );
qof_instance_set_dirty( fixture->inst );
g_assert( qof_instance_get_dirty_flag( fixture->inst ) );
g_assert( !qof_collection_is_dirty( col ) );
g_assert( qof_instance_get_dirty( fixture->inst ) );
/* clean up */
qof_instance_set_collection( fixture->inst, NULL );
qof_collection_destroy( col );
}
/* mock display name function */
static gchar*
mock_get_display_name(const QofInstance* inst)
{
gchar *display_name;
g_assert( inst );
g_assert( QOF_INSTANCE_GET_CLASS( inst )->get_display_name == mock_get_display_name );
is_called = TRUE;
display_name = g_strdup_printf("Mock display name %p", inst );
return display_name;
}
static void
test_instance_display_name( Fixture *fixture, gconstpointer pData )
{
QofIdType type = "test type";
QofCollection *col;
gchar *display_name, *default_display_name, *mock_display_name;
/* setup */
g_assert( fixture->inst );
is_called = FALSE;
col = qof_collection_new ( type );
g_assert( col );
qof_instance_set_collection( fixture->inst, col );
g_assert( qof_instance_get_collection( fixture->inst ) );
default_display_name = g_strdup_printf( "Object %s %p", type, fixture->inst );
mock_display_name = g_strdup_printf( "Mock display name %p", fixture->inst );
g_test_message( "Test instance when display name not set" );
g_assert( QOF_INSTANCE_GET_CLASS( fixture->inst )->get_display_name == NULL );
display_name = qof_instance_get_display_name( fixture->inst );
g_assert( !is_called );
g_assert_cmpstr( display_name, == , default_display_name );
g_free( display_name );
g_test_message( "Test instance when display name is set" );
QOF_INSTANCE_GET_CLASS( fixture->inst )->get_display_name = mock_get_display_name;
display_name = qof_instance_get_display_name( fixture->inst );
g_assert( is_called );
g_assert_cmpstr( display_name, == , mock_display_name );
g_free( display_name );
/* clean up */
g_free( default_display_name );
g_free( mock_display_name );
qof_instance_set_collection( fixture->inst, NULL );
qof_collection_destroy( col );
}
static void
mock_backend_begin( QofBackend *be, QofInstance *inst )
{
g_assert( be );
g_assert( inst );
g_assert_cmpstr( inst->e_type, == , "test type" );
is_called = TRUE;
}
static void
test_instance_begin_edit( Fixture *fixture, gconstpointer pData )
{
QofBook *book;
gboolean result;
/* setup */
auto be = new QofInstMockBackend;
g_assert( be );
book = qof_book_new();
g_assert( book );
g_assert( QOF_IS_BOOK( book ) );
qof_book_set_backend( book, be );
g_assert( fixture->inst );
fixture->inst->e_type = "test type";
g_assert( qof_instance_get_dirty_flag( fixture->inst ) == FALSE );
g_assert_cmpint( qof_instance_get_editlevel( fixture->inst ), == , 0 );
g_test_message( "Test when instance is null" );
result = qof_begin_edit( NULL );
g_assert( result == FALSE );
g_test_message( "Test when instance's editlevel is >= 1" );
qof_instance_increase_editlevel( fixture->inst );
result = qof_begin_edit( fixture->inst );
g_assert( result == FALSE );
g_assert_cmpint( qof_instance_get_editlevel( fixture->inst ), == , 2 );
g_test_message( "Test when instance's editlevel is <= 0 and backend not set" );
qof_instance_reset_editlevel( fixture->inst );
result = qof_begin_edit( fixture->inst );
g_assert( result == TRUE );
g_assert_cmpint( qof_instance_get_editlevel( fixture->inst ), == , 1 );
g_assert( qof_instance_get_dirty_flag( fixture->inst ) == TRUE );
g_test_message( "Test when instance's editlevel is <= 0 and backend is set" );
result = FALSE;
qof_instance_reset_editlevel( fixture->inst );
qof_instance_set_dirty_flag( fixture->inst, FALSE );
qof_instance_set_book( fixture->inst, book );
result = qof_begin_edit( fixture->inst );
g_assert( result == TRUE );
g_assert_cmpint( qof_instance_get_editlevel( fixture->inst ), == , 1 );
g_assert( qof_instance_get_dirty_flag( fixture->inst ) == FALSE );
/* clean up */
qof_book_set_backend( book, NULL );
qof_book_destroy( book );
delete be;
}
static void
test_instance_commit_edit( Fixture *fixture, gconstpointer pData )
{
gboolean result;
const gchar *msg = "[qof_commit_edit()] unbalanced call - resetting (was -2)";
const gchar *log_domain = "qof.engine";
auto loglevel = static_cast<GLogLevelFlags>(G_LOG_LEVEL_CRITICAL | G_LOG_FLAG_FATAL);
auto check = test_error_struct_new(log_domain, loglevel, msg);
g_test_message( "Test when instance set to null" );
result = qof_commit_edit( NULL );
g_assert( !result );
g_test_message( "Test when instance's editlevel >= 2" );
qof_instance_increase_editlevel( fixture->inst );
qof_instance_increase_editlevel( fixture->inst );
g_assert_cmpint( qof_instance_get_editlevel( fixture->inst ), == , 2 );
result = qof_commit_edit( fixture->inst );
g_assert_cmpint( qof_instance_get_editlevel( fixture->inst ), == , 1 );
g_assert( !result );
g_test_message( "Test when instance's editlevel = 1" );
result = qof_commit_edit( fixture->inst );
g_assert_cmpint( qof_instance_get_editlevel( fixture->inst ), == , 0 );
g_assert( result );
g_test_message( "Test when instance's editlevel < 0" );
g_test_log_set_fatal_handler ( ( GTestLogFatalFunc )fatal_handler, NULL );
auto hdlr = g_log_set_handler (log_domain, loglevel,
(GLogFunc)test_checked_handler, check);
qof_instance_decrease_editlevel( fixture->inst );
g_assert_cmpint( qof_instance_get_editlevel( fixture->inst ), == , -1 );
result = qof_commit_edit( fixture->inst );
g_assert_cmpint( qof_instance_get_editlevel( fixture->inst ), == , 0 );
g_assert_cmpstr( error_message, == , "[qof_commit_edit()] unbalanced call - resetting (was -2)" );
g_free( error_message );
g_log_remove_handler (log_domain, hdlr);
test_error_struct_free(check);
}
/* backend commit test start */
static void
test_instance_commit_edit_part2( Fixture *fixture, gconstpointer pData )
{
QofBook *book;
gboolean result;
/* setup */
auto be = new QofInstMockBackend;
g_assert( be );
book = qof_book_new();
g_assert( book );
g_assert( QOF_IS_BOOK( book ) );
qof_book_set_backend( book, be );
/* init */
result = FALSE;
commit_test.m_commit_called = false;
commit_test.m_commit_with_err_called = false;
commit_test.m_on_error_called = false;
commit_test.m_on_free_called = false;
commit_test.m_on_done_called = false;
commit_test.m_inst = fixture->inst;
commit_test.m_be = be;
qof_instance_set_dirty_flag( fixture->inst, TRUE );
g_test_message( "Test when instance's backend not set, callbacks not set" );
g_assert( qof_instance_get_infant( fixture->inst ) );
g_assert( !qof_instance_get_destroying( fixture->inst ) );
result = qof_commit_edit_part2( fixture->inst, NULL, NULL, NULL );
g_assert( result );
g_assert( qof_instance_get_dirty_flag( fixture->inst ) );
g_assert( qof_instance_get_infant( fixture->inst ) );
g_assert( !commit_test.m_commit_called );
g_assert( !commit_test.m_commit_with_err_called );
g_assert( !commit_test.m_on_error_called );
g_assert( !commit_test.m_on_free_called );
g_assert( !commit_test.m_on_done_called );
g_test_message( "Test when instance's backend not set, do_free is false" );
qof_instance_set_destroying( fixture->inst, TRUE );
result = qof_commit_edit_part2( fixture->inst, on_error, on_done, on_free );
g_assert( result );
g_assert( qof_instance_get_dirty_flag( fixture->inst ) );
g_assert( qof_instance_get_infant( fixture->inst ) );
g_assert( !commit_test.m_commit_called );
g_assert( !commit_test.m_commit_with_err_called );
g_assert( !commit_test.m_on_error_called );
g_assert( commit_test.m_on_free_called );
g_assert( !commit_test.m_on_done_called );
g_test_message( "Test when instance's backend not set, do_free is false" );
qof_instance_set_destroying( fixture->inst, FALSE );
commit_test.m_on_free_called = false;
result = qof_commit_edit_part2( fixture->inst, on_error, on_done, on_free );
g_assert( result );
g_assert( qof_instance_get_dirty_flag( fixture->inst ) );
g_assert( qof_instance_get_infant( fixture->inst ) );
g_assert( !commit_test.m_commit_called );
g_assert( !commit_test.m_commit_with_err_called );
g_assert( !commit_test.m_on_error_called );
g_assert( !commit_test.m_on_free_called );
g_assert( commit_test.m_on_done_called );
g_test_message( "Test when instance's backend is set, all cb set, no error produced" );
qof_instance_set_book( fixture->inst, book );
qof_instance_set_destroying( fixture->inst, FALSE );
commit_test.m_on_done_called = false;
result = qof_commit_edit_part2( fixture->inst, on_error, on_done, on_free );
g_assert( result );
g_assert( !qof_instance_get_dirty_flag( fixture->inst ) );
g_assert( !qof_instance_get_infant( fixture->inst ) );
g_assert( commit_test.m_commit_called );
g_assert( !commit_test.m_commit_with_err_called );
g_assert( !commit_test.m_on_error_called );
g_assert( !commit_test.m_on_free_called );
g_assert( commit_test.m_on_done_called );
g_test_message( "Test when instance's backend is set, all cb set, error produced" );
commit_test.m_commit_called = false;
commit_test.m_on_done_called = false;
be->inject_error(ERR_BACKEND_NO_HANDLER);
qof_instance_set_dirty_flag( fixture->inst, TRUE );
qof_instance_set_destroying( fixture->inst, TRUE );
result = qof_commit_edit_part2( fixture->inst, on_error, on_done, on_free );
g_assert( !result );
g_assert( !qof_instance_get_dirty_flag( fixture->inst ) );
g_assert( !qof_instance_get_destroying( fixture->inst ) );
g_assert( commit_test.m_commit_called );
g_assert( commit_test.m_on_error_called );
g_assert( !commit_test.m_on_free_called );
g_assert( !commit_test.m_on_done_called );
/* clean up */
qof_book_set_backend( book, NULL );
qof_book_destroy( book );
delete be;
}
/* backend commit test end */
/* object reference tests */
static struct
{
gpointer inst;
gpointer ref;
gboolean refers_to_object_called;
} refers_test_struct;
static gboolean
mock_refers_to_object( const QofInstance* inst, const QofInstance* ref )
{
g_assert( inst );
g_assert( ref );
g_assert( refers_test_struct.inst == inst );
g_assert( refers_test_struct.ref == ref );
refers_test_struct.refers_to_object_called = TRUE;
return TRUE;
}
static void
test_instance_refers_to_object( Fixture *fixture, gconstpointer pData )
{
QofInstance * ref;
ref = static_cast<QofInstance*>(g_object_new( QOF_TYPE_INSTANCE, NULL ));
g_assert( fixture->inst );
g_assert( ref );
g_assert( QOF_INSTANCE_GET_CLASS( fixture->inst )->refers_to_object == NULL );
refers_test_struct.refers_to_object_called = FALSE;
refers_test_struct.inst = fixture->inst;
refers_test_struct.ref = ref;
g_test_message( "Test when refers to object not set" );
g_assert( !qof_instance_refers_to_object( fixture->inst, ref ) );
g_assert( !refers_test_struct.refers_to_object_called );
g_test_message( "Test when refers to object set" );
QOF_INSTANCE_GET_CLASS( fixture->inst )->refers_to_object = mock_refers_to_object;
g_assert( qof_instance_refers_to_object( fixture->inst, ref ) );
g_assert( refers_test_struct.refers_to_object_called );
g_object_unref( ref );
}
static struct
{
GList *list;
gpointer ref;
guint call_count;
} refers_test_struct_from_col;
static gboolean
mock_refers_to_object_from_col( const QofInstance* inst, const QofInstance* ref )
{
g_assert( inst );
g_assert( ref );
g_assert( g_list_find( refers_test_struct_from_col.list, inst ) );
g_assert( refers_test_struct_from_col.ref == ref );
refers_test_struct_from_col.call_count++;
refers_test_struct.refers_to_object_called = TRUE;
return TRUE;
}
static void
test_instance_get_referring_object_list_from_collection( void )
{
QofIdType type = "test type";
QofBook *book;
GList *inst_list = NULL;
GList *result = NULL;
QofCollection *coll;
QofInstance *ref;
/* randomly init number of entities >=0 and < 10 */
gint32 list_length = g_test_rand_int_range( 0, 10 );
int i;
/* setup book and ref instance */
book = qof_book_new();
g_assert( book );
g_assert( QOF_IS_BOOK( book ) );
ref = static_cast<QofInstance*>(g_object_new( QOF_TYPE_INSTANCE, NULL ));
g_assert( ref );
g_assert( QOF_IS_INSTANCE( ref ) );
QOF_INSTANCE_GET_CLASS( ref )->refers_to_object = NULL;
refers_test_struct_from_col.call_count = 0;
/* init list of entities of one type,
* put them into book collection and
* save in the list
*/
for (i = 0; i < list_length; i++ )
{
auto inst = static_cast<QofInstance*>(g_object_new( QOF_TYPE_INSTANCE, NULL ));
g_assert( inst );
qof_instance_init_data( inst, type, book );
inst_list = g_list_append ( inst_list, inst );
g_assert_cmpint( g_list_length( inst_list ), == , (i + 1) );
}
g_assert_cmpint( list_length, == , g_list_length( inst_list ) );
g_test_message( "Test when refers to object not set" );
coll = qof_book_get_collection( book, type );
g_assert( coll );
result = qof_instance_get_referring_object_list_from_collection( coll, ref );
g_assert( !result );
g_assert_cmpint( refers_test_struct_from_col.call_count, == , 0 );
g_test_message( "Test when refers to object is set" );
QOF_INSTANCE_GET_CLASS( ref )->refers_to_object = mock_refers_to_object_from_col;
refers_test_struct_from_col.list = inst_list;
refers_test_struct_from_col.ref = ref;
result = qof_instance_get_referring_object_list_from_collection( coll, ref );
if ( list_length == 0 )
g_assert( !result );
else
g_assert( result );
g_assert_cmpint( g_list_length( inst_list ), == , g_list_length( result ) );
g_assert_cmpint( g_list_length( inst_list ), == , refers_test_struct_from_col.call_count );
/* clean up list and destroy book */
g_list_foreach( inst_list, (GFunc) g_object_unref, NULL );
g_list_free( inst_list );
g_list_free( result );
qof_book_destroy( book );
g_object_unref( ref );
}
static struct
{
gpointer inst;
gpointer ref;
gboolean get_typed_referring_object_list_called;
} get_typed_referring_object_list_struct;
static GList*
mock_get_typed_referring_object_list( const QofInstance* inst, const QofInstance* ref )
{
GList* result = NULL;
g_assert( inst );
g_assert( ref );
g_assert( get_typed_referring_object_list_struct.inst == inst );
g_assert( get_typed_referring_object_list_struct.ref == ref );
get_typed_referring_object_list_struct.get_typed_referring_object_list_called = TRUE;
return g_list_append( result, (gpointer) inst );
}
static void
test_instance_get_typed_referring_object_list( void )
{
QofInstance *inst;
QofInstance *ref;
QofBook *book;
GList* result = NULL;
/* setup */
inst = static_cast<QofInstance*>(g_object_new( QOF_TYPE_INSTANCE, NULL ));
ref = static_cast<QofInstance*>(g_object_new( QOF_TYPE_INSTANCE, NULL ));
book = qof_book_new();
g_assert( inst );
g_assert( ref );
g_assert( book );
QOF_INSTANCE_GET_CLASS( inst )->refers_to_object = NULL;
QOF_INSTANCE_GET_CLASS( inst )->get_typed_referring_object_list = NULL;
qof_instance_init_data( inst, "test type", book );
get_typed_referring_object_list_struct.get_typed_referring_object_list_called = FALSE;
/*
* cases when refers to object is set are not tested in current function
* as they are checked in the previous tests
*/
g_test_message( "Test when get typed referring object list is not set" );
result = qof_instance_get_typed_referring_object_list( inst, ref );
g_assert( !result );
g_assert( !get_typed_referring_object_list_struct.get_typed_referring_object_list_called );
g_list_free( result );
g_test_message( "Test when get typed referring object list is set" );
QOF_INSTANCE_GET_CLASS( inst )->get_typed_referring_object_list = mock_get_typed_referring_object_list;
get_typed_referring_object_list_struct.inst = inst;
get_typed_referring_object_list_struct.ref = ref;
result = qof_instance_get_typed_referring_object_list( inst, ref );
g_assert( result );
g_assert_cmpint( g_list_length( result ), == , 1 );
g_assert( get_typed_referring_object_list_struct.get_typed_referring_object_list_called );
g_list_free( result );
/* clean */
g_object_unref( inst );
g_object_unref( ref );
qof_book_destroy( book );
}
static struct
{
guint refers_to_object_call_count;
guint get_typed_referring_object_list_count;
} get_referring_object_list_struct;
static gboolean
mock_simple_refers_to_object( const QofInstance* inst, const QofInstance* ref )
{
g_assert( inst );
g_assert( ref );
if ( inst->e_type == ref->e_type )
{
get_referring_object_list_struct.refers_to_object_call_count++;
return TRUE;
}
return FALSE;
}
static GList*
mock_simple_get_typed_referring_object_list(const QofInstance* inst, const QofInstance* ref)
{
g_assert( inst );
g_assert( ref );
get_referring_object_list_struct.get_typed_referring_object_list_count++;
return qof_instance_get_referring_object_list_from_collection(qof_instance_get_collection(inst), ref);
}
static void
test_instance_get_referring_object_list( void )
{
/* walk through the book's each collection's each instance */
QofInstance *ref1;
QofInstance *ref2;
QofBook *book;
QofIdType type1 = "type1";
QofIdType type2 = "type2";
gint32 col1_length = g_test_rand_int_range( 0, 10 );
gint32 col2_length = g_test_rand_int_range( 0, 10 );
GList* inst_list1 = NULL;
GList* inst_list2 = NULL;
GList* result = NULL;
int i, j;
/* setup */
book = qof_book_new();
g_assert( book );
g_assert( QOF_IS_BOOK( book ) );
ref1 = static_cast<QofInstance*>(g_object_new( QOF_TYPE_INSTANCE, NULL ));
g_assert( ref1 );
ref2 = static_cast<QofInstance*>(g_object_new( QOF_TYPE_INSTANCE, NULL ));
g_assert( ref2 );
qof_instance_init_data( ref1, type1, book );
qof_instance_init_data( ref2, type2, book );
QOF_INSTANCE_GET_CLASS( ref1 )->refers_to_object = NULL;
QOF_INSTANCE_GET_CLASS( ref1 )->get_typed_referring_object_list = NULL;
g_assert_cmpint( qof_collection_count( qof_book_get_collection( book, type1 ) ), == , 1 );
g_assert_cmpint( qof_collection_count( qof_book_get_collection( book, type2 ) ), == , 1 );
get_referring_object_list_struct.refers_to_object_call_count = 0;
get_referring_object_list_struct.get_typed_referring_object_list_count = 0;
/*
* fill two collections with different types
* and random number of elements
*/
for (i = 0; i < col1_length; i++ )
{
auto inst = static_cast<QofInstance*>(g_object_new( QOF_TYPE_INSTANCE, NULL ));
g_assert( inst );
qof_instance_init_data( inst, type1, book );
inst_list1 = g_list_append ( inst_list1, inst );
g_assert_cmpint( g_list_length( inst_list1 ), == , (i + 1) );
}
g_assert_cmpint( qof_collection_count( qof_book_get_collection( book, type1 ) ), == , col1_length + 1 );
g_assert_cmpint( g_list_length( inst_list1 ), == , col1_length );
for (j = 0; j < col2_length; j++ )
{
auto inst = static_cast<QofInstance*>(g_object_new( QOF_TYPE_INSTANCE, NULL ));
g_assert( inst );
qof_instance_init_data( inst, type2, book );
inst_list2 = g_list_append ( inst_list2, inst );
g_assert_cmpint( g_list_length( inst_list2 ), == , (j + 1) );
}
g_assert_cmpint( qof_collection_count( qof_book_get_collection( book, type2 ) ), == , col2_length + 1 );
g_assert_cmpint( g_list_length( inst_list2 ), == , col2_length );
g_test_message( "Test object list returned for ref1 instance by default" );
result = qof_instance_get_referring_object_list( ref1 );
g_assert( !result );
g_assert_cmpint( get_referring_object_list_struct.refers_to_object_call_count, == , 0 );
g_test_message( "Test object list returned for ref2 instance by default" );
result = qof_instance_get_referring_object_list( ref2 );
g_assert( !result );
g_assert_cmpint( get_referring_object_list_struct.refers_to_object_call_count, == , 0 );
/*
* refers to object is made simple as it is tested enough
* it checks if instance types are equal
* that is for ref1 we should get all elements from collection with type1
* for ref2 we should get all elements from collection with type2
*/
g_test_message( "Test object list returned for ref1 instance when refers_to_object is set" );
QOF_INSTANCE_GET_CLASS( ref1 )->refers_to_object = mock_simple_refers_to_object;
result = qof_instance_get_referring_object_list( ref1 );
g_assert( result );
g_assert_cmpint( g_list_length( result ), == , col1_length + 1 );
g_assert_cmpint( get_referring_object_list_struct.refers_to_object_call_count, == , col1_length + 1 );
g_list_free( result );
g_test_message( "Test object list returned for ref2 instance when refers_to_object is set" );
get_referring_object_list_struct.refers_to_object_call_count = 0;
result = qof_instance_get_referring_object_list( ref2 );
g_assert( result );
g_assert_cmpint( g_list_length( result ), == , col2_length + 1 );
g_assert_cmpint( get_referring_object_list_struct.refers_to_object_call_count, == , col2_length + 1 );
g_list_free( result );
g_test_message( "Test object list returned for ref1 instance when refers_to_object is set and get typed set" );
QOF_INSTANCE_GET_CLASS( ref1 )->get_typed_referring_object_list = mock_simple_get_typed_referring_object_list;
get_referring_object_list_struct.refers_to_object_call_count = 0;
get_referring_object_list_struct.get_typed_referring_object_list_count = 0;
result = qof_instance_get_referring_object_list( ref1 );
g_assert( result );
g_assert_cmpint( g_list_length( result ), == , col1_length + 1 );
g_assert_cmpint( get_referring_object_list_struct.refers_to_object_call_count, == , col1_length + 1 );
g_assert_cmpint( get_referring_object_list_struct.get_typed_referring_object_list_count, == , 2 );
g_list_free( result );
g_test_message( "Test object list returned for ref2 instance when refers_to_object is set and get typed set" );
get_referring_object_list_struct.refers_to_object_call_count = 0;
get_referring_object_list_struct.get_typed_referring_object_list_count = 0;
result = qof_instance_get_referring_object_list( ref2 );
g_assert( result );
g_assert_cmpint( g_list_length( result ), == , col2_length + 1 );
g_assert_cmpint( get_referring_object_list_struct.refers_to_object_call_count, == , col2_length + 1 );
g_assert_cmpint( get_referring_object_list_struct.get_typed_referring_object_list_count, == , 2 );
g_list_free( result );
/* clean */
g_object_unref( ref1 );
g_object_unref( ref2 );
g_list_foreach( inst_list1, (GFunc) g_object_unref, NULL );
g_list_foreach( inst_list2, (GFunc) g_object_unref, NULL );
g_list_free( inst_list1 );
g_list_free( inst_list2 );
qof_book_destroy( book );
}
extern "C" void
test_suite_qofinstance ( void )
{
GNC_TEST_ADD( suitename, "set get book", Fixture, NULL, setup, test_instance_set_get_book, teardown );
GNC_TEST_ADD( suitename, "set get guid", Fixture, NULL, setup, test_instance_set_get_guid, teardown );
GNC_TEST_ADD_FUNC( suitename, "instance new and destroy", test_instance_new_destroy );
GNC_TEST_ADD_FUNC( suitename, "init data", test_instance_init_data );
GNC_TEST_ADD( suitename, "get set slots", Fixture, NULL, setup, test_instance_get_set_slots, teardown );
GNC_TEST_ADD_FUNC( suitename, "version compare", test_instance_version_cmp );
GNC_TEST_ADD( suitename, "get set dirty", Fixture, NULL, setup, test_instance_get_set_dirty, teardown );
GNC_TEST_ADD( suitename, "display name", Fixture, NULL, setup, test_instance_display_name, teardown );
GNC_TEST_ADD( suitename, "begin edit", Fixture, NULL, setup, test_instance_begin_edit, teardown );
GNC_TEST_ADD( suitename, "commit edit", Fixture, NULL, setup, test_instance_commit_edit, teardown );
GNC_TEST_ADD( suitename, "commit edit part 2", Fixture, NULL, setup, test_instance_commit_edit_part2, teardown );
GNC_TEST_ADD( suitename, "instance refers to object", Fixture, NULL, setup, test_instance_refers_to_object, teardown );
GNC_TEST_ADD_FUNC( suitename, "instance get referring object list from collection", test_instance_get_referring_object_list_from_collection );
GNC_TEST_ADD_FUNC( suitename, "instance get typed referring object list", test_instance_get_typed_referring_object_list);
GNC_TEST_ADD_FUNC( suitename, "instance get referring object list", test_instance_get_referring_object_list );
}