Use GUIDs to represent QofInstances instead of pointers.

Converting them to pointers for Scheme to use. Prevents
dangling pointers when the user deletes a QofInstance as long as the
Scheme report code re-fetches its pointers from the options when it's
regenerated.
This commit is contained in:
John Ralls 2022-03-12 17:58:23 -08:00
parent a7a643f7f2
commit d4c3c30b1a
10 changed files with 169 additions and 86 deletions

View File

@ -1524,7 +1524,7 @@ create_option_widget<GncOptionUIType::DATE_BOTH>(GncOption& option,
documentation, enclosing, packed);
}
using GncOptionAccountList = std::vector<const Account*>;
using GncOptionAccountList = std::vector<GncGUID>;
static void
account_select_all_cb(GtkWidget *widget, gpointer data)
@ -1604,8 +1604,12 @@ public:
GList *acc_list = nullptr;
const GncOptionAccountList& accounts =
option.get_value<GncOptionAccountList>();
for (auto account : accounts)
acc_list = g_list_prepend(acc_list, static_cast<void*>(const_cast<Account*>(account)));
auto book{gnc_get_current_book()};
for (auto guid : accounts)
{
auto account{xaccAccountLookup(&guid, book)};
acc_list = g_list_prepend(acc_list, account);
}
acc_list = g_list_reverse(acc_list);
gnc_tree_view_account_set_selected_accounts(widget, acc_list, TRUE);
g_list_free(acc_list);
@ -1617,7 +1621,10 @@ public:
GncOptionAccountList acc_vec;
acc_vec.reserve(g_list_length(acc_list));
for (auto node = acc_list; node; node = g_list_next(node))
acc_vec.push_back(static_cast<const Account*>(node->data));
{
auto guid{qof_entity_get_guid(node->data)};
acc_vec.push_back(*guid);
}
g_list_free(acc_list);
option.set_value(acc_vec);
}

View File

@ -275,13 +275,20 @@ GncOptionAccountListValue::validate(const GncOptionAccountList& values) const
return true;
if ((get_ui_type() == GncOptionUIType::ACCOUNT_SEL || !m_multiselect) &&
values.size() != 1)
{
std::cerr << "GncOptionAccountListValue::validate: Multiple values for a non-multiselect option." << std::endl;
return false;
}
if (m_allowed.empty())
return true;
for(auto account : values) {
auto book{gnc_get_current_book()};
for(auto& guid : values)
{
if (std::find(m_allowed.begin(), m_allowed.end(),
xaccAccountGetType(account)) == m_allowed.end())
return false;
xaccAccountGetType(xaccAccountLookup(&guid, book))) == m_allowed.end())
{
std::cerr << "GncOptionAccountListValue::validate: Account " << gnc::GUID(guid).to_string() << " is not of an allowed type" << std::endl;
return false; }
}
return true;
}
@ -310,17 +317,33 @@ GncOptionAccountListValue::get_default_value() const
if (!account_list)
return retval;
auto book{gnc_get_current_book()};
for (auto node = account_list; node; node = g_list_next (node))
{
if (std::find(m_allowed.begin(), m_allowed.end(),
xaccAccountGetType(GNC_ACCOUNT(node->data))) != m_allowed.end())
{
retval.push_back(GNC_ACCOUNT(node->data));
retval.push_back(*qof_entity_get_guid(GNC_ACCOUNT(node->data)));
break;
}
}
g_list_free(account_list);
return retval;
}
static bool
operator==(const GncGUID& l, const GncGUID& r)
{
return guid_equal(&l, &r);
}
bool
GncOptionAccountListValue::is_changed() const noexcept
{
return m_value != m_default_value;
}
/**
* Create a GList of account types to pass to gnc_account_sel_set_acct_filters.
@ -354,15 +377,20 @@ GncOptionAccountSelValue::validate(const Account* value) const
const Account*
GncOptionAccountSelValue::get_value() const
{
return m_value ? m_value : get_default_value();
auto book{gnc_get_current_book()};
return guid_equal(guid_null(), &m_value) ? get_default_value() :
xaccAccountLookup(&m_value, book);
}
const Account*
GncOptionAccountSelValue::get_default_value() const
{
if (m_default_value)
return m_default_value;
if (!guid_equal(guid_null(), &m_default_value))
{
auto book{gnc_get_current_book()};
return xaccAccountLookup(&m_default_value, book);
}
/* If no default has been set and there's an allowed set then find the first
* account that matches one of the allowed account types.
@ -713,7 +741,7 @@ GncOptionAccountListValue::serialize() const noexcept
if (!first)
retval += " ";
first = false;
retval += qof_instance_to_string(QOF_INSTANCE(val));
retval += guid_to_string(&val);
}
return retval;
}
@ -732,8 +760,9 @@ GncOptionAccountListValue::deserialize(const std::string& str) noexcept
if (!first)
++pos;
first = false;
auto ptr = qof_instance_from_string(str.substr(pos, pos + GUID_ENCODING_LENGTH), get_ui_type());
m_value.push_back(reinterpret_cast<Account*>(ptr));
GncGUID guid{};
string_to_guid(str.substr(pos, pos + GUID_ENCODING_LENGTH).c_str(), &guid);
m_value.push_back(guid);
pos += GUID_ENCODING_LENGTH;
}
return true;
@ -743,7 +772,7 @@ std::string
GncOptionAccountSelValue::serialize() const noexcept
{
static const std::string no_value{"No Value"};
return m_value ?qof_instance_to_string(QOF_INSTANCE(m_value)) : no_value;
return guid_equal(guid_null(), &m_value) ? no_value : guid_to_string(&m_value);
}
bool

View File

@ -717,7 +717,7 @@ operator>> <GncOptionMultichoiceValue>(std::istream& iss,
}
using GncOptionAccountList = std::vector<const Account*>;
using GncOptionAccountList = std::vector<GncGUID>;
using GncOptionAccountTypeList = std::vector<GNCAccountType>;
@ -795,7 +795,7 @@ public:
}
GList* account_type_list() const noexcept;
void reset_default_value() { m_value = m_default_value; }
bool is_changed() const noexcept { return m_value != m_default_value; }
bool is_changed() const noexcept;
GncOptionUIType get_ui_type() const noexcept { return m_ui_type; }
void make_internal() { m_ui_type = GncOptionUIType::INTERNAL; }
bool is_multiselect() const noexcept { return m_multiselect; }
@ -821,7 +821,7 @@ operator<< <GncOptionAccountListValue>(std::ostream& oss,
first = false;
else
oss << " ";
oss << qof_instance_to_string(QOF_INSTANCE(value));
oss << guid_to_string(&value);
}
return oss;
}
@ -836,7 +836,10 @@ operator>> <GncOptionAccountListValue>(std::istream& iss,
std::string str;
std::getline(iss, str, ' ');
if (!str.empty())
values.emplace_back((Account*)qof_instance_from_string(str, opt.get_ui_type()));
{
auto guid{qof_entity_get_guid(qof_instance_from_string(str, opt.get_ui_type()))};
values.push_back(*guid);
}
else
break;
}
@ -856,32 +859,32 @@ public:
const char* key, const char* doc_string,
GncOptionUIType ui_type) :
OptionClassifier{section, name, key, doc_string}, m_ui_type{ui_type},
m_value{}, m_default_value{}, m_allowed{} {}
m_value{*guid_null()}, m_default_value{*guid_null()}, m_allowed{} {}
GncOptionAccountSelValue(const char* section, const char* name,
const char* key, const char* doc_string,
GncOptionUIType ui_type,
const Account* value) :
OptionClassifier{section, name, key, doc_string}, m_ui_type{ui_type},
m_value{const_cast<Account*>(value)},
m_default_value{const_cast<Account*>(value)}, m_allowed{} {}
m_value{*qof_entity_get_guid(value)},
m_default_value{*qof_entity_get_guid(value)}, m_allowed{} {}
GncOptionAccountSelValue(const char* section, const char* name,
const char* key, const char* doc_string,
GncOptionUIType ui_type,
GncOptionAccountTypeList&& allowed) :
OptionClassifier{section, name, key, doc_string}, m_ui_type{ui_type},
m_value{}, m_default_value{}, m_allowed{std::move(allowed)} {}
m_value{*guid_null()}, m_default_value{*guid_null()},
m_allowed{std::move(allowed)} {}
GncOptionAccountSelValue(const char* section, const char* name,
const char* key, const char* doc_string,
GncOptionUIType ui_type,
const Account* value,
GncOptionAccountTypeList&& allowed) :
OptionClassifier{section, name, key, doc_string}, m_ui_type{ui_type},
m_value{}, m_default_value{}, m_allowed{std::move(allowed)} {
m_value{*guid_null()}, m_default_value{*guid_null()}, m_allowed{std::move(allowed)} {
if (!validate(value))
throw std::invalid_argument("Supplied Value not in allowed set.");
m_value = const_cast<Account*>(value);
m_default_value = const_cast<Account*>(value);
m_value = m_default_value = *qof_entity_get_guid(value);
}
const Account* get_value() const;
@ -889,25 +892,31 @@ public:
bool validate (const Account* value) const;
void set_value (const Account* value) {
if (validate(value))
//throw!
m_value = const_cast<Account*>(value);
{
auto guid{qof_entity_get_guid(value)};
m_value = *guid;
}
//else throw
}
void set_default_value (const Account* value) {
if (validate(value))
//throw!
m_value = m_default_value = const_cast<Account*>(value);
{
auto guid{qof_entity_get_guid(value)};
m_value = m_default_value = *guid;
}
//else throw
}
GList* account_type_list() const noexcept;
void reset_default_value() { m_value = m_default_value; }
bool is_changed() const noexcept { return m_value != m_default_value; }
bool is_changed() const noexcept { return !guid_equal(&m_value, &m_default_value); }
GncOptionUIType get_ui_type() const noexcept { return m_ui_type; }
void make_internal() { m_ui_type = GncOptionUIType::INTERNAL; }
std::string serialize() const noexcept;
bool deserialize(const std::string& str) noexcept;
private:
GncOptionUIType m_ui_type;
Account* m_value;
Account* m_default_value;
GncGUID m_value;
GncGUID m_default_value;
GncOptionAccountTypeList m_allowed;
};

View File

@ -28,6 +28,7 @@
#include <sstream>
#include <kvp-value.hpp>
#include <qofbookslots.h>
#include <guid.hpp>
#include "gnc-optiondb.h"
#include "gnc-optiondb.hpp"
#include "gnc-optiondb-impl.hpp"
@ -708,6 +709,11 @@ gnc_register_account_list_limited_option(GncOptionDB* db,
{
try
{
std::cout << "gnc_register_account_list_limited_option for accounts ";
std::for_each(value.begin(), value.end(), [](auto& guid){
std::cout << gnc::GUID(guid).to_string() << " ";
});
std::cout << std::endl;
GncOption option{GncOptionAccountListValue{section, name, key, doc_string,
GncOptionUIType::ACCOUNT_LIST, value, std::move(allowed)}};
db->register_option(section, std::move(option));
@ -729,7 +735,7 @@ find_children(Account* account, void* data)
const GncOptionAccountTypeList& types = datapair->second;
if (std::find(types.begin(), types.end(),
xaccAccountGetType(account)) != types.end())
list.push_back(account);
list.push_back(*qof_entity_get_guid(account));
}
GncOptionAccountList

View File

@ -54,7 +54,7 @@ extern "C"
class GncOptionDB;
using GncOptionDBPtr = std::unique_ptr<GncOptionDB>;
using GncOptionAccountList = std::vector<const Account*>;
using GncOptionAccountList = std::vector<GncGUID>;
using GncOptionAccountTypeList = std::vector<GNCAccountType>;
using GncMultichoiceOptionEntry = std::tuple<const std::string,

View File

@ -428,7 +428,10 @@ scm_to_value<GncOptionAccountList>(SCM new_value)
void* account{};
SWIG_ConvertPtr(node, &account, SWIGTYPE_p_Account, 0);
if (account)
retval.push_back(static_cast<Account*>(account));
{
auto guid{qof_entity_get_guid(static_cast<Account*>(account))};
retval.push_back(*guid);
}
next = scm_cdr(next);
if (scm_is_null(next))
break;
@ -440,9 +443,13 @@ template <>inline SCM
scm_from_value<GncOptionAccountList>(GncOptionAccountList value)
{
SCM s_list = SCM_EOL;
for (auto acct : value)
auto book{gnc_get_current_book()};
for (auto guid : value)
{
auto acct{xaccAccountLookup(&guid, book)};
s_list = scm_cons(SWIG_NewPointerObj(acct, SWIGTYPE_p_Account, 0),
s_list);
}
return scm_reverse(s_list);
}
@ -452,13 +459,14 @@ void gnc_option_test_book_destroy(QofBook*);
QofBook*
gnc_option_test_book_new()
{
return static_cast<QofBook*>(g_object_new(QOF_TYPE_BOOK, nullptr));
auto session = gnc_get_current_session();
return gnc_get_current_book();
}
void
gnc_option_test_book_destroy(QofBook* book)
{
g_object_unref(book);
gnc_clear_current_session();
}
%}
@ -574,7 +582,8 @@ gnc_option_test_book_destroy(QofBook* book)
SCM s_account = scm_list_ref($input, scm_from_size_t(i));
Account* acct = (Account*)SWIG_MustGetPtr(s_account,
SWIGTYPE_p_Account, 1, 0);
$1.push_back(acct);
if (acct)
$1.push_back(*qof_entity_get_guid(acct));
}
}
@ -602,7 +611,7 @@ gnc_option_test_book_destroy(QofBook* book)
$1 = &types;
}
%typemap(in) GncOptionAccountList
%typemap(in) GncOptionAccountList const & (GncOptionAccountList alist)
{
auto len = scm_is_true($input) ? scm_to_size_t(scm_length($input)) : 0;
for (std::size_t i = 0; i < len; ++i)
@ -610,8 +619,10 @@ gnc_option_test_book_destroy(QofBook* book)
SCM s_account = scm_list_ref($input, scm_from_size_t(i));
Account* acct = (Account*)SWIG_MustGetPtr(s_account,
SWIGTYPE_p_Account, 1, 0);
$1.push_back(acct);
if (acct)
alist.push_back(*qof_entity_get_guid(acct));
}
$1 = &alist;
}
%typemap(in) GncOptionAccountList& (GncOptionAccountList acclist)
@ -623,7 +634,7 @@ gnc_option_test_book_destroy(QofBook* book)
SCM s_account = scm_list_ref($input, scm_from_size_t(i));
Account* acct = (Account*)SWIG_MustGetPtr(s_account,
SWIGTYPE_p_Account, 1, 0);
acclist.push_back(acct);
acclist.push_back(*qof_entity_get_guid(acct));
}
$1 = &acclist;
}
@ -631,18 +642,26 @@ gnc_option_test_book_destroy(QofBook* book)
%typemap(out) GncOptionAccountList
{
$result = SCM_EOL;
for (auto acct : $1)
auto book{gnc_get_current_book()};
for (auto guid : $1)
{
auto acct{xaccAccountLookup(&guid, book)};
$result = scm_cons(SWIG_NewPointerObj(acct, SWIGTYPE_p_Account, 0),
$result);
}
$result = scm_reverse($result);
}
%typemap(out) GncOptionAccountList&
%typemap(out) const GncOptionAccountList&
{
$result = SCM_EOL;
for (auto acct : *$1)
auto book{gnc_get_current_book()};
for (auto guid : *$1)
{
auto acct{xaccAccountLookup(&guid, book)};
$result = scm_cons(SWIG_NewPointerObj(acct, SWIGTYPE_p_Account, 0),
$result);
}
$result = scm_reverse ($result)
}
@ -1080,17 +1099,17 @@ inline SCM return_scm_value(ValueType value)
GncOptionAccountListValue>)
{
static const SCM list_format_str{scm_from_utf8_string("'~s")};
auto acct_list{option.get_value()};
if (acct_list.empty())
auto guid_list{option.get_value()};
if (guid_list.empty())
return no_value;
SCM guid_list{SCM_EOL};
for(auto acct : acct_list)
SCM string_list{SCM_EOL};
for(auto guid : guid_list)
{
auto acct_str{qof_instance_to_string(QOF_INSTANCE(acct))};
auto acct_scm{scm_from_utf8_string(acct_str.c_str())};
guid_list = scm_cons(acct_scm, guid_list);
auto guid_str{guid_to_string(&guid)};
auto guid_scm{scm_from_utf8_string(guid_str)};
string_list = scm_cons(guid_scm, string_list);
}
return scm_simple_format(SCM_BOOL_F, list_format_str, scm_list_1(guid_list));
return scm_simple_format(SCM_BOOL_F, list_format_str, scm_list_1(string_list));
}
if constexpr (is_QofInstanceValue_v<decltype(option)>)

View File

@ -515,7 +515,7 @@ find_children(Account* account, void* data)
const GncOptionAccountTypeList& types = datapair->second;
if (std::find(types.begin(), types.end(),
xaccAccountGetType(account)) != types.end())
list.push_back(account);
list.push_back(*qof_entity_get_guid(account));
}
class GncOptionAccountTest : public ::testing::Test
@ -571,6 +571,12 @@ protected:
Account* m_root;
};
static bool
operator==(const GncGUID& l, const GncGUID& r)
{
return guid_equal(&l, &r);
}
TEST_F(GncOptionAccountTest, test_test_constructor_and_destructor)
{
EXPECT_TRUE(m_book != NULL);
@ -662,9 +668,9 @@ TEST_F(GncOptionAccountTest, test_account_list_out)
GncOptionUIType::ACCOUNT_LIST,
acclist}};
std::ostringstream oss;
std::string acc_guids{gnc::GUID{*qof_instance_get_guid(acclist[0])}.to_string()};
std::string acc_guids{gnc::GUID{acclist[0]}.to_string()};
acc_guids += " ";
acc_guids += gnc::GUID{*qof_instance_get_guid(acclist[1])}.to_string();
acc_guids += gnc::GUID{acclist[1]}.to_string();
oss << option;
EXPECT_EQ(acc_guids, oss.str());
@ -675,7 +681,7 @@ TEST_F(GncOptionAccountTest, test_account_list_out)
GncOptionUIType::ACCOUNT_LIST,
accsel,
GncOptionAccountTypeList{ACCT_TYPE_BANK}}};
acc_guids = gnc::GUID{*qof_instance_get_guid(accsel[0])}.to_string();
acc_guids = gnc::GUID{accsel[0]}.to_string();
oss.str("");
oss << sel_option;
@ -688,9 +694,9 @@ TEST_F(GncOptionAccountTest, test_account_list_in)
GncOption option{GncOptionAccountListValue{"foo", "bar", "baz", "Bogus Option",
GncOptionUIType::ACCOUNT_LIST,
acclist}};
std::string acc_guids{gnc::GUID{*qof_instance_get_guid(acclist[0])}.to_string()};
std::string acc_guids{gnc::GUID{acclist[0]}.to_string()};
acc_guids += " ";
acc_guids += gnc::GUID{*qof_instance_get_guid(acclist[1])}.to_string();
acc_guids += gnc::GUID{acclist[1]}.to_string();
std::istringstream iss{acc_guids};
iss >> option;
@ -703,7 +709,7 @@ TEST_F(GncOptionAccountTest, test_account_list_in)
accsel,
GncOptionAccountTypeList{ACCT_TYPE_BANK}}};
GncOptionAccountList acclistbad{list_of_types({ACCT_TYPE_STOCK})};
acc_guids = gnc::GUID{*qof_instance_get_guid(acclistbad[1])}.to_string();
acc_guids = gnc::GUID{acclistbad[1]}.to_string();
acc_guids += " ";
iss.str(acc_guids);
@ -711,7 +717,7 @@ TEST_F(GncOptionAccountTest, test_account_list_in)
EXPECT_EQ(accsel, sel_option.get_value<GncOptionAccountList>());
iss.clear(); //Reset the failedbit from the invalid selection type.
acc_guids = gnc::GUID{*qof_instance_get_guid(acclist[1])}.to_string();
acc_guids = gnc::GUID{acclist[1]}.to_string();
EXPECT_NO_THROW({
iss.str(acc_guids);
iss >> sel_option;

View File

@ -86,10 +86,12 @@ TEST_F(GncOptionDBTest, test_register_string_option)
*/
struct AccountTestBook
struct GncOptionDBAccountTest : public ::testing::Test
{
AccountTestBook() :
m_book{qof_book_new()}, m_root{gnc_account_create_root(m_book)}
GncOptionDBAccountTest() :
m_sess{gnc_get_current_session()}, m_book{gnc_get_current_book()},
m_root{gnc_account_create_root(m_book)},
m_db{std::make_unique<GncOptionDB>()}
{
auto create_account = [this](Account* parent, GNCAccountType type,
const char* name)->Account* {
@ -117,31 +119,31 @@ struct AccountTestBook
create_account(expenses, ACCT_TYPE_EXPENSE, "Gas");
create_account(expenses, ACCT_TYPE_EXPENSE, "Rent");
}
~AccountTestBook()
~GncOptionDBAccountTest()
{
xaccAccountBeginEdit(m_root);
xaccAccountDestroy(m_root); //It does the commit
qof_book_destroy(m_book);
gnc_clear_current_session();
}
QofSession* m_sess;
QofBook* m_book;
Account* m_root;
GncOptionDBPtr m_db;
};
TEST_F(GncOptionDBTest, test_register_account_list_option)
TEST_F(GncOptionDBAccountTest, test_register_account_list_option)
{
AccountTestBook book;
auto acclist{gnc_account_list_from_types(book.m_book, {ACCT_TYPE_STOCK})};
auto acclist{gnc_account_list_from_types(m_book, {ACCT_TYPE_STOCK})};
gnc_register_account_list_option(m_db, "foo", "bar", "baz",
"Phony Option", acclist);
EXPECT_EQ(4U, m_db->find_option("foo", "bar")->get_value<GncOptionAccountList>().size());
EXPECT_EQ(acclist[3], m_db->find_option("foo", "bar")->get_value<GncOptionAccountList>().at(3));
}
TEST_F(GncOptionDBTest, test_register_account_list_limited_option)
TEST_F(GncOptionDBAccountTest, test_register_account_list_limited_option)
{
AccountTestBook book;
auto acclist{gnc_account_list_from_types(book.m_book, {ACCT_TYPE_STOCK})};
auto acclist{gnc_account_list_from_types(m_book, {ACCT_TYPE_STOCK})};
gnc_register_account_list_limited_option(m_db, "foo", "bar", "baz",
"Phony Option", acclist,
{ACCT_TYPE_STOCK});
@ -149,10 +151,9 @@ TEST_F(GncOptionDBTest, test_register_account_list_limited_option)
EXPECT_EQ(acclist[3], m_db->find_option("foo", "bar")->get_value<GncOptionAccountList>().at(3));
}
TEST_F(GncOptionDBTest, test_register_account_sel_limited_option)
TEST_F(GncOptionDBAccountTest, test_register_account_sel_limited_option)
{
AccountTestBook book;
auto acclist{gnc_account_list_from_types(book.m_book, {ACCT_TYPE_STOCK})};
auto acclist{gnc_account_list_from_types(m_book, {ACCT_TYPE_STOCK})};
GncOptionAccountList accsel{acclist[2]};
gnc_register_account_list_limited_option(m_db, "foo", "bar", "baz",
"Phony Option", accsel,
@ -161,10 +162,9 @@ TEST_F(GncOptionDBTest, test_register_account_sel_limited_option)
EXPECT_EQ(accsel[0], m_db->find_option("foo", "bar")->get_value<GncOptionAccountList>().at(0));
}
TEST_F(GncOptionDBTest, test_register_account_sel_limited_option_fail_construct)
TEST_F(GncOptionDBAccountTest, test_register_account_sel_limited_option_fail_construct)
{
AccountTestBook book;
auto acclist{gnc_account_list_from_types(book.m_book, {ACCT_TYPE_STOCK})};
auto acclist{gnc_account_list_from_types(m_book, {ACCT_TYPE_STOCK})};
GncOptionAccountList accsel{acclist[2]};
gnc_register_account_list_limited_option(m_db, "foo", "bar", "baz", "Phony Option",
accsel, {ACCT_TYPE_BANK});
@ -276,6 +276,12 @@ TEST_F(GncOptionDBTest, test_register_start_date_option)
}
static bool
operator==(const GncGUID& l, const GncGUID& r)
{
return guid_equal(&l, &r);
}
class GncOptionDBIOTest : public ::testing::Test
{
protected:
@ -322,7 +328,8 @@ protected:
RelativeDatePeriod::START_CURRENT_QUARTER);
gnc_register_account_list_option(m_db, "quux", "xyzzy", "second",
"Phony AccountList Option",
{aapl, hpe});
{*qof_entity_get_guid(aapl),
*qof_entity_get_guid(hpe)});
}
~GncOptionDBIOTest()

View File

@ -315,7 +315,7 @@ veritatis et quasi architecto beatae vitae dicta sunt, explicabo.")
(test-template test-account-list-output-template)
(new-acclist (gnc-account-list-from-types book (list ACCT-TYPE-BANK))))
(gnc:option-set-value option new-acclist)
(test-equal "account list form"
(test-equal "account list form" ;;fails
(test-template (GncOption-serialize option))
(gnc:generate-restore-forms odb "options"))
))
@ -338,7 +338,7 @@ veritatis et quasi architecto beatae vitae dicta sunt, explicabo.")
(let ((option (gnc:lookup-option odb "foo" "bar"))
(test-template test-string-output-template))
(gnc:option-set-value option bank)
(test-equal "account sel form"
(test-equal "account sel form" ;; fails
(test-template (GncOption-serialize option))
(gnc:generate-restore-forms odb "options"))
))

View File

@ -112,16 +112,16 @@
(test-equal (car acctlist) (car acct-list))) )))
(define (test-make-account-list-limited-option book)
(test-group "test-make-account-list-option"
(test-group "test-make-account-list-limited-option"
(let ((option-db (new-gnc-optiondb))
(acctlist (gnc-account-list-from-types book
(list ACCT-TYPE-STOCK))))
(gnc-register-account-list-limited-option
(gnc-register-account-list-limited-option ;; Error not account type twice
option-db "foo" "bar" "baz"
"Phony Option" acctlist (list ACCT-TYPE-STOCK))
(let ((acct-list (gnc-option-value option-db "foo" "bar")))
(test-equal (length acctlist) (length acct-list))
(test-equal (cadr acctlist) (cadr acct-list)))
(test-equal (length acctlist) (length acct-list)) ;; fails acct-list 4 vs #f
(test-equal (cadr acctlist) (cadr acct-list))) ;; fails () vs. #f both wrong
(gnc-register-account-list-limited-option
option-db "waldo" "pepper" "baz"
"Phony Option" acctlist (list ACCT-TYPE-BANK))