/* KLayout Layout Viewer Copyright (C) 2006-2019 Matthias Koefferlein 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; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "dbObject.h" #include "tlUnitTest.h" namespace { struct AO : public db::Op { AO (int dd) : d (dd) { ++ao_inst; } ~AO () { --ao_inst; } int d; static int inst_count () { return ao_inst; } static int ao_inst; }; int AO::ao_inst = 0; struct A : public db::Object { A (db::Manager *m) : db::Object (m), x (0) { } void add (int d) { if (transacting ()) { manager ()->queue (this, new AO (d)); } x += d; } void undo (db::Op *op) { AO *aop = dynamic_cast (op); x -= aop->d; } void redo (db::Op *op) { AO *aop = dynamic_cast (op); tl_assert (aop != 0); x += aop->d; } int x; }; } TEST(1) { db::Manager *man = new db::Manager (); { EXPECT_EQ (man->available_undo ().first, false); EXPECT_EQ (man->available_redo ().first, false); A a (man); man->transaction ("add 1"); a.add (1); man->commit (); EXPECT_EQ (a.x, 1); EXPECT_EQ (man->available_undo ().first, true); EXPECT_EQ (man->available_undo ().second, "add 1"); man->undo (); EXPECT_EQ (a.x, 0); EXPECT_EQ (man->available_undo ().first, false); EXPECT_EQ (man->available_redo ().first, true); EXPECT_EQ (man->available_redo ().second, "add 1"); man->redo (); EXPECT_EQ (man->available_redo ().first, false); EXPECT_EQ (a.x, 1); man->undo (); EXPECT_EQ (a.x, 0); EXPECT_EQ (man->available_undo ().first, false); man->transaction ("add 1,2"); a.add (1); a.add (2); man->commit (); EXPECT_EQ (a.x, 3); EXPECT_EQ (man->available_undo ().first, true); EXPECT_EQ (man->available_redo ().first, false); man->transaction ("add 3"); a.add (3); man->commit (); EXPECT_EQ (a.x, 6); man->undo (); EXPECT_EQ (a.x, 3); EXPECT_EQ (man->available_undo ().first, true); EXPECT_EQ (man->available_redo ().first, true); man->undo (); EXPECT_EQ (a.x, 0); EXPECT_EQ (man->available_undo ().first, false); EXPECT_EQ (man->available_redo ().first, true); } delete man; EXPECT_EQ (AO::inst_count (), 0); } // The same than above but with implicitly declared operations through // redo. namespace { struct BO : public db::Op { BO (int dd) : db::Op (false), d (dd) { ++bo_inst; } ~BO () { --bo_inst; } int d; static int inst_count () { return bo_inst; } static int bo_inst; }; int BO::bo_inst = 0; struct B : public db::Object { B (db::Manager *m) : db::Object (m), x (0) { } void add (int d) { if (transacting ()) { manager ()->queue (this, new BO (d)); } } void undo (db::Op *op) { BO *bop = dynamic_cast (op); x -= bop->d; } void redo (db::Op *op) { BO *bop = dynamic_cast (op); tl_assert (bop != 0); x += bop->d; } int x; }; } TEST(2) { db::Manager *man = new db::Manager (); { EXPECT_EQ (man->available_undo ().first, false); EXPECT_EQ (man->available_redo ().first, false); B b (man); man->transaction ("add 1"); b.add (1); man->commit (); EXPECT_EQ (b.x, 1); EXPECT_EQ (man->available_undo ().first, true); EXPECT_EQ (man->available_undo ().second, "add 1"); man->undo (); EXPECT_EQ (b.x, 0); EXPECT_EQ (man->available_undo ().first, false); EXPECT_EQ (man->available_redo ().first, true); EXPECT_EQ (man->available_redo ().second, "add 1"); man->redo (); EXPECT_EQ (man->available_redo ().first, false); EXPECT_EQ (b.x, 1); man->undo (); EXPECT_EQ (b.x, 0); EXPECT_EQ (man->available_undo ().first, false); man->transaction ("add 1,2"); b.add (1); b.add (2); man->commit (); EXPECT_EQ (b.x, 3); EXPECT_EQ (man->available_undo ().first, true); EXPECT_EQ (man->available_redo ().first, false); man->transaction ("add 3"); b.add (3); man->commit (); EXPECT_EQ (b.x, 6); man->undo (); EXPECT_EQ (b.x, 3); EXPECT_EQ (man->available_undo ().first, true); EXPECT_EQ (man->available_redo ().first, true); man->undo (); EXPECT_EQ (b.x, 0); EXPECT_EQ (man->available_undo ().first, false); EXPECT_EQ (man->available_redo ().first, true); } delete man; EXPECT_EQ (BO::inst_count (), 0); }