klayout/src/tl/unit_tests/tlCommandLineParserTests.cc

417 lines
9.6 KiB
C++

/*
KLayout Layout Viewer
Copyright (C) 2006-2025 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 "tlCommandLineParser.h"
#include "tlUnitTest.h"
TEST(1)
{
std::string a;
int b = 0;
bool c = false;
double d = 1;
bool e = false;
std::string f;
tl::CommandLineOptions cmd;
cmd << tl::arg ("a", &a, "")
<< tl::arg ("?b", &b, "")
<< tl::arg ("-c", &c, "")
<< tl::arg ("!-cc", &c, "")
<< tl::arg ("--plong|-p", &d, "")
<< tl::arg ("--elong", &e, "")
<< tl::arg ("-f|--flong=value", &f, "");
{
const char *argv[] = { "x", "y" };
cmd.parse (sizeof (argv) / sizeof (argv[0]), (char **) argv);
}
EXPECT_EQ (a, "y");
EXPECT_EQ (b, 0);
{
const char *argv[] = { "x", "z", "17" };
cmd.parse (sizeof (argv) / sizeof (argv[0]), (char **) argv);
}
EXPECT_EQ (a, "z");
EXPECT_EQ (b, 17);
b = 0;
{
const char *argv[] = { "x", "u", "-c" };
cmd.parse (sizeof (argv) / sizeof (argv[0]), (char **) argv);
}
EXPECT_EQ (a, "u");
EXPECT_EQ (b, 0);
EXPECT_EQ (c, true);
b = 0;
c = true;
{
const char *argv[] = { "x", "u", "-cc" };
cmd.parse (sizeof (argv) / sizeof (argv[0]), (char **) argv);
}
EXPECT_EQ (a, "u");
EXPECT_EQ (b, 0);
EXPECT_EQ (c, false);
b = 0;
c = true;
{
const char *argv[] = { "x", "u", "-cc=false" };
cmd.parse (sizeof (argv) / sizeof (argv[0]), (char **) argv);
}
EXPECT_EQ (a, "u");
EXPECT_EQ (b, 0);
EXPECT_EQ (c, true);
b = 0;
c = true;
{
const char *argv[] = { "x", "u", "-cc=true" };
cmd.parse (sizeof (argv) / sizeof (argv[0]), (char **) argv);
}
EXPECT_EQ (a, "u");
EXPECT_EQ (b, 0);
EXPECT_EQ (c, false);
{
const char *argv[] = { "x", "u", "-c", "-cc" };
cmd.parse (sizeof (argv) / sizeof (argv[0]), (char **) argv);
}
EXPECT_EQ (c, false);
b = 0;
c = false;
{
const char *argv[] = { "x", "u", "-c", "-p=21" };
cmd.parse (sizeof (argv) / sizeof (argv[0]), (char **) argv);
}
EXPECT_EQ (a, "u");
EXPECT_EQ (b, 0);
EXPECT_EQ (c, true);
EXPECT_EQ (d, 21);
b = 0;
c = false;
{
const char *argv[] = { "x", "u", "-p", "22", "-c" };
cmd.parse (sizeof (argv) / sizeof (argv[0]), (char **) argv);
}
EXPECT_EQ (a, "u");
EXPECT_EQ (b, 0);
EXPECT_EQ (c, true);
EXPECT_EQ (d, 22);
e = false;
{
const char *argv[] = { "x", "u", "--plong", "23" };
cmd.parse (sizeof (argv) / sizeof (argv[0]), (char **) argv);
}
EXPECT_EQ (a, "u");
EXPECT_EQ (d, 23);
EXPECT_EQ (e, false);
{
const char *argv[] = { "x", "u", "--plong=24", "--elong" };
cmd.parse (sizeof (argv) / sizeof (argv[0]), (char **) argv);
}
EXPECT_EQ (a, "u");
EXPECT_EQ (d, 24);
EXPECT_EQ (e, true);
{
const char *argv[] = { "x", "u", "-c", "-f=foo" };
cmd.parse (sizeof (argv) / sizeof (argv[0]), (char **) argv);
}
EXPECT_EQ (a, "u");
EXPECT_EQ (f, "foo");
{
const char *argv[] = { "x", "u", "--flong", "bar" };
cmd.parse (sizeof (argv) / sizeof (argv[0]), (char **) argv);
}
EXPECT_EQ (a, "u");
EXPECT_EQ (f, "bar");
}
struct Values
{
Values ()
{
b = 0;
d = 1;
c = e = false;
}
void set_a (const std::string &x) { a = x; }
void set_b (int x) { b = x; }
void set_c (bool x) { c = x; }
void set_d (const double &x) { d = x; }
void set_e (bool x) { e = x; }
void set_f (std::string x) { f = x; }
std::string a;
int b;
bool c;
double d;
bool e;
std::string f;
};
TEST(2)
{
Values v;
tl::CommandLineOptions cmd;
cmd << tl::arg ("a", &v, &Values::set_a, "")
<< tl::arg ("?b", &v, &Values::set_b, "")
<< tl::arg ("-c", &v, &Values::set_c, "")
<< tl::arg ("!-cc", &v, &Values::set_c, "")
<< tl::arg ("--plong|-p", &v, &Values::set_d, "")
<< tl::arg ("--elong", &v, &Values::set_e, "")
<< tl::arg ("-f|--flong=value", &v, &Values::set_f, "");
{
const char *argv[] = { "x", "y" };
cmd.parse (sizeof (argv) / sizeof (argv[0]), (char **) argv);
}
EXPECT_EQ (v.a, "y");
EXPECT_EQ (v.b, 0);
{
const char *argv[] = { "x", "z", "17" };
cmd.parse (sizeof (argv) / sizeof (argv[0]), (char **) argv);
}
EXPECT_EQ (v.a, "z");
EXPECT_EQ (v.b, 17);
v.b = 0;
{
const char *argv[] = { "x", "u", "-c" };
cmd.parse (sizeof (argv) / sizeof (argv[0]), (char **) argv);
}
EXPECT_EQ (v.a, "u");
EXPECT_EQ (v.b, 0);
EXPECT_EQ (v.c, true);
v.b = 0;
v.c = true;
{
const char *argv[] = { "x", "u", "-cc" };
cmd.parse (sizeof (argv) / sizeof (argv[0]), (char **) argv);
}
EXPECT_EQ (v.a, "u");
EXPECT_EQ (v.b, 0);
EXPECT_EQ (v.c, false);
{
const char *argv[] = { "x", "u", "-c", "-cc" };
cmd.parse (sizeof (argv) / sizeof (argv[0]), (char **) argv);
}
EXPECT_EQ (v.c, false);
v.b = 0;
v.c = false;
{
const char *argv[] = { "x", "u", "-c", "-p=21" };
cmd.parse (sizeof (argv) / sizeof (argv[0]), (char **) argv);
}
EXPECT_EQ (v.a, "u");
EXPECT_EQ (v.b, 0);
EXPECT_EQ (v.c, true);
EXPECT_EQ (v.d, 21);
v.b = 0;
v.c = false;
{
const char *argv[] = { "x", "u", "-p", "22", "-c" };
cmd.parse (sizeof (argv) / sizeof (argv[0]), (char **) argv);
}
EXPECT_EQ (v.a, "u");
EXPECT_EQ (v.b, 0);
EXPECT_EQ (v.c, true);
EXPECT_EQ (v.d, 22);
v.e = false;
{
const char *argv[] = { "x", "u", "--plong", "23" };
cmd.parse (sizeof (argv) / sizeof (argv[0]), (char **) argv);
}
EXPECT_EQ (v.a, "u");
EXPECT_EQ (v.d, 23);
EXPECT_EQ (v.e, false);
{
const char *argv[] = { "x", "u", "--plong=24", "--elong" };
cmd.parse (sizeof (argv) / sizeof (argv[0]), (char **) argv);
}
EXPECT_EQ (v.a, "u");
EXPECT_EQ (v.d, 24);
EXPECT_EQ (v.e, true);
{
const char *argv[] = { "x", "u", "-c", "-f=foo" };
cmd.parse (sizeof (argv) / sizeof (argv[0]), (char **) argv);
}
EXPECT_EQ (v.a, "u");
EXPECT_EQ (v.f, "foo");
{
const char *argv[] = { "x", "u", "--flong", "bar" };
cmd.parse (sizeof (argv) / sizeof (argv[0]), (char **) argv);
}
EXPECT_EQ (v.a, "u");
EXPECT_EQ (v.f, "bar");
}
// Array arguments
TEST(3)
{
std::vector<std::string> a;
std::vector<int> b;
tl::CommandLineOptions cmd;
cmd << tl::arg ("a", &a, "")
<< tl::arg ("-b", &b, "");
{
const char *argv[] = { "x", "r,u,v" };
cmd.parse (sizeof (argv) / sizeof (argv[0]), (char **) argv);
}
EXPECT_EQ (int (a.size ()), 3);
EXPECT_EQ (a[0], "r");
EXPECT_EQ (a[1], "u");
EXPECT_EQ (a[2], "v");
EXPECT_EQ (b.empty (), true);
a.clear ();
{
const char *argv[] = { "x", "\"r,u\",v" };
cmd.parse (sizeof (argv) / sizeof (argv[0]), (char **) argv);
}
EXPECT_EQ (int (a.size ()), 2);
EXPECT_EQ (a[0], "r,u");
EXPECT_EQ (a[1], "v");
EXPECT_EQ (b.empty (), true);
a.clear ();
{
const char *argv[] = { "x", "'\"'", "-b=1,5,-13" };
cmd.parse (sizeof (argv) / sizeof (argv[0]), (char **) argv);
}
EXPECT_EQ (int (a.size ()), 1);
EXPECT_EQ (a[0], "\"");
EXPECT_EQ (int (b.size ()), 3);
EXPECT_EQ (b[0], 1);
EXPECT_EQ (b[1], 5);
EXPECT_EQ (b[2], -13);
a.clear ();
b.clear ();
{
const char *argv[] = { "x", "", "-b", "-13,21" };
cmd.parse (sizeof (argv) / sizeof (argv[0]), (char **) argv);
}
EXPECT_EQ (int (a.size ()), 0);
EXPECT_EQ (int (b.size ()), 2);
EXPECT_EQ (b[0], -13);
EXPECT_EQ (b[1], 21);
}
// Repeated array arguments
TEST(4)
{
std::vector<std::string> a;
std::vector<int> b;
tl::CommandLineOptions cmd;
cmd << tl::arg ("*-a|--along", &a, "")
<< tl::arg ("*-b|--blong", &b, "");
{
const char *argv[] = { "x", "-a", "r,u,v" };
cmd.parse (sizeof (argv) / sizeof (argv[0]), (char **) argv);
}
EXPECT_EQ (int (a.size ()), 1);
EXPECT_EQ (a[0], "r,u,v");
EXPECT_EQ (b.empty (), true);
a.clear ();
b.clear ();
{
const char *argv[] = { "x", "-b", "1", "-a=r", "-a", "u", "--along=v", "--blong=2" };
cmd.parse (sizeof (argv) / sizeof (argv[0]), (char **) argv);
}
EXPECT_EQ (int (a.size ()), 3);
EXPECT_EQ (int (b.size ()), 2);
EXPECT_EQ (a[0], "r");
EXPECT_EQ (a[1], "u");
EXPECT_EQ (a[2], "v");
EXPECT_EQ (b[0], 1);
EXPECT_EQ (b[1], 2);
}
// Repeated and non-repeated plain arguments
TEST(5)
{
std::string a;
std::vector<std::string> b;
std::vector<std::string> c;
tl::CommandLineOptions cmd;
cmd << tl::arg ("a", &a, "")
<< tl::arg ("b", &b, "")
<< tl::arg ("?*c", &c, "");
{
const char *argv[] = { "x", "y", "r,u,v" };
cmd.parse (sizeof (argv) / sizeof (argv[0]), (char **) argv);
}
EXPECT_EQ (int (b.size ()), 3);
EXPECT_EQ (int (c.size ()), 0);
EXPECT_EQ (a, "y");
EXPECT_EQ (b[0], "r");
EXPECT_EQ (b[1], "u");
EXPECT_EQ (b[2], "v");
a.clear ();
b.clear ();
c.clear ();
{
const char *argv[] = { "x", "y", "r,u,v", "a,b", "c", "d" };
cmd.parse (sizeof (argv) / sizeof (argv[0]), (char **) argv);
}
EXPECT_EQ (int (b.size ()), 3);
EXPECT_EQ (int (c.size ()), 3);
EXPECT_EQ (a, "y");
EXPECT_EQ (b[0], "r");
EXPECT_EQ (b[1], "u");
EXPECT_EQ (b[2], "v");
EXPECT_EQ (c[0], "a,b");
EXPECT_EQ (c[1], "c");
EXPECT_EQ (c[2], "d");
}