From: <ste...@us...> - 2013-01-20 04:24:11
|
Revision: 3374 http://moneymanagerex.svn.sourceforge.net/moneymanagerex/?rev=3374&view=rev Author: stef145g Date: 2013-01-20 04:24:03 +0000 (Sun, 20 Jan 2013) Log Message: ----------- New classes with tests. Not integrated at this point. Modified Paths: -------------- trunk/mmex/build/msw-vc-2010e/tests/mmex_tests_mmex_tests.vcxproj trunk/mmex/build/msw-vc-2010e/tests/mmex_tests_mmex_tests.vcxproj.filters trunk/mmex/src/mmtransaction.cpp trunk/mmex/src/mmtransaction.h trunk/mmex/src/tests/testing_util.cpp trunk/mmex/src/tests/testing_util.h Added Paths: ----------- trunk/mmex/src/tests/new_classes_test.cpp Modified: trunk/mmex/build/msw-vc-2010e/tests/mmex_tests_mmex_tests.vcxproj =================================================================== --- trunk/mmex/build/msw-vc-2010e/tests/mmex_tests_mmex_tests.vcxproj 2013-01-20 02:10:42 UTC (rev 3373) +++ trunk/mmex/build/msw-vc-2010e/tests/mmex_tests_mmex_tests.vcxproj 2013-01-20 04:24:03 UTC (rev 3374) @@ -376,6 +376,7 @@ <ClCompile Include="..\..\..\src\optionsdialog.cpp" /> <ClCompile Include="..\..\..\src\paths.cpp" /> <ClCompile Include="..\..\..\src\payeedialog.cpp" /> + <ClCompile Include="..\..\..\src\tests\new_classes_test.cpp" /> <ClCompile Include="..\..\..\src\tests\testing_util.cpp" /> <ClCompile Include="..\..\..\src\win\platfdep.cpp" /> <ClCompile Include="..\..\..\src\recentfiles.cpp" /> Modified: trunk/mmex/build/msw-vc-2010e/tests/mmex_tests_mmex_tests.vcxproj.filters =================================================================== --- trunk/mmex/build/msw-vc-2010e/tests/mmex_tests_mmex_tests.vcxproj.filters 2013-01-20 02:10:42 UTC (rev 3373) +++ trunk/mmex/build/msw-vc-2010e/tests/mmex_tests_mmex_tests.vcxproj.filters 2013-01-20 04:24:03 UTC (rev 3374) @@ -252,6 +252,9 @@ <ClCompile Include="..\..\..\src\tests\testing_util.cpp"> <Filter>Test Files</Filter> </ClCompile> + <ClCompile Include="..\..\..\src\tests\new_classes_test.cpp"> + <Filter>Test Files</Filter> + </ClCompile> </ItemGroup> <ItemGroup> <ClInclude Include="..\..\..\src\aboutdialog.h"> Modified: trunk/mmex/src/mmtransaction.cpp =================================================================== --- trunk/mmex/src/mmtransaction.cpp 2013-01-20 02:10:42 UTC (rev 3373) +++ trunk/mmex/src/mmtransaction.cpp 2013-01-20 04:24:03 UTC (rev 3374) @@ -19,6 +19,223 @@ #include "util.h" #include "mmcoredb.h" +TSplitEntry::TSplitEntry() +: id_(-1) +, id_trans_(-1) +, id_category_(-1) +, id_subcategory_(-1) +, amount_(0.0) +{} + +int TSplitEntry::GetSplitEntryId() +{ + return id_; +} + +// Holds a single entry for a known transaction +TSplitEntry::TSplitEntry(wxSQLite3ResultSet& q1) +{ + id_ = q1.GetInt(wxT("SPLITTRANSID")); + id_trans_ = q1.GetInt(wxT("TRANSID")); + id_category_ = q1.GetInt(wxT("CATEGID")); + id_subcategory_ = q1.GetInt(wxT("SUBCATEGID")); + amount_ = q1.GetDouble(wxT("SPLITTRANSAMOUNT")); +} + +void TSplitEntry::Save(wxSQLite3Database* db, wxString db_table) +{ + wxString sql_statement; + sql_statement << wxT("INSERT INTO ") << db_table + << wxT(" (TRANSID, CATEGID, SUBCATEGID, SPLITTRANSAMOUNT )") + << wxT(" values (?, ?, ?, ?)"); + wxSQLite3Statement st = db->PrepareStatement(sql_statement); + st.Bind(1, id_trans_); + st.Bind(2, id_category_); + st.Bind(3, id_subcategory_); + st.Bind(4, amount_); + + st.ExecuteUpdate(); + id_ = (db->GetLastRowId()).ToLong(); + st.Finalize(); + mmOptions::instance().databaseUpdated_ = true; +} + +void TSplitEntry::Update(wxSQLite3Database* db, wxString db_table) +{ + wxString sql_statement; + sql_statement << wxT("UPDATE ") << db_table << wxT(" SET ") + << wxT("TRANSID = ?, CATEGID = ?, SUBCATEGID = ?, ") + << wxT("SPLITTRANSAMOUNT = ? ") + << wxT("WHERE SPLITTRANSID = ?"); + wxSQLite3Statement st = db->PrepareStatement(sql_statement); + st.Bind(1, id_trans_); + st.Bind(2, id_category_); + st.Bind(3, id_subcategory_); + st.Bind(4, amount_); + st.Bind(5, id_); + + st.ExecuteUpdate(); + st.Finalize(); + mmOptions::instance().databaseUpdated_ = true; +} + +void TSplitEntry::Delete(wxSQLite3Database* db, wxString db_table) +{ + wxString sql_statement; + sql_statement << wxT("delete from ") << db_table + << wxT(" where SPLITTRANSID = ?"); + wxSQLite3Statement st = db->PrepareStatement(sql_statement); + st.Bind(1, id_); + + st.ExecuteUpdate(); + st.Finalize(); + mmOptions::instance().databaseUpdated_ = true; +} +//----------------------------------------------------------------------------- + + +//----------------------------------------------------------------------------- +TSplitEntriesList::TSplitEntriesList(boost::shared_ptr<wxSQLite3Database> db, wxString db_table) +: db_(db) +, db_table_(db_table) +, global_entries_() +{ + LoadEntries(); +} + +void TSplitEntriesList::LoadEntries() +{ + wxString sql_statement; + sql_statement << wxT("select SPLITTRANSID, TRANSID,") + << wxT(" CATEGID, SUBCATEGID,") + << wxT(" SPLITTRANSAMOUNT ") + << wxT("from ") << db_table_ << wxT(" order by SPLITTRANSID"); + wxSQLite3ResultSet q1 = db_->ExecuteQuery(sql_statement); + while (q1.NextRow()) + { + boost::shared_ptr<TSplitEntry> pEntry(new TSplitEntry(q1)); + global_entries_.push_back(pEntry); + } + q1.Finalize(); +} +//----------------------------------------------------------------------------- + + +//----------------------------------------------------------------------------- +// Holds the list of split transactions for a transaction +TSplitTransactionList::TSplitTransactionList(int id_transaction, TSplitEntriesList& entries_List) +: id_transaction_(id_transaction) +, entries_List_(entries_List) +, total_(0.0) +, entries_() +{ + LoadEntries(); +} + +// Load a list of entries for a transaction from the global list +void TSplitTransactionList::LoadEntries() +{ + for (size_t index = 0; index < entries_List_.global_entries_.size(); ++index) + { + if (entries_List_.global_entries_[index]->id_trans_ == id_transaction_) + { + boost::shared_ptr<TSplitEntry> pEntry = entries_List_.global_entries_[index]; + entries_.push_back(pEntry); + total_ += pEntry->amount_; + } + } +} + +double TSplitTransactionList::TotalAmount() +{ + return total_; +} + +void TSplitTransactionList::AddEntry(boost::shared_ptr<TSplitEntry> pEntry) +{ + total_ += pEntry->amount_; + entries_.push_back(pEntry); // Add to local list + entries_List_.global_entries_.push_back(pEntry); // Add to global list + pEntry->Save(entries_List_.db_.get(), entries_List_.db_table_); +} + +double TSplitTransactionList::AddEntry(int cat_id, int subcat_id, double amount) +{ + boost::shared_ptr<TSplitEntry> pEntry(new TSplitEntry()); + + pEntry->id_trans_ = id_transaction_; + pEntry->id_category_ = cat_id; + pEntry->id_subcategory_ = subcat_id; + pEntry->amount_ = amount; + AddEntry(pEntry); + return pEntry->id_; +} + +void TSplitTransactionList::UpdateEntry(boost::shared_ptr<TSplitEntry> split_entry) +{ + split_entry->Update(entries_List_.db_.get(), entries_List_.db_table_); + ReEvaluateTotal(); +} + +void TSplitTransactionList::DeleteEntry(boost::shared_ptr<TSplitEntry> split_entry) +{ + split_entry->Delete(entries_List_.db_.get(), entries_List_.db_table_); + entries_.clear(); + RemoveGlobalEntry(split_entry->id_); + total_ = 0.0; + LoadEntries(); +} + +void TSplitTransactionList::RemoveGlobalEntry(int entry_id) +{ + for (size_t index = 0; index < entries_List_.global_entries_.size(); ++index) + { + if (entries_List_.global_entries_[index]->id_ == entry_id) + { + entries_List_.global_entries_.erase(entries_List_.global_entries_.begin() + index); + break; + } + } +} + +int TSplitTransactionList::GetListSize() +{ + return entries_.size(); +} + +boost::shared_ptr<TSplitEntry> TSplitTransactionList::GetEntryPtr(int id_split_trans) +{ + boost::shared_ptr<TSplitEntry> entry_ptr; + for (size_t i = 0; i < entries_.size(); ++i) + { + if (entries_[i]->id_ == id_split_trans) + { + entry_ptr = entries_[i]; + break; + } + } + + return entry_ptr; +} + +boost::shared_ptr<TSplitEntry> TSplitTransactionList::GetIndexedEntryPtr(int index) +{ + return entries_[index]; +} + +void TSplitTransactionList::ReEvaluateTotal() +{ + total_ = 0.0; + for (size_t i = 0; i < entries_.size(); ++i) + { + total_ += entries_[i]->amount_; + } +} + + +/*********************************************************************************** + Existing code + **********************************************************************************/ void mmSplitTransactionEntries::addSplit(boost::shared_ptr<mmSplitTransactionEntry> split) { total_ += split->splitAmount_; Modified: trunk/mmex/src/mmtransaction.h =================================================================== --- trunk/mmex/src/mmtransaction.h 2013-01-20 02:10:42 UTC (rev 3373) +++ trunk/mmex/src/mmtransaction.h 2013-01-20 04:24:03 UTC (rev 3374) @@ -26,6 +26,99 @@ class mmCoreDB; +/*********************************************************************************** + SplitTransactions_V1 and BudgetSplitTransactions_V1 tables have the same structure. + The classes TSplitTransactionList and TSplitTransEntry can be used for both tables. + **********************************************************************************/ +const wxString SPLIT_TRANS_TABLE = wxT("SPLITTRANSACTIONS_V1"); +const wxString BUDGET_SPLIT_TRANS_TABLE = wxT("BUDGETSPLITTRANSACTIONS_V1"); + +/*********************************************************************************** + New class TSplitTransEntry + This class holds a single split transaction entry + **********************************************************************************/ +class TSplitEntry +{ +private: + int id_; + int id_trans_; + + void Save(wxSQLite3Database* db, wxString db_table); + void Update(wxSQLite3Database* db, wxString db_table); + void Delete(wxSQLite3Database* db, wxString db_table); + + /// Used when creating a new entry for TSplitTransactionList + TSplitEntry(); + +public: + int id_category_; + int id_subcategory_; + double amount_; + + /// Used to load an entry from the database. + TSplitEntry(wxSQLite3ResultSet& q1); + + int GetSplitEntryId(); + + DECLARE_NO_COPY_CLASS(TSplitEntry); + friend class TSplitTransactionList; +}; + +/*********************************************************************************** + Load all split transaction entries into memory for increased performance. + **********************************************************************************/ +class TSplitEntriesList +{ +private: + boost::shared_ptr<wxSQLite3Database> db_; + wxString db_table_; + std::vector< boost::shared_ptr<TSplitEntry> > global_entries_; + + void LoadEntries(); + + +public: + TSplitEntriesList(boost::shared_ptr<wxSQLite3Database> db, wxString db_table = SPLIT_TRANS_TABLE); + + friend class TSplitTransactionList; +}; + +/*********************************************************************************** + This class holds a list of split transaction entries for a single transaction + **********************************************************************************/ +class TSplitTransactionList +{ +private: + int id_transaction_; + TSplitEntriesList& entries_List_; + double total_; + std::vector< boost::shared_ptr<TSplitEntry> > entries_; + + /// Load the transaction split entries from the global list. + void LoadEntries(); + + void AddEntry(boost::shared_ptr<TSplitEntry> split_entry); + void ReEvaluateTotal(); + void RemoveGlobalEntry(int entry_id); + +public: + TSplitTransactionList(int id_transaction, TSplitEntriesList& entries_List); + + double TotalAmount(); + + double AddEntry(int cat_id, int subcat_id, double amount); + void UpdateEntry(boost::shared_ptr<TSplitEntry> split_entry); + void DeleteEntry(boost::shared_ptr<TSplitEntry> split_entry); + + int GetListSize(); + boost::shared_ptr<TSplitEntry> GetEntryPtr(int id_split_trans); + boost::shared_ptr<TSplitEntry> GetIndexedEntryPtr(int index); + +}; + +/*********************************************************************************** + Existing code + **********************************************************************************/ class mmTransaction { public: Added: trunk/mmex/src/tests/new_classes_test.cpp =================================================================== --- trunk/mmex/src/tests/new_classes_test.cpp (rev 0) +++ trunk/mmex/src/tests/new_classes_test.cpp 2013-01-20 04:24:03 UTC (rev 3374) @@ -0,0 +1,171 @@ +/************************************************************************* + Copyright (C) 2013 Stefano Giorgio + + 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, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + *************************************************************************/ +/**************************************************************************** + These tests can be run independantly of other tests by excluding + dbwrapper_test.cpp from the project. Alternatively, this module can be + prevented from running by excluding mmex_lua_test.cpp from the project. + + Note: Total test time is meaningless with this module included. + + ****************************************************************************/ +#include <UnitTest++.h> +#include "testing_util.h" + +#ifdef NEW_CLASSES_TEST_INCLUDED_IN_BUILD +/***************************************************************************************** + The tests for the new classes + *****************************************************************************************/ +SUITE(new_classes_test) +{ + +// ---------------------------------------------------------------------------- +// The test: init_DB has been duplicated in this suite to ensure that the +// database is initialised when this module is used on its own. +// ---------------------------------------------------------------------------- +TEST(init_DB) +{ + printf("\nnew_classes_test: START"); + display_STD_IO_separation_line(); + const wxDateTime start_time(wxDateTime::UNow()); + + mmCoreDB* pCore = pDb_core().get(); + CHECK(pCore->displayDatabaseError_ == true); + + displayTimeTaken(wxT("init_DB"), start_time); +} +//---------------------------------------------------------------------------- + +TEST(TSplitTransactionList_test_create) +{ + const wxDateTime start_time(wxDateTime::UNow()); + + TSplitEntriesList global_splits(get_pDb()); + + int trans_id = 9; + TSplitTransactionList split_list_9(trans_id, global_splits); + + split_list_9.AddEntry(10,20,100); + split_list_9.AddEntry(10,21,200); + split_list_9.AddEntry(10,22,300); + split_list_9.AddEntry(10,22,400); + CHECK_EQUAL(1000, split_list_9.TotalAmount()); + + trans_id = 10; + TSplitTransactionList split_list_10(trans_id, global_splits); + + split_list_10.AddEntry(10,20,100); + split_list_10.AddEntry(10,21,200); + split_list_10.AddEntry(10,22,300); + split_list_10.AddEntry(10,22,400); + CHECK_EQUAL(1000, split_list_10.TotalAmount()); + + trans_id = 11; + TSplitTransactionList split_list_11(trans_id, global_splits); + + split_list_11.AddEntry(10,20,100); + split_list_11.AddEntry(10,21,200); + split_list_11.AddEntry(10,22,300); + split_list_11.AddEntry(10,22,400); + CHECK_EQUAL(1000, split_list_11.TotalAmount()); + + TSplitTransactionList split_list_2(trans_id, global_splits); + CHECK_EQUAL(1000, split_list_2.TotalAmount()); + + displayTimeTaken(wxT("TSplitTransList_test_create"), start_time); +} + +TEST(TSplitTransactionList_test_update) +{ + const wxDateTime start_time(wxDateTime::UNow()); + + TSplitEntriesList global_splits(get_pDb()); + + int trans_id = 10; + TSplitTransactionList split_list(trans_id, global_splits); + CHECK_EQUAL(1000, split_list.TotalAmount()); + + int list_size = split_list.GetListSize(); + CHECK_EQUAL(4, list_size); + // record_id = 3, list_index = 2 + boost::shared_ptr<TSplitEntry> pEntry = split_list.GetIndexedEntryPtr(2); + + pEntry->amount_ = 500; + split_list.UpdateEntry(pEntry); + CHECK_EQUAL(1200, split_list.TotalAmount()); + + displayTimeTaken(wxT("TSplitTransList_test_update"), start_time); +} + +TEST(TSplitTransactionList_test_delete) +{ + const wxDateTime start_time(wxDateTime::UNow()); + + TSplitEntriesList global_splits(get_pDb()); + + int trans_id = 10; + TSplitTransactionList split_list(trans_id, global_splits); + CHECK_EQUAL(1200, split_list.TotalAmount()); + + int list_size = split_list.GetListSize(); + CHECK_EQUAL(4, list_size); + boost::shared_ptr<TSplitEntry> pEntry = split_list.GetIndexedEntryPtr(2); + split_list.DeleteEntry(pEntry); + CHECK_EQUAL(700, split_list.TotalAmount()); + list_size = split_list.GetListSize(); + CHECK_EQUAL(3, list_size); + + pEntry = split_list.GetIndexedEntryPtr(2); + + int entry_id = pEntry->GetSplitEntryId(); + + pEntry = split_list.GetEntryPtr(entry_id); + if (pEntry) + { + split_list.DeleteEntry(pEntry); + CHECK_EQUAL(300, split_list.TotalAmount()); + } + displayTimeTaken(wxT("TSplitTransList_test_delete"), start_time); +} + +TEST(TSplitTransactionList_test_add_after_delete) +{ + const wxDateTime start_time(wxDateTime::UNow()); + + TSplitEntriesList global_splits(get_pDb()); + + int trans_id = 10; + TSplitTransactionList split_list(trans_id, global_splits); + CHECK_EQUAL(300, split_list.TotalAmount()); + + int list_size = split_list.GetListSize(); + CHECK_EQUAL(2, list_size); + + double split_entry_id; + split_entry_id = split_list.AddEntry(10,21,200); + split_entry_id = split_list.AddEntry(10,22,300); + CHECK_EQUAL(800, split_list.TotalAmount()); + + displayTimeTaken(wxT("TSplitTranList_test_add_after_delete"), start_time); +} + + +} // End of SUITE: mmex_new_classes_test + + +//---------------------------------------------------------------------------- +#endif // NEW_CLASSES_TEST_INCLUDED_IN_BUILD Modified: trunk/mmex/src/tests/testing_util.cpp =================================================================== --- trunk/mmex/src/tests/testing_util.cpp 2013-01-20 02:10:42 UTC (rev 3373) +++ trunk/mmex/src/tests/testing_util.cpp 2013-01-20 04:24:03 UTC (rev 3374) @@ -63,7 +63,13 @@ boost::shared_ptr<wxSQLite3Database> get_pInidb() { +// change order for termination case +#ifdef DBWRAPPER_TEST_INCLUDED_IN_BUILD static Cleanup temp_IniDatabase(getIniDbPpath(), true); +#else + static Cleanup temp_IniDatabase(getIniDbPpath()); +#endif + static boost::shared_ptr<wxSQLite3Database> pInidb(new wxSQLite3Database); if (!pInidb->IsOpen()) @@ -97,7 +103,13 @@ boost::shared_ptr<wxSQLite3Database> get_pDb() { +#ifdef DBWRAPPER_TEST_INCLUDED_IN_BUILD static Cleanup temp_database(getDbPath()); +#else + static Cleanup temp_database(getDbPath(), true); +#endif + + boost::shared_ptr<wxSQLite3Database> pDb = static_db_ptr(); if (!pDb->IsOpen()) Modified: trunk/mmex/src/tests/testing_util.h =================================================================== --- trunk/mmex/src/tests/testing_util.h 2013-01-20 02:10:42 UTC (rev 3373) +++ trunk/mmex/src/tests/testing_util.h 2013-01-20 04:24:03 UTC (rev 3374) @@ -18,13 +18,10 @@ *************************************************************************/ #pragma once -/**************************************************************************** - Revision of last commit: $Revision: 3245 $ - Author of last commit: $Author: stef145g $ - ****************************************************************************/ -#define UTIL_TEST_INCLUDED_IN_BUILD -#define DBWRAPPER_TEST_INCLUDED_IN_BUILD -#define MMEX_LUA_TEST_INCLUDED_IN_BUILD +//#define UTIL_TEST_INCLUDED_IN_BUILD +//#define DBWRAPPER_TEST_INCLUDED_IN_BUILD +//#define MMEX_LUA_TEST_INCLUDED_IN_BUILD +#define NEW_CLASSES_TEST_INCLUDED_IN_BUILD #include <boost/scoped_ptr.hpp> #include <wx/filename.h> This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |