mirror of https://github.com/KLayout/klayout.git
233 lines
4.9 KiB
C++
233 lines
4.9 KiB
C++
|
|
/*
|
|
|
|
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<AO *> (op);
|
|
x -= aop->d;
|
|
}
|
|
|
|
void redo (db::Op *op)
|
|
{
|
|
AO *aop = dynamic_cast<AO *> (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<BO *> (op);
|
|
x -= bop->d;
|
|
}
|
|
|
|
void redo (db::Op *op)
|
|
{
|
|
BO *bop = dynamic_cast<BO *> (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);
|
|
}
|
|
|