diff options
author | Henning Baldersheim <balder@yahoo-inc.com> | 2022-05-19 21:57:59 +0000 |
---|---|---|
committer | Henning Baldersheim <balder@yahoo-inc.com> | 2022-05-20 12:38:48 +0000 |
commit | 64500ab17deb86b394edc81f4ad42b5a2c43fe30 (patch) | |
tree | 64334ba1513b697dacd5068981a8ee5b7ad92f3b /vespalib/src/tests/objects | |
parent | cfa6ec5cdbd1cf39558d3f85101de05230d6c225 (diff) |
Fold staging_vespalib into vespalib
Diffstat (limited to 'vespalib/src/tests/objects')
11 files changed, 627 insertions, 0 deletions
diff --git a/vespalib/src/tests/objects/identifiable/.gitignore b/vespalib/src/tests/objects/identifiable/.gitignore new file mode 100644 index 00000000000..a547ace8ee4 --- /dev/null +++ b/vespalib/src/tests/objects/identifiable/.gitignore @@ -0,0 +1,5 @@ +.depend +Makefile +asciistream_test +identifiable_test +vespalib_identifiable_test_app diff --git a/vespalib/src/tests/objects/identifiable/CMakeLists.txt b/vespalib/src/tests/objects/identifiable/CMakeLists.txt new file mode 100644 index 00000000000..c4aefa44350 --- /dev/null +++ b/vespalib/src/tests/objects/identifiable/CMakeLists.txt @@ -0,0 +1,9 @@ +# Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +vespa_add_executable(vespalib_identifiable_test_app TEST + SOURCES + identifiable_test.cpp + namedobject.cpp + DEPENDS + vespalib +) +vespa_add_test(NAME vespalib_identifiable_test_app COMMAND vespalib_identifiable_test_app) diff --git a/vespalib/src/tests/objects/identifiable/identifiable_test.cpp b/vespalib/src/tests/objects/identifiable/identifiable_test.cpp new file mode 100644 index 00000000000..b3adfbfa9e2 --- /dev/null +++ b/vespalib/src/tests/objects/identifiable/identifiable_test.cpp @@ -0,0 +1,338 @@ +// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. + +#include "namedobject.h" +#include <vespa/vespalib/objects/identifiable.hpp> +#include <vespa/vespalib/objects/nbostream.h> +#include <vespa/vespalib/util/exceptions.h> +#include <vespa/vespalib/testkit/testapp.h> + +using namespace vespalib; + +class IdentifiableTest : public TestApp { + void requireThatIdentifiableCastCanCastPointers(); + void requireThatIdentifiableCastCanCastReferences(); + void testNamedObject(); + void testNboStream(); + template <typename T> + void testStream(const T & a); + void testNboSerializer(); + template <typename T> + void testSerializer(const T & a); +public: + int Main() override; +}; + +#define CID_Abstract 0x700000 +#define CID_A 0x700001 +#define CID_B 0x700002 +#define CID_C 0x700003 + +class Abstract : public Identifiable +{ +public: + DECLARE_IDENTIFIABLE_ABSTRACT(Abstract); + virtual ~Abstract() { } + virtual void someAbstractVirtualMethod() = 0; +}; + +class A : public Abstract +{ +public: + DECLARE_IDENTIFIABLE(A); + A() { } + void someAbstractVirtualMethod() override { }; +}; + +class B : public A +{ +public: + DECLARE_IDENTIFIABLE(B); + B() { } +}; + +class C : public Identifiable +{ +private: + int _value; + +public: + DECLARE_IDENTIFIABLE(C); + C() : _value(0) {} + C(int value) : _value(value) {} + C *clone() const { return new C(*this); } + virtual int cmp(const Identifiable &rhs) const { + int result(cmpClassId(rhs)); + if (result == 0) { + result = _value - static_cast<const C &>(rhs)._value; + } + return result; + } +}; + +IMPLEMENT_IDENTIFIABLE_ABSTRACT(Abstract, Identifiable); +IMPLEMENT_IDENTIFIABLE(A, Abstract); +IMPLEMENT_IDENTIFIABLE(B, A); +IMPLEMENT_IDENTIFIABLE(C, Identifiable); + +void +IdentifiableTest::testNamedObject() +{ + NamedObject a("first"), b("second");; + nbostream os; + NBOSerializer nos(os); + nos << a << b; + EXPECT_EQUAL(27u,os.size()); + Identifiable::UP o1; + o1 = Identifiable::create(nos); + EXPECT_EQUAL(14u, os.size()); + ASSERT_TRUE(o1->inherits(NamedObject::classId)); + ASSERT_TRUE(o1->getClass().id() == NamedObject::classId); + EXPECT_TRUE(static_cast<const NamedObject &>(*o1).getName() == "first"); + o1 = Identifiable::create(nos); + EXPECT_EQUAL(0u, os.size()); + ASSERT_TRUE(o1->inherits(NamedObject::classId)); + ASSERT_TRUE(o1->getClass().id() == NamedObject::classId); + EXPECT_TRUE(static_cast<const NamedObject &>(*o1).getName() == "second"); +} + +template <typename T> +void IdentifiableTest::testStream(const T & a) +{ + nbostream s; + s << a; + T b; + s >> b; + EXPECT_TRUE(s.empty()); + EXPECT_EQUAL(a, b); + EXPECT_EQUAL(nbostream::ok, s.state()); + EXPECT_TRUE(s.good()); +} + +template <typename T> +void IdentifiableTest::testSerializer(const T & a) +{ + nbostream t; + NBOSerializer s(t); + s << a; + T b; + s >> b; + EXPECT_TRUE(s.getStream().empty()); + EXPECT_EQUAL(a, b); + EXPECT_EQUAL(nbostream::ok, s.getStream().state()); +} + +void IdentifiableTest::testNboSerializer() +{ + testSerializer(true); + testSerializer(false); + testSerializer(static_cast<int8_t>('a')); + testSerializer(static_cast<uint8_t>(156)); + testSerializer(static_cast<int16_t>(156)); + testSerializer(static_cast<int32_t>(156)); + testSerializer(static_cast<int64_t>(156)); + testSerializer(static_cast<uint16_t>(156)); + testSerializer(static_cast<uint32_t>(156)); + testSerializer(static_cast<uint64_t>(156)); + testSerializer(static_cast<float>(156)); + testSerializer(static_cast<double>(156)); + testSerializer(vespalib::string("abcdefgh")); +} + +void IdentifiableTest::testNboStream() +{ + testStream(true); + testStream(false); + testStream('a'); + testStream(static_cast<unsigned char>(156)); + testStream(static_cast<int16_t>(156)); + testStream(static_cast<int32_t>(156)); + testStream(static_cast<int64_t>(156)); + testStream(static_cast<uint16_t>(156)); + testStream(static_cast<uint32_t>(156)); + testStream(static_cast<uint64_t>(156)); + testStream(static_cast<float>(156)); + testStream(static_cast<double>(156)); + testStream(std::string("abcdefgh")); + testStream(vespalib::string("abcdefgh")); + { + nbostream s(4); + EXPECT_EQUAL(4u, s.capacity()); + s << "abcdef"; + EXPECT_EQUAL(nbostream::ok, s.state()); + EXPECT_EQUAL(10u, s.size()); + EXPECT_EQUAL(16u, s.capacity()); + EXPECT_EQUAL(0, strncmp(s.data() + 4, "abcdef", 6)); + } + { + nbostream s(8); + EXPECT_EQUAL(0u, s.size()); + EXPECT_EQUAL(8u, s.capacity()); + const char * prev = s.data(); + s << "ABCD"; + EXPECT_EQUAL(8u, s.size()); + EXPECT_EQUAL(8u, s.capacity()); + EXPECT_EQUAL(prev, s.data()); + s << "A long string that will cause resizing"; + EXPECT_EQUAL(50u, s.size()); + EXPECT_EQUAL(64u, s.capacity()); + EXPECT_NOT_EQUAL(prev, s.data()); + } + { + nbostream s(8); + EXPECT_EQUAL(0u, s.size()); + EXPECT_EQUAL(8u, s.capacity()); + const char * prev = s.data(); + s << "ABCD"; + EXPECT_EQUAL(8u, s.size()); + EXPECT_EQUAL(8u, s.capacity()); + EXPECT_EQUAL(prev, s.data()); + s.reserve(50); + EXPECT_NOT_EQUAL(prev, s.data()); + EXPECT_EQUAL(8u, s.size()); + EXPECT_EQUAL(64u, s.capacity()); + prev = s.data(); + s << "A long string that will cause resizing"; + EXPECT_EQUAL(50u, s.size()); + EXPECT_EQUAL(64u, s.capacity()); + EXPECT_EQUAL(prev, s.data()); + } + { + nbostream s; + s << int64_t(9); + EXPECT_EQUAL(8u, s.size()); + EXPECT_EQUAL(0u, s.rp()); + int64_t a(7), b(1); + s >> a; + EXPECT_EQUAL(0u, s.size()); + EXPECT_EQUAL(8u, s.rp()); + EXPECT_TRUE(s.empty()); + EXPECT_TRUE(s.good()); + EXPECT_EQUAL(9, a); + try { + s >> b; + EXPECT_TRUE(false); + } catch (const IllegalStateException & e) { + EXPECT_EQUAL("Stream failed bufsize(1024), readp(8), writep(8)", e.getMessage()); + } + EXPECT_EQUAL(0u, s.size()); + EXPECT_EQUAL(8u, s.rp()); + EXPECT_TRUE(s.empty()); + EXPECT_FALSE(s.good()); + EXPECT_EQUAL(1, b); + EXPECT_EQUAL(nbostream::eof, s.state()); + } +} + +int +IdentifiableTest::Main() +{ + TEST_INIT("identifiable_test"); + + TEST_DO(requireThatIdentifiableCastCanCastPointers()); + TEST_DO(requireThatIdentifiableCastCanCastReferences()); + testNamedObject(); + testNboStream(); + testNboSerializer(); + + A a; + B b; + + const Identifiable::RuntimeClass & rtcA = a.getClass(); + EXPECT_EQUAL(rtcA.id(), static_cast<unsigned int>(A::classId)); + EXPECT_EQUAL(strcmp(rtcA.name(), "A"), 0); + + const Identifiable::RuntimeClass & rtcB = b.getClass(); + EXPECT_EQUAL(rtcB.id(), static_cast<unsigned int>(B::classId)); + EXPECT_EQUAL(strcmp(rtcB.name(), "B"), 0); + + const Identifiable::RuntimeClass * rt(Identifiable::classFromId(0x1ab76245)); + ASSERT_TRUE(rt == NULL); + rt = Identifiable::classFromId(Abstract::classId); + ASSERT_TRUE(rt != NULL); + Identifiable * u = rt->create(); + ASSERT_TRUE(u == NULL); + rt = Identifiable::classFromId(A::classId); + ASSERT_TRUE(rt != NULL); + rt = Identifiable::classFromId(B::classId); + ASSERT_TRUE(rt != NULL); + + Identifiable * o = rt->create(); + ASSERT_TRUE(o != NULL); + + const Identifiable::RuntimeClass & rtc = o->getClass(); + ASSERT_TRUE(rtc.id() == B::classId); + ASSERT_TRUE(strcmp(rtc.name(), "B") == 0); + ASSERT_TRUE(o->inherits(B::classId)); + ASSERT_TRUE(o->inherits(A::classId)); + ASSERT_TRUE(o->inherits(Abstract::classId)); + ASSERT_TRUE(o->inherits(Identifiable::classId)); + ASSERT_TRUE(o->getClass().id() == B::classId); + nbostream os; + NBOSerializer nos(os); + nos << *o; + EXPECT_EQUAL(os.size(), 4u); + Identifiable::UP o2 = Identifiable::create(nos); + EXPECT_TRUE(os.empty()); + ASSERT_TRUE(o->inherits(B::classId)); + ASSERT_TRUE(o->getClass().id() == B::classId); + delete o; + + rt = Identifiable::classFromName("NotBNorA"); + ASSERT_TRUE(rt == NULL); + rt = Identifiable::classFromName("B"); + ASSERT_TRUE(rt != NULL); + o = rt->create(); + ASSERT_TRUE(o != NULL); + const Identifiable::RuntimeClass & rtc2 = o->getClass(); + ASSERT_TRUE(rtc2.id() == B::classId); + ASSERT_TRUE(strcmp(rtc2.name(), "B") == 0); + ASSERT_TRUE(o->inherits(B::classId)); + ASSERT_TRUE(o->inherits(A::classId)); + ASSERT_TRUE(o->inherits(Abstract::classId)); + ASSERT_TRUE(o->inherits(Identifiable::classId)); + ASSERT_TRUE(o->getClass().id() == B::classId); + delete o; + + IdentifiablePtr<C> c0(NULL); + IdentifiablePtr<C> c1(new C(10)); + IdentifiablePtr<C> c2(new C(20)); + + EXPECT_LESS(c0.cmp(c1), 0); + EXPECT_EQUAL(c0.cmp(c0), 0); + EXPECT_GREATER(c1.cmp(c0), 0); + + EXPECT_LESS(c1.cmp(c2), 0); + EXPECT_EQUAL(c1.cmp(c1), 0); + EXPECT_GREATER(c2.cmp(c1), 0); + + TEST_DONE(); +} + +void IdentifiableTest::requireThatIdentifiableCastCanCastPointers() { + A a; + B b; + EXPECT_TRUE(Identifiable::cast<A *>(&a)); + EXPECT_TRUE(Identifiable::cast<A *>(&b)); + EXPECT_TRUE(!Identifiable::cast<B *>(&a)); + EXPECT_TRUE(Identifiable::cast<B *>(&b)); + EXPECT_TRUE(Identifiable::cast<Abstract *>(&a)); + EXPECT_TRUE(Identifiable::cast<Abstract *>(&b)); +} + +void IdentifiableTest::requireThatIdentifiableCastCanCastReferences() { + A a; + B b; + try { + // These should not throw. + Identifiable::cast<A &>(a); + Identifiable::cast<A &>(b); + Identifiable::cast<B &>(b); + Identifiable::cast<Abstract &>(a); + Identifiable::cast<Abstract &>(b); + } catch (std::bad_cast &e) { + TEST_FATAL(e.what()); + } + EXPECT_EXCEPTION(Identifiable::cast<B &>(a), std::bad_cast, "bad_cast"); +} + +TEST_APPHOOK(IdentifiableTest) diff --git a/vespalib/src/tests/objects/identifiable/namedobject.cpp b/vespalib/src/tests/objects/identifiable/namedobject.cpp new file mode 100644 index 00000000000..3e8d3291177 --- /dev/null +++ b/vespalib/src/tests/objects/identifiable/namedobject.cpp @@ -0,0 +1,19 @@ +// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +#include "namedobject.h" + +namespace vespalib { + +IMPLEMENT_IDENTIFIABLE_NS(vespalib, NamedObject, Identifiable); + + +Serializer & NamedObject::onSerialize(Serializer & os) const +{ + return os.put(_name); +} + +Deserializer & NamedObject::onDeserialize(Deserializer & is) +{ + return is.get(_name); +} + +} diff --git a/vespalib/src/tests/objects/identifiable/namedobject.h b/vespalib/src/tests/objects/identifiable/namedobject.h new file mode 100644 index 00000000000..784715a66f6 --- /dev/null +++ b/vespalib/src/tests/objects/identifiable/namedobject.h @@ -0,0 +1,23 @@ +// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +#pragma once + +#include <vespa/vespalib/objects/identifiable.h> +#include <string> + +namespace vespalib +{ + +class NamedObject : public Identifiable +{ +public: + DECLARE_IDENTIFIABLE_NS(vespalib, NamedObject); + DECLARE_NBO_SERIALIZE; + NamedObject() : _name() { } + NamedObject(const string & name) : _name(name) { } + const string & getName() const { return _name; } +private: + string _name; +}; + +} + diff --git a/vespalib/src/tests/objects/objectdump/.gitignore b/vespalib/src/tests/objects/objectdump/.gitignore new file mode 100644 index 00000000000..6ddd515391d --- /dev/null +++ b/vespalib/src/tests/objects/objectdump/.gitignore @@ -0,0 +1,4 @@ +.depend +Makefile +objectdump_test +vespalib_objectdump_test_app diff --git a/vespalib/src/tests/objects/objectdump/CMakeLists.txt b/vespalib/src/tests/objects/objectdump/CMakeLists.txt new file mode 100644 index 00000000000..67395998b39 --- /dev/null +++ b/vespalib/src/tests/objects/objectdump/CMakeLists.txt @@ -0,0 +1,8 @@ +# Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +vespa_add_executable(vespalib_objectdump_test_app TEST + SOURCES + objectdump.cpp + DEPENDS + vespalib +) +vespa_add_test(NAME vespalib_objectdump_test_app COMMAND vespalib_objectdump_test_app) diff --git a/vespalib/src/tests/objects/objectdump/objectdump.cpp b/vespalib/src/tests/objects/objectdump/objectdump.cpp new file mode 100644 index 00000000000..812b1e79e17 --- /dev/null +++ b/vespalib/src/tests/objects/objectdump/objectdump.cpp @@ -0,0 +1,115 @@ +// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. + +#include <vespa/vespalib/testkit/testapp.h> +#include <vespa/vespalib/objects/identifiable.h> +#include <vespa/vespalib/objects/visit.hpp> + +#define CID_Base 10000000 +#define CID_Foo 10000001 +#define CID_Bar 10000002 +#define CID_Baz 10000003 + +using vespalib::ObjectVisitor; +using vespalib::IdentifiablePtr; + +struct Base : public vespalib::Identifiable +{ + DECLARE_IDENTIFIABLE(Base); + virtual Base *clone() const { return new Base(*this); } +}; +IMPLEMENT_IDENTIFIABLE(Base, vespalib::Identifiable); + +struct Baz : public Base +{ + DECLARE_IDENTIFIABLE(Baz); + Baz *clone() const override { return new Baz(*this); } +}; +IMPLEMENT_IDENTIFIABLE(Baz, Base); + +struct Bar : public Base +{ + DECLARE_IDENTIFIABLE(Bar); + bool _bool; + int8_t _int8; + uint8_t _uint8; + int16_t _int16; + uint16_t _uint16; + int32_t _int32; + uint32_t _uint32; + int64_t _int64; + uint64_t _uint64; + float _float; + double _double; + vespalib::string _string; + Bar() : _bool(true), _int8(-1), _uint8(1), _int16(-2), _uint16(2), + _int32(-4), _uint32(4), _int64(-8), _uint64(8), + _float(2.5), _double(2.75), _string("bla bla") {} + + Bar *clone() const override { return new Bar(*this); } + + void visitMembers(ObjectVisitor &v) const override { + visit(v, "_bool", _bool); + visit(v, "_int8", _int8); + visit(v, "_uint8", _uint8); + visit(v, "_int16", _int16); + visit(v, "_uint16", _uint16); + visit(v, "_int32", _int32); + visit(v, "_uint32", _uint32); + visit(v, "_int64", _int64); + visit(v, "_uint64", _uint64); + visit(v, "_float", _float); + visit(v, "_double", _double); + visit(v, "_string", _string); + visit(v, "info", "a dummy string"); + visit(v, "(const char*)0", (const char*)0); + } +}; +IMPLEMENT_IDENTIFIABLE(Bar, Base); + +struct Foo : public Base +{ + DECLARE_IDENTIFIABLE(Foo); + Bar _objMember; + Baz _objMember2; + Baz *_objPtr; + std::vector<Bar> _list; + std::vector<IdentifiablePtr<Base> > _list2; + + Foo(); + ~Foo(); + Foo *clone() const override { return new Foo(*this); } + void visitMembers(ObjectVisitor &v) const override; +}; + +Foo::~Foo() { } +Foo::Foo() + : _objMember(), _objMember2(), _objPtr(0), _list(), _list2() +{ + _list.push_back(Bar()); + _list.push_back(Bar()); + _list.push_back(Bar()); + _list2.push_back(Bar()); + _list2.push_back(Baz()); +} + +void +Foo::visitMembers(ObjectVisitor &v) const { + visit(v, "_objMember", _objMember); + visit(v, "_objMember2", _objMember2); + visit(v, "_objPtr", _objPtr); + visit(v, "_list", _list); + visit(v, "_list2", _list2); +} + +IMPLEMENT_IDENTIFIABLE(Foo, Base); + +TEST_SETUP(Test); + +int +Test::Main() +{ + TEST_INIT("objectdump_test"); + Foo foo; + fprintf(stderr, "%s", foo.asString().c_str()); + TEST_DONE(); +} diff --git a/vespalib/src/tests/objects/objectselection/.gitignore b/vespalib/src/tests/objects/objectselection/.gitignore new file mode 100644 index 00000000000..f6aefd07270 --- /dev/null +++ b/vespalib/src/tests/objects/objectselection/.gitignore @@ -0,0 +1,4 @@ +.depend +Makefile +objectselection_test +vespalib_objectselection_test_app diff --git a/vespalib/src/tests/objects/objectselection/CMakeLists.txt b/vespalib/src/tests/objects/objectselection/CMakeLists.txt new file mode 100644 index 00000000000..94f43078820 --- /dev/null +++ b/vespalib/src/tests/objects/objectselection/CMakeLists.txt @@ -0,0 +1,8 @@ +# Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +vespa_add_executable(vespalib_objectselection_test_app TEST + SOURCES + objectselection.cpp + DEPENDS + vespalib +) +vespa_add_test(NAME vespalib_objectselection_test_app COMMAND vespalib_objectselection_test_app) diff --git a/vespalib/src/tests/objects/objectselection/objectselection.cpp b/vespalib/src/tests/objects/objectselection/objectselection.cpp new file mode 100644 index 00000000000..aa9c841f2dc --- /dev/null +++ b/vespalib/src/tests/objects/objectselection/objectselection.cpp @@ -0,0 +1,94 @@ +// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. + +#include <vespa/vespalib/testkit/testapp.h> +#include <vespa/vespalib/objects/identifiable.hpp> +#include <vespa/vespalib/objects/objectpredicate.h> +#include <vespa/vespalib/objects/objectoperation.h> + +using namespace vespalib; + +#define CID_Foo 60000005 +#define CID_Bar 60000010 + +struct Foo : public Identifiable +{ + typedef IdentifiablePtr<Foo> CP; + std::vector<CP> nodes; + + DECLARE_IDENTIFIABLE(Foo); + virtual Foo *clone() const { return new Foo(*this); } + void selectMembers(const ObjectPredicate &p, ObjectOperation &o) override { + for (uint32_t i = 0; i < nodes.size(); ++i) { + nodes[i]->select(p, o); + } + } +}; +IMPLEMENT_IDENTIFIABLE(Foo, Identifiable); + +struct Bar : public Foo +{ + int value; + + DECLARE_IDENTIFIABLE(Bar); + Bar() : value(0) {} + Bar(int v) { value = v; } + Bar *clone() const override { return new Bar(*this); } +}; +IMPLEMENT_IDENTIFIABLE(Bar, Identifiable); + +struct ObjectType : public ObjectPredicate +{ + uint32_t cid; + ObjectType(uint32_t id) : cid(id) {} + bool check(const Identifiable &obj) const override { + return (obj.getClass().id() == cid); + } +}; + +struct ObjectCollect : public ObjectOperation +{ + std::vector<Identifiable*> nodes; + ~ObjectCollect() override; + void execute(Identifiable &obj) override { + nodes.push_back(&obj); + } +}; + +ObjectCollect::~ObjectCollect() = default; + +TEST_SETUP(Test); + +int +Test::Main() +{ + TEST_INIT("objectselection_test"); + { + Foo f1; + Foo f2; + Foo f3; + Bar b1(1); + Bar b2(2); + Bar b3(3); + Bar b4(4); + f2.nodes.push_back(b1); + f2.nodes.push_back(b2); + f3.nodes.push_back(b3); + f3.nodes.push_back(b4); + f1.nodes.push_back(f2); + f1.nodes.push_back(f3); + + ObjectType predicate(Bar::classId); + ObjectCollect operation; + f1.select(predicate, operation); + ASSERT_TRUE(operation.nodes.size() == 4); + ASSERT_TRUE(operation.nodes[0]->getClass().id() == Bar::classId); + ASSERT_TRUE(operation.nodes[1]->getClass().id() == Bar::classId); + ASSERT_TRUE(operation.nodes[2]->getClass().id() == Bar::classId); + ASSERT_TRUE(operation.nodes[3]->getClass().id() == Bar::classId); + ASSERT_TRUE(((Bar*)operation.nodes[0])->value == 1); + ASSERT_TRUE(((Bar*)operation.nodes[1])->value == 2); + ASSERT_TRUE(((Bar*)operation.nodes[2])->value == 3); + ASSERT_TRUE(((Bar*)operation.nodes[3])->value == 4); + } + TEST_DONE(); +} |