klayout/src/buddies/unit_tests/bdBasicTests.cc

354 lines
15 KiB
C++

/*
KLayout Layout Viewer
Copyright (C) 2006-2024 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 "bdWriterOptions.h"
#include "bdReaderOptions.h"
#include "tlCommandLineParser.h"
#include "tlUnitTest.h"
#include "dbLayout.h"
#include "dbCell.h"
#include "dbSaveLayoutOptions.h"
// Testing writer options
TEST(1)
{
bd::GenericWriterOptions opt;
tl::CommandLineOptions cmd;
opt.add_options (cmd);
const char *argv[] = {
"x",
"-os=1.25",
"-od=0.125",
"--drop-empty-cells",
"--keep-instances",
"--no-context-info",
// CIF
"--blank-separator",
"--dummy-calls",
// DXF
"-op=2",
// GDS2
"-ol=MYLIBNAME",
"-ov=250",
"--multi-xy-records",
"--no-timestamps",
"--no-zero-length-paths",
"--user-units=2.5",
"--write-cell-properties",
"--write-file-properties",
// OASIS
"-ob=false",
"-ok=9",
"-ot=false",
"--recompress",
"--subst-char=XY",
"--write-std-properties=2"
};
cmd.parse (sizeof (argv) / sizeof (argv[0]), const_cast<char **> (argv));
db::Layout layout;
db::SaveLayoutOptions stream_opt;
EXPECT_EQ (stream_opt.dont_write_empty_cells (), false);
EXPECT_EQ (stream_opt.keep_instances (), false);
EXPECT_EQ (stream_opt.write_context_info (), true);
EXPECT_EQ (stream_opt.get_option_by_name ("cif_blank_separator").to_bool (), false);
EXPECT_EQ (stream_opt.get_option_by_name ("cif_dummy_calls").to_bool (), false);
EXPECT_EQ (stream_opt.get_option_by_name ("dxf_polygon_mode").to_int (), 0);
EXPECT_EQ (stream_opt.get_option_by_name ("gds2_libname").to_string (), "LIB");
EXPECT_EQ (stream_opt.get_option_by_name ("gds2_max_vertex_count").to_uint (), (unsigned int) 8000);
EXPECT_EQ (stream_opt.get_option_by_name ("gds2_multi_xy_records").to_bool (), false);
EXPECT_EQ (stream_opt.get_option_by_name ("gds2_write_timestamps").to_bool (), true);
EXPECT_EQ (stream_opt.get_option_by_name ("gds2_no_zero_length_paths").to_bool (), false);
EXPECT_EQ (tl::to_string (stream_opt.get_option_by_name ("gds2_user_units").to_double ()), "1");
EXPECT_EQ (stream_opt.get_option_by_name ("gds2_write_cell_properties").to_bool (), false);
EXPECT_EQ (stream_opt.get_option_by_name ("gds2_write_file_properties").to_bool (), false);
EXPECT_EQ (stream_opt.get_option_by_name ("oasis_write_cblocks").to_bool (), true);
EXPECT_EQ (stream_opt.get_option_by_name ("oasis_compression_level").to_int (), 2);
EXPECT_EQ (stream_opt.get_option_by_name ("oasis_strict_mode").to_bool (), true);
EXPECT_EQ (stream_opt.get_option_by_name ("oasis_recompress").to_bool (), false);
EXPECT_EQ (stream_opt.get_option_by_name ("oasis_substitution_char").to_string (), "*");
EXPECT_EQ (stream_opt.get_option_by_name ("oasis_write_std_properties_ext").to_int (), 1);
opt.configure (stream_opt, layout);
EXPECT_EQ (stream_opt.scale_factor (), 1.25);
EXPECT_EQ (stream_opt.dbu (), 0.125);
EXPECT_EQ (stream_opt.dont_write_empty_cells (), true);
EXPECT_EQ (stream_opt.keep_instances (), true);
EXPECT_EQ (stream_opt.write_context_info (), false);
EXPECT_EQ (stream_opt.get_option_by_name ("cif_blank_separator").to_bool (), true);
EXPECT_EQ (stream_opt.get_option_by_name ("cif_dummy_calls").to_bool (), true);
EXPECT_EQ (stream_opt.get_option_by_name ("dxf_polygon_mode").to_int (), 2);
EXPECT_EQ (stream_opt.get_option_by_name ("gds2_libname").to_string (), "MYLIBNAME");
EXPECT_EQ (stream_opt.get_option_by_name ("gds2_max_vertex_count").to_uint (), (unsigned int) 250);
EXPECT_EQ (stream_opt.get_option_by_name ("gds2_multi_xy_records").to_bool (), true);
EXPECT_EQ (stream_opt.get_option_by_name ("gds2_write_timestamps").to_bool (), false);
EXPECT_EQ (stream_opt.get_option_by_name ("gds2_no_zero_length_paths").to_bool (), true);
EXPECT_EQ (tl::to_string (stream_opt.get_option_by_name ("gds2_user_units").to_double ()), "2.5");
EXPECT_EQ (stream_opt.get_option_by_name ("gds2_write_cell_properties").to_bool (), true);
EXPECT_EQ (stream_opt.get_option_by_name ("gds2_write_file_properties").to_bool (), true);
EXPECT_EQ (stream_opt.get_option_by_name ("oasis_write_cblocks").to_bool (), false);
EXPECT_EQ (stream_opt.get_option_by_name ("oasis_compression_level").to_int (), 9);
EXPECT_EQ (stream_opt.get_option_by_name ("oasis_strict_mode").to_bool (), false);
EXPECT_EQ (stream_opt.get_option_by_name ("oasis_recompress").to_bool (), true);
EXPECT_EQ (stream_opt.get_option_by_name ("oasis_substitution_char").to_string (), "X");
EXPECT_EQ (stream_opt.get_option_by_name ("oasis_write_std_properties_ext").to_int (), 2);
}
static std::string cells2string (const db::Layout &layout, const std::set<db::cell_index_type> &cells)
{
std::string res;
for (std::set<db::cell_index_type>::const_iterator c = cells.begin (); c != cells.end (); ++c) {
if (c != cells.begin ()) {
res += ",";
}
res += layout.cell_name (*c);
}
return res;
}
// Testing writer options: cell resolution
TEST(2)
{
// Build a layout with the hierarchy
// TOP -> A, B
// A -> B
// B -> C
// C -> D
db::Layout layout;
db::cell_index_type itop = layout.add_cell ("TOP");
db::cell_index_type ia = layout.add_cell ("A");
db::cell_index_type ib = layout.add_cell ("B");
db::cell_index_type ic = layout.add_cell ("C");
db::cell_index_type id = layout.add_cell ("D");
layout.cell (itop).insert (db::CellInstArray (ia, db::Trans ()));
layout.cell (itop).insert (db::CellInstArray (ib, db::Trans ()));
layout.cell (ia).insert (db::CellInstArray (ib, db::Trans ()));
layout.cell (ib).insert (db::CellInstArray (ic, db::Trans ()));
layout.cell (ic).insert (db::CellInstArray (id, db::Trans ()));
bd::GenericWriterOptions opt;
tl::CommandLineOptions cmd;
opt.add_options (cmd);
std::set <db::cell_index_type> cells;
std::vector <std::pair <unsigned int, db::LayerProperties> > valid_layers;
db::SaveLayoutOptions stream_opt;
{
const char *argv[] = { "x",
"--write-cells=A,-C,(C)",
};
cmd.parse (sizeof (argv) / sizeof (argv[0]), (char **) argv);
}
opt.configure (stream_opt, layout);
cells.clear ();
valid_layers.clear ();
stream_opt.get_cells (layout, cells, valid_layers);
EXPECT_EQ (cells2string (layout, cells), "A,B,C");
{
const char *argv[] = { "x",
"--write-cells=(C),(TOP)",
};
cmd.parse (sizeof (argv) / sizeof (argv[0]), (char **) argv);
}
opt.configure (stream_opt, layout);
cells.clear ();
valid_layers.clear ();
stream_opt.get_cells (layout, cells, valid_layers);
EXPECT_EQ (cells2string (layout, cells), "TOP,C");
{
const char *argv[] = { "x",
"--write-cells=(TOP),+B",
};
cmd.parse (sizeof (argv) / sizeof (argv[0]), (char **) argv);
}
opt.configure (stream_opt, layout);
cells.clear ();
valid_layers.clear ();
stream_opt.get_cells (layout, cells, valid_layers);
EXPECT_EQ (cells2string (layout, cells), "TOP,B,C,D");
}
// Testing reader options
TEST(10)
{
bd::GenericReaderOptions opt;
tl::CommandLineOptions cmd;
opt.add_options (cmd);
const char *argv[] = { "x",
// CIF and DXF
"-id=0.125",
// CIF
"-iw=1",
// DXF
"-iu=2.5",
"--dxf-circle-accuracy=0.5",
"--dxf-circle-points=1000",
"--dxf-keep-other-cells",
"--dxf-polyline-mode=3",
"--dxf-render-texts-as-polygons",
"--dxf-text-scaling=75",
// GDS2 and OASIS
"--no-properties",
"--no-texts",
// GDS2
"-ib=3",
"--no-big-records",
"--no-multi-xy-records",
// General
"-im=1/0 3,4/0-255 A:17/0",
"-is",
"--blend-mode=1",
// OASIS
"--expect-strict-mode=1"
};
cmd.parse (sizeof (argv) / sizeof (argv[0]), (char **) argv);
db::LoadLayoutOptions stream_opt;
EXPECT_EQ (tl::to_string (stream_opt.get_option_by_name ("cif_dbu").to_double ()), "0.001");
EXPECT_EQ (stream_opt.get_option_by_name ("cif_wire_mode").to_uint (), (unsigned int) 0);
EXPECT_EQ (stream_opt.get_option_by_name ("cif_layer_map").to_user<db::LayerMap> ().to_string (), "layer_map()");
EXPECT_EQ (stream_opt.get_option_by_name ("cif_create_other_layers").to_bool (), true);
EXPECT_EQ (tl::to_string (stream_opt.get_option_by_name ("dxf_dbu").to_double ()), "0.001");
EXPECT_EQ (stream_opt.get_option_by_name ("dxf_layer_map").to_user<db::LayerMap> ().to_string (), "layer_map()");
EXPECT_EQ (stream_opt.get_option_by_name ("dxf_create_other_layers").to_bool (), true);
EXPECT_EQ (stream_opt.get_option_by_name ("dxf_unit").to_double (), 1.0);
EXPECT_EQ (tl::to_string (stream_opt.get_option_by_name ("dxf_circle_accuracy").to_double ()), "0");
EXPECT_EQ (stream_opt.get_option_by_name ("dxf_circle_points").to_int (), 100);
EXPECT_EQ (stream_opt.get_option_by_name ("dxf_keep_other_cells").to_bool (), false);
EXPECT_EQ (stream_opt.get_option_by_name ("dxf_polyline_mode").to_int (), 0);
EXPECT_EQ (stream_opt.get_option_by_name ("dxf_render_texts_as_polygons").to_bool (), false);
EXPECT_EQ (stream_opt.get_option_by_name ("dxf_text_scaling").to_int (), 100);
EXPECT_EQ (stream_opt.get_option_by_name ("layer_map").to_user<db::LayerMap> ().to_string (), "layer_map()");
EXPECT_EQ (stream_opt.get_option_by_name ("create_other_layers").to_bool (), true);
EXPECT_EQ (stream_opt.get_option_by_name ("cell_conflict_resolution").to_string (), "AddToCell");
EXPECT_EQ (stream_opt.get_option_by_name ("properties_enabled").to_bool (), true);
EXPECT_EQ (stream_opt.get_option_by_name ("text_enabled").to_bool (), true);
EXPECT_EQ (stream_opt.get_option_by_name ("gds2_box_mode").to_uint (), (unsigned int) 1);
EXPECT_EQ (stream_opt.get_option_by_name ("gds2_allow_big_records").to_bool (), true);
EXPECT_EQ (stream_opt.get_option_by_name ("gds2_allow_multi_xy_records").to_bool (), true);
EXPECT_EQ (stream_opt.get_option_by_name ("oasis_expect_strict_mode").to_int (), -1);
opt.configure (stream_opt);
EXPECT_EQ (tl::to_string (stream_opt.get_option_by_name ("cif_dbu").to_double ()), "0.125");
EXPECT_EQ (stream_opt.get_option_by_name ("cif_wire_mode").to_uint (), (unsigned int) 1);
EXPECT_EQ (stream_opt.get_option_by_name ("cif_layer_map").to_user<db::LayerMap> ().to_string (), "layer_map('1/0';'3-4/0-255';'A : 17/0')");
EXPECT_EQ (stream_opt.get_option_by_name ("cif_create_other_layers").to_bool (), false);
EXPECT_EQ (tl::to_string (stream_opt.get_option_by_name ("dxf_dbu").to_double ()), "0.125");
EXPECT_EQ (stream_opt.get_option_by_name ("dxf_layer_map").to_user<db::LayerMap> ().to_string (), "layer_map('1/0';'3-4/0-255';'A : 17/0')");
EXPECT_EQ (stream_opt.get_option_by_name ("dxf_create_other_layers").to_bool (), false);
EXPECT_EQ (stream_opt.get_option_by_name ("dxf_unit").to_double (), 2.5);
EXPECT_EQ (tl::to_string (stream_opt.get_option_by_name ("dxf_circle_accuracy").to_double ()), "0.5");
EXPECT_EQ (stream_opt.get_option_by_name ("dxf_circle_points").to_int (), 1000);
EXPECT_EQ (stream_opt.get_option_by_name ("dxf_keep_other_cells").to_bool (), true);
EXPECT_EQ (stream_opt.get_option_by_name ("dxf_polyline_mode").to_int (), 3);
EXPECT_EQ (stream_opt.get_option_by_name ("dxf_render_texts_as_polygons").to_bool (), true);
EXPECT_EQ (stream_opt.get_option_by_name ("dxf_text_scaling").to_int (), 75);
EXPECT_EQ (stream_opt.get_option_by_name ("layer_map").to_user<db::LayerMap> ().to_string (), "layer_map('1/0';'3-4/0-255';'A : 17/0')");
EXPECT_EQ (stream_opt.get_option_by_name ("create_other_layers").to_bool (), false);
EXPECT_EQ (stream_opt.get_option_by_name ("cell_conflict_resolution").to_string (), "OverwriteCell");
EXPECT_EQ (stream_opt.get_option_by_name ("properties_enabled").to_bool (), false);
EXPECT_EQ (stream_opt.get_option_by_name ("text_enabled").to_bool (), false);
EXPECT_EQ (stream_opt.get_option_by_name ("gds2_box_mode").to_uint (), (unsigned int) 3);
EXPECT_EQ (stream_opt.get_option_by_name ("gds2_allow_big_records").to_bool (), false);
EXPECT_EQ (stream_opt.get_option_by_name ("gds2_allow_multi_xy_records").to_bool (), false);
EXPECT_EQ (stream_opt.get_option_by_name ("oasis_expect_strict_mode").to_int (), 1);
}
// Testing reader options - blend mode "Rename" is default
TEST(11)
{
bd::GenericReaderOptions opt;
tl::CommandLineOptions cmd;
opt.add_options (cmd);
const char *argv[] = { "x" };
cmd.parse (sizeof (argv) / sizeof (argv[0]), (char **) argv);
db::LoadLayoutOptions stream_opt;
opt.configure (stream_opt);
EXPECT_EQ (stream_opt.get_option_by_name ("cell_conflict_resolution").to_string (), "RenameCell");
}
// Testing writer options
TEST(12_issue1885)
{
bd::GenericWriterOptions opt;
tl::CommandLineOptions cmd;
opt.add_options (cmd);
db::Layout layout;
db::SaveLayoutOptions stream_opt;
opt.configure (stream_opt, layout);
EXPECT_EQ (stream_opt.get_option_by_name ("oasis_substitution_char").to_string (), "");
const char *argv[] = {
"x",
"--subst-char=x",
};
cmd.parse (sizeof (argv) / sizeof (argv[0]), const_cast<char **> (argv));
opt.configure (stream_opt, layout);
EXPECT_EQ (stream_opt.get_option_by_name ("oasis_substitution_char").to_string (), "x");
const char *argv2[] = {
"x",
"--subst-char=",
};
cmd.parse (sizeof (argv2) / sizeof (argv2[0]), const_cast<char **> (argv2));
opt.configure (stream_opt, layout);
EXPECT_EQ (stream_opt.get_option_by_name ("oasis_substitution_char").to_string (), "");
}