This is an automated email from the ASF dual-hosted git repository. pnoltes pushed a commit to branch feature/cxx in repository https://gitbox.apache.org/repos/asf/celix.git
commit 7c425db376c8707ee7b80246ee6be7de1d0781e9 Author: Pepijn Noltes <[email protected]> AuthorDate: Mon Jan 7 15:51:24 2019 +0100 CELIX-438: Adds some shell tui gtests --- .travis.yml | 10 +- bundles/pubsub/test/CMakeLists.txt | 1 + bundles/shell/cxx_shell_tui/CMakeLists.txt | 18 ++-- bundles/shell/cxx_shell_tui/gtest/CMakeLists.txt | 9 +- .../cxx_shell_tui/gtest/src/ShellTui_tests.cc | 65 ++++++++++++ .../shell/cxx_shell_tui/include/celix/ShellTui.h | 69 ++++++++++++ bundles/shell/cxx_shell_tui/src/ShellTui.cc | 116 +++++++++++++++++++++ .../shell/cxx_shell_tui/src/ShellTuiActivator.cc | 109 +------------------ 8 files changed, 277 insertions(+), 120 deletions(-) diff --git a/.travis.yml b/.travis.yml index eb92e78..3c0f470 100644 --- a/.travis.yml +++ b/.travis.yml @@ -44,11 +44,11 @@ before_install: - if [ "$TRAVIS_OS_NAME" = "osx" ]; then brew update && brew install lcov libffi zeromq czmq glog cpputest jansson && brew link --force libffi; fi before_script: - - wget https://github.com/cpputest/cpputest/releases/download/v3.8/cpputest-3.8.tar.gz -O /tmp/cpputest.tar.gz - - tar -xzvf /tmp/cpputest.tar.gz -C /tmp - - if [ "$CC" = "clang" ]; then export CXX="clang++"; fi && cd /tmp/cpputest-* && ./configure --prefix=/usr/local && make && sudo make install && cd - - - cd /tmp/cpputest-* && ./configure --prefix=/usr/local && make && sudo make install && cd - - - mkdir build install + - wget https://github.com/cpputest/cpputest/releases/download/v3.8/cpputest-3.8.tar.gz -O /tmp/cpputest.tar.gz + - tar -xzvf /tmp/cpputest.tar.gz -C /tmp + - if [ "$CC" = "clang" ]; then export CXX="clang++"; fi && cd /tmp/cpputest-* && ./configure --prefix=/usr/local && make && sudo make install && cd - + - cd /tmp/cpputest-* && ./configure --prefix=/usr/local && make && sudo make install && cd - + - mkdir build install - export BUILD_OPTIONS=" \ -DBUILD_RSA_REMOTE_SERVICE_ADMIN_DFI=ON \ -DBUILD_DEPLOYMENT_ADMIN=ON \ diff --git a/bundles/pubsub/test/CMakeLists.txt b/bundles/pubsub/test/CMakeLists.txt index 39e5575..5f72d1f 100644 --- a/bundles/pubsub/test/CMakeLists.txt +++ b/bundles/pubsub/test/CMakeLists.txt @@ -86,6 +86,7 @@ add_celix_container(pubsub_udpmc_tst DIR ${PROJECT_BINARY_DIR}/runtimes/test/pubsub/udpmc LAUNCHER celix_test_runner ) + add_celix_container(pubsub_zmq_tst NAME deploy_tst BUNDLES diff --git a/bundles/shell/cxx_shell_tui/CMakeLists.txt b/bundles/shell/cxx_shell_tui/CMakeLists.txt index d5b65f7..97d98b5 100644 --- a/bundles/shell/cxx_shell_tui/CMakeLists.txt +++ b/bundles/shell/cxx_shell_tui/CMakeLists.txt @@ -15,19 +15,25 @@ # specific language governing permissions and limitations # under the License. -#TODO rename to celix::shell_tui +add_library(shell_tui_static STATIC + src/ShellTui.cc +) +target_include_directories(shell_tui_static PUBLIC include) +target_link_libraries(shell_tui_static PRIVATE celix_framework_cxx glog::glog celix_cxx_shell_api) +target_compile_options(shell_tui_static PRIVATE -fPIC) + #OR static lib, but then with all symbols to force constructor attribute add_library(celix_cxx_shell_tui SHARED src/ShellTuiActivator.cc - src/shell_test.cc) +) target_include_directories(celix_cxx_shell_tui PRIVATE src) -target_link_libraries(celix_cxx_shell_tui PRIVATE celix_cxx_shell_api glog::glog) +target_link_libraries(celix_cxx_shell_tui PRIVATE shell_tui_static celix_cxx_shell_api glog::glog) target_link_libraries(celix_cxx_shell_tui PUBLIC celix_framework_cxx) -#if (ENABLE_TESTING) -# add_subdirectory(gtest) -#endif () +if (ENABLE_TESTING) + add_subdirectory(gtest) +endif () add_executable(shell_test diff --git a/bundles/shell/cxx_shell_tui/gtest/CMakeLists.txt b/bundles/shell/cxx_shell_tui/gtest/CMakeLists.txt index b4a7204..7626eb5 100644 --- a/bundles/shell/cxx_shell_tui/gtest/CMakeLists.txt +++ b/bundles/shell/cxx_shell_tui/gtest/CMakeLists.txt @@ -17,9 +17,10 @@ set(SOURCES src/main.cc + src/ShellTui_tests.cc ) -add_executable(celix_shell_cxx_tests ${SOURCES}) -target_link_libraries(celix_shell_cxx_tests PRIVATE gtest celix_framework_cxx celix_shell_cxx) +add_executable(celix_cxx_shell_tui_tests ${SOURCES}) +target_link_libraries(celix_cxx_shell_tui_tests PRIVATE gtest celix_framework_cxx shell_tui_static celix_cxx_shell_api) -add_test(NAME celix_shell_cxx_tests COMMAND celix_shell_cxx_tests) -SETUP_TARGET_FOR_COVERAGE(celix_shell_cxx_tests_cov celix_shell_cxx_tests ${CMAKE_BINARY_DIR}/coverage/celix_shell_cxx_tests/celix_shell_cxx_tests) \ No newline at end of file +add_test(NAME celix_cxx_shell_tui_tests COMMAND celix_cxx_shell_tui_tests) +SETUP_TARGET_FOR_COVERAGE(celix_cxx_shell_tui_tests_cov celix_cxx_shell_tui_tests ${CMAKE_BINARY_DIR}/coverage/celix_cxx_shell_tui_tests/celix_cxx_shell_tui_tests ..) \ No newline at end of file diff --git a/bundles/shell/cxx_shell_tui/gtest/src/ShellTui_tests.cc b/bundles/shell/cxx_shell_tui/gtest/src/ShellTui_tests.cc new file mode 100644 index 0000000..6989f27 --- /dev/null +++ b/bundles/shell/cxx_shell_tui/gtest/src/ShellTui_tests.cc @@ -0,0 +1,65 @@ +/** + *Licensed to the Apache Software Foundation (ASF) under one + *or more contributor license agreements. See the NOTICE file + *distributed with this work for additional information + *regarding copyright ownership. The ASF licenses this file + *to you under the Apache License, Version 2.0 (the + *"License"); you may not use this file except in compliance + *with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + *Unless required by applicable law or agreed to in writing, + *software distributed under the License is distributed on an + *"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + *specific language governing permissions and limitations + *under the License. + */ + +#include <sstream> + +#include "gtest/gtest.h" + +#include "celix/api.h" +#include "celix/ShellTui.h" + +class ShellTuiTest : public ::testing::Test { +public: + ShellTuiTest() {} + ~ShellTuiTest(){} + + celix::Framework& framework() { return fw; } +private: + celix::Framework fw{}; +}; + + + + +TEST_F(ShellTuiTest, AcceptCommand) { + { + std::stringstream stream{}; + celix::ShellTui tui{&stream, &stream}; + usleep(100000);//IMPROVE, for now wait till stdin reading thread is started + + stream.flush(); + std::string output = stream.str(); + size_t pos = output.find("->"); //prompt should be printed + EXPECT_LE(pos, output.size()); + } + + //TODO make working +// { +// std::stringstream stream{}; +// celix::ShellTui tui{&stream, &stream}; +// std::string cmd = "lb\n"; +// write(STDIN_FILENO, cmd.c_str(), cmd.size()); +// usleep(100000);//IMPROVE, for now wait till stdin command is processed on other thread. +// stream.flush(); +// std::string output = stream.str(); +// size_t pos = output.find("1: Framework"); //expect lb result +// EXPECT_LE(pos, output.size()); +// } + +} \ No newline at end of file diff --git a/bundles/shell/cxx_shell_tui/include/celix/ShellTui.h b/bundles/shell/cxx_shell_tui/include/celix/ShellTui.h new file mode 100644 index 0000000..67db882 --- /dev/null +++ b/bundles/shell/cxx_shell_tui/include/celix/ShellTui.h @@ -0,0 +1,69 @@ +/** + *Licensed to the Apache Software Foundation (ASF) under one + *or more contributor license agreements. See the NOTICE file + *distributed with this work for additional information + *regarding copyright ownership. The ASF licenses this file + *to you under the Apache License, Version 2.0 (the + *"License"); you may not use this file except in compliance + *with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + *Unless required by applicable law or agreed to in writing, + *software distributed under the License is distributed on an + *"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + *specific language governing permissions and limitations + *under the License. + */ + +#ifndef CELIX_SHELLTUI_H +#define CELIX_SHELLTUI_H + +#include <sstream> +#include <mutex> +#include <thread> + +#include "celix/api.h" +#include "celix/IShellCommand.h" +#include "celix/IShell.h" + + + + +namespace celix { + static constexpr int SHELL_TUI_LINE_SIZE = 256; + + class ShellTui { + public: + ShellTui(std::ostream *_outStream, std::ostream *_errStream); + ~ShellTui(); + + ShellTui(const ShellTui&) = delete; + ShellTui& operator=(const ShellTui&) = delete; + + void setShell(std::shared_ptr<celix::IShell> _shell); + private: + void runnable(); + void writePrompt(); + void parseInput(); + + std::ostream * const outStream; + std::ostream * const errStream; + + std::mutex mutex{}; + std::shared_ptr<celix::IShell> shell{}; + + std::thread readThread{}; + + int readPipeFd{}; + int writePipeFd{}; + + + char in[SHELL_TUI_LINE_SIZE+1]{}; + char buffer[SHELL_TUI_LINE_SIZE+1]{}; + int pos{}; + }; +} + +#endif //CELIX_SHELLTUI_H diff --git a/bundles/shell/cxx_shell_tui/src/ShellTui.cc b/bundles/shell/cxx_shell_tui/src/ShellTui.cc new file mode 100644 index 0000000..d9358d3 --- /dev/null +++ b/bundles/shell/cxx_shell_tui/src/ShellTui.cc @@ -0,0 +1,116 @@ +/** + *Licensed to the Apache Software Foundation (ASF) under one + *or more contributor license agreements. See the NOTICE file + *distributed with this work for additional information + *regarding copyright ownership. The ASF licenses this file + *to you under the Apache License, Version 2.0 (the + *"License"); you may not use this file except in compliance + *with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + *Unless required by applicable law or agreed to in writing, + *software distributed under the License is distributed on an + *"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + *specific language governing permissions and limitations + *under the License. + */ + + +#include "celix/ShellTui.h" + +#include <memory> +#include <sstream> + +#include <thread> +#include <cstdio> +#include <unistd.h> +#include <fcntl.h> +#include <mutex> + +#include <glog/logging.h> + +#include "celix/api.h" +#include "celix/IShellCommand.h" +#include "celix/IShell.h" + +static constexpr const char * const PROMPT = "-> "; +static constexpr int KEY_ENTER = '\n'; + +celix::ShellTui::ShellTui(std::ostream *_outStream, std::ostream *_errStream) : outStream{_outStream}, errStream{_errStream} { + int fds[2]; + int rc = pipe(fds); + if (rc == 0) { + readPipeFd = fds[0]; + writePipeFd = fds[1]; + if(fcntl(writePipeFd, F_SETFL, O_NONBLOCK) == 0) { + readThread = std::thread{&ShellTui::runnable, this}; + } else { + LOG(ERROR) << "fcntl on pipe failed" << std::endl; + } + } else { + LOG(ERROR) << "fcntl on pipe failed" << std::endl; + } +} + + +celix::ShellTui::~ShellTui() { + write(writePipeFd, "\0", 1); //trigger select to stop + readThread.join(); +} + +void celix::ShellTui::runnable() { + //setup file descriptors + fd_set rfds; + int nfds = writePipeFd > STDIN_FILENO ? (writePipeFd +1) : (STDIN_FILENO + 1); + + for (;;) { + writePrompt(); + FD_ZERO(&rfds); + FD_SET(STDIN_FILENO, &rfds); + FD_SET(readPipeFd, &rfds); + + if (select(nfds, &rfds, NULL, NULL, NULL) > 0) { + if (FD_ISSET(readPipeFd, &rfds)) { + break; //something is written to the pipe -> exit thread + } else if (FD_ISSET(STDIN_FILENO, &rfds)) { + parseInput(); + } + } + } +} + +void celix::ShellTui::writePrompt() { + *outStream << PROMPT; + std::flush(*outStream); + outStream->flush(); +} + +void celix::ShellTui::parseInput() { + char* line = NULL; + int nr_chars = (int)read(STDIN_FILENO, buffer, SHELL_TUI_LINE_SIZE-pos-1); + for (int bufpos = 0; bufpos < nr_chars; bufpos++) { + if (buffer[bufpos] == KEY_ENTER) { //end of line -> forward command + line = in; // todo trim string + std::lock_guard<std::mutex> lck{mutex}; + if (shell) { + shell->executeCommandLine(line, *outStream, *errStream); + } else { + *errStream << "Shell service not available\n"; + } + pos = 0; + in[pos] = '\0'; + } else { //text + in[pos] = buffer[bufpos]; + in[pos + 1] = '\0'; + pos++; + continue; + } + } //for +} + +void celix::ShellTui::setShell(std::shared_ptr<celix::IShell> _shell) { + std::lock_guard<std::mutex> lck{mutex}; + shell = std::move(_shell); +} \ No newline at end of file diff --git a/bundles/shell/cxx_shell_tui/src/ShellTuiActivator.cc b/bundles/shell/cxx_shell_tui/src/ShellTuiActivator.cc index 0958ab0..70b3cce 100644 --- a/bundles/shell/cxx_shell_tui/src/ShellTuiActivator.cc +++ b/bundles/shell/cxx_shell_tui/src/ShellTuiActivator.cc @@ -17,126 +17,25 @@ *under the License. */ -#include <thread> -#include <cstdio> -#include <unistd.h> -#include <fcntl.h> -#include <mutex> - -#include <glog/logging.h> +#include <iostream> #include "celix/api.h" #include "celix/IShellCommand.h" #include "celix/IShell.h" -static constexpr int LINE_SIZE = 256; -static constexpr const char * const PROMPT = "-> "; - -static constexpr int KEY_ENTER = '\n'; +#include "celix/ShellTui.h" namespace { - class ShellTui { - public: - ShellTui() { - int fds[2]; - int rc = pipe(fds); - if (rc == 0) { - readPipeFd = fds[0]; - writePipeFd = fds[1]; - if(fcntl(writePipeFd, F_SETFL, O_NONBLOCK) == 0) { - readThread = std::thread{&ShellTui::runnable, this}; - } else { - LOG(ERROR) << "fcntl on pipe failed" << std::endl; - } - } else { - LOG(ERROR) << "fcntl on pipe failed" << std::endl; - } - } - - ~ShellTui() { - write(writePipeFd, "\0", 1); //trigger select to stop - readThread.join(); - } - - void runnable() { - //setup file descriptors - fd_set rfds; - int nfds = writePipeFd > STDIN_FILENO ? (writePipeFd +1) : (STDIN_FILENO + 1); - - for (;;) { - writePrompt(); - FD_ZERO(&rfds); - FD_SET(STDIN_FILENO, &rfds); - FD_SET(readPipeFd, &rfds); - - if (select(nfds, &rfds, NULL, NULL, NULL) > 0) { - if (FD_ISSET(readPipeFd, &rfds)) { - break; //something is written to the pipe -> exit thread - } else if (FD_ISSET(STDIN_FILENO, &rfds)) { - parseInput(); - } - } - } - } - - void writePrompt() { - std::cout << PROMPT; - std::flush(std::cout); - } - - void parseInput() { - char* line = NULL; - int nr_chars = (int)read(STDIN_FILENO, buffer, LINE_SIZE-pos-1); - for (int bufpos = 0; bufpos < nr_chars; bufpos++) { - if (buffer[bufpos] == KEY_ENTER) { //end of line -> forward command - line = in; // todo trim string - std::lock_guard<std::mutex> lck{mutex}; - if (shell) { - shell->executeCommandLine(line, std::cout, std::cerr); - } else { - std::cerr << "Shell service not available\n"; - } - pos = 0; - in[pos] = '\0'; - } else { //text - in[pos] = buffer[bufpos]; - in[pos + 1] = '\0'; - pos++; - continue; - } - } //for - } - - void setShell(std::shared_ptr<celix::IShell> _shell) { - std::lock_guard<std::mutex> lck{mutex}; - shell = _shell; - } - private: - std::mutex mutex{}; - std::shared_ptr<celix::IShell> shell{}; - - std::thread readThread{}; - - int readPipeFd{}; - int writePipeFd{}; - - - char in[LINE_SIZE+1]{}; - char buffer[LINE_SIZE+1]{}; - int pos{}; - }; - - class ShellTuiBundleActivator : public celix::IBundleActivator { public: ShellTuiBundleActivator(std::shared_ptr<celix::BundleContext> ctx) { celix::ServiceTrackerOptions<celix::IShell> opts{}; - opts.set = std::bind(&ShellTui::setShell, &tui, std::placeholders::_1); + opts.set = std::bind(&celix::ShellTui::setShell, &tui, std::placeholders::_1); trk = ctx->trackServices(opts); } private: - ShellTui tui{}; + celix::ShellTui tui{&std::cout, &std::cerr}; celix::ServiceTracker trk{}; };
