diff options
Diffstat (limited to 'unittests/Editline/EditlineTest.cpp')
| -rw-r--r-- | unittests/Editline/EditlineTest.cpp | 320 |
1 files changed, 0 insertions, 320 deletions
diff --git a/unittests/Editline/EditlineTest.cpp b/unittests/Editline/EditlineTest.cpp deleted file mode 100644 index ffa95560d3e32..0000000000000 --- a/unittests/Editline/EditlineTest.cpp +++ /dev/null @@ -1,320 +0,0 @@ -//===-- EditlineTest.cpp ----------------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#ifndef LLDB_DISABLE_LIBEDIT - -#define EDITLINE_TEST_DUMP_OUTPUT 0 - -#include <stdio.h> -#include <unistd.h> - -#include <memory> -#include <thread> - -#include "gtest/gtest.h" - -#include "lldb/Host/Editline.h" -#include "lldb/Host/FileSystem.h" -#include "lldb/Host/Pipe.h" -#include "lldb/Host/PseudoTerminal.h" -#include "lldb/Utility/Status.h" -#include "lldb/Utility/StringList.h" - -using namespace lldb_private; - -namespace { -const size_t TIMEOUT_MILLIS = 5000; -} - -class FilePointer { -public: - FilePointer() = delete; - - FilePointer(const FilePointer &) = delete; - - FilePointer(FILE *file_p) : _file_p(file_p) {} - - ~FilePointer() { - if (_file_p != nullptr) { - const int close_result = fclose(_file_p); - EXPECT_EQ(0, close_result); - } - } - - operator FILE *() { return _file_p; } - -private: - FILE *_file_p; -}; - -/** - Wraps an Editline class, providing a simple way to feed - input (as if from the keyboard) and receive output from Editline. - */ -class EditlineAdapter { -public: - EditlineAdapter(); - - void CloseInput(); - - bool IsValid() const { return _editline_sp.get() != nullptr; } - - lldb_private::Editline &GetEditline() { return *_editline_sp; } - - bool SendLine(const std::string &line); - - bool SendLines(const std::vector<std::string> &lines); - - bool GetLine(std::string &line, bool &interrupted, size_t timeout_millis); - - bool GetLines(lldb_private::StringList &lines, bool &interrupted, - size_t timeout_millis); - - void ConsumeAllOutput(); - -private: - static bool IsInputComplete(lldb_private::Editline *editline, - lldb_private::StringList &lines, void *baton); - - std::unique_ptr<lldb_private::Editline> _editline_sp; - - PseudoTerminal _pty; - int _pty_master_fd; - int _pty_slave_fd; - - std::unique_ptr<FilePointer> _el_slave_file; -}; - -EditlineAdapter::EditlineAdapter() - : _editline_sp(), _pty(), _pty_master_fd(-1), _pty_slave_fd(-1), - _el_slave_file() { - lldb_private::Status error; - - // Open the first master pty available. - char error_string[256]; - error_string[0] = '\0'; - if (!_pty.OpenFirstAvailableMaster(O_RDWR, error_string, - sizeof(error_string))) { - fprintf(stderr, "failed to open first available master pty: '%s'\n", - error_string); - return; - } - - // Grab the master fd. This is a file descriptor we will: - // (1) write to when we want to send input to editline. - // (2) read from when we want to see what editline sends back. - _pty_master_fd = _pty.GetMasterFileDescriptor(); - - // Open the corresponding slave pty. - if (!_pty.OpenSlave(O_RDWR, error_string, sizeof(error_string))) { - fprintf(stderr, "failed to open slave pty: '%s'\n", error_string); - return; - } - _pty_slave_fd = _pty.GetSlaveFileDescriptor(); - - _el_slave_file.reset(new FilePointer(fdopen(_pty_slave_fd, "rw"))); - EXPECT_FALSE(nullptr == *_el_slave_file); - if (*_el_slave_file == nullptr) - return; - - // Create an Editline instance. - _editline_sp.reset(new lldb_private::Editline("gtest editor", *_el_slave_file, - *_el_slave_file, - *_el_slave_file, false)); - _editline_sp->SetPrompt("> "); - - // Hookup our input complete callback. - _editline_sp->SetIsInputCompleteCallback(IsInputComplete, this); -} - -void EditlineAdapter::CloseInput() { - if (_el_slave_file != nullptr) - _el_slave_file.reset(nullptr); -} - -bool EditlineAdapter::SendLine(const std::string &line) { - // Ensure we're valid before proceeding. - if (!IsValid()) - return false; - - // Write the line out to the pipe connected to editline's input. - ssize_t input_bytes_written = - ::write(_pty_master_fd, line.c_str(), - line.length() * sizeof(std::string::value_type)); - - const char *eoln = "\n"; - const size_t eoln_length = strlen(eoln); - input_bytes_written = - ::write(_pty_master_fd, eoln, eoln_length * sizeof(char)); - - EXPECT_NE(-1, input_bytes_written) << strerror(errno); - EXPECT_EQ(eoln_length * sizeof(char), size_t(input_bytes_written)); - return eoln_length * sizeof(char) == size_t(input_bytes_written); -} - -bool EditlineAdapter::SendLines(const std::vector<std::string> &lines) { - for (auto &line : lines) { -#if EDITLINE_TEST_DUMP_OUTPUT - printf("<stdin> sending line \"%s\"\n", line.c_str()); -#endif - if (!SendLine(line)) - return false; - } - return true; -} - -// We ignore the timeout for now. -bool EditlineAdapter::GetLine(std::string &line, bool &interrupted, - size_t /* timeout_millis */) { - // Ensure we're valid before proceeding. - if (!IsValid()) - return false; - - _editline_sp->GetLine(line, interrupted); - return true; -} - -bool EditlineAdapter::GetLines(lldb_private::StringList &lines, - bool &interrupted, size_t /* timeout_millis */) { - // Ensure we're valid before proceeding. - if (!IsValid()) - return false; - - _editline_sp->GetLines(1, lines, interrupted); - return true; -} - -bool EditlineAdapter::IsInputComplete(lldb_private::Editline *editline, - lldb_private::StringList &lines, - void *baton) { - // We'll call ourselves complete if we've received a balanced set of braces. - int start_block_count = 0; - int brace_balance = 0; - - for (size_t i = 0; i < lines.GetSize(); ++i) { - for (auto ch : lines[i]) { - if (ch == '{') { - ++start_block_count; - ++brace_balance; - } else if (ch == '}') - --brace_balance; - } - } - - return (start_block_count > 0) && (brace_balance == 0); -} - -void EditlineAdapter::ConsumeAllOutput() { - FilePointer output_file(fdopen(_pty_master_fd, "r")); - - int ch; - while ((ch = fgetc(output_file)) != EOF) { -#if EDITLINE_TEST_DUMP_OUTPUT - char display_str[] = {0, 0, 0}; - switch (ch) { - case '\t': - display_str[0] = '\\'; - display_str[1] = 't'; - break; - case '\n': - display_str[0] = '\\'; - display_str[1] = 'n'; - break; - case '\r': - display_str[0] = '\\'; - display_str[1] = 'r'; - break; - default: - display_str[0] = ch; - break; - } - printf("<stdout> 0x%02x (%03d) (%s)\n", ch, ch, display_str); -// putc(ch, stdout); -#endif - } -} - -class EditlineTestFixture : public ::testing::Test { -private: - EditlineAdapter _el_adapter; - std::shared_ptr<std::thread> _sp_output_thread; - -public: - void SetUp() { - FileSystem::Initialize(); - - // We need a TERM set properly for editline to work as expected. - setenv("TERM", "vt100", 1); - - // Validate the editline adapter. - EXPECT_TRUE(_el_adapter.IsValid()); - if (!_el_adapter.IsValid()) - return; - - // Dump output. - _sp_output_thread.reset( - new std::thread([&] { _el_adapter.ConsumeAllOutput(); })); - } - - void TearDown() { - _el_adapter.CloseInput(); - if (_sp_output_thread) - _sp_output_thread->join(); - - FileSystem::Terminate(); - } - - EditlineAdapter &GetEditlineAdapter() { return _el_adapter; } -}; - -TEST_F(EditlineTestFixture, EditlineReceivesSingleLineText) { - // Send it some text via our virtual keyboard. - const std::string input_text("Hello, world"); - EXPECT_TRUE(GetEditlineAdapter().SendLine(input_text)); - - // Verify editline sees what we put in. - std::string el_reported_line; - bool input_interrupted = false; - const bool received_line = GetEditlineAdapter().GetLine( - el_reported_line, input_interrupted, TIMEOUT_MILLIS); - - EXPECT_TRUE(received_line); - EXPECT_FALSE(input_interrupted); - EXPECT_EQ(input_text, el_reported_line); -} - -TEST_F(EditlineTestFixture, EditlineReceivesMultiLineText) { - // Send it some text via our virtual keyboard. - std::vector<std::string> input_lines; - input_lines.push_back("int foo()"); - input_lines.push_back("{"); - input_lines.push_back("printf(\"Hello, world\");"); - input_lines.push_back("}"); - input_lines.push_back(""); - - EXPECT_TRUE(GetEditlineAdapter().SendLines(input_lines)); - - // Verify editline sees what we put in. - lldb_private::StringList el_reported_lines; - bool input_interrupted = false; - - EXPECT_TRUE(GetEditlineAdapter().GetLines(el_reported_lines, - input_interrupted, TIMEOUT_MILLIS)); - EXPECT_FALSE(input_interrupted); - - // Without any auto indentation support, our output should directly match our - // input. - EXPECT_EQ(input_lines.size(), el_reported_lines.GetSize()); - if (input_lines.size() == el_reported_lines.GetSize()) { - for (size_t i = 0; i < input_lines.size(); ++i) - EXPECT_EQ(input_lines[i], el_reported_lines[i]); - } -} - -#endif |
