mirror of
https://github.com/arun11299/cpp-subprocess.git
synced 2025-09-16 10:44:43 -04:00
Compare commits
57 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
ad47657ddd | ||
![]() |
60d4ad8d52 | ||
![]() |
777cfa77d1 | ||
![]() |
f6232a7f26 | ||
![]() |
9974ff69cd | ||
![]() |
625a877579 | ||
![]() |
ed313971c0 | ||
![]() |
98a88e2499 | ||
![]() |
38d98d9d20 | ||
![]() |
778543b2f2 | ||
![]() |
34033d03de | ||
![]() |
04b015a8e5 | ||
![]() |
2d8a8eebb0 | ||
![]() |
beda7b5244 | ||
![]() |
3afe581c1f | ||
![]() |
4025693dec | ||
![]() |
40cd59c097 | ||
![]() |
40bcc2daa9 | ||
![]() |
06858e5fd7 | ||
![]() |
d19cce111c | ||
![]() |
46d2b244c4 | ||
![]() |
d809374661 | ||
![]() |
64f4dfc2e5 | ||
![]() |
5a8adeb758 | ||
![]() |
af23f33880 | ||
![]() |
d9ed0d606f | ||
![]() |
1392c47cbb | ||
![]() |
cbc9e82158 | ||
![]() |
399616b408 | ||
![]() |
2ef9f168d3 | ||
![]() |
bf4289c1a0 | ||
![]() |
2bec886e79 | ||
![]() |
0218c51b8c | ||
![]() |
fa58db9d6e | ||
![]() |
5f43a237dc | ||
![]() |
718d0c816a | ||
![]() |
dafa7dd36b | ||
![]() |
2f6bb248c6 | ||
![]() |
f1a698b50e | ||
![]() |
a458bcfc4a | ||
![]() |
9c624ce4e3 | ||
![]() |
126ee2978f | ||
![]() |
a5cc965f72 | ||
![]() |
6931e3d69f | ||
![]() |
3ab04aecaa | ||
![]() |
785ff230a8 | ||
![]() |
f6799fcc34 | ||
![]() |
871577770a | ||
![]() |
5d92f48492 | ||
![]() |
de5f791d04 | ||
![]() |
3e29149ad1 | ||
![]() |
e6cb89cb6e | ||
![]() |
d74481c564 | ||
![]() |
7ebcd80c05 | ||
![]() |
ced3d53e3a | ||
![]() |
0894e7f6db | ||
![]() |
899e9b997d |
20
.editorconfig
Normal file
20
.editorconfig
Normal file
@ -0,0 +1,20 @@
|
||||
# EditorConfig is awesome: http://EditorConfig.org
|
||||
|
||||
# top-most EditorConfig file
|
||||
root = true
|
||||
|
||||
# Unix-style newlines with a newline ending every file
|
||||
[*]
|
||||
charset = utf-8
|
||||
indent_style = space
|
||||
indent_size = 4
|
||||
end_of_line = lf
|
||||
|
||||
[*.{c,cppi,cc,h,hpp}]
|
||||
indent_size = 2
|
||||
|
||||
# Tab indentation (no size specified)
|
||||
[Makefile,makefile,GNUmakefile]
|
||||
indent_style = tab
|
||||
|
||||
#[*.{js,py}]
|
76
.github/workflows/cmake-multi-platform.yml
vendored
Normal file
76
.github/workflows/cmake-multi-platform.yml
vendored
Normal file
@ -0,0 +1,76 @@
|
||||
# This starter workflow is for a CMake project running on multiple platforms. There is a different starter workflow if you just want a single platform.
|
||||
# See: https://github.com/actions/starter-workflows/blob/main/ci/cmake-single-platform.yml
|
||||
name: CMake on multiple platforms
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ "master" ]
|
||||
pull_request:
|
||||
branches: [ "master" ]
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ${{ matrix.os }}
|
||||
|
||||
strategy:
|
||||
# Set fail-fast to false to ensure that feedback is delivered for all matrix combinations. Consider changing this to true when your workflow is stable.
|
||||
fail-fast: false
|
||||
|
||||
# Set up a matrix to run the following 3 configurations:
|
||||
# 1. <Windows, Debug, latest MSVC compiler toolchain on the default runner image, default generator>
|
||||
# 2. <Linux, Debug, latest GCC compiler toolchain on the default runner image, default generator>
|
||||
# 3. <Linux, Debug, latest Clang compiler toolchain on the default runner image, default generator>
|
||||
#
|
||||
# To add more build types (Release, Debug, RelWithDebInfo, etc.) customize the build_type list.
|
||||
matrix:
|
||||
os: [ubuntu-latest, windows-latest]
|
||||
build_type: [Debug]
|
||||
c_compiler: [gcc, clang, cl]
|
||||
include:
|
||||
- os: windows-latest
|
||||
c_compiler: cl
|
||||
cpp_compiler: cl
|
||||
- os: ubuntu-latest
|
||||
c_compiler: gcc
|
||||
cpp_compiler: g++
|
||||
- os: ubuntu-latest
|
||||
c_compiler: clang
|
||||
cpp_compiler: clang++
|
||||
exclude:
|
||||
- os: windows-latest
|
||||
c_compiler: gcc
|
||||
- os: windows-latest
|
||||
c_compiler: clang
|
||||
- os: ubuntu-latest
|
||||
c_compiler: cl
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: Set reusable strings
|
||||
# Turn repeated input strings (such as the build output directory) into step outputs. These step outputs can be used throughout the workflow file.
|
||||
id: strings
|
||||
shell: bash
|
||||
run: |
|
||||
echo "build-output-dir=${{ github.workspace }}/build" >> "$GITHUB_OUTPUT"
|
||||
|
||||
- name: Configure CMake
|
||||
# Configure CMake in a 'build' subdirectory. `CMAKE_BUILD_TYPE` is only required if you are using a single-configuration generator such as make.
|
||||
# See https://cmake.org/cmake/help/latest/variable/CMAKE_BUILD_TYPE.html?highlight=cmake_build_type
|
||||
run: >
|
||||
cmake -B ${{ steps.strings.outputs.build-output-dir }}
|
||||
-DCMAKE_CXX_COMPILER=${{ matrix.cpp_compiler }}
|
||||
-DCMAKE_C_COMPILER=${{ matrix.c_compiler }}
|
||||
-DCMAKE_BUILD_TYPE=${{ matrix.build_type }}
|
||||
-DSUBPROCESS_TESTS=ON
|
||||
-S ${{ github.workspace }}
|
||||
|
||||
- name: Build
|
||||
# Build your program with the given configuration. Note that --config is needed because the default Windows generator is a multi-config generator (Visual Studio generator).
|
||||
run: cmake --build ${{ steps.strings.outputs.build-output-dir }} --config ${{ matrix.build_type }}
|
||||
|
||||
- name: Test
|
||||
working-directory: ${{ steps.strings.outputs.build-output-dir }}
|
||||
# Execute tests defined by the CMake configuration. Note that --build-config is needed because the default Windows generator is a multi-config generator (Visual Studio generator).
|
||||
# See https://cmake.org/cmake/help/latest/manual/ctest.1.html for more detail
|
||||
run: ctest --build-config ${{ matrix.build_type }} --timeout 10 -j4
|
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
build
|
||||
.vscode
|
63
CMakeLists.txt
Normal file
63
CMakeLists.txt
Normal file
@ -0,0 +1,63 @@
|
||||
cmake_minimum_required(VERSION 3.5)
|
||||
project(subprocess VERSION 2.2 LANGUAGES CXX)
|
||||
|
||||
set(CMAKE_CXX_STANDARD 11 CACHE STRING "C++ standard to use")
|
||||
option(EXPORT_COMPILE_COMMANDS "create clang compile database" ON)
|
||||
option(SUBPROCESS_TESTS "enable subprocess tests" OFF)
|
||||
option(SUBPROCESS_INSTALL "enable subprocess install" OFF)
|
||||
|
||||
find_package(Threads REQUIRED)
|
||||
|
||||
add_library(subprocess INTERFACE)
|
||||
target_link_libraries(subprocess INTERFACE Threads::Threads)
|
||||
target_sources(subprocess PUBLIC
|
||||
FILE_SET HEADERS
|
||||
FILES
|
||||
cpp-subprocess/subprocess.hpp
|
||||
BASE_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/
|
||||
)
|
||||
add_library(cpp-subprocess::subprocess ALIAS subprocess)
|
||||
|
||||
if(SUBPROCESS_INSTALL)
|
||||
install(
|
||||
TARGETS subprocess COMPONENT subprocess
|
||||
EXPORT subprocess
|
||||
FILE_SET HEADERS DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
|
||||
)
|
||||
|
||||
include(CMakePackageConfigHelpers)
|
||||
|
||||
configure_package_config_file(
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/cmake/subprocess-config.cmake.in"
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/subprocess-config.cmake"
|
||||
INSTALL_DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/subprocess"
|
||||
PATH_VARS PROJECT_NAME PROJECT_VERSION
|
||||
)
|
||||
|
||||
write_basic_package_version_file(
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/beman.exemplar-version.cmake"
|
||||
VERSION ${PROJECT_VERSION}
|
||||
COMPATIBILITY ExactVersion
|
||||
)
|
||||
|
||||
install(
|
||||
FILES
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/subprocess-config.cmake"
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/subprocess-version.cmake"
|
||||
DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/subprocess"
|
||||
COMPONENT subprocess
|
||||
)
|
||||
|
||||
install(
|
||||
EXPORT subprocess
|
||||
DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/beman.exemplar"
|
||||
NAMESPACE cpp-subprocess::
|
||||
FILE subprocess-targets.cmake
|
||||
COMPONENT subprocess
|
||||
)
|
||||
endif()
|
||||
|
||||
if(SUBPROCESS_TESTS)
|
||||
include(CTest)
|
||||
add_subdirectory(test)
|
||||
endif()
|
27
README.md
27
README.md
@ -1,4 +1,4 @@
|
||||
![Subprocessing in C++]
|
||||
## [Subprocessing in C++]
|
||||
|
||||
## Design Goals
|
||||
The only goal was to develop something that is as close as python2.7 subprocess module in dealing with processes.
|
||||
@ -13,14 +13,16 @@ This library had these design goals:
|
||||
|
||||
|
||||
## Supported Platforms
|
||||
Unlike python2.7 subprocess module, this library currently only supports MAC OS and Linux.
|
||||
It has no support for Windows in its current state.
|
||||
This library supports MAC OS and Linux.
|
||||
|
||||
Support for Windows is limited at this time. Please report any specific use-cases that fail,
|
||||
and they will be fixed as they are reported.
|
||||
|
||||
## Integration
|
||||
Subprocess library has just a single source `subprocess.hpp` present at the top directory of this repository. All you need to do is add
|
||||
|
||||
```cpp
|
||||
#inlcude "subprocess.hpp"
|
||||
#include "cpp-subprocess/subprocess.hpp"
|
||||
|
||||
using namespace subprocess;
|
||||
// OR
|
||||
@ -31,9 +33,24 @@ to the files where you want to make use of subprocessing. Make sure to add neces
|
||||
|
||||
Checkout http://templated-thoughts.blogspot.in/2016/03/sub-processing-with-modern-c.html as well.
|
||||
|
||||
## CMake Projects
|
||||
|
||||
```cmake
|
||||
include(FetchContent)
|
||||
FetchContent_Declare(
|
||||
cpp-subprocess
|
||||
GIT_REPOSITORY https://github.com/arun11299/cpp-subprocess.git
|
||||
GIT_TAG v2.2
|
||||
)
|
||||
FetchContent_MakeAvailable(cpp-subprocess)
|
||||
|
||||
target_link_libraries(<your_target> PRIVATE cpp-subprocess::subprocess)
|
||||
```
|
||||
|
||||
## Compiler Support
|
||||
Linux - g++ 4.8 and above
|
||||
Mac OS - Clang 3.4 and later
|
||||
Windows - MSVC 2015 and above
|
||||
|
||||
## Examples
|
||||
Here are few examples to show how to get started:
|
||||
@ -48,7 +65,7 @@ std::cout << "Data len: " << obuf.length << std::endl;
|
||||
|
||||
More detailed way:
|
||||
```cpp
|
||||
auto p = Popen({"ls", "-l"});
|
||||
auto p = Popen({"ls", "-l"}, output{PIPE});
|
||||
auto obuf = p.communicate().first;
|
||||
std::cout << "Data : " << obuf.buf.data() << std::endl;
|
||||
std::cout << "Data len: " << obuf.length << std::endl;
|
||||
|
7
cmake/subprocess-config.cmake
Normal file
7
cmake/subprocess-config.cmake
Normal file
@ -0,0 +1,7 @@
|
||||
set(SUBPROCESS_VERSION @PROJECT_VERSION@)
|
||||
|
||||
@PACKAGE_INIT@
|
||||
|
||||
include(${CMAKE_CURRENT_LIST_DIR}/@PROJECT_NAME@-targets.cmake)
|
||||
|
||||
check_required_components(@PROJECT_NAME@)
|
913
subprocess.hpp → cpp-subprocess/subprocess.hpp
Executable file → Normal file
913
subprocess.hpp → cpp-subprocess/subprocess.hpp
Executable file → Normal file
File diff suppressed because it is too large
Load Diff
35
test/CMakeLists.txt
Normal file
35
test/CMakeLists.txt
Normal file
@ -0,0 +1,35 @@
|
||||
set(test_names test_subprocess test_cat test_double_quotes test_env test_err_redirection test_exception test_split test_main test_ret_code)
|
||||
set(test_files env_script.sh write_err.sh write_err.txt)
|
||||
|
||||
|
||||
foreach(test_name IN LISTS test_names)
|
||||
add_executable(${test_name} ${test_name}.cc)
|
||||
target_link_libraries(${test_name} PRIVATE subprocess)
|
||||
|
||||
add_test(
|
||||
NAME ${test_name}
|
||||
COMMAND $<TARGET_FILE:${test_name}>
|
||||
)
|
||||
endforeach()
|
||||
|
||||
foreach(test_file IN LISTS test_files)
|
||||
configure_file(
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/${test_file}
|
||||
${CMAKE_CURRENT_BINARY_DIR}/${test_file}
|
||||
COPYONLY
|
||||
)
|
||||
endforeach()
|
||||
|
||||
|
||||
set(TEST_REDIRECTION_PYTHON_SCRIPT_PATH ${CMAKE_CURRENT_SOURCE_DIR}/test_redirection.py)
|
||||
configure_file(
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/test_redirection.cc.in
|
||||
${CMAKE_CURRENT_BINARY_DIR}/test_redirection.cc
|
||||
@ONLY
|
||||
)
|
||||
add_executable(test_redirection ${CMAKE_CURRENT_BINARY_DIR}/test_redirection.cc)
|
||||
target_link_libraries(test_redirection PRIVATE subprocess)
|
||||
add_test(
|
||||
NAME test_redirection
|
||||
COMMAND $<TARGET_FILE:test_redirection>
|
||||
)
|
@ -1 +1 @@
|
||||
through stdin to stdoutthrough stdin to stdoutthrough stdin to stdoutthrough stdin to stdout
|
||||
through stdin to stdout
|
@ -1,5 +1,5 @@
|
||||
#include <iostream>
|
||||
#include "../subprocess.hpp"
|
||||
#include <cpp-subprocess/subprocess.hpp>
|
||||
|
||||
namespace sp = subprocess;
|
||||
|
||||
@ -23,6 +23,24 @@ void test_cat_file_redirection()
|
||||
std::cout << "END_TEST" << std::endl;
|
||||
}
|
||||
|
||||
void test_cat_send_terminate()
|
||||
{
|
||||
std::cout << "Test::test_cat_send_terminate" << std::endl;
|
||||
std::vector<sp::Popen> pops;
|
||||
|
||||
for (int i=0; i < 5; i++) {
|
||||
pops.emplace_back(sp::Popen({"cat", "-"}, sp::input{sp::PIPE}));
|
||||
pops[i].send("3 5\n", 5);
|
||||
pops[i].close_input();
|
||||
}
|
||||
|
||||
for (int i=0; i < 5; i++) {
|
||||
pops[i].wait();
|
||||
}
|
||||
|
||||
std::cout << "END_TEST" << std::endl;
|
||||
}
|
||||
|
||||
void test_buffer_growth()
|
||||
{
|
||||
auto obuf = sp::check_output({"cat", "../subprocess.hpp"});
|
||||
@ -40,9 +58,17 @@ void test_buffer_growth_threaded_comm()
|
||||
}
|
||||
|
||||
int main() {
|
||||
test_cat_pipe_redirection();
|
||||
#ifndef __USING_WINDOWS__
|
||||
|
||||
// test_cat_pipe_redirection();
|
||||
test_cat_send_terminate();
|
||||
/*
|
||||
test_cat_file_redirection();
|
||||
test_buffer_growth();
|
||||
test_buffer_growth_threaded_comm();
|
||||
*/
|
||||
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
30
test/test_double_quotes.cc
Normal file
30
test/test_double_quotes.cc
Normal file
@ -0,0 +1,30 @@
|
||||
#include <cpp-subprocess/subprocess.hpp>
|
||||
|
||||
#include <cassert>
|
||||
#include <string>
|
||||
|
||||
namespace sp = subprocess;
|
||||
|
||||
// JSON requires the use of double quotes (see: https://json.org/).
|
||||
// This test verifies proper handling of them.
|
||||
void test_double_quotes()
|
||||
{
|
||||
// A simple JSON object.
|
||||
const std::string expected{"{\"name\": \"value\"}"};
|
||||
#ifdef __USING_WINDOWS__
|
||||
const std::string command{"cmd.exe /c echo "};
|
||||
#else
|
||||
const std::string command{"echo "};
|
||||
#endif
|
||||
auto p = sp::Popen(command + expected, sp::output{sp::PIPE});
|
||||
const auto out = p.communicate().first;
|
||||
std::string result{out.buf.begin(), out.buf.end()};
|
||||
// The `echo` command appends a newline.
|
||||
result.erase(result.find_last_not_of(" \n\r\t") + 1);
|
||||
assert(result == expected);
|
||||
}
|
||||
|
||||
int main() {
|
||||
test_double_quotes();
|
||||
return 0;
|
||||
}
|
@ -1,8 +1,10 @@
|
||||
#include <iostream>
|
||||
#include "../subprocess.hpp"
|
||||
#include <cpp-subprocess/subprocess.hpp>
|
||||
|
||||
using namespace subprocess;
|
||||
|
||||
#ifndef __USING_WINDOWS__
|
||||
|
||||
void test_env()
|
||||
{
|
||||
int st= Popen("./env_script.sh", environment{{
|
||||
@ -13,7 +15,11 @@ void test_env()
|
||||
assert (st == 0);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
int main() {
|
||||
#ifndef __USING_WINDOWS__
|
||||
test_env();
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
#include <iostream>
|
||||
#include "../subprocess.hpp"
|
||||
#include <cpp-subprocess/subprocess.hpp>
|
||||
|
||||
using namespace subprocess;
|
||||
|
||||
@ -11,6 +11,8 @@ void test_redirect()
|
||||
}
|
||||
|
||||
int main() {
|
||||
#ifndef __USING_WINDOWS__
|
||||
test_redirect();
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
27
test/test_exception.cc
Normal file
27
test/test_exception.cc
Normal file
@ -0,0 +1,27 @@
|
||||
#include <cassert>
|
||||
#include <cstring>
|
||||
#include <cpp-subprocess/subprocess.hpp>
|
||||
|
||||
namespace sp = subprocess;
|
||||
|
||||
void test_exception()
|
||||
{
|
||||
bool caught = false;
|
||||
try {
|
||||
auto p = sp::Popen("invalid_command");
|
||||
assert(false); // Expected to throw
|
||||
} catch (sp::CalledProcessError& e) {
|
||||
#ifdef __USING_WINDOWS__
|
||||
assert(std::strstr(e.what(), "CreateProcess failed: The system cannot find the file specified."));
|
||||
#else
|
||||
assert(std::strstr(e.what(), "execve failed: No such file or directory"));
|
||||
#endif
|
||||
caught = true;
|
||||
}
|
||||
assert(caught);
|
||||
}
|
||||
|
||||
int main() {
|
||||
test_exception();
|
||||
return 0;
|
||||
}
|
23
test/test_redirection.cc.in
Normal file
23
test/test_redirection.cc.in
Normal file
@ -0,0 +1,23 @@
|
||||
#include <cpp-subprocess/subprocess.hpp>
|
||||
|
||||
#include <cstdlib>
|
||||
#include <string>
|
||||
#include <tuple>
|
||||
|
||||
using namespace subprocess;
|
||||
|
||||
int main() {
|
||||
auto p = Popen("python3 @TEST_REDIRECTION_PYTHON_SCRIPT_PATH@", output{PIPE}, error{PIPE});
|
||||
OutBuffer out_buf;
|
||||
ErrBuffer err_buf;
|
||||
std::tie(out_buf, err_buf) = p.communicate();
|
||||
std::string out{out_buf.buf.data()};
|
||||
std::string err{err_buf.buf.data()};
|
||||
|
||||
if (out.find("Hello message.") == std::string::npos) return EXIT_FAILURE;
|
||||
if (err.find("Hello message.") != std::string::npos) return EXIT_FAILURE;
|
||||
if (out.find("Error report.") != std::string::npos) return EXIT_FAILURE;
|
||||
if (err.find("Error report.") == std::string::npos) return EXIT_FAILURE;
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
7
test/test_redirection.py
Executable file
7
test/test_redirection.py
Executable file
@ -0,0 +1,7 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
import sys
|
||||
|
||||
if __name__ == "__main__":
|
||||
print("Hello message.")
|
||||
print("Error report.", file=sys.stderr)
|
@ -1,14 +1,26 @@
|
||||
#include <iostream>
|
||||
#include "../subprocess.hpp"
|
||||
#include <cpp-subprocess/subprocess.hpp>
|
||||
|
||||
#ifdef __USING_WINDOWS__
|
||||
#include <Windows.h>
|
||||
#endif
|
||||
|
||||
namespace sp = subprocess;
|
||||
|
||||
void test_ret_code()
|
||||
{
|
||||
std::cout << "Test::test_poll_ret_code" << std::endl;
|
||||
#ifdef __USING_WINDOWS__
|
||||
auto p = sp::Popen({"cmd.exe", "/c", "exit", "1"});
|
||||
#else
|
||||
auto p = sp::Popen({"/usr/bin/false"});
|
||||
#endif
|
||||
while (p.poll() == -1) {
|
||||
#ifdef __USING_WINDOWS__
|
||||
Sleep(100);
|
||||
#else
|
||||
usleep(1000 * 100);
|
||||
#endif
|
||||
}
|
||||
assert (p.retcode() == 1);
|
||||
}
|
||||
@ -25,9 +37,27 @@ void test_ret_code_comm()
|
||||
std::cout << "retcode: " << cut.retcode() << std::endl;
|
||||
}
|
||||
|
||||
void test_ret_code_check_output()
|
||||
{
|
||||
using namespace sp;
|
||||
bool caught = false;
|
||||
try {
|
||||
auto obuf = check_output({"/bin/false"}, shell{false});
|
||||
assert(false); // Expected to throw
|
||||
} catch (CalledProcessError &e) {
|
||||
std::cout << "retcode: " << e.retcode << std::endl;
|
||||
assert (e.retcode == 1);
|
||||
caught = true;
|
||||
}
|
||||
assert(caught);
|
||||
}
|
||||
|
||||
int main() {
|
||||
test_ret_code();
|
||||
#ifndef __USING_WINDOWS__
|
||||
test_ret_code_comm();
|
||||
test_ret_code_check_output();
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
BIN
test/test_split
BIN
test/test_split
Binary file not shown.
@ -1,11 +1,15 @@
|
||||
#include <iostream>
|
||||
#include "../subprocess.hpp"
|
||||
#include <cpp-subprocess/subprocess.hpp>
|
||||
|
||||
using namespace subprocess;
|
||||
|
||||
void test_exename()
|
||||
{
|
||||
#ifdef __USING_WINDOWS__
|
||||
auto ret = call({"--version"}, executable{"cmake"}, shell{false});
|
||||
#else
|
||||
auto ret = call({"-l"}, executable{"ls"}, shell{false});
|
||||
#endif
|
||||
std::cout << ret << std::endl;
|
||||
}
|
||||
|
||||
@ -35,7 +39,11 @@ void test_easy_piping()
|
||||
|
||||
void test_shell()
|
||||
{
|
||||
auto obuf = check_output({"ls", "-l"}, shell{false});
|
||||
#ifdef __USING_WINDOWS__
|
||||
auto obuf = check_output({"cmake", "--version"}, shell{false});
|
||||
#else
|
||||
auto obuf = check_output({"ls", "-l"}, shell{false});
|
||||
#endif
|
||||
std::cout << obuf.buf.data() << std::endl;
|
||||
}
|
||||
|
||||
@ -43,20 +51,49 @@ void test_sleep()
|
||||
{
|
||||
auto p = Popen({"sleep", "30"}, shell{true});
|
||||
|
||||
while (p.poll() == -1) {
|
||||
while (p.poll() == -1)
|
||||
{
|
||||
std::cout << "Waiting..." << std::endl;
|
||||
#ifdef __USING_WINDOWS__
|
||||
#else
|
||||
sleep(1);
|
||||
#endif
|
||||
}
|
||||
|
||||
std::cout << "Sleep ended: ret code = " << p.retcode() << std::endl;
|
||||
}
|
||||
|
||||
void test_read_all()
|
||||
{
|
||||
Popen p = Popen({"echo", "12345678"}, output{PIPE});
|
||||
|
||||
std::vector<char> buf(6);
|
||||
int rbytes = util::read_all(p.output(), buf);
|
||||
|
||||
std::string out(buf.begin(), buf.end());
|
||||
|
||||
assert(out == "12345678\n" && rbytes == 9); // echo puts a new line at the end of output
|
||||
std::cout << "read_all() succeeded" << std::endl;
|
||||
}
|
||||
|
||||
void test_simple_cmd()
|
||||
{
|
||||
auto p = Popen({"ls", "-l"}, output{PIPE});
|
||||
auto obuf = p.communicate().first;
|
||||
std::cout << "Data : " << obuf.buf.data() << std::endl;
|
||||
std::cout << "Data len: " << obuf.length << std::endl;
|
||||
}
|
||||
|
||||
int main() {
|
||||
/*
|
||||
test_exename();
|
||||
test_input();
|
||||
test_piping();
|
||||
test_easy_piping();
|
||||
test_shell();
|
||||
test_sleep();
|
||||
test_read_all();
|
||||
*/
|
||||
test_simple_cmd();
|
||||
return 0;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user