diff options
| author | Matthias Melcher <github@matthiasm.com> | 2023-02-23 15:42:05 +0100 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2023-02-23 15:42:05 +0100 |
| commit | 9f87af8ad9a3d8112518b6bbb5b6075881a5b9a2 (patch) | |
| tree | fe96512734abb7b29bc6b8fac9816d7cc0c4ae3f /test/unittest_core.cxx | |
| parent | 92818939267fc7fbb6a33d86fb78576f55ce6aca (diff) | |
Fl_String refactoring and extension (#683)
- add true unittest and Fl_String testing
- interface and printout are similar to gtest
without requiring external linkage.
just run `unittest --core`.
- new Fl_String API
- extended API to fl_input_str and fl_password_str
- co-authored-by: Albrecht Schlosser <albrechts.fltk@online.de>
Diffstat (limited to 'test/unittest_core.cxx')
| -rw-r--r-- | test/unittest_core.cxx | 253 |
1 files changed, 253 insertions, 0 deletions
diff --git a/test/unittest_core.cxx b/test/unittest_core.cxx new file mode 100644 index 000000000..7e6699956 --- /dev/null +++ b/test/unittest_core.cxx @@ -0,0 +1,253 @@ +// +// Unit tests for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2023 by Bill Spitzak and others. +// +// This library is free software. Distribution and use rights are outlined in +// the file "COPYING" which should have been included with this file. If this +// file is missing or damaged, see the license at: +// +// https://www.fltk.org/COPYING.php +// +// Please see the following page on how to report bugs and issues: +// +// https://www.fltk.org/bugs.php +// + +#include "unittests.h" + +#include <FL/Fl_Group.H> +#include <FL/Fl_Simple_Terminal.H> +#include <FL/Fl_String.H> + +/* Test Fl_String constructor and assignment. */ +TEST(Fl_String, Assignment) { + Fl_String null; + EXPECT_STREQ(null.c_str(), ""); // default initialisation is an empty string + EXPECT_TRUE(null.empty()); + + Fl_String null2(NULL); + EXPECT_STREQ(null2.c_str(), ""); // initialise with a NULL pointer gets an empty string + EXPECT_TRUE(null2.empty()); + + Fl_String empty(""); + EXPECT_STREQ(empty.c_str(), ""); // also, empty CString make empty Fl_String + EXPECT_TRUE(empty.empty()); + + Fl_String text("hello"); + EXPECT_STREQ(text.c_str(), "hello"); // Load some text from a CString + EXPECT_EQ(text.size(), 5); // did we get the size right? + EXPECT_EQ(text.strlen(), 5); // do we have a trailing 0 + EXPECT_GE(text.capacity(), 5); // do we have the capacity + EXPECT_TRUE(!text.empty()); // test the empty() method + + Fl_String text2("abcdef", 3); + EXPECT_STREQ(text2.c_str(), "abc"); + EXPECT_EQ(text2.size(), 3); + + Fl_String text3("abc\0def", 7); + EXPECT_EQ(text3.strlen(), 3); + EXPECT_EQ(text3.size(), 7); + + Fl_String text4(text); + EXPECT_STREQ(text4.c_str(), "hello"); + + Fl_String text5 = text; + EXPECT_STREQ(text5.c_str(), "hello"); + + Fl_String text6 = "yoohoo"; + EXPECT_STREQ(text6.c_str(), "yoohoo"); + + return true; +} + +/* Test methods that access Fl_String content and parts of it. */ +TEST(Fl_String, Access) { + Fl_String hello = "hello"; + EXPECT_STREQ(hello.c_str(), "hello"); + EXPECT_STREQ(hello.data(), "hello"); + EXPECT_EQ(hello[1], 'e'); + EXPECT_EQ(hello[hello.size()], 0); + EXPECT_EQ(hello.at(1), 'e'); + EXPECT_EQ(hello.at(-1), 0); + EXPECT_EQ(hello.at(11), 0); + + hello[1] = 'a'; + EXPECT_STREQ(hello.c_str(), "hallo"); + + hello.data()[1] = 'e'; + EXPECT_STREQ(hello.c_str(), "hello"); + + return true; +} + +/* Test the Fl_String capacity management. */ +TEST(Fl_String, Capacity) { + Fl_String hello; + EXPECT_EQ(hello.capacity(), 0); + + hello = "hi"; + EXPECT_STREQ(hello.c_str(), "hi"); + EXPECT_GE(hello.capacity(), 2); + + hello = "the quick brown fox jumps over the lazy dog"; + EXPECT_STREQ(hello.c_str(), "the quick brown fox jumps over the lazy dog"); + EXPECT_GE(hello.capacity(), 41); + + int c = hello.capacity(); + hello.reserve(c+100); + EXPECT_STREQ(hello.c_str(), "the quick brown fox jumps over the lazy dog"); + EXPECT_GE(hello.capacity(), 141); + + hello = "hi"; + hello.shrink_to_fit(); + EXPECT_EQ(hello.capacity(), 2); + + return true; +} + +/* Test all methods that operate on Fl_String. */ +TEST(Fl_String, Operations) { + Fl_String empty; + Fl_String hello = "Hello", world = "World"; + hello.resize(4); + EXPECT_STREQ(hello.c_str(), "Hell"); + + hello.clear(); + EXPECT_TRUE(hello.empty()); + + hello = "Hello"; + hello.insert(3, "-"); + EXPECT_STREQ(hello.c_str(), "Hel-lo"); + hello = "Hello"; + hello.erase(2, 2); + EXPECT_STREQ(hello.c_str(), "Heo"); + + hello = "Hello"; + hello.push_back('!'); + EXPECT_STREQ(hello.c_str(), "Hello!"); + hello.pop_back(); + EXPECT_STREQ(hello.c_str(), "Hello"); + hello.append(world); + EXPECT_STREQ(hello.c_str(), "HelloWorld"); + hello.append("!"); + EXPECT_STREQ(hello.c_str(), "HelloWorld!"); + hello = "Hello"; + hello += world; + EXPECT_STREQ(hello.c_str(), "HelloWorld"); + hello += "!"; + EXPECT_STREQ(hello.c_str(), "HelloWorld!"); + hello += '?'; + EXPECT_STREQ(hello.c_str(), "HelloWorld!?"); + + hello = "Hello"; + hello.replace(0, 0, "Say ", 4); + EXPECT_STREQ(hello.c_str(), "Say Hello"); + hello.replace(0, 4, ""); + EXPECT_STREQ(hello.c_str(), "Hello"); + hello.replace(2, 2, "bb"); + EXPECT_STREQ(hello.c_str(), "Hebbo"); + hello.replace(2, 2, "xxx"); + EXPECT_STREQ(hello.c_str(), "Hexxxo"); + hello.replace(2, 3, "ll"); + EXPECT_STREQ(hello.c_str(), "Hello"); + hello.replace(2, 0, NULL, 0); + EXPECT_STREQ(hello.c_str(), "Hello"); + hello.replace(Fl_String::npos, Fl_String::npos, world); + EXPECT_STREQ(hello.c_str(), "HelloWorld"); + + hello = "Hello"; + Fl_String sub = hello.substr(); + EXPECT_STREQ(sub.c_str(), "Hello"); // check correct usage + sub = hello.substr(2); + EXPECT_STREQ(sub.c_str(), "llo"); + sub = hello.substr(2, 2); + EXPECT_STREQ(sub.c_str(), "ll"); + sub = hello.substr(-1, 2); + EXPECT_TRUE(sub.empty()); // check faulty values + sub = hello.substr(20, 2); + EXPECT_TRUE(sub.empty()); + sub = empty.substr(0, 2); + EXPECT_TRUE(sub.empty()); + + return true; +} + +/* Test all Fl_String functions that are no part of the class. */ +TEST(Fl_String, Non-Member Functions) { + Fl_String a = "a", b = "b", empty = "", result; + result = a + b; + EXPECT_STREQ(result.c_str(), "ab"); + result = a + empty; + EXPECT_STREQ(result.c_str(), "a"); + result = a + "c"; + EXPECT_STREQ(result.c_str(), "ac"); + result = empty + "x"; + EXPECT_STREQ(result.c_str(), "x"); + EXPECT_TRUE(!(a == b)); + EXPECT_TRUE(a == a); + EXPECT_TRUE(empty == empty); + EXPECT_TRUE(a+b == "ab"); + EXPECT_TRUE(a+"b" == "a" + b); + + return true; +} + +// +//------- test aspects of the FLTK core library ---------- +// + +/* + Create a tab with only a terminal window in it. When shown for the first time, + unittest will visualize progress by runing all regsitered tests one-by-one + every few miliseconds. + + When run in command line mode (option `--core`), all tests are executed + at full speed. + */ +class Ut_Core_Test : public Fl_Group { + + Fl_Simple_Terminal *tty; + bool suite_ran_; + +public: + + // Create the tab + static Fl_Widget *create() { + return new Ut_Core_Test(UT_TESTAREA_X, UT_TESTAREA_Y, UT_TESTAREA_W, UT_TESTAREA_H); + } + + // Constructor for this tab + Ut_Core_Test(int x, int y, int w, int h) + : Fl_Group(x, y, w, h), + tty(NULL), + suite_ran_(false) + { + tty = new Fl_Simple_Terminal(x+4, y+4, w-8, h-8, "Unittest Log"); + tty->ansi(true); + end(); + Ut_Suite::tty = tty; + } + + // Run one single test and repeat calling this until all tests are done + static void timer_cb(void*) { + // Run a test every few miliseconds to visualize the progress + if (Ut_Suite::run_next_test()) + Fl::repeat_timeout(0.2, timer_cb); + } + + // Showing this tab for the first time will trigger the tests + void show() FL_OVERRIDE { + Fl_Group::show(); + if (!suite_ran_) { + Fl::add_timeout(0.5, timer_cb); + suite_ran_ = true; + } + } +}; + +// Register this tab with the unittest app. +UnitTest core(UT_TEST_CORE, "Core Functionality", Ut_Core_Test::create); + + + |
