mirror of
https://github.com/dankamongmen/notcurses
synced 2025-03-09 17:19:03 -04:00
* introduce doctest over googletest #202 * call dtester in in targets * doctest conversion #202 * channel.cpp -> doctest #202 * egcpool tests -> doctest #202 * input tests to doctester * zaxis -> doctest * drone: always define LANG * libav to doctest #202 * panelreel tests to doctest #202 * spec that a C++17 compiler is now required for doctest #202 * enmetric tests -> doctest #202 * fade tests -> doctest #202 * notcurses test case -> doctest #202 * last conversion to doctest #202 * finish move to doctest #202 * drone: set up make test
This commit is contained in:
parent
d4caefc55d
commit
ce2a390b52
@ -37,3 +37,4 @@ steps:
|
||||
- cd build
|
||||
- cmake .. -DCMAKE_BUILD_TYPE=Release
|
||||
- make
|
||||
- env LANG="en_US.UTF-8" make test
|
||||
|
@ -6,7 +6,7 @@ project(notcurses VERSION 0.9.3
|
||||
set(CMAKE_CXX_EXTENSIONS OFF)
|
||||
set(CMAKE_C_STANDARD 11)
|
||||
set(CMAKE_C_VISIBILITY_PRESET hidden)
|
||||
set(CMAKE_CXX_STANDARD 14)
|
||||
set(CMAKE_CXX_STANDARD 17)
|
||||
set(CMAKE_CXX_VISIBILITY_PRESET hidden)
|
||||
|
||||
include(GNUInstallDirs)
|
||||
@ -212,7 +212,7 @@ endif()
|
||||
# Testing
|
||||
file(GLOB TESTSRCS CONFIGURE_DEPENDS tests/*.cpp)
|
||||
add_executable(notcurses-tester ${TESTSRCS})
|
||||
find_package(GTest 1.9 REQUIRED)
|
||||
find_package(doctest REQUIRED doctest>=1.2.7)
|
||||
target_include_directories(notcurses-tester
|
||||
PRIVATE
|
||||
include
|
||||
@ -220,19 +220,24 @@ target_include_directories(notcurses-tester
|
||||
src/lib
|
||||
)
|
||||
target_link_libraries(notcurses-tester
|
||||
GTest::GTest
|
||||
notcurses
|
||||
PRIVATE
|
||||
doctest::doctest
|
||||
notcurses
|
||||
)
|
||||
target_compile_options(notcurses-tester PRIVATE
|
||||
-Wall -Wextra -W -Wshadow
|
||||
target_compile_options(notcurses-tester
|
||||
PRIVATE
|
||||
-Wall -Wextra -W -Wshadow
|
||||
)
|
||||
target_compile_definitions(notcurses-tester
|
||||
PRIVATE
|
||||
FORTIFY_SOURCE=2
|
||||
)
|
||||
|
||||
gtest_discover_tests(notcurses-tester)
|
||||
enable_testing()
|
||||
add_test(
|
||||
NAME notcurses-tester
|
||||
COMMAND notcurses-tester
|
||||
)
|
||||
|
||||
# pkg-config support
|
||||
configure_file(tools/notcurses.pc.in
|
||||
|
@ -101,7 +101,7 @@ that fine library.
|
||||
|
||||
## Requirements
|
||||
|
||||
* A C11 and a C++14 compiler
|
||||
* A C11 and a C++17 compiler
|
||||
* CMake 3.13.0+
|
||||
* From NCURSES: terminfo 6.1+
|
||||
* (OPTIONAL) From FFMpeg: libswscale 5.0+, libavformat 57.0+, libavutil 56.0+
|
||||
|
2
debian/control
vendored
2
debian/control
vendored
@ -3,7 +3,7 @@ Priority: optional
|
||||
Maintainer: Nick Black <dankamongmen@gmail.com>
|
||||
Build-Depends: debhelper-compat (= 12), cmake (>= 3.13), pkg-config (>= 0.29),
|
||||
libgtest-dev (>= 1.8.0), libncurses-dev (>= 6.1), libavformat-dev (>= 57.0),
|
||||
libswscale-dev (>= 5.0), libavutil-dev (>= 56.0)
|
||||
libswscale-dev (>= 5.0), libavutil-dev (>= 56.0), doctest-dev (>= 1.2.7)
|
||||
Standards-Version: 4.4.1.1
|
||||
Section: libs
|
||||
Homepage: https://nick-black.com/dankwiki/index.php/notcurses
|
||||
|
@ -10,13 +10,6 @@
|
||||
#define BLOCKSIZE 512 // show this many per page
|
||||
#define CHUNKSIZE 32 // show this many per line
|
||||
|
||||
static int
|
||||
fade_block(struct ncplane* nn, const struct timespec* subdelay){
|
||||
int ret = ncplane_fadein(nn, subdelay, demo_fader);
|
||||
ncplane_destroy(nn);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int
|
||||
draw_block(struct ncplane* nn, uint32_t blockstart){
|
||||
cell ul = CELL_TRIVIAL_INITIALIZER, ur = CELL_TRIVIAL_INITIALIZER;
|
||||
@ -204,9 +197,9 @@ int unicodeblocks_demo(struct notcurses* nc){
|
||||
if(ncplane_printf_aligned(n, 6 + BLOCKSIZE / CHUNKSIZE, NCALIGN_CENTER, "%s", description) <= 0){
|
||||
return -1;
|
||||
}
|
||||
if(fade_block(nn, &subdelay)){ // destroys nn
|
||||
return -1;
|
||||
}
|
||||
notcurses_render(nc);
|
||||
nanosleep(&subdelay, NULL);
|
||||
ncplane_destroy(nn);
|
||||
// for a 32-bit wchar_t, we would want up through 24 bits of block ID. but
|
||||
// really, the vast majority of space is unused.
|
||||
blockstart += BLOCKSIZE;
|
||||
|
@ -99,10 +99,6 @@ int ncplane_fadein(ncplane* n, const struct timespec* ts, fadecb fader){
|
||||
int maxsteps = maxfsteps > maxbsteps ? maxfsteps : maxbsteps;
|
||||
uint64_t nanosecs_total = ts->tv_sec * NANOSECS_IN_SEC + ts->tv_nsec;
|
||||
uint64_t nanosecs_step = nanosecs_total / maxsteps;
|
||||
while(nanosecs_step < 10000000){ // 10msec
|
||||
nanosecs_step *= 10;
|
||||
maxsteps = nanosecs_total / nanosecs_step;
|
||||
}
|
||||
struct timespec times;
|
||||
clock_gettime(CLOCK_MONOTONIC, ×);
|
||||
// Start time in absolute nanoseconds
|
||||
@ -178,10 +174,6 @@ int ncplane_fadeout(struct ncplane* n, const struct timespec* ts, fadecb fader){
|
||||
int maxsteps = maxfsteps > maxbsteps ? maxfsteps : maxbsteps;
|
||||
uint64_t nanosecs_total = ts->tv_sec * NANOSECS_IN_SEC + ts->tv_nsec;
|
||||
uint64_t nanosecs_step = nanosecs_total / maxsteps;
|
||||
while(nanosecs_step < 10000000){ // 10msec
|
||||
nanosecs_step *= 10;
|
||||
maxsteps = nanosecs_total / nanosecs_step;
|
||||
}
|
||||
struct timespec times;
|
||||
clock_gettime(CLOCK_MONOTONIC, ×);
|
||||
// Start time in absolute nanoseconds
|
||||
|
184
tests/cell.cpp
184
tests/cell.cpp
@ -2,119 +2,109 @@
|
||||
#include "egcpool.h"
|
||||
#include "main.h"
|
||||
|
||||
class CellTest : public :: testing::Test {
|
||||
protected:
|
||||
void SetUp() override {
|
||||
setlocale(LC_ALL, "");
|
||||
if(getenv("TERM") == nullptr){
|
||||
GTEST_SKIP();
|
||||
}
|
||||
notcurses_options nopts{};
|
||||
nopts.inhibit_alternate_screen = true;
|
||||
nopts.suppress_bannner = true;
|
||||
outfp_ = fopen("/dev/tty", "wb");
|
||||
ASSERT_NE(nullptr, outfp_);
|
||||
nc_ = notcurses_init(&nopts, outfp_);
|
||||
ASSERT_NE(nullptr, nc_);
|
||||
n_ = notcurses_stdplane(nc_);
|
||||
ASSERT_NE(nullptr, n_);
|
||||
TEST_CASE("Cell") {
|
||||
// common initialization
|
||||
if(getenv("TERM") == nullptr){
|
||||
return;
|
||||
}
|
||||
|
||||
void TearDown() override {
|
||||
if(nc_){
|
||||
EXPECT_EQ(0, notcurses_stop(nc_));
|
||||
}
|
||||
if(outfp_){
|
||||
fclose(outfp_);
|
||||
}
|
||||
}
|
||||
|
||||
struct notcurses* nc_{};
|
||||
struct ncplane* n_{};
|
||||
FILE* outfp_{};
|
||||
};
|
||||
outfp_ = fopen("/dev/tty", "wb");
|
||||
REQUIRE(nullptr != outfp_);
|
||||
notcurses_options nopts{};
|
||||
nopts.inhibit_alternate_screen = true;
|
||||
nopts.suppress_bannner = true;
|
||||
struct notcurses* nc_ = notcurses_init(&nopts, outfp_);
|
||||
REQUIRE(nullptr != nc_);
|
||||
struct ncplane* n_ = notcurses_stdplane(nc_);
|
||||
REQUIRE(nullptr != n_);
|
||||
|
||||
TEST_F(CellTest, LoadSimple) {
|
||||
SUBCASE("LoadSimple") {
|
||||
cell c = CELL_TRIVIAL_INITIALIZER;
|
||||
REQUIRE(1 == cell_load(n_, &c, " "));
|
||||
CHECK(cell_simple_p(&c));
|
||||
cell_release(n_, &c);
|
||||
}
|
||||
|
||||
SUBCASE("SetItalic") {
|
||||
cell c = CELL_TRIVIAL_INITIALIZER;
|
||||
ASSERT_EQ(1, cell_load(n_, &c, " "));
|
||||
EXPECT_TRUE(cell_simple_p(&c));
|
||||
cell_release(n_, &c);
|
||||
}
|
||||
int dimy, dimx;
|
||||
notcurses_term_dim_yx(nc_, &dimy, &dimx);
|
||||
cell_styles_set(&c, CELL_STYLE_ITALIC);
|
||||
REQUIRE(1 == cell_load(n_, &c, "i"));
|
||||
cell_set_fg_rgb(&c, 255, 255, 255);
|
||||
ncplane_set_default(n_, &c);
|
||||
cell_release(n_, &c);
|
||||
CHECK(0 == notcurses_render(nc_));
|
||||
cell_styles_off(&c, CELL_STYLE_ITALIC);
|
||||
}
|
||||
|
||||
TEST_F(CellTest, SetItalic) {
|
||||
cell c = CELL_TRIVIAL_INITIALIZER;
|
||||
int dimy, dimx;
|
||||
notcurses_term_dim_yx(nc_, &dimy, &dimx);
|
||||
cell_styles_set(&c, CELL_STYLE_ITALIC);
|
||||
ASSERT_EQ(1, cell_load(n_, &c, "i"));
|
||||
cell_set_fg_rgb(&c, 255, 255, 255);
|
||||
ncplane_set_default(n_, &c);
|
||||
cell_release(n_, &c);
|
||||
EXPECT_EQ(0, notcurses_render(nc_));
|
||||
cell_styles_off(&c, CELL_STYLE_ITALIC);
|
||||
}
|
||||
SUBCASE("SetBold") {
|
||||
cell c = CELL_TRIVIAL_INITIALIZER;
|
||||
int dimy, dimx;
|
||||
notcurses_term_dim_yx(nc_, &dimy, &dimx);
|
||||
cell_styles_set(&c, CELL_STYLE_BOLD);
|
||||
REQUIRE(1 == cell_load(n_, &c, "b"));
|
||||
cell_set_fg_rgb(&c, 255, 255, 255);
|
||||
ncplane_set_default(n_, &c);
|
||||
cell_release(n_, &c);
|
||||
CHECK(0 == notcurses_render(nc_));
|
||||
cell_styles_off(&c, CELL_STYLE_BOLD);
|
||||
}
|
||||
|
||||
TEST_F(CellTest, SetBold) {
|
||||
cell c = CELL_TRIVIAL_INITIALIZER;
|
||||
int dimy, dimx;
|
||||
notcurses_term_dim_yx(nc_, &dimy, &dimx);
|
||||
cell_styles_set(&c, CELL_STYLE_BOLD);
|
||||
ASSERT_EQ(1, cell_load(n_, &c, "b"));
|
||||
cell_set_fg_rgb(&c, 255, 255, 255);
|
||||
ncplane_set_default(n_, &c);
|
||||
cell_release(n_, &c);
|
||||
EXPECT_EQ(0, notcurses_render(nc_));
|
||||
cell_styles_off(&c, CELL_STYLE_BOLD);
|
||||
}
|
||||
SUBCASE("SetUnderline") {
|
||||
cell c = CELL_TRIVIAL_INITIALIZER;
|
||||
int dimy, dimx;
|
||||
notcurses_term_dim_yx(nc_, &dimy, &dimx);
|
||||
cell_styles_set(&c, CELL_STYLE_UNDERLINE);
|
||||
REQUIRE(1 == cell_load(n_, &c, "u"));
|
||||
cell_set_fg_rgb(&c, 255, 255, 255);
|
||||
ncplane_set_default(n_, &c);
|
||||
cell_release(n_, &c);
|
||||
CHECK(0 == notcurses_render(nc_));
|
||||
cell_styles_off(&c, CELL_STYLE_UNDERLINE);
|
||||
}
|
||||
|
||||
TEST_F(CellTest, SetUnderline) {
|
||||
cell c = CELL_TRIVIAL_INITIALIZER;
|
||||
int dimy, dimx;
|
||||
notcurses_term_dim_yx(nc_, &dimy, &dimx);
|
||||
cell_styles_set(&c, CELL_STYLE_UNDERLINE);
|
||||
ASSERT_EQ(1, cell_load(n_, &c, "u"));
|
||||
cell_set_fg_rgb(&c, 255, 255, 255);
|
||||
ncplane_set_default(n_, &c);
|
||||
cell_release(n_, &c);
|
||||
EXPECT_EQ(0, notcurses_render(nc_));
|
||||
cell_styles_off(&c, CELL_STYLE_UNDERLINE);
|
||||
}
|
||||
|
||||
/*TEST_F(CellTest, CellLoadTamil) {
|
||||
/* SUBCASE("CellLoadTamil") {
|
||||
const char zerodeg[] = "\u0bb8\u0bc0\u0bb0\u0bc7\u0bb3\u0b95\u0bbf\u0b95\u0bbf\u0bb0\u0bbf";
|
||||
cell c = CELL_TRIVIAL_INITIALIZER;
|
||||
size_t ulen = cell_load(n_, &c, zerodeg);
|
||||
// First have U+0BB8 TAMIL LETTER SA U+0BC0 TAMIL VOWEL SIGN II
|
||||
// // e0 ae b8 e0 af 80
|
||||
ASSERT_EQ(6, ulen);
|
||||
REQUIRE(6 == ulen);
|
||||
ulen = cell_load(n_, &c, zerodeg + ulen);
|
||||
// U+0BB0 TAMIL LETTER RA U+0BCB TAMIL VOWEL SIGN OO
|
||||
// e0 ae b0 e0 af 8b
|
||||
ASSERT_EQ(6, ulen);
|
||||
REQUIRE(6 == ulen);
|
||||
// FIXME
|
||||
}*/
|
||||
}*/
|
||||
|
||||
TEST_F(CellTest, CellSetFGAlpha){
|
||||
cell c = CELL_TRIVIAL_INITIALIZER;
|
||||
EXPECT_GT(0, cell_set_fg_alpha(&c, -1));
|
||||
EXPECT_GT(0, cell_set_fg_alpha(&c, 4));
|
||||
EXPECT_EQ(0, cell_set_fg_alpha(&c, CELL_ALPHA_OPAQUE));
|
||||
EXPECT_EQ(CELL_ALPHA_OPAQUE, cell_get_fg_alpha(&c));
|
||||
EXPECT_EQ(0, cell_set_fg_alpha(&c, CELL_ALPHA_HIGHCONTRAST));
|
||||
EXPECT_EQ(CELL_ALPHA_HIGHCONTRAST, cell_get_fg_alpha(&c));
|
||||
EXPECT_TRUE(cell_fg_default_p(&c));
|
||||
EXPECT_TRUE(cell_bg_default_p(&c));
|
||||
SUBCASE("CellSetFGAlpha"){
|
||||
cell c = CELL_TRIVIAL_INITIALIZER;
|
||||
CHECK(0 > cell_set_fg_alpha(&c, -1));
|
||||
CHECK(0 > cell_set_fg_alpha(&c, 4));
|
||||
CHECK(0 == cell_set_fg_alpha(&c, CELL_ALPHA_OPAQUE));
|
||||
CHECK(CELL_ALPHA_OPAQUE == cell_get_fg_alpha(&c));
|
||||
CHECK(0 == cell_set_fg_alpha(&c, CELL_ALPHA_HIGHCONTRAST));
|
||||
CHECK(CELL_ALPHA_HIGHCONTRAST == cell_get_fg_alpha(&c));
|
||||
CHECK(cell_fg_default_p(&c));
|
||||
CHECK(cell_bg_default_p(&c));
|
||||
}
|
||||
|
||||
SUBCASE("CellSetBGAlpha"){
|
||||
cell c = CELL_TRIVIAL_INITIALIZER;
|
||||
CHECK(0 > cell_set_bg_alpha(&c, -1));
|
||||
CHECK(0 > cell_set_bg_alpha(&c, 4));
|
||||
CHECK(0 == cell_set_bg_alpha(&c, CELL_ALPHA_OPAQUE));
|
||||
CHECK(CELL_ALPHA_OPAQUE == cell_get_bg_alpha(&c));
|
||||
CHECK(0 != cell_set_bg_alpha(&c, CELL_ALPHA_HIGHCONTRAST));
|
||||
CHECK(0 == cell_set_bg_alpha(&c, CELL_ALPHA_TRANSPARENT));
|
||||
CHECK(CELL_ALPHA_TRANSPARENT == cell_get_bg_alpha(&c));
|
||||
CHECK(cell_fg_default_p(&c));
|
||||
CHECK(cell_bg_default_p(&c));
|
||||
}
|
||||
|
||||
// common teardown
|
||||
CHECK(0 == notcurses_stop(nc_));
|
||||
CHECK(0 == fclose(outfp_));
|
||||
}
|
||||
|
||||
TEST_F(CellTest, CellSetBGAlpha){
|
||||
cell c = CELL_TRIVIAL_INITIALIZER;
|
||||
EXPECT_GT(0, cell_set_bg_alpha(&c, -1));
|
||||
EXPECT_GT(0, cell_set_bg_alpha(&c, 4));
|
||||
EXPECT_EQ(0, cell_set_bg_alpha(&c, CELL_ALPHA_OPAQUE));
|
||||
EXPECT_EQ(CELL_ALPHA_OPAQUE, cell_get_bg_alpha(&c));
|
||||
EXPECT_NE(0, cell_set_bg_alpha(&c, CELL_ALPHA_HIGHCONTRAST));
|
||||
EXPECT_EQ(0, cell_set_bg_alpha(&c, CELL_ALPHA_TRANSPARENT));
|
||||
EXPECT_EQ(CELL_ALPHA_TRANSPARENT, cell_get_bg_alpha(&c));
|
||||
EXPECT_TRUE(cell_fg_default_p(&c));
|
||||
EXPECT_TRUE(cell_bg_default_p(&c));
|
||||
}
|
||||
|
@ -1,14 +1,7 @@
|
||||
#include <notcurses.h>
|
||||
#include "main.h"
|
||||
|
||||
class ChannelTest : public :: testing::Test {
|
||||
protected:
|
||||
void SetUp() override {
|
||||
setlocale(LC_ALL, "");
|
||||
}
|
||||
};
|
||||
|
||||
TEST_F(ChannelTest, ChannelGetRGB){
|
||||
TEST_CASE("ChannelGetRGB") {
|
||||
const struct t {
|
||||
uint32_t channel;
|
||||
int r, g, b;
|
||||
@ -20,14 +13,14 @@ TEST_F(ChannelTest, ChannelGetRGB){
|
||||
};
|
||||
for(auto i = 0u ; i < sizeof(test) / sizeof(*test) ; ++i){
|
||||
unsigned r, g, b;
|
||||
EXPECT_EQ(test[i].channel, channel_get_rgb(test[i].channel, &r, &g, &b));
|
||||
EXPECT_EQ(test[i].r, r);
|
||||
EXPECT_EQ(test[i].g, g);
|
||||
EXPECT_EQ(test[i].b, b);
|
||||
CHECK(test[i].channel == channel_get_rgb(test[i].channel, &r, &g, &b));
|
||||
CHECK(test[i].r == r);
|
||||
CHECK(test[i].g == g);
|
||||
CHECK(test[i].b == b);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(ChannelTest, ChannelGetAlpha){
|
||||
TEST_CASE("ChannelGetAlpha") {
|
||||
const struct t {
|
||||
uint32_t channel;
|
||||
int a;
|
||||
@ -40,11 +33,11 @@ TEST_F(ChannelTest, ChannelGetAlpha){
|
||||
{ .channel = 0xffffffff, .a = 3, },
|
||||
};
|
||||
for(auto i = 0u ; i < sizeof(test) / sizeof(*test) ; ++i){
|
||||
EXPECT_EQ(test[i].a, channel_get_alpha(test[i].channel));
|
||||
CHECK(test[i].a == channel_get_alpha(test[i].channel));
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(ChannelTest, ChannelGetDefault){
|
||||
TEST_CASE("ChannelGetDefault") {
|
||||
const struct t {
|
||||
uint32_t channel;
|
||||
bool def;
|
||||
@ -57,19 +50,19 @@ TEST_F(ChannelTest, ChannelGetDefault){
|
||||
{ .channel = 0xffffffff, .def = false, },
|
||||
};
|
||||
for(auto i = 0u ; i < sizeof(test) / sizeof(*test) ; ++i){
|
||||
EXPECT_EQ(test[i].def, channel_default_p(test[i].channel));
|
||||
CHECK(test[i].def == channel_default_p(test[i].channel));
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(ChannelTest, ChannelSetDefault){
|
||||
TEST_CASE("ChannelSetDefault") {
|
||||
const uint32_t channels[] = {
|
||||
0x40000000, 0x4fffffff, 0xcfffffff,
|
||||
0x40808080, 0x40080808, 0xffffffff,
|
||||
};
|
||||
for(auto i = 0u ; i < sizeof(channels) / sizeof(*channels) ; ++i){
|
||||
uint32_t channel = channels[i];
|
||||
EXPECT_FALSE(channel_default_p(channel));
|
||||
CHECK(!channel_default_p(channel));
|
||||
channel_set_default(&channel);
|
||||
EXPECT_TRUE(channel_default_p(channel));
|
||||
CHECK(channel_default_p(channel));
|
||||
}
|
||||
}
|
||||
|
5942
tests/doctest.h
Normal file
5942
tests/doctest.h
Normal file
File diff suppressed because it is too large
Load Diff
@ -1,211 +1,208 @@
|
||||
#include <vector>
|
||||
#include <notcurses.h>
|
||||
#include "egcpool.h"
|
||||
#include "main.h"
|
||||
|
||||
class EGCPoolTest : public :: testing::Test {
|
||||
protected:
|
||||
void SetUp() override {
|
||||
setlocale(LC_ALL, "");
|
||||
}
|
||||
|
||||
void TearDown() override {
|
||||
egcpool_dump(&pool_);
|
||||
}
|
||||
TEST_CASE("EGCpool") {
|
||||
|
||||
egcpool pool_{};
|
||||
};
|
||||
|
||||
TEST_F(EGCPoolTest, Initialized) {
|
||||
EXPECT_EQ(nullptr, pool_.pool);
|
||||
EXPECT_EQ(0, pool_.poolsize);
|
||||
EXPECT_EQ(0, pool_.poolwrite);
|
||||
EXPECT_EQ(0, pool_.poolused);
|
||||
}
|
||||
SUBCASE("Initialized") {
|
||||
CHECK(!pool_.pool);
|
||||
CHECK(!pool_.poolsize);
|
||||
CHECK(!pool_.poolwrite);
|
||||
CHECK(!pool_.poolused);
|
||||
}
|
||||
|
||||
TEST_F(EGCPoolTest, UTF8EGC) {
|
||||
const char* wstr = "☢";
|
||||
int c;
|
||||
auto ulen = utf8_egc_len(wstr, &c);
|
||||
ASSERT_LT(0, ulen);
|
||||
EXPECT_LT(0, c);
|
||||
wstr = "▓";
|
||||
ulen = utf8_egc_len(wstr, &c);
|
||||
ASSERT_LT(0, ulen);
|
||||
EXPECT_LT(0, c);
|
||||
}
|
||||
SUBCASE("UTF8EGC") {
|
||||
const char* wstr = "☢";
|
||||
int c;
|
||||
auto ulen = utf8_egc_len(wstr, &c);
|
||||
REQUIRE(0 < ulen);
|
||||
CHECK(0 < c);
|
||||
wstr = "▓";
|
||||
ulen = utf8_egc_len(wstr, &c);
|
||||
REQUIRE(0 < ulen);
|
||||
CHECK(0 < c);
|
||||
}
|
||||
|
||||
// we're gonna run both a composed latin a with grave, and then a latin a with
|
||||
// a combining nonspacing grave
|
||||
TEST_F(EGCPoolTest, UTF8EGCCombining) {
|
||||
const char* w1 = "\u00e0"; // (utf8: c3 a0)
|
||||
const char* w2 = "\u0061\u0300"; // (utf8: 61 cc 80)
|
||||
const char* w3 = "\u0061"; // (utf8: 61)
|
||||
int c1, c2, c3;
|
||||
auto u1 = utf8_egc_len(w1, &c1);
|
||||
auto u2 = utf8_egc_len(w2, &c2);
|
||||
auto u3 = utf8_egc_len(w3, &c3);
|
||||
ASSERT_EQ(2, u1);
|
||||
ASSERT_EQ(3, u2);
|
||||
ASSERT_EQ(1, u3);
|
||||
ASSERT_EQ(1, c1);
|
||||
ASSERT_EQ(1, c2);
|
||||
ASSERT_EQ(1, c3);
|
||||
}
|
||||
// we're gonna run both a composed latin a with grave, and then a latin a with
|
||||
// a combining nonspacing grave
|
||||
SUBCASE("UTF8EGCCombining") {
|
||||
const char* w1 = "\u00e0"; // (utf8: c3 a0)
|
||||
const char* w2 = "\u0061\u0300"; // (utf8: 61 cc 80)
|
||||
const char* w3 = "\u0061"; // (utf8: 61)
|
||||
int c1, c2, c3;
|
||||
auto u1 = utf8_egc_len(w1, &c1);
|
||||
auto u2 = utf8_egc_len(w2, &c2);
|
||||
auto u3 = utf8_egc_len(w3, &c3);
|
||||
REQUIRE(2 == u1);
|
||||
REQUIRE(3 == u2);
|
||||
REQUIRE(1 == u3);
|
||||
REQUIRE(1 == c1);
|
||||
REQUIRE(1 == c2);
|
||||
REQUIRE(1 == c3);
|
||||
}
|
||||
|
||||
TEST_F(EGCPoolTest, AddAndRemove) {
|
||||
const char* wstr = "\ufdfd"; // bismallih
|
||||
int c;
|
||||
auto ulen = utf8_egc_len(wstr, &c);
|
||||
ASSERT_LE(0, egcpool_stash(&pool_, wstr, ulen));
|
||||
ASSERT_EQ(1, c); // not considered wide, believe it or not
|
||||
EXPECT_NE(nullptr, pool_.pool);
|
||||
EXPECT_STREQ(pool_.pool, wstr);
|
||||
EXPECT_LT(0, pool_.poolsize);
|
||||
EXPECT_EQ(ulen + 1, pool_.poolused);
|
||||
EXPECT_LT(0, pool_.poolwrite);
|
||||
EXPECT_LE(pool_.poolused, pool_.poolsize);
|
||||
egcpool_release(&pool_, 0);
|
||||
EXPECT_EQ('\0', *pool_.pool);
|
||||
EXPECT_LT(0, pool_.poolsize);
|
||||
EXPECT_EQ(0, pool_.poolused);
|
||||
EXPECT_LT(0, pool_.poolwrite);
|
||||
}
|
||||
SUBCASE("AddAndRemove") {
|
||||
const char* wstr = "\ufdfd"; // bismallih
|
||||
int c;
|
||||
auto ulen = utf8_egc_len(wstr, &c);
|
||||
REQUIRE(0 <= egcpool_stash(&pool_, wstr, ulen));
|
||||
REQUIRE(1 == c); // not considered wide, believe it or not
|
||||
CHECK(pool_.pool);
|
||||
CHECK(!strcmp(pool_.pool, wstr));
|
||||
CHECK(0 < pool_.poolsize);
|
||||
CHECK(ulen + 1 == pool_.poolused);
|
||||
CHECK(0 < pool_.poolwrite);
|
||||
CHECK(pool_.poolused <= pool_.poolsize);
|
||||
egcpool_release(&pool_, 0);
|
||||
CHECK_EQ('\0', *pool_.pool);
|
||||
CHECK(0 < pool_.poolsize);
|
||||
CHECK(0 == pool_.poolused);
|
||||
CHECK(0 < pool_.poolwrite);
|
||||
}
|
||||
|
||||
TEST_F(EGCPoolTest, AddTwiceRemoveFirst) {
|
||||
const char* wstr = "\u8840"; // cjk unified ideograph, wide
|
||||
int c1, c2; // column counts
|
||||
auto u1 = utf8_egc_len(wstr, &c1); // bytes consumed
|
||||
auto u2 = utf8_egc_len(wstr, &c2);
|
||||
int o1 = egcpool_stash(&pool_, wstr, u1);
|
||||
int o2 = egcpool_stash(&pool_, wstr, u2);
|
||||
ASSERT_LE(0, o1);
|
||||
ASSERT_LT(o1, o2);
|
||||
ASSERT_EQ(2, c1);
|
||||
ASSERT_EQ(c1, c2);
|
||||
EXPECT_NE(nullptr, pool_.pool);
|
||||
EXPECT_STREQ(pool_.pool + o1, wstr);
|
||||
EXPECT_STREQ(pool_.pool + o2, wstr);
|
||||
EXPECT_LT(0, pool_.poolsize);
|
||||
EXPECT_EQ(u1 + u2 + 2, pool_.poolused);
|
||||
EXPECT_EQ(u1 + u2 + 2, pool_.poolwrite);
|
||||
EXPECT_LE(pool_.poolused, pool_.poolsize);
|
||||
egcpool_release(&pool_, o1);
|
||||
EXPECT_EQ('\0', pool_.pool[o1]);
|
||||
EXPECT_EQ(u2 + 1, pool_.poolused);
|
||||
EXPECT_LT(0, pool_.poolwrite);
|
||||
}
|
||||
SUBCASE("AddTwiceRemoveFirst") {
|
||||
const char* wstr = "\u8840"; // cjk unified ideograph, wide
|
||||
int c1, c2; // column counts
|
||||
auto u1 = utf8_egc_len(wstr, &c1); // bytes consumed
|
||||
auto u2 = utf8_egc_len(wstr, &c2);
|
||||
int o1 = egcpool_stash(&pool_, wstr, u1);
|
||||
int o2 = egcpool_stash(&pool_, wstr, u2);
|
||||
REQUIRE(0 <= o1);
|
||||
REQUIRE(o1 < o2);
|
||||
REQUIRE(2 == c1);
|
||||
REQUIRE(c1 == c2);
|
||||
CHECK(pool_.pool);
|
||||
CHECK(!strcmp(pool_.pool + o1, wstr));
|
||||
CHECK(!strcmp(pool_.pool + o2, wstr));
|
||||
CHECK(0 < pool_.poolsize);
|
||||
CHECK(u1 + u2 + 2 == pool_.poolused);
|
||||
CHECK(u1 + u2 + 2 == pool_.poolwrite);
|
||||
CHECK(pool_.poolused < pool_.poolsize);
|
||||
egcpool_release(&pool_, o1);
|
||||
CHECK('\0' == pool_.pool[o1]);
|
||||
CHECK(u2 + 1 == pool_.poolused);
|
||||
CHECK(0 < pool_.poolwrite);
|
||||
}
|
||||
|
||||
TEST_F(EGCPoolTest, AddTwiceRemoveSecond) {
|
||||
const char* wstr = "\u8840"; // cjk unified ideograph, wide
|
||||
int c1, c2; // column counts
|
||||
auto u1 = utf8_egc_len(wstr, &c1); // bytes consumed
|
||||
auto u2 = utf8_egc_len(wstr, &c2);
|
||||
int o1 = egcpool_stash(&pool_, wstr, u1);
|
||||
int o2 = egcpool_stash(&pool_, wstr, u2);
|
||||
ASSERT_LT(o1, o2);
|
||||
ASSERT_EQ(2, c1);
|
||||
ASSERT_EQ(c1, c2);
|
||||
EXPECT_NE(nullptr, pool_.pool);
|
||||
EXPECT_STREQ(pool_.pool + o1, wstr);
|
||||
EXPECT_STREQ(pool_.pool + o2, wstr);
|
||||
EXPECT_LT(0, pool_.poolsize);
|
||||
EXPECT_EQ(u1 + u2 + 2, pool_.poolused);
|
||||
EXPECT_EQ(u1 + u2 + 2, pool_.poolwrite);
|
||||
EXPECT_LE(pool_.poolused, pool_.poolsize);
|
||||
egcpool_release(&pool_, o2);
|
||||
EXPECT_EQ('\0', pool_.pool[o2]);
|
||||
EXPECT_EQ(u2 + 1, pool_.poolused);
|
||||
EXPECT_LT(0, pool_.poolwrite);
|
||||
}
|
||||
SUBCASE("AddTwiceRemoveSecond") {
|
||||
const char* wstr = "\u8840"; // cjk unified ideograph, wide
|
||||
int c1, c2; // column counts
|
||||
auto u1 = utf8_egc_len(wstr, &c1); // bytes consumed
|
||||
auto u2 = utf8_egc_len(wstr, &c2);
|
||||
int o1 = egcpool_stash(&pool_, wstr, u1);
|
||||
int o2 = egcpool_stash(&pool_, wstr, u2);
|
||||
REQUIRE(o1 < o2);
|
||||
REQUIRE(2 == c1);
|
||||
REQUIRE(c1 == c2);
|
||||
CHECK(pool_.pool);
|
||||
CHECK(!strcmp(pool_.pool + o1, wstr));
|
||||
CHECK(!strcmp(pool_.pool + o2, wstr));
|
||||
CHECK(0 < pool_.poolsize);
|
||||
CHECK(u1 + u2 + 2 == pool_.poolused);
|
||||
CHECK(u1 + u2 + 2 == pool_.poolwrite);
|
||||
CHECK(pool_.poolused <= pool_.poolsize);
|
||||
egcpool_release(&pool_, o2);
|
||||
CHECK('\0' == pool_.pool[o2]);
|
||||
CHECK(u2 + 1 == pool_.poolused);
|
||||
CHECK(0 < pool_.poolwrite);
|
||||
}
|
||||
|
||||
// POOL_MINIMUM_ALLOC is the minimum size of an egcpool once it goes active.
|
||||
// add EGCs to it past this boundary, and verify that they're all still
|
||||
// accurate.
|
||||
TEST_F(EGCPoolTest, ForceReallocation) {
|
||||
std::vector<int> candidates;
|
||||
char* firstalloc = nullptr;
|
||||
for(auto i = 0u ; i < 1u << 20u ; ++i){
|
||||
char mb[MB_CUR_MAX + 1];
|
||||
wchar_t wcs = i + 0x80;
|
||||
auto r = wctomb(mb, wcs);
|
||||
if(r < 0){
|
||||
candidates.push_back(-1);
|
||||
continue;
|
||||
// POOL_MINIMUM_ALLOC is the minimum size of an egcpool once it goes active.
|
||||
// add EGCs to it past this boundary, and verify that they're all still
|
||||
// accurate.
|
||||
SUBCASE("ForceReallocation") {
|
||||
std::vector<int> candidates;
|
||||
char* firstalloc = nullptr;
|
||||
for(auto i = 0u ; i < 1u << 20u ; ++i){
|
||||
char mb[MB_CUR_MAX + 1];
|
||||
wchar_t wcs = i + 0x80;
|
||||
auto r = wctomb(mb, wcs);
|
||||
if(r < 0){
|
||||
candidates.push_back(-1);
|
||||
continue;
|
||||
}
|
||||
REQUIRE(sizeof(mb) >= r);
|
||||
mb[r] = '\0';
|
||||
candidates.push_back(egcpool_stash(&pool_, mb, r));
|
||||
REQUIRE((1u << 24u) > candidates[i]);
|
||||
if(!firstalloc){
|
||||
firstalloc = pool_.pool;
|
||||
}
|
||||
}
|
||||
ASSERT_GE(sizeof(mb), r);
|
||||
mb[r] = '\0';
|
||||
candidates.push_back(egcpool_stash(&pool_, mb, r));
|
||||
ASSERT_GT(1u << 24u, candidates[i]);
|
||||
if(!firstalloc){
|
||||
firstalloc = pool_.pool;
|
||||
// verify that we moved the pool at least once
|
||||
REQUIRE(pool_.pool != firstalloc);
|
||||
for(auto i = 0u ; i < candidates.size() ; ++i){
|
||||
auto stored = pool_.pool + candidates[i];
|
||||
char mb[MB_CUR_MAX + 1];
|
||||
wchar_t wcs = i + 0x80;
|
||||
auto r = wctomb(mb, wcs);
|
||||
if(r < 0){
|
||||
REQUIRE(-1 == candidates[i]);
|
||||
continue;
|
||||
}
|
||||
REQUIRE(0 < r);
|
||||
mb[r] = '\0';
|
||||
CHECK(!strcmp(mb, stored));
|
||||
}
|
||||
}
|
||||
// verify that we moved the pool at least once
|
||||
ASSERT_NE(pool_.pool, firstalloc);
|
||||
for(auto i = 0u ; i < candidates.size() ; ++i){
|
||||
auto stored = pool_.pool + candidates[i];
|
||||
char mb[MB_CUR_MAX + 1];
|
||||
wchar_t wcs = i + 0x80;
|
||||
auto r = wctomb(mb, wcs);
|
||||
if(r < 0){
|
||||
ASSERT_EQ(-1, candidates[i]);
|
||||
continue;
|
||||
}
|
||||
ASSERT_LT(0, r);
|
||||
mb[r] = '\0';
|
||||
EXPECT_STREQ(mb, stored);
|
||||
}
|
||||
}
|
||||
|
||||
// POOL_MINIMUM_ALLOC is the minimum size of an egcpool once it goes active.
|
||||
// add EGCs to it past this boundary, and verify that they're all still
|
||||
// accurate.
|
||||
TEST_F(EGCPoolTest, ForceReallocationWithRemovals) {
|
||||
std::vector<int> candidates;
|
||||
char* curpool = nullptr;
|
||||
for(auto i = 0u ; i < 1u << 20u ; ++i){
|
||||
char mb[MB_CUR_MAX + 1];
|
||||
wchar_t wcs = (i % 0x1000) + 0x80;
|
||||
auto r = wctomb(mb, wcs);
|
||||
if(r < 0){
|
||||
candidates.push_back(-1);
|
||||
continue;
|
||||
}
|
||||
ASSERT_GE(sizeof(mb), r);
|
||||
mb[r] = '\0';
|
||||
candidates.push_back(egcpool_stash(&pool_, mb, r));
|
||||
// POOL_MINIMUM_ALLOC is the minimum size of an egcpool once it goes active.
|
||||
// add EGCs to it past this boundary, and verify that they're all still
|
||||
// accurate.
|
||||
SUBCASE("ForceReallocationWithRemovals") {
|
||||
std::vector<int> candidates;
|
||||
char* curpool = nullptr;
|
||||
for(auto i = 0u ; i < 1u << 20u ; ++i){
|
||||
char mb[MB_CUR_MAX + 1];
|
||||
wchar_t wcs = (i % 0x1000) + 0x80;
|
||||
auto r = wctomb(mb, wcs);
|
||||
if(r < 0){
|
||||
candidates.push_back(-1);
|
||||
continue;
|
||||
}
|
||||
REQUIRE(sizeof(mb) >= r);
|
||||
mb[r] = '\0';
|
||||
candidates.push_back(egcpool_stash(&pool_, mb, r));
|
||||
|
||||
ASSERT_GT(1u << 24u, candidates[i]);
|
||||
if(pool_.pool != curpool){
|
||||
// cut through and release a bunch of them
|
||||
if(curpool){
|
||||
for(auto j = 0u ; j < i ; j += 13){
|
||||
if(candidates[j] >= 0){
|
||||
egcpool_release(&pool_, candidates[j]);
|
||||
candidates[j] = -1;
|
||||
REQUIRE((1u << 24u) > candidates[i]);
|
||||
if(pool_.pool != curpool){
|
||||
// cut through and release a bunch of them
|
||||
if(curpool){
|
||||
for(auto j = 0u ; j < i ; j += 13){
|
||||
if(candidates[j] >= 0){
|
||||
egcpool_release(&pool_, candidates[j]);
|
||||
candidates[j] = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
curpool = pool_.pool;
|
||||
}
|
||||
curpool = pool_.pool;
|
||||
}
|
||||
int no = 0;
|
||||
for(auto i = 0u ; i < candidates.size() ; ++i){
|
||||
if(candidates[i] == -1){
|
||||
++no;
|
||||
continue;
|
||||
}
|
||||
auto stored = pool_.pool + candidates[i];
|
||||
char mb[MB_CUR_MAX + 1];
|
||||
wchar_t wcs = (i % 0x1000) + 0x80;
|
||||
auto r = wctomb(mb, wcs);
|
||||
if(r < 0){
|
||||
REQUIRE(-1 == candidates[i]);
|
||||
continue;
|
||||
}
|
||||
REQUIRE(0 < r);
|
||||
mb[r] = '\0';
|
||||
CHECK(!strcmp(mb, stored));
|
||||
}
|
||||
CHECK(candidates.size() / 13 > no);
|
||||
}
|
||||
int no = 0;
|
||||
for(auto i = 0u ; i < candidates.size() ; ++i){
|
||||
if(candidates[i] == -1){
|
||||
++no;
|
||||
continue;
|
||||
}
|
||||
auto stored = pool_.pool + candidates[i];
|
||||
char mb[MB_CUR_MAX + 1];
|
||||
wchar_t wcs = (i % 0x1000) + 0x80;
|
||||
auto r = wctomb(mb, wcs);
|
||||
if(r < 0){
|
||||
ASSERT_EQ(-1, candidates[i]);
|
||||
continue;
|
||||
}
|
||||
ASSERT_LT(0, r);
|
||||
mb[r] = '\0';
|
||||
EXPECT_STREQ(mb, stored);
|
||||
}
|
||||
ASSERT_GT(candidates.size() / 13, no);
|
||||
|
||||
// common cleanup
|
||||
egcpool_dump(&pool_);
|
||||
|
||||
}
|
||||
|
@ -2,332 +2,323 @@
|
||||
#include <cfenv>
|
||||
#include <iostream>
|
||||
|
||||
class EnmetricTest : public :: testing::Test {
|
||||
protected:
|
||||
void SetUp() override {
|
||||
setlocale(LC_ALL, "");
|
||||
decisep_ = localeconv()->decimal_point;
|
||||
ASSERT_NE(nullptr, decisep_);
|
||||
ASSERT_EQ(1, strlen(decisep_));
|
||||
}
|
||||
|
||||
void TearDown() override {
|
||||
}
|
||||
|
||||
const char* decisep_{};
|
||||
|
||||
char* impericize_enmetric(uintmax_t val, unsigned decimal, char* buf,
|
||||
int omitdec, unsigned mult, int uprefix);
|
||||
};
|
||||
|
||||
// run enmetric, and then change any localized decimal separator into our
|
||||
// proud imperial yankee capitalist democratic one dot under god period.
|
||||
// manifest destiny, bitchhhhhhhezzzz!
|
||||
char* EnmetricTest::impericize_enmetric(uintmax_t val, unsigned decimal,
|
||||
char* buf, int omitdec, unsigned mult,
|
||||
int uprefix) {
|
||||
enmetric(val, decimal, buf, omitdec, mult, uprefix);
|
||||
char* impericize_enmetric(uintmax_t val, unsigned decimal, char* buf,
|
||||
int omitdec, unsigned mult, int uprefix) {
|
||||
const char* decisep = localeconv()->decimal_point;
|
||||
REQUIRE(decisep);
|
||||
REQUIRE(1 == strlen(decisep));
|
||||
REQUIRE(enmetric(val, decimal, buf, omitdec, mult, uprefix));
|
||||
char* commie = buf;
|
||||
while( (commie = strstr(commie, decisep_)) ){
|
||||
while( (commie = strstr(commie, decisep)) ){
|
||||
*commie = '.'; // https://dank.qemfd.net/images/16whcc.jpg
|
||||
++commie;
|
||||
}
|
||||
return buf;
|
||||
}
|
||||
|
||||
TEST_F(EnmetricTest, CornerInts) {
|
||||
char buf[PREFIXSTRLEN + 1];
|
||||
impericize_enmetric(0, 1, buf, 0, 1000, '\0');
|
||||
EXPECT_STREQ("0.00", buf);
|
||||
impericize_enmetric(0, 1, buf, 0, 1024, 'i');
|
||||
EXPECT_STREQ("0.00", buf); // no suffix on < mult
|
||||
impericize_enmetric(1, 1, buf, 0, 1000, '\0');
|
||||
EXPECT_STREQ("1.00", buf);
|
||||
impericize_enmetric(1, 1, buf, 0, 1024, 'i');
|
||||
EXPECT_STREQ("1.00", buf);
|
||||
impericize_enmetric(0, 1, buf, 1, 1000, '\0');
|
||||
EXPECT_STREQ("0", buf);
|
||||
impericize_enmetric(0, 1, buf, 1, 1024, 'i');
|
||||
EXPECT_STREQ("0", buf); // no suffix on < mult
|
||||
impericize_enmetric(1, 1, buf, 1, 1000, '\0');
|
||||
EXPECT_STREQ("1", buf);
|
||||
impericize_enmetric(1, 1, buf, 1, 1024, 'i');
|
||||
EXPECT_STREQ("1", buf);
|
||||
impericize_enmetric(999, 1, buf, 1, 1000, '\0');
|
||||
EXPECT_STREQ("999", buf);
|
||||
impericize_enmetric(1000, 1, buf, 1, 1000, '\0');
|
||||
EXPECT_STREQ("1K", buf);
|
||||
impericize_enmetric(1000, 1, buf, 1, 1000, 'i');
|
||||
EXPECT_STREQ("1Ki", buf);
|
||||
impericize_enmetric(1000, 1, buf, 1, 1024, 'i');
|
||||
EXPECT_STREQ("1000", buf); // FIXME should be 0.977Ki
|
||||
impericize_enmetric(1023, 1, buf, 1, 1000, '\0');
|
||||
EXPECT_STREQ("1.02K", buf);
|
||||
impericize_enmetric(1023, 1, buf, 1, 1024, 'i');
|
||||
EXPECT_STREQ("1023", buf);
|
||||
impericize_enmetric(1024, 1, buf, 1, 1000, '\0');
|
||||
EXPECT_STREQ("1.02K", buf);
|
||||
impericize_enmetric(1024, 1, buf, 1, 1024, 'i');
|
||||
EXPECT_STREQ("1Ki", buf);
|
||||
impericize_enmetric(1025, 1, buf, 1, 1000, '\0');
|
||||
EXPECT_STREQ("1.02K", buf);
|
||||
impericize_enmetric(1025, 1, buf, 0, 1024, 'i');
|
||||
EXPECT_STREQ("1.00Ki", buf);
|
||||
impericize_enmetric(1025, 1, buf, 1, 1024, 'i');
|
||||
EXPECT_STREQ("1.00Ki", buf);
|
||||
impericize_enmetric(4096, 1, buf, 1, 1000, '\0');
|
||||
EXPECT_STREQ("4.09K", buf);
|
||||
impericize_enmetric(4096, 1, buf, 1, 1024, 'i');
|
||||
EXPECT_STREQ("4Ki", buf);
|
||||
}
|
||||
TEST_CASE("Enmetric") {
|
||||
const char* decisep = localeconv()->decimal_point;
|
||||
REQUIRE(decisep);
|
||||
REQUIRE(1 == strlen(decisep));
|
||||
|
||||
TEST_F(EnmetricTest, Maxints) {
|
||||
char buf[PREFIXSTRLEN + 1];
|
||||
// FIXME these will change based on the size of intmax_t and uintmax_t
|
||||
impericize_enmetric(INTMAX_MAX - 1, 1, buf, 0, 1000, '\0');
|
||||
EXPECT_STREQ("9.22E", buf);
|
||||
impericize_enmetric(INTMAX_MAX, 1, buf, 0, 1000, '\0');
|
||||
EXPECT_STREQ("9.22E", buf);
|
||||
impericize_enmetric(UINTMAX_MAX - 1, 1, buf, 0, 1000, '\0');
|
||||
EXPECT_STREQ("18.44E", buf);
|
||||
impericize_enmetric(UINTMAX_MAX, 1, buf, 0, 1000, '\0');
|
||||
EXPECT_STREQ("18.44E", buf);
|
||||
}
|
||||
SUBCASE("CornerInts") {
|
||||
char buf[PREFIXSTRLEN + 1];
|
||||
impericize_enmetric(0, 1, buf, 0, 1000, '\0');
|
||||
CHECK(!strcmp("0.00", buf));
|
||||
impericize_enmetric(0, 1, buf, 0, 1024, 'i');
|
||||
CHECK(!strcmp("0.00", buf)); // no suffix on < mult
|
||||
impericize_enmetric(1, 1, buf, 0, 1000, '\0');
|
||||
CHECK(!strcmp("1.00", buf));
|
||||
impericize_enmetric(1, 1, buf, 0, 1024, 'i');
|
||||
CHECK(!strcmp("1.00", buf));
|
||||
impericize_enmetric(0, 1, buf, 1, 1000, '\0');
|
||||
CHECK(!strcmp("0", buf));
|
||||
impericize_enmetric(0, 1, buf, 1, 1024, 'i');
|
||||
CHECK(!strcmp("0", buf)); // no suffix on < mult
|
||||
impericize_enmetric(1, 1, buf, 1, 1000, '\0');
|
||||
CHECK(!strcmp("1", buf));
|
||||
impericize_enmetric(1, 1, buf, 1, 1024, 'i');
|
||||
CHECK(!strcmp("1", buf));
|
||||
impericize_enmetric(999, 1, buf, 1, 1000, '\0');
|
||||
CHECK(!strcmp("999", buf));
|
||||
impericize_enmetric(1000, 1, buf, 1, 1000, '\0');
|
||||
CHECK(!strcmp("1K", buf));
|
||||
impericize_enmetric(1000, 1, buf, 1, 1000, 'i');
|
||||
CHECK(!strcmp("1Ki", buf));
|
||||
impericize_enmetric(1000, 1, buf, 1, 1024, 'i');
|
||||
CHECK(!strcmp("1000", buf)); // FIXME should be 0.977Ki
|
||||
impericize_enmetric(1023, 1, buf, 1, 1000, '\0');
|
||||
CHECK(!strcmp("1.02K", buf));
|
||||
impericize_enmetric(1023, 1, buf, 1, 1024, 'i');
|
||||
CHECK(!strcmp("1023", buf));
|
||||
impericize_enmetric(1024, 1, buf, 1, 1000, '\0');
|
||||
CHECK(!strcmp("1.02K", buf));
|
||||
impericize_enmetric(1024, 1, buf, 1, 1024, 'i');
|
||||
CHECK(!strcmp("1Ki", buf));
|
||||
impericize_enmetric(1025, 1, buf, 1, 1000, '\0');
|
||||
CHECK(!strcmp("1.02K", buf));
|
||||
impericize_enmetric(1025, 1, buf, 0, 1024, 'i');
|
||||
CHECK(!strcmp("1.00Ki", buf));
|
||||
impericize_enmetric(1025, 1, buf, 1, 1024, 'i');
|
||||
CHECK(!strcmp("1.00Ki", buf));
|
||||
impericize_enmetric(4096, 1, buf, 1, 1000, '\0');
|
||||
CHECK(!strcmp("4.09K", buf));
|
||||
impericize_enmetric(4096, 1, buf, 1, 1024, 'i');
|
||||
CHECK(!strcmp("4Ki", buf));
|
||||
}
|
||||
|
||||
TEST_F(EnmetricTest, Maxints1024) {
|
||||
ASSERT_EQ(0, fesetround(FE_TOWARDZERO));
|
||||
char buf[PREFIXSTRLEN + 1], gold[PREFIXSTRLEN + 1];
|
||||
// FIXME these will change based on the size of intmax_t and uintmax_t
|
||||
enmetric(INTMAX_MAX - 1, 1, buf, 0, 1024, 'i');
|
||||
sprintf(gold, "%.2fEi", ((double)(INTMAX_MAX - (1ull << 53))) / (1ull << 60));
|
||||
EXPECT_STREQ(gold, buf);
|
||||
enmetric(INTMAX_MAX + 1ull, 1, buf, 0, 1024, 'i');
|
||||
sprintf(gold, "%.2fEi", ((double)(INTMAX_MAX + 1ull)) / (1ull << 60));
|
||||
EXPECT_STREQ(gold, buf);
|
||||
impericize_enmetric(UINTMAX_MAX - 1, 1, buf, 0, 1024, 'i');
|
||||
EXPECT_STREQ("15.99Ei", buf);
|
||||
impericize_enmetric(UINTMAX_MAX, 1, buf, 0, 1024, 'i');
|
||||
EXPECT_STREQ("15.99Ei", buf);
|
||||
enmetric(UINTMAX_MAX - (1ull << 53), 1, buf, 0, 1024, 'i');
|
||||
sprintf(gold, "%.2fEi", ((double)UINTMAX_MAX - (1ull << 53)) / (1ull << 60));
|
||||
EXPECT_STREQ(gold, buf);
|
||||
}
|
||||
SUBCASE("Maxints") {
|
||||
char buf[PREFIXSTRLEN + 1];
|
||||
// FIXME these will change based on the size of intmax_t and uintmax_t
|
||||
impericize_enmetric(INTMAX_MAX - 1, 1, buf, 0, 1000, '\0');
|
||||
CHECK(!strcmp("9.22E", buf));
|
||||
impericize_enmetric(INTMAX_MAX, 1, buf, 0, 1000, '\0');
|
||||
CHECK(!strcmp("9.22E", buf));
|
||||
impericize_enmetric(UINTMAX_MAX - 1, 1, buf, 0, 1000, '\0');
|
||||
CHECK(!strcmp("18.44E", buf));
|
||||
impericize_enmetric(UINTMAX_MAX, 1, buf, 0, 1000, '\0');
|
||||
CHECK(!strcmp("18.44E", buf));
|
||||
}
|
||||
|
||||
const char suffixes[] = "\0KMGTPE";
|
||||
SUBCASE("Maxints1024") {
|
||||
REQUIRE(0 == fesetround(FE_TOWARDZERO));
|
||||
char buf[PREFIXSTRLEN + 1], gold[PREFIXSTRLEN + 1];
|
||||
// FIXME these will change based on the size of intmax_t and uintmax_t
|
||||
enmetric(INTMAX_MAX - 1, 1, buf, 0, 1024, 'i');
|
||||
sprintf(gold, "%.2fEi", ((double)(INTMAX_MAX - (1ull << 53))) / (1ull << 60));
|
||||
CHECK(!strcmp(gold, buf));
|
||||
enmetric(INTMAX_MAX + 1ull, 1, buf, 0, 1024, 'i');
|
||||
sprintf(gold, "%.2fEi", ((double)(INTMAX_MAX + 1ull)) / (1ull << 60));
|
||||
CHECK(!strcmp(gold, buf));
|
||||
impericize_enmetric(UINTMAX_MAX - 1, 1, buf, 0, 1024, 'i');
|
||||
CHECK(!strcmp("15.99Ei", buf));
|
||||
impericize_enmetric(UINTMAX_MAX, 1, buf, 0, 1024, 'i');
|
||||
CHECK(!strcmp("15.99Ei", buf));
|
||||
enmetric(UINTMAX_MAX - (1ull << 53), 1, buf, 0, 1024, 'i');
|
||||
sprintf(gold, "%.2fEi", ((double)UINTMAX_MAX - (1ull << 53)) / (1ull << 60));
|
||||
CHECK(!strcmp(gold, buf));
|
||||
}
|
||||
|
||||
TEST_F(EnmetricTest, PowersOfTen) {
|
||||
char gold[PREFIXSTRLEN + 1];
|
||||
char buf[PREFIXSTRLEN + 1];
|
||||
uintmax_t goldval = 1;
|
||||
uintmax_t val = 1;
|
||||
size_t i = 0;
|
||||
do{
|
||||
enmetric(val, 1, buf, 0, 1000, '\0');
|
||||
const int sidx = i / 3;
|
||||
snprintf(gold, sizeof(gold), "%ju%s00%c", goldval, decisep_, suffixes[sidx]);
|
||||
EXPECT_STREQ(gold, buf);
|
||||
if(UINTMAX_MAX / val < 10){
|
||||
break;
|
||||
}
|
||||
val *= 10;
|
||||
if((goldval *= 10) == 1000){
|
||||
goldval = 1;
|
||||
}
|
||||
}while(++i < sizeof(suffixes) * 3);
|
||||
// If we ran through all our suffixes, that's a problem
|
||||
EXPECT_GT(sizeof(suffixes) * 3, i);
|
||||
}
|
||||
const char suffixes[] = "\0KMGTPE";
|
||||
|
||||
TEST_F(EnmetricTest, PowersOfTenNoDec) {
|
||||
char gold[PREFIXSTRLEN + 1];
|
||||
char buf[PREFIXSTRLEN + 1];
|
||||
uintmax_t goldval = 1;
|
||||
uintmax_t val = 1;
|
||||
size_t i = 0;
|
||||
do{
|
||||
enmetric(val, 1, buf, 1, 1000, '\0');
|
||||
const int sidx = i / 3;
|
||||
snprintf(gold, sizeof(gold), "%ju%c", goldval, suffixes[sidx]);
|
||||
EXPECT_STREQ(gold, buf);
|
||||
if(UINTMAX_MAX / val < 10){
|
||||
break;
|
||||
}
|
||||
val *= 10;
|
||||
if((goldval *= 10) == 1000){
|
||||
goldval = 1;
|
||||
}
|
||||
}while(++i < sizeof(suffixes) * 3);
|
||||
// If we ran through all our suffixes, that's a problem
|
||||
EXPECT_GT(sizeof(suffixes) * 3, i);
|
||||
}
|
||||
SUBCASE("PowersOfTen") {
|
||||
char gold[PREFIXSTRLEN + 1];
|
||||
char buf[PREFIXSTRLEN + 1];
|
||||
uintmax_t goldval = 1;
|
||||
uintmax_t val = 1;
|
||||
size_t i = 0;
|
||||
do{
|
||||
enmetric(val, 1, buf, 0, 1000, '\0');
|
||||
const int sidx = i / 3;
|
||||
snprintf(gold, sizeof(gold), "%ju%s00%c", goldval, decisep, suffixes[sidx]);
|
||||
CHECK(!strcmp(gold, buf));
|
||||
if(UINTMAX_MAX / val < 10){
|
||||
break;
|
||||
}
|
||||
val *= 10;
|
||||
if((goldval *= 10) == 1000){
|
||||
goldval = 1;
|
||||
}
|
||||
}while(++i < sizeof(suffixes) * 3);
|
||||
// If we ran through all our suffixes, that's a problem
|
||||
CHECK(sizeof(suffixes) * 3 > i);
|
||||
}
|
||||
|
||||
TEST_F(EnmetricTest, PowersOfTwo) {
|
||||
char gold[BPREFIXSTRLEN + 1];
|
||||
char buf[BPREFIXSTRLEN + 1];
|
||||
uintmax_t goldval = 1;
|
||||
uintmax_t val = 1;
|
||||
size_t i = 0;
|
||||
do{
|
||||
enmetric(val, 1, buf, 0, 1024, 'i');
|
||||
const int sidx = i / 10;
|
||||
snprintf(gold, sizeof(gold), "%ju%s00%ci", goldval, decisep_, suffixes[sidx]);
|
||||
EXPECT_STREQ(gold, buf);
|
||||
if(UINTMAX_MAX / val < 10){
|
||||
break;
|
||||
}
|
||||
val *= 2;
|
||||
if((goldval *= 2) == 1024){
|
||||
goldval = 1;
|
||||
}
|
||||
}while(++i < sizeof(suffixes) * 10);
|
||||
// If we ran through all our suffixes, that's a problem
|
||||
EXPECT_GT(sizeof(suffixes) * 10, i);
|
||||
}
|
||||
SUBCASE("PowersOfTenNoDec") {
|
||||
char gold[PREFIXSTRLEN + 1];
|
||||
char buf[PREFIXSTRLEN + 1];
|
||||
uintmax_t goldval = 1;
|
||||
uintmax_t val = 1;
|
||||
size_t i = 0;
|
||||
do{
|
||||
enmetric(val, 1, buf, 1, 1000, '\0');
|
||||
const int sidx = i / 3;
|
||||
snprintf(gold, sizeof(gold), "%ju%c", goldval, suffixes[sidx]);
|
||||
CHECK(!strcmp(gold, buf));
|
||||
if(UINTMAX_MAX / val < 10){
|
||||
break;
|
||||
}
|
||||
val *= 10;
|
||||
if((goldval *= 10) == 1000){
|
||||
goldval = 1;
|
||||
}
|
||||
}while(++i < sizeof(suffixes) * 3);
|
||||
// If we ran through all our suffixes, that's a problem
|
||||
CHECK(sizeof(suffixes) * 3 > i);
|
||||
}
|
||||
|
||||
TEST_F(EnmetricTest, PowersOfTwoNoDec) {
|
||||
char gold[BPREFIXSTRLEN + 1];
|
||||
char buf[BPREFIXSTRLEN + 1];
|
||||
uintmax_t goldval = 1;
|
||||
uintmax_t val = 1;
|
||||
size_t i = 0;
|
||||
do{
|
||||
enmetric(val, 1, buf, 1, 1024, 'i');
|
||||
const int sidx = i / 10;
|
||||
snprintf(gold, sizeof(gold), "%ju%ci", goldval, suffixes[sidx]);
|
||||
EXPECT_STREQ(gold, buf);
|
||||
if(UINTMAX_MAX / val < 10){
|
||||
break;
|
||||
}
|
||||
val *= 2;
|
||||
if((goldval *= 2) == 1024){
|
||||
goldval = 1;
|
||||
}
|
||||
}while(++i < sizeof(suffixes) * 10);
|
||||
// If we ran through all our suffixes, that's a problem
|
||||
EXPECT_GT(sizeof(suffixes) * 10, i);
|
||||
}
|
||||
SUBCASE("PowersOfTwo") {
|
||||
char gold[BPREFIXSTRLEN + 1];
|
||||
char buf[BPREFIXSTRLEN + 1];
|
||||
uintmax_t goldval = 1;
|
||||
uintmax_t val = 1;
|
||||
size_t i = 0;
|
||||
do{
|
||||
enmetric(val, 1, buf, 0, 1024, 'i');
|
||||
const int sidx = i / 10;
|
||||
snprintf(gold, sizeof(gold), "%ju%s00%ci", goldval, decisep, suffixes[sidx]);
|
||||
CHECK(!strcmp(gold, buf));
|
||||
if(UINTMAX_MAX / val < 10){
|
||||
break;
|
||||
}
|
||||
val *= 2;
|
||||
if((goldval *= 2) == 1024){
|
||||
goldval = 1;
|
||||
}
|
||||
}while(++i < sizeof(suffixes) * 10);
|
||||
// If we ran through all our suffixes, that's a problem
|
||||
CHECK(sizeof(suffixes) * 10 > i);
|
||||
}
|
||||
|
||||
TEST_F(EnmetricTest, PowersOfTwoAsTens) {
|
||||
char gold[PREFIXSTRLEN + 1];
|
||||
char buf[PREFIXSTRLEN + 1];
|
||||
uintmax_t vfloor = 1;
|
||||
uintmax_t val = 1;
|
||||
size_t i = 0;
|
||||
ASSERT_EQ(0, fesetround(FE_TOWARDZERO));
|
||||
do{
|
||||
enmetric(val, 1, buf, 0, 1000, '\0');
|
||||
const int sidx = i / 10;
|
||||
snprintf(gold, sizeof(gold), "%.2f%c",
|
||||
((double)val) / vfloor, suffixes[sidx]);
|
||||
EXPECT_STREQ(gold, buf);
|
||||
if(UINTMAX_MAX / val < 10){
|
||||
break;
|
||||
}
|
||||
val *= 2;
|
||||
if(i % 10 == 9){
|
||||
vfloor *= 1000;
|
||||
}
|
||||
}while(++i < sizeof(suffixes) * 10);
|
||||
// If we ran through all our suffixes, that's a problem
|
||||
EXPECT_GT(sizeof(suffixes) * 10, i);
|
||||
}
|
||||
SUBCASE("PowersOfTwoNoDec") {
|
||||
char gold[BPREFIXSTRLEN + 1];
|
||||
char buf[BPREFIXSTRLEN + 1];
|
||||
uintmax_t goldval = 1;
|
||||
uintmax_t val = 1;
|
||||
size_t i = 0;
|
||||
do{
|
||||
enmetric(val, 1, buf, 1, 1024, 'i');
|
||||
const int sidx = i / 10;
|
||||
snprintf(gold, sizeof(gold), "%ju%ci", goldval, suffixes[sidx]);
|
||||
CHECK(!strcmp(gold, buf));
|
||||
if(UINTMAX_MAX / val < 10){
|
||||
break;
|
||||
}
|
||||
val *= 2;
|
||||
if((goldval *= 2) == 1024){
|
||||
goldval = 1;
|
||||
}
|
||||
}while(++i < sizeof(suffixes) * 10);
|
||||
// If we ran through all our suffixes, that's a problem
|
||||
CHECK(sizeof(suffixes) * 10 > i);
|
||||
}
|
||||
|
||||
TEST_F(EnmetricTest, PowersOfTenAsTwos) {
|
||||
char gold[BPREFIXSTRLEN + 1];
|
||||
char buf[BPREFIXSTRLEN + 1];
|
||||
uintmax_t vfloor = 1;
|
||||
uintmax_t val = 1;
|
||||
size_t i = 0;
|
||||
ASSERT_EQ(0, fesetround(FE_TOWARDZERO));
|
||||
do{
|
||||
enmetric(val, 1, buf, 0, 1024, 'i');
|
||||
const int sidx = i ? (i - 1) / 3 : 0;
|
||||
snprintf(gold, sizeof(gold), "%.2f%ci",
|
||||
((double)val) / vfloor, suffixes[sidx]);
|
||||
EXPECT_STREQ(gold, buf);
|
||||
if(UINTMAX_MAX / val < 10){
|
||||
break;
|
||||
}
|
||||
val *= 10;
|
||||
if(i && i % 3 == 0){
|
||||
vfloor *= 1024;
|
||||
}
|
||||
}while(++i < sizeof(suffixes) * 10);
|
||||
// If we ran through all our suffixes, that's a problem
|
||||
EXPECT_GT(sizeof(suffixes) * 10, i);
|
||||
}
|
||||
SUBCASE("PowersOfTwoAsTens") {
|
||||
char gold[PREFIXSTRLEN + 1];
|
||||
char buf[PREFIXSTRLEN + 1];
|
||||
uintmax_t vfloor = 1;
|
||||
uintmax_t val = 1;
|
||||
size_t i = 0;
|
||||
REQUIRE(0 == fesetround(FE_TOWARDZERO));
|
||||
do{
|
||||
enmetric(val, 1, buf, 0, 1000, '\0');
|
||||
const int sidx = i / 10;
|
||||
snprintf(gold, sizeof(gold), "%.2f%c",
|
||||
((double)val) / vfloor, suffixes[sidx]);
|
||||
CHECK(!strcmp(gold, buf));
|
||||
if(UINTMAX_MAX / val < 10){
|
||||
break;
|
||||
}
|
||||
val *= 2;
|
||||
if(i % 10 == 9){
|
||||
vfloor *= 1000;
|
||||
}
|
||||
}while(++i < sizeof(suffixes) * 10);
|
||||
// If we ran through all our suffixes, that's a problem
|
||||
CHECK(sizeof(suffixes) * 10 > i);
|
||||
}
|
||||
|
||||
TEST_F(EnmetricTest, PowersOfTenMinusOne) {
|
||||
char gold[PREFIXSTRLEN + 1];
|
||||
char buf[PREFIXSTRLEN + 1];
|
||||
uintmax_t vfloor = 1;
|
||||
uintmax_t val = 1;
|
||||
size_t i = 0;
|
||||
ASSERT_EQ(0, fesetround(FE_TOWARDZERO));
|
||||
do{
|
||||
enmetric(val - 1, 1, buf, 0, 1000, '\0');
|
||||
const int sidx = i ? (i - 1) / 3 : 0;
|
||||
snprintf(gold, sizeof(gold), "%.2f%c",
|
||||
((double)(val - 1)) / vfloor, suffixes[sidx]);
|
||||
EXPECT_STREQ(gold, buf);
|
||||
if(UINTMAX_MAX / val < 10){
|
||||
break;
|
||||
}
|
||||
val *= 10;
|
||||
if(i && i % 3 == 0){
|
||||
vfloor *= 1000;
|
||||
}
|
||||
}while(++i < sizeof(suffixes) * 3);
|
||||
// If we ran through all our suffixes, that's a problem
|
||||
EXPECT_GT(sizeof(suffixes) * 3, i);
|
||||
}
|
||||
SUBCASE("PowersOfTenAsTwos") {
|
||||
char gold[BPREFIXSTRLEN + 1];
|
||||
char buf[BPREFIXSTRLEN + 1];
|
||||
uintmax_t vfloor = 1;
|
||||
uintmax_t val = 1;
|
||||
size_t i = 0;
|
||||
REQUIRE(0 == fesetround(FE_TOWARDZERO));
|
||||
do{
|
||||
enmetric(val, 1, buf, 0, 1024, 'i');
|
||||
const int sidx = i ? (i - 1) / 3 : 0;
|
||||
snprintf(gold, sizeof(gold), "%.2f%ci",
|
||||
((double)val) / vfloor, suffixes[sidx]);
|
||||
CHECK(!strcmp(gold, buf));
|
||||
if(UINTMAX_MAX / val < 10){
|
||||
break;
|
||||
}
|
||||
val *= 10;
|
||||
if(i && i % 3 == 0){
|
||||
vfloor *= 1024;
|
||||
}
|
||||
}while(++i < sizeof(suffixes) * 10);
|
||||
// If we ran through all our suffixes, that's a problem
|
||||
CHECK(sizeof(suffixes) * 10 > i);
|
||||
}
|
||||
|
||||
TEST_F(EnmetricTest, PowersOfTenPlusOne) {
|
||||
char gold[PREFIXSTRLEN + 1];
|
||||
char buf[PREFIXSTRLEN + 1];
|
||||
uintmax_t vfloor = 1;
|
||||
uintmax_t val = 1;
|
||||
size_t i = 0;
|
||||
ASSERT_EQ(0, fesetround(FE_TOWARDZERO));
|
||||
do{
|
||||
enmetric(val + 1, 1, buf, 0, 1000, '\0');
|
||||
const int sidx = i / 3;
|
||||
snprintf(gold, sizeof(gold), "%.2f%c",
|
||||
((double)(val + 1)) / vfloor, suffixes[sidx]);
|
||||
EXPECT_STREQ(gold, buf);
|
||||
if(UINTMAX_MAX / val < 10){
|
||||
break;
|
||||
}
|
||||
val *= 10;
|
||||
if(i % 3 == 2){
|
||||
vfloor *= 1000;
|
||||
}
|
||||
}while(++i < sizeof(suffixes) * 3);
|
||||
// If we ran through all our suffixes, that's a problem
|
||||
EXPECT_GT(sizeof(suffixes) * 3, i);
|
||||
}
|
||||
SUBCASE("PowersOfTenMinusOne") {
|
||||
char gold[PREFIXSTRLEN + 1];
|
||||
char buf[PREFIXSTRLEN + 1];
|
||||
uintmax_t vfloor = 1;
|
||||
uintmax_t val = 1;
|
||||
size_t i = 0;
|
||||
REQUIRE(0 == fesetround(FE_TOWARDZERO));
|
||||
do{
|
||||
enmetric(val - 1, 1, buf, 0, 1000, '\0');
|
||||
const int sidx = i ? (i - 1) / 3 : 0;
|
||||
snprintf(gold, sizeof(gold), "%.2f%c",
|
||||
((double)(val - 1)) / vfloor, suffixes[sidx]);
|
||||
CHECK(!strcmp(gold, buf));
|
||||
if(UINTMAX_MAX / val < 10){
|
||||
break;
|
||||
}
|
||||
val *= 10;
|
||||
if(i && i % 3 == 0){
|
||||
vfloor *= 1000;
|
||||
}
|
||||
}while(++i < sizeof(suffixes) * 3);
|
||||
// If we ran through all our suffixes, that's a problem
|
||||
CHECK(sizeof(suffixes) * 3 > i);
|
||||
}
|
||||
|
||||
SUBCASE("PowersOfTenPlusOne") {
|
||||
char gold[PREFIXSTRLEN + 1];
|
||||
char buf[PREFIXSTRLEN + 1];
|
||||
uintmax_t vfloor = 1;
|
||||
uintmax_t val = 1;
|
||||
size_t i = 0;
|
||||
REQUIRE(0 == fesetround(FE_TOWARDZERO));
|
||||
do{
|
||||
enmetric(val + 1, 1, buf, 0, 1000, '\0');
|
||||
const int sidx = i / 3;
|
||||
snprintf(gold, sizeof(gold), "%.2f%c",
|
||||
((double)(val + 1)) / vfloor, suffixes[sidx]);
|
||||
CHECK(!strcmp(gold, buf));
|
||||
if(UINTMAX_MAX / val < 10){
|
||||
break;
|
||||
}
|
||||
val *= 10;
|
||||
if(i % 3 == 2){
|
||||
vfloor *= 1000;
|
||||
}
|
||||
}while(++i < sizeof(suffixes) * 3);
|
||||
// If we ran through all our suffixes, that's a problem
|
||||
CHECK(sizeof(suffixes) * 3 > i);
|
||||
}
|
||||
|
||||
SUBCASE("PowersOfTenMinusOneAsTwos") {
|
||||
char gold[BPREFIXSTRLEN + 1];
|
||||
char buf[BPREFIXSTRLEN + 1];
|
||||
uintmax_t vfloor = 1;
|
||||
uintmax_t val = 1;
|
||||
size_t i = 0;
|
||||
REQUIRE(0 == fesetround(FE_TOWARDZERO));
|
||||
do{
|
||||
enmetric(val - 1, 1, buf, 0, 1024, 'i');
|
||||
const int sidx = i ? (i - 1) / 3 : 0;
|
||||
snprintf(gold, sizeof(gold), "%.2f%ci",
|
||||
((double)(val - 1)) / vfloor, suffixes[sidx]);
|
||||
CHECK(!strcmp(gold, buf));
|
||||
if(UINTMAX_MAX / val < 10){
|
||||
break;
|
||||
}
|
||||
val *= 10;
|
||||
if(i && i % 3 == 0){
|
||||
vfloor *= 1024;
|
||||
}
|
||||
}while(++i < sizeof(suffixes) * 10);
|
||||
// If we ran through all our suffixes, that's a problem
|
||||
CHECK(sizeof(suffixes) * 10 > i);
|
||||
}
|
||||
|
||||
TEST_F(EnmetricTest, PowersOfTenMinusOneAsTwos) {
|
||||
char gold[BPREFIXSTRLEN + 1];
|
||||
char buf[BPREFIXSTRLEN + 1];
|
||||
uintmax_t vfloor = 1;
|
||||
uintmax_t val = 1;
|
||||
size_t i = 0;
|
||||
ASSERT_EQ(0, fesetround(FE_TOWARDZERO));
|
||||
do{
|
||||
enmetric(val - 1, 1, buf, 0, 1024, 'i');
|
||||
const int sidx = i ? (i - 1) / 3 : 0;
|
||||
snprintf(gold, sizeof(gold), "%.2f%ci",
|
||||
((double)(val - 1)) / vfloor, suffixes[sidx]);
|
||||
EXPECT_STREQ(gold, buf);
|
||||
if(UINTMAX_MAX / val < 10){
|
||||
break;
|
||||
}
|
||||
val *= 10;
|
||||
if(i && i % 3 == 0){
|
||||
vfloor *= 1024;
|
||||
}
|
||||
}while(++i < sizeof(suffixes) * 10);
|
||||
// If we ran through all our suffixes, that's a problem
|
||||
EXPECT_GT(sizeof(suffixes) * 10, i);
|
||||
}
|
||||
|
101
tests/fade.cpp
101
tests/fade.cpp
@ -2,69 +2,56 @@
|
||||
#include <cstdlib>
|
||||
#include <iostream>
|
||||
|
||||
class FadeTest : public :: testing::Test {
|
||||
protected:
|
||||
void SetUp() override {
|
||||
setlocale(LC_ALL, "");
|
||||
if(getenv("TERM") == nullptr){
|
||||
GTEST_SKIP();
|
||||
}
|
||||
notcurses_options nopts{};
|
||||
nopts.inhibit_alternate_screen = true;
|
||||
outfp_ = fopen("/dev/tty", "wb");
|
||||
ASSERT_NE(nullptr, outfp_);
|
||||
nc_ = notcurses_init(&nopts, outfp_);
|
||||
ASSERT_NE(nullptr, nc_);
|
||||
if(!notcurses_canfade(nc_)){
|
||||
GTEST_SKIP();
|
||||
}
|
||||
n_ = notcurses_stdplane(nc_);
|
||||
ASSERT_NE(nullptr, n_);
|
||||
ASSERT_EQ(0, ncplane_cursor_move_yx(n_, 0, 0));
|
||||
int dimy, dimx;
|
||||
ncplane_dim_yx(n_, &dimy, &dimx);
|
||||
cell c = CELL_TRIVIAL_INITIALIZER;
|
||||
c.gcluster = '*';
|
||||
cell_set_fg_rgb(&c, 0xff, 0xff, 0xff);
|
||||
unsigned rgb = 0xffffffu;
|
||||
for(int y = 0 ; y < dimy ; ++y){
|
||||
for(int x = 0 ; x < dimx ; ++x){
|
||||
rgb -= 32;
|
||||
if(rgb < 32){
|
||||
rgb = 0xffffffu;
|
||||
}
|
||||
cell_set_fg_rgb(&c, (rgb >> 16u) & 0xff, (rgb >> 8u) & 0xff, rgb & 0xff);
|
||||
cell_set_bg_rgb(&c, rgb & 0xff, (rgb >> 16u) & 0xff, (rgb >> 8u) & 0xff);
|
||||
EXPECT_LT(0, ncplane_putc(n_, &c));
|
||||
TEST_CASE("Fade") {
|
||||
if(getenv("TERM") == nullptr){
|
||||
return;
|
||||
}
|
||||
FILE* outfp_ = fopen("/dev/tty", "wb");
|
||||
REQUIRE(outfp_);
|
||||
notcurses_options nopts{};
|
||||
nopts.inhibit_alternate_screen = true;
|
||||
struct notcurses* nc_ = notcurses_init(&nopts, outfp_);
|
||||
REQUIRE(nc_);
|
||||
struct ncplane* n_ = notcurses_stdplane(nc_);
|
||||
REQUIRE(n_);
|
||||
if(!notcurses_canfade(nc_)){
|
||||
return;
|
||||
}
|
||||
REQUIRE(0 == ncplane_cursor_move_yx(n_, 0, 0));
|
||||
int dimy, dimx;
|
||||
ncplane_dim_yx(n_, &dimy, &dimx);
|
||||
cell c = CELL_TRIVIAL_INITIALIZER;
|
||||
c.gcluster = '*';
|
||||
cell_set_fg_rgb(&c, 0xff, 0xff, 0xff);
|
||||
unsigned rgb = 0xffffffu;
|
||||
for(int y = 0 ; y < dimy ; ++y){
|
||||
for(int x = 0 ; x < dimx ; ++x){
|
||||
rgb -= 32;
|
||||
if(rgb < 32){
|
||||
rgb = 0xffffffu;
|
||||
}
|
||||
cell_set_fg_rgb(&c, (rgb >> 16u) & 0xff, (rgb >> 8u) & 0xff, rgb & 0xff);
|
||||
cell_set_bg_rgb(&c, rgb & 0xff, (rgb >> 16u) & 0xff, (rgb >> 8u) & 0xff);
|
||||
CHECK(0 < ncplane_putc(n_, &c));
|
||||
}
|
||||
}
|
||||
|
||||
void TearDown() override {
|
||||
if(nc_){
|
||||
EXPECT_EQ(0, notcurses_stop(nc_));
|
||||
}
|
||||
if(outfp_){
|
||||
fclose(outfp_);
|
||||
}
|
||||
SUBCASE("FadeOut") {
|
||||
CHECK(0 == notcurses_render(nc_));
|
||||
struct timespec ts;
|
||||
ts.tv_sec = 1;
|
||||
ts.tv_nsec = 0;
|
||||
REQUIRE(0 == ncplane_fadeout(n_, &ts, nullptr));
|
||||
}
|
||||
|
||||
struct notcurses* nc_{};
|
||||
struct ncplane* n_{};
|
||||
FILE* outfp_{};
|
||||
};
|
||||
SUBCASE("FadeIn") {
|
||||
struct timespec ts;
|
||||
ts.tv_sec = 1;
|
||||
ts.tv_nsec = 0;
|
||||
REQUIRE(0 == ncplane_fadein(n_, &ts, nullptr));
|
||||
}
|
||||
|
||||
TEST_F(FadeTest, FadeOut) {
|
||||
EXPECT_EQ(0, notcurses_render(nc_));
|
||||
struct timespec ts;
|
||||
ts.tv_sec = 1;
|
||||
ts.tv_nsec = 0;
|
||||
ASSERT_EQ(0, ncplane_fadeout(n_, &ts, nullptr));
|
||||
}
|
||||
CHECK(0 == notcurses_stop(nc_));
|
||||
CHECK(0 == fclose(outfp_));
|
||||
|
||||
TEST_F(FadeTest, FadeIn) {
|
||||
struct timespec ts;
|
||||
ts.tv_sec = 1;
|
||||
ts.tv_nsec = 0;
|
||||
ASSERT_EQ(0, ncplane_fadein(n_, &ts, nullptr));
|
||||
}
|
||||
|
@ -1,38 +1,20 @@
|
||||
#include "main.h"
|
||||
|
||||
class InputTest : public :: testing::Test {
|
||||
protected:
|
||||
void SetUp() override {
|
||||
setlocale(LC_ALL, "");
|
||||
if(getenv("TERM") == nullptr){
|
||||
GTEST_SKIP();
|
||||
}
|
||||
notcurses_options nopts{};
|
||||
nopts.inhibit_alternate_screen = true;
|
||||
nopts.suppress_bannner = true;
|
||||
outfp_ = fopen("/dev/tty", "wb");
|
||||
ASSERT_NE(nullptr, outfp_);
|
||||
nc_ = notcurses_init(&nopts, outfp_);
|
||||
ASSERT_NE(nullptr, nc_);
|
||||
TEST_CASE("NotcursesInput") {
|
||||
if(getenv("TERM") == nullptr){
|
||||
return;
|
||||
}
|
||||
notcurses_options nopts{};
|
||||
nopts.inhibit_alternate_screen = true;
|
||||
nopts.suppress_bannner = true;
|
||||
FILE* outfp_ = fopen("/dev/tty", "wb");
|
||||
REQUIRE(outfp_);
|
||||
struct notcurses* nc_ = notcurses_init(&nopts, outfp_);
|
||||
REQUIRE(nc_);
|
||||
|
||||
void TearDown() override {
|
||||
if(nc_){
|
||||
EXPECT_EQ(0, notcurses_stop(nc_));
|
||||
}
|
||||
if(outfp_){
|
||||
fclose(outfp_);
|
||||
}
|
||||
}
|
||||
REQUIRE(0 == notcurses_mouse_enable(nc_));
|
||||
CHECK(0 == notcurses_mouse_disable(nc_));
|
||||
|
||||
struct notcurses* nc_{};
|
||||
FILE* outfp_{};
|
||||
};
|
||||
|
||||
TEST_F(InputTest, TestMouseOn){
|
||||
ASSERT_EQ(0, notcurses_mouse_enable(nc_));
|
||||
}
|
||||
|
||||
TEST_F(InputTest, TestMouseOff){
|
||||
ASSERT_EQ(0, notcurses_mouse_disable(nc_));
|
||||
CHECK(0 == notcurses_stop(nc_));
|
||||
CHECK(0 == fclose(outfp_));
|
||||
}
|
||||
|
@ -4,79 +4,72 @@
|
||||
#include "internal.h"
|
||||
#include "main.h"
|
||||
|
||||
class InternalsTest : public :: testing::Test {
|
||||
protected:
|
||||
void SetUp() override {
|
||||
setlocale(LC_ALL, "");
|
||||
}
|
||||
};
|
||||
|
||||
TEST_F(InternalsTest, RGBtoANSIWhite) {
|
||||
TEST_CASE("RGBtoANSIWhite") {
|
||||
unsigned r, g, b;
|
||||
for(r = 250 ; r < 256 ; ++r){
|
||||
g = b = r;
|
||||
EXPECT_EQ(15, rgb_quantize_256(r, g, b));
|
||||
CHECK(15 == rgb_quantize_256(r, g, b));
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(InternalsTest, RGBtoANSIBlack) {
|
||||
TEST_CASE("RGBtoANSIBlack") {
|
||||
unsigned r, g, b;
|
||||
for(r = 0 ; r < 10 ; ++r){
|
||||
g = b = r;
|
||||
EXPECT_EQ(0, rgb_quantize_256(r, g, b));
|
||||
CHECK(0 == rgb_quantize_256(r, g, b));
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(InternalsTest, RGBtoANSIGrey) {
|
||||
TEST_CASE("RGBtoANSIGrey") {
|
||||
unsigned r, g, b;
|
||||
for(r = 10 ; r < 244 ; ++r){
|
||||
g = b = r;
|
||||
EXPECT_EQ(231 + (r * 5) / 49, rgb_quantize_256(r, g, b));
|
||||
CHECK(231 + (r * 5) / 49 == rgb_quantize_256(r, g, b));
|
||||
}
|
||||
}
|
||||
|
||||
// Pure reds are either 0 (black), or 16 plus 36 * [0..5].
|
||||
TEST_F(InternalsTest, RGBtoANSIRed) {
|
||||
TEST_CASE("RGBtoANSIRed") {
|
||||
unsigned r, g, b;
|
||||
g = b = 0x0;
|
||||
for(r = 0 ; r < 256 ; ++r){
|
||||
int c256 = rgb_quantize_256(r, g, b);
|
||||
if(r < 8){
|
||||
EXPECT_EQ(0, c256);
|
||||
CHECK(0 == c256);
|
||||
}else{
|
||||
EXPECT_LT(15, c256);
|
||||
EXPECT_EQ(16, c256 % 36);
|
||||
CHECK(15 < c256);
|
||||
CHECK(16 == c256 % 36);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Pure greens are either 0 (black), or 16 plus 6 * [0..5].
|
||||
TEST_F(InternalsTest, RGBtoANSIGreen) {
|
||||
TEST_CASE("RGBtoANSIGreen") {
|
||||
unsigned r, g, b;
|
||||
r = b = 0x0;
|
||||
for(g = 0 ; g < 256 ; ++g){
|
||||
int c256 = rgb_quantize_256(r, g, b);
|
||||
EXPECT_GT(48, c256);
|
||||
CHECK(48 > c256);
|
||||
if(g < 8){
|
||||
EXPECT_EQ(0, c256);
|
||||
CHECK(0 == c256);
|
||||
}else{
|
||||
EXPECT_LT(15, c256);
|
||||
EXPECT_EQ(4, c256 % 6);
|
||||
CHECK(15 < c256);
|
||||
CHECK(4 == c256 % 6);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Pure blues are either 0 (black), or one of the first 6 colors [16..22].
|
||||
TEST_F(InternalsTest, RGBtoANSIBlue) {
|
||||
TEST_CASE("RGBtoANSIBlue") {
|
||||
unsigned r, g, b;
|
||||
r = g = 0x0;
|
||||
for(b = 0 ; b < 256 ; ++b){
|
||||
int c256 = rgb_quantize_256(r, g, b);
|
||||
EXPECT_GT(22, c256);
|
||||
CHECK(22 > c256);
|
||||
if(b < 8){
|
||||
EXPECT_EQ(0, c256);
|
||||
CHECK(0 == c256);
|
||||
}else{
|
||||
EXPECT_LT(15, c256);
|
||||
CHECK(15 < c256);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
182
tests/libav.cpp
182
tests/libav.cpp
@ -1,104 +1,92 @@
|
||||
#include <notcurses.h>
|
||||
#include "version.h"
|
||||
#include "main.h"
|
||||
|
||||
class LibavTest : public :: testing::Test {
|
||||
protected:
|
||||
void SetUp() override {
|
||||
setlocale(LC_ALL, "");
|
||||
if(getenv("TERM") == nullptr){
|
||||
GTEST_SKIP();
|
||||
}
|
||||
notcurses_options nopts{};
|
||||
nopts.inhibit_alternate_screen = true;
|
||||
nopts.suppress_bannner = true;
|
||||
outfp_ = fopen("/dev/tty", "wb");
|
||||
ASSERT_NE(nullptr, outfp_);
|
||||
nc_ = notcurses_init(&nopts, outfp_);
|
||||
ASSERT_NE(nullptr, nc_);
|
||||
ncp_ = notcurses_stdplane(nc_);
|
||||
ASSERT_NE(nullptr, ncp_);
|
||||
}
|
||||
|
||||
void TearDown() override {
|
||||
if(nc_){
|
||||
EXPECT_EQ(0, notcurses_stop(nc_));
|
||||
}
|
||||
if(outfp_){
|
||||
fclose(outfp_);
|
||||
}
|
||||
}
|
||||
|
||||
notcurses* nc_{};
|
||||
ncplane* ncp_{};
|
||||
FILE* outfp_{};
|
||||
};
|
||||
|
||||
#ifdef DISABLE_FFMPEG
|
||||
TEST_F(LibavTest, LibavDisabled){
|
||||
ASSERT_FALSE(notcurses_canopen(nc_));
|
||||
}
|
||||
#else
|
||||
#ifndef DISABLE_FFMPEG
|
||||
#include <libavutil/pixdesc.h>
|
||||
#include <libavutil/avconfig.h>
|
||||
#include <libavcodec/avcodec.h> // ffmpeg doesn't reliably "C"-guard itself
|
||||
|
||||
TEST_F(LibavTest, LibavEnabled){
|
||||
ASSERT_TRUE(notcurses_canopen(nc_));
|
||||
}
|
||||
|
||||
TEST_F(LibavTest, LoadImage) {
|
||||
int averr;
|
||||
int dimy, dimx;
|
||||
ncplane_dim_yx(ncp_, &dimy, &dimx);
|
||||
auto ncv = ncplane_visual_open(ncp_, "../data/dsscaw-purp.png", &averr);
|
||||
ASSERT_NE(nullptr, ncv);
|
||||
ASSERT_EQ(0, averr);
|
||||
auto frame = ncvisual_decode(ncv, &averr);
|
||||
ASSERT_NE(nullptr, frame);
|
||||
ASSERT_EQ(0, averr);
|
||||
EXPECT_EQ(dimy * 2, frame->height);
|
||||
EXPECT_EQ(dimx, frame->width);
|
||||
EXPECT_EQ(0, ncvisual_render(ncv, 0, 0, 0, 0));
|
||||
EXPECT_EQ(0, notcurses_render(nc_));
|
||||
frame = ncvisual_decode(ncv, &averr);
|
||||
ASSERT_EQ(nullptr, frame);
|
||||
EXPECT_EQ(AVERROR_EOF, averr);
|
||||
ncvisual_destroy(ncv);
|
||||
}
|
||||
|
||||
// FIXME ought run through full video, not just first frame
|
||||
TEST_F(LibavTest, LoadVideo) {
|
||||
int averr;
|
||||
int dimy, dimx;
|
||||
ncplane_dim_yx(ncp_, &dimy, &dimx);
|
||||
auto ncv = ncplane_visual_open(ncp_, "../data/fm6.mkv", &averr);
|
||||
ASSERT_NE(nullptr, ncv);
|
||||
EXPECT_EQ(0, averr);
|
||||
auto frame = ncvisual_decode(ncv, &averr);
|
||||
ASSERT_NE(nullptr, frame);
|
||||
EXPECT_EQ(0, averr);
|
||||
EXPECT_EQ(dimy * 2, frame->height);
|
||||
EXPECT_EQ(dimx, frame->width);
|
||||
EXPECT_EQ(0, ncvisual_render(ncv, 0, 0, 0, 0));
|
||||
EXPECT_EQ(0, notcurses_render(nc_));
|
||||
ncvisual_destroy(ncv);
|
||||
}
|
||||
|
||||
TEST_F(LibavTest, LoadVideoCreatePlane) {
|
||||
int averr;
|
||||
int dimy, dimx;
|
||||
ncplane_dim_yx(ncp_, &dimy, &dimx);
|
||||
auto ncv = ncvisual_open_plane(nc_, "../data/fm6.mkv", &averr, 0, 0, NCSCALE_STRETCH);
|
||||
ASSERT_NE(nullptr, ncv);
|
||||
EXPECT_EQ(0, averr);
|
||||
auto frame = ncvisual_decode(ncv, &averr);
|
||||
ASSERT_NE(nullptr, frame);
|
||||
EXPECT_EQ(0, averr);
|
||||
EXPECT_EQ(dimy * 2, frame->height);
|
||||
EXPECT_EQ(dimx, frame->width);
|
||||
EXPECT_EQ(0, ncvisual_render(ncv, 0, 0, 0, 0));
|
||||
EXPECT_EQ(0, notcurses_render(nc_));
|
||||
ncvisual_destroy(ncv);
|
||||
}
|
||||
#endif
|
||||
|
||||
TEST_CASE("Multimedia") {
|
||||
if(getenv("TERM") == nullptr){
|
||||
return;
|
||||
}
|
||||
notcurses_options nopts{};
|
||||
nopts.inhibit_alternate_screen = true;
|
||||
nopts.suppress_bannner = true;
|
||||
FILE* outfp_ = fopen("/dev/tty", "wb");
|
||||
REQUIRE(outfp_);
|
||||
notcurses* nc_ = notcurses_init(&nopts, outfp_);
|
||||
REQUIRE(nc_);
|
||||
ncplane* ncp_ = notcurses_stdplane(nc_);
|
||||
REQUIRE(ncp_);
|
||||
|
||||
#ifdef DISABLE_FFMPEG
|
||||
SUBCASE("LibavDisabled"){
|
||||
REQUIRE(!notcurses_canopen(nc_));
|
||||
}
|
||||
#else
|
||||
SUBCASE("LibavEnabled"){
|
||||
REQUIRE(notcurses_canopen(nc_));
|
||||
}
|
||||
|
||||
SUBCASE("LoadImage") {
|
||||
int averr;
|
||||
int dimy, dimx;
|
||||
ncplane_dim_yx(ncp_, &dimy, &dimx);
|
||||
auto ncv = ncplane_visual_open(ncp_, "../data/dsscaw-purp.png", &averr);
|
||||
REQUIRE(ncv);
|
||||
REQUIRE(0 == averr);
|
||||
auto frame = ncvisual_decode(ncv, &averr);
|
||||
REQUIRE(frame);
|
||||
REQUIRE(0 == averr);
|
||||
CHECK(dimy * 2 == frame->height);
|
||||
CHECK(dimx == frame->width);
|
||||
CHECK(0 == ncvisual_render(ncv, 0, 0, 0, 0));
|
||||
CHECK(0 == notcurses_render(nc_));
|
||||
frame = ncvisual_decode(ncv, &averr);
|
||||
REQUIRE_EQ(nullptr, frame);
|
||||
CHECK(AVERROR_EOF == averr);
|
||||
ncvisual_destroy(ncv);
|
||||
}
|
||||
|
||||
// FIXME ought run through full video, not just first frame
|
||||
SUBCASE("LoadVideo") {
|
||||
int averr;
|
||||
int dimy, dimx;
|
||||
ncplane_dim_yx(ncp_, &dimy, &dimx);
|
||||
auto ncv = ncplane_visual_open(ncp_, "../data/fm6.mkv", &averr);
|
||||
REQUIRE(ncv);
|
||||
CHECK(0 == averr);
|
||||
auto frame = ncvisual_decode(ncv, &averr);
|
||||
REQUIRE(frame);
|
||||
CHECK(0 == averr);
|
||||
CHECK(dimy * 2 == frame->height);
|
||||
CHECK(dimx == frame->width);
|
||||
CHECK(0 == ncvisual_render(ncv, 0, 0, 0, 0));
|
||||
CHECK(0 == notcurses_render(nc_));
|
||||
ncvisual_destroy(ncv);
|
||||
}
|
||||
|
||||
SUBCASE("LoadVideoCreatePlane") {
|
||||
int averr;
|
||||
int dimy, dimx;
|
||||
ncplane_dim_yx(ncp_, &dimy, &dimx);
|
||||
auto ncv = ncvisual_open_plane(nc_, "../data/fm6.mkv", &averr, 0, 0, NCSCALE_STRETCH);
|
||||
REQUIRE(ncv);
|
||||
CHECK(0 == averr);
|
||||
auto frame = ncvisual_decode(ncv, &averr);
|
||||
REQUIRE_NE(nullptr, frame);
|
||||
CHECK(0 == averr);
|
||||
CHECK(dimy * 2 == frame->height);
|
||||
CHECK(dimx == frame->width);
|
||||
CHECK(0 == ncvisual_render(ncv, 0, 0, 0, 0));
|
||||
CHECK(0 == notcurses_render(nc_));
|
||||
ncvisual_destroy(ncv);
|
||||
}
|
||||
#endif
|
||||
|
||||
CHECK(!notcurses_stop(nc_));
|
||||
CHECK(!fclose(outfp_));
|
||||
}
|
||||
|
||||
|
@ -1,3 +1,4 @@
|
||||
#define DOCTEST_CONFIG_IMPLEMENT
|
||||
#include <clocale>
|
||||
#include <iostream>
|
||||
#include "main.h"
|
||||
@ -7,6 +8,26 @@ int main(int argc, char **argv){
|
||||
std::cerr << "Coudln't set locale based on user preferences!" << std::endl;
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
::testing::InitGoogleTest(&argc, argv);
|
||||
return RUN_ALL_TESTS();
|
||||
doctest::Context context;
|
||||
|
||||
// defaults
|
||||
context.addFilter("test-case-exclude", "*math*"); // exclude test cases with "math" in their name
|
||||
context.setOption("abort-after", 5); // stop test execution after 5 failed assertions
|
||||
context.setOption("order-by", "name"); // sort the test cases by their name
|
||||
|
||||
context.applyCommandLine(argc, argv);
|
||||
|
||||
// overrides
|
||||
context.setOption("no-breaks", true); // don't break in the debugger when assertions fail
|
||||
|
||||
int res = context.run(); // run
|
||||
|
||||
if(context.shouldExit()){ // important - query flags (and --exit) rely on the user doing this
|
||||
return res; // propagate the result of the tests
|
||||
}
|
||||
|
||||
int client_stuff_return_code = 0;
|
||||
// your program - if the testing framework is integrated in your production code
|
||||
|
||||
return res + client_stuff_return_code; // the result from doctest is propagated here as well
|
||||
}
|
||||
|
@ -1,14 +1,8 @@
|
||||
#ifndef NOTCURSES_TEST_MAIN
|
||||
#define NOTCURSES_TEST_MAIN
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
#include "doctest.h"
|
||||
#include <notcurses.h>
|
||||
#include <curses.h>
|
||||
|
||||
// GTEST_SKIP only came along in GoogleTest 1.9
|
||||
#ifndef GTEST_SKIP
|
||||
#define GTEST_SKIP() return;
|
||||
#endif
|
||||
|
||||
|
||||
#endif
|
||||
|
1667
tests/ncplane.cpp
1667
tests/ncplane.cpp
File diff suppressed because it is too large
Load Diff
@ -1,154 +1,141 @@
|
||||
#include <string>
|
||||
#include <cstdlib>
|
||||
#include <iostream>
|
||||
#include <notcurses.h>
|
||||
#include "internal.h"
|
||||
#include "main.h"
|
||||
|
||||
class NotcursesTest : public :: testing::Test {
|
||||
protected:
|
||||
void SetUp() override {
|
||||
setlocale(LC_ALL, "");
|
||||
if(getenv("TERM") == nullptr){
|
||||
GTEST_SKIP();
|
||||
}
|
||||
notcurses_options nopts{};
|
||||
nopts.inhibit_alternate_screen = true;
|
||||
nopts.suppress_bannner = true;
|
||||
outfp_ = fopen("/dev/tty", "wb");
|
||||
ASSERT_NE(nullptr, outfp_);
|
||||
nc_ = notcurses_init(&nopts, outfp_);
|
||||
ASSERT_NE(nullptr, nc_);
|
||||
TEST_CASE("NotcursesBase") {
|
||||
|
||||
if(getenv("TERM") == nullptr){
|
||||
return;
|
||||
}
|
||||
notcurses_options nopts{};
|
||||
nopts.inhibit_alternate_screen = true;
|
||||
nopts.suppress_bannner = true;
|
||||
FILE* outfp_ = fopen("/dev/tty", "wb");
|
||||
REQUIRE(outfp_);
|
||||
struct notcurses* nc_ = notcurses_init(&nopts, outfp_);
|
||||
REQUIRE(nc_);
|
||||
|
||||
SUBCASE("NotcursesVersionString") {
|
||||
const char* ver = notcurses_version();
|
||||
REQUIRE(ver);
|
||||
REQUIRE(0 < strlen(ver));
|
||||
std::cout << "notcurses version " << ver << std::endl;
|
||||
}
|
||||
|
||||
void TearDown() override {
|
||||
if(nc_){
|
||||
EXPECT_EQ(0, notcurses_stop(nc_));
|
||||
SUBCASE("TermDimensions") {
|
||||
int x, y;
|
||||
notcurses_term_dim_yx(nc_, &y, &x);
|
||||
auto stry = getenv("LINES");
|
||||
if(stry){
|
||||
auto envy = std::stoi(stry, nullptr);
|
||||
CHECK(envy == y);
|
||||
}
|
||||
if(outfp_){
|
||||
fclose(outfp_);
|
||||
auto strx = getenv("COLUMNS");
|
||||
if(stry){
|
||||
auto envx = std::stoi(strx, nullptr);
|
||||
CHECK(envx == x);
|
||||
}
|
||||
}
|
||||
|
||||
struct notcurses* nc_{};
|
||||
FILE* outfp_{};
|
||||
};
|
||||
|
||||
TEST_F(NotcursesTest, NotcursesVersionString) {
|
||||
const char* ver = notcurses_version();
|
||||
ASSERT_NE(nullptr, ver);
|
||||
ASSERT_LT(0, strlen(ver));
|
||||
std::cout << "notcurses version " << ver << std::endl;
|
||||
}
|
||||
|
||||
TEST_F(NotcursesTest, BasicLifetime) {
|
||||
}
|
||||
|
||||
TEST_F(NotcursesTest, TermDimensions) {
|
||||
int x, y;
|
||||
notcurses_term_dim_yx(nc_, &y, &x);
|
||||
auto stry = getenv("LINES");
|
||||
if(stry){
|
||||
auto envy = std::stoi(stry, nullptr);
|
||||
EXPECT_EQ(envy, y);
|
||||
SUBCASE("ResizeSameSize") {
|
||||
int x, y;
|
||||
notcurses_term_dim_yx(nc_, &y, &x);
|
||||
int newx, newy;
|
||||
CHECK(0 == notcurses_resize(nc_, &newy, &newx));
|
||||
CHECK(newx == x);
|
||||
CHECK(newy == y);
|
||||
}
|
||||
auto strx = getenv("COLUMNS");
|
||||
if(stry){
|
||||
auto envx = std::stoi(strx, nullptr);
|
||||
EXPECT_EQ(envx, x);
|
||||
|
||||
// we should at least have CELL_STYLE_BOLD everywhere, i should think?
|
||||
SUBCASE("CursesStyles") {
|
||||
unsigned attrs = notcurses_supported_styles(nc_);
|
||||
CHECK(1 == !!(CELL_STYLE_BOLD & attrs));
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(NotcursesTest, ResizeSameSize) {
|
||||
int x, y;
|
||||
notcurses_term_dim_yx(nc_, &y, &x);
|
||||
int newx, newy;
|
||||
EXPECT_EQ(0, notcurses_resize(nc_, &newy, &newx));
|
||||
EXPECT_EQ(newx, x);
|
||||
EXPECT_EQ(newy, y);
|
||||
}
|
||||
// it is an error to attempt to destroy the standard plane
|
||||
SUBCASE("RejectDestroyStdPlane") {
|
||||
ncplane* ncp = notcurses_stdplane(nc_);
|
||||
REQUIRE(ncp);
|
||||
REQUIRE(0 > ncplane_destroy(ncp));
|
||||
}
|
||||
|
||||
// we should at least have CELL_STYLE_BOLD everywhere, i should think?
|
||||
TEST_F(NotcursesTest, CursesStyles) {
|
||||
unsigned attrs = notcurses_supported_styles(nc_);
|
||||
EXPECT_EQ(1, !!(CELL_STYLE_BOLD & attrs));
|
||||
}
|
||||
// it is an error to attempt to move the standard plane
|
||||
SUBCASE("RejectMoveStdPlane") {
|
||||
ncplane* ncp = notcurses_stdplane(nc_);
|
||||
REQUIRE(ncp);
|
||||
REQUIRE(0 > ncplane_move_yx(ncp, 1, 1));
|
||||
}
|
||||
|
||||
// it is an error to attempt to destroy the standard plane
|
||||
TEST_F(NotcursesTest, RejectDestroyStdPlane) {
|
||||
ncplane* ncp = notcurses_stdplane(nc_);
|
||||
ASSERT_NE(nullptr, ncp);
|
||||
ASSERT_NE(0, ncplane_destroy(ncp));
|
||||
}
|
||||
|
||||
// it is an error to attempt to move the standard plane
|
||||
TEST_F(NotcursesTest, RejectMoveStdPlane) {
|
||||
ncplane* ncp = notcurses_stdplane(nc_);
|
||||
ASSERT_NE(nullptr, ncp);
|
||||
ASSERT_NE(0, ncplane_move_yx(ncp, 1, 1));
|
||||
}
|
||||
|
||||
// create planes partitioning the entirety of the screen, one at each coordinate
|
||||
TEST_F(NotcursesTest, TileScreenWithPlanes) {
|
||||
int maxx, maxy;
|
||||
notcurses_term_dim_yx(nc_, &maxy, &maxx);
|
||||
auto total = maxx * maxy;
|
||||
struct ncplane** planes = new struct ncplane*[total];
|
||||
int* planesecrets = new int[total];
|
||||
for(int y = 0 ; y < maxy ; ++y){
|
||||
for(int x = 0 ; x < maxx ; ++x){
|
||||
const auto idx = y * maxx + x;
|
||||
planes[idx] = notcurses_newplane(nc_, 1, 1, y, x, &planesecrets[idx]);
|
||||
ASSERT_NE(nullptr, planes[idx]);
|
||||
// create planes partitioning the entirety of the screen, one at each coordinate
|
||||
SUBCASE("TileScreenWithPlanes") {
|
||||
int maxx, maxy;
|
||||
notcurses_term_dim_yx(nc_, &maxy, &maxx);
|
||||
auto total = maxx * maxy;
|
||||
struct ncplane** planes = new struct ncplane*[total];
|
||||
int* planesecrets = new int[total];
|
||||
for(int y = 0 ; y < maxy ; ++y){
|
||||
for(int x = 0 ; x < maxx ; ++x){
|
||||
const auto idx = y * maxx + x;
|
||||
planes[idx] = notcurses_newplane(nc_, 1, 1, y, x, &planesecrets[idx]);
|
||||
REQUIRE(planes[idx]);
|
||||
}
|
||||
}
|
||||
}
|
||||
ASSERT_EQ(0, notcurses_render(nc_));
|
||||
for(int y = 0 ; y < maxy ; ++y){
|
||||
for(int x = 0 ; x < maxx ; ++x){
|
||||
const auto idx = y * maxx + x;
|
||||
auto userptr = ncplane_userptr(planes[idx]);
|
||||
ASSERT_NE(nullptr, userptr);
|
||||
EXPECT_EQ(userptr, &planesecrets[idx]);
|
||||
ASSERT_EQ(0, ncplane_destroy(planes[idx]));
|
||||
REQUIRE(0 == notcurses_render(nc_));
|
||||
for(int y = 0 ; y < maxy ; ++y){
|
||||
for(int x = 0 ; x < maxx ; ++x){
|
||||
const auto idx = y * maxx + x;
|
||||
auto userptr = ncplane_userptr(planes[idx]);
|
||||
REQUIRE(userptr);
|
||||
CHECK(userptr == &planesecrets[idx]);
|
||||
REQUIRE(0 == ncplane_destroy(planes[idx]));
|
||||
}
|
||||
}
|
||||
delete[] planesecrets;
|
||||
delete[] planes;
|
||||
REQUIRE(0 == notcurses_render(nc_));
|
||||
}
|
||||
delete[] planesecrets;
|
||||
delete[] planes;
|
||||
ASSERT_EQ(0, notcurses_render(nc_));
|
||||
}
|
||||
|
||||
TEST_F(NotcursesTest, ChannelSetFGAlpha){
|
||||
uint64_t channel = 0;
|
||||
EXPECT_GT(0, channels_set_fg_alpha(&channel, -1));
|
||||
EXPECT_GT(0, channels_set_fg_alpha(&channel, 4));
|
||||
EXPECT_EQ(0, channels_set_fg_alpha(&channel, CELL_ALPHA_OPAQUE));
|
||||
EXPECT_EQ(CELL_ALPHA_OPAQUE, channels_get_fg_alpha(channel));
|
||||
EXPECT_EQ(0, channels_set_fg_alpha(&channel, CELL_ALPHA_HIGHCONTRAST));
|
||||
EXPECT_EQ(CELL_ALPHA_HIGHCONTRAST, channels_get_fg_alpha(channel));
|
||||
EXPECT_TRUE(channels_fg_default_p(channel));
|
||||
EXPECT_TRUE(channels_bg_default_p(channel));
|
||||
}
|
||||
SUBCASE("ChannelSetFGAlpha"){
|
||||
uint64_t channel = 0;
|
||||
CHECK(0 > channels_set_fg_alpha(&channel, -1));
|
||||
CHECK(0 > channels_set_fg_alpha(&channel, 4));
|
||||
CHECK(0 == channels_set_fg_alpha(&channel, CELL_ALPHA_OPAQUE));
|
||||
CHECK(CELL_ALPHA_OPAQUE == channels_get_fg_alpha(channel));
|
||||
CHECK(0 == channels_set_fg_alpha(&channel, CELL_ALPHA_HIGHCONTRAST));
|
||||
CHECK(CELL_ALPHA_HIGHCONTRAST == channels_get_fg_alpha(channel));
|
||||
CHECK(channels_fg_default_p(channel));
|
||||
CHECK(channels_bg_default_p(channel));
|
||||
}
|
||||
|
||||
TEST_F(NotcursesTest, ChannelSetBGAlpha){
|
||||
uint64_t channel = 0;
|
||||
EXPECT_GT(0, channels_set_bg_alpha(&channel, -1));
|
||||
EXPECT_GT(0, channels_set_bg_alpha(&channel, 4));
|
||||
EXPECT_EQ(0, channels_set_bg_alpha(&channel, CELL_ALPHA_OPAQUE));
|
||||
EXPECT_EQ(0, channels_get_bg_alpha(channel));
|
||||
EXPECT_EQ(0, channels_set_bg_alpha(&channel, CELL_ALPHA_TRANSPARENT));
|
||||
EXPECT_NE(0, channels_set_bg_alpha(&channel, CELL_ALPHA_HIGHCONTRAST));
|
||||
EXPECT_EQ(CELL_ALPHA_TRANSPARENT, channels_get_bg_alpha(channel));
|
||||
EXPECT_TRUE(channels_fg_default_p(channel));
|
||||
EXPECT_TRUE(channels_bg_default_p(channel));
|
||||
}
|
||||
SUBCASE("ChannelSetBGAlpha"){
|
||||
uint64_t channel = 0;
|
||||
CHECK(0 > channels_set_bg_alpha(&channel, -1));
|
||||
CHECK(0 > channels_set_bg_alpha(&channel, 4));
|
||||
CHECK(0 == channels_set_bg_alpha(&channel, CELL_ALPHA_OPAQUE));
|
||||
CHECK(CELL_ALPHA_OPAQUE == channels_get_bg_alpha(channel));
|
||||
CHECK(0 == channels_set_bg_alpha(&channel, CELL_ALPHA_TRANSPARENT));
|
||||
CHECK(0 > channels_set_bg_alpha(&channel, CELL_ALPHA_HIGHCONTRAST));
|
||||
CHECK(CELL_ALPHA_TRANSPARENT == channels_get_bg_alpha(channel));
|
||||
CHECK(channels_fg_default_p(channel));
|
||||
CHECK(channels_bg_default_p(channel));
|
||||
}
|
||||
|
||||
SUBCASE("Stats"){
|
||||
struct ncstats stats;
|
||||
notcurses_stats(nc_, &stats);
|
||||
CHECK(0 == stats.renders);
|
||||
CHECK(0 == notcurses_render(nc_));
|
||||
notcurses_stats(nc_, &stats);
|
||||
CHECK(1 == stats.renders);
|
||||
notcurses_reset_stats(nc_);
|
||||
notcurses_stats(nc_, &stats);
|
||||
CHECK(0 == stats.renders);
|
||||
}
|
||||
|
||||
CHECK(0 == notcurses_stop(nc_));
|
||||
CHECK(0 == fclose(outfp_));
|
||||
|
||||
TEST_F(NotcursesTest, Stats){
|
||||
struct ncstats stats;
|
||||
notcurses_stats(nc_, &stats);
|
||||
EXPECT_EQ(0, stats.renders);
|
||||
EXPECT_EQ(0, notcurses_render(nc_));
|
||||
notcurses_stats(nc_, &stats);
|
||||
EXPECT_EQ(1, stats.renders);
|
||||
notcurses_reset_stats(nc_);
|
||||
notcurses_stats(nc_, &stats);
|
||||
EXPECT_EQ(0, stats.renders);
|
||||
}
|
||||
|
@ -1,258 +1,243 @@
|
||||
#include "main.h"
|
||||
#include <iostream>
|
||||
|
||||
class PanelReelTest : public :: testing::Test {
|
||||
protected:
|
||||
void SetUp() override {
|
||||
setlocale(LC_ALL, "");
|
||||
if(getenv("TERM") == nullptr){
|
||||
GTEST_SKIP();
|
||||
}
|
||||
notcurses_options nopts{};
|
||||
nopts.inhibit_alternate_screen = true;
|
||||
nopts.suppress_bannner = true;
|
||||
outfp_ = fopen("/dev/tty", "wb");
|
||||
ASSERT_NE(nullptr, outfp_);
|
||||
nc_ = notcurses_init(&nopts, outfp_);
|
||||
ASSERT_NE(nullptr, nc_);
|
||||
n_ = notcurses_stdplane(nc_);
|
||||
ASSERT_NE(nullptr, n_);
|
||||
ASSERT_EQ(0, ncplane_cursor_move_yx(n_, 0, 0));
|
||||
}
|
||||
|
||||
void TearDown() override {
|
||||
if(nc_){
|
||||
EXPECT_EQ(0, notcurses_stop(nc_));
|
||||
}
|
||||
if(outfp_){
|
||||
fclose(outfp_);
|
||||
}
|
||||
}
|
||||
|
||||
struct notcurses* nc_{};
|
||||
struct ncplane* n_{};
|
||||
FILE* outfp_{};
|
||||
};
|
||||
|
||||
|
||||
TEST_F(PanelReelTest, InitLinear) {
|
||||
panelreel_options p = { };
|
||||
struct panelreel* pr = panelreel_create(n_, &p, -1);
|
||||
ASSERT_NE(nullptr, pr);
|
||||
}
|
||||
|
||||
TEST_F(PanelReelTest, InitLinearInfinite) {
|
||||
panelreel_options p{};
|
||||
p.infinitescroll = true;
|
||||
struct panelreel* pr = panelreel_create(n_, &p, -1);
|
||||
ASSERT_NE(nullptr, pr);
|
||||
}
|
||||
|
||||
TEST_F(PanelReelTest, InitCircular) {
|
||||
panelreel_options p{};
|
||||
p.infinitescroll = true;
|
||||
p.circular = true;
|
||||
struct panelreel* pr = panelreel_create(n_, &p, -1);
|
||||
ASSERT_NE(nullptr, pr);
|
||||
ASSERT_EQ(0, panelreel_destroy(pr));
|
||||
}
|
||||
|
||||
// circular is not allowed to be true when infinitescroll is false
|
||||
TEST_F(PanelReelTest, FiniteCircleRejected) {
|
||||
panelreel_options p{};
|
||||
p.infinitescroll = false;
|
||||
p.circular = true;
|
||||
struct panelreel* pr = panelreel_create(n_, &p, -1);
|
||||
ASSERT_EQ(nullptr, pr);
|
||||
}
|
||||
|
||||
// We ought be able to invoke panelreel_next() and panelreel_prev() safely,
|
||||
// even if there are no tablets. They both ought return nullptr.
|
||||
TEST_F(PanelReelTest, MovementWithoutTablets) {
|
||||
panelreel_options p{};
|
||||
p.infinitescroll = false;
|
||||
struct panelreel* pr = panelreel_create(n_, &p, -1);
|
||||
ASSERT_NE(nullptr, pr);
|
||||
EXPECT_EQ(nullptr, panelreel_next(pr));
|
||||
// EXPECT_EQ(0, panelreel_validate(n_, pr));
|
||||
EXPECT_EQ(nullptr, panelreel_prev(pr));
|
||||
// EXPECT_EQ(0, panelreel_validate(n_, pr));
|
||||
}
|
||||
|
||||
int panelcb(struct tablet* t, int begx, int begy, int maxx, int maxy, bool cliptop){
|
||||
EXPECT_NE(nullptr, tablet_ncplane(t));
|
||||
EXPECT_LT(begx, maxx);
|
||||
EXPECT_LT(begy, maxy);
|
||||
EXPECT_EQ(nullptr, tablet_userptr(t));
|
||||
EXPECT_FALSE(cliptop);
|
||||
CHECK(tablet_ncplane(t));
|
||||
CHECK(begx < maxx);
|
||||
CHECK(begy < maxy);
|
||||
CHECK(!tablet_userptr(t));
|
||||
CHECK(!cliptop);
|
||||
// FIXME verify geometry is as expected
|
||||
return 0;
|
||||
}
|
||||
|
||||
TEST_F(PanelReelTest, OneTablet) {
|
||||
panelreel_options p{};
|
||||
p.infinitescroll = false;
|
||||
struct panelreel* pr = panelreel_create(n_, &p, -1);
|
||||
ASSERT_NE(nullptr, pr);
|
||||
struct tablet* t = panelreel_add(pr, nullptr, nullptr, panelcb, nullptr);
|
||||
ASSERT_NE(nullptr, t);
|
||||
// EXPECT_EQ(0, panelreel_validate(n_, pr));
|
||||
EXPECT_EQ(0, panelreel_del(pr, t));
|
||||
// EXPECT_EQ(0, panelreel_validate(n_, pr));
|
||||
}
|
||||
TEST_CASE("PanelReelTest") {
|
||||
if(getenv("TERM") == nullptr){
|
||||
return;
|
||||
}
|
||||
notcurses_options nopts{};
|
||||
nopts.inhibit_alternate_screen = true;
|
||||
nopts.suppress_bannner = true;
|
||||
FILE* outfp_ = fopen("/dev/tty", "wb");
|
||||
REQUIRE(outfp_);
|
||||
struct notcurses* nc_ = notcurses_init(&nopts, outfp_);
|
||||
REQUIRE(nc_);
|
||||
struct ncplane* n_ = notcurses_stdplane(nc_);
|
||||
REQUIRE(n_);
|
||||
REQUIRE(0 == ncplane_cursor_move_yx(n_, 0, 0));
|
||||
|
||||
TEST_F(PanelReelTest, MovementWithOneTablet) {
|
||||
panelreel_options p{};
|
||||
p.infinitescroll = false;
|
||||
struct panelreel* pr = panelreel_create(n_, &p, -1);
|
||||
ASSERT_NE(nullptr, pr);
|
||||
struct tablet* t = panelreel_add(pr, nullptr, nullptr, panelcb, nullptr);
|
||||
ASSERT_NE(nullptr, t);
|
||||
// EXPECT_EQ(0, panelreel_validate(n_, pr));
|
||||
EXPECT_NE(nullptr, panelreel_next(pr));
|
||||
// EXPECT_EQ(0, panelreel_validate(n_, pr));
|
||||
EXPECT_NE(nullptr, panelreel_prev(pr));
|
||||
// EXPECT_EQ(0, panelreel_validate(n_, pr));
|
||||
EXPECT_EQ(0, panelreel_del(pr, t));
|
||||
// EXPECT_EQ(0, panelreel_validate(n_, pr));
|
||||
}
|
||||
SUBCASE("InitLinear") {
|
||||
panelreel_options p = { };
|
||||
struct panelreel* pr = panelreel_create(n_, &p, -1);
|
||||
REQUIRE(pr);
|
||||
}
|
||||
|
||||
TEST_F(PanelReelTest, DeleteActiveTablet) {
|
||||
panelreel_options p{};
|
||||
p.infinitescroll = false;
|
||||
struct panelreel* pr = panelreel_create(n_, &p, -1);
|
||||
ASSERT_NE(nullptr, pr);
|
||||
struct tablet* t = panelreel_add(pr, nullptr, nullptr, panelcb, nullptr);
|
||||
ASSERT_NE(nullptr, t);
|
||||
EXPECT_EQ(0, panelreel_del_focused(pr));
|
||||
}
|
||||
SUBCASE("InitLinearInfinite") {
|
||||
panelreel_options p{};
|
||||
p.infinitescroll = true;
|
||||
struct panelreel* pr = panelreel_create(n_, &p, -1);
|
||||
REQUIRE(pr);
|
||||
}
|
||||
|
||||
TEST_F(PanelReelTest, NoBorder) {
|
||||
panelreel_options p{};
|
||||
p.bordermask = NCBOXMASK_LEFT | NCBOXMASK_RIGHT |
|
||||
NCBOXMASK_TOP | NCBOXMASK_BOTTOM;
|
||||
struct panelreel* pr = panelreel_create(n_, &p, -1);
|
||||
ASSERT_NE(nullptr, pr);
|
||||
}
|
||||
SUBCASE("InitCircular") {
|
||||
panelreel_options p{};
|
||||
p.infinitescroll = true;
|
||||
p.circular = true;
|
||||
struct panelreel* pr = panelreel_create(n_, &p, -1);
|
||||
REQUIRE(pr);
|
||||
REQUIRE(0 == panelreel_destroy(pr));
|
||||
}
|
||||
|
||||
TEST_F(PanelReelTest, BadBorderBitsRejected) {
|
||||
panelreel_options p{};
|
||||
p.bordermask = NCBOXMASK_LEFT * 2;
|
||||
struct panelreel* pr = panelreel_create(n_, &p, -1);
|
||||
ASSERT_EQ(nullptr, pr);
|
||||
}
|
||||
// circular is not allowed to be true when infinitescroll is false
|
||||
SUBCASE("FiniteCircleRejected") {
|
||||
panelreel_options p{};
|
||||
p.infinitescroll = false;
|
||||
p.circular = true;
|
||||
struct panelreel* pr = panelreel_create(n_, &p, -1);
|
||||
REQUIRE(!pr);
|
||||
}
|
||||
|
||||
TEST_F(PanelReelTest, NoTabletBorder) {
|
||||
panelreel_options p{};
|
||||
p.tabletmask = NCBOXMASK_LEFT | NCBOXMASK_RIGHT |
|
||||
NCBOXMASK_TOP | NCBOXMASK_BOTTOM;
|
||||
struct panelreel* pr = panelreel_create(n_, &p, -1);
|
||||
ASSERT_NE(nullptr, pr);
|
||||
}
|
||||
// We ought be able to invoke panelreel_next() and panelreel_prev() safely,
|
||||
// even if there are no tablets. They both ought return nullptr.
|
||||
SUBCASE("MovementWithoutTablets") {
|
||||
panelreel_options p{};
|
||||
p.infinitescroll = false;
|
||||
struct panelreel* pr = panelreel_create(n_, &p, -1);
|
||||
REQUIRE(pr);
|
||||
CHECK(!panelreel_next(pr));
|
||||
// CHECK_EQ(0, panelreel_validate(n_, pr));
|
||||
CHECK(!panelreel_prev(pr));
|
||||
// CHECK_EQ(0, panelreel_validate(n_, pr));
|
||||
}
|
||||
|
||||
TEST_F(PanelReelTest, NoTopBottomBorder) {
|
||||
panelreel_options p{};
|
||||
p.bordermask = NCBOXMASK_TOP | NCBOXMASK_BOTTOM;
|
||||
struct panelreel* pr = panelreel_create(n_, &p, -1);
|
||||
ASSERT_NE(nullptr, pr);
|
||||
}
|
||||
SUBCASE("OneTablet") {
|
||||
panelreel_options p{};
|
||||
p.infinitescroll = false;
|
||||
struct panelreel* pr = panelreel_create(n_, &p, -1);
|
||||
REQUIRE(pr);
|
||||
struct tablet* t = panelreel_add(pr, nullptr, nullptr, panelcb, nullptr);
|
||||
REQUIRE(t);
|
||||
// CHECK_EQ(0, panelreel_validate(n_, pr));
|
||||
CHECK(0 == panelreel_del(pr, t));
|
||||
// CHECK_EQ(0, panelreel_validate(n_, pr));
|
||||
}
|
||||
|
||||
TEST_F(PanelReelTest, NoSideBorders) {
|
||||
panelreel_options p{};
|
||||
p.bordermask = NCBOXMASK_LEFT | NCBOXMASK_RIGHT;
|
||||
struct panelreel* pr = panelreel_create(n_, &p, -1);
|
||||
ASSERT_NE(nullptr, pr);
|
||||
}
|
||||
SUBCASE("MovementWithOneTablet") {
|
||||
panelreel_options p{};
|
||||
p.infinitescroll = false;
|
||||
struct panelreel* pr = panelreel_create(n_, &p, -1);
|
||||
REQUIRE(pr);
|
||||
struct tablet* t = panelreel_add(pr, nullptr, nullptr, panelcb, nullptr);
|
||||
REQUIRE(t);
|
||||
// CHECK_EQ(0, panelreel_validate(n_, pr));
|
||||
CHECK(panelreel_next(pr));
|
||||
// CHECK_EQ(0, panelreel_validate(n_, pr));
|
||||
CHECK(panelreel_prev(pr));
|
||||
// CHECK_EQ(0, panelreel_validate(n_, pr));
|
||||
CHECK(0 == panelreel_del(pr, t));
|
||||
// CHECK_EQ(0, panelreel_validate(n_, pr));
|
||||
}
|
||||
|
||||
TEST_F(PanelReelTest, BadTabletBorderBitsRejected) {
|
||||
panelreel_options p{};
|
||||
p.tabletmask = NCBOXMASK_LEFT * 2;
|
||||
struct panelreel* pr = panelreel_create(n_, &p, -1);
|
||||
ASSERT_EQ(nullptr, pr);
|
||||
}
|
||||
SUBCASE("DeleteActiveTablet") {
|
||||
panelreel_options p{};
|
||||
p.infinitescroll = false;
|
||||
struct panelreel* pr = panelreel_create(n_, &p, -1);
|
||||
REQUIRE(pr);
|
||||
struct tablet* t = panelreel_add(pr, nullptr, nullptr, panelcb, nullptr);
|
||||
REQUIRE(t);
|
||||
CHECK(0 == panelreel_del_focused(pr));
|
||||
}
|
||||
|
||||
/*
|
||||
// Make a target window occupying all but a containing perimeter of the
|
||||
// specified WINDOW (which will usually be n_).
|
||||
struct ncpanel* make_targwin(struct ncpanel* w) {
|
||||
cchar_t cc;
|
||||
int cpair = COLOR_GREEN;
|
||||
EXPECT_EQ(OK, setcchar(&cc, L"W", 0, 0, &cpair));
|
||||
int x, y, xx, yy;
|
||||
getbegyx(w, y, x);
|
||||
getmaxyx(w, yy, xx);
|
||||
yy -= 2;
|
||||
xx -= 2;
|
||||
++x;
|
||||
++y;
|
||||
WINDOW* ww = subwin(w, yy, xx, y, x);
|
||||
EXPECT_NE(nullptr, ww);
|
||||
PANEL* p = new_panel(ww);
|
||||
EXPECT_NE(nullptr, p);
|
||||
EXPECT_EQ(OK, wbkgrnd(ww, &cc));
|
||||
return p;
|
||||
}
|
||||
SUBCASE("NoBorder") {
|
||||
panelreel_options p{};
|
||||
p.bordermask = NCBOXMASK_LEFT | NCBOXMASK_RIGHT |
|
||||
NCBOXMASK_TOP | NCBOXMASK_BOTTOM;
|
||||
struct panelreel* pr = panelreel_create(n_, &p, -1);
|
||||
REQUIRE(pr);
|
||||
}
|
||||
|
||||
TEST_F(PanelReelTest, InitWithinSubwin) {
|
||||
panelreel_options p{};
|
||||
p.loff = 1;
|
||||
p.roff = 1;
|
||||
p.toff = 1;
|
||||
p.boff = 1;
|
||||
EXPECT_EQ(0, clear());
|
||||
PANEL* base = make_targwin(n_);
|
||||
ASSERT_NE(nullptr, base);
|
||||
WINDOW* basew = panel_window(base);
|
||||
ASSERT_NE(nullptr, basew);
|
||||
struct panelreel* pr = panelreel_create(basew, &p, -1);
|
||||
ASSERT_NE(nullptr, pr);
|
||||
EXPECT_EQ(0, panelreel_validate(basew, pr));
|
||||
ASSERT_EQ(0, panelreel_destroy(pr));
|
||||
EXPECT_EQ(OK, del_panel(base));
|
||||
EXPECT_EQ(OK, delwin(basew));
|
||||
}
|
||||
SUBCASE("BadBorderBitsRejected") {
|
||||
panelreel_options p{};
|
||||
p.bordermask = NCBOXMASK_LEFT * 2;
|
||||
struct panelreel* pr = panelreel_create(n_, &p, -1);
|
||||
REQUIRE(!pr);
|
||||
}
|
||||
|
||||
TEST_F(PanelReelTest, SubwinNoPanelreelBorders) {
|
||||
panelreel_options p{};
|
||||
p.loff = 1;
|
||||
p.roff = 1;
|
||||
p.toff = 1;
|
||||
p.boff = 1;
|
||||
p.bordermask = NCBOXMASK_LEFT | NCBOXMASK_RIGHT |
|
||||
NCBOXMASK_TOP | NCBOXMASK_BOTTOM;
|
||||
EXPECT_EQ(0, clear());
|
||||
PANEL* base = make_targwin(n_);
|
||||
ASSERT_NE(nullptr, base);
|
||||
WINDOW* basew = panel_window(base);
|
||||
ASSERT_NE(nullptr, basew);
|
||||
struct panelreel* pr = panelreel_create(basew, &p, -1);
|
||||
ASSERT_NE(nullptr, pr);
|
||||
EXPECT_EQ(0, panelreel_validate(basew, pr));
|
||||
ASSERT_EQ(0, panelreel_destroy(pr));
|
||||
EXPECT_EQ(OK, del_panel(base));
|
||||
EXPECT_EQ(OK, delwin(basew));
|
||||
}
|
||||
SUBCASE("NoTabletBorder") {
|
||||
panelreel_options p{};
|
||||
p.tabletmask = NCBOXMASK_LEFT | NCBOXMASK_RIGHT |
|
||||
NCBOXMASK_TOP | NCBOXMASK_BOTTOM;
|
||||
struct panelreel* pr = panelreel_create(n_, &p, -1);
|
||||
REQUIRE(pr);
|
||||
}
|
||||
|
||||
TEST_F(PanelReelTest, SubwinNoOffsetGeom) {
|
||||
panelreel_options p{};
|
||||
EXPECT_EQ(0, clear());
|
||||
PANEL* base = make_targwin(n_);
|
||||
ASSERT_NE(nullptr, base);
|
||||
WINDOW* basew = panel_window(base);
|
||||
ASSERT_NE(nullptr, basew);
|
||||
struct panelreel* pr = panelreel_create(basew, &p, -1);
|
||||
ASSERT_NE(nullptr, pr);
|
||||
EXPECT_EQ(0, panelreel_validate(basew, pr));
|
||||
ASSERT_EQ(0, panelreel_destroy(pr));
|
||||
EXPECT_EQ(OK, del_panel(base));
|
||||
EXPECT_EQ(OK, delwin(basew));
|
||||
}
|
||||
*/
|
||||
SUBCASE("NoTopBottomBorder") {
|
||||
panelreel_options p{};
|
||||
p.bordermask = NCBOXMASK_TOP | NCBOXMASK_BOTTOM;
|
||||
struct panelreel* pr = panelreel_create(n_, &p, -1);
|
||||
REQUIRE(pr);
|
||||
}
|
||||
|
||||
TEST_F(PanelReelTest, TransparentBackground) {
|
||||
panelreel_options p{};
|
||||
channels_set_bg_alpha(&p.bgchannel, 3);
|
||||
struct panelreel* pr = panelreel_create(n_, &p, -1);
|
||||
ASSERT_NE(nullptr, pr);
|
||||
// FIXME
|
||||
SUBCASE("NoSideBorders") {
|
||||
panelreel_options p{};
|
||||
p.bordermask = NCBOXMASK_LEFT | NCBOXMASK_RIGHT;
|
||||
struct panelreel* pr = panelreel_create(n_, &p, -1);
|
||||
REQUIRE(pr);
|
||||
}
|
||||
|
||||
SUBCASE("BadTabletBorderBitsRejected") {
|
||||
panelreel_options p{};
|
||||
p.tabletmask = NCBOXMASK_LEFT * 2;
|
||||
struct panelreel* pr = panelreel_create(n_, &p, -1);
|
||||
REQUIRE(!pr);
|
||||
}
|
||||
|
||||
/*
|
||||
// Make a target window occupying all but a containing perimeter of the
|
||||
// specified WINDOW (which will usually be n_).
|
||||
struct ncpanel* make_targwin(struct ncpanel* w) {
|
||||
cchar_t cc;
|
||||
int cpair = COLOR_GREEN;
|
||||
CHECK_EQ(OK, setcchar(&cc, L"W", 0, 0, &cpair));
|
||||
int x, y, xx, yy;
|
||||
getbegyx(w, y, x);
|
||||
getmaxyx(w, yy, xx);
|
||||
yy -= 2;
|
||||
xx -= 2;
|
||||
++x;
|
||||
++y;
|
||||
WINDOW* ww = subwin(w, yy, xx, y, x);
|
||||
CHECK_NE(nullptr, ww);
|
||||
PANEL* p = new_panel(ww);
|
||||
CHECK_NE(nullptr, p);
|
||||
CHECK_EQ(OK, wbkgrnd(ww, &cc));
|
||||
return p;
|
||||
}
|
||||
|
||||
SUBCASE("InitWithinSubwin") {
|
||||
panelreel_options p{};
|
||||
p.loff = 1;
|
||||
p.roff = 1;
|
||||
p.toff = 1;
|
||||
p.boff = 1;
|
||||
CHECK_EQ(0, clear());
|
||||
PANEL* base = make_targwin(n_);
|
||||
REQUIRE_NE(nullptr, base);
|
||||
WINDOW* basew = panel_window(base);
|
||||
REQUIRE_NE(nullptr, basew);
|
||||
struct panelreel* pr = panelreel_create(basew, &p, -1);
|
||||
REQUIRE_NE(nullptr, pr);
|
||||
CHECK_EQ(0, panelreel_validate(basew, pr));
|
||||
REQUIRE_EQ(0, panelreel_destroy(pr));
|
||||
CHECK_EQ(OK, del_panel(base));
|
||||
CHECK_EQ(OK, delwin(basew));
|
||||
}
|
||||
|
||||
SUBCASE("SubwinNoPanelreelBorders") {
|
||||
panelreel_options p{};
|
||||
p.loff = 1;
|
||||
p.roff = 1;
|
||||
p.toff = 1;
|
||||
p.boff = 1;
|
||||
p.bordermask = NCBOXMASK_LEFT | NCBOXMASK_RIGHT |
|
||||
NCBOXMASK_TOP | NCBOXMASK_BOTTOM;
|
||||
CHECK_EQ(0, clear());
|
||||
PANEL* base = make_targwin(n_);
|
||||
REQUIRE_NE(nullptr, base);
|
||||
WINDOW* basew = panel_window(base);
|
||||
REQUIRE_NE(nullptr, basew);
|
||||
struct panelreel* pr = panelreel_create(basew, &p, -1);
|
||||
REQUIRE_NE(nullptr, pr);
|
||||
CHECK_EQ(0, panelreel_validate(basew, pr));
|
||||
REQUIRE_EQ(0, panelreel_destroy(pr));
|
||||
CHECK_EQ(OK, del_panel(base));
|
||||
CHECK_EQ(OK, delwin(basew));
|
||||
}
|
||||
|
||||
SUBCASE("SubwinNoOffsetGeom") {
|
||||
panelreel_options p{};
|
||||
CHECK_EQ(0, clear());
|
||||
PANEL* base = make_targwin(n_);
|
||||
REQUIRE_NE(nullptr, base);
|
||||
WINDOW* basew = panel_window(base);
|
||||
REQUIRE_NE(nullptr, basew);
|
||||
struct panelreel* pr = panelreel_create(basew, &p, -1);
|
||||
REQUIRE_NE(nullptr, pr);
|
||||
CHECK_EQ(0, panelreel_validate(basew, pr));
|
||||
REQUIRE_EQ(0, panelreel_destroy(pr));
|
||||
CHECK_EQ(OK, del_panel(base));
|
||||
CHECK_EQ(OK, delwin(basew));
|
||||
}
|
||||
*/
|
||||
|
||||
SUBCASE("TransparentBackground") {
|
||||
panelreel_options p{};
|
||||
channels_set_bg_alpha(&p.bgchannel, 3);
|
||||
struct panelreel* pr = panelreel_create(n_, &p, -1);
|
||||
REQUIRE(pr);
|
||||
// FIXME
|
||||
}
|
||||
|
||||
CHECK(0 == notcurses_stop(nc_));
|
||||
CHECK(0 == fclose(outfp_));
|
||||
}
|
||||
|
232
tests/zaxis.cpp
232
tests/zaxis.cpp
@ -2,136 +2,122 @@
|
||||
#include <cstdlib>
|
||||
#include <iostream>
|
||||
|
||||
class ZAxisTest : public :: testing::Test {
|
||||
protected:
|
||||
void SetUp() override {
|
||||
setlocale(LC_ALL, "");
|
||||
if(getenv("TERM") == nullptr){
|
||||
GTEST_SKIP();
|
||||
}
|
||||
notcurses_options nopts{};
|
||||
nopts.inhibit_alternate_screen = true;
|
||||
nopts.suppress_bannner = true;
|
||||
outfp_ = fopen("/dev/tty", "wb");
|
||||
ASSERT_NE(nullptr, outfp_);
|
||||
nc_ = notcurses_init(&nopts, outfp_);
|
||||
ASSERT_NE(nullptr, nc_);
|
||||
n_ = notcurses_stdplane(nc_);
|
||||
ASSERT_NE(nullptr, n_);
|
||||
TEST_CASE("ZAxisTest") {
|
||||
if(getenv("TERM") == nullptr){
|
||||
return;
|
||||
}
|
||||
notcurses_options nopts{};
|
||||
nopts.inhibit_alternate_screen = true;
|
||||
nopts.suppress_bannner = true;
|
||||
FILE* outfp_ = fopen("/dev/tty", "wb");
|
||||
REQUIRE(outfp_);
|
||||
struct notcurses* nc_ = notcurses_init(&nopts, outfp_);
|
||||
REQUIRE(nc_);
|
||||
struct ncplane* n_ = notcurses_stdplane(nc_);
|
||||
REQUIRE(n_);
|
||||
|
||||
SUBCASE("StdPlaneOnly") {
|
||||
struct ncplane* top = notcurses_top(nc_);
|
||||
CHECK(n_ == top);
|
||||
CHECK(!ncplane_below(top));
|
||||
}
|
||||
|
||||
void TearDown() override {
|
||||
if(nc_){
|
||||
EXPECT_EQ(0, notcurses_stop(nc_));
|
||||
}
|
||||
if(outfp_){
|
||||
fclose(outfp_);
|
||||
}
|
||||
// if you want to move the plane which is already top+bottom to either, go ahead
|
||||
SUBCASE("StdPlaneOnanism") {
|
||||
CHECK(0 == ncplane_move_top(n_));
|
||||
struct ncplane* top = notcurses_top(nc_);
|
||||
CHECK(n_ == top);
|
||||
CHECK(!ncplane_below(top));
|
||||
CHECK(0 == ncplane_move_bottom(n_));
|
||||
CHECK(!ncplane_below(n_));
|
||||
}
|
||||
|
||||
struct notcurses* nc_{};
|
||||
struct ncplane* n_{};
|
||||
FILE* outfp_{};
|
||||
};
|
||||
// you can't place a plane above or below itself, stdplane or otherwise
|
||||
SUBCASE("NoMoveSelf") {
|
||||
struct ncplane* np = notcurses_newplane(nc_, 2, 2, 0, 0, nullptr);
|
||||
REQUIRE(np);
|
||||
CHECK(ncplane_move_below(n_, n_));
|
||||
CHECK(ncplane_move_above(n_, n_));
|
||||
CHECK(ncplane_move_below(np, np));
|
||||
CHECK(ncplane_move_above(np, np));
|
||||
}
|
||||
|
||||
TEST_F(ZAxisTest, StdPlaneOnly) {
|
||||
struct ncplane* top = notcurses_top(nc_);
|
||||
EXPECT_EQ(n_, top);
|
||||
EXPECT_EQ(nullptr, ncplane_below(top));
|
||||
}
|
||||
// new planes ought be on the top
|
||||
SUBCASE("NewPlaneOnTop") {
|
||||
struct ncplane* np = notcurses_newplane(nc_, 2, 2, 0, 0, nullptr);
|
||||
REQUIRE(np);
|
||||
struct ncplane* top = notcurses_top(nc_);
|
||||
CHECK(np == top);
|
||||
CHECK(n_ == ncplane_below(top));
|
||||
CHECK(!ncplane_below(n_));
|
||||
}
|
||||
|
||||
// if you want to move the plane which is already top+bottom to either, go ahead
|
||||
TEST_F(ZAxisTest, StdPlaneOnanism) {
|
||||
EXPECT_EQ(0, ncplane_move_top(n_));
|
||||
struct ncplane* top = notcurses_top(nc_);
|
||||
EXPECT_EQ(n_, top);
|
||||
EXPECT_EQ(nullptr, ncplane_below(top));
|
||||
EXPECT_EQ(0, ncplane_move_bottom(n_));
|
||||
EXPECT_EQ(nullptr, ncplane_below(n_));
|
||||
}
|
||||
// "move" top plane to top. everything ought remain the same.
|
||||
SUBCASE("TopToTop") {
|
||||
struct ncplane* np = notcurses_newplane(nc_, 2, 2, 0, 0, nullptr);
|
||||
REQUIRE(np);
|
||||
struct ncplane* top = notcurses_top(nc_);
|
||||
CHECK(np == top);
|
||||
CHECK(n_ == ncplane_below(top));
|
||||
CHECK(!ncplane_below(n_));
|
||||
CHECK(!ncplane_move_top(np));
|
||||
// verify it
|
||||
top = notcurses_top(nc_);
|
||||
CHECK(np == top);
|
||||
CHECK(n_ == ncplane_below(top));
|
||||
CHECK(!ncplane_below(n_));
|
||||
}
|
||||
|
||||
// you can't place a plane above or below itself, stdplane or otherwise
|
||||
TEST_F(ZAxisTest, NoMoveSelf) {
|
||||
struct ncplane* np = notcurses_newplane(nc_, 2, 2, 0, 0, nullptr);
|
||||
ASSERT_NE(nullptr, np);
|
||||
EXPECT_NE(0, ncplane_move_below(n_, n_));
|
||||
EXPECT_NE(0, ncplane_move_above(n_, n_));
|
||||
EXPECT_NE(0, ncplane_move_below(np, np));
|
||||
EXPECT_NE(0, ncplane_move_above(np, np));
|
||||
}
|
||||
// move top plane to bottom, and verify enumeration
|
||||
SUBCASE("TopToBottom") {
|
||||
struct ncplane* np = notcurses_newplane(nc_, 2, 2, 0, 0, nullptr);
|
||||
REQUIRE(np);
|
||||
struct ncplane* top = notcurses_top(nc_);
|
||||
CHECK(np == top);
|
||||
CHECK(n_ == ncplane_below(top));
|
||||
CHECK(!ncplane_below(n_));
|
||||
CHECK(!ncplane_move_bottom(np));
|
||||
top = notcurses_top(nc_);
|
||||
CHECK(n_ == top);
|
||||
CHECK(np == ncplane_below(top));
|
||||
CHECK(!ncplane_below(np));
|
||||
}
|
||||
|
||||
// new planes ought be on the top
|
||||
TEST_F(ZAxisTest, NewPlaneOnTop) {
|
||||
struct ncplane* np = notcurses_newplane(nc_, 2, 2, 0, 0, nullptr);
|
||||
ASSERT_NE(nullptr, np);
|
||||
struct ncplane* top = notcurses_top(nc_);
|
||||
EXPECT_EQ(np, top);
|
||||
EXPECT_EQ(n_, ncplane_below(top));
|
||||
EXPECT_EQ(nullptr, ncplane_below(n_));
|
||||
}
|
||||
// verify that moving one above another, with no other changes, is reflected at
|
||||
// render time (requires explicit damage maintenance from move functionality).
|
||||
SUBCASE("ZAxisDamage") {
|
||||
cell cat = CELL_TRIVIAL_INITIALIZER;
|
||||
cell c = CELL_SIMPLE_INITIALIZER('x');
|
||||
REQUIRE(!cell_set_fg_rgb(&c, 0xff, 0, 0));
|
||||
REQUIRE(1 == ncplane_putc(n_, &c));
|
||||
CHECK(!notcurses_render(nc_));
|
||||
REQUIRE(!ncplane_cursor_move_yx(n_, 0, 0));
|
||||
REQUIRE(1 == ncplane_at_cursor(n_, &cat));
|
||||
REQUIRE(cell_simple_p(&cat));
|
||||
REQUIRE('x' == cat.gcluster);
|
||||
struct ncplane* n2 = notcurses_newplane(nc_, 2, 2, 0, 0, nullptr);
|
||||
REQUIRE(1 == cell_load(n2, &c, "y"));
|
||||
REQUIRE(!cell_set_fg_rgb(&c, 0, 0xff, 0));
|
||||
REQUIRE(1 == ncplane_putc(n2, &c));
|
||||
CHECK_EQ(0, notcurses_render(nc_));
|
||||
REQUIRE(!ncplane_cursor_move_yx(n2, 0, 0));
|
||||
REQUIRE(1 == ncplane_at_cursor(n2, &cat));
|
||||
REQUIRE('y' == cat.gcluster);
|
||||
struct ncplane* n3 = notcurses_newplane(nc_, 2, 2, 0, 0, nullptr);
|
||||
REQUIRE(1 == cell_load(n3, &c, "z"));
|
||||
REQUIRE(!cell_set_fg_rgb(&c, 0, 0, 0xff));
|
||||
REQUIRE(1 == ncplane_putc(n3, &c));
|
||||
CHECK(!notcurses_render(nc_));
|
||||
REQUIRE(!ncplane_cursor_move_yx(n3, 0, 0));
|
||||
REQUIRE(1 == ncplane_at_cursor(n3, &cat));
|
||||
REQUIRE('z' == cat.gcluster);
|
||||
// FIXME testing damage requires notcurses keeping a copy of the screen....
|
||||
// FIXME move y atop z
|
||||
// FIXME inspect
|
||||
// FIXME move z atop y
|
||||
// FIXME inspect
|
||||
}
|
||||
|
||||
// "move" top plane to top. everything ought remain the same.
|
||||
TEST_F(ZAxisTest, TopToTop) {
|
||||
struct ncplane* np = notcurses_newplane(nc_, 2, 2, 0, 0, nullptr);
|
||||
ASSERT_NE(nullptr, np);
|
||||
struct ncplane* top = notcurses_top(nc_);
|
||||
EXPECT_EQ(np, top);
|
||||
EXPECT_EQ(n_, ncplane_below(top));
|
||||
EXPECT_EQ(nullptr, ncplane_below(n_));
|
||||
EXPECT_EQ(0, ncplane_move_top(np));
|
||||
// verify it
|
||||
top = notcurses_top(nc_);
|
||||
EXPECT_EQ(np, top);
|
||||
EXPECT_EQ(n_, ncplane_below(top));
|
||||
EXPECT_EQ(nullptr, ncplane_below(n_));
|
||||
}
|
||||
|
||||
// move top plane to bottom, and verify enumeration
|
||||
TEST_F(ZAxisTest, TopToBottom) {
|
||||
struct ncplane* np = notcurses_newplane(nc_, 2, 2, 0, 0, nullptr);
|
||||
ASSERT_NE(nullptr, np);
|
||||
struct ncplane* top = notcurses_top(nc_);
|
||||
EXPECT_EQ(np, top);
|
||||
EXPECT_EQ(n_, ncplane_below(top));
|
||||
EXPECT_EQ(nullptr, ncplane_below(n_));
|
||||
EXPECT_EQ(0, ncplane_move_bottom(np));
|
||||
top = notcurses_top(nc_);
|
||||
EXPECT_EQ(n_, top);
|
||||
EXPECT_EQ(np, ncplane_below(top));
|
||||
EXPECT_EQ(nullptr, ncplane_below(np));
|
||||
}
|
||||
|
||||
// verify that moving one above another, with no other changes, is reflected at
|
||||
// render time (requires explicit damage maintenance from move functionality).
|
||||
TEST_F(ZAxisTest, ZAxisDamage) {
|
||||
cell cat = CELL_TRIVIAL_INITIALIZER;
|
||||
cell c = CELL_SIMPLE_INITIALIZER('x');
|
||||
ASSERT_EQ(0, cell_set_fg_rgb(&c, 0xff, 0, 0));
|
||||
ASSERT_EQ(1, ncplane_putc(n_, &c));
|
||||
EXPECT_EQ(0, notcurses_render(nc_));
|
||||
ASSERT_EQ(0, ncplane_cursor_move_yx(n_, 0, 0));
|
||||
ASSERT_EQ(1, ncplane_at_cursor(n_, &cat));
|
||||
ASSERT_TRUE(cell_simple_p(&cat));
|
||||
ASSERT_EQ('x', cat.gcluster);
|
||||
struct ncplane* n2 = notcurses_newplane(nc_, 2, 2, 0, 0, nullptr);
|
||||
ASSERT_EQ(1, cell_load(n2, &c, "y"));
|
||||
ASSERT_EQ(0, cell_set_fg_rgb(&c, 0, 0xff, 0));
|
||||
ASSERT_EQ(1, ncplane_putc(n2, &c));
|
||||
EXPECT_EQ(0, notcurses_render(nc_));
|
||||
ASSERT_EQ(0, ncplane_cursor_move_yx(n2, 0, 0));
|
||||
ASSERT_EQ(1, ncplane_at_cursor(n2, &cat));
|
||||
ASSERT_EQ('y', cat.gcluster);
|
||||
struct ncplane* n3 = notcurses_newplane(nc_, 2, 2, 0, 0, nullptr);
|
||||
ASSERT_EQ(1, cell_load(n3, &c, "z"));
|
||||
ASSERT_EQ(0, cell_set_fg_rgb(&c, 0, 0, 0xff));
|
||||
ASSERT_EQ(1, ncplane_putc(n3, &c));
|
||||
EXPECT_EQ(0, notcurses_render(nc_));
|
||||
ASSERT_EQ(0, ncplane_cursor_move_yx(n3, 0, 0));
|
||||
ASSERT_EQ(1, ncplane_at_cursor(n3, &cat));
|
||||
ASSERT_EQ('z', cat.gcluster);
|
||||
// FIXME testing damage requires notcurses keeping a copy of the screen....
|
||||
// FIXME move y atop z
|
||||
// FIXME inspect
|
||||
// FIXME move z atop y
|
||||
// FIXME inspect
|
||||
CHECK(0 == notcurses_stop(nc_));
|
||||
CHECK(0 == fclose(outfp_));
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user