mgorny created this revision.
mgorny added reviewers: labath, emaste, krytarowski, teemperor, JDevlieghere.
mgorny requested review of this revision.

https://reviews.llvm.org/D110962

Files:
  lldb/unittests/Host/CMakeLists.txt
  lldb/unittests/Host/TerminalTest.cpp

Index: lldb/unittests/Host/TerminalTest.cpp
===================================================================
--- /dev/null
+++ lldb/unittests/Host/TerminalTest.cpp
@@ -0,0 +1,135 @@
+//===-- TerminalTest.cpp --------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/Host/Terminal.h"
+
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+
+#if defined(__linux__)
+#include <pty.h>
+#elif defined(__FreeBSD__)
+#include <libutil.h>
+#else // Darwin, NetBSD, OpenBSD
+#include <util.h>
+#endif
+#include <termios.h>
+#include <unistd.h>
+
+using namespace lldb_private;
+
+class TerminalTest : public ::testing::Test {
+protected:
+  int m_master;
+  int m_slave;
+
+  void SetUp() override {
+    ASSERT_EQ(openpty(&m_master, &m_slave, nullptr, nullptr, nullptr), 0);
+  }
+
+  void TearDown() override {
+    close(m_slave);
+    close(m_master);
+  }
+};
+
+TEST_F(TerminalTest, PtyIsATerminal) {
+  Terminal term{m_slave};
+  EXPECT_EQ(term.IsATerminal(), true);
+}
+
+TEST_F(TerminalTest, PipeIsNotATerminal) {
+  int pipefd[2];
+  ASSERT_EQ(pipe(pipefd), 0);
+  Terminal pipeterm{pipefd[0]};
+  EXPECT_EQ(pipeterm.IsATerminal(), false);
+  close(pipefd[0]);
+  close(pipefd[1]);
+}
+
+TEST_F(TerminalTest, SetEcho) {
+  struct termios terminfo;
+  Terminal term{m_slave};
+
+  ASSERT_EQ(term.SetEcho(true), true);
+  ASSERT_EQ(tcgetattr(m_slave, &terminfo), 0);
+  EXPECT_NE(terminfo.c_lflag & ECHO, 0U);
+
+  ASSERT_EQ(term.SetEcho(false), true);
+  ASSERT_EQ(tcgetattr(m_slave, &terminfo), 0);
+  EXPECT_EQ(terminfo.c_lflag & ECHO, 0U);
+}
+
+TEST_F(TerminalTest, SetCanonical) {
+  struct termios terminfo;
+  Terminal term{m_slave};
+
+  ASSERT_EQ(term.SetCanonical(true), true);
+  ASSERT_EQ(tcgetattr(m_slave, &terminfo), 0);
+  EXPECT_NE(terminfo.c_lflag & ICANON, 0U);
+
+  ASSERT_EQ(term.SetCanonical(false), true);
+  ASSERT_EQ(tcgetattr(m_slave, &terminfo), 0);
+  EXPECT_EQ(terminfo.c_lflag & ICANON, 0U);
+}
+
+TEST_F(TerminalTest, SaveRestoreRAII) {
+  struct termios orig_terminfo;
+  struct termios terminfo;
+  ASSERT_EQ(tcgetattr(m_slave, &orig_terminfo), 0);
+
+  Terminal term{m_slave};
+
+  {
+    TerminalState term_state{term};
+    terminfo = orig_terminfo;
+
+    // make some arbitrary changes
+    terminfo.c_iflag ^= IGNPAR | INLCR;
+    terminfo.c_oflag ^= OPOST | OCRNL;
+    terminfo.c_cflag ^= PARENB | PARODD;
+    terminfo.c_lflag ^= ICANON | ECHO;
+    terminfo.c_cc[VEOF] ^= 8;
+    terminfo.c_cc[VEOL] ^= 4;
+    cfsetispeed(&terminfo, B9600);
+    cfsetospeed(&terminfo, B9600);
+
+    ASSERT_EQ(tcsetattr(m_slave, TCSANOW, &terminfo), 0);
+  }
+
+  ASSERT_EQ(tcgetattr(m_slave, &terminfo), 0);
+  ASSERT_EQ(memcmp(&terminfo, &orig_terminfo, sizeof(terminfo)), 0);
+}
+
+TEST_F(TerminalTest, SaveRestore) {
+  TerminalState term_state;
+
+  struct termios orig_terminfo;
+  struct termios terminfo;
+  ASSERT_EQ(tcgetattr(m_slave, &orig_terminfo), 0);
+
+  Terminal term{m_slave};
+  term_state.Save(term, false);
+  terminfo = orig_terminfo;
+
+  // make some arbitrary changes
+  terminfo.c_iflag ^= IGNPAR | INLCR;
+  terminfo.c_oflag ^= OPOST | OCRNL;
+  terminfo.c_cflag ^= PARENB | PARODD;
+  terminfo.c_lflag ^= ICANON | ECHO;
+  terminfo.c_cc[VEOF] ^= 8;
+  terminfo.c_cc[VEOL] ^= 4;
+  cfsetispeed(&terminfo, B9600);
+  cfsetospeed(&terminfo, B9600);
+
+  ASSERT_EQ(tcsetattr(m_slave, TCSANOW, &terminfo), 0);
+
+  term_state.Restore();
+  ASSERT_EQ(tcgetattr(m_slave, &terminfo), 0);
+  ASSERT_EQ(memcmp(&terminfo, &orig_terminfo, sizeof(terminfo)), 0);
+}
Index: lldb/unittests/Host/CMakeLists.txt
===================================================================
--- lldb/unittests/Host/CMakeLists.txt
+++ lldb/unittests/Host/CMakeLists.txt
@@ -14,6 +14,7 @@
   SocketTestUtilities.cpp
   XMLTest.cpp
 )
+set (EXTRA_LIBS)
 
 if (CMAKE_SYSTEM_NAME MATCHES "Linux|Android")
   list(APPEND FILES
@@ -22,10 +23,25 @@
   )
 endif()
 
+# TODO: support more systems
+if (LLDB_ENABLE_TERMIOS AND
+    CMAKE_SYSTEM_NAME MATCHES "Darwin|FreeBSD|Linux|NetBSD|OpenBSD")
+  list(APPEND FILES
+    TerminalTest.cpp
+  )
+
+  if (NOT CMAKE_SYSTEM_NAME MATCHES "Darwin")
+    list(APPEND EXTRA_LIBS
+      util
+    )
+  endif()
+endif()
+
 add_lldb_unittest(HostTests
   ${FILES}
   LINK_LIBS
     lldbHost
     lldbUtilityHelpers
     LLVMTestingSupport
+    ${EXTRA_LIBS}
   )
_______________________________________________
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to