klayout/src/plugins/streamers/oasis/unit_tests/dbOASISReader.cc

582 lines
14 KiB
C++

/*
KLayout Layout Viewer
Copyright (C) 2006-2018 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 "dbOASISReader.h"
#include "dbTextWriter.h"
#include "dbTestSupport.h"
#include "tlLog.h"
#include "tlUnitTest.h"
#include "tlStream.h"
#include "tlFileUtils.h"
#include <stdlib.h>
void
compare_ref (tl::TestBase *_this, const char *test, const db::Layout &layout)
{
tl::OutputStringStream os;
tl::OutputStream ostream (os);
db::TextWriter writer (ostream);
writer.write (layout);
std::string oss = os.string ();
std::string fn_au (tl::testsrc ());
fn_au += "/testdata/oasis/t";
fn_au += test;
fn_au += "_au.txt";
std::string au;
try {
tl::InputFile is (fn_au);
tl::InputStream istream (is);
au = istream.read_all ();
} catch (...) {
// ignore read errors on au files -> this way they can be updated easily
}
// Normalize the golden data's CRLF line breaks on Windows
au = tl::replaced (au, "\r\n", "\n");
if (au != oss) {
EXPECT_EQ (oss, au)
std::string fn (_this->tmp_file (std::string ("t") + test + "_au.txt"));
{
tl::OutputFile ofs (fn);
tl::OutputStream ofstream (ofs);
ofstream.put (oss);
}
tl::info << "To update golden data use";
tl::info << " cp " << fn << " " << tl::absolute_file_path (fn_au);
#if 0 // auto update
system ((std::string ("cp ") + fn + " " + tl::absolute_file_path (fn_au)).c_str ());
tl::info << "Golden data updated.";
#endif
}
}
void
run_test (tl::TestBase *_this, const char *test)
{
db::Manager m;
db::Layout layout (&m);
std::string fn (tl::testsrc ());
fn += "/testdata/oasis/t";
fn += test;
fn += ".oas";
tl::InputStream stream (fn);
db::Reader reader (stream);
reader.set_warnings_as_errors (true);
bool error = false;
try {
reader.read (layout);
} catch (tl::Exception &ex) {
tl::error << ex.msg ();
error = true;
}
EXPECT_EQ (error, false)
compare_ref (_this, test, layout);
}
void
run_test_error (tl::TestBase *_this, const char *test, const char *msg_au)
{
db::Manager m;
db::Layout layout (&m);
std::string fn (tl::testsrc ());
fn += "/testdata/oasis/t";
fn += test;
fn += ".oas";
tl::InputStream stream (fn);
db::Reader reader (stream);
reader.set_warnings_as_errors (true);
std::string msg;
bool error = false;
try {
reader.read (layout);
} catch (tl::Exception &ex) {
msg = ex.msg ();
error = true;
}
EXPECT_EQ (error, true)
EXPECT_EQ (msg, msg_au)
}
TEST(1_1)
{
run_test (_this, "1.1");
}
TEST(1_2)
{
run_test (_this, "1.2");
}
TEST(1_3)
{
run_test (_this, "1.3");
}
TEST(1_4)
{
run_test (_this, "1.4");
}
TEST(1_5)
{
run_test (_this, "1.5");
}
TEST(10_1)
{
run_test (_this, "10.1");
}
TEST(11_1)
{
run_test (_this, "11.1");
}
TEST(11_2)
{
run_test (_this, "11.2");
}
TEST(11_3)
{
run_test (_this, "11.3");
}
TEST(11_4)
{
run_test (_this, "11.4");
}
TEST(11_5)
{
run_test (_this, "11.5");
}
TEST(11_6)
{
run_test (_this, "11.6");
}
TEST(11_7)
{
run_test (_this, "11.7");
}
TEST(11_8)
{
run_test_error (_this, "11.8", "Modal variable accessed before being defined: last-value-list (position=96, cell=)");
}
TEST(11_9)
{
run_test_error (_this, "11.9", "Modal variable accessed before being defined: last-value-list (position=118, cell=)");
}
TEST(12_1)
{
run_test (_this, "12.1");
}
TEST(13_1)
{
run_test (_this, "13.1");
}
TEST(13_2)
{
run_test (_this, "13.2");
}
TEST(13_3)
{
run_test (_this, "13.3");
}
TEST(13_4)
{
run_test (_this, "13.4");
}
TEST(14_1)
{
run_test (_this, "14.1");
}
TEST(2_1)
{
run_test (_this, "2.1");
}
TEST(2_2)
{
run_test (_this, "2.2");
}
TEST(2_3)
{
run_test_error (_this, "2.3", "Explicit and implicit CELLNAME modes cannot be mixed (position=45, cell=)");
}
TEST(2_4)
{
run_test (_this, "2.4");
}
TEST(2_5)
{
run_test_error (_this, "2.5", "No cellname defined for cell name id 2 (position=305, cell=)");
}
TEST(2_6)
{
run_test (_this, "2.6");
}
TEST(3_1)
{
run_test (_this, "3.1");
}
TEST(3_10)
{
run_test (_this, "3.10");
}
TEST(3_11)
{
run_test_error (_this, "3.11", "Modal variable accessed before being defined: text-string (position=50, cell=ABC)");
}
TEST(3_12)
{
run_test (_this, "3.12");
}
TEST(3_2)
{
run_test (_this, "3.2");
}
TEST(3_3)
{
run_test_error (_this, "3.3", "Explicit and implicit TEXTSTRING modes cannot be mixed (position=41, cell=)");
}
TEST(3_4)
{
run_test_error (_this, "3.4", "No text string defined for text string id 2 (position=309, cell=)");
}
TEST(3_5)
{
run_test (_this, "3.5");
}
TEST(3_6)
{
run_test_error (_this, "3.6", "Modal variable accessed before being defined: repetition (position=52, cell=ABC)");
}
TEST(3_7)
{
run_test_error (_this, "3.7", "Modal variable accessed before being defined: textlayer (position=50, cell=ABC)");
}
TEST(3_8)
{
run_test_error (_this, "3.8", "Modal variable accessed before being defined: texttype (position=50, cell=ABC)");
}
TEST(3_9)
{
run_test (_this, "3.9");
}
TEST(4_1)
{
run_test (_this, "4.1");
}
TEST(4_2)
{
run_test (_this, "4.2");
}
TEST(5_1)
{
run_test (_this, "5.1");
}
TEST(5_2)
{
run_test (_this, "5.2");
}
TEST(5_3)
{
run_test (_this, "5.3");
}
TEST(6_1)
{
run_test (_this, "6.1");
}
TEST(7_1)
{
run_test (_this, "7.1");
}
TEST(8_1)
{
run_test (_this, "8.1");
}
TEST(8_2)
{
run_test (_this, "8.2");
}
TEST(8_3)
{
run_test (_this, "8.3");
}
TEST(8_4)
{
run_test (_this, "8.4");
}
TEST(8_5)
{
run_test (_this, "8.5");
}
TEST(8_6)
{
run_test (_this, "8.6");
}
TEST(8_7)
{
run_test (_this, "8.7");
}
TEST(8_8)
{
run_test (_this, "8.8");
}
TEST(9_1)
{
run_test (_this, "9.1");
}
TEST(9_2)
{
run_test (_this, "9.2");
}
// Tests add-on reading
TEST(99)
{
const char *expected =
"begin_lib 0.001\n"
"begin_cell {A}\n"
"boundary 1 2 {-100 200} {-100 400} {100 200} {-100 200}\n"
"boundary 1 2 {-100 600} {-100 800} {100 600} {-100 600}\n"
"box 1 2 {300 -400} {400 -200}\n"
"end_cell\n"
"begin_cell {TOP}\n"
"sref {A} 0 0 1 {-300 1200}\n"
"sref {A} 0 0 1 {-300 400}\n"
"sref {A} 0 0 1 {-300 800}\n"
"sref {A} 0 0 1 {0 1200}\n"
"sref {A} 0 1 1 {700 400}\n"
"sref {A} 90 0 1 {700 1400}\n"
"sref {A} 90 1 1 {700 2400}\n"
"end_cell\n"
"begin_cell {B}\n"
"boundary 1 2 {-100 200} {100 400} {300 200} {-100 200}\n"
"boundary 1 2 {-100 600} {100 800} {300 600} {-100 600}\n"
"end_cell\n"
"end_lib\n"
;
db::Manager m;
db::Layout layout (&m);
{
std::string fn (tl::testsrc ());
fn += "/testdata/oasis/t9.2.oas";
tl::InputStream stream (fn);
db::Reader reader (stream);
reader.set_warnings_as_errors (true);
bool error = false;
try {
db::LayerMap map = reader.read (layout);
} catch (tl::Exception &ex) {
tl::error << ex.msg ();
error = true;
}
EXPECT_EQ (error, false)
}
{
std::string fn (tl::testsrc ());
fn += "/testdata/oasis/t8.7.oas";
tl::InputStream stream (fn);
db::Reader reader (stream);
reader.set_warnings_as_errors (true);
bool error = false;
try {
db::LayerMap map = reader.read (layout);
} catch (tl::Exception &ex) {
tl::error << ex.msg ();
error = true;
}
EXPECT_EQ (error, false)
}
tl::OutputStringStream os;
tl::OutputStream ostream (os);
db::TextWriter writer (ostream);
writer.write (layout);
EXPECT_EQ (std::string (os.string ()), std::string (expected))
}
// XGEOMTRY tests (#773)
TEST(100)
{
const char *expected =
"begin_lib 0.0001\n"
"begin_cell {mask}\n"
"boundary 7 1 {13237 5356} {13210 5490} {13192 5530} {13170 5563} {13130 5586} {13090 5583} {13070 5570} {13050 5551} {13037 5530} {13021 5490} {12988 5378} {12938 5390} {12963 5530} {12977 5570} {12998 5610} {13034 5650} {13051 5663} {13090 5678} {13130 5679} {13171 5667} {13210 5638} {13232 5611} {13253 5570} {13274 5490} {13291 5365} {13237 5356}\n"
"boundary 4 0 {10772 1658} {10772 1744} {14510 1744} {14510 1658} {10772 1658}\n"
"boundary 4 0 {14510 1658} {14510 1744} {15672 1744} {15672 1658} {14510 1658}\n"
"boundary 4 0 {18157 647} {18157 676} {21642 676} {21642 647} {18157 647}\n"
"boundary 6 0 {6743 2449} {6743 4230} {9061 4230} {9061 2449} {6743 2449}\n"
"boundary 2 3 {21642 3613} {21642 4005} {19409 4005} {19409 6980} {21812 6980} {21812 4958} {21942 4958} {21942 4005} {21812 4005} {21812 3613} {21642 3613}\n"
"boundary 2 4 {21642 4005} {21642 4958} {21812 4958} {21812 4005} {21642 4005}\n"
"boundary 8 0 {21680 4106} {21640 4107} {21600 4118} {21574 4130} {21560 4138} {21520 4163} {21509 4170} {21480 4194} {21458 4210} {21440 4227} {21411 4250} {21400 4262} {21366 4290} {21360 4298} {21324 4330} {21320 4335} {21282 4370} {21280 4373} {21241 4410} {21240 4411} {21200 4450} {21160 4490} {21159 4490} {21039 4610} {21000 4650} {20960 4690} {20960 4691} {20921 4730} {20920 4732} {20896 4770} {20886 4810} {20882 4850} {20880 4930} {20880 5330} {20920 5370} {20960 5370} {21000 5340} {21013 5330} {21040 5325} {21080 5309} {21120 5291} {21121 5290} {21160 5276} {21200 5258} {21210 5250} {21240 5240} {21280 5222} {21295 5210} {21320 5202} {21360 5181} {21374 5170} {21400 5160} {21440 5136} {21447 5130} {21480 5112} {21510 5090} {21520 5086} {21560 5058} {21568 5050} {21600 5027} {21617 5010} {21640 4993} {21662 4970} {21680 4955} {21701 4930} {21720 4910} {21735 4890} {21760 4856} {21764 4850} {21786 4810} {21800 4781} {21805 4770} {21818 4730} {21828 4690} {21836 4650} {21840 4616} {21841 4610} {21845 4530} {21845 4450} {21844 4410} {21841 4370} {21840 4358} {21836 4330} {21829 4290} {21818 4250} {21803 4210} {21800 4205} {21778 4170} {21760 4148} {21738 4130} {21720 4118} {21680 4106}\n"
"boundary 1 0 {17922 6288} {17922 6510} {18150 6510} {18150 6288} {17922 6288}\n"
"boundary 1 0 {18157 647} {18157 676} {21630 676} {21630 647} {18157 647}\n"
"boundary 1 0 {21956 0} {21956 89} {22047 89} {22047 0} {21956 0}\n"
"boundary 3 0 {15392 1744} {15392 1774} {15672 1774} {15672 1744} {15392 1744}\n"
"boundary 5 1 {15550 1658} {15550 1673} {15570 1673} {15570 1658} {15550 1658}\n"
"boundary 5 1 {15661 1657} {15641 1659} {15642 1671} {15662 1669} {15661 1657}\n"
"boundary 5 1 {18150 7440} {18150 7460} {18162 7460} {18162 7440} {18150 7440}\n"
"boundary 5 1 {18150 8488} {18150 8508} {18162 8508} {18162 8488} {18150 8488}\n"
"boundary 5 1 {18150 9480} {18150 9500} {18162 9500} {18162 9480} {18150 9480}\n"
"boundary 5 1 {18670 3411} {18670 3468} {18690 3468} {18690 3411} {18670 3411}\n"
"boundary 5 1 {19470 3411} {19470 3468} {19490 3468} {19490 3411} {19470 3411}\n"
"boundary 5 1 {20217 3411} {20217 3468} {20237 3468} {20237 3411} {20217 3411}\n"
"boundary 5 1 {21630 2048} {21630 2068} {21642 2068} {21642 2048} {21630 2048}\n"
"boundary 5 1 {21630 2293} {21630 2313} {21642 2313} {21642 2293} {21630 2293}\n"
"boundary 5 1 {21930 9308} {21930 9328} {21942 9328} {21942 9308} {21930 9308}\n"
"boundary 5 1 {21930 9600} {21930 9620} {21942 9620} {21942 9600} {21930 9600}\n"
"boundary 5 1 {23570 6128} {23570 6148} {23582 6148} {23582 6128} {23570 6128}\n"
"boundary 5 1 {23570 6147} {23570 6167} {23582 6167} {23582 6147} {23570 6147}\n"
"boundary 5 1 {25710 1978} {25710 1998} {25722 1998} {25722 1978} {25710 1978}\n"
"boundary 5 1 {25710 2800} {25710 2820} {25722 2820} {25722 2800} {25710 2800}\n"
"boundary 5 2 {18074 6408} {17971 6486} {17983 6502} {18086 6424} {18074 6408}\n"
"end_cell\n"
"end_lib\n"
;
db::Manager m;
db::Layout layout (&m);
{
std::string fn (tl::testsrc ());
fn += "/testdata/oasis/xgeometry_test.oas";
tl::InputStream stream (fn);
db::Reader reader (stream);
reader.set_warnings_as_errors (true);
reader.read (layout);
}
tl::OutputStringStream os;
tl::OutputStream ostream (os);
db::TextWriter writer (ostream);
writer.write (layout);
EXPECT_EQ (std::string (os.string ()), std::string (expected))
}
TEST(Bug_121_1)
{
db::Manager m;
db::Layout layout (&m);
{
tl::InputStream file (tl::testsrc () + "/testdata/oasis/bug_121a.oas");
db::OASISReader reader (file);
reader.read (layout);
}
{
tl::InputStream file (tl::testsrc () + "/testdata/oasis/bug_121b.oas");
db::OASISReader reader (file);
reader.read (layout);
}
std::string fn_au (tl::testsrc () + "/testdata/oasis/bug_121_au1.gds");
db::compare_layouts (_this, layout, fn_au, db::WriteGDS2, 1);
}
TEST(Bug_121_2)
{
db::Manager m;
db::Layout layout (&m);
{
tl::InputStream file (tl::testsrc () + "/testdata/oasis/bug_121a.oas");
db::OASISReader reader (file);
reader.read (layout);
}
{
tl::InputStream file (tl::testsrc () + "/testdata/oasis/bug_121c.oas");
db::OASISReader reader (file);
reader.read (layout);
}
std::string fn_au (tl::testsrc () + "/testdata/oasis/bug_121_au2.gds");
db::compare_layouts (_this, layout, fn_au, db::WriteGDS2, 1);
}