#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() { // check numeric limits { RDValue v(std::numeric_limits::min()); std::cerr << "min: " << std::numeric_limits::min() << " " << rdvalue_cast(v) << std::endl; REQUIRE(rdvalue_cast(v) == std::numeric_limits::min()); REQUIRE(rdvalue_cast(RDValue(v)) == std::numeric_limits::min()); v = std::numeric_limits::max(); REQUIRE(rdvalue_cast(v) == std::numeric_limits::max()); REQUIRE(rdvalue_cast(RDValue(v)) == std::numeric_limits::max()); } { RDValue v(std::numeric_limits::max()); REQUIRE(rdvalue_cast(v) == std::numeric_limits::max()); RDValue vv(v); REQUIRE(rdvalue_cast(vv) == std::numeric_limits::max()); v = std::numeric_limits::min(); RDValue vvv(v); REQUIRE(rdvalue_cast(v) == std::numeric_limits::min()); REQUIRE(rdvalue_cast(vvv) == std::numeric_limits::min()); } } TEST_CASE("testLimits") { { RDValue v(std::numeric_limits::min()); REQUIRE(rdvalue_cast(v) == std::numeric_limits::min()); REQUIRE(rdvalue_cast(RDValue(v)) == std::numeric_limits::min()); v = std::numeric_limits::max(); REQUIRE(rdvalue_cast(v) == std::numeric_limits::max()); REQUIRE(rdvalue_cast(RDValue(v)) == std::numeric_limits::max()); } { RDValue v(std::numeric_limits::max()); REQUIRE(rdvalue_cast(v) == std::numeric_limits::max()); RDValue vv(v); REQUIRE(rdvalue_cast(vv) == std::numeric_limits::max()); v = std::numeric_limits::min(); RDValue vvv(v); REQUIRE(rdvalue_cast(v) == std::numeric_limits::min()); REQUIRE(rdvalue_cast(vvv) == std::numeric_limits::min()); } } TEST_CASE("testPOD") { testLimits(); testLimits(); testLimits(); testLimits(); testLimits(); } 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); REQUIRE(rdvalue_cast>(v) == data); RDValue vv; copy_rdvalue(vv, v); REQUIRE(rdvalue_cast>(vv) == data); RDValue::cleanup_rdvalue(v); // desctructor... RDValue::cleanup_rdvalue(vv); } TEST_CASE("testPODVectors") { testVector(); testVector(); testVector(); testVector(); testVector(); // stored in anys } TEST_CASE("testStringVect") { std::vector vecs; vecs.emplace_back("my"); vecs.emplace_back("dog"); vecs.emplace_back("has"); vecs.emplace_back("fleas"); RDValue v(vecs); REQUIRE(rdvalue_cast>(v) == vecs); RDValue vc; copy_rdvalue(vc, v); REQUIRE(rdvalue_cast>(vc) == vecs); RDValue vv = vecs; RDValue vvc; copy_rdvalue(vvc, vv); REQUIRE(rdvalue_cast>(vv) == vecs); REQUIRE(rdvalue_cast>(vvc) == vecs); RDValue::cleanup_rdvalue(v); RDValue::cleanup_rdvalue(vc); RDValue::cleanup_rdvalue(vv); RDValue::cleanup_rdvalue(vvc); } TEST_CASE("testMapsAndLists") { { typedef std::map listtype; listtype m; m["foo"] = 1; m["bar"] = 2; RDValue v(m); REQUIRE(rdvalue_cast(v) == m); RDValue::cleanup_rdvalue(v); } { std::list m; m.emplace_back("foo"); m.emplace_back("bar"); RDValue v(m); REQUIRE(rdvalue_cast>(v) == m); RDValue::cleanup_rdvalue(v); } } TEST_CASE("testNaN") { double nan = sqrt(-1.0); RDValue v(nan); REQUIRE(v.getTag() == RDTypeTag::DoubleTag); REQUIRE(std::isnan(rdvalue_cast(v))); RDValue vv(2.0); REQUIRE(rdvalue_is(vv)); REQUIRE(vv.getTag() == RDTypeTag::DoubleTag); } 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); } }; TEST_CASE("testPropertyPickler") { testProp(1234); testProp(1234.); testProp(1234.0f); testProp(1234u); testProp(true); testProp( std::string("the quick brown fox jumps over the lazy dog")); testProp(0); testProp(0.); testProp(0.0f); testProp(0u); testProp(false); } TEST_CASE("testPickleBinaryString") { 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); REQUIRE(streamWriteProps(ss, p)); } { RDProps p2; streamReadProps(ss, p2); REQUIRE(p2.getProp("foo") == str); } } TEST_CASE("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"); 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"); p.setProp("foo", 32767 + 1); REQUIRE_THROWS_AS(p.getProp("foo"), boost::numeric::positive_overflow); REQUIRE_THROWS_AS(p.getProp("foo"), boost::numeric::positive_overflow); REQUIRE_THROWS_AS(p.getProp("foo"), boost::numeric::positive_overflow); p.setProp("foo", 65535 + 1); REQUIRE_THROWS_AS(p.getProp("foo"), boost::numeric::positive_overflow); p.setProp("foo", -1); REQUIRE_THROWS_AS(p.getProp("foo"), boost::numeric::negative_overflow); p.getProp("foo"); REQUIRE_THROWS_AS(p.getProp("foo"), boost::numeric::negative_overflow); } TEST_CASE("testStringToDouble") { RDProps p; p.setProp("foo", "123.0 "); p.setProp("bar", " 123.0 "); REQUIRE(p.getProp("foo") == 123.0); REQUIRE(p.getProp("foo") == 123.0f); REQUIRE_THROWS_AS(p.getProp("bar"), std::bad_any_cast); }