// test_incremental_expression.cc // // Copyright (C) 2010 Daniel Burrows // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License as // published by the Free Software Foundation; either version 2 of the // License, or (at your option) any later version. // // This program is distributed in the hope that it will be useful, but // WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; see the file COPYING. If not, write to // the Free Software Foundation, Inc., 59 Temple Place - Suite 330, // Boston, MA 02111-1307, USA. #include #include #include namespace cw = cwidget; namespace { // Make it possible to "show" vectors. template std::ostream &operator<<(std::ostream &out, const std::vector &v) { out << "["; for(typename std::vector::const_iterator it = v.begin(); it != v.end(); ++it) { if(it != v.begin()) out << ", "; out << *it; } out << "]"; return out; } // Helper class for the code below that records a single call to // child_modified(). template class child_modified_call { cw::util::ref_ptr > child; T old_value, new_value; public: child_modified_call(const cw::util::ref_ptr > &_child, const T &_old_value, const T &_new_value) : child(_child), old_value(_old_value), new_value(_new_value) { } const cw::util::ref_ptr > &get_child() const { return child; } const T &get_old_value() const { return old_value; } const T &get_new_value() const { return new_value; } bool operator==(const child_modified_call &other) const { return child == other.child && old_value == other.old_value && new_value == other.new_value; } }; template std::ostream &operator<<(std::ostream &out, const child_modified_call &t) { return out << "child_modified(child = " << t.get_child() << ", old_value = " << t.get_old_value() << ", new_value = " << t.get_new_value() << ")"; } template class get_value_call { T return_value; public: get_value_call(const T &_return_value) : return_value(_return_value) { } const T &get_return_value() const { return return_value; } bool operator==(const get_value_call &other) const { return return_value == other.return_value; } }; template std::ostream &operator<<(std::ostream &out, const get_value_call &c) { return out << "get_value() => " << c.get_return_value(); } // A class that implements the expression container interface, // passing all interesting calls to a single sub-object and // recording all the calls to child_modified. template class fake_container : public expression_container { cw::util::ref_ptr > real_object; std::vector > calls; fake_container(const cw::util::ref_ptr > &_real_object) : real_object(_real_object) { real_object->add_parent(this); } public: ~fake_container() { real_object->remove_parent(this); } static cw::util::ref_ptr > create(const cw::util::ref_ptr > &child) { return new fake_container(child); } const std::vector > &get_calls() const { return calls; } void child_modified(const cw::util::ref_ptr > &child, T old_value, T new_value) { calls.push_back(child_modified_call(child, old_value, new_value)); } T get_value() { return real_object->get_value(); } void dump(std::ostream &out) { real_object->dump(out); } }; // Records calls to expression_box::changed. template class changed_call { T new_value; public: changed_call(const T &_new_value) : new_value(_new_value) { } const T &get_new_value() const { return new_value; } }; template std::ostream &operator<<(std::ostream &out, const changed_call &c) { return out << "changed(" << c.get_new_value() << ")"; } // A helper class used to test that expression_wrapper behaves as // advertised. // // Wraps its subexpression and records all the calls to // child_modified() and changed(). template class fake_wrapper : public expression_wrapper { std::vector, changed_call > > calls; fake_wrapper() : expression_wrapper() { } fake_wrapper(const cw::util::ref_ptr > &child) : expression_wrapper(child) { } public: static cw::util::ref_ptr create() { return new fake_wrapper; } static cw::util::ref_ptr create(const cw::util::ref_ptr > &child) { return new fake_wrapper(child); } void child_modified(const cw::util::ref_ptr > &child, T old_value, T new_value) { calls.push_back(child_modified_call(child, old_value, new_value)); expression_wrapper::child_modified(child, old_value, new_value); } void changed(T new_value) { calls.push_back(changed_call(new_value)); expression_wrapper::changed(this->get_child()); } }; } class TestIncrementalExpression : public CppUnit::TestFixture { CPPUNIT_TEST_SUITE(TestIncrementalExpression); CPPUNIT_TEST(testIncrementalExpressionGetVarValue); CPPUNIT_TEST(testIncrementalExpressionSetVarValue); CPPUNIT_TEST(testIncrementalExpressionVarSignalChange); // TODO: test comparisons? // TODO: test conversions to string? CPPUNIT_TEST(testIncrementalExpressionWeakRefDeref); CPPUNIT_TEST(testIncrementalExpressionWeakRefGetValidLive); CPPUNIT_TEST(testIncrementalExpressionWeakRefGetValidDead); CPPUNIT_TEST(testNotFalse); CPPUNIT_TEST(testNotTrue); CPPUNIT_TEST(testNotRaiseInput); CPPUNIT_TEST(testNotLowerInput); CPPUNIT_TEST(testNotNull); CPPUNIT_TEST(testAndEmpty); CPPUNIT_TEST(testAndSingletonRaise); CPPUNIT_TEST(testAndSingletonLower); CPPUNIT_TEST(testAndSingletonRaiseByRemoving); CPPUNIT_TEST(testAndSingletonLowerByAppending); CPPUNIT_TEST(testAndSingletonNull); CPPUNIT_TEST(testAndDoubletonFirstNull); CPPUNIT_TEST(testAndDoubletonSecondNull); CPPUNIT_TEST(testAndDoubletonBothNull); CPPUNIT_TEST(testAndDoubletonRaiseFirst); CPPUNIT_TEST(testAndDoubletonRaiseSecond); CPPUNIT_TEST(testAndDoubletonRaiseFirstNoEffect); CPPUNIT_TEST(testAndDoubletonRaiseSecondNoEffect); CPPUNIT_TEST(testAndDoubletonLowerFirst); CPPUNIT_TEST(testAndDoubletonLowerSecond); CPPUNIT_TEST(testAndDoubletonLowerFirstNoEffect); CPPUNIT_TEST(testAndDoubletonLowerSecondNoEffect); CPPUNIT_TEST(testOrEmpty); CPPUNIT_TEST(testOrSingletonRaise); CPPUNIT_TEST(testOrSingletonLower); CPPUNIT_TEST(testOrSingletonLowerByRemoving); CPPUNIT_TEST(testOrSingletonRaiseByAppending); CPPUNIT_TEST(testOrSingletonNull); CPPUNIT_TEST(testOrDoubletonFirstNull); CPPUNIT_TEST(testOrDoubletonSecondNull); CPPUNIT_TEST(testOrDoubletonBothNull); CPPUNIT_TEST(testOrDoubletonRaiseFirst); CPPUNIT_TEST(testOrDoubletonRaiseSecond); CPPUNIT_TEST(testOrDoubletonRaiseFirstNoEffect); CPPUNIT_TEST(testOrDoubletonRaiseSecondNoEffect); CPPUNIT_TEST(testOrDoubletonLowerFirst); CPPUNIT_TEST(testOrDoubletonLowerSecond); CPPUNIT_TEST(testOrDoubletonLowerFirstNoEffect); CPPUNIT_TEST(testOrDoubletonLowerSecondNoEffect); CPPUNIT_TEST_SUITE_END(); public: void testIncrementalExpressionGetVarValue() { cw::util::ref_ptr > v0 = var_e::create(0), v5 = var_e::create(5), v9 = var_e::create(9); CPPUNIT_ASSERT_EQUAL(0, v0->get_value()); CPPUNIT_ASSERT_EQUAL(5, v5->get_value()); CPPUNIT_ASSERT_EQUAL(9, v9->get_value()); } void testIncrementalExpressionSetVarValue() { cw::util::ref_ptr > v = var_e::create(123456); v->set_value(987654); CPPUNIT_ASSERT_EQUAL(987654, v->get_value()); } void testIncrementalExpressionVarSignalChange() { cw::util::ref_ptr > v = var_e::create(55555); cw::util::ref_ptr > c = fake_container::create(v); std::vector > expected_calls; expected_calls.push_back(child_modified_call(v, 55555, 42)); expected_calls.push_back(child_modified_call(v, 42, 10)); v->set_value(42); // Test that setting to the same value doesn't emit a signal. v->set_value(42); v->set_value(10); CPPUNIT_ASSERT_EQUAL(expected_calls, c->get_calls()); } void testIncrementalExpressionWeakRefDeref() { cw::util::ref_ptr > e = var_e::create(5); expression_weak_ref > e_ref = e; CPPUNIT_ASSERT_EQUAL(e.unsafe_get_ref(), e_ref.get_value()); } void testIncrementalExpressionWeakRefGetValidLive() { cw::util::ref_ptr > e = var_e::create(5); expression_weak_ref > e_ref = e; CPPUNIT_ASSERT(e_ref.get_valid()); } void testIncrementalExpressionWeakRefGetValidDead() { cw::util::ref_ptr > e = var_e::create(5); expression_weak_ref > e_ref = e; e = cw::util::ref_ptr >(); CPPUNIT_ASSERT(!e_ref.get_valid()); } void testNotFalse() { cw::util::ref_ptr > v = var_e::create(true); cw::util::ref_ptr > not_v = not_e::create(v); CPPUNIT_ASSERT(!not_v->get_value()); } void testNotTrue() { cw::util::ref_ptr > v = var_e::create(false); cw::util::ref_ptr > not_v = not_e::create(v); CPPUNIT_ASSERT(not_v->get_value()); } void testNotRaiseInput() { cw::util::ref_ptr > v = var_e::create(false); cw::util::ref_ptr > not_v = not_e::create(v); cw::util::ref_ptr > not_v_wrap = fake_container::create(not_v); CPPUNIT_ASSERT(not_v->get_value()); v->set_value(true); CPPUNIT_ASSERT(!not_v->get_value()); std::vector > expected; expected.push_back(child_modified_call(not_v, true, false)); CPPUNIT_ASSERT_EQUAL(expected, not_v_wrap->get_calls()); } void testNotLowerInput() { cw::util::ref_ptr > v = var_e::create(true); cw::util::ref_ptr > not_v = not_e::create(v); cw::util::ref_ptr > not_v_wrap = fake_container::create(not_v); CPPUNIT_ASSERT(!not_v->get_value()); v->set_value(false); CPPUNIT_ASSERT(not_v->get_value()); std::vector > expected; expected.push_back(child_modified_call(not_v, false, true)); CPPUNIT_ASSERT_EQUAL(expected, not_v_wrap->get_calls()); } void testNotNull() { cw::util::ref_ptr > not_null = not_e::create(cw::util::ref_ptr >()); CPPUNIT_ASSERT(!not_null->get_value()); } void testAndEmpty() { cw::util::ref_ptr > empty[] = { }; cw::util::ref_ptr > e = and_e::create(empty, empty); CPPUNIT_ASSERT(e->get_value()); } private: cw::util::ref_ptr getAndSingleton(cw::util::ref_ptr > v1) { cw::util::ref_ptr > subexprs_begin[] = { v1 }; cw::util::ref_ptr > *subexprs_end = subexprs_begin + sizeof(subexprs_begin) / sizeof(subexprs_begin[0]); return and_e::create(subexprs_begin, subexprs_end); } public: void testAndSingletonRaise() { cw::util::ref_ptr > v1 = var_e::create(false); cw::util::ref_ptr e = getAndSingleton(v1); cw::util::ref_ptr > e_wrap = fake_container::create(e); CPPUNIT_ASSERT(!e->get_value()); v1->set_value(true); CPPUNIT_ASSERT(e->get_value()); std::vector > expected; expected.push_back(child_modified_call(e, false, true)); CPPUNIT_ASSERT_EQUAL(expected, e_wrap->get_calls()); } void testAndSingletonLower() { cw::util::ref_ptr > v1 = var_e::create(true); cw::util::ref_ptr e = getAndSingleton(v1); cw::util::ref_ptr > e_wrap = fake_container::create(e); CPPUNIT_ASSERT(e->get_value()); v1->set_value(false); CPPUNIT_ASSERT(!e->get_value()); std::vector > expected; expected.push_back(child_modified_call(e, true, false)); CPPUNIT_ASSERT_EQUAL(expected, e_wrap->get_calls()); } void testAndSingletonRaiseByRemoving() { cw::util::ref_ptr > v1 = var_e::create(false); cw::util::ref_ptr e = getAndSingleton(v1); cw::util::ref_ptr > e_wrap = fake_container::create(e); CPPUNIT_ASSERT(!e->get_value()); e->remove_child(v1); CPPUNIT_ASSERT(e->get_value()); std::vector > expected; expected.push_back(child_modified_call(e, false, true)); CPPUNIT_ASSERT_EQUAL(expected, e_wrap->get_calls()); } void testAndSingletonLowerByAppending() { cw::util::ref_ptr > v1 = var_e::create(true); cw::util::ref_ptr e = getAndSingleton(v1); cw::util::ref_ptr > e_wrap = fake_container::create(e); CPPUNIT_ASSERT(e->get_value()); e->add_child(var_e::create(false)); CPPUNIT_ASSERT(!e->get_value()); std::vector > expected; expected.push_back(child_modified_call(e, true, false)); CPPUNIT_ASSERT_EQUAL(expected, e_wrap->get_calls()); } void testAndSingletonNull() { cw::util::ref_ptr e = getAndSingleton(cw::util::ref_ptr >()); CPPUNIT_ASSERT(e->get_value()); } private: cw::util::ref_ptr getAndDoubleton(const cw::util::ref_ptr > &v1, const cw::util::ref_ptr > &v2) { cw::util::ref_ptr > subexprs_begin[] = { v1, v2 }; cw::util::ref_ptr > *subexprs_end = subexprs_begin + sizeof(subexprs_begin) / sizeof(subexprs_begin[0]); return and_e::create(subexprs_begin, subexprs_end); } public: void testAndDoubletonFirstNull() { cw::util::ref_ptr > v1, v2 = var_e::create(true); cw::util::ref_ptr e = getAndDoubleton(v1, v2); CPPUNIT_ASSERT(e->get_value()); } void testAndDoubletonSecondNull() { cw::util::ref_ptr > v1 = var_e::create(true), v2; cw::util::ref_ptr e = getAndDoubleton(v1, v2); CPPUNIT_ASSERT(e->get_value()); } void testAndDoubletonBothNull() { cw::util::ref_ptr > v1, v2; cw::util::ref_ptr e = getAndDoubleton(v1, v2); CPPUNIT_ASSERT(e->get_value()); } void testAndDoubletonRaiseSecond() { cw::util::ref_ptr > v1 = var_e::create(true), v2 = var_e::create(false); cw::util::ref_ptr e = getAndDoubleton(v1, v2); cw::util::ref_ptr > e_wrap = fake_container::create(e); CPPUNIT_ASSERT(!e->get_value()); v2->set_value(true); CPPUNIT_ASSERT(e->get_value()); std::vector > expected; expected.push_back(child_modified_call(e, false, true)); CPPUNIT_ASSERT_EQUAL(expected, e_wrap->get_calls()); } void testAndDoubletonRaiseFirst() { cw::util::ref_ptr > v1 = var_e::create(false), v2 = var_e::create(true); cw::util::ref_ptr e = getAndDoubleton(v1, v2); cw::util::ref_ptr > e_wrap = fake_container::create(e); CPPUNIT_ASSERT(!e->get_value()); v1->set_value(true); CPPUNIT_ASSERT(e->get_value()); std::vector > expected; expected.push_back(child_modified_call(e, false, true)); CPPUNIT_ASSERT_EQUAL(expected, e_wrap->get_calls()); } void testAndDoubletonRaiseFirstNoEffect() { cw::util::ref_ptr > v1 = var_e::create(false), v2 = var_e::create(false); cw::util::ref_ptr e = getAndDoubleton(v1, v2); cw::util::ref_ptr > e_wrap = fake_container::create(e); CPPUNIT_ASSERT(!e->get_value()); v1->set_value(true); CPPUNIT_ASSERT(!e->get_value()); std::vector > expected; CPPUNIT_ASSERT_EQUAL(expected, e_wrap->get_calls()); } void testAndDoubletonRaiseSecondNoEffect() { cw::util::ref_ptr > v1 = var_e::create(false), v2 = var_e::create(false); cw::util::ref_ptr e = getAndDoubleton(v1, v2); cw::util::ref_ptr > e_wrap = fake_container::create(e); CPPUNIT_ASSERT(!e->get_value()); v2->set_value(true); CPPUNIT_ASSERT(!e->get_value()); std::vector > expected; CPPUNIT_ASSERT_EQUAL(expected, e_wrap->get_calls()); } void testAndDoubletonLowerFirst() { cw::util::ref_ptr > v1 = var_e::create(true), v2 = var_e::create(true); cw::util::ref_ptr e = getAndDoubleton(v1, v2); cw::util::ref_ptr > e_wrap = fake_container::create(e); CPPUNIT_ASSERT(e->get_value()); v1->set_value(false); CPPUNIT_ASSERT(!e->get_value()); std::vector > expected; expected.push_back(child_modified_call(e, true, false)); CPPUNIT_ASSERT_EQUAL(expected, e_wrap->get_calls()); } void testAndDoubletonLowerSecond() { cw::util::ref_ptr > v1 = var_e::create(true), v2 = var_e::create(true); cw::util::ref_ptr e = getAndDoubleton(v1, v2); cw::util::ref_ptr > e_wrap = fake_container::create(e); CPPUNIT_ASSERT(e->get_value()); v2->set_value(false); CPPUNIT_ASSERT(!e->get_value()); std::vector > expected; expected.push_back(child_modified_call(e, true, false)); CPPUNIT_ASSERT_EQUAL(expected, e_wrap->get_calls()); } void testAndDoubletonLowerFirstNoEffect() { cw::util::ref_ptr > v1 = var_e::create(true), v2 = var_e::create(false); cw::util::ref_ptr e = getAndDoubleton(v1, v2); cw::util::ref_ptr > e_wrap = fake_container::create(e); CPPUNIT_ASSERT(!e->get_value()); v1->set_value(false); CPPUNIT_ASSERT(!e->get_value()); std::vector > expected; CPPUNIT_ASSERT_EQUAL(expected, e_wrap->get_calls()); } void testAndDoubletonLowerSecondNoEffect() { cw::util::ref_ptr > v1 = var_e::create(false), v2 = var_e::create(true); cw::util::ref_ptr e = getAndDoubleton(v1, v2); cw::util::ref_ptr > e_wrap = fake_container::create(e); CPPUNIT_ASSERT(!e->get_value()); v2->set_value(false); CPPUNIT_ASSERT(!e->get_value()); std::vector > expected; CPPUNIT_ASSERT_EQUAL(expected, e_wrap->get_calls()); } void testOrEmpty() { cw::util::ref_ptr > empty[] = { }; cw::util::ref_ptr > e = or_e::create(empty, empty); CPPUNIT_ASSERT(!e->get_value()); } private: cw::util::ref_ptr getOrSingleton(cw::util::ref_ptr > v1) { cw::util::ref_ptr > subexprs_begin[] = { v1 }; cw::util::ref_ptr > *subexprs_end = subexprs_begin + sizeof(subexprs_begin) / sizeof(subexprs_begin[0]); return or_e::create(subexprs_begin, subexprs_end); } public: void testOrSingletonRaise() { cw::util::ref_ptr > v1 = var_e::create(false); cw::util::ref_ptr e = getOrSingleton(v1); cw::util::ref_ptr > e_wrap = fake_container::create(e); CPPUNIT_ASSERT(!e->get_value()); v1->set_value(true); CPPUNIT_ASSERT(e->get_value()); std::vector > expected; expected.push_back(child_modified_call(e, false, true)); CPPUNIT_ASSERT_EQUAL(expected, e_wrap->get_calls()); } void testOrSingletonLower() { cw::util::ref_ptr > v1 = var_e::create(true); cw::util::ref_ptr e = getOrSingleton(v1); cw::util::ref_ptr > e_wrap = fake_container::create(e); CPPUNIT_ASSERT(e->get_value()); v1->set_value(false); CPPUNIT_ASSERT(!e->get_value()); std::vector > expected; expected.push_back(child_modified_call(e, true, false)); CPPUNIT_ASSERT_EQUAL(expected, e_wrap->get_calls()); } void testOrSingletonLowerByRemoving() { cw::util::ref_ptr > v1 = var_e::create(true); cw::util::ref_ptr e = getOrSingleton(v1); cw::util::ref_ptr > e_wrap = fake_container::create(e); CPPUNIT_ASSERT(e->get_value()); e->remove_child(v1); CPPUNIT_ASSERT(!e->get_value()); std::vector > expected; expected.push_back(child_modified_call(e, true, false)); CPPUNIT_ASSERT_EQUAL(expected, e_wrap->get_calls()); } void testOrSingletonRaiseByAppending() { cw::util::ref_ptr > v1 = var_e::create(false); cw::util::ref_ptr e = getOrSingleton(v1); cw::util::ref_ptr > e_wrap = fake_container::create(e); CPPUNIT_ASSERT(!e->get_value()); e->add_child(var_e::create(true)); CPPUNIT_ASSERT(e->get_value()); std::vector > expected; expected.push_back(child_modified_call(e, false, true)); CPPUNIT_ASSERT_EQUAL(expected, e_wrap->get_calls()); } void testOrSingletonNull() { cw::util::ref_ptr e = getOrSingleton(cw::util::ref_ptr >()); CPPUNIT_ASSERT(e->get_value()); } private: cw::util::ref_ptr getOrDoubleton(const cw::util::ref_ptr > &v1, const cw::util::ref_ptr > &v2) { cw::util::ref_ptr > subexprs_begin[] = { v1, v2 }; cw::util::ref_ptr > *subexprs_end = subexprs_begin + sizeof(subexprs_begin) / sizeof(subexprs_begin[0]); return or_e::create(subexprs_begin, subexprs_end); } public: void testOrDoubletonFirstNull() { cw::util::ref_ptr > v1, v2 = var_e::create(false); cw::util::ref_ptr e = getOrDoubleton(v1, v2); CPPUNIT_ASSERT(e->get_value()); } void testOrDoubletonSecondNull() { cw::util::ref_ptr > v1 = var_e::create(false), v2; cw::util::ref_ptr e = getOrDoubleton(v1, v2); CPPUNIT_ASSERT(e->get_value()); } void testOrDoubletonBothNull() { cw::util::ref_ptr > v1, v2; cw::util::ref_ptr e = getOrDoubleton(v1, v2); CPPUNIT_ASSERT(e->get_value()); } void testOrDoubletonRaiseFirst() { cw::util::ref_ptr > v1 = var_e::create(false), v2 = var_e::create(false); cw::util::ref_ptr e = getOrDoubleton(v1, v2); cw::util::ref_ptr > e_wrap = fake_container::create(e); CPPUNIT_ASSERT(!e->get_value()); v1->set_value(true); CPPUNIT_ASSERT(e->get_value()); std::vector > expected; expected.push_back(child_modified_call(e, false, true)); CPPUNIT_ASSERT_EQUAL(expected, e_wrap->get_calls()); } void testOrDoubletonRaiseSecond() { cw::util::ref_ptr > v1 = var_e::create(false), v2 = var_e::create(false); cw::util::ref_ptr e = getOrDoubleton(v1, v2); cw::util::ref_ptr > e_wrap = fake_container::create(e); CPPUNIT_ASSERT(!e->get_value()); v2->set_value(true); CPPUNIT_ASSERT(e->get_value()); std::vector > expected; expected.push_back(child_modified_call(e, false, true)); CPPUNIT_ASSERT_EQUAL(expected, e_wrap->get_calls()); } void testOrDoubletonRaiseFirstNoEffect() { cw::util::ref_ptr > v1 = var_e::create(false), v2 = var_e::create(true); cw::util::ref_ptr e = getOrDoubleton(v1, v2); cw::util::ref_ptr > e_wrap = fake_container::create(e); CPPUNIT_ASSERT(e->get_value()); v1->set_value(true); CPPUNIT_ASSERT(e->get_value()); std::vector > expected; CPPUNIT_ASSERT_EQUAL(expected, e_wrap->get_calls()); } void testOrDoubletonRaiseSecondNoEffect() { cw::util::ref_ptr > v1 = var_e::create(true), v2 = var_e::create(false); cw::util::ref_ptr e = getOrDoubleton(v1, v2); cw::util::ref_ptr > e_wrap = fake_container::create(e); CPPUNIT_ASSERT(e->get_value()); v2->set_value(true); CPPUNIT_ASSERT(e->get_value()); std::vector > expected; CPPUNIT_ASSERT_EQUAL(expected, e_wrap->get_calls()); } void testOrDoubletonLowerFirst() { cw::util::ref_ptr > v1 = var_e::create(true), v2 = var_e::create(false); cw::util::ref_ptr e = getOrDoubleton(v1, v2); cw::util::ref_ptr > e_wrap = fake_container::create(e); CPPUNIT_ASSERT(e->get_value()); v1->set_value(false); CPPUNIT_ASSERT(!e->get_value()); std::vector > expected; expected.push_back(child_modified_call(e, true, false)); CPPUNIT_ASSERT_EQUAL(expected, e_wrap->get_calls()); } void testOrDoubletonLowerSecond() { cw::util::ref_ptr > v1 = var_e::create(false), v2 = var_e::create(true); cw::util::ref_ptr e = getOrDoubleton(v1, v2); cw::util::ref_ptr > e_wrap = fake_container::create(e); CPPUNIT_ASSERT(e->get_value()); v2->set_value(false); CPPUNIT_ASSERT(!e->get_value()); std::vector > expected; expected.push_back(child_modified_call(e, true, false)); CPPUNIT_ASSERT_EQUAL(expected, e_wrap->get_calls()); } void testOrDoubletonLowerFirstNoEffect() { cw::util::ref_ptr > v1 = var_e::create(true), v2 = var_e::create(true); cw::util::ref_ptr e = getOrDoubleton(v1, v2); cw::util::ref_ptr > e_wrap = fake_container::create(e); CPPUNIT_ASSERT(e->get_value()); v1->set_value(false); CPPUNIT_ASSERT(e->get_value()); std::vector > expected; CPPUNIT_ASSERT_EQUAL(expected, e_wrap->get_calls()); } void testOrDoubletonLowerSecondNoEffect() { cw::util::ref_ptr > v1 = var_e::create(true), v2 = var_e::create(true); cw::util::ref_ptr e = getOrDoubleton(v1, v2); cw::util::ref_ptr > e_wrap = fake_container::create(e); CPPUNIT_ASSERT(e->get_value()); v2->set_value(false); CPPUNIT_ASSERT(e->get_value()); std::vector > expected; CPPUNIT_ASSERT_EQUAL(expected, e_wrap->get_calls()); } }; CPPUNIT_TEST_SUITE_REGISTRATION(TestIncrementalExpression);