mirror of https://github.com/KLayout/klayout.git
ReportDatabase#merge - a method to merge two report databases
This commit is contained in:
parent
8a594c1626
commit
992947f748
|
|
@ -1676,6 +1676,15 @@ Class<rdb::Database> decl_ReportDatabase ("rdb", "ReportDatabase",
|
|||
"\n"
|
||||
"This method has been added in version 0.29.1."
|
||||
) +
|
||||
gsi::method ("merge", &rdb::Database::merge, gsi::arg ("other"),
|
||||
"@brief Merges the other database with this one\n"
|
||||
"This method will merge the other database with this one. The other database needs to have the same top cell than\n"
|
||||
"this database. In the merge step, identical cells and categories will be identified and missing cells or categories\n"
|
||||
"will be created in this database. After that, all items will be transferred from the other database into this one\n"
|
||||
"and will be associated with cells and categories from this database.\n"
|
||||
"\n"
|
||||
"This method has been added in version 0.30.7."
|
||||
) +
|
||||
gsi::method ("is_modified?", &rdb::Database::is_modified,
|
||||
"@brief Returns a value indicating whether the database has been modified\n"
|
||||
) +
|
||||
|
|
|
|||
|
|
@ -958,11 +958,18 @@ Tags::tag (id_type id)
|
|||
void
|
||||
Tags::import_tag (const Tag &t)
|
||||
{
|
||||
Tag &tt = tag (t.name (), t.is_user_tag ());
|
||||
tt.set_description (t.description ());
|
||||
import_tag_with_ref (t);
|
||||
}
|
||||
|
||||
bool
|
||||
Tag &
|
||||
Tags::import_tag_with_ref (const Tag &t)
|
||||
{
|
||||
Tag &tt = tag (t.name (), t.is_user_tag ());
|
||||
tt.set_description (t.description ());
|
||||
return tt;
|
||||
}
|
||||
|
||||
bool
|
||||
Tags::has_tag (const std::string &name, bool user_tag) const
|
||||
{
|
||||
return m_ids_for_names.find (std::make_pair (name, user_tag)) != m_ids_for_names.end ();
|
||||
|
|
@ -1314,6 +1321,13 @@ Database::import_tags (const Tags &tags)
|
|||
}
|
||||
}
|
||||
|
||||
Tag &
|
||||
Database::import_tag (const Tag &tag)
|
||||
{
|
||||
set_modified ();
|
||||
return m_tags.import_tag_with_ref (tag);
|
||||
}
|
||||
|
||||
void
|
||||
Database::import_categories (Categories *categories)
|
||||
{
|
||||
|
|
@ -1880,41 +1894,52 @@ namespace
|
|||
};
|
||||
}
|
||||
|
||||
static void map_category (const rdb::Category &cat, const rdb::Database &db, std::map<id_type, id_type> &cat2cat)
|
||||
static void map_category (const rdb::Category &cat, rdb::Database &db, std::map<id_type, id_type> &cat2cat, std::map<id_type, id_type> &rev_cat2cat, bool create_missing, rdb::Category *parent)
|
||||
{
|
||||
const rdb::Category *this_cat = db.category_by_name (cat.path ());
|
||||
rdb::Category *this_cat = db.category_by_name_non_const (cat.path ());
|
||||
if (! this_cat && create_missing) {
|
||||
this_cat = db.create_category (parent, cat.name ());
|
||||
this_cat->set_description (cat.description ());
|
||||
}
|
||||
if (this_cat) {
|
||||
cat2cat.insert (std::make_pair (this_cat->id (), cat.id ()));
|
||||
rev_cat2cat.insert (std::make_pair (cat.id (), this_cat->id ()));
|
||||
}
|
||||
|
||||
for (auto c = cat.sub_categories ().begin (); c != cat.sub_categories ().end (); ++c) {
|
||||
map_category (*c, db, cat2cat);
|
||||
map_category (*c, db, cat2cat, rev_cat2cat, create_missing, this_cat);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Database::apply (const rdb::Database &other)
|
||||
static void map_databases (rdb::Database &self, const rdb::Database &other,
|
||||
std::map<id_type, id_type> &cell2cell,
|
||||
std::map<id_type, id_type> &rev_cell2cell,
|
||||
std::map<id_type, id_type> &cat2cat,
|
||||
std::map<id_type, id_type> &rev_cat2cat,
|
||||
std::map<id_type, id_type> &tag2tag,
|
||||
std::map<id_type, id_type> &rev_tag2tag,
|
||||
bool create_missing)
|
||||
{
|
||||
std::map<id_type, id_type> cell2cell;
|
||||
std::map<id_type, id_type> cat2cat;
|
||||
std::map<id_type, id_type> tag2tag;
|
||||
std::map<id_type, id_type> rev_tag2tag;
|
||||
|
||||
for (auto c = other.cells ().begin (); c != other.cells ().end (); ++c) {
|
||||
// TODO: do we have a consistent scheme of naming variants? What requirements
|
||||
// exist towards detecting variant specific waivers
|
||||
const rdb::Cell *this_cell = cell_by_qname (c->qname ());
|
||||
rdb::Cell *this_cell = self.cell_by_qname_non_const (c->qname ());
|
||||
if (! this_cell && create_missing) {
|
||||
this_cell = self.create_cell (c->name (), c->variant (), c->layout_name ());
|
||||
this_cell->import_references (c->references ());
|
||||
}
|
||||
if (this_cell) {
|
||||
cell2cell.insert (std::make_pair (this_cell->id (), c->id ()));
|
||||
rev_cell2cell.insert (std::make_pair (c->id (), this_cell->id ()));
|
||||
}
|
||||
}
|
||||
|
||||
for (auto c = other.categories ().begin (); c != other.categories ().end (); ++c) {
|
||||
map_category (*c, *this, cat2cat);
|
||||
map_category (*c, self, cat2cat, rev_cat2cat, create_missing, 0);
|
||||
}
|
||||
|
||||
std::map<std::string, id_type> tags_by_name;
|
||||
for (auto c = tags ().begin_tags (); c != tags ().end_tags (); ++c) {
|
||||
for (auto c = self.tags ().begin_tags (); c != self.tags ().end_tags (); ++c) {
|
||||
tags_by_name.insert (std::make_pair (c->name (), c->id ()));
|
||||
}
|
||||
|
||||
|
|
@ -1923,8 +1948,25 @@ Database::apply (const rdb::Database &other)
|
|||
if (t != tags_by_name.end ()) {
|
||||
tag2tag.insert (std::make_pair (t->second, c->id ()));
|
||||
rev_tag2tag.insert (std::make_pair (c->id (), t->second));
|
||||
} else if (create_missing) {
|
||||
auto tt = self.import_tag (*c);
|
||||
tag2tag.insert (std::make_pair (tt.id (), c->id ()));
|
||||
rev_tag2tag.insert (std::make_pair (c->id (), tt.id ()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Database::apply (const rdb::Database &other)
|
||||
{
|
||||
std::map<id_type, id_type> cell2cell;
|
||||
std::map<id_type, id_type> rev_cell2cell;
|
||||
std::map<id_type, id_type> cat2cat;
|
||||
std::map<id_type, id_type> rev_cat2cat;
|
||||
std::map<id_type, id_type> tag2tag;
|
||||
std::map<id_type, id_type> rev_tag2tag;
|
||||
|
||||
map_databases (*this, other, cell2cell, rev_cell2cell, cat2cat, rev_cat2cat, tag2tag, rev_tag2tag, false);
|
||||
|
||||
std::map<std::pair<id_type, id_type>, ValueMapEntry> value_map;
|
||||
|
||||
|
|
@ -1963,6 +2005,50 @@ Database::apply (const rdb::Database &other)
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
Database::merge (const Database &other)
|
||||
{
|
||||
if (top_cell_name () != other.top_cell_name ()) {
|
||||
throw tl::Exception (tl::to_string (tr ("Merging of RDB databases requires identical top cell names")));
|
||||
}
|
||||
|
||||
std::map<id_type, id_type> cell2cell;
|
||||
std::map<id_type, id_type> rev_cell2cell;
|
||||
std::map<id_type, id_type> cat2cat;
|
||||
std::map<id_type, id_type> rev_cat2cat;
|
||||
std::map<id_type, id_type> tag2tag;
|
||||
std::map<id_type, id_type> rev_tag2tag;
|
||||
|
||||
map_databases (*this, other, cell2cell, rev_cell2cell, cat2cat, rev_cat2cat, tag2tag, rev_tag2tag, true);
|
||||
|
||||
for (Items::const_iterator i = other.items ().begin (); i != other.items ().end (); ++i) {
|
||||
|
||||
auto icell = rev_cell2cell.find (i->cell_id ());
|
||||
if (icell == rev_cell2cell.end ()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
auto icat = rev_cat2cat.find (i->category_id ());
|
||||
if (icat == rev_cat2cat.end ()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
rdb::Item *this_item = create_item (icell->second, icat->second);
|
||||
|
||||
this_item->set_values (i->values ());
|
||||
this_item->set_multiplicity (i->multiplicity ());
|
||||
this_item->set_comment (i->comment ());
|
||||
this_item->set_image_str (i->image_str ());
|
||||
|
||||
for (auto tt = rev_tag2tag.begin (); tt != rev_tag2tag.end (); ++tt) {
|
||||
if (i->has_tag (tt->first)) {
|
||||
this_item->add_tag (tt->second);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Database::scan_layout (const db::Layout &layout, db::cell_index_type cell_index, const std::vector<std::pair<unsigned int, std::string> > &layers_and_descriptions, bool flat)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1987,6 +1987,11 @@ public:
|
|||
*/
|
||||
void import_tag (const Tag &tag);
|
||||
|
||||
/**
|
||||
* @brief Import a tag and returns the reference for the new tag
|
||||
*/
|
||||
Tag &import_tag_with_ref (const Tag &tag);
|
||||
|
||||
/**
|
||||
* @brief Clear the collection of tags
|
||||
*/
|
||||
|
|
@ -2143,6 +2148,11 @@ public:
|
|||
*/
|
||||
void import_tags (const Tags &tags);
|
||||
|
||||
/**
|
||||
* @brief Import a tag
|
||||
*/
|
||||
Tag &import_tag (const Tag &tag);
|
||||
|
||||
/**
|
||||
* @brief Get the reference to the categories collection (const version)
|
||||
*/
|
||||
|
|
@ -2478,6 +2488,17 @@ public:
|
|||
*/
|
||||
void apply (const rdb::Database &other);
|
||||
|
||||
/**
|
||||
* @brief Merges another database to this one
|
||||
*
|
||||
* Merging requires the other database to have the same top cell.
|
||||
* Merging involves:
|
||||
* * categories present in other, but not in *this will be created (based on category name and parent category)
|
||||
* * cells present in other, but not in *this will be created (based on cell name and variant)
|
||||
* * items will be transferred from other to *this based on cell and category
|
||||
*/
|
||||
void merge (const rdb::Database &other);
|
||||
|
||||
/**
|
||||
* @brief Scans a layout into this RDB
|
||||
*
|
||||
|
|
|
|||
|
|
@ -822,3 +822,250 @@ TEST(13_ApplyIgnoreUnknownTag)
|
|||
EXPECT_EQ (i1->tag_str (), "tag2");
|
||||
}
|
||||
|
||||
TEST(20_MergeBasic)
|
||||
{
|
||||
rdb::Database db1;
|
||||
db1.set_top_cell_name ("A");
|
||||
|
||||
rdb::Database db2;
|
||||
db1.set_top_cell_name ("B");
|
||||
|
||||
try {
|
||||
// can't merge DB's with different top cell names
|
||||
db1.merge (db2);
|
||||
EXPECT_EQ (0, 1);
|
||||
} catch (...) { }
|
||||
|
||||
db1.set_top_cell_name ("TOP");
|
||||
db2.set_top_cell_name ("TOP");
|
||||
db1.merge (db2);
|
||||
|
||||
{
|
||||
rdb::Cell *cell = db2.create_cell ("A", "VAR", "ALAY");
|
||||
|
||||
rdb::Category *pcat = db2.create_category ("PCAT");
|
||||
rdb::Category *cat = db2.create_category (pcat, "CAT");
|
||||
cat->set_description ("A child category");
|
||||
|
||||
// create two tags
|
||||
/*auto t1_id =*/ db2.tags ().tag ("T1").id ();
|
||||
auto t2_id = db2.tags ().tag ("T2", true).id ();
|
||||
|
||||
rdb::Item *item = db2.create_item (cell->id (), cat->id ());
|
||||
item->set_comment ("Comment");
|
||||
item->add_tag (t2_id);
|
||||
item->set_image_str ("%nonsense%");
|
||||
item->set_multiplicity (42);
|
||||
item->add_value (db::DBox (0, 0, 1.0, 1.5));
|
||||
item->add_value (42.0);
|
||||
}
|
||||
|
||||
db1.merge (db2);
|
||||
|
||||
auto c = db1.cells ().begin ();
|
||||
tl_assert (c != db1.cells ().end ());
|
||||
const rdb::Cell *cell = c.operator-> ();
|
||||
++c;
|
||||
EXPECT_EQ (c == db1.cells ().end (), true);
|
||||
EXPECT_EQ (cell->name (), "A");
|
||||
EXPECT_EQ (cell->variant (), "VAR");
|
||||
EXPECT_EQ (cell->layout_name (), "ALAY");
|
||||
|
||||
const rdb::Category *cat = db1.category_by_name ("PCAT.CAT");
|
||||
tl_assert (cat != 0);
|
||||
EXPECT_EQ (cat->name (), "CAT");
|
||||
EXPECT_EQ (cat->path (), "PCAT.CAT");
|
||||
EXPECT_EQ (cat->description (), "A child category");
|
||||
EXPECT_EQ (cat->num_items (), size_t (1));
|
||||
|
||||
auto i = db1.items ().begin ();
|
||||
tl_assert (i != db1.items ().end ());
|
||||
const rdb::Item *item = i.operator-> ();
|
||||
++i;
|
||||
EXPECT_EQ (i == db1.items ().end (), true);
|
||||
EXPECT_EQ (item->category_id (), cat->id ());
|
||||
EXPECT_EQ (item->cell_id (), cell->id ());
|
||||
EXPECT_EQ (item->comment (), "Comment");
|
||||
EXPECT_EQ (item->multiplicity (), size_t (42));
|
||||
EXPECT_EQ (item->has_image (), true);
|
||||
EXPECT_EQ (item->image_str (), "%nonsense%")
|
||||
EXPECT_EQ (item->values ().to_string (&db1), "box: (0,0;1,1.5);float: 42");
|
||||
EXPECT_EQ (item->tag_str (), "#T2");
|
||||
}
|
||||
|
||||
TEST(21_MergeCategories)
|
||||
{
|
||||
rdb::Database db1;
|
||||
db1.set_top_cell_name ("TOP");
|
||||
|
||||
rdb::Database db2;
|
||||
db2.set_top_cell_name ("TOP");
|
||||
|
||||
{
|
||||
rdb::Category *pcat = db1.create_category ("PCAT");
|
||||
pcat->set_description ("db1");
|
||||
rdb::Category *cat = db1.create_category (pcat, "CAT");
|
||||
cat->set_description ("db1");
|
||||
}
|
||||
|
||||
{
|
||||
rdb::Category *pcat = db2.create_category ("PCAT");
|
||||
pcat->set_description ("db2a");
|
||||
rdb::Category *cat2 = db2.create_category (pcat, "CAT2");
|
||||
cat2->set_description ("db2a");
|
||||
|
||||
rdb::Category *pcat2 = db2.create_category ("PCAT2");
|
||||
pcat2->set_description ("db2b");
|
||||
rdb::Category *cat3 = db2.create_category (pcat2, "CAT3");
|
||||
cat3->set_description ("db2b");
|
||||
}
|
||||
|
||||
db1.merge (db2);
|
||||
|
||||
const rdb::Category *cat;
|
||||
|
||||
cat = db1.category_by_name ("PCAT");
|
||||
tl_assert (cat != 0);
|
||||
EXPECT_EQ (cat->name (), "PCAT");
|
||||
EXPECT_EQ (cat->description (), "db1");
|
||||
|
||||
cat = db1.category_by_name ("PCAT2");
|
||||
tl_assert (cat != 0);
|
||||
EXPECT_EQ (cat->name (), "PCAT2");
|
||||
EXPECT_EQ (cat->description (), "db2b");
|
||||
|
||||
cat = db1.category_by_name ("PCAT.CAT");
|
||||
tl_assert (cat != 0);
|
||||
EXPECT_EQ (cat->name (), "CAT");
|
||||
EXPECT_EQ (cat->description (), "db1");
|
||||
|
||||
cat = db1.category_by_name ("PCAT.CAT2");
|
||||
tl_assert (cat != 0);
|
||||
EXPECT_EQ (cat->name (), "CAT2");
|
||||
EXPECT_EQ (cat->description (), "db2a");
|
||||
|
||||
cat = db1.category_by_name ("PCAT2.CAT3");
|
||||
tl_assert (cat != 0);
|
||||
EXPECT_EQ (cat->name (), "CAT3");
|
||||
EXPECT_EQ (cat->description (), "db2b");
|
||||
|
||||
int ncat = 0;
|
||||
for (auto c = db1.categories ().begin (); c != db1.categories ().end (); ++c) {
|
||||
++ncat;
|
||||
for (auto s = c->sub_categories ().begin (); s != c->sub_categories ().end (); ++s) {
|
||||
++ncat;
|
||||
}
|
||||
}
|
||||
EXPECT_EQ (ncat, 5);
|
||||
}
|
||||
|
||||
TEST(22_MergeCells)
|
||||
{
|
||||
rdb::Database db1;
|
||||
db1.set_top_cell_name ("TOP");
|
||||
|
||||
rdb::Database db2;
|
||||
db2.set_top_cell_name ("TOP");
|
||||
|
||||
{
|
||||
rdb::Cell *parent;
|
||||
parent = db1.create_cell ("TOP");
|
||||
|
||||
rdb::Cell *cell;
|
||||
cell = db1.create_cell ("A");
|
||||
cell->references ().insert (rdb::Reference (db::DCplxTrans (db::DVector (1.0, 2.0)), parent->id ()));
|
||||
cell = db1.create_cell ("A", "VAR1", "ALAY");
|
||||
cell->references ().insert (rdb::Reference (db::DCplxTrans (db::DVector (1.0, -2.0)), parent->id ()));
|
||||
}
|
||||
|
||||
{
|
||||
rdb::Cell *parent;
|
||||
parent = db2.create_cell ("TOP");
|
||||
|
||||
rdb::Cell *cell;
|
||||
cell = db2.create_cell ("B");
|
||||
cell->references ().insert (rdb::Reference (db::DCplxTrans (db::DVector (1.0, 0.0)), parent->id ()));
|
||||
cell = db2.create_cell ("A");
|
||||
cell->references ().insert (rdb::Reference (db::DCplxTrans (db::DVector (1.0, 2.5)), parent->id ())); // reference not taken!
|
||||
cell = db2.create_cell ("A", "VAR2", "ALAY");
|
||||
cell->references ().insert (rdb::Reference (db::DCplxTrans (db::DVector (1.0, -1.0)), parent->id ()));
|
||||
}
|
||||
|
||||
db1.merge (db2);
|
||||
|
||||
std::set<std::string> cells;
|
||||
for (auto c = db1.cells ().begin (); c != db1.cells ().end (); ++c) {
|
||||
if (c->references ().begin () != c->references ().end ()) {
|
||||
cells.insert (c->qname () + "[" + c->references ().begin ()->trans_str () + "]");
|
||||
} else {
|
||||
cells.insert (c->qname ());
|
||||
}
|
||||
}
|
||||
|
||||
EXPECT_EQ (tl::join (cells.begin (), cells.end (), ";"), "A:1[r0 *1 1,2];A:VAR1[r0 *1 1,-2];A:VAR2[r0 *1 1,-1];B[r0 *1 1,0];TOP");
|
||||
}
|
||||
|
||||
TEST(23_MergeTags)
|
||||
{
|
||||
rdb::Database db1;
|
||||
db1.set_top_cell_name ("TOP");
|
||||
|
||||
rdb::Database db2;
|
||||
db2.set_top_cell_name ("TOP");
|
||||
|
||||
db1.tags ().tag ("T1");
|
||||
db1.tags ().tag ("T2");
|
||||
|
||||
db2.tags ().tag ("T1");
|
||||
db2.tags ().tag ("T3", true);
|
||||
|
||||
db1.merge (db2);
|
||||
|
||||
std::set<std::string> tags;
|
||||
for (auto t = db1.tags ().begin_tags (); t != db1.tags ().end_tags (); ++t) {
|
||||
tags.insert (t->is_user_tag () ? "#" + t->name () : t->name ());
|
||||
}
|
||||
EXPECT_EQ (tl::join (tags.begin (), tags.end (), ";"), "#T3;T1;T2");
|
||||
}
|
||||
|
||||
TEST(24_MergeItems)
|
||||
{
|
||||
rdb::Database db1;
|
||||
db1.set_top_cell_name ("TOP");
|
||||
|
||||
rdb::Database db2;
|
||||
db2.set_top_cell_name ("TOP");
|
||||
|
||||
{
|
||||
rdb::Cell *cell = db1.create_cell ("TOP");
|
||||
rdb::Category *cat1 = db1.create_category ("CAT1");
|
||||
rdb::Category *cat2 = db1.create_category ("CAT2");
|
||||
|
||||
rdb::Item *item;
|
||||
item = db1.create_item (cell->id (), cat1->id ());
|
||||
item->set_comment ("db1a");
|
||||
item = db1.create_item (cell->id (), cat2->id ());
|
||||
item->set_comment ("db1b");
|
||||
}
|
||||
|
||||
{
|
||||
rdb::Cell *cell = db2.create_cell ("TOP");
|
||||
rdb::Category *cat1 = db2.create_category ("CAT1");
|
||||
rdb::Category *cat3 = db2.create_category ("CAT3");
|
||||
|
||||
rdb::Item *item;
|
||||
item = db2.create_item (cell->id (), cat1->id ());
|
||||
item->set_comment ("db2a");
|
||||
item = db2.create_item (cell->id (), cat3->id ());
|
||||
item->set_comment ("db2b");
|
||||
}
|
||||
|
||||
db1.merge (db2);
|
||||
|
||||
std::set<std::string> items;
|
||||
for (auto i = db1.items ().begin (); i != db1.items ().end (); ++i) {
|
||||
const rdb::Item *item = i.operator-> ();
|
||||
items.insert (item->cell_qname () + ":" + item->category_name () + "=" + item->comment ());
|
||||
}
|
||||
EXPECT_EQ (tl::join (items.begin (), items.end (), ";"), "TOP:CAT1=db1a;TOP:CAT1=db2a;TOP:CAT2=db1b;TOP:CAT3=db2b");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1205,6 +1205,77 @@ class RDB_TestClass < TestBase
|
|||
|
||||
end
|
||||
|
||||
# apply
|
||||
def test_16
|
||||
|
||||
rdb1 = RBA::ReportDatabase::new
|
||||
cat = rdb1.create_category("CAT")
|
||||
cell = rdb1.create_cell("TOP")
|
||||
item = rdb1.create_item(cell, cat)
|
||||
item.add_value("item1")
|
||||
item.add_tag(rdb1.tag_id("t1"))
|
||||
|
||||
assert_equal(item.tags_str, "t1")
|
||||
|
||||
rdb2 = RBA::ReportDatabase::new
|
||||
cat = rdb2.create_category("CAT")
|
||||
cell = rdb2.create_cell("TOP")
|
||||
item = rdb2.create_item(cell, cat)
|
||||
item.add_value("item1")
|
||||
item.add_tag(rdb2.tag_id("t2"))
|
||||
|
||||
assert_equal(item.tags_str, "t2")
|
||||
|
||||
items = rdb1.each_item.to_a
|
||||
assert_equal(items.size, 1)
|
||||
|
||||
assert_equal(items[0].tags_str, "t1")
|
||||
|
||||
rdb1.apply(rdb2)
|
||||
|
||||
items = rdb1.each_item.to_a
|
||||
assert_equal(items.size, 1)
|
||||
|
||||
assert_equal(items[0].tags_str, "t2")
|
||||
|
||||
end
|
||||
|
||||
# merge
|
||||
def test_17
|
||||
|
||||
rdb1 = RBA::ReportDatabase::new
|
||||
cat = rdb1.create_category("CAT")
|
||||
cell = rdb1.create_cell("TOP")
|
||||
item = rdb1.create_item(cell, cat)
|
||||
item.add_value("item1")
|
||||
item.add_tag(rdb1.tag_id("t1"))
|
||||
|
||||
assert_equal(item.tags_str, "t1")
|
||||
|
||||
rdb2 = RBA::ReportDatabase::new
|
||||
cat = rdb2.create_category("CAT")
|
||||
cell = rdb2.create_cell("TOP")
|
||||
item = rdb2.create_item(cell, cat)
|
||||
item.add_value("item1")
|
||||
item.add_tag(rdb2.tag_id("t2"))
|
||||
|
||||
assert_equal(item.tags_str, "t2")
|
||||
|
||||
items = rdb1.each_item.to_a
|
||||
assert_equal(items.size, 1)
|
||||
|
||||
assert_equal(items[0].tags_str, "t1")
|
||||
|
||||
rdb1.merge(rdb2)
|
||||
|
||||
items = rdb1.each_item.to_a
|
||||
assert_equal(items.size, 2)
|
||||
|
||||
assert_equal(items[0].tags_str, "t1")
|
||||
assert_equal(items[1].tags_str, "t2")
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
load("test_epilogue.rb")
|
||||
|
|
|
|||
Loading…
Reference in New Issue