Unit test for Python are now auto-generated from the C++ tests.
This commit is contained in:
parent
3020f0f851
commit
e851c02d27
17 changed files with 475 additions and 1629 deletions
36
Makefile.am
36
Makefile.am
|
|
@ -437,10 +437,42 @@ extra_tests_SOURCES = \
|
|||
extra_tests_CPPFLAGS = -I$(srcdir)/test $(lib_cppflags)
|
||||
extra_tests_LDADD = $(math_tests_LDADD) libledger_extra.la
|
||||
|
||||
all_tests_sources = \
|
||||
$(util_tests_SOURCES) \
|
||||
$(math_tests_SOURCES) \
|
||||
$(expr_tests_SOURCES) \
|
||||
$(data_tests_SOURCES) \
|
||||
$(parse_tests_SOURCES) \
|
||||
$(report_tests_SOURCES) \
|
||||
$(extra_tests_SOURCES)
|
||||
|
||||
EXTRA_DIST += test/python
|
||||
|
||||
PyUnitTests_SOURCES = test/__init__.py test/PyUnitTests.py test/UnitTests.py
|
||||
|
||||
all_py_tests_sources = \
|
||||
$(patsubst test/unit/%.cc,test/python/%.py, \
|
||||
$(filter test/unit/t_%.cc,$(all_tests_sources)))
|
||||
|
||||
test/python/%.py: test/unit/%.cc test/convert.py
|
||||
$(PYTHON) $(srcdir)/test/convert.py $< $@
|
||||
|
||||
test/python/UnitTests.py: $(all_py_tests_sources)
|
||||
@echo "from unittest import TextTestRunner, TestSuite" > $@
|
||||
@for file in $$(ls $(srcdir)/test/unit/*.cc); do \
|
||||
base=$$(basename $$file); \
|
||||
base=$$(echo $$base | sed 's/\.cc//'); \
|
||||
echo "import $$base" >> $@; \
|
||||
done
|
||||
@echo "suites = [" >> $@
|
||||
@for file in $$(ls $(srcdir)/test/unit/*.cc); do \
|
||||
base=$$(basename $$file); \
|
||||
base=$$(echo $$base | sed 's/\.cc//'); \
|
||||
echo " $$base.suite()," >> $@; \
|
||||
done
|
||||
@echo "]" >> $@
|
||||
@echo "TextTestRunner().run(TestSuite(suites))" >> $@
|
||||
|
||||
ESC_python=`echo "$(PYTHON)" | sed 's/\//\\\\\//g'`
|
||||
ESC_srcdir=`echo "$(srcdir)" | sed 's/\//\\\\\//g'`
|
||||
ESC_builddir=`echo "$(top_builddir)" | sed 's/\//\\\\\//g'`
|
||||
|
|
@ -448,7 +480,9 @@ ESC_distdir=`echo "$(distdir)" | sed 's/\//\\\\\//g'`
|
|||
|
||||
# jww (2007-05-10): This rule will not be triggered on systems that
|
||||
# define an EXEEXT.
|
||||
PyUnitTests: $(srcdir)/test/PyUnitTests.py
|
||||
PyUnitTests: $(srcdir)/test/PyUnitTests.py test/python/UnitTests.py
|
||||
@echo all_test_sources: $(all_tests_sources)
|
||||
@echo all_py_test_sources: $(all_py_tests_sources)
|
||||
cat $(srcdir)/test/PyUnitTests.py \
|
||||
| sed "s/%python%/$(ESC_python)/" \
|
||||
| sed "s/%srcdir%/$(ESC_srcdir)/g" \
|
||||
|
|
|
|||
|
|
@ -97,13 +97,23 @@ void py_parse_str_2(amount_t& amount, const string& str, unsigned char flags) {
|
|||
amount.parse(str, flags);
|
||||
}
|
||||
|
||||
void py_print(amount_t& amount, object out) {
|
||||
if (PyFile_Check(out.ptr())) {
|
||||
pyofstream outstr(reinterpret_cast<PyFileObject *>(out.ptr()));
|
||||
amount.print(outstr);
|
||||
} else {
|
||||
PyErr_SetString(PyExc_IOError,
|
||||
"Argument to amount.print_(file) is not a file object");
|
||||
}
|
||||
}
|
||||
|
||||
void py_read_1(amount_t& amount, object in) {
|
||||
if (PyFile_Check(in.ptr())) {
|
||||
pyifstream instr(reinterpret_cast<PyFileObject *>(in.ptr()));
|
||||
amount.read(instr);
|
||||
} else {
|
||||
PyErr_SetString(PyExc_IOError,
|
||||
"Argument to amount.parse(file) is not a file object");
|
||||
"Argument to amount.read(file) is not a file object");
|
||||
}
|
||||
}
|
||||
void py_read_2(amount_t& amount, const std::string& str) {
|
||||
|
|
@ -111,6 +121,25 @@ void py_read_2(amount_t& amount, const std::string& str) {
|
|||
amount.read(p);
|
||||
}
|
||||
|
||||
void py_write_xml_1(amount_t& amount, object out) {
|
||||
if (PyFile_Check(out.ptr())) {
|
||||
pyofstream outstr(reinterpret_cast<PyFileObject *>(out.ptr()));
|
||||
amount.write_xml(outstr);
|
||||
} else {
|
||||
PyErr_SetString(PyExc_IOError,
|
||||
"Argument to amount.write_xml(file) is not a file object");
|
||||
}
|
||||
}
|
||||
void py_write_xml_2(amount_t& amount, object out, const int depth) {
|
||||
if (PyFile_Check(out.ptr())) {
|
||||
pyofstream outstr(reinterpret_cast<PyFileObject *>(out.ptr()));
|
||||
amount.write_xml(outstr, depth);
|
||||
} else {
|
||||
PyErr_SetString(PyExc_IOError,
|
||||
"Argument to amount.write_xml(file, depth) is not a file object");
|
||||
}
|
||||
}
|
||||
|
||||
#define EXC_TRANSLATOR(type) \
|
||||
void exc_translate_ ## type(const type& err) { \
|
||||
PyErr_SetString(PyExc_ArithmeticError, err.what()); \
|
||||
|
|
@ -124,12 +153,10 @@ void export_amount()
|
|||
scope().attr("AMOUNT_PARSE_NO_REDUCE") = AMOUNT_PARSE_NO_REDUCE;
|
||||
|
||||
class_< amount_t > ("Amount")
|
||||
#if 0
|
||||
.def("initialize", &amount_t::initialize)
|
||||
.staticmethod("initialize")
|
||||
.def("shutdown", &amount_t::shutdown)
|
||||
.staticmethod("shutdown")
|
||||
#endif
|
||||
|
||||
.add_static_property("current_pool",
|
||||
make_getter(&amount_t::current_pool,
|
||||
|
|
@ -266,7 +293,7 @@ internal precision.")
|
|||
.def(double() / self)
|
||||
#endif
|
||||
|
||||
.add_property("precision", &amount_t::precision)
|
||||
.def("precision", &amount_t::precision)
|
||||
|
||||
.def("negate", &amount_t::negate)
|
||||
.def("in_place_negate", &amount_t::in_place_negate,
|
||||
|
|
@ -317,22 +344,21 @@ internal precision.")
|
|||
#endif
|
||||
.def("fits_in_long", &amount_t::fits_in_long)
|
||||
|
||||
.add_property("quantity_string", &amount_t::quantity_string)
|
||||
.def("quantity_string", &amount_t::quantity_string)
|
||||
|
||||
.add_property("commodity",
|
||||
make_function(&amount_t::commodity,
|
||||
return_value_policy<reference_existing_object>()),
|
||||
make_function(&amount_t::set_commodity,
|
||||
with_custodian_and_ward<1, 2>()))
|
||||
.def("commodity", &amount_t::commodity,
|
||||
return_value_policy<reference_existing_object>())
|
||||
.def("set_commodity", &amount_t::set_commodity,
|
||||
with_custodian_and_ward<1, 2>())
|
||||
|
||||
.def("has_commodity", &amount_t::has_commodity)
|
||||
.def("clear_commodity", &amount_t::clear_commodity)
|
||||
.add_property("number", &amount_t::number)
|
||||
.def("number", &amount_t::number)
|
||||
|
||||
.def("annotate", &amount_t::annotate)
|
||||
.def("is_annotated", &amount_t::is_annotated)
|
||||
#if 0
|
||||
.add_property("annotation", &amount_t::annotation)
|
||||
.def("annotation", &amount_t::annotation)
|
||||
#endif
|
||||
.def("strip_annotations", &amount_t::strip_annotations)
|
||||
|
||||
|
|
@ -344,10 +370,18 @@ internal precision.")
|
|||
.def("parse_conversion", &amount_t::parse_conversion)
|
||||
.staticmethod("parse_conversion")
|
||||
|
||||
.def("print_", py_print)
|
||||
|
||||
.def("read", py_read_1)
|
||||
.def("read", py_read_2)
|
||||
.def("write", &amount_t::write)
|
||||
|
||||
.def("read_xml", &amount_t::read_xml)
|
||||
.def("write_xml", py_write_xml_1)
|
||||
.def("write_xml", py_write_xml_2)
|
||||
|
||||
.def("dump", &amount_t::dump)
|
||||
|
||||
.def("valid", &amount_t::valid)
|
||||
;
|
||||
|
||||
|
|
|
|||
|
|
@ -40,6 +40,13 @@ namespace ledger {
|
|||
|
||||
using namespace boost::python;
|
||||
|
||||
void py_add_price(commodity_t& commodity,
|
||||
const datetime_t& date,
|
||||
const amount_t& price)
|
||||
{
|
||||
commodity.add_price(date, price);
|
||||
}
|
||||
|
||||
void export_commodity()
|
||||
{
|
||||
scope().attr("COMMODITY_STYLE_DEFAULTS") = COMMODITY_STYLE_DEFAULTS;
|
||||
|
|
@ -57,7 +64,9 @@ void export_commodity()
|
|||
|
||||
.def("drop_flags", &commodity_t::drop_flags)
|
||||
|
||||
.add_property("precision", &commodity_t::precision)
|
||||
.def("add_price", py_add_price)
|
||||
|
||||
.def("precision", &commodity_t::precision)
|
||||
;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -32,12 +32,6 @@
|
|||
#include "pyinterp.h"
|
||||
#include "pyutils.h"
|
||||
|
||||
#include <boost/cast.hpp>
|
||||
#include <boost/python/module.hpp>
|
||||
#include <boost/python/def.hpp>
|
||||
#include <boost/python/to_python_converter.hpp>
|
||||
|
||||
#include <Python.h>
|
||||
#include <datetime.h>
|
||||
|
||||
// jww (2007-05-04): Convert time duration objects to PyDelta
|
||||
|
|
@ -121,12 +115,26 @@ struct datetime_from_python
|
|||
typedef register_python_conversion<datetime_t, datetime_to_python, datetime_from_python>
|
||||
datetime_python_conversion;
|
||||
|
||||
datetime_t py_parse_datetime(const string& str) {
|
||||
return parse_datetime(str);
|
||||
}
|
||||
|
||||
date_t py_parse_date(const string& str) {
|
||||
return parse_date(str);
|
||||
}
|
||||
|
||||
void export_times()
|
||||
{
|
||||
date_python_conversion();
|
||||
datetime_python_conversion();
|
||||
date_python_conversion();
|
||||
|
||||
register_optional_to_python<datetime_t>();
|
||||
register_optional_to_python<date_t>();
|
||||
|
||||
scope().attr("parse_datetime") = &py_parse_datetime;
|
||||
scope().attr("parse_date") = &py_parse_date;
|
||||
scope().attr("current_time") = current_time;
|
||||
scope().attr("current_date") = current_date;
|
||||
}
|
||||
|
||||
} // namespace ledger
|
||||
|
|
|
|||
|
|
@ -3,4 +3,4 @@
|
|||
PYTHONPATH="%builddir%":"%srcdir%":$PYTHONPATH \
|
||||
LD_LIBRARY_PATH="%builddir%/.libs":$LD_LIBRARY_PATH \
|
||||
DYLD_LIBRARY_PATH="%builddir%/.libs":$DYLD_LIBRARY_PATH \
|
||||
%python% "%srcdir%"/test/UnitTests.py
|
||||
%python% "%builddir%"/test/python/UnitTests.py
|
||||
|
|
|
|||
|
|
@ -1,9 +0,0 @@
|
|||
from unittest import TextTestRunner, TestSuite
|
||||
|
||||
import test.python.math.t_amount as t_amount
|
||||
|
||||
suites = [
|
||||
t_amount.suite(),
|
||||
]
|
||||
|
||||
TextTestRunner().run(TestSuite(suites))
|
||||
174
test/convert.py
Executable file
174
test/convert.py
Executable file
|
|
@ -0,0 +1,174 @@
|
|||
#!/usr/bin/env python
|
||||
|
||||
# convert.py: This script converts a C++ Ledger unit test into an equivalent
|
||||
# Python unit test.
|
||||
#
|
||||
# Copyright (c) 2003-2009, John Wiegley. All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are
|
||||
# met:
|
||||
#
|
||||
# - Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
#
|
||||
# - Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution.
|
||||
#
|
||||
# - Neither the name of New Artisans LLC nor the names of its
|
||||
# contributors may be used to endorse or promote products derived from
|
||||
# this software without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
import re
|
||||
import sys
|
||||
import os
|
||||
|
||||
source = os.path.abspath(sys.argv[1])
|
||||
base = os.path.splitext(source)[0]
|
||||
target = os.path.abspath(sys.argv[2])
|
||||
|
||||
dirname = os.path.dirname(target)
|
||||
if not os.path.isdir(dirname):
|
||||
os.makedirs(dirname)
|
||||
|
||||
fd = open(source, "r")
|
||||
fo = open(target, "w")
|
||||
|
||||
fo.write('''# -*- coding: utf-8 -*-
|
||||
|
||||
import unittest
|
||||
import exceptions
|
||||
import operator
|
||||
|
||||
from ledger import *
|
||||
from StringIO import *
|
||||
from datetime import *
|
||||
|
||||
internalAmount = Amount.exact
|
||||
|
||||
class %sTestCase(unittest.TestCase):
|
||||
testSession = None
|
||||
|
||||
def assertValid(self, amt):
|
||||
self.assertTrue(amt.valid())''' % os.path.basename(base))
|
||||
|
||||
not_for_python = 0
|
||||
|
||||
for line in fd.readlines():
|
||||
if re.match('^#ifndef NOT_FOR_PYTHON', line):
|
||||
not_for_python += 1
|
||||
continue
|
||||
elif not_for_python > 0:
|
||||
if re.match('^#endif // NOT_FOR_PYTHON', line):
|
||||
not_for_python -= 1
|
||||
continue
|
||||
|
||||
if re.match('^(using|CPP|[#{}/])', line):
|
||||
continue
|
||||
if re.match('^\s+[{}]\s+$', line):
|
||||
continue
|
||||
|
||||
if not re.search('assert', line):
|
||||
match = re.match('void [^:]+::(test[^(]+|setUp|tearDown)\(\)', line)
|
||||
if match:
|
||||
fo.write(' def %s(self):\n' % match.group(1))
|
||||
continue
|
||||
|
||||
match = re.search(' ([a-z:_<>]+?)&?\s+([a-z0-9_]+)(\((.+?)\))?;', line)
|
||||
if match:
|
||||
if match.group(1) != "std::string":
|
||||
line = ' %s = %s(%s)\n' % (match.group(2), match.group(1),
|
||||
match.group(4) or "")
|
||||
else:
|
||||
line = ''
|
||||
|
||||
match = re.search(' ([a-z:_<>]+?)&?\s+([a-z0-9]+)\s*=\s*([^(]+);', line)
|
||||
if match:
|
||||
line = ' %s = %s(%s)\n' % (match.group(2), match.group(1),
|
||||
match.group(3))
|
||||
|
||||
match = re.search(' ([a-z:_<>]+?)\s+([a-z0-9]+)\s*=\s*(.+?)$', line)
|
||||
if match:
|
||||
line = ' %s = %s\n' % (match.group(2), match.group(3))
|
||||
|
||||
line = re.sub('CPPUNIT_ASSERT', 'self.assertTrue', line)
|
||||
line = re.sub('assertValid', 'self.assertValid', line)
|
||||
line = re.sub('assertTrue', 'self.assertTrue', line)
|
||||
line = re.sub('assertFalse', 'self.assertFalse', line)
|
||||
line = re.sub('assertNotEqual', 'self.assertNotEqual', line)
|
||||
line = re.sub('assertEqual', 'self.assertEqual', line)
|
||||
line = re.sub('assertThrow\(([^,]+), ([^,)]+?)\)',
|
||||
'self.assertRaises(\\2, lambda: \\1)', line)
|
||||
#line = re.sub('optional<([^>]+?)>', '\\1', line)
|
||||
line = re.sub('amount_t::precision_t\(([^)]+?)\)', '\\1', line)
|
||||
|
||||
# Determine this list automatically by scanning the class_ lines in
|
||||
# python/*.cc
|
||||
line = re.sub('amount_t::', 'Amount.', line)
|
||||
line = re.sub('commodity_t\(([^)]+?)\)', '\\1', line)
|
||||
line = re.sub('commodity_t::', 'Commodity.', line)
|
||||
line = re.sub('balance_t::', 'Balance.', line)
|
||||
line = re.sub('balance_pair_t::', 'BalancePair.', line)
|
||||
line = re.sub('value_t::', 'Value.', line)
|
||||
|
||||
line = re.sub('amount_t', 'Amount', line)
|
||||
line = re.sub('commodity_t', 'Commodity', line)
|
||||
line = re.sub('balance_t', 'Balance', line)
|
||||
line = re.sub('balance_pair_t', 'BalancePair', line)
|
||||
line = re.sub('value_t', 'Value', line)
|
||||
|
||||
line = re.sub('ledger::', '', line)
|
||||
line = re.sub('std::istringstream', 'StringIO', line)
|
||||
line = re.sub('std::ostringstream', 'StringIO', line)
|
||||
line = re.sub('set_session_context\(&session\)',
|
||||
'self.testSession = session()\n set_session_context(self.testSession)', line)
|
||||
line = re.sub('set_session_context\(\)',
|
||||
'set_session_context()\n self.testSession = None', line)
|
||||
line = re.sub('([a-z_]+?)_t\b', '\\1', line)
|
||||
line = re.sub('std::string\(([^)]+?)\)', '\\1', line)
|
||||
line = re.sub('string\(([^)]+?)\)', '\\1', line)
|
||||
line = re.sub('\.print\(([^)]+?)\)', '.print_(\\1)', line)
|
||||
line = re.sub('true', 'True', line)
|
||||
line = re.sub('false', 'False', line)
|
||||
line = re.sub('([0-9]+)[FL]', '\\1', line)
|
||||
line = re.sub('([0-9]+)UL', '\\1L', line)
|
||||
line = re.sub(';', '', line)
|
||||
line = re.sub('//', '#', line)
|
||||
line = re.sub('->', '.', line)
|
||||
line = re.sub('(\s+|\()(\S+?) \? (.+?) : (.+?)\)',
|
||||
'\\1\\3 if \\2 else \\4)', line)
|
||||
line = re.sub('if \((.+?)\)( {)?$', 'if \\1:', line)
|
||||
line = re.sub('(} )?else( {)?$', 'else:', line)
|
||||
|
||||
line = re.sub('amount_error', 'exceptions.ArithmeticError', line)
|
||||
|
||||
match = re.match('^ ', line)
|
||||
if match:
|
||||
fo.write(' ' + line)
|
||||
else:
|
||||
fo.write(line)
|
||||
|
||||
fo.write('''
|
||||
|
||||
def suite():
|
||||
return unittest.TestLoader().loadTestsFromTestCase(%sTestCase)
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
''' % os.path.basename(base))
|
||||
|
||||
fo.close()
|
||||
fd.close()
|
||||
File diff suppressed because it is too large
Load diff
|
|
@ -42,11 +42,13 @@ void AmountTestCase::testParser()
|
|||
|
||||
assertEqual(amount_t::precision_t(2), x12.commodity().precision());
|
||||
|
||||
#ifndef NOT_FOR_PYTHON
|
||||
string buf("$100...");
|
||||
std::istringstream input(buf);
|
||||
amount_t x13;
|
||||
x13.parse(input);
|
||||
assertEqual(x12, x13);
|
||||
#endif // NOT_FOR_PYTHON
|
||||
|
||||
amount_t x14;
|
||||
assertThrow(x14.parse("DM"), amount_error);
|
||||
|
|
@ -210,6 +212,7 @@ void AmountTestCase::testCommodityConstructors()
|
|||
assertValid(x10);
|
||||
}
|
||||
|
||||
#ifndef NOT_FOR_PYTHON
|
||||
void AmountTestCase::testAssignment()
|
||||
{
|
||||
amount_t x0;
|
||||
|
|
@ -315,6 +318,7 @@ void AmountTestCase::testCommodityAssignment()
|
|||
assertValid(x9);
|
||||
assertValid(x10);
|
||||
}
|
||||
#endif // NOT_FOR_PYTHON
|
||||
|
||||
void AmountTestCase::testEquality()
|
||||
{
|
||||
|
|
@ -350,35 +354,24 @@ void AmountTestCase::testEquality()
|
|||
void AmountTestCase::testCommodityEquality()
|
||||
{
|
||||
amount_t x0;
|
||||
amount_t x1;
|
||||
amount_t x2;
|
||||
amount_t x3;
|
||||
amount_t x4;
|
||||
amount_t x5;
|
||||
amount_t x6;
|
||||
amount_t x7;
|
||||
amount_t x8;
|
||||
amount_t x9;
|
||||
amount_t x10;
|
||||
|
||||
x1 = "$123.45";
|
||||
x2 = "-$123.45";
|
||||
x3 = "$-123.45";
|
||||
x4 = "DM 123.45";
|
||||
x5 = "-DM 123.45";
|
||||
x6 = "DM -123.45";
|
||||
x7 = "123.45 euro";
|
||||
x8 = "-123.45 euro";
|
||||
x9 = "123.45€";
|
||||
x10 = "-123.45€";
|
||||
amount_t x1("$123.45");
|
||||
amount_t x2("-$123.45");
|
||||
amount_t x3("$-123.45");
|
||||
amount_t x4("DM 123.45");
|
||||
amount_t x5("-DM 123.45");
|
||||
amount_t x6("DM -123.45");
|
||||
amount_t x7("123.45 euro");
|
||||
amount_t x8("-123.45 euro");
|
||||
amount_t x9("123.45€");
|
||||
amount_t x10("-123.45€");
|
||||
|
||||
assertTrue(x0.is_null());
|
||||
assertThrow(x0.is_zero(), amount_error);
|
||||
assertThrow(x0.is_realzero(), amount_error);
|
||||
assertThrow(assert(x0.sign() == 0), amount_error);
|
||||
assertThrow(assert(x0.compare(x1) < 0), amount_error);
|
||||
assertThrow(assert(x0.compare(x2) > 0), amount_error);
|
||||
assertThrow(assert(x0.compare(x0) == 0), amount_error);
|
||||
assertThrow(x0.sign() == 0, amount_error);
|
||||
assertThrow(x0.compare(x1) < 0, amount_error);
|
||||
assertThrow(x0.compare(x2) > 0, amount_error);
|
||||
assertThrow(x0.compare(x0) == 0, amount_error);
|
||||
|
||||
assertTrue(x1 != x2);
|
||||
assertTrue(x1 != x4);
|
||||
|
|
@ -1335,7 +1328,7 @@ void AmountTestCase::testTruth()
|
|||
amount_t x1("1234");
|
||||
amount_t x2("1234.56");
|
||||
|
||||
assertThrow(assert(x0 ? 1 : 0), amount_error);
|
||||
assertThrow(x0 ? 1 : 0, amount_error);
|
||||
|
||||
assertTrue(x1);
|
||||
assertTrue(x2);
|
||||
|
|
@ -1442,24 +1435,24 @@ void AmountTestCase::testCommodityConversion()
|
|||
assertValid(x1);
|
||||
}
|
||||
|
||||
#ifndef NOT_FOR_PYTHON
|
||||
void AmountTestCase::testPrinting()
|
||||
{
|
||||
amount_t x0;
|
||||
amount_t x1("982340823.380238098235098235098235098");
|
||||
|
||||
#if 0
|
||||
{
|
||||
std::ostringstream bufstr;
|
||||
assertThrow(bufstr << x0, amount_error);
|
||||
std::ostringstream bufstr;
|
||||
x0.print(bufstr);
|
||||
assertEqual(std::string("<null>"), bufstr.str());
|
||||
}
|
||||
#endif
|
||||
|
||||
{
|
||||
std::ostringstream bufstr;
|
||||
bufstr << x1;
|
||||
std::ostringstream bufstr;
|
||||
x1.print(bufstr);
|
||||
|
||||
assertEqual(std::string("982340823.380238098235098235098235098"),
|
||||
bufstr.str());
|
||||
assertEqual(std::string("982340823.380238098235098235098235098"),
|
||||
bufstr.str());
|
||||
}
|
||||
|
||||
assertValid(x0);
|
||||
|
|
@ -1472,26 +1465,26 @@ void AmountTestCase::testCommodityPrinting()
|
|||
amount_t x2("$982340823.38");
|
||||
|
||||
{
|
||||
std::ostringstream bufstr;
|
||||
bufstr << x1;
|
||||
std::ostringstream bufstr;
|
||||
x1.print(bufstr);
|
||||
|
||||
assertEqual(std::string("$982340823.386238098235098235098235098"),
|
||||
bufstr.str());
|
||||
assertEqual(std::string("$982340823.386238098235098235098235098"),
|
||||
bufstr.str());
|
||||
}
|
||||
|
||||
{
|
||||
std::ostringstream bufstr;
|
||||
bufstr << (x1 * x2).to_string();
|
||||
std::ostringstream bufstr;
|
||||
(x1 * x2).print(bufstr);
|
||||
|
||||
assertEqual(std::string("$964993493285024293.18099172508158508135413499124"),
|
||||
bufstr.str());
|
||||
assertEqual(std::string("$964993493285024293.18099172508158508135413499124"),
|
||||
bufstr.str());
|
||||
}
|
||||
|
||||
{
|
||||
std::ostringstream bufstr;
|
||||
bufstr << (x2 * x1).to_string();
|
||||
std::ostringstream bufstr;
|
||||
(x2 * x1).print(bufstr);
|
||||
|
||||
assertEqual(std::string("$964993493285024293.18"), bufstr.str());
|
||||
assertEqual(std::string("$964993493285024293.18"), bufstr.str());
|
||||
}
|
||||
|
||||
assertValid(x1);
|
||||
|
|
@ -1512,14 +1505,14 @@ void AmountTestCase::testSerialization()
|
|||
|
||||
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();
|
||||
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;
|
||||
|
|
@ -1528,12 +1521,12 @@ void AmountTestCase::testSerialization()
|
|||
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);
|
||||
std::istringstream storage(buf);
|
||||
x1b.read(storage);
|
||||
x2b.read(storage);
|
||||
x3b.read(storage);
|
||||
x4b.read(storage);
|
||||
x5b.read(storage);
|
||||
}
|
||||
|
||||
assertEqual(x1, x1b);
|
||||
|
|
@ -1541,6 +1534,7 @@ void AmountTestCase::testSerialization()
|
|||
assertEqual(x3, x3b);
|
||||
assertEqual(x4, x4b);
|
||||
|
||||
#ifndef NOT_FOR_PYTHON
|
||||
const char * ptr = buf.c_str();
|
||||
|
||||
amount_t x1c;
|
||||
|
|
@ -1549,17 +1543,18 @@ void AmountTestCase::testSerialization()
|
|||
amount_t x4c;
|
||||
amount_t x5c;
|
||||
{
|
||||
x1c.read(ptr);
|
||||
x2c.read(ptr);
|
||||
x3c.read(ptr);
|
||||
x4c.read(ptr);
|
||||
x5c.read(ptr);
|
||||
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);
|
||||
#endif // NOT_FOR_PYTHON
|
||||
|
||||
assertValid(x1);
|
||||
assertValid(x2);
|
||||
|
|
@ -1574,3 +1569,14 @@ void AmountTestCase::testSerialization()
|
|||
assertValid(x3c);
|
||||
assertValid(x4c);
|
||||
}
|
||||
|
||||
void AmountTestCase::testXmlSerialization()
|
||||
{
|
||||
amount_t x1("$8,192.34");
|
||||
|
||||
std::ostringstream storage;
|
||||
x1.write_xml(storage);
|
||||
|
||||
assertEqual(std::string("<amount>\n <commodity flags=\"PT\">\n <symbol>$</symbol>\n </commodity>\n <quantity>8192.34</quantity>\n</amount>\n"), storage.str());
|
||||
}
|
||||
#endif // NOT_FOR_PYTHON
|
||||
|
|
|
|||
|
|
@ -48,6 +48,7 @@ class AmountTestCase : public CPPUNIT_NS::TestCase
|
|||
CPPUNIT_TEST(testPrinting);
|
||||
CPPUNIT_TEST(testCommodityPrinting);
|
||||
CPPUNIT_TEST(testSerialization);
|
||||
CPPUNIT_TEST(testXmlSerialization);
|
||||
|
||||
CPPUNIT_TEST_SUITE_END();
|
||||
|
||||
|
|
@ -99,6 +100,7 @@ public:
|
|||
void testPrinting();
|
||||
void testCommodityPrinting();
|
||||
void testSerialization();
|
||||
void testXmlSerialization();
|
||||
|
||||
private:
|
||||
AmountTestCase(const AmountTestCase ©);
|
||||
|
|
|
|||
|
|
@ -26,4 +26,5 @@ void BalanceTestCase::tearDown()
|
|||
|
||||
void BalanceTestCase::testConstructors()
|
||||
{
|
||||
int x = 1;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,14 +17,25 @@ void CommodityTestCase::tearDown() {
|
|||
|
||||
void CommodityTestCase::testPriceHistory()
|
||||
{
|
||||
datetime_t jan17_05 = parse_datetime("2005/01/17 00:00:00");
|
||||
datetime_t jan17_06 = parse_datetime("2006/01/17 00:00:00");
|
||||
datetime_t jan17_07 = parse_datetime("2007/01/17 00:00:00");
|
||||
datetime_t feb27_07 = parse_datetime("2007/02/27 18:00:00");
|
||||
datetime_t feb28_07 = parse_datetime("2007/02/28 06:00:00");
|
||||
datetime_t feb28_07sbm = parse_datetime("2007/02/28 11:59:59");
|
||||
datetime_t mar01_07 = parse_datetime("2007/03/01 00:00:00");
|
||||
datetime_t apr15_07 = parse_datetime("2007/04/15 13:00:00");
|
||||
#ifndef NOT_FOR_PYTHON
|
||||
datetime_t jan17_05;
|
||||
datetime_t jan17_06;
|
||||
datetime_t jan17_07;
|
||||
datetime_t feb27_07;
|
||||
datetime_t feb28_07;
|
||||
datetime_t feb28_07sbm;
|
||||
datetime_t mar01_07;
|
||||
datetime_t apr15_07;
|
||||
#endif // NOT_FOR_PYTHON
|
||||
|
||||
jan17_05 = parse_datetime("2005/01/17 00:00:00");
|
||||
jan17_06 = parse_datetime("2006/01/17 00:00:00");
|
||||
jan17_07 = parse_datetime("2007/01/17 00:00:00");
|
||||
feb27_07 = parse_datetime("2007/02/27 18:00:00");
|
||||
feb28_07 = parse_datetime("2007/02/28 06:00:00");
|
||||
feb28_07sbm = parse_datetime("2007/02/28 11:59:59");
|
||||
mar01_07 = parse_datetime("2007/03/01 00:00:00");
|
||||
apr15_07 = parse_datetime("2007/04/15 13:00:00");
|
||||
|
||||
amount_t x0;
|
||||
amount_t x1("100.10 AAPL");
|
||||
|
|
@ -45,15 +56,18 @@ void CommodityTestCase::testPriceHistory()
|
|||
aapl.add_price(jan17_05, amount_t("EUR 23.00"));
|
||||
aapl.add_price(jan17_06, amount_t("CAD 25.00"));
|
||||
|
||||
commodity_t& euro(amount_t("EUR 1.00").commodity());
|
||||
amount_t one_euro("EUR 1.00");
|
||||
commodity_t& euro(one_euro.commodity());
|
||||
|
||||
euro.add_price(feb27_07, amount_t("CAD 1.40"));
|
||||
euro.add_price(jan17_05, amount_t("$0.78"));
|
||||
|
||||
commodity_t& cad(amount_t("CAD 1.00").commodity());
|
||||
amount_t one_cad("CAD 1.00");
|
||||
commodity_t& cad(one_cad.commodity());
|
||||
|
||||
cad.add_price(jan17_06, amount_t("$1.11"));
|
||||
|
||||
#ifndef NOT_FOR_PYTHON
|
||||
optional<amount_t> amt = x1.value(feb28_07sbm);
|
||||
assertTrue(amt);
|
||||
assertEqual(amount_t("$1831.83"), *amt);
|
||||
|
|
@ -76,6 +90,7 @@ void CommodityTestCase::testPriceHistory()
|
|||
amt = x1.value(current_time, cad);
|
||||
assertTrue(amt);
|
||||
assertEqual(amount_t("CAD 3223.22"), *amt);
|
||||
#endif // NOT_FOR_PYTHON
|
||||
|
||||
assertValid(x1);
|
||||
}
|
||||
|
|
@ -83,15 +98,18 @@ void CommodityTestCase::testPriceHistory()
|
|||
void CommodityTestCase::testLots()
|
||||
{
|
||||
// jww (2007-04-17): tbd
|
||||
int x = 1;
|
||||
}
|
||||
|
||||
void CommodityTestCase::testScalingBase()
|
||||
{
|
||||
// jww (2007-04-17): tbd
|
||||
int x = 1;
|
||||
}
|
||||
|
||||
void CommodityTestCase::testReduction()
|
||||
{
|
||||
// jww (2007-04-17): tbd
|
||||
int x = 1;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -9,15 +9,20 @@ CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(ValueExprTestCase, "expr");
|
|||
void ValueExprTestCase::setUp()
|
||||
{
|
||||
amount_t::initialize();
|
||||
#ifndef NOT_FOR_PYTHON
|
||||
expr_t::initialize();
|
||||
#endif // NOT_FOR_PYTHON
|
||||
}
|
||||
|
||||
void ValueExprTestCase::tearDown()
|
||||
{
|
||||
#ifndef NOT_FOR_PYTHON
|
||||
expr_t::shutdown();
|
||||
#endif // NOT_FOR_PYTHON
|
||||
amount_t::shutdown();
|
||||
}
|
||||
|
||||
void ValueExprTestCase::testConstructors()
|
||||
{
|
||||
int x = 1;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,81 +1,109 @@
|
|||
#include "t_times.h"
|
||||
|
||||
#include "utils.h"
|
||||
|
||||
using namespace ledger;
|
||||
|
||||
CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(DateTimeTestCase, "util");
|
||||
|
||||
void DateTimeTestCase::setUp() {}
|
||||
void DateTimeTestCase::tearDown() {}
|
||||
void DateTimeTestCase::setUp() {
|
||||
int x = 1;
|
||||
}
|
||||
void DateTimeTestCase::tearDown() {
|
||||
int x = 1;
|
||||
}
|
||||
|
||||
void DateTimeTestCase::testConstructors()
|
||||
{
|
||||
#if 0
|
||||
std::time_t time_t_now = std::time(NULL);
|
||||
struct tm * moment = std::localtime(&time_t_now);
|
||||
|
||||
#ifndef NOT_FOR_PYTHON
|
||||
std::time_t now = std::time(NULL);
|
||||
struct tm * moment = std::localtime(&now);
|
||||
std::time_t localMoment = std::mktime(moment);
|
||||
#endif // NOT_FOR_PYTHON
|
||||
|
||||
ptime d0;
|
||||
ptime d1(parse_datetime("1990/01/01"));
|
||||
ptime d3(boost::posix_time::from_time_t(localMoment));
|
||||
ptime d4(parse_datetime("2006/12/25"));
|
||||
//ptime d5(parse_datetime("12/25"));
|
||||
ptime d6(parse_datetime("2006.12.25"));
|
||||
//ptime d7(parse_datetime("12.25"));
|
||||
ptime d8(parse_datetime("2006-12-25"));
|
||||
//ptime d9(parse_datetime("12-25"));
|
||||
#if 0
|
||||
ptime d10(parse_datetime("tue"));
|
||||
ptime d11(parse_datetime("tuesday"));
|
||||
ptime d12(parse_datetime("feb"));
|
||||
ptime d13(parse_datetime("february"));
|
||||
ptime d14(parse_datetime("2006"));
|
||||
#endif
|
||||
ptime d15(d3);
|
||||
#ifndef NOT_FOR_PYTHON
|
||||
datetime_t d0;
|
||||
datetime_t d1;
|
||||
datetime_t d3;
|
||||
datetime_t d4;
|
||||
datetime_t d5;
|
||||
datetime_t d6;
|
||||
datetime_t d7;
|
||||
datetime_t d8;
|
||||
datetime_t d9;
|
||||
|
||||
datetime_t d10;
|
||||
datetime_t d11;
|
||||
datetime_t d12;
|
||||
datetime_t d13;
|
||||
datetime_t d14;
|
||||
datetime_t d15;
|
||||
#endif // NOT_FOR_PYTHON
|
||||
|
||||
d1 = parse_datetime("1990/01/01");
|
||||
#ifndef NOT_FOR_PYTHON
|
||||
d3 = boost::posix_time::from_time_t(localMoment);
|
||||
#endif // NOT_FOR_PYTHON
|
||||
d4 = parse_datetime("2006/12/25");
|
||||
d5 = parse_datetime("12/25");
|
||||
d6 = parse_datetime("2006.12.25");
|
||||
d7 = parse_datetime("12.25");
|
||||
d8 = parse_datetime("2006-12-25");
|
||||
d9 = parse_datetime("12-25");
|
||||
|
||||
d10 = parse_datetime("tue");
|
||||
d11 = parse_datetime("tuesday");
|
||||
d12 = parse_datetime("feb");
|
||||
d13 = parse_datetime("february");
|
||||
d14 = parse_datetime("2006");
|
||||
#ifndef NOT_FOR_PYTHON
|
||||
d15 = d3;
|
||||
#endif // NOT_FOR_PYTHON
|
||||
|
||||
#ifndef NOT_FOR_PYTHON
|
||||
assertTrue(d0.is_not_a_date_time());
|
||||
assertFalse(d1.is_not_a_date_time());
|
||||
assertFalse(d4.is_not_a_date_time());
|
||||
#endif // NOT_FOR_PYTHON
|
||||
|
||||
assertTrue(now > d1);
|
||||
//assertTrue(now <= d3);
|
||||
assertTrue(now > d4);
|
||||
assertTrue(current_time > d1);
|
||||
assertTrue(current_time > d4);
|
||||
|
||||
#ifndef NOT_FOR_PYTHON
|
||||
assertEqual(d3, d15);
|
||||
#endif // NOT_FOR_PYTHON
|
||||
assertEqual(d4, d6);
|
||||
assertEqual(d4, d8);
|
||||
//assertEqual(d5, d7);
|
||||
//assertEqual(d5, d9);
|
||||
#if 0
|
||||
assertEqual(d5, d7);
|
||||
assertEqual(d5, d9);
|
||||
assertEqual(d10, d11);
|
||||
assertEqual(d12, d13);
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
assertThrow(parse_datetime("2007/02/29"), datetime_error *);
|
||||
assertThrow(parse_datetime("2007/13/01"), datetime_error *);
|
||||
assertThrow(parse_datetime("2007/00/01"), datetime_error *);
|
||||
assertThrow(parse_datetime("2007/01/00"), datetime_error *);
|
||||
assertThrow(parse_datetime("2007/00/00"), datetime_error *);
|
||||
assertThrow(parse_datetime("2007/05/32"), datetime_error *);
|
||||
#ifndef NOT_FOR_PYTHON
|
||||
assertThrow(parse_datetime("2007/02/29"), boost::gregorian::bad_day_of_month);
|
||||
//assertThrow(parse_datetime("2007/13/01"), datetime_error);
|
||||
//assertThrow(parse_datetime("2007/00/01"), datetime_error);
|
||||
assertThrow(parse_datetime("2007/01/00"), boost::gregorian::bad_day_of_month);
|
||||
//assertThrow(parse_datetime("2007/00/00"), boost::gregorian::bad_day_of_month);
|
||||
//assertThrow(parse_datetime("2007/05/32"), boost::gregorian::bad_day_of_month);
|
||||
|
||||
assertThrow(parse_datetime("2006x/12/25"), datetime_error *);
|
||||
assertThrow(parse_datetime("2006/12x/25"), datetime_error *);
|
||||
//assertThrow(parse_datetime("2006/12/25x"), datetime_error *);
|
||||
assertThrow(parse_datetime("2006x/12/25"), datetime_error);
|
||||
assertThrow(parse_datetime("2006/12x/25"), datetime_error);
|
||||
assertThrow(parse_datetime("2006/12/25x"), datetime_error);
|
||||
|
||||
assertThrow(parse_datetime("feb/12/25"), datetime_error *);
|
||||
assertThrow(parse_datetime("2006/mon/25"), datetime_error *);
|
||||
assertThrow(parse_datetime("2006/12/web"), datetime_error *);
|
||||
assertThrow(parse_datetime("feb/12/25"), datetime_error);
|
||||
assertThrow(parse_datetime("2006/mon/25"), datetime_error);
|
||||
assertThrow(parse_datetime("2006/12/web"), datetime_error);
|
||||
|
||||
assertThrow(parse_datetime("12*25"), datetime_error *);
|
||||
assertThrow(parse_datetime("12*25"), datetime_error);
|
||||
|
||||
assertThrow(parse_datetime("tuf"), datetime_error *);
|
||||
assertThrow(parse_datetime("tufsday"), datetime_error *);
|
||||
assertThrow(parse_datetime("fec"), datetime_error *);
|
||||
assertThrow(parse_datetime("fecruary"), datetime_error *);
|
||||
assertThrow(parse_datetime("207x"), datetime_error *);
|
||||
assertThrow(parse_datetime("hello"), datetime_error *);
|
||||
|
||||
interval_t i1;
|
||||
interval_t i2;
|
||||
#endif
|
||||
assertThrow(parse_datetime("tuf"), datetime_error);
|
||||
assertThrow(parse_datetime("tufsday"), datetime_error);
|
||||
assertThrow(parse_datetime("fec"), datetime_error);
|
||||
assertThrow(parse_datetime("fecruary"), datetime_error);
|
||||
assertThrow(parse_datetime("207x"), datetime_error);
|
||||
assertThrow(parse_datetime("hello"), datetime_error);
|
||||
#endif // NOT_FOR_PYTHON
|
||||
#endif
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,9 +2,14 @@
|
|||
|
||||
CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(UtilitiesTestCase, "util");
|
||||
|
||||
void UtilitiesTestCase::setUp() {}
|
||||
void UtilitiesTestCase::tearDown() {}
|
||||
void UtilitiesTestCase::setUp() {
|
||||
int x = 1;
|
||||
}
|
||||
void UtilitiesTestCase::tearDown() {
|
||||
int x = 1;
|
||||
}
|
||||
|
||||
void UtilitiesTestCase::testConstructors()
|
||||
{
|
||||
int x = 1;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue