The unit tests for amount.cc now cover every part of the code except

for two: those concerning annotated commodities (which will be covered
in the t_commodity.cc tests) and reading of optimized amounts in the
binary journal reader.
This commit is contained in:
John Wiegley 2007-05-09 10:02:56 +00:00
parent 623e6e024c
commit 8e20c378d6
8 changed files with 398 additions and 199 deletions

View file

@ -1,3 +1,8 @@
- Add tracing code for functions that records call count and total - Add tracing code for functions that records call count and total
time spent, as well as average time per call. This would implement time spent, as well as average time per call. This would implement
selective profiling. selective profiling.
- Make sure that if any constructors cause memory to be allocated,
that the memory is held by an auto_ptr until the constructor is
done; otherwise, an exception raised from within the constructor
will not call the destructor to free the memory.

View file

@ -131,20 +131,6 @@ void amount_t::shutdown()
} }
} }
void amount_t::_init()
{
// This is only called on an initialized amount by amount_t::parse.
if (! quantity) {
quantity = new bigint_t;
}
else if (quantity->ref > 1) {
_release();
quantity = new bigint_t;
}
commodity_ = NULL;
}
void amount_t::_copy(const amount_t& amt) void amount_t::_copy(const amount_t& amt)
{ {
if (quantity != amt.quantity) { if (quantity != amt.quantity) {
@ -183,13 +169,9 @@ void amount_t::_resize(precision_t prec)
_dup(); _dup();
if (prec < quantity->prec) { assert(prec > quantity->prec);
mpz_ui_pow_ui(divisor, 10, quantity->prec - prec);
mpz_tdiv_q(MPZ(quantity), MPZ(quantity), divisor);
} else {
mpz_ui_pow_ui(divisor, 10, prec - quantity->prec); mpz_ui_pow_ui(divisor, 10, prec - quantity->prec);
mpz_mul(MPZ(quantity), MPZ(quantity), divisor); mpz_mul(MPZ(quantity), MPZ(quantity), divisor);
}
quantity->prec = prec; quantity->prec = prec;
} }
@ -359,7 +341,7 @@ int amount_t::compare(const amount_t& amt) const
return mpz_cmp(MPZ(quantity), MPZ(amt.quantity)); return mpz_cmp(MPZ(quantity), MPZ(amt.quantity));
} }
else if (quantity->prec < amt.quantity->prec) { else if (quantity->prec < amt.quantity->prec) {
amount_t t = *this; amount_t t(*this);
t._resize(amt.quantity->prec); t._resize(amt.quantity->prec);
return mpz_cmp(MPZ(t.quantity), MPZ(amt.quantity)); return mpz_cmp(MPZ(t.quantity), MPZ(amt.quantity));
} }
@ -607,11 +589,11 @@ amount_t& amount_t::in_place_negate()
amount_t amount_t::round(precision_t prec) const amount_t amount_t::round(precision_t prec) const
{ {
amount_t t = *this;
if (! quantity) if (! quantity)
throw_(amount_error, "Cannot round an uninitialized amount"); throw_(amount_error, "Cannot round an uninitialized amount");
amount_t t(*this);
if (quantity->prec <= prec) { if (quantity->prec <= prec) {
if (quantity && quantity->has_flags(BIGINT_KEEP_PREC)) { if (quantity && quantity->has_flags(BIGINT_KEEP_PREC)) {
t._dup(); t._dup();
@ -637,7 +619,7 @@ amount_t amount_t::unround() const
else if (quantity->has_flags(BIGINT_KEEP_PREC)) else if (quantity->has_flags(BIGINT_KEEP_PREC))
return *this; return *this;
amount_t t = *this; amount_t t(*this);
t._dup(); t._dup();
t.quantity->add_flags(BIGINT_KEEP_PREC); t.quantity->add_flags(BIGINT_KEEP_PREC);
@ -915,7 +897,23 @@ void amount_t::parse(std::istream& in, flags_t flags)
if (quant.empty()) if (quant.empty())
throw_(amount_error, "No quantity specified for amount"); throw_(amount_error, "No quantity specified for amount");
_init(); // this will reuse a current value // Allocate memory for the amount's quantity value. We have to
// monitor the allocation in an auto_ptr because this function gets
// called sometimes from amount_t's constructor; and if there is an
// exeception thrown by any of the function calls after this point,
// the destructor will never be called and the memory never freed.
std::auto_ptr<bigint_t> safe_holder;
if (! quantity) {
quantity = new bigint_t;
safe_holder.reset(quantity);
}
else if (quantity->ref > 1) {
_release();
quantity = new bigint_t;
safe_holder.reset(quantity);
}
// Create the commodity if has not already been seen, and update the // Create the commodity if has not already been seen, and update the
// precision if something greater was used for the quantity. // precision if something greater was used for the quantity.
@ -965,9 +963,9 @@ void amount_t::parse(std::istream& in, flags_t flags)
// Set the commodity's flags and precision accordingly // Set the commodity's flags and precision accordingly
if (commodity_ && if (commodity_ && (newly_created || ! (flags & AMOUNT_PARSE_NO_MIGRATE))) {
(newly_created || ! (flags & AMOUNT_PARSE_NO_MIGRATE))) {
commodity().add_flags(comm_flags); commodity().add_flags(comm_flags);
if (quantity->prec > commodity().precision()) if (quantity->prec > commodity().precision())
commodity().set_precision(quantity->prec); commodity().set_precision(quantity->prec);
} }
@ -1004,6 +1002,8 @@ void amount_t::parse(std::istream& in, flags_t flags)
if (! (flags & AMOUNT_PARSE_NO_REDUCE)) if (! (flags & AMOUNT_PARSE_NO_REDUCE))
in_place_reduce(); in_place_reduce();
safe_holder.release(); // `this->quantity' owns the pointer
} }
void amount_t::parse_conversion(const string& larger_str, void amount_t::parse_conversion(const string& larger_str,
@ -1201,8 +1201,6 @@ void amount_t::print(std::ostream& _out, bool omit_commodity,
// entire amount string, and not just the first part. // entire amount string, and not just the first part.
_out << out.str(); _out << out.str();
return;
} }
@ -1225,7 +1223,7 @@ void amount_t::read(std::istream& in)
else if (ident == 0) else if (ident == 0)
commodity_ = current_pool->null_commodity; commodity_ = current_pool->null_commodity;
else { else {
commodity_ = current_pool->find(ident - 1); commodity_ = current_pool->find(ident);
assert(commodity_); assert(commodity_);
} }
@ -1234,10 +1232,7 @@ void amount_t::read(std::istream& in)
char byte; char byte;
in.read(&byte, sizeof(byte)); in.read(&byte, sizeof(byte));
if (byte == 0) { if (byte < 3) {
quantity = NULL;
}
else if (byte == 1) {
quantity = new bigint_t; quantity = new bigint_t;
unsigned short len; unsigned short len;
@ -1263,7 +1258,7 @@ void amount_t::read(std::istream& in)
} }
} }
void amount_t::read(char *& data) void amount_t::read(const char *& data)
{ {
// Read in the commodity for this amount // Read in the commodity for this amount
@ -1274,7 +1269,7 @@ void amount_t::read(char *& data)
else if (ident == 0) else if (ident == 0)
commodity_ = current_pool->null_commodity; commodity_ = current_pool->null_commodity;
else { else {
commodity_ = current_pool->find(ident - 1); commodity_ = current_pool->find(ident);
assert(commodity_); assert(commodity_);
} }
@ -1282,12 +1277,13 @@ void amount_t::read(char *& data)
char byte = *data++;; char byte = *data++;;
if (byte == 0) { if (byte < 3) {
quantity = NULL; if (byte == 2) {
}
else if (byte == 1) {
quantity = new((bigint_t *)bigints_next) bigint_t; quantity = new((bigint_t *)bigints_next) bigint_t;
bigints_next += sizeof(bigint_t); bigints_next += sizeof(bigint_t);
} else {
quantity = new bigint_t;
}
unsigned short len = *((unsigned short *) data); unsigned short len = *((unsigned short *) data);
data += sizeof(unsigned short); data += sizeof(unsigned short);
@ -1303,6 +1299,8 @@ void amount_t::read(char *& data)
data += sizeof(precision_t); data += sizeof(precision_t);
quantity->set_flags(*((flags_t *) data)); quantity->set_flags(*((flags_t *) data));
data += sizeof(flags_t); data += sizeof(flags_t);
if (byte == 2)
quantity->add_flags(BIGINT_BULK_ALLOC); quantity->add_flags(BIGINT_BULK_ALLOC);
} else { } else {
uint_fast32_t index = *((uint_fast32_t *) data); uint_fast32_t index = *((uint_fast32_t *) data);
@ -1315,7 +1313,7 @@ void amount_t::read(char *& data)
} }
} }
void amount_t::write(std::ostream& out) const void amount_t::write(std::ostream& out, bool optimized) const
{ {
// Write out the commodity for this amount // Write out the commodity for this amount
@ -1331,11 +1329,14 @@ void amount_t::write(std::ostream& out) const
char byte; char byte;
if (quantity->index == 0) { if (! optimized || quantity->index == 0) {
quantity->index = ++bigints_index; if (optimized) {
quantity->index = ++bigints_index; // if !optimized, this is garbage
bigints_count++; bigints_count++;
byte = 2;
} else {
byte = 1; byte = 1;
}
out.write(&byte, sizeof(byte)); out.write(&byte, sizeof(byte));
std::size_t size; std::size_t size;
@ -1359,7 +1360,7 @@ void amount_t::write(std::ostream& out) const
// Since this value has already been written, we simply write // Since this value has already been written, we simply write
// out a reference to which one it was. // out a reference to which one it was.
byte = 2; byte = 3;
out.write(&byte, sizeof(byte)); out.write(&byte, sizeof(byte));
out.write((char *)&quantity->index, sizeof(quantity->index)); out.write((char *)&quantity->index, sizeof(quantity->index));
} }

View file

@ -141,7 +141,6 @@ public:
static bool stream_fullstrings; static bool stream_fullstrings;
protected: protected:
void _init();
void _copy(const amount_t& amt); void _copy(const amount_t& amt);
void _dup(); void _dup();
void _resize(precision_t prec); void _resize(precision_t prec);
@ -326,7 +325,7 @@ public:
precision_t precision() const; precision_t precision() const;
amount_t negate() const { amount_t negate() const {
amount_t temp = *this; amount_t temp(*this);
temp.in_place_negate(); temp.in_place_negate();
return temp; return temp;
} }
@ -575,6 +574,7 @@ public:
void parse(const string& str, flags_t flags = 0) { void parse(const string& str, flags_t flags = 0) {
std::istringstream stream(str); std::istringstream stream(str);
parse(stream, flags); parse(stream, flags);
assert(stream.eof());
} }
static void parse_conversion(const string& larger_str, static void parse_conversion(const string& larger_str,
@ -616,12 +616,17 @@ public:
* an input stream into a buffer. It advances the pointer passed in * an input stream into a buffer. It advances the pointer passed in
* to the end of the deserialized amount. * to the end of the deserialized amount.
* *
* write(ostream) writes an amount to an output stream in a compact * write(ostream, [bool]) writes an amount to an output stream in a
* binary format. * compact binary format. If the second parameter is true,
* quantities with multiple reference counts will be written in an
* optimized fashion. NOTE: This form of usage is valid only for
* the binary journal writer, it should not be used otherwise, as it
* has strict requirements for reading that only the binary reader
* knows about.
*/ */
void read(std::istream& in); void read(std::istream& in);
void read(char *& data); void read(const char *& data);
void write(std::ostream& out) const; void write(std::ostream& out, bool optimize = false) const;
/** /**
* Debugging methods. There are two methods defined to help with * Debugging methods. There are two methods defined to help with
@ -691,6 +696,8 @@ inline bool amount_t::operator==(const amount_t& amt) const {
} }
inline amount_t amount_t::round() const { inline amount_t amount_t::round() const {
if (! quantity)
throw_(amount_error, "Cannot round an uninitialized amount");
if (! has_commodity()) if (! has_commodity())
return *this; return *this;
return round(commodity().precision()); return round(commodity().precision());

View file

@ -68,7 +68,7 @@ void read_binary_bool(std::istream& in, bool& num)
read_binary_guard(in, 0x2006); read_binary_guard(in, 0x2006);
} }
void read_binary_bool(char *& data, bool& num) void read_binary_bool(const char *& data, bool& num)
{ {
read_binary_guard(data, 0x2005); read_binary_guard(data, 0x2005);
unsigned char val = *((unsigned char *) data); unsigned char val = *((unsigned char *) data);
@ -104,7 +104,7 @@ void read_binary_string(std::istream& in, string& str)
read_binary_guard(in, 0x3002); read_binary_guard(in, 0x3002);
} }
void read_binary_string(char *& data, string& str) void read_binary_string(const char *& data, string& str)
{ {
read_binary_guard(data, 0x3001); read_binary_guard(data, 0x3001);
@ -127,7 +127,7 @@ void read_binary_string(char *& data, string& str)
read_binary_guard(data, 0x3002); read_binary_guard(data, 0x3002);
} }
void read_binary_string(char *& data, string * str) void read_binary_string(const char *& data, string * str)
{ {
read_binary_guard(data, 0x3001); read_binary_guard(data, 0x3001);
@ -151,7 +151,7 @@ void read_binary_string(char *& data, string * str)
} }
#if 0 #if 0
inline void read_binary_value(char *& data, value_t& val) inline void read_binary_value(const char *& data, value_t& val)
{ {
val.type = static_cast<value_t::type_t>(read_binary_long<int>(data)); val.type = static_cast<value_t::type_t>(read_binary_long<int>(data));
@ -176,7 +176,7 @@ inline void read_binary_value(char *& data, value_t& val)
} }
} }
inline void read_binary_mask(char *& data, mask_t *& mask) inline void read_binary_mask(const char *& data, mask_t *& mask)
{ {
bool exclude; bool exclude;
read_binary_number(data, exclude); read_binary_number(data, exclude);
@ -187,7 +187,7 @@ inline void read_binary_mask(char *& data, mask_t *& mask)
mask->exclude = exclude; mask->exclude = exclude;
} }
inline void read_binary_transaction(char *& data, transaction_t * xact) inline void read_binary_transaction(const char *& data, transaction_t * xact)
{ {
read_binary_number(data, xact->_date); read_binary_number(data, xact->_date);
read_binary_number(data, xact->_date_eff); read_binary_number(data, xact->_date_eff);
@ -230,7 +230,7 @@ inline void read_binary_transaction(char *& data, transaction_t * xact)
xact->data = NULL; xact->data = NULL;
} }
inline void read_binary_entry_base(char *& data, entry_base_t * entry, inline void read_binary_entry_base(const char *& data, entry_base_t * entry,
transaction_t *& xact_pool, bool& finalize) transaction_t *& xact_pool, bool& finalize)
{ {
read_binary_long(data, entry->src_idx); read_binary_long(data, entry->src_idx);
@ -253,7 +253,7 @@ inline void read_binary_entry_base(char *& data, entry_base_t * entry,
} }
} }
inline void read_binary_entry(char *& data, entry_t * entry, inline void read_binary_entry(const char *& data, entry_t * entry,
transaction_t *& xact_pool, bool& finalize) transaction_t *& xact_pool, bool& finalize)
{ {
entry->data = entry->data =
@ -266,7 +266,7 @@ inline void read_binary_entry(char *& data, entry_t * entry,
read_binary_string(data, &entry->payee); read_binary_string(data, &entry->payee);
} }
inline void read_binary_auto_entry(char *& data, auto_entry_t * entry, inline void read_binary_auto_entry(const char *& data, auto_entry_t * entry,
transaction_t *& xact_pool) transaction_t *& xact_pool)
{ {
bool ignore; bool ignore;
@ -277,7 +277,7 @@ inline void read_binary_auto_entry(char *& data, auto_entry_t * entry,
entry->predicate.parse(pred_str); entry->predicate.parse(pred_str);
} }
inline void read_binary_period_entry(char *& data, period_entry_t * entry, inline void read_binary_period_entry(const char *& data, period_entry_t * entry,
transaction_t *& xact_pool, bool& finalize) transaction_t *& xact_pool, bool& finalize)
{ {
read_binary_entry_base(data, entry, xact_pool, finalize); read_binary_entry_base(data, entry, xact_pool, finalize);
@ -286,7 +286,7 @@ inline void read_binary_period_entry(char *& data, period_entry_t * entry,
entry->period.parse(stream); entry->period.parse(stream);
} }
inline commodity_base_t * read_binary_commodity_base(char *& data) inline commodity_base_t * read_binary_commodity_base(const char *& data)
{ {
commodity_base_t * commodity = new commodity_base_t; commodity_base_t * commodity = new commodity_base_t;
*base_commodities_next++ = commodity; *base_commodities_next++ = commodity;
@ -300,7 +300,7 @@ inline commodity_base_t * read_binary_commodity_base(char *& data)
return commodity; return commodity;
} }
inline void read_binary_commodity_base_extra(char *& data, inline void read_binary_commodity_base_extra(const char *& data,
commodity_t::ident_t ident) commodity_t::ident_t ident)
{ {
commodity_base_t * commodity = base_commodities[ident]; commodity_base_t * commodity = base_commodities[ident];
@ -339,7 +339,7 @@ inline void read_binary_commodity_base_extra(char *& data,
} }
} }
inline commodity_t * read_binary_commodity(char *& data) inline commodity_t * read_binary_commodity(const char *& data)
{ {
commodity_t * commodity = new commodity_t; commodity_t * commodity = new commodity_t;
*commodities_next++ = commodity; *commodities_next++ = commodity;
@ -353,7 +353,7 @@ inline commodity_t * read_binary_commodity(char *& data)
return commodity; return commodity;
} }
inline commodity_t * read_binary_commodity_annotated(char *& data) inline commodity_t * read_binary_commodity_annotated(const char *& data)
{ {
annotated_commodity_t * commodity = new annotated_commodity_t; annotated_commodity_t * commodity = new annotated_commodity_t;
*commodities_next++ = commodity; *commodities_next++ = commodity;
@ -381,7 +381,7 @@ inline commodity_t * read_binary_commodity_annotated(char *& data)
} }
inline inline
account_t * read_binary_account(char *& data, journal_t * journal, account_t * read_binary_account(const char *& data, journal_t * journal,
account_t * master = NULL) account_t * master = NULL)
{ {
account_t * acct = new account_t(NULL); account_t * acct = new account_t(NULL);

View file

@ -55,7 +55,7 @@ inline void read_binary_number_nocheck(std::istream& in, T& num) {
} }
template <typename T> template <typename T>
inline void read_binary_number_nocheck(char *& data, T& num) { inline void read_binary_number_nocheck(const char *& data, T& num) {
num = *((T *) data); num = *((T *) data);
data += sizeof(T); data += sizeof(T);
} }
@ -68,7 +68,7 @@ inline T read_binary_number_nocheck(std::istream& in) {
} }
template <typename T> template <typename T>
inline T read_binary_number_nocheck(char *& data) { inline T read_binary_number_nocheck(const char *& data) {
T num; T num;
read_binary_number_nocheck(data, num); read_binary_number_nocheck(data, num);
return num; return num;
@ -90,7 +90,7 @@ inline void read_binary_number(std::istream& in, T& num) {
} }
template <typename T> template <typename T>
inline void read_binary_number(char *& data, T& num) { inline void read_binary_number(const char *& data, T& num) {
read_binary_guard(data, 0x2003); read_binary_guard(data, 0x2003);
num = *((T *) data); num = *((T *) data);
data += sizeof(T); data += sizeof(T);
@ -105,14 +105,14 @@ inline T read_binary_number(std::istream& in) {
} }
template <typename T> template <typename T>
inline T read_binary_number(char *& data) { inline T read_binary_number(const char *& data) {
T num; T num;
read_binary_number(data, num); read_binary_number(data, num);
return num; return num;
} }
void read_binary_bool(std::istream& in, bool& num); void read_binary_bool(std::istream& in, bool& num);
void read_binary_bool(char *& data, bool& num); void read_binary_bool(const char *& data, bool& num);
inline bool read_binary_bool(std::istream& in) { inline bool read_binary_bool(std::istream& in) {
bool num; bool num;
@ -120,7 +120,7 @@ inline bool read_binary_bool(std::istream& in) {
return num; return num;
} }
inline bool read_binary_bool(char *& data) { inline bool read_binary_bool(const char *& data) {
bool num; bool num;
read_binary_bool(data, num); read_binary_bool(data, num);
return num; return num;
@ -156,7 +156,7 @@ void read_binary_long(std::istream& in, T& num)
} }
template <typename T> template <typename T>
void read_binary_long(char *& data, T& num) void read_binary_long(const char *& data, T& num)
{ {
read_binary_guard(data, 0x2001); read_binary_guard(data, 0x2001);
@ -192,15 +192,15 @@ inline T read_binary_long(std::istream& in) {
} }
template <typename T> template <typename T>
inline T read_binary_long(char *& data) { inline T read_binary_long(const char *& data) {
T num; T num;
read_binary_long(data, num); read_binary_long(data, num);
return num; return num;
} }
void read_binary_string(std::istream& in, string& str); void read_binary_string(std::istream& in, string& str);
void read_binary_string(char *& data, string& str); void read_binary_string(const char *& data, string& str);
void read_binary_string(char *& data, string * str); void read_binary_string(const char *& data, string * str);
inline string read_binary_string(std::istream& in) { inline string read_binary_string(std::istream& in) {
string temp; string temp;
@ -208,7 +208,7 @@ inline string read_binary_string(std::istream& in) {
return temp; return temp;
} }
inline string read_binary_string(char *& data) { inline string read_binary_string(const char *& data) {
string temp; string temp;
read_binary_string(data, temp); read_binary_string(data, temp);
return temp; return temp;

View file

@ -30,16 +30,51 @@ void AmountTestCase::testParser()
amount_t x5(x4); amount_t x5(x4);
amount_t x6(x4); amount_t x6(x4);
amount_t x7(x4); amount_t x7(x4);
amount_t x8("$123.456"); amount_t x8("$123.45");
amount_t x9(x8); amount_t x9(x8);
amount_t x10(x8); amount_t x10(x8);
amount_t x11(x8); amount_t x11(x8);
amount_t x12("$100"); amount_t x12("$100");
assertEqual(amount_t::precision_t(3), x12.commodity().precision()); assertEqual(amount_t::precision_t(2), x12.commodity().precision());
string buf("$100...");
std::istringstream input(buf);
amount_t x13;
x13.parse(input);
assertEqual(x12, x13);
amount_t x14;
assertThrow(x14.parse("DM"), amount_error);
amount_t x15("$1.000.000,00"); // parsing this switches us to European
amount_t x16("$2000");
assertEqual(string("$2.000,00"), x16.to_string());
x16.parse("$2000,00");
assertEqual(string("$2.000,00"), x16.to_string());
// Since European-ness is an additive quality, we must switch back
// to American-ness manually
x15.commodity().drop_flags(COMMODITY_STYLE_EUROPEAN);
amount_t x17("$1,000,000.00"); // parsing this switches back to American
amount_t x18("$2000");
assertEqual(string("$2,000.00"), x18.to_string());
x18.parse("$2,000");
assertEqual(string("$2,000.00"), x18.to_string());
assertEqual(x15, x17);
amount_t x19("EUR 1000");
amount_t x20("EUR 1000");
assertEqual(string("EUR 1000"), x19.to_string());
assertEqual(string("EUR 1000"), x20.to_string());
x1.parse("$100.0000", AMOUNT_PARSE_NO_MIGRATE); x1.parse("$100.0000", AMOUNT_PARSE_NO_MIGRATE);
assertEqual(amount_t::precision_t(3), x12.commodity().precision()); assertEqual(amount_t::precision_t(2), x12.commodity().precision());
assertEqual(x1.commodity(), x12.commodity()); assertEqual(x1.commodity(), x12.commodity());
assertEqual(x1, x12); assertEqual(x1, x12);
@ -71,18 +106,18 @@ void AmountTestCase::testParser()
x11.parse("$100.00", AMOUNT_PARSE_NO_MIGRATE | AMOUNT_PARSE_NO_REDUCE); x11.parse("$100.00", AMOUNT_PARSE_NO_MIGRATE | AMOUNT_PARSE_NO_REDUCE);
assertEqual(x11, x12); assertEqual(x11, x12);
assertTrue(x0.valid()); assertValid(x0);
assertTrue(x1.valid()); assertValid(x1);
assertTrue(x2.valid()); assertValid(x2);
assertTrue(x3.valid()); assertValid(x3);
assertTrue(x5.valid()); assertValid(x5);
assertTrue(x6.valid()); assertValid(x6);
assertTrue(x7.valid()); assertValid(x7);
assertTrue(x8.valid()); assertValid(x8);
assertTrue(x9.valid()); assertValid(x9);
assertTrue(x10.valid()); assertValid(x10);
assertTrue(x11.valid()); assertValid(x11);
assertTrue(x12.valid()); assertValid(x12);
} }
void AmountTestCase::testConstructors() void AmountTestCase::testConstructors()
@ -111,17 +146,17 @@ void AmountTestCase::testConstructors()
assertEqual(x10, x3); assertEqual(x10, x3);
assertEqual(x10, x9); assertEqual(x10, x9);
assertTrue(x0.valid()); assertValid(x0);
assertTrue(x1.valid()); assertValid(x1);
assertTrue(x2.valid()); assertValid(x2);
assertTrue(x3.valid()); assertValid(x3);
assertTrue(x5.valid()); assertValid(x5);
assertTrue(x6.valid()); assertValid(x6);
assertTrue(x7.valid()); assertValid(x7);
assertTrue(x8.valid()); assertValid(x8);
assertTrue(x9.valid()); assertValid(x9);
assertTrue(x10.valid()); assertValid(x10);
assertTrue(x11.valid()); assertValid(x11);
} }
void AmountTestCase::testCommodityConstructors() void AmountTestCase::testCommodityConstructors()
@ -215,16 +250,16 @@ void AmountTestCase::testAssignment()
assertTrue(x0.is_null()); assertTrue(x0.is_null());
assertTrue(x1.is_null()); assertTrue(x1.is_null());
assertTrue(x0.valid()); assertValid(x0);
assertTrue(x1.valid()); assertValid(x1);
assertTrue(x2.valid()); assertValid(x2);
assertTrue(x3.valid()); assertValid(x3);
assertTrue(x5.valid()); assertValid(x5);
assertTrue(x6.valid()); assertValid(x6);
assertTrue(x7.valid()); assertValid(x7);
assertTrue(x8.valid()); assertValid(x8);
assertTrue(x9.valid()); assertValid(x9);
assertTrue(x10.valid()); assertValid(x10);
} }
void AmountTestCase::testCommodityAssignment() void AmountTestCase::testCommodityAssignment()
@ -290,12 +325,19 @@ void AmountTestCase::testEquality()
assertTrue(x4 == x5); assertTrue(x4 == x5);
assertTrue(x4 == x6); assertTrue(x4 == x6);
assertTrue(x1.valid()); assertTrue(x1 == 123456L);
assertTrue(x2.valid()); assertTrue(123456L == x1);
assertTrue(x3.valid()); assertTrue(x1 == 123456UL);
assertTrue(x4.valid()); assertTrue(123456UL == x1);
assertTrue(x5.valid()); assertTrue(x1 == 123456.0);
assertTrue(x6.valid()); assertTrue(123456.0 == x1);
assertValid(x1);
assertValid(x2);
assertValid(x3);
assertValid(x4);
assertValid(x5);
assertValid(x6);
} }
void AmountTestCase::testCommodityEquality() void AmountTestCase::testCommodityEquality()
@ -367,19 +409,19 @@ void AmountTestCase::testComparisons()
assertTrue(x3 < x4); assertTrue(x3 < x4);
assertTrue(x1 < 100L); assertTrue(x1 < 100L);
assertTrue(x1 < 100UL);
assertTrue(x1 < 100.0);
assertTrue(100L > x1); assertTrue(100L > x1);
assertTrue(x1 < 100UL);
assertTrue(100UL > x1); assertTrue(100UL > x1);
assertTrue(x1 < 100.0);
assertTrue(100.0 > x1); assertTrue(100.0 > x1);
assertTrue(x0.valid()); assertValid(x0);
assertTrue(x1.valid()); assertValid(x1);
assertTrue(x2.valid()); assertValid(x2);
assertTrue(x3.valid()); assertValid(x3);
assertTrue(x4.valid()); assertValid(x4);
assertTrue(x5.valid()); assertValid(x5);
assertTrue(x6.valid()); assertValid(x6);
} }
void AmountTestCase::testCommodityComparisons() void AmountTestCase::testCommodityComparisons()
@ -390,6 +432,7 @@ void AmountTestCase::testCommodityComparisons()
amount_t x4(internalAmount("$123.4544")); amount_t x4(internalAmount("$123.4544"));
amount_t x5("$-123.45"); amount_t x5("$-123.45");
amount_t x6("$123.45"); amount_t x6("$123.45");
amount_t x7("DM 123.45");
assertTrue(x1 > x3); assertTrue(x1 > x3);
assertTrue(x3 <= x5); assertTrue(x3 <= x5);
@ -398,6 +441,8 @@ void AmountTestCase::testCommodityComparisons()
assertFalse(x3 == x5); assertFalse(x3 == x5);
assertTrue(x3 < x1); assertTrue(x3 < x1);
assertTrue(x3 < x4); assertTrue(x3 < x4);
assertFalse(x6 == x7);
assertThrow(x6 < x7, amount_error);
assertValid(x1); assertValid(x1);
assertValid(x2); assertValid(x2);
@ -409,6 +454,7 @@ void AmountTestCase::testCommodityComparisons()
void AmountTestCase::testIntegerAddition() void AmountTestCase::testIntegerAddition()
{ {
amount_t x0;
amount_t x1(123L); amount_t x1(123L);
amount_t y1(456L); amount_t y1(456L);
@ -425,9 +471,10 @@ void AmountTestCase::testIntegerAddition()
assertEqual(amount_t("246913578246913578246913578"), x4 + x4); assertEqual(amount_t("246913578246913578246913578"), x4 + x4);
assertTrue(x1.valid()); assertValid(x0);
assertTrue(y1.valid()); assertValid(x1);
assertTrue(x4.valid()); assertValid(y1);
assertValid(x4);
} }
void AmountTestCase::testFractionalAddition() void AmountTestCase::testFractionalAddition()
@ -450,9 +497,9 @@ void AmountTestCase::testFractionalAddition()
assertEqual(amount_t("246913578246913578.246913578246913578"), x2 + x2); assertEqual(amount_t("246913578246913578.246913578246913578"), x2 + x2);
assertTrue(x1.valid()); assertValid(x1);
assertTrue(y1.valid()); assertValid(y1);
assertTrue(x2.valid()); assertValid(x2);
} }
void AmountTestCase::testCommodityAddition() void AmountTestCase::testCommodityAddition()
@ -474,6 +521,8 @@ void AmountTestCase::testCommodityAddition()
assertEqual(string("$246.91"), (x1 + x2).to_string()); assertEqual(string("$246.91"), (x1 + x2).to_string());
assertThrow(x1 + x0, amount_error); assertThrow(x1 + x0, amount_error);
assertThrow(x0 + x1, amount_error);
assertThrow(x0 + x0, amount_error);
assertThrow(x1 + x3, amount_error); assertThrow(x1 + x3, amount_error);
assertThrow(x1 + x4, amount_error); assertThrow(x1 + x4, amount_error);
assertThrow(x1 + x5, amount_error); assertThrow(x1 + x5, amount_error);
@ -530,10 +579,10 @@ void AmountTestCase::testIntegerSubtraction()
assertEqual(amount_t("123456789115218063137220803"), x4 - y4); assertEqual(amount_t("123456789115218063137220803"), x4 - y4);
assertEqual(amount_t("-123456789115218063137220803"), y4 - x4); assertEqual(amount_t("-123456789115218063137220803"), y4 - x4);
assertTrue(x1.valid()); assertValid(x1);
assertTrue(y1.valid()); assertValid(y1);
assertTrue(x4.valid()); assertValid(x4);
assertTrue(y4.valid()); assertValid(y4);
} }
void AmountTestCase::testFractionalSubtraction() void AmountTestCase::testFractionalSubtraction()
@ -557,10 +606,10 @@ void AmountTestCase::testFractionalSubtraction()
assertEqual(amount_t("123446916777474329.874482549545456789"), x2 - y2); assertEqual(amount_t("123446916777474329.874482549545456789"), x2 - y2);
assertEqual(amount_t("-123446916777474329.874482549545456789"), y2 - x2); assertEqual(amount_t("-123446916777474329.874482549545456789"), y2 - x2);
assertTrue(x1.valid()); assertValid(x1);
assertTrue(y1.valid()); assertValid(y1);
assertTrue(x2.valid()); assertValid(x2);
assertTrue(y2.valid()); assertValid(y2);
} }
void AmountTestCase::testCommoditySubtraction() void AmountTestCase::testCommoditySubtraction()
@ -586,6 +635,8 @@ void AmountTestCase::testCommoditySubtraction()
assertEqual(string("$-0.01"), (x1 - x2).to_string()); assertEqual(string("$-0.01"), (x1 - x2).to_string());
assertThrow(x1 - x0, amount_error); assertThrow(x1 - x0, amount_error);
assertThrow(x0 - x1, amount_error);
assertThrow(x0 - x0, amount_error);
assertThrow(x1 - x3, amount_error); assertThrow(x1 - x3, amount_error);
assertThrow(x1 - x4, amount_error); assertThrow(x1 - x4, amount_error);
assertThrow(x1 - x5, amount_error); assertThrow(x1 - x5, amount_error);
@ -672,9 +723,9 @@ void AmountTestCase::testIntegerMultiplication()
assertEqual(amount_t("15241578780673678546105778281054720515622620750190521"), assertEqual(amount_t("15241578780673678546105778281054720515622620750190521"),
x4 * x4); x4 * x4);
assertTrue(x1.valid()); assertValid(x1);
assertTrue(y1.valid()); assertValid(y1);
assertTrue(x4.valid()); assertValid(x4);
} }
void AmountTestCase::testFractionalMultiplication() void AmountTestCase::testFractionalMultiplication()
@ -709,13 +760,14 @@ void AmountTestCase::testFractionalMultiplication()
assertEqual(amount_t("15241578780673678546105778311537878.046486820281054720515622620750190521"), assertEqual(amount_t("15241578780673678546105778311537878.046486820281054720515622620750190521"),
x2 * x2); x2 * x2);
assertTrue(x1.valid()); assertValid(x1);
assertTrue(y1.valid()); assertValid(y1);
assertTrue(x2.valid()); assertValid(x2);
} }
void AmountTestCase::testCommodityMultiplication() void AmountTestCase::testCommodityMultiplication()
{ {
amount_t x0;
amount_t x1("$123.12"); amount_t x1("$123.12");
amount_t y1("$456.45"); amount_t y1("$456.45");
amount_t x2(internalAmount("$123.456789")); amount_t x2(internalAmount("$123.456789"));
@ -741,6 +793,9 @@ void AmountTestCase::testCommodityMultiplication()
assertEqual(string("$15200.00"), (x1 * x2).to_string()); assertEqual(string("$15200.00"), (x1 * x2).to_string());
assertEqual(string("$15199.99986168"), (x2 * x1).to_string()); assertEqual(string("$15199.99986168"), (x2 * x1).to_string());
assertThrow(x1 * x0, amount_error);
assertThrow(x0 * x1, amount_error);
assertThrow(x0 * x0, amount_error);
assertThrow(x1 * x3, amount_error); assertThrow(x1 * x3, amount_error);
assertThrow(x1 * x4, amount_error); assertThrow(x1 * x4, amount_error);
assertThrow(x1 * x5, amount_error); assertThrow(x1 * x5, amount_error);
@ -799,10 +854,10 @@ void AmountTestCase::testIntegerDivision()
assertEqual(amount_t(1L), x4 / x4); assertEqual(amount_t(1L), x4 / x4);
assertEqual(amount_t("2204585520061728377204585.517857"), x4 / y4); assertEqual(amount_t("2204585520061728377204585.517857"), x4 / y4);
assertTrue(x1.valid()); assertValid(x1);
assertTrue(y1.valid()); assertValid(y1);
assertTrue(x4.valid()); assertValid(x4);
assertTrue(y4.valid()); assertValid(y4);
} }
void AmountTestCase::testFractionalDivision() void AmountTestCase::testFractionalDivision()
@ -838,14 +893,15 @@ void AmountTestCase::testFractionalDivision()
assertEqual(amount_t(1.0), x4 / x4); assertEqual(amount_t(1.0), x4 / x4);
assertEqual(amount_t("21739560323910.7554497273748437197344556164046"), x4 / y4); assertEqual(amount_t("21739560323910.7554497273748437197344556164046"), x4 / y4);
assertTrue(x1.valid()); assertValid(x1);
assertTrue(y1.valid()); assertValid(y1);
assertTrue(x4.valid()); assertValid(x4);
assertTrue(y4.valid()); assertValid(y4);
} }
void AmountTestCase::testCommodityDivision() void AmountTestCase::testCommodityDivision()
{ {
amount_t x0;
amount_t x1("$123.12"); amount_t x1("$123.12");
amount_t y1("$456.45"); amount_t y1("$456.45");
amount_t x2(internalAmount("$123.456789")); amount_t x2(internalAmount("$123.456789"));
@ -871,6 +927,9 @@ void AmountTestCase::testCommodityDivision()
assertEqual(string("$1.00"), (x1 / x2).to_string()); assertEqual(string("$1.00"), (x1 / x2).to_string());
assertEqual(string("$1.00273545321637426901"), (x2 / x1).to_string()); assertEqual(string("$1.00273545321637426901"), (x2 / x1).to_string());
assertThrow(x1 / x0, amount_error);
assertThrow(x0 / x1, amount_error);
assertThrow(x0 / x0, amount_error);
assertThrow(x1 / x3, amount_error); assertThrow(x1 / x3, amount_error);
assertThrow(x1 / x4, amount_error); assertThrow(x1 / x4, amount_error);
assertThrow(x1 / x5, amount_error); assertThrow(x1 / x5, amount_error);
@ -905,6 +964,7 @@ void AmountTestCase::testCommodityDivision()
void AmountTestCase::testNegation() void AmountTestCase::testNegation()
{ {
amount_t x0;
amount_t x1(-123456L); amount_t x1(-123456L);
amount_t x3(-123.456); amount_t x3(-123.456);
amount_t x5("-123456"); amount_t x5("-123456");
@ -913,6 +973,7 @@ void AmountTestCase::testNegation()
amount_t x8(string("-123.456")); amount_t x8(string("-123.456"));
amount_t x9(- x3); amount_t x9(- x3);
assertThrow(x0.negate(), amount_error);
assertEqual(x5, x1); assertEqual(x5, x1);
assertEqual(x7, x1); assertEqual(x7, x1);
assertEqual(x6, x3); assertEqual(x6, x3);
@ -924,14 +985,14 @@ void AmountTestCase::testNegation()
assertEqual(x3, x10); assertEqual(x3, x10);
assertTrue(x1.valid()); assertValid(x1);
assertTrue(x3.valid()); assertValid(x3);
assertTrue(x5.valid()); assertValid(x5);
assertTrue(x6.valid()); assertValid(x6);
assertTrue(x7.valid()); assertValid(x7);
assertTrue(x8.valid()); assertValid(x8);
assertTrue(x9.valid()); assertValid(x9);
assertTrue(x10.valid()); assertValid(x10);
} }
void AmountTestCase::testCommodityNegation() void AmountTestCase::testCommodityNegation()
@ -999,9 +1060,9 @@ void AmountTestCase::testAbs()
assertEqual(amount_t(1234L), x1.abs()); assertEqual(amount_t(1234L), x1.abs());
assertEqual(amount_t(1234L), x2.abs()); assertEqual(amount_t(1234L), x2.abs());
assertTrue(x0.valid()); assertValid(x0);
assertTrue(x1.valid()); assertValid(x1);
assertTrue(x2.valid()); assertValid(x2);
} }
void AmountTestCase::testCommodityAbs() void AmountTestCase::testCommodityAbs()
@ -1018,15 +1079,45 @@ void AmountTestCase::testCommodityAbs()
void AmountTestCase::testFractionalRound() void AmountTestCase::testFractionalRound()
{ {
amount_t x0;
amount_t x1("1234.567890"); amount_t x1("1234.567890");
assertEqual(amount_t("1234.56789"), x1.round(6)); assertThrow(x0.precision(), amount_error);
assertEqual(amount_t("1234.56789"), x1.round(5)); assertThrow(x0.round(), amount_error);
assertEqual(amount_t("1234.5679"), x1.round(4)); assertThrow(x0.round(2), amount_error);
assertEqual(amount_t("1234.568"), x1.round(3)); assertThrow(x0.unround(), amount_error);
assertEqual(amount_t("1234.57"), x1.round(2)); assertEqual(amount_t::precision_t(6), x1.precision());
assertEqual(amount_t("1234.6"), x1.round(1));
assertEqual(amount_t("1235"), x1.round(0)); amount_t x1b(x1.unround());
assertEqual(x1b.precision(), x1b.unround().precision());
amount_t y7(x1.round(7));
amount_t y6(x1.round(6));
amount_t y5(x1.round(5));
amount_t y4(x1.round(4));
amount_t y3(x1.round(3));
amount_t y2(x1.round(2));
amount_t y1(x1.round(1));
amount_t y0(x1.round(0));
assertEqual(amount_t::precision_t(6), y7.precision());
assertEqual(amount_t::precision_t(6), y6.precision());
assertEqual(amount_t::precision_t(5), y5.precision());
assertEqual(amount_t::precision_t(4), y4.precision());
assertEqual(amount_t::precision_t(3), y3.precision());
assertEqual(amount_t::precision_t(2), y2.precision());
assertEqual(amount_t::precision_t(1), y1.precision());
assertEqual(amount_t::precision_t(0), y0.precision());
assertEqual(amount_t("1234.56789"), y7);
assertEqual(amount_t("1234.56789"), y6);
assertEqual(amount_t("1234.56789"), y5);
assertEqual(amount_t("1234.5679"), y4);
assertEqual(amount_t("1234.568"), y3);
assertEqual(amount_t("1234.57"), y2);
assertEqual(amount_t("1234.6"), y1);
assertEqual(amount_t("1235"), y0);
amount_t x2("9876.543210"); amount_t x2("9876.543210");
@ -1064,11 +1155,11 @@ void AmountTestCase::testFractionalRound()
x5.round(37)); x5.round(37));
assertEqual(amount_t(0L), x5.round(36)); assertEqual(amount_t(0L), x5.round(36));
assertTrue(x1.valid()); assertValid(x1);
assertTrue(x2.valid()); assertValid(x2);
assertTrue(x3.valid()); assertValid(x3);
assertTrue(x4.valid()); assertValid(x4);
assertTrue(x5.valid()); assertValid(x5);
} }
void AmountTestCase::testCommodityRound() void AmountTestCase::testCommodityRound()
@ -1153,6 +1244,7 @@ void AmountTestCase::testCommodityDisplayRound()
void AmountTestCase::testReduction() void AmountTestCase::testReduction()
{ {
amount_t x0;
amount_t x1("60s"); amount_t x1("60s");
amount_t x2("600s"); amount_t x2("600s");
amount_t x3("6000s"); amount_t x3("6000s");
@ -1166,9 +1258,12 @@ void AmountTestCase::testReduction()
amount_t x11("1000h"); // 3600000s amount_t x11("1000h"); // 3600000s
amount_t x12("10000h"); // 36000000s amount_t x12("10000h"); // 36000000s
assertThrow(x0.reduce(), amount_error);
assertThrow(x0.unreduce(), amount_error);
assertEqual(x2, x5); assertEqual(x2, x5);
assertEqual(x3, x6); assertEqual(x3, x6);
assertEqual(x4, x10); assertEqual(x4, x10);
assertEqual(string("100.0h"), x4.unreduce().to_string());
} }
void AmountTestCase::testSign() void AmountTestCase::testSign()
@ -1185,11 +1280,11 @@ void AmountTestCase::testSign()
assertTrue(x3.sign() > 0); assertTrue(x3.sign() > 0);
assertTrue(x4.sign() < 0); assertTrue(x4.sign() < 0);
assertTrue(x0.valid()); assertValid(x0);
assertTrue(x1.valid()); assertValid(x1);
assertTrue(x2.valid()); assertValid(x2);
assertTrue(x3.valid()); assertValid(x3);
assertTrue(x4.valid()); assertValid(x4);
} }
void AmountTestCase::testCommoditySign() void AmountTestCase::testCommoditySign()
@ -1221,9 +1316,9 @@ void AmountTestCase::testTruth()
assertTrue(x1); assertTrue(x1);
assertTrue(x2); assertTrue(x2);
assertTrue(x0.valid()); assertValid(x0);
assertTrue(x1.valid()); assertValid(x1);
assertTrue(x2.valid()); assertValid(x2);
} }
void AmountTestCase::testCommodityTruth() void AmountTestCase::testCommodityTruth()
@ -1256,8 +1351,8 @@ void AmountTestCase::testForZero()
assertFalse(x1.is_zero()); assertFalse(x1.is_zero());
assertFalse(x1.is_realzero()); assertFalse(x1.is_realzero());
assertTrue(x0.valid()); assertValid(x0);
assertTrue(x1.valid()); assertValid(x1);
} }
void AmountTestCase::testCommodityForZero() void AmountTestCase::testCommodityForZero()
@ -1273,27 +1368,35 @@ void AmountTestCase::testCommodityForZero()
void AmountTestCase::testIntegerConversion() void AmountTestCase::testIntegerConversion()
{ {
amount_t x0;
amount_t x1(123456L); amount_t x1(123456L);
amount_t x2("12345682348723487324");
assertThrow(x0.to_long(), amount_error);
assertThrow(x0.to_double(), amount_error);
assertFalse(x2.fits_in_long());
assertEqual(123456L, x1.to_long()); assertEqual(123456L, x1.to_long());
assertEqual(123456.0, x1.to_double()); assertEqual(123456.0, x1.to_double());
assertEqual(string("123456"), x1.to_string()); assertEqual(string("123456"), x1.to_string());
assertEqual(string("123456"), x1.quantity_string()); assertEqual(string("123456"), x1.quantity_string());
assertTrue(x1.valid()); assertValid(x1);
} }
void AmountTestCase::testFractionalConversion() void AmountTestCase::testFractionalConversion()
{ {
amount_t x1(1234.56); amount_t x1(1234.56);
amount_t x2("1234.5683787634678348734");
assertThrow(x1.to_long(), amount_error); // loses precision assertThrow(x1.to_long(), amount_error); // loses precision
assertThrow(x2.to_double(), amount_error); // loses precision
assertFalse(x2.fits_in_double());
assertEqual(1234L, x1.to_long(true)); assertEqual(1234L, x1.to_long(true));
assertEqual(1234.56, x1.to_double()); assertEqual(1234.56, x1.to_double());
assertEqual(string("1234.56"), x1.to_string()); assertEqual(string("1234.56"), x1.to_string());
assertEqual(string("1234.56"), x1.quantity_string()); assertEqual(string("1234.56"), x1.quantity_string());
assertTrue(x1.valid()); assertValid(x1);
} }
void AmountTestCase::testCommodityConversion() void AmountTestCase::testCommodityConversion()
@ -1327,8 +1430,8 @@ void AmountTestCase::testPrinting()
bufstr.str()); bufstr.str());
} }
assertTrue(x0.valid()); assertValid(x0);
assertTrue(x1.valid()); assertValid(x1);
} }
void AmountTestCase::testCommodityPrinting() void AmountTestCase::testCommodityPrinting()
@ -1362,3 +1465,80 @@ void AmountTestCase::testCommodityPrinting()
assertValid(x1); assertValid(x1);
assertValid(x2); assertValid(x2);
} }
void AmountTestCase::testSerialization()
{
amount_t x0;
amount_t x1("$8,192.34");
amount_t x2("8192.34");
amount_t x3("8192.34");
amount_t x4("-8192.34");
amount_t x5(x4);
// Force x3's pointer to actually be set to null_commodity
x3.set_commodity(*x3.current_pool->null_commodity);
std::string buf;
{
std::ostringstream storage;
assertThrow(x0.write(storage), amount_error);
x1.write(storage);
x2.write(storage);
x3.write(storage);
x4.write(storage);
x5.write(storage);
buf = storage.str();
}
amount_t x1b;
amount_t x2b;
amount_t x3b;
amount_t x4b;
amount_t x5b;
{
std::istringstream storage(buf);
x1b.read(storage);
x2b.read(storage);
x3b.read(storage);
x4b.read(storage);
x5b.read(storage);
}
assertEqual(x1, x1b);
assertEqual(x2, x2b);
assertEqual(x3, x3b);
assertEqual(x4, x4b);
const char * ptr = buf.c_str();
amount_t x1c;
amount_t x2c;
amount_t x3c;
amount_t x4c;
amount_t x5c;
{
x1c.read(ptr);
x2c.read(ptr);
x3c.read(ptr);
x4c.read(ptr);
x5c.read(ptr);
}
assertEqual(x1, x1b);
assertEqual(x2, x2b);
assertEqual(x3, x3b);
assertEqual(x4, x4b);
assertValid(x1);
assertValid(x2);
assertValid(x3);
assertValid(x4);
assertValid(x1b);
assertValid(x2b);
assertValid(x3b);
assertValid(x4b);
assertValid(x1c);
assertValid(x2c);
assertValid(x3c);
assertValid(x4c);
}

View file

@ -47,6 +47,7 @@ class AmountTestCase : public CPPUNIT_NS::TestCase
CPPUNIT_TEST(testCommodityConversion); CPPUNIT_TEST(testCommodityConversion);
CPPUNIT_TEST(testPrinting); CPPUNIT_TEST(testPrinting);
CPPUNIT_TEST(testCommodityPrinting); CPPUNIT_TEST(testCommodityPrinting);
CPPUNIT_TEST(testSerialization);
CPPUNIT_TEST_SUITE_END(); CPPUNIT_TEST_SUITE_END();
@ -99,6 +100,7 @@ public:
void testCommodityConversion(); void testCommodityConversion();
void testPrinting(); void testPrinting();
void testCommodityPrinting(); void testCommodityPrinting();
void testSerialization();
private: private:
AmountTestCase(const AmountTestCase &copy); AmountTestCase(const AmountTestCase &copy);

View file

@ -19,8 +19,12 @@ void CommodityTestCase::testPriceHistory()
ptime apr15_07 = parse_datetime("2007/04/15 13:00:00"); ptime apr15_07 = parse_datetime("2007/04/15 13:00:00");
// jww (2007-04-17): tbd // jww (2007-04-17): tbd
amount_t x0;
amount_t x1("100.10 AAPL"); amount_t x1("100.10 AAPL");
assertThrow(x0.value(), amount_error);
assertFalse(x1.value());
// Commodities cannot be constructed by themselves, since a great // Commodities cannot be constructed by themselves, since a great
// deal of their state depends on how they were seen to be used. // deal of their state depends on how they were seen to be used.
commodity_t& aapl(x1.commodity()); commodity_t& aapl(x1.commodity());