#include #include "RDValue.h" #include "RDProps.h" #include "Invariant.h" #include "StreamOps.h" #include #include #include #include #include #include #include #include #include using namespace RDKit; template void testLimits() { BOOST_LOG(rdErrorLog) << "Test limits" << std::endl; // check numeric limits { RDValue v(std::numeric_limits::min()); std::cerr << "min: " << std::numeric_limits::min() << " " << rdvalue_cast(v) << std::endl; CHECK_INVARIANT(rdvalue_cast(v) == std::numeric_limits::min(), "bad min"); CHECK_INVARIANT( rdvalue_cast(RDValue(v)) == std::numeric_limits::min(), "bad min"); v = std::numeric_limits::max(); CHECK_INVARIANT(rdvalue_cast(v) == std::numeric_limits::max(), "bad max"); CHECK_INVARIANT( rdvalue_cast(RDValue(v)) == std::numeric_limits::max(), "bad max"); } { RDValue v(std::numeric_limits::max()); CHECK_INVARIANT(rdvalue_cast(v) == std::numeric_limits::max(), "bad max"); RDValue vv(v); CHECK_INVARIANT(rdvalue_cast(vv) == std::numeric_limits::max(), "bad max"); v = std::numeric_limits::min(); RDValue vvv(v); CHECK_INVARIANT(rdvalue_cast(v) == std::numeric_limits::min(), "bad min"); CHECK_INVARIANT(rdvalue_cast(vvv) == std::numeric_limits::min(), "bad min"); } BOOST_LOG(rdErrorLog) << "..done" << std::endl; } void testPOD() { BOOST_LOG(rdErrorLog) << "Test POD" << std::endl; testLimits(); testLimits(); testLimits(); testLimits(); testLimits(); BOOST_LOG(rdErrorLog) << "..done" << std::endl; } template void testVector() { T minv = std::numeric_limits::min(); T maxv = std::numeric_limits::max(); std::vector data; data.push_back(minv); data.push_back(maxv); data.push_back(T()); RDValue v(data); CHECK_INVARIANT(rdvalue_cast>(v) == data, "bad vec"); RDValue vv; copy_rdvalue(vv, v); CHECK_INVARIANT(rdvalue_cast>(vv) == data, "bad copy constructor"); RDValue::cleanup_rdvalue(v); // desctructor... RDValue::cleanup_rdvalue(vv); } void testPODVectors() { BOOST_LOG(rdErrorLog) << "Test String Vect" << std::endl; testVector(); testVector(); testVector(); testVector(); testVector(); // stored in anys BOOST_LOG(rdErrorLog) << "..done" << std::endl; } void testStringVect() { BOOST_LOG(rdErrorLog) << "Test String Vect" << std::endl; std::vector vecs; vecs.emplace_back("my"); vecs.emplace_back("dog"); vecs.emplace_back("has"); vecs.emplace_back("fleas"); RDValue v(vecs); CHECK_INVARIANT(rdvalue_cast>(v) == vecs, "bad vect"); RDValue vc; copy_rdvalue(vc, v); CHECK_INVARIANT(rdvalue_cast>(vc) == vecs, "bad vect"); RDValue vv = vecs; RDValue vvc; copy_rdvalue(vvc, vv); CHECK_INVARIANT(rdvalue_cast>(vv) == vecs, "bad vect"); CHECK_INVARIANT(rdvalue_cast>(vvc) == vecs, "bad vect"); RDValue::cleanup_rdvalue(v); // desctructor... RDValue::cleanup_rdvalue(vc); // desctructor... RDValue::cleanup_rdvalue(vv); // desctructor... RDValue::cleanup_rdvalue(vvc); // desctructor... BOOST_LOG(rdErrorLog) << "..done" << std::endl; } void testMapsAndLists() { BOOST_LOG(rdErrorLog) << "Test Maps And Lists" << std::endl; { typedef std::map listtype; listtype m; m["foo"] = 1; m["bar"] = 2; RDValue v(m); CHECK_INVARIANT(rdvalue_cast(v) == m, "bad map cast"); RDValue::cleanup_rdvalue(v); } { std::list m; m.emplace_back("foo"); m.emplace_back("bar"); RDValue v(m); CHECK_INVARIANT(rdvalue_cast>(v) == m, "bad map cast"); RDValue::cleanup_rdvalue(v); } BOOST_LOG(rdErrorLog) << "..done" << std::endl; } void testNaN() { // make a NaN BOOST_LOG(rdErrorLog) << "Test NaN" << std::endl; double nan = sqrt(-1.0); RDValue v(nan); TEST_ASSERT(v.getTag() == RDTypeTag::DoubleTag); CHECK_INVARIANT(std::isnan(rdvalue_cast(v)), "Oops, can't store NaNs!"); RDValue vv(2.0); TEST_ASSERT(rdvalue_is(vv)); TEST_ASSERT(vv.getTag() == RDTypeTag::DoubleTag); BOOST_LOG(rdErrorLog) << "..done" << std::endl; } template std::vector makeVec() { std::vector vec; vec.push_back((T)0); vec.push_back((T)1); vec.push_back((T)2); vec.push_back((T)3); vec.push_back((T)4); vec.push_back((T)5); return vec; } template void testProp(T val) { std::stringstream ss; { RDProps p; p.setProp("foo", val); TEST_ASSERT(streamWriteProps(ss, p)); } { RDProps p2; streamReadProps(ss, p2); TEST_ASSERT(p2.getProp("foo") == val); } }; void testPropertyPickler() { BOOST_LOG(rdErrorLog) << "Test Property Pickler" << std::endl; std::cerr << "== int" << std::endl; testProp(1234); std::cerr << "== double" << std::endl; testProp(1234.); std::cerr << "== float" << std::endl; testProp(1234.0f); std::cerr << "== unsigned int" << std::endl; testProp(1234u); std::cerr << "== bool" << std::endl; testProp(true); std::cerr << "== std::string" << std::endl; testProp( std::string("the quick brown fox jumps over the lazy dog")); testProp(0); testProp(0.); testProp(0.0f); testProp(0u); testProp(false); /* testProp(makeVec()); testProp(makeVec()); testProp(makeVec()); testProp(makeVec()); { std::vector v; v.push_back("a"); v.push_back("b"); v.push_back("c"); v.push_back("d"); v.push_back("e"); testProp(v); } */ BOOST_LOG(rdErrorLog) << "..done" << std::endl; } void testPickleBinaryString() { BOOST_LOG(rdErrorLog) << "Pickle Binary String" << std::endl; char buf[10]; for (int i = 0; i < 10; ++i) { buf[i] = (char)i; } std::string str(buf, 10); std::stringstream ss; { RDProps p; p.setProp("foo", str); TEST_ASSERT(streamWriteProps(ss, p)); } { RDProps p2; streamReadProps(ss, p2); TEST_ASSERT(p2.getProp("foo") == str); } BOOST_LOG(rdErrorLog) << "..done" << std::endl; } void testIntConversions() { RDProps p; p.setProp("foo", 1); p.getProp("foo"); p.getProp("foo"); p.getProp("foo"); p.getProp("foo"); p.setProp("foo", 1); p.getProp("foo"); p.setProp("foo", 1); p.getProp("foo"); p.getProp("foo"); p.getProp("foo"); p.getProp("foo"); // Test that min/max values of smaller types do not under/overflow p.setProp("foo", 0); p.getProp("foo"); p.getProp("foo"); p.setProp("foo", 255); p.getProp("foo"); p.setProp("foo", 65535); p.getProp("foo"); p.setProp("foo", -128); p.getProp("foo"); p.setProp("foo", -32768); p.getProp("foo"); p.setProp("foo", 127); p.getProp("foo"); p.setProp("foo", 32767); p.getProp("foo"); // Test some overflows p.setProp("foo", 32767 + 1); try { p.getProp("foo"); // should fail TEST_ASSERT(0); } catch (boost::numeric::positive_overflow&) { } try { p.getProp("foo"); // should fail TEST_ASSERT(0); } catch (boost::numeric::positive_overflow&) { } try { p.getProp("foo"); // should fail TEST_ASSERT(0); } catch (boost::numeric::positive_overflow&) { } p.setProp("foo", 65535 + 1); try { p.getProp("foo"); // should fail TEST_ASSERT(0); } catch (boost::numeric::positive_overflow&) { } p.setProp("foo", -1); try { p.getProp("foo"); // should fail TEST_ASSERT(0); } catch (boost::numeric::negative_overflow&) { } p.getProp("foo"); // should pass try { p.getProp("foo"); // should fail TEST_ASSERT(0); } catch (boost::numeric::negative_overflow&) { } } int main() { std::cerr << "-- running tests -- " << std::endl; testPOD(); testPODVectors(); testStringVect(); testNaN(); testPropertyPickler(); testPickleBinaryString(); testIntConversions(); }