TEST_F(ImapPlainTest, AddAccount) { // prevent the embedded beginedit/commitedit from doing anything qof_instance_increase_editlevel(QOF_INSTANCE(t_bank_account)); qof_instance_mark_clean(QOF_INSTANCE(t_bank_account)); gnc_account_imap_add_account(t_imap, "foo", "bar", t_expense_account1); gnc_account_imap_add_account(t_imap, "baz", "waldo", t_expense_account2); gnc_account_imap_add_account(t_imap, NULL, "pepper", t_expense_account1); gnc_account_imap_add_account(t_imap, NULL, "salt", t_expense_account2); EXPECT_EQ(1, qof_instance_get_editlevel(QOF_INSTANCE(t_bank_account))); EXPECT_TRUE(qof_instance_get_dirty_flag(QOF_INSTANCE(t_bank_account))); qof_instance_mark_clean(QOF_INSTANCE(t_bank_account)); gnc_account_imap_add_account(t_imap, NULL, NULL, t_expense_account2); EXPECT_FALSE(qof_instance_get_dirty_flag(QOF_INSTANCE(t_bank_account))); gnc_account_imap_add_account(t_imap, "pork", "sausage", NULL); EXPECT_FALSE(qof_instance_get_dirty_flag(QOF_INSTANCE(t_bank_account))); qof_instance_reset_editlevel(QOF_INSTANCE(t_bank_account)); auto root = qof_instance_get_slots(QOF_INSTANCE(t_bank_account)); auto value = root->get_slot({IMAP_FRAME, "foo", "bar"}); auto check_account = [this](KvpValue* v) { return xaccAccountLookup(v->get<GncGUID*>(), this->t_imap->book); }; EXPECT_EQ(t_expense_account1, check_account(value)); value = root->get_slot({IMAP_FRAME, "baz", "waldo"}); EXPECT_EQ(t_expense_account2, check_account(value)); value = root->get_slot({IMAP_FRAME, "pepper"}); EXPECT_EQ(t_expense_account1, check_account(value)); value = root->get_slot({IMAP_FRAME, "salt"}); EXPECT_EQ(t_expense_account2, check_account(value)); value = root->get_slot({IMAP_FRAME, "pork", "sausage"}); EXPECT_EQ(nullptr, value); }
static GncBillTerm* load_single_billterm (GncSqlBackend* sql_be, GncSqlRow& row, BillTermParentGuidVec& l_billterms_needing_parents) { g_return_val_if_fail (sql_be != NULL, NULL); auto guid = gnc_sql_load_guid (sql_be, row); auto pBillTerm = gncBillTermLookup (sql_be->book(), guid); if (pBillTerm == nullptr) { pBillTerm = gncBillTermCreate (sql_be->book()); } gnc_sql_load_object (sql_be, row, GNC_ID_BILLTERM, pBillTerm, col_table); /* If the billterm doesn't have a parent, it might be because it hasn't been loaded yet. If so, add this billterm to the list of billterms with no parent, along with the parent GncGUID so that after they are all loaded, the parents can be fixed up. */ if (gncBillTermGetParent (pBillTerm) == NULL) { BillTermParentGuid s; s.billterm = pBillTerm; s.have_guid = false; gnc_sql_load_object (sql_be, row, GNC_ID_TAXTABLE, &s, billterm_parent_col_table); if (s.have_guid) l_billterms_needing_parents.push_back(new BillTermParentGuid(s)); } qof_instance_mark_clean (QOF_INSTANCE (pBillTerm)); return pBillTerm; }
TEST_F(ImapBayesTest, AddAccountBayes) { // prevent the embedded beginedit/commitedit from doing anything qof_instance_increase_editlevel(QOF_INSTANCE(t_bank_account)); qof_instance_mark_clean(QOF_INSTANCE(t_bank_account)); gnc_account_imap_add_account_bayes(t_imap, t_list1, t_expense_account1); gnc_account_imap_add_account_bayes(t_imap, t_list2, t_expense_account2); gnc_account_imap_add_account_bayes(t_imap, t_list3, t_expense_account1); gnc_account_imap_add_account_bayes(t_imap, t_list4, t_expense_account2); EXPECT_EQ(1, qof_instance_get_editlevel(QOF_INSTANCE(t_bank_account))); EXPECT_TRUE(qof_instance_get_dirty_flag(QOF_INSTANCE(t_bank_account))); qof_instance_mark_clean(QOF_INSTANCE(t_bank_account)); gnc_account_imap_add_account_bayes(t_imap, t_list5, NULL); EXPECT_FALSE(qof_instance_get_dirty_flag(QOF_INSTANCE(t_bank_account))); qof_instance_reset_editlevel(QOF_INSTANCE(t_bank_account)); auto root = qof_instance_get_slots(QOF_INSTANCE(t_bank_account)); auto acct1_guid = guid_to_string (xaccAccountGetGUID(t_expense_account1)); auto acct2_guid = guid_to_string (xaccAccountGetGUID(t_expense_account2)); auto value = root->get_slot({IMAP_FRAME_BAYES, "foo", "bar"}); auto check_account = [this](KvpValue* v) { return (v->get<const char*>(), this->t_imap->book); }; value = root->get_slot({IMAP_FRAME_BAYES, foo, acct1_guid}); EXPECT_EQ(1, value->get<int64_t>()); value = root->get_slot({IMAP_FRAME_BAYES, bar, acct1_guid}); EXPECT_EQ(1, value->get<int64_t>()); value = root->get_slot({IMAP_FRAME_BAYES, baz, acct2_guid}); EXPECT_EQ(1, value->get<int64_t>()); value = root->get_slot({IMAP_FRAME_BAYES, waldo, acct2_guid}); EXPECT_EQ(1, value->get<int64_t>()); value = root->get_slot({IMAP_FRAME_BAYES, pepper, acct1_guid}); EXPECT_EQ(1, value->get<int64_t>()); value = root->get_slot({IMAP_FRAME_BAYES, salt, acct2_guid}); EXPECT_EQ(1, value->get<int64_t>()); value = root->get_slot({IMAP_FRAME_BAYES, baz, acct1_guid}); EXPECT_EQ(nullptr, value); qof_instance_increase_editlevel(QOF_INSTANCE(t_bank_account)); gnc_account_imap_add_account_bayes(t_imap, t_list2, t_expense_account2); qof_instance_mark_clean(QOF_INSTANCE(t_bank_account)); qof_instance_reset_editlevel(QOF_INSTANCE(t_bank_account)); value = root->get_slot({IMAP_FRAME_BAYES, baz, acct2_guid}); EXPECT_EQ(2, value->get<int64_t>()); }
TEST_F(ImapPlainTest, DeleteAccount) { Path path1 {IMAP_FRAME, "foo", "waldo"}; Path path2 {IMAP_FRAME, "foo"}; Path path3 {IMAP_FRAME}; // prevent the embedded beginedit/commitedit from doing anything qof_instance_increase_editlevel(QOF_INSTANCE(t_bank_account)); qof_instance_mark_clean(QOF_INSTANCE(t_bank_account)); gnc_account_imap_add_account(t_imap, "foo", "bar", t_expense_account1); gnc_account_imap_add_account(t_imap, "foo", "waldo", t_expense_account2); gnc_account_imap_add_account(t_imap, NULL, "pepper", t_expense_account1); EXPECT_EQ(1, qof_instance_get_editlevel(QOF_INSTANCE(t_bank_account))); EXPECT_TRUE(qof_instance_get_dirty_flag(QOF_INSTANCE(t_bank_account))); qof_instance_mark_clean(QOF_INSTANCE(t_bank_account)); gnc_account_imap_delete_account(t_imap, NULL, NULL); EXPECT_FALSE(qof_instance_get_dirty_flag(QOF_INSTANCE(t_bank_account))); gnc_account_imap_delete_account(t_imap, "foo", "waldo"); EXPECT_TRUE(qof_instance_get_dirty_flag(QOF_INSTANCE(t_bank_account))); qof_instance_mark_clean(QOF_INSTANCE(t_bank_account)); EXPECT_EQ(t_expense_account1, gnc_account_imap_find_account(t_imap, "foo", "bar")); EXPECT_EQ(nullptr, gnc_account_imap_find_account(t_imap, "foo", "waldo")); auto root = qof_instance_get_slots(QOF_INSTANCE(t_bank_account)); EXPECT_EQ(nullptr, root->get_slot(path1)); gnc_account_imap_delete_account(t_imap, "foo", "bar"); EXPECT_TRUE(qof_instance_get_dirty_flag(QOF_INSTANCE(t_bank_account))); qof_instance_mark_clean(QOF_INSTANCE(t_bank_account)); EXPECT_EQ(nullptr, root->get_slot(path2)); gnc_account_imap_delete_account(t_imap, NULL, "pepper"); EXPECT_TRUE(qof_instance_get_dirty_flag(QOF_INSTANCE(t_bank_account))); qof_instance_mark_clean(QOF_INSTANCE(t_bank_account)); EXPECT_EQ(nullptr, root->get_slot(path3)); qof_instance_reset_editlevel(QOF_INSTANCE(t_bank_account)); }
static GncBillTerm* load_single_billterm (GncSqlBackend* be, GncSqlRow* row, GList** l_billterms_needing_parents) { const GncGUID* guid; GncBillTerm* pBillTerm; g_return_val_if_fail (be != NULL, NULL); g_return_val_if_fail (row != NULL, NULL); guid = gnc_sql_load_guid (be, row); pBillTerm = gncBillTermLookup (be->book, guid); if (pBillTerm == NULL) { pBillTerm = gncBillTermCreate (be->book); } gnc_sql_load_object (be, row, GNC_ID_BILLTERM, pBillTerm, col_table); /* If the billterm doesn't have a parent, it might be because it hasn't been loaded yet. If so, add this billterm to the list of billterms with no parent, along with the parent GncGUID so that after they are all loaded, the parents can be fixed up. */ if (gncBillTermGetParent (pBillTerm) == NULL) { billterm_parent_guid_struct* s = static_cast<decltype (s)> ( g_malloc (sizeof (billterm_parent_guid_struct))); g_assert (s != NULL); s->billterm = pBillTerm; s->have_guid = FALSE; gnc_sql_load_object (be, row, GNC_ID_TAXTABLE, s, billterm_parent_col_table); if (s->have_guid) { *l_billterms_needing_parents = g_list_prepend (*l_billterms_needing_parents, s); } else { g_free (s); } } qof_instance_mark_clean (QOF_INSTANCE (pBillTerm)); return pBillTerm; }
static void load_single_taxtable( GncSqlBackend* be, GncSqlRow* row, GList** l_tt_needing_parents ) { const GncGUID* guid; GncTaxTable* tt; g_return_if_fail( be != NULL ); g_return_if_fail( row != NULL ); guid = gnc_sql_load_guid( be, row ); tt = gncTaxTableLookup( be->book, guid ); if ( tt == NULL ) { tt = gncTaxTableCreate( be->book ); } gnc_sql_load_object( be, row, GNC_ID_TAXTABLE, tt, tt_col_table ); gnc_sql_slots_load( be, QOF_INSTANCE(tt) ); load_taxtable_entries( be, tt ); /* If the tax table doesn't have a parent, it might be because it hasn't been loaded yet. If so, add this tax table to the list of tax tables with no parent, along with the parent GncGUID so that after they are all loaded, the parents can be fixed up. */ if ( gncTaxTableGetParent( tt ) == NULL ) { taxtable_parent_guid_struct* s = static_cast<decltype(s)>( g_malloc(sizeof(taxtable_parent_guid_struct))); g_assert( s != NULL ); s->tt = tt; s->have_guid = FALSE; gnc_sql_load_object( be, row, GNC_ID_TAXTABLE, s, tt_parent_col_table ); if ( s->have_guid ) { *l_tt_needing_parents = g_list_prepend( *l_tt_needing_parents, s ); } else { g_free( s ); } } qof_instance_mark_clean( QOF_INSTANCE(tt) ); }
static GncInvoice* load_single_invoice (GncSqlBackend* be, GncSqlRow& row) { const GncGUID* guid; GncInvoice* pInvoice; g_return_val_if_fail (be != NULL, NULL); guid = gnc_sql_load_guid (be, row); pInvoice = gncInvoiceLookup (be->book(), guid); if (pInvoice == NULL) { pInvoice = gncInvoiceCreate (be->book()); } gnc_sql_load_object (be, row, GNC_ID_INVOICE, pInvoice, col_table); qof_instance_mark_clean (QOF_INSTANCE (pInvoice)); return pInvoice; }
static GncVendor* load_single_vendor (GncSqlBackend* sql_be, GncSqlRow& row) { const GncGUID* guid; GncVendor* pVendor; g_return_val_if_fail (sql_be != NULL, NULL); guid = gnc_sql_load_guid (sql_be, row); pVendor = gncVendorLookup (sql_be->book(), guid); if (pVendor == NULL) { pVendor = gncVendorCreate (sql_be->book()); } gnc_sql_load_object (sql_be, row, GNC_ID_VENDOR, pVendor, col_table); qof_instance_mark_clean (QOF_INSTANCE (pVendor)); return pVendor; }
static GncEmployee* load_single_employee (GncSqlBackend* sql_be, GncSqlRow& row) { const GncGUID* guid; GncEmployee* pEmployee; g_return_val_if_fail (sql_be != NULL, NULL); guid = gnc_sql_load_guid (sql_be, row); pEmployee = gncEmployeeLookup (sql_be->book(), guid); if (pEmployee == NULL) { pEmployee = gncEmployeeCreate (sql_be->book()); } gnc_sql_load_object (sql_be, row, GNC_ID_EMPLOYEE, pEmployee, col_table); qof_instance_mark_clean (QOF_INSTANCE (pEmployee)); return pEmployee; }
static GncOrder* load_single_order (GncSqlBackend* be, GncSqlRow& row) { const GncGUID* guid; GncOrder* pOrder; g_return_val_if_fail (be != NULL, NULL); guid = gnc_sql_load_guid (be, row); pOrder = gncOrderLookup (be->book(), guid); if (pOrder == NULL) { pOrder = gncOrderCreate (be->book()); } gnc_sql_load_object (be, row, GNC_ID_ORDER, pOrder, col_table); qof_instance_mark_clean (QOF_INSTANCE (pOrder)); return pOrder; }
static GncJob* load_single_job( GncSqlBackend* be, GncSqlRow* row ) { const GncGUID* guid; GncJob* pJob; g_return_val_if_fail( be != NULL, NULL ); g_return_val_if_fail( row != NULL, NULL ); guid = gnc_sql_load_guid( be, row ); pJob = gncJobLookup( be->book, guid ); if ( pJob == NULL ) { pJob = gncJobCreate( be->book ); } gnc_sql_load_object( be, row, GNC_ID_JOB, pJob, col_table ); qof_instance_mark_clean( QOF_INSTANCE(pJob) ); return pJob; }
static GncCustomer* load_single_customer( GncSqlBackend* be, GncSqlRow* row ) { const GncGUID* guid; GncCustomer* pCustomer; g_return_val_if_fail( be != NULL, NULL ); g_return_val_if_fail( row != NULL, NULL ); guid = gnc_sql_load_guid( be, row ); pCustomer = gncCustomerLookup( be->book, guid ); if ( pCustomer == NULL ) { pCustomer = gncCustomerCreate( be->book ); } gnc_sql_load_object( be, row, GNC_ID_CUSTOMER, pCustomer, col_table ); qof_instance_mark_clean( QOF_INSTANCE(pCustomer) ); return pCustomer; }
/* ================================================================= */ static void load_single_book (GncSqlBackend* sql_be, GncSqlRow& row) { QofBook* pBook; g_return_if_fail (sql_be != NULL); gnc_sql_load_guid (sql_be, row); pBook = sql_be->book(); if (pBook == NULL) { pBook = qof_book_new (); } qof_book_begin_edit (pBook); gnc_sql_load_object (sql_be, row, GNC_ID_BOOK, pBook, col_table); gnc_sql_slots_load (sql_be, QOF_INSTANCE (pBook)); qof_book_commit_edit (pBook); qof_instance_mark_clean (QOF_INSTANCE (pBook)); }
static void load_single_taxtable (GncSqlBackend* sql_be, GncSqlRow& row, TaxTblParentGuidVec& l_tt_needing_parents) { const GncGUID* guid; GncTaxTable* tt; g_return_if_fail (sql_be != NULL); guid = gnc_sql_load_guid (sql_be, row); tt = gncTaxTableLookup (sql_be->book(), guid); if (tt == nullptr) { tt = gncTaxTableCreate (sql_be->book()); } gnc_sql_load_object (sql_be, row, GNC_ID_TAXTABLE, tt, tt_col_table); gnc_sql_slots_load (sql_be, QOF_INSTANCE (tt)); load_taxtable_entries (sql_be, tt); /* If the tax table doesn't have a parent, it might be because it hasn't been loaded yet. if so, add this tax table to the list of tax tables with no parent, along with the parent GncGUID so that after they are all loaded, the parents can be fixed up. */ if (gncTaxTableGetParent (tt) == NULL) { TaxTblParentGuid s; s.tt = tt; s.have_guid = false; gnc_sql_load_object (sql_be, row, GNC_ID_TAXTABLE, &s, tt_parent_col_table); if (s.have_guid) l_tt_needing_parents.push_back(new TaxTblParentGuid(s)); } qof_instance_mark_clean (QOF_INSTANCE (tt)); }
static void mark_sx_clean(gpointer data, gpointer user_data) { SchedXaction *sx = (SchedXaction *) data; qof_instance_mark_clean (QOF_INSTANCE(sx)); }
/* Commit_edit handler - find the correct backend handler for this object * type and call its commit handler */ void GncSqlBackend::commit_edit (QofInstance* inst) { sql_backend be_data; gboolean is_dirty; gboolean is_destroying; gboolean is_infant; g_return_if_fail (inst != NULL); if (qof_book_is_readonly(m_book)) { qof_backend_set_error (&qof_be, ERR_BACKEND_READONLY); (void)m_conn->rollback_transaction (); return; } /* During initial load where objects are being created, don't commit anything, but do mark the object as clean. */ if (m_loading) { qof_instance_mark_clean (inst); return; } // The engine has a PriceDB object but it isn't in the database if (strcmp (inst->e_type, "PriceDB") == 0) { qof_instance_mark_clean (inst); qof_book_mark_session_saved (m_book); return; } ENTER (" "); is_dirty = qof_instance_get_dirty_flag (inst); is_destroying = qof_instance_get_destroying (inst); is_infant = qof_instance_get_infant (inst); DEBUG ("%s dirty = %d, do_free = %d, infant = %d\n", (inst->e_type ? inst->e_type : "(null)"), is_dirty, is_destroying, is_infant); if (!is_dirty && !is_destroying) { LEAVE ("!dirty OR !destroying"); return; } if (!m_conn->begin_transaction ()) { PERR ("begin_transaction failed\n"); LEAVE ("Rolled back - database transaction begin error"); return; } bool is_ok = true; auto obe = m_backend_registry.get_object_backend(std::string{inst->e_type}); if (obe != nullptr) is_ok = obe->commit(this, inst); else { PERR ("Unknown object type '%s'\n", inst->e_type); (void)m_conn->rollback_transaction (); // Don't let unknown items still mark the book as being dirty qof_book_mark_session_saved(m_book); qof_instance_mark_clean (inst); LEAVE ("Rolled back - unknown object type"); return; } if (!is_ok) { // Error - roll it back (void)m_conn->rollback_transaction(); // This *should* leave things marked dirty LEAVE ("Rolled back - database error"); return; } (void)m_conn->commit_transaction (); qof_book_mark_session_saved(m_book); qof_instance_mark_clean (inst); LEAVE (""); }
TEST_F(ImapBayesTest, ConvertAccountBayes) { // prevent the embedded beginedit/commitedit from doing anything qof_instance_increase_editlevel(QOF_INSTANCE(t_bank_account)); qof_instance_mark_clean(QOF_INSTANCE(t_bank_account)); gnc_account_imap_add_account_bayes(t_imap, t_list1, t_expense_account1); //Food gnc_account_imap_add_account_bayes(t_imap, t_list2, t_expense_account2); //Drink auto root = qof_instance_get_slots(QOF_INSTANCE(t_bank_account)); auto book = qof_instance_get_slots(QOF_INSTANCE(t_imap->book)); auto acct1_guid = guid_to_string (xaccAccountGetGUID(t_expense_account1)); //Food auto acct2_guid = guid_to_string (xaccAccountGetGUID(t_expense_account2)); //Drink auto acct3_guid = guid_to_string (xaccAccountGetGUID(t_asset_account2)); //Asset-Bank auto acct4_guid = guid_to_string (xaccAccountGetGUID(t_sav_account)); //Sav Bank auto val1 = new KvpValue(static_cast<int64_t>(10)); auto val2 = new KvpValue(static_cast<int64_t>(5)); auto val3 = new KvpValue(static_cast<int64_t>(2)); // Test for existing entries, all will be 1 auto value = root->get_slot({IMAP_FRAME_BAYES, foo, acct1_guid}); EXPECT_EQ(1, value->get<int64_t>()); value = root->get_slot({IMAP_FRAME_BAYES, bar, acct1_guid}); EXPECT_EQ(1, value->get<int64_t>()); value = root->get_slot({IMAP_FRAME_BAYES, baz, acct2_guid}); EXPECT_EQ(1, value->get<int64_t>()); value = root->get_slot({IMAP_FRAME_BAYES, waldo, acct2_guid}); EXPECT_EQ(1, value->get<int64_t>()); // Set up some old entries root->set_path({IMAP_FRAME_BAYES, pepper, "Asset-Bank"}, val1); root->set_path({IMAP_FRAME_BAYES, salt, "Asset-Bank#Bank"}, val1); root->set_path({IMAP_FRAME_BAYES, salt, "Asset>Bank#Bank"}, val2); root->set_path({IMAP_FRAME_BAYES, pork, "Expense#Food"}, val2); root->set_path({IMAP_FRAME_BAYES, sausage, "Expense#Drink"}, val3); root->set_path({IMAP_FRAME_BAYES, foo, "Expense#Food"}, val2); EXPECT_EQ(1, qof_instance_get_editlevel(QOF_INSTANCE(t_bank_account))); EXPECT_TRUE(qof_instance_get_dirty_flag(QOF_INSTANCE(t_bank_account))); qof_instance_mark_clean(QOF_INSTANCE(t_bank_account)); // Start Convert gnc_account_imap_convert_bayes (t_imap->book); // convert from 'Asset-Bank' to 'Asset-Bank' guid value = root->get_slot({IMAP_FRAME_BAYES, pepper, acct3_guid}); EXPECT_EQ(10, value->get<int64_t>()); // convert from 'Asset-Bank#Bank' to 'Sav Bank' guid value = root->get_slot({IMAP_FRAME_BAYES, salt, acct4_guid}); EXPECT_EQ(10, value->get<int64_t>()); // convert from 'Expense#Food' to 'Food' guid value = root->get_slot({IMAP_FRAME_BAYES, pork, acct1_guid}); EXPECT_EQ(5, value->get<int64_t>()); // convert from 'Expense#Drink' to 'Drink' guid value = root->get_slot({IMAP_FRAME_BAYES, sausage, acct2_guid}); EXPECT_EQ(2, value->get<int64_t>()); // convert from 'Expense#Food' to 'Food' guid but add to original value value = root->get_slot({IMAP_FRAME_BAYES, foo, acct1_guid}); EXPECT_EQ(6, value->get<int64_t>()); // Check for run once flag auto vals = book->get_slot("changed-bayesian-to-guid"); EXPECT_STREQ("true", vals->get<const char*>()); EXPECT_EQ(1, qof_instance_get_editlevel(QOF_INSTANCE(t_bank_account))); EXPECT_TRUE(qof_instance_get_dirty_flag(QOF_INSTANCE(t_bank_account))); }