diff --git a/src/buddies/src/bd/strmclip.cc b/src/buddies/src/bd/strmclip.cc index e329b5242..74e43b583 100644 --- a/src/buddies/src/bd/strmclip.cc +++ b/src/buddies/src/bd/strmclip.cc @@ -193,7 +193,7 @@ BD_PUBLIC int strmclip (int argc, char *argv[]) "If given, this name will be used as the top cell name in the output file. " "By default the output's top cell will be \"CLIPPED_\" plus the input's top cell name." ) - << tl::arg ("*-r|--rect=\"l,b,r,t\"", &data, &ClipData::add_box, "Specifies a clip box", + << tl::arg ("*-r|--rect=\"l,b,r,t\"", &data, &ClipData::add_box, "Specifies a clip box", "This option specifies the box to clip in micrometer units. The box is given " "by left, bottom, right and top coordinates. This option can be used multiple times " "to produce a clip covering more than one rectangle." diff --git a/src/buddies/src/bd/strmcmp.cc b/src/buddies/src/bd/strmcmp.cc index 8f7c828ad..2bf4ca800 100644 --- a/src/buddies/src/bd/strmcmp.cc +++ b/src/buddies/src/bd/strmcmp.cc @@ -34,9 +34,9 @@ BD_PUBLIC int strmcmp (int argc, char *argv[]) generic_reader_options_a.set_group_prefix ("Input A"); bd::GenericReaderOptions generic_reader_options_b; - generic_reader_options_a.set_prefix ("b"); - generic_reader_options_a.set_long_prefix ("b-"); - generic_reader_options_a.set_group_prefix ("Input B"); + generic_reader_options_b.set_prefix ("b"); + generic_reader_options_b.set_long_prefix ("b-"); + generic_reader_options_b.set_group_prefix ("Input B"); std::string infile_a, infile_b; std::string top_a, top_b; @@ -133,7 +133,7 @@ BD_PUBLIC int strmcmp (int argc, char *argv[]) cmd.parse (argc, argv); if (top_a.empty () != top_b.empty ()) { - throw tl::Exception ("Both --top-a and --top-b top cells must be given"); + throw tl::Exception ("Both -ta|--top-a and -tb|--top-b top cells must be given"); } db::Layout layout_a; @@ -152,7 +152,7 @@ BD_PUBLIC int strmcmp (int argc, char *argv[]) db::LoadLayoutOptions load_options; generic_reader_options_b.configure (load_options); - tl::InputStream stream (infile_a); + tl::InputStream stream (infile_b); db::Reader reader (stream); reader.read (layout_b, load_options); } @@ -195,6 +195,30 @@ BD_PUBLIC int strmcmp (int argc, char *argv[]) db::Coord tolerance_dbu = db::coord_traits::rounded (tolerance / std::min (layout_a.dbu (), layout_b.dbu ())); bool result = false; + if (smart_cell_mapping && top_a.empty ()) { + + db::Layout::top_down_const_iterator t; + + t = layout_a.begin_top_down (); + if (t != layout_a.end_top_cells ()) { + top_a = layout_a.cell_name (*t); + ++t; + if (t != layout_a.end_top_cells ()) { + throw tl::Exception ("Top cell of first layout is not unique which is required for -c|--cell-mapping"); + } + } + + t = layout_b.begin_top_down (); + if (t != layout_b.end_top_cells ()) { + top_b = layout_b.cell_name (*t); + ++t; + if (t != layout_b.end_top_cells ()) { + throw tl::Exception ("Top cell of second layout is not unique which is required for -c|--cell-mapping"); + } + } + + } + if (! top_a.empty ()) { std::pair index_a = layout_a.cell_by_name (top_a.c_str ()); diff --git a/src/buddies/unit_tests/bdStrm2txtTests.cc b/src/buddies/unit_tests/bdStrm2txtTests.cc new file mode 100644 index 000000000..bfa924242 --- /dev/null +++ b/src/buddies/unit_tests/bdStrm2txtTests.cc @@ -0,0 +1,43 @@ + +/* + + KLayout Layout Viewer + Copyright (C) 2006-2017 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 "utHead.h" +#include "bdCommon.h" + +BD_PUBLIC int strm2txt (int argc, char *argv[]); + +TEST(1) +{ + std::string input = ut::testsrc (); + input += "/testdata/gds/t10.gds"; + + std::string au = ut::testsrc (); + au += "/testdata/bd/strm2txt_au.txt"; + + std::string output = this->tmp_file (); + + char *argv[] = { "x", const_cast (input.c_str ()), const_cast (output.c_str ()) }; + + EXPECT_EQ (strm2txt (sizeof (argv) / sizeof (argv[0]), argv), 0); + + this->compare_text_files (output, au); +} diff --git a/src/buddies/unit_tests/bdStrmclipTests.cc b/src/buddies/unit_tests/bdStrmclipTests.cc new file mode 100644 index 000000000..0838aa0d4 --- /dev/null +++ b/src/buddies/unit_tests/bdStrmclipTests.cc @@ -0,0 +1,103 @@ + +/* + + KLayout Layout Viewer + Copyright (C) 2006-2017 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 "utHead.h" +#include "bdCommon.h" +#include "dbReader.h" + +BD_PUBLIC int strmclip (int argc, char *argv[]); + +TEST(1A) +{ + std::string input = ut::testsrc (); + input += "/testdata/bd/strm2clip_in.gds"; + + std::string au = ut::testsrc (); + au += "/testdata/bd/strm2clip_au1.gds"; + + std::string output = this->tmp_file (); + + char *argv[] = { "x", const_cast (input.c_str ()), const_cast (output.c_str ()), "-r=0,-2,9,5", "-r=13,-2,16,3", "-r=13,5,16,7" }; + + EXPECT_EQ (strmclip (sizeof (argv) / sizeof (argv[0]), argv), 0); + + db::Layout layout; + + { + tl::InputStream stream (output); + db::Reader reader (stream); + reader.read (layout); + } + + this->compare_layouts (layout, au, ut::NoNormalization); +} + +TEST(1B) +{ + std::string input = ut::testsrc (); + input += "/testdata/bd/strm2clip_in.gds"; + + std::string au = ut::testsrc (); + au += "/testdata/bd/strm2clip_au1.gds"; + + std::string output = this->tmp_file (); + + char *argv[] = { "x", const_cast (input.c_str ()), const_cast (output.c_str ()), "-l=100/0" }; + + EXPECT_EQ (strmclip (sizeof (argv) / sizeof (argv[0]), argv), 0); + + db::Layout layout; + + { + tl::InputStream stream (output); + db::Reader reader (stream); + reader.read (layout); + } + + this->compare_layouts (layout, au, ut::NoNormalization); +} + +TEST(2) +{ + std::string input = ut::testsrc (); + input += "/testdata/bd/strm2clip_in.gds"; + + std::string au = ut::testsrc (); + au += "/testdata/bd/strm2clip_au2.gds"; + + std::string output = this->tmp_file (); + + char *argv[] = { "x", const_cast (input.c_str ()), const_cast (output.c_str ()), "-r=0,-2,9,5", "-t", "INV2", "-x=CLIP_OUT" }; + + EXPECT_EQ (strmclip (sizeof (argv) / sizeof (argv[0]), argv), 0); + + db::Layout layout; + + { + tl::InputStream stream (output); + db::Reader reader (stream); + reader.read (layout); + } + + this->compare_layouts (layout, au, ut::NoNormalization); +} + diff --git a/src/buddies/unit_tests/bdStrmcmpTests.cc b/src/buddies/unit_tests/bdStrmcmpTests.cc new file mode 100644 index 000000000..389b6eaaf --- /dev/null +++ b/src/buddies/unit_tests/bdStrmcmpTests.cc @@ -0,0 +1,535 @@ + +/* + + KLayout Layout Viewer + Copyright (C) 2006-2017 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 "utHead.h" +#include "bdCommon.h" +#include "dbReader.h" +#include "tlLog.h" + +#include + +BD_PUBLIC int strmcmp (int argc, char *argv[]); + +class CaptureChannel : public tl::Channel +{ +public: + CaptureChannel () + { + // .. nothing yet .. + } + + std::string captured_text () const + { + return m_text.str (); + } + + void clear () + { + m_text.str (std::string ()); + } + +protected: + virtual void puts (const char *s) + { + m_text << s; + } + + virtual void endl () + { + m_text << "\n"; + } + + virtual void end () { } + virtual void begin () { } + +private: + std::ostringstream m_text; +}; + + +TEST(1) +{ + CaptureChannel cap; + + tl::warn.add (&cap, false); + tl::info.add (&cap, false); + tl::error.add (&cap, false); + + tl::info << "Self test"; + EXPECT_EQ (cap.captured_text (), "Self test\n"); + cap.clear (); + EXPECT_EQ (cap.captured_text (), ""); + + std::string input_a = ut::testsrc (); + input_a += "/testdata/bd/strmcmp_in.gds"; + + std::string input_b = ut::testsrc (); + input_b += "/testdata/bd/strmcmp_ref1.gds"; + + char *argv[] = { "x", const_cast (input_a.c_str ()), const_cast (input_b.c_str ()) }; + + EXPECT_EQ (strmcmp (sizeof (argv) / sizeof (argv[0]), argv), 0); + + EXPECT_EQ (cap.captured_text (), ""); +} + +TEST(2A) +{ + CaptureChannel cap; + + tl::warn.add (&cap, false); + tl::info.add (&cap, false); + tl::error.add (&cap, false); + + std::string input_a = ut::testsrc (); + input_a += "/testdata/bd/strmcmp_in.gds"; + + std::string input_b = ut::testsrc (); + input_b += "/testdata/bd/strmcmp_ref2.gds"; + + char *argv[] = { "x", const_cast (input_a.c_str ()), const_cast (input_b.c_str ()) }; + + EXPECT_EQ (strmcmp (sizeof (argv) / sizeof (argv[0]), argv), 1); + + EXPECT_EQ (cap.captured_text (), + "Boxes differ for layer 8/0 in cell RINGO\n" + "Not in b but in a:\n" + " (-1720,1600;23160,2000)\n" + "Not in a but in b:\n" + " (-1520,1600;23160,2000)\n" + "Texts differ for layer 8/1 in cell RINGO\n" + "Not in b but in a:\n" + " ('FB',r0 0,1800)\n" + "Not in a but in b:\n" + " ('BF',r0 0,1800)\n" + "Layouts differ\n" + ); +} + +TEST(2B) +{ + CaptureChannel cap; + + tl::warn.add (&cap, false); + tl::info.add (&cap, false); + tl::error.add (&cap, false); + + std::string input_a = ut::testsrc (); + input_a += "/testdata/bd/strmcmp_in.gds"; + + std::string input_b = ut::testsrc (); + input_b += "/testdata/bd/strmcmp_ref2.gds"; + + char *argv[] = { "x", "-s", const_cast (input_a.c_str ()), const_cast (input_b.c_str ()) }; + + EXPECT_EQ (strmcmp (sizeof (argv) / sizeof (argv[0]), argv), 1); + + EXPECT_EQ (cap.captured_text (), ""); +} + +TEST(2C) +{ + CaptureChannel cap; + + tl::warn.add (&cap, false); + tl::info.add (&cap, false); + tl::error.add (&cap, false); + + std::string input_a = ut::testsrc (); + input_a += "/testdata/bd/strmcmp_in.gds"; + + std::string input_b = ut::testsrc (); + input_b += "/testdata/bd/strmcmp_ref2.gds"; + + char *argv[] = { "x", "-am=8/0", "-as", "-bm=8/0", "-bs", const_cast (input_a.c_str ()), const_cast (input_b.c_str ()) }; + + EXPECT_EQ (strmcmp (sizeof (argv) / sizeof (argv[0]), argv), 1); + + EXPECT_EQ (cap.captured_text (), + "Boxes differ for layer 8/0 in cell RINGO\n" + "Not in b but in a:\n" + " (-1720,1600;23160,2000)\n" + "Not in a but in b:\n" + " (-1520,1600;23160,2000)\n" + "Layouts differ\n" + ); +} + +TEST(2D) +{ + CaptureChannel cap; + + tl::warn.add (&cap, false); + tl::info.add (&cap, false); + tl::error.add (&cap, false); + + std::string input_a = ut::testsrc (); + input_a += "/testdata/bd/strmcmp_in.gds"; + + std::string input_b = ut::testsrc (); + input_b += "/testdata/bd/strmcmp_ref2.gds"; + + char *argv[] = { "x", "-m=1", const_cast (input_a.c_str ()), const_cast (input_b.c_str ()) }; + + EXPECT_EQ (strmcmp (sizeof (argv) / sizeof (argv[0]), argv), 1); + + EXPECT_EQ (cap.captured_text (), + "...\n" + "Report is shortened after 0 lines.\n" + "Layouts differ\n" + ); +} + +TEST(2E) +{ + CaptureChannel cap; + + tl::warn.add (&cap, false); + tl::info.add (&cap, false); + tl::error.add (&cap, false); + + std::string input_a = ut::testsrc (); + input_a += "/testdata/bd/strmcmp_in.gds"; + + std::string input_b = ut::testsrc (); + input_b += "/testdata/bd/strmcmp_ref2.gds"; + + char *argv[] = { "x", "-ta=INV2", "-tb=INV2", const_cast (input_a.c_str ()), const_cast (input_b.c_str ()) }; + + EXPECT_EQ (strmcmp (sizeof (argv) / sizeof (argv[0]), argv), 0); +} + +TEST(2F) +{ + CaptureChannel cap; + + tl::warn.add (&cap, false); + tl::info.add (&cap, false); + tl::error.add (&cap, false); + + std::string input_a = ut::testsrc (); + input_a += "/testdata/bd/strmcmp_in.gds"; + + std::string input_b = ut::testsrc (); + input_b += "/testdata/bd/strmcmp_ref2.gds"; + + char *argv[] = { "x", "-u", const_cast (input_a.c_str ()), const_cast (input_b.c_str ()) }; + + EXPECT_EQ (strmcmp (sizeof (argv) / sizeof (argv[0]), argv), 1); + + EXPECT_EQ (cap.captured_text (), + "Bounding boxes differ for cell RINGO, (-1720,-800;25160,3800) vs. (-1700,-800;25160,3800)\n" + "Per-layer bounding boxes differ for cell RINGO, layer (8/0), (-1720,-450;25160,3250) vs. (-1520,-450;25160,3250)\n" + "Boxes differ for layer 8/0 in cell RINGO\n" + "Texts differ for layer 8/1 in cell RINGO\n" + "Layouts differ\n" + ); +} + +TEST(3A) +{ + CaptureChannel cap; + + tl::warn.add (&cap, false); + tl::info.add (&cap, false); + tl::error.add (&cap, false); + + std::string input_a = ut::testsrc (); + input_a += "/testdata/bd/strmcmp_in.gds"; + + std::string input_b = ut::testsrc (); + input_b += "/testdata/bd/strmcmp_ref3.gds"; + + char *argv[] = { "x", const_cast (input_a.c_str ()), const_cast (input_b.c_str ()) }; + + EXPECT_EQ (strmcmp (sizeof (argv) / sizeof (argv[0]), argv), 1); + + EXPECT_EQ (cap.captured_text (), + "Boxes differ for layer 8/0 in cell RINGO\n" + "Not in b but in a:\n" + " (-1720,1600;23160,2000)\n" + "Not in a but in b:\n" + " (-1721,1600;23160,2000)\n" + "Layouts differ\n" + ); +} + +TEST(3B) +{ + CaptureChannel cap; + + tl::warn.add (&cap, false); + tl::info.add (&cap, false); + tl::error.add (&cap, false); + + std::string input_a = ut::testsrc (); + input_a += "/testdata/bd/strmcmp_in.gds"; + + std::string input_b = ut::testsrc (); + input_b += "/testdata/bd/strmcmp_ref3.gds"; + + char *argv[] = { "x", "-t=0.001", const_cast (input_a.c_str ()), const_cast (input_b.c_str ()) }; + + EXPECT_EQ (strmcmp (sizeof (argv) / sizeof (argv[0]), argv), 0); +} + +TEST(4A) +{ + CaptureChannel cap; + + tl::warn.add (&cap, false); + tl::info.add (&cap, false); + tl::error.add (&cap, false); + + std::string input_a = ut::testsrc (); + input_a += "/testdata/bd/strmcmp_in.gds"; + + std::string input_b = ut::testsrc (); + input_b += "/testdata/bd/strmcmp_ref4.gds"; + + char *argv[] = { "x", const_cast (input_a.c_str ()), const_cast (input_b.c_str ()) }; + + EXPECT_EQ (strmcmp (sizeof (argv) / sizeof (argv[0]), argv), 1); + + EXPECT_EQ (cap.captured_text (), + "Paths differ for layer 3/0 in cell TRANS\n" + "Not in b but in a:\n" + " (0,-800;0,800) w=250 bx=0 ex=0 r=false\n" + "Not in a but in b:\n" + "Boxes differ for layer 3/0 in cell TRANS\n" + "Not in b but in a:\n" + "Not in a but in b:\n" + " (-125,-800;125,800)\n" + "Layouts differ\n" + ); +} + +TEST(4B) +{ + CaptureChannel cap; + + tl::warn.add (&cap, false); + tl::info.add (&cap, false); + tl::error.add (&cap, false); + + std::string input_a = ut::testsrc (); + input_a += "/testdata/bd/strmcmp_in.gds"; + + std::string input_b = ut::testsrc (); + input_b += "/testdata/bd/strmcmp_ref4.gds"; + + char *argv[] = { "x", "-p", const_cast (input_a.c_str ()), const_cast (input_b.c_str ()) }; + + EXPECT_EQ (strmcmp (sizeof (argv) / sizeof (argv[0]), argv), 0); +} + +TEST(5A) +{ + CaptureChannel cap; + + tl::warn.add (&cap, false); + tl::info.add (&cap, false); + tl::error.add (&cap, false); + + std::string input_a = ut::testsrc (); + input_a += "/testdata/bd/strmcmp_in.gds"; + + std::string input_b = ut::testsrc (); + input_b += "/testdata/bd/strmcmp_ref5.gds"; + + char *argv[] = { "x", "-u", const_cast (input_a.c_str ()), const_cast (input_b.c_str ()) }; + + EXPECT_EQ (strmcmp (sizeof (argv) / sizeof (argv[0]), argv), 1); + + EXPECT_EQ (cap.captured_text (), + "Instances differ in cell RINGO\n" + "Layouts differ\n" + ); +} + +TEST(5B) +{ + CaptureChannel cap; + + tl::warn.add (&cap, false); + tl::info.add (&cap, false); + tl::error.add (&cap, false); + + std::string input_a = ut::testsrc (); + input_a += "/testdata/bd/strmcmp_in.gds"; + + std::string input_b = ut::testsrc (); + input_b += "/testdata/bd/strmcmp_ref5.gds"; + + char *argv[] = { "x", "--expand-arrays", const_cast (input_a.c_str ()), const_cast (input_b.c_str ()) }; + + EXPECT_EQ (strmcmp (sizeof (argv) / sizeof (argv[0]), argv), 0); +} + +TEST(6A) +{ + CaptureChannel cap; + + tl::warn.add (&cap, false); + tl::info.add (&cap, false); + tl::error.add (&cap, false); + + std::string input_a = ut::testsrc (); + input_a += "/testdata/bd/strmcmp_in.gds"; + + std::string input_b = ut::testsrc (); + input_b += "/testdata/bd/strmcmp_ref6.gds"; + + char *argv[] = { "x", "-r", const_cast (input_a.c_str ()), const_cast (input_b.c_str ()) }; + + EXPECT_EQ (strmcmp (sizeof (argv) / sizeof (argv[0]), argv), 1); + + EXPECT_EQ (cap.captured_text (), + "Boxes differ for layer 8/0 in cell RINGO\n" + "Not in b but in a:\n" + " (-1720,1600;23160,2000)\n" + "Not in a but in b:\n" + " (-1720,1600;23160,2000) {1 {VALUE}}\n" + "Layouts differ\n" + ); +} + +TEST(6B) +{ + CaptureChannel cap; + + tl::warn.add (&cap, false); + tl::info.add (&cap, false); + tl::error.add (&cap, false); + + std::string input_a = ut::testsrc (); + input_a += "/testdata/bd/strmcmp_in.gds"; + + std::string input_b = ut::testsrc (); + input_b += "/testdata/bd/strmcmp_ref6.gds"; + + char *argv[] = { "x", "-np", const_cast (input_a.c_str ()), const_cast (input_b.c_str ()) }; + + EXPECT_EQ (strmcmp (sizeof (argv) / sizeof (argv[0]), argv), 0); +} + +TEST(7A) +{ + CaptureChannel cap; + + tl::warn.add (&cap, false); + tl::info.add (&cap, false); + tl::error.add (&cap, false); + + std::string input_a = ut::testsrc (); + input_a += "/testdata/bd/strmcmp_in.gds"; + + std::string input_b = ut::testsrc (); + input_b += "/testdata/bd/strmcmp_ref7.oas"; + + char *argv[] = { "x", const_cast (input_a.c_str ()), const_cast (input_b.c_str ()) }; + + EXPECT_EQ (strmcmp (sizeof (argv) / sizeof (argv[0]), argv), 1); + + EXPECT_EQ (cap.captured_text (), + "Layer names differ between layout a and b for layer 3/0: vs. NAME\n" + "Layouts differ\n" + ); +} + +TEST(7B) +{ + CaptureChannel cap; + + tl::warn.add (&cap, false); + tl::info.add (&cap, false); + tl::error.add (&cap, false); + + std::string input_a = ut::testsrc (); + input_a += "/testdata/bd/strmcmp_in.gds"; + + std::string input_b = ut::testsrc (); + input_b += "/testdata/bd/strmcmp_ref7.oas"; + + char *argv[] = { "x", "-nl", const_cast (input_a.c_str ()), const_cast (input_b.c_str ()) }; + + EXPECT_EQ (strmcmp (sizeof (argv) / sizeof (argv[0]), argv), 0); +} + +TEST(8A) +{ + CaptureChannel cap; + + tl::warn.add (&cap, false); + tl::info.add (&cap, false); + tl::error.add (&cap, false); + + std::string input_a = ut::testsrc (); + input_a += "/testdata/bd/strmcmp_in.gds"; + + std::string input_b = ut::testsrc (); + input_b += "/testdata/bd/strmcmp_ref8.gds"; + + char *argv[] = { "x", const_cast (input_a.c_str ()), const_cast (input_b.c_str ()) }; + + EXPECT_EQ (strmcmp (sizeof (argv) / sizeof (argv[0]), argv), 1); + + EXPECT_EQ (cap.captured_text (), + "Cell TRANS is not present in layout b, but in a\n" + "Cell SNART is not present in layout a, but in b\n" + "Instances differ in cell INV2\n" + "Not in b but in a:\n" + " TRANS r0 *1 -400,0\n" + " TRANS r0 *1 -400,2800\n" + " TRANS m0 *1 400,0\n" + " TRANS m0 *1 400,2800\n" + "Not in a but in b:\n" + " SNART r0 *1 -400,0\n" + " SNART r0 *1 -400,2800\n" + " SNART m0 *1 400,0\n" + " SNART m0 *1 400,2800\n" + "Layouts differ\n" + ); +} + +TEST(8B) +{ + CaptureChannel cap; + + tl::warn.add (&cap, false); + tl::info.add (&cap, false); + tl::error.add (&cap, false); + + std::string input_a = ut::testsrc (); + input_a += "/testdata/bd/strmcmp_in.gds"; + + std::string input_b = ut::testsrc (); + input_b += "/testdata/bd/strmcmp_ref8.gds"; + + char *argv[] = { "x", "-c", const_cast (input_a.c_str ()), const_cast (input_b.c_str ()) }; + + EXPECT_EQ (strmcmp (sizeof (argv) / sizeof (argv[0]), argv), 0); + + EXPECT_EQ (cap.captured_text (), + "Cell TRANS in a is renamed to SNART in b\n" + ); +} diff --git a/src/buddies/unit_tests/unit_tests.pro b/src/buddies/unit_tests/unit_tests.pro index 723ce3feb..eec620229 100644 --- a/src/buddies/unit_tests/unit_tests.pro +++ b/src/buddies/unit_tests/unit_tests.pro @@ -7,6 +7,9 @@ include($$PWD/../../lib_ut.pri) SOURCES = \ bdBasicTests.cc \ bdConverterTests.cc \ + bdStrm2txtTests.cc \ + bdStrmclipTests.cc \ + bdStrmcmpTests.cc INCLUDEPATH += ../src/bd diff --git a/src/db/dbLayoutDiff.cc b/src/db/dbLayoutDiff.cc index 6c75eea44..9e8b4b069 100644 --- a/src/db/dbLayoutDiff.cc +++ b/src/db/dbLayoutDiff.cc @@ -747,10 +747,6 @@ do_compare_layouts (const db::Layout &a, const db::Cell *top_a, const db::Layout common_cells.push_back (cb->first); } else { r.cell_name_differs (std::string (a.cell_name (cm.second)), cm.second, cb->first, cb->second); - differs = true; - if (flags & layout_diff::f_silent) { - return false; - } common_cells.push_back (a.cell_name (cm.second)); // use layout A cell name as reference } @@ -1176,7 +1172,7 @@ PrintingDifferenceReceiver::enough (tl::Channel &ch) } if (m_count == m_max_count) { - enough (tl::warn) << "..." << tl::endl << "layout_diff: report is shortened after " << (m_max_count - 1) << " lines."; + tl::warn << "..." << tl::endl << "Report is shortened after " << (m_max_count - 1) << " lines."; } throw tl::CancelException (); } @@ -1228,18 +1224,19 @@ PrintingDifferenceReceiver::print_diffs (const db::PropertiesRepository &pr, con for (typename std::vector >::const_iterator s = anotb.begin (); s != anotb.end (); ++s) { enough (tl::info) << " " << s->first.to_string () << tl::noendl; if (s->second != 0) { - tl::info << " [" << s->second << "]"; if (m_print_properties) { const db::PropertiesRepository::properties_set &props = pr.properties (s->second); for (db::PropertiesRepository::properties_set::const_iterator p = props.begin (); p != props.end (); ++p) { const tl::Variant &name = pr.prop_name (p->first); if (name.is_long ()) { - tl::info << " {" << int (name.to_long ()) << " {" << p->second.to_string () << "}}"; + tl::info << " {" << int (name.to_long ()) << " {" << p->second.to_string () << "}}" << tl::noendl; } else { - tl::info << " {{" << name.to_string () << "} {" << p->second.to_string () << "}}"; + tl::info << " {{" << name.to_string () << "} {" << p->second.to_string () << "}}" << tl::noendl; } } - tl::info << "}"; + tl::info << ""; + } else { + tl::info << " [" << s->second << "]"; } } else { tl::info << ""; @@ -1251,7 +1248,7 @@ void PrintingDifferenceReceiver::dbu_differs (double dbu_a, double dbu_b) { try { - enough (tl::error) << "layout_diff: database units differ " << dbu_a << " vs. " << dbu_b; + enough (tl::error) << "Database units differ " << dbu_a << " vs. " << dbu_b; } catch (tl::CancelException) { // ignore cancel exceptions } @@ -1261,7 +1258,7 @@ void PrintingDifferenceReceiver::layer_in_a_only (const db::LayerProperties &la) { try { - enough (tl::error) << "layout_diff: layer " << la.to_string () << " is not present in layout b, but in a"; + enough (tl::error) << "Layer " << la.to_string () << " is not present in layout b, but in a"; } catch (tl::CancelException) { // ignore cancel exceptions } @@ -1271,7 +1268,7 @@ void PrintingDifferenceReceiver::layer_in_b_only (const db::LayerProperties &lb) { try { - enough (tl::error) << "layout_diff: layer " << lb.to_string () << " is not present in layout a, but in b"; + enough (tl::error) << "Layer " << lb.to_string () << " is not present in layout a, but in b"; } catch (tl::CancelException) { // ignore cancel exceptions } @@ -1281,7 +1278,7 @@ void PrintingDifferenceReceiver::layer_name_differs (const db::LayerProperties &la, const db::LayerProperties &lb) { try { - enough (tl::error) << "layout_diff: layer names differ between layout a and b for layer " << la.layer << "/" << la.datatype << ": " + enough (tl::error) << "Layer names differ between layout a and b for layer " << la.layer << "/" << la.datatype << ": " << la.name << " vs. " << lb.name; } catch (tl::CancelException) { // ignore cancel exceptions @@ -1292,7 +1289,7 @@ void PrintingDifferenceReceiver::cell_in_a_only (const std::string &cellname, db::cell_index_type /*ci*/) { try { - enough (tl::error) << "layout_diff: cell " << cellname << " is not present in layout b, but in a"; + enough (tl::error) << "Cell " << cellname << " is not present in layout b, but in a"; } catch (tl::CancelException) { // ignore cancel exceptions } @@ -1302,7 +1299,7 @@ void PrintingDifferenceReceiver::cell_in_b_only (const std::string &cellname, db::cell_index_type /*ci*/) { try { - enough (tl::error) << "layout_diff: cell " << cellname << " is not present in layout a, but in b"; + enough (tl::error) << "Cell " << cellname << " is not present in layout a, but in b"; } catch (tl::CancelException) { // ignore cancel exceptions } @@ -1312,7 +1309,7 @@ void PrintingDifferenceReceiver::cell_name_differs (const std::string &cellname_a, db::cell_index_type /*cia*/, const std::string &cellname_b, db::cell_index_type /*cib*/) { try { - enough (tl::error) << "layout_diff: cell " << cellname_a << " in a is renamed to " << cellname_b << " in b"; + enough (tl::error) << "Cell " << cellname_a << " in a is renamed to " << cellname_b << " in b"; } catch (tl::CancelException) { // ignore cancel exceptions } @@ -1322,7 +1319,7 @@ void PrintingDifferenceReceiver::bbox_differs (const db::Box &ba, const db::Box &bb) { try { - enough (tl::error) << "layout_diff: bounding boxes differ for cell " << m_cellname << ", " << ba.to_string () << " vs. " << bb.to_string (); + enough (tl::error) << "Bounding boxes differ for cell " << m_cellname << ", " << ba.to_string () << " vs. " << bb.to_string (); } catch (tl::CancelException) { // ignore cancel exceptions } @@ -1338,36 +1335,20 @@ void PrintingDifferenceReceiver::begin_inst_differences () { try { - enough (tl::error) << "layout_diff: instances differ in cell " << m_cellname; + enough (tl::error) << "Instances differ in cell " << m_cellname; } catch (tl::CancelException) { // ignore cancel exceptions } } void -PrintingDifferenceReceiver::instances_in_a (const std::vector &insts_a, const std::vector &cell_names, const db::PropertiesRepository & /*props*/) +PrintingDifferenceReceiver::instances_in_a (const std::vector & /*insts_a*/, const std::vector & /*cell_names*/, const db::PropertiesRepository & /*props*/) { - try { - enough (tl::info) << "list for a:"; - for (std::vector ::const_iterator s = insts_a.begin (); s != insts_a.end (); ++s) { - print_cell_inst (*s, cell_names); - } - } catch (tl::CancelException) { - // ignore cancel exceptions - } } void -PrintingDifferenceReceiver::instances_in_b (const std::vector &insts_b, const std::vector &cell_names, const db::PropertiesRepository & /*props*/) +PrintingDifferenceReceiver::instances_in_b (const std::vector & /*insts_b*/, const std::vector & /*cell_names*/, const db::PropertiesRepository & /*props*/) { - try { - enough (tl::info) << "list for b:"; - for (std::vector ::const_iterator s = insts_b.begin (); s != insts_b.end (); ++s) { - print_cell_inst (*s, cell_names); - } - } catch (tl::CancelException) { - // ignore cancel exceptions - } } void @@ -1411,7 +1392,7 @@ void PrintingDifferenceReceiver::per_layer_bbox_differs (const db::Box &ba, const db::Box &bb) { try { - enough (tl::error) << "layout_diff: per-layer bounding boxes differ for cell " << m_cellname << ", layer (" << m_layer.to_string () << "), " + enough (tl::error) << "Per-layer bounding boxes differ for cell " << m_cellname << ", layer (" << m_layer.to_string () << "), " << ba.to_string () << " vs. " << bb.to_string (); } catch (tl::CancelException) { // ignore cancel exceptions @@ -1422,7 +1403,7 @@ void PrintingDifferenceReceiver::begin_polygon_differences () { try { - enough (tl::error) << "layout_diff: polygons differ for layer " << m_layer.to_string () << " in cell " << m_cellname; + enough (tl::error) << "Polygons differ for layer " << m_layer.to_string () << " in cell " << m_cellname; } catch (tl::CancelException) { // ignore cancel exceptions } @@ -1450,7 +1431,7 @@ void PrintingDifferenceReceiver::begin_path_differences () { try { - enough (tl::error) << "layout_diff: paths differ for layer " << m_layer.to_string () << " in cell " << m_cellname; + enough (tl::error) << "Paths differ for layer " << m_layer.to_string () << " in cell " << m_cellname; } catch (tl::CancelException) { // ignore cancel exceptions } @@ -1478,7 +1459,7 @@ void PrintingDifferenceReceiver::begin_box_differences () { try { - enough (tl::error) << "layout_diff: boxes differ for layer " << m_layer.to_string () << " in cell " << m_cellname; + enough (tl::error) << "Boxes differ for layer " << m_layer.to_string () << " in cell " << m_cellname; } catch (tl::CancelException) { // ignore cancel exceptions } @@ -1506,7 +1487,7 @@ void PrintingDifferenceReceiver::begin_edge_differences () { try { - enough (tl::error) << "layout_diff: edges differ for layer " << m_layer.to_string () << " in cell " << m_cellname; + enough (tl::error) << "Edges differ for layer " << m_layer.to_string () << " in cell " << m_cellname; } catch (tl::CancelException) { // ignore cancel exceptions } @@ -1534,7 +1515,7 @@ void PrintingDifferenceReceiver::begin_text_differences () { try { - enough (tl::error) << "layout_diff: texts differ for layer " << m_layer.to_string () << " in cell " << m_cellname; + enough (tl::error) << "Texts differ for layer " << m_layer.to_string () << " in cell " << m_cellname; } catch (tl::CancelException) { // ignore cancel exceptions } diff --git a/src/ut/utHead.h b/src/ut/utHead.h index dcb507b0e..b68cecc47 100644 --- a/src/ut/utHead.h +++ b/src/ut/utHead.h @@ -196,6 +196,11 @@ struct UT_PUBLIC TestBase */ void compare_layouts (const db::Layout &layout, const std::string &au_file, const db::LayerMap &lmap, bool read_all_others, NormalizationMode norm = WriteGDS2, db::Coord tolerance = 0); + /** + * @brief Compares two text files + */ + void compare_text_files (const std::string &path_a, const std::string &path_b); + /** * @brief The test's name * @return The name of the test diff --git a/src/ut/utMain.cc b/src/ut/utMain.cc index d1379cb97..b5ea53945 100644 --- a/src/ut/utMain.cc +++ b/src/ut/utMain.cc @@ -776,10 +776,37 @@ void TestBase::compare_layouts (const db::Layout &layout, const std::string &au_ } if (! equal) { - raise (tl::sprintf ("Compare failed - see %s vs %s\n", tmp_file, au_file + (n > 1 ? " and variants" : ""))); + raise (tl::sprintf ("Compare failed - see\n actual: %s\n golden: %s%s", + tl::to_string (QFileInfo (tl::to_qstring (tmp_file)).absoluteFilePath ()), + tl::to_string (QFileInfo (tl::to_qstring (au_file)).absoluteFilePath ()), + (n > 1 ? "\nand variants" : ""))); } } +static std::string read_file (const std::string &path) +{ + QFile file (tl::to_qstring (path)); + if (! file.open (QIODevice::ReadOnly | QIODevice::Text)) { + tl::warn << tl::sprintf ("Unable to open file %s", path); + } + + QByteArray ba = file.readAll (); + return std::string (ba.constData (), 0, ba.size ()); +} + +void TestBase::compare_text_files (const std::string &path_a, const std::string &path_b) +{ + std::string text_a = read_file (path_a); + std::string text_b = read_file (path_b); + + if (text_a != text_b) { + raise (tl::sprintf ("Compare failed - see:\n file 1: %s\n file 2: %s", + tl::to_string (QFileInfo (tl::to_qstring (path_a)).absoluteFilePath ()), + tl::to_string (QFileInfo (tl::to_qstring (path_b)).absoluteFilePath ()))); + } +} + + static int main_cont (int argc, char **argv); int diff --git a/testdata/bd/strm2clip_au1.gds b/testdata/bd/strm2clip_au1.gds new file mode 100644 index 000000000..45056634a Binary files /dev/null and b/testdata/bd/strm2clip_au1.gds differ diff --git a/testdata/bd/strm2clip_au2.gds b/testdata/bd/strm2clip_au2.gds new file mode 100644 index 000000000..f8709ccc4 Binary files /dev/null and b/testdata/bd/strm2clip_au2.gds differ diff --git a/testdata/bd/strm2clip_in.gds b/testdata/bd/strm2clip_in.gds new file mode 100644 index 000000000..d69737d82 Binary files /dev/null and b/testdata/bd/strm2clip_in.gds differ diff --git a/testdata/bd/strm2txt_au.txt b/testdata/bd/strm2txt_au.txt new file mode 100644 index 000000000..5440a7b82 --- /dev/null +++ b/testdata/bd/strm2txt_au.txt @@ -0,0 +1,58 @@ +begin_lib 0.001 +begin_cell {TRANS} +box 2 0 {-650 -475} {650 475} +box 4 0 {-510 -310} {-290 -90} +box 4 0 {-510 90} {-290 310} +box 4 0 {290 -310} {510 -90} +box 4 0 {290 90} {510 310} +box 6 0 {-580 -380} {-220 380} +box 6 0 {220 -380} {580 380} +path 3 0 250 0 0 {0 -800} {0 800} +end_cell +begin_cell {INV2} +sref {TRANS} 0 0 1 {-400 0} +sref {TRANS} 0 0 1 {-400 2800} +sref {TRANS} 0 1 1 {400 0} +sref {TRANS} 0 1 1 {400 2800} +path 6 0 360 0 0 {800 200} {1120 200} {1120 1800} {800 1800} {800 2420} +box 6 0 {-980 -420} {-620 2420} +box 6 0 {-800 820} {580 1180} +box 3 0 {-525 -250} {-275 2250} +box 3 0 {275 -250} {525 2250} +box 3 0 {220 820} {580 1180} +box 3 0 {-1700 1620} {-400 1980} +box 8 0 {-1400 -450} {1400 450} +box 8 0 {-1400 2350} {1400 3250} +box 1 0 {-1400 1800} {1400 3800} +box 5 0 {290 890} {510 1110} +box 5 0 {-1630 1690} {-1410 1910} +box 7 0 {-125 -325} {125 -75} +box 7 0 {-125 75} {125 325} +box 7 0 {-125 2475} {125 2725} +box 7 0 {-125 2875} {125 3125} +text 3 1 0 0 {-800 1800} {IN} +text 6 1 0 0 {800 1800} {OUT} +end_cell +begin_cell {RINGO} +sref {INV2} 0 0 1 {0 0} +sref {INV2} 0 0 1 {2640 0} +sref {INV2} 0 0 1 {5280 0} +sref {INV2} 0 0 1 {7920 0} +sref {INV2} 0 0 1 {10560 0} +sref {INV2} 0 0 1 {13200 0} +sref {INV2} 0 0 1 {15840 0} +sref {INV2} 0 0 1 {18480 0} +sref {INV2} 0 0 1 {21120 0} +sref {INV2} 0 0 1 {23760 0} +box 6 0 {-1700 1620} {-1340 1980} +box 8 0 {-1720 1600} {23160 2000} +box 8 0 {24360 1600} {24760 2000} +box 7 0 {-1645 1675} {-1395 1925} +box 7 0 {22835 1675} {23085 1925} +box 7 0 {24435 1675} {24685 1925} +text 8 1 0 0 {24560 1800} {OSC} +text 8 1 0 0 {0 1800} {FB} +text 8 1 0 0 {0 0} {VSS} +text 8 1 0 0 {0 2800} {VDD} +end_cell +end_lib diff --git a/testdata/bd/strmcmp_in.gds b/testdata/bd/strmcmp_in.gds new file mode 100644 index 000000000..fa837f4e2 Binary files /dev/null and b/testdata/bd/strmcmp_in.gds differ diff --git a/testdata/bd/strmcmp_ref1.gds b/testdata/bd/strmcmp_ref1.gds new file mode 100644 index 000000000..fa837f4e2 Binary files /dev/null and b/testdata/bd/strmcmp_ref1.gds differ diff --git a/testdata/bd/strmcmp_ref2.gds b/testdata/bd/strmcmp_ref2.gds new file mode 100644 index 000000000..1903c32aa Binary files /dev/null and b/testdata/bd/strmcmp_ref2.gds differ diff --git a/testdata/bd/strmcmp_ref3.gds b/testdata/bd/strmcmp_ref3.gds new file mode 100644 index 000000000..2a465c3f4 Binary files /dev/null and b/testdata/bd/strmcmp_ref3.gds differ diff --git a/testdata/bd/strmcmp_ref4.gds b/testdata/bd/strmcmp_ref4.gds new file mode 100644 index 000000000..8aa4781b2 Binary files /dev/null and b/testdata/bd/strmcmp_ref4.gds differ diff --git a/testdata/bd/strmcmp_ref5.gds b/testdata/bd/strmcmp_ref5.gds new file mode 100644 index 000000000..9824d197f Binary files /dev/null and b/testdata/bd/strmcmp_ref5.gds differ diff --git a/testdata/bd/strmcmp_ref6.gds b/testdata/bd/strmcmp_ref6.gds new file mode 100644 index 000000000..e45441f4d Binary files /dev/null and b/testdata/bd/strmcmp_ref6.gds differ diff --git a/testdata/bd/strmcmp_ref7.oas b/testdata/bd/strmcmp_ref7.oas new file mode 100644 index 000000000..94632b1e1 Binary files /dev/null and b/testdata/bd/strmcmp_ref7.oas differ diff --git a/testdata/bd/strmcmp_ref8.gds b/testdata/bd/strmcmp_ref8.gds new file mode 100644 index 000000000..251c916d3 Binary files /dev/null and b/testdata/bd/strmcmp_ref8.gds differ