* 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 testpull/232/head
parent
d4caefc55d
commit
ce2a390b52
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;
|
||||
}
|
||||
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;
|
||||
// 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
// 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;
|
||||
// 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));
|
||||
}
|
||||
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){
|
||||
ASSERT_EQ(-1, candidates[i]);
|
||||
continue;
|
||||
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));
|
||||
}
|
||||
ASSERT_LT(0, r);
|
||||
mb[r] = '\0';
|
||||
EXPECT_STREQ(mb, stored);
|
||||
CHECK(candidates.size() / 13 > no);
|
||||
}
|
||||
ASSERT_GT(candidates.size() / 13, no);
|
||||
|
||||
// common cleanup
|
||||
egcpool_dump(&pool_);
|
||||
|
||||
}
|
||||
|
@ -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_);
|
||||
}
|
||||
}
|
||||
|
||||
struct notcurses* nc_{};
|
||||
FILE* outfp_{};
|
||||
};
|
||||
|
||||
TEST_F(InputTest, TestMouseOn){
|
||||
ASSERT_EQ(0, notcurses_mouse_enable(nc_));
|
||||
}
|
||||
REQUIRE(0 == notcurses_mouse_enable(nc_));
|
||||
CHECK(0 == notcurses_mouse_disable(nc_));
|
||||
|
||||
TEST_F(InputTest, TestMouseOff){
|
||||
ASSERT_EQ(0, notcurses_mouse_disable(nc_));
|
||||
CHECK(0 == notcurses_stop(nc_));
|
||||
CHECK(0 == fclose(outfp_));
|
||||
}
|
||||
|
@ -1,104 +1,92 @@
|
||||
#include <notcurses.h>
|
||||
#include "version.h"
|
||||
#include "main.h"
|
||||
#ifndef DISABLE_FFMPEG
|
||||
#include <libavutil/pixdesc.h>
|
||||
#include <libavutil/avconfig.h>
|
||||
#include <libavcodec/avcodec.h> // ffmpeg doesn't reliably "C"-guard itself
|
||||
#endif
|
||||
|
||||
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_);
|
||||
}
|
||||
TEST_CASE("Multimedia") {
|
||||
if(getenv("TERM") == nullptr){
|
||||
return;
|
||||
}
|
||||
|
||||
notcurses* nc_{};
|
||||
ncplane* ncp_{};
|
||||
FILE* outfp_{};
|
||||
};
|
||||
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
|
||||
TEST_F(LibavTest, LibavDisabled){
|
||||
ASSERT_FALSE(notcurses_canopen(nc_));
|
||||
}
|
||||
SUBCASE("LibavDisabled"){
|
||||
REQUIRE(!notcurses_canopen(nc_));
|
||||
}
|
||||
#else
|
||||
#include <libavutil/pixdesc.h>
|
||||
#include <libavutil/avconfig.h>
|
||||
#include <libavcodec/avcodec.h> // ffmpeg doesn't reliably "C"-guard itself
|
||||
SUBCASE("LibavEnabled"){
|
||||
REQUIRE(notcurses_canopen(nc_));
|
||||
}
|
||||
|
||||
TEST_F(LibavTest, LibavEnabled){
|
||||
ASSERT_TRUE(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);
|
||||
}
|
||||
|
||||
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
|
||||
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);
|
||||
}
|
||||
|
||||
// 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);
|
||||
}
|
||||
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
|
||||
|
||||
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);
|
||||
CHECK(!notcurses_stop(nc_));
|
||||
CHECK(!fclose(outfp_));
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -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
|
||||
|
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);
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
// 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));
|
||||
}
|
||||
// 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));
|
||||
}
|
||||
|
||||
// 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 destroy the standard plane
|
||||
SUBCASE("RejectDestroyStdPlane") {
|
||||
ncplane* ncp = notcurses_stdplane(nc_);
|
||||
REQUIRE(ncp);
|
||||
REQUIRE(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));
|
||||
}
|
||||
// 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));
|
||||
}
|
||||
|
||||
// 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);
|
||||
int panelcb(struct tablet* t, int begx, int begy, int maxx, int maxy, bool 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, InitLinearInfinite) {
|
||||
panelreel_options p{};
|
||||
p.infinitescroll = true;
|
||||
struct panelreel* pr = panelreel_create(n_, &p, -1);
|
||||
ASSERT_NE(nullptr, 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));
|
||||
|
||||
SUBCASE("InitLinear") {
|
||||
panelreel_options p = { };
|
||||
struct panelreel* pr = panelreel_create(n_, &p, -1);
|
||||
REQUIRE(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));
|
||||
}
|
||||
SUBCASE("InitLinearInfinite") {
|
||||
panelreel_options p{};
|
||||
p.infinitescroll = true;
|
||||
struct panelreel* pr = panelreel_create(n_, &p, -1);
|
||||
REQUIRE(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);
|
||||
}
|
||||
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));
|
||||
}
|
||||
|
||||
// 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));
|
||||
}
|
||||
// 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);
|
||||
}
|
||||
|
||||
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);
|
||||
// FIXME verify geometry is as expected
|
||||
return 0;
|
||||
}
|
||||
// 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, 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));
|
||||
}
|
||||
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, 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("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, 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("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));
|
||||
}
|
||||
|
||||
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("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, BadBorderBitsRejected) {
|
||||
panelreel_options p{};
|
||||
p.bordermask = NCBOXMASK_LEFT * 2;
|
||||
struct panelreel* pr = panelreel_create(n_, &p, -1);
|
||||
ASSERT_EQ(nullptr, pr);
|
||||
}
|
||||
SUBCASE("BadBorderBitsRejected") {
|
||||
panelreel_options p{};
|
||||
p.bordermask = NCBOXMASK_LEFT * 2;
|
||||
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);
|
||||
}
|
||||
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, NoTopBottomBorder) {
|
||||
panelreel_options p{};
|
||||
p.bordermask = NCBOXMASK_TOP | NCBOXMASK_BOTTOM;
|
||||
struct panelreel* pr = panelreel_create(n_, &p, -1);
|
||||
ASSERT_NE(nullptr, pr);
|
||||
}
|
||||
SUBCASE("NoTopBottomBorder") {
|
||||
panelreel_options p{};
|
||||
p.bordermask = NCBOXMASK_TOP | NCBOXMASK_BOTTOM;
|
||||
struct panelreel* pr = panelreel_create(n_, &p, -1);
|
||||
REQUIRE(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("NoSideBorders") {
|
||||
panelreel_options p{};
|
||||
p.bordermask = NCBOXMASK_LEFT | NCBOXMASK_RIGHT;
|
||||
struct panelreel* pr = panelreel_create(n_, &p, -1);
|
||||
REQUIRE(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("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;
|
||||
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;
|
||||
}
|
||||
/*
|
||||
// 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;
|
||||
}
|
||||
|
||||
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("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));
|
||||
}
|
||||
|
||||
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("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));
|
||||
}
|
||||
|
||||
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("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
|
||||
}
|
||||
|
||||
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
|
||||
CHECK(0 == notcurses_stop(nc_));
|
||||
CHECK(0 == fclose(outfp_));
|
||||
}
|
||||
|
Loading…
Reference in New Issue