/*********************************************************************** * ftermopenbsd-test.cpp - FTermOpenBSD unit tests * * * * This file is part of the FINAL CUT widget toolkit * * * * Copyright 2019-2021 Markus Gans * * * * FINAL CUT is free software; you can redistribute it and/or modify * * it under the terms of the GNU Lesser General Public License as * * published by the Free Software Foundation; either version 3 of * * the License, or (at your option) any later version. * * * * FINAL CUT is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU Lesser General Public License for more details. * * * * You should have received a copy of the GNU Lesser General Public * * License along with this program. If not, see * * . * ***********************************************************************/ #include #undef buttons // from term.h #include #include #include #include #include #include #include #include #include #include #include #include #define CPPUNIT_ASSERT_CSTRING(expected, actual) \ check_c_string (expected, actual, CPPUNIT_SOURCELINE()) //---------------------------------------------------------------------- void check_c_string ( const char* s1 , const char* s2 , CppUnit::SourceLine sourceLine ) { if ( s1 == 0 && s2 == 0 ) // Strings are equal return; if ( s1 && s2 && std::strcmp (s1, s2) == 0 ) // Strings are equal return; ::CppUnit::Asserter::fail ("Strings are not equal", sourceLine); } namespace test { //---------------------------------------------------------------------- // class FSystemTest //---------------------------------------------------------------------- class FSystemTest : public finalcut::FSystem { public: // Constructor FSystemTest(); // Destructor virtual ~FSystemTest(); // Methods uChar inPortByte (uShort) override; void outPortByte (uChar, uShort) override; int isTTY (int) const override; int ioctl (int, uLong, ...) override; int open (const char*, int, ...) override; int close (int) override; FILE* fopen (const char*, const char*) override; int fclose (FILE*) override; int putchar (int) override; uid_t getuid() override; uid_t geteuid() override; int getpwuid_r (uid_t, struct passwd*, char* , size_t, struct passwd** ) override; char* realpath (const char*, char*) override; wskbd_bell_data& getBell(); private: kbd_t kbdencoding{512}; wskbd_bell_data system_bell{}; }; // constructors and destructor //---------------------------------------------------------------------- FSystemTest::FSystemTest() // constructor { // Initialize bell values system_bell.which = 0; system_bell.pitch = 1500; system_bell.period = 100; system_bell.volume = 50; } //---------------------------------------------------------------------- FSystemTest::~FSystemTest() // destructor { } // public methods of FSystemTest //---------------------------------------------------------------------- uChar FSystemTest::inPortByte (uShort) { return 0; } //---------------------------------------------------------------------- void FSystemTest::outPortByte (uChar, uShort) { } //---------------------------------------------------------------------- int FSystemTest::isTTY (int fd) const { std::cerr << "Call: isatty (fd=" << fd << ")\n"; return 1; } //---------------------------------------------------------------------- int FSystemTest::ioctl (int fd, uLong request, ...) { va_list args{}; void* argp{}; std::string req_string{}; int ret_val{-1}; va_start (args, request); argp = va_arg (args, void*); switch ( request ) { case WSKBDIO_GETENCODING: { req_string = "WSKBDIO_GETENCODING"; kbd_t* kbd_enc = static_cast(argp); *kbd_enc = kbdencoding; ret_val = 0; break; } case WSKBDIO_SETENCODING: { req_string = "WSKBDIO_SETENCODING"; kbd_t* kbd_enc = static_cast(argp); kbdencoding = *kbd_enc; ret_val = 0; break; } case WSKBDIO_GETDEFAULTBELL: { req_string = "WSKBDIO_GETDEFAULTBELL"; wskbd_bell_data* spk = static_cast(argp); spk->which = 0; spk->pitch = 1500; spk->period = 100; spk->volume = 50; ret_val = 0; break; } case WSKBDIO_SETBELL: { req_string = "WSKBDIO_SETBELL"; wskbd_bell_data* spk = static_cast(argp); if ( spk->which & WSKBD_BELL_DOPITCH ) system_bell.pitch = spk->pitch; else system_bell.pitch = 1500; if ( spk->which & WSKBD_BELL_DOPERIOD ) system_bell.period = spk->period; else system_bell.period = 100; if ( spk->which & WSKBD_BELL_DOVOLUME ) system_bell.volume = spk->volume; else system_bell.volume = 50; spk->which = WSKBD_BELL_DOALL; ret_val = 0; break; } case TIOCGWINSZ: req_string = "TIOCGWINSZ"; struct winsize* win_size = static_cast(argp); win_size->ws_col = 80; win_size->ws_row = 25; ret_val = 0; break; } va_end (args); std::cerr << "Call: ioctl (fd=" << fd << ", request=" << req_string << "(0x" << std::hex << request << ")" << ", argp=" << argp << std::dec << ")\n"; return ret_val; } //---------------------------------------------------------------------- int FSystemTest::open (const char* pathname, int flags, ...) { va_list args{}; va_start (args, flags); mode_t mode = static_cast(va_arg (args, int)); va_end (args); std::cerr << "Call: open (pathname=\"" << pathname << "\", flags=" << flags << ", mode=" << mode << ")\n"; return 0; } //---------------------------------------------------------------------- int FSystemTest::close (int fildes) { std::cerr << "Call: close (fildes=" << fildes << ")\n"; return 0; } //---------------------------------------------------------------------- FILE* FSystemTest::fopen (const char* path, const char* mode) { std::cerr << "Call: fopen (path=" << path << ", mode=" << mode << ")\n"; return 0; } //---------------------------------------------------------------------- int FSystemTest::fclose (FILE* fp) { std::cerr << "Call: fclose (fp=" << fp << ")\n"; return 0; } //---------------------------------------------------------------------- int FSystemTest::putchar (int c) { #if defined(__sun) && defined(__SVR4) return std::putchar(char(c)); #else return std::putchar(c); #endif } //---------------------------------------------------------------------- uid_t FSystemTest::getuid() { return 0; } //---------------------------------------------------------------------- uid_t FSystemTest::geteuid() { return 0; } //---------------------------------------------------------------------- int FSystemTest::getpwuid_r ( uid_t, struct passwd*, char* , size_t, struct passwd** ) { return 0; } //---------------------------------------------------------------------- char* FSystemTest::realpath (const char*, char*) { return const_cast(""); } //---------------------------------------------------------------------- wskbd_bell_data& FSystemTest::getBell() { return system_bell; } } // namespace test //---------------------------------------------------------------------- // class ftermopenbsdTest //---------------------------------------------------------------------- class ftermopenbsdTest : public CPPUNIT_NS::TestFixture, test::ConEmu { public: ftermopenbsdTest(); protected: void classNameTest(); void netbsdConsoleTest(); void openbsdConsoleTest(); private: // Adds code needed to register the test suite CPPUNIT_TEST_SUITE (ftermopenbsdTest); // Add a methods to the test suite CPPUNIT_TEST (classNameTest); CPPUNIT_TEST (netbsdConsoleTest); CPPUNIT_TEST (openbsdConsoleTest); // End of test suite definition CPPUNIT_TEST_SUITE_END(); }; //---------------------------------------------------------------------- ftermopenbsdTest::ftermopenbsdTest() { } //---------------------------------------------------------------------- void ftermopenbsdTest::classNameTest() { const finalcut::FTermOpenBSD p{}; const finalcut::FString& classname = p.getClassName(); CPPUNIT_ASSERT ( classname == "FTermOpenBSD" ); } //---------------------------------------------------------------------- void ftermopenbsdTest::netbsdConsoleTest() { std::unique_ptr fsys = finalcut::make_unique(); finalcut::FTerm::setFSystem(fsys); std::cout << "\n"; auto& data = finalcut::FTerm::getFTermData(); auto& encoding_list = data.getEncodingList(); encoding_list["UTF-8"] = finalcut::Encoding::UTF8; encoding_list["UTF8"] = finalcut::Encoding::UTF8; encoding_list["VT100"] = finalcut::Encoding::VT100; encoding_list["PC"] = finalcut::Encoding::PC; encoding_list["ASCII"] = finalcut::Encoding::ASCII; data.setTermEncoding(finalcut::Encoding::VT100); data.setBaudrate(9600); data.setTermType("wsvt25"); data.setTermFileName("/dev/ttyE1"); data.setTTYFileDescriptor(0); data.supportShadowCharacter (false); data.supportHalfBlockCharacter (false); data.supportCursorOptimisation (true); data.setCursorHidden (true); data.useAlternateScreen (false); data.setASCIIConsole (true); data.setVT100Console (false); data.setUTF8Console (false); data.setUTF8 (false); data.setNewFont (false); data.setVGAFont (false); data.setMonochron (false); data.setTermResized (false); // setupterm is needed for tputs in ncurses >= 6.1 setupterm (static_cast(0), 1, static_cast(0)); auto& term_detection = finalcut::FTerm::getFTermDetection(); term_detection.setTerminalDetection(true); pid_t pid = forkConEmu(); if ( isConEmuChildProcess(pid) ) { // (gdb) set follow-fork-mode child finalcut::FTermOpenBSD netbsd; setenv ("TERM", "wsvt25", 1); setenv ("COLUMNS", "80", 1); setenv ("LINES", "25", 1); unsetenv("TERMCAP"); unsetenv("COLORTERM"); unsetenv("COLORFGBG"); unsetenv("VTE_VERSION"); unsetenv("XTERM_VERSION"); unsetenv("ROXTERM_ID"); unsetenv("KONSOLE_DBUS_SESSION"); unsetenv("KONSOLE_DCOP"); unsetenv("TMUX"); netbsd.disableMetaSendsEscape(); netbsd.init(); term_detection.detect(); finalcut::FTerm::detectTermSize(); #if DEBUG const finalcut::FString& sec_da = \ finalcut::FTerm::getFTermDebugData().getSecDAString(); CPPUNIT_ASSERT ( sec_da == "\033[>24;20;0c" ); #endif CPPUNIT_ASSERT ( isatty(0) == 1 ); CPPUNIT_ASSERT ( ! term_detection.isOpenBSDTerm() ); CPPUNIT_ASSERT ( term_detection.isNetBSDTerm() ); CPPUNIT_ASSERT ( data.getTermGeometry().getWidth() == 80 ); CPPUNIT_ASSERT ( data.getTermGeometry().getHeight() == 25 ); CPPUNIT_ASSERT ( ! data.hasShadowCharacter() ); CPPUNIT_ASSERT ( ! data.hasHalfBlockCharacter() ); netbsd.finish(); netbsd.enableMetaSendsEscape(); netbsd.init(); CPPUNIT_ASSERT ( isatty(0) == 1 ); CPPUNIT_ASSERT ( ! term_detection.isOpenBSDTerm() ); CPPUNIT_ASSERT ( term_detection.isNetBSDTerm() ); CPPUNIT_ASSERT ( data.getTermGeometry().getWidth() == 80 ); CPPUNIT_ASSERT ( data.getTermGeometry().getHeight() == 25 ); CPPUNIT_ASSERT ( ! data.hasShadowCharacter() ); CPPUNIT_ASSERT ( ! data.hasHalfBlockCharacter() ); netbsd.finish(); closeConEmuStdStreams(); exit(EXIT_SUCCESS); } else // Parent { // Start the terminal emulation startConEmuTerminal (ConEmu::console::netbsd_con); if ( waitpid(pid, 0, WUNTRACED) != pid ) std::cerr << "waitpid error" << std::endl; } } //---------------------------------------------------------------------- void ftermopenbsdTest::openbsdConsoleTest() { std::unique_ptr fsys = finalcut::make_unique(); finalcut::FTerm::setFSystem(fsys); std::cout << "\n"; auto& data = finalcut::FTerm::getFTermData(); auto& encoding_list = data.getEncodingList(); encoding_list["UTF-8"] = finalcut::Encoding::UTF8; encoding_list["UTF8"] = finalcut::Encoding::UTF8; encoding_list["VT100"] = finalcut::Encoding::VT100; encoding_list["PC"] = finalcut::Encoding::PC; encoding_list["ASCII"] = finalcut::Encoding::ASCII; data.setTermEncoding(finalcut::Encoding::VT100); data.setBaudrate(9600); data.setTermType("vt220"); data.setTermFileName("/dev/ttyC0"); data.setTTYFileDescriptor(0); data.supportShadowCharacter (false); data.supportHalfBlockCharacter (false); data.supportCursorOptimisation (true); data.setCursorHidden (true); data.useAlternateScreen (false); data.setASCIIConsole (true); data.setVT100Console (false); data.setUTF8Console (false); data.setUTF8 (false); data.setNewFont (false); data.setVGAFont (false); data.setMonochron (false); data.setTermResized (false); // setupterm is needed for tputs in ncurses >= 6.1 setupterm (static_cast(0), 1, static_cast(0)); auto& term_detection = finalcut::FTerm::getFTermDetection(); term_detection.setTerminalDetection(true); pid_t pid = forkConEmu(); if ( isConEmuChildProcess(pid) ) { // (gdb) set follow-fork-mode child finalcut::FTermOpenBSD openbsd; setenv ("TERM", "vt220", 1); setenv ("COLUMNS", "80", 1); setenv ("LINES", "25", 1); unsetenv("TERMCAP"); unsetenv("COLORTERM"); unsetenv("COLORFGBG"); unsetenv("VTE_VERSION"); unsetenv("XTERM_VERSION"); unsetenv("ROXTERM_ID"); unsetenv("KONSOLE_DBUS_SESSION"); unsetenv("KONSOLE_DCOP"); unsetenv("TMUX"); const auto& fsystem = finalcut::FTerm::getFSystem(); auto fsystest = static_cast(fsystem.get()); wskbd_bell_data& speaker = fsystest->getBell(); openbsd.disableMetaSendsEscape(); openbsd.init(); term_detection.detect(); finalcut::FTerm::detectTermSize(); #if DEBUG const finalcut::FString& sec_da = \ finalcut::FTerm::getFTermDebugData().getSecDAString(); CPPUNIT_ASSERT ( sec_da == "\033[>24;20;0c" ); #endif CPPUNIT_ASSERT ( isatty(0) == 1 ); CPPUNIT_ASSERT ( term_detection.isOpenBSDTerm() ); CPPUNIT_ASSERT ( ! term_detection.isNetBSDTerm() ); CPPUNIT_ASSERT ( data.getTermGeometry().getWidth() == 80 ); CPPUNIT_ASSERT ( data.getTermGeometry().getHeight() == 25 ); CPPUNIT_ASSERT ( ! data.hasShadowCharacter() ); CPPUNIT_ASSERT ( ! data.hasHalfBlockCharacter() ); CPPUNIT_ASSERT_CSTRING ( term_detection.getTermType(), "pccon" ); openbsd.finish(); openbsd.enableMetaSendsEscape(); openbsd.init(); CPPUNIT_ASSERT ( isatty(0) == 1 ); CPPUNIT_ASSERT ( term_detection.isOpenBSDTerm() ); CPPUNIT_ASSERT ( ! term_detection.isNetBSDTerm() ); CPPUNIT_ASSERT ( data.getTermGeometry().getWidth() == 80 ); CPPUNIT_ASSERT ( data.getTermGeometry().getHeight() == 25 ); CPPUNIT_ASSERT ( ! data.hasShadowCharacter() ); CPPUNIT_ASSERT ( ! data.hasHalfBlockCharacter() ); CPPUNIT_ASSERT ( speaker.pitch == 1500 ); CPPUNIT_ASSERT ( speaker.period == 100 ); CPPUNIT_ASSERT ( speaker.volume == 50 ); openbsd.setBeep (20, 100); // Hz < 21 CPPUNIT_ASSERT ( speaker.pitch == 1500 ); CPPUNIT_ASSERT ( speaker.period == 100 ); CPPUNIT_ASSERT ( speaker.volume == 50 ); openbsd.setBeep (32767, 100); // Hz > 32766 CPPUNIT_ASSERT ( speaker.pitch == 1500 ); CPPUNIT_ASSERT ( speaker.period == 100 ); CPPUNIT_ASSERT ( speaker.volume == 50 ); openbsd.setBeep (200, -1); // ms < 0 CPPUNIT_ASSERT ( speaker.pitch == 1500 ); CPPUNIT_ASSERT ( speaker.period == 100 ); CPPUNIT_ASSERT ( speaker.volume == 50 ); openbsd.setBeep (200, 2000); // ms > 1999 CPPUNIT_ASSERT ( speaker.pitch == 1500 ); CPPUNIT_ASSERT ( speaker.period == 100 ); CPPUNIT_ASSERT ( speaker.volume == 50 ); openbsd.setBeep (200, 100); // 200 Hz - 100 ms CPPUNIT_ASSERT ( speaker.pitch == 200 ); CPPUNIT_ASSERT ( speaker.period == 100 ); CPPUNIT_ASSERT ( speaker.volume == 50 ); openbsd.resetBeep(); CPPUNIT_ASSERT ( speaker.pitch == 1500 ); CPPUNIT_ASSERT ( speaker.period == 100 ); CPPUNIT_ASSERT ( speaker.volume == 50 ); openbsd.finish(); closeConEmuStdStreams(); exit(EXIT_SUCCESS); } else // Parent { // Start the terminal emulation startConEmuTerminal (ConEmu::console::openbsd_con); if ( waitpid(pid, 0, WUNTRACED) != pid ) std::cerr << "waitpid error" << std::endl; } } // Put the test suite in the registry CPPUNIT_TEST_SUITE_REGISTRATION (ftermopenbsdTest); // The general unit test main part #include