Commit 691fa499 authored by Tijana Vukovic's avatar Tijana Vukovic
Browse files

Added windows process test for string and binary input

parent 48b2c661
#include <iostream> #include <iostream>
#include <array>
#include <string> #include <string>
#include <vector> #include <vector>
#include <Windows.h> #include <Windows.h>
#include <migraphx/ranges.hpp>
#include <migraphx/errors.hpp> #include <migraphx/errors.hpp>
#include <migraphx/file_buffer.hpp>
#include <migraphx/msgpack.hpp>
int main() void read_stdin()
{ {
std::vector<char> result; std::vector<char> result;
constexpr std::size_t BUFFER_SIZE = 1024;
DWORD bytes_read;
TCHAR buffer[BUFFER_SIZE];
HANDLE std_in = GetStdHandle(STD_INPUT_HANDLE); HANDLE std_in = GetStdHandle(STD_INPUT_HANDLE);
HANDLE std_out = GetStdHandle(STD_OUTPUT_HANDLE); HANDLE std_out = GetStdHandle(STD_OUTPUT_HANDLE);
if(std_in == INVALID_HANDLE_VALUE) if(std_in == INVALID_HANDLE_VALUE)
MIGRAPHX_THROW("STDIN invalid handle (" + std::to_string(GetLastError()) + ")"); MIGRAPHX_THROW("STDIN invalid handle (" + std::to_string(GetLastError()) + ")");
constexpr std::size_t BUFFER_SIZE = 1024; if(std_out == INVALID_HANDLE_VALUE)
DWORD bytes_read; MIGRAPHX_THROW("STDOUT invalid handle (" + std::to_string(GetLastError()) + ")");
TCHAR buffer[BUFFER_SIZE];
for(;;) for(;;)
{ {
BOOL status = ReadFile(std_in, buffer, BUFFER_SIZE, &bytes_read, nullptr); BOOL status = ReadFile(std_in, buffer, BUFFER_SIZE, &bytes_read, nullptr);
...@@ -25,8 +32,9 @@ int main() ...@@ -25,8 +32,9 @@ int main()
DWORD written; DWORD written;
if(WriteFile(std_out, buffer, bytes_read, &written, nullptr) == FALSE) if(WriteFile(std_out, buffer, bytes_read, &written, nullptr) == FALSE)
break; break;
// result.insert(result.end(), buffer, buffer + bytes_read);
} }
// std::cout << result.data(); }
return 0;
int main(int argc, char const* argv[]) {
read_stdin();
} }
#include <Windows.h> #include <Windows.h>
#include <tchar.h>
#include <iostream> #include <iostream>
#include <string> #include <cstring>
#include "test.hpp" #include "test.hpp"
#include <migraphx/errors.hpp>
#include <migraphx/file_buffer.hpp>
#include <migraphx/filesystem.hpp>
#include <migraphx/msgpack.hpp> #include <migraphx/msgpack.hpp>
#include <migraphx/process.hpp> #include <migraphx/process.hpp>
#include <migraphx/filesystem.hpp>
#include <migraphx/errors.hpp>
#include <tchar.h>
#define BUFSIZE MAX_PATH #define BUFSIZE MAX_PATH
constexpr std::size_t BUFFER_SIZE = 4096;
STARTUPINFO info;
PROCESS_INFORMATION process_info;
enum class direction
{
input,
output
};
template <direction dir>
class pipe
{
public:
explicit pipe()
{
SECURITY_ATTRIBUTES attrs;
attrs.nLength = sizeof(SECURITY_ATTRIBUTES);
attrs.bInheritHandle = TRUE;
attrs.lpSecurityDescriptor = nullptr;
if(CreatePipe(&m_read, &m_write, &attrs, 0) == FALSE)
throw GetLastError();
if(dir == direction::output)
{
// Do not inherit the read handle for the output pipe
if(SetHandleInformation(m_read, HANDLE_FLAG_INHERIT, 0) == 0)
throw GetLastError();
}
else
{
// Do not inherit the write handle for the input pipe
if(SetHandleInformation(m_write, HANDLE_FLAG_INHERIT, 0) == 0)
throw GetLastError();
}
}
pipe(const pipe&) = delete;
pipe& operator=(const pipe&) = delete;
pipe(pipe&&) = default;
~pipe()
{
if(m_write != nullptr)
{
CloseHandle(m_write);
}
if(m_read != nullptr)
{
CloseHandle(m_read);
}
}
bool close_write_handle()
{
auto result = true;
if(m_write != nullptr)
{
result = CloseHandle(m_write) == TRUE;
m_write = nullptr;
}
return result;
}
bool close_read_handle()
{
auto result = true;
if(m_read != nullptr)
{
result = CloseHandle(m_read) == TRUE;
m_read = nullptr;
}
return result;
}
std::pair<bool, DWORD> read(LPVOID buffer, DWORD length) const
{
DWORD bytes_read;
if(ReadFile(m_read, buffer, length, &bytes_read, nullptr) == FALSE and
GetLastError() == ERROR_MORE_DATA)
{
return {true, bytes_read};
}
return {false, bytes_read};
}
HANDLE get_read_handle() const { return m_read; }
bool write(LPCVOID buffer, DWORD length) const
{
DWORD bytes_written;
return WriteFile(m_write, buffer, length, &bytes_written, nullptr) == TRUE;
}
HANDLE get_write_handle() const { return m_write; }
HANDLE m_write = nullptr, m_read = nullptr;
};
std::string get_cwd() std::string get_cwd()
{ {
...@@ -21,69 +123,138 @@ std::string get_cwd() ...@@ -21,69 +123,138 @@ std::string get_cwd()
return std::string(Buffer); return std::string(Buffer);
} }
void CreateProcess(pipe<direction::input>& input,
pipe<direction::output>& output,
const std::string& child_process_name,
const std::string& cwd)
{
ZeroMemory(&info, sizeof(STARTUPINFO));
info.cb = sizeof(STARTUPINFO);
info.hStdError = output.get_write_handle();
info.hStdOutput = output.get_write_handle();
info.hStdInput = input.get_read_handle();
info.dwFlags |= STARTF_USESTDHANDLES;
TCHAR cmdline[MAX_PATH];
std::strncpy(cmdline, child_process_name.c_str(), MAX_PATH);
ZeroMemory(&process_info, sizeof(process_info));
if(CreateProcess(nullptr,
cmdline,
nullptr,
nullptr,
TRUE,
0,
nullptr,
cwd.empty() ? nullptr : static_cast<LPCSTR>(cwd.c_str()),
&info,
&process_info) == FALSE)
{
MIGRAPHX_THROW("Error creating process (" + std::to_string(GetLastError()) + ")");
}
if(not output.close_write_handle())
MIGRAPHX_THROW("Error closing STDOUT handle for writing (" +
std::to_string(GetLastError()) + ")");
if(not input.close_read_handle())
MIGRAPHX_THROW("Error closing STDIN handle for reading (" +
std::to_string(GetLastError()) + ")");
}
void write_to_child(LPCVOID buffer, std::size_t n, pipe<direction::input>& input)
{
DWORD bytes_written;
if(WriteFile(input.m_write, buffer, n, &bytes_written, nullptr) ==
FALSE)
{
MIGRAPHX_THROW("Error writing to child STDIN (" + std::to_string(GetLastError()) + ")");
}
if(not input.close_write_handle())
MIGRAPHX_THROW("Error closing STDIN handle for writing (" + std::to_string(GetLastError()) +
")");
}
std::vector<char> read_from_child(pipe<direction::output>& output) {
std::vector<char> result;
DWORD bytes_read;
TCHAR buffer[BUFFER_SIZE];
for(;;)
{
BOOL status = ReadFile(output.m_read, buffer, BUFFER_SIZE, &bytes_read, nullptr);
if(status == FALSE or bytes_read == 0)
break;
result.insert(result.end(), buffer, buffer + bytes_read);
}
return result;
}
TEST_CASE(string_data) TEST_CASE(string_data)
{ {
std::string cwd = get_cwd(); std::string cwd = get_cwd();
auto child_path = migraphx::fs::path{cwd};
std::string string_data = "Parent string"; std::string string_data = "Parent string";
// write string data to child process std::string child_process_name = "test_child.exe";
migraphx::process{"test_child.exe"}.cwd(child_path).write([&](auto writer) {
migraphx::to_msgpack(string_data, writer); pipe<direction::input> input{};
}); pipe<direction::output> output{};
//// parent process read from child stdout CreateProcess(input, output, child_process_name, cwd);
// std::vector<char> result;
// HANDLE std_in = GetStdHandle(STD_INPUT_HANDLE); // write to child process
// if(std_in == INVALID_HANDLE_VALUE) TCHAR buffer[BUFFER_SIZE];
// MIGRAPHX_THROW("STDIN invalid handle (" + std::to_string(GetLastError()) + ")"); std::strncpy(buffer, string_data.c_str(), BUFFER_SIZE);
// constexpr std::size_t BUFFER_SIZE = 4096; write_to_child(buffer, BUFFER_SIZE, input);
// DWORD bytes_read;
// TCHAR buffer[BUFFER_SIZE]; // read from child stdout
// for(;;) std::vector<char> result = read_from_child(output);
// {
// BOOL status = ReadFile(std_in, buffer, BUFFER_SIZE, &bytes_read, nullptr); WaitForSingleObject(process_info.hProcess, INFINITE);
// if(status == FALSE or bytes_read == 0)
// break; DWORD status{};
GetExitCodeProcess(process_info.hProcess, &status);
// result.insert(result.end(), buffer, buffer + bytes_read);
// } CloseHandle(process_info.hProcess);
CloseHandle(process_info.hThread);
// EXPECT(result.data() == string_data);
//compare input parent and output child process
EXPECT(result.data() == string_data);
} }
TEST_CASE(binary_data) TEST_CASE(binary_data)
{ {
std::string cwd = get_cwd();
// binary data
std::vector<char> binary_data = {'B', 'i', 'n', 'a', 'r', 'y'}; std::vector<char> binary_data = {'B', 'i', 'n', 'a', 'r', 'y'};
std::string cwd = get_cwd();
auto child_path = migraphx::fs::path{cwd}; std::string child_process_name = "test_child.exe";
// write string data to child process pipe<direction::input> input{};
migraphx::process{"test_child.exe"}.cwd(child_path).write([&](auto writer) { pipe<direction::output> output{};
migraphx::to_msgpack(binary_data, writer);
}); CreateProcess(input, output, child_process_name, cwd);
//// parent process read from child stdout write_to_child(binary_data.data(), binary_data.size(), input);
// std::vector<char> result;
// HANDLE std_in = GetStdHandle(STD_INPUT_HANDLE); // read from child stdout
// if(std_in == INVALID_HANDLE_VALUE) std::vector<char> result = read_from_child(output);
// MIGRAPHX_THROW("STDIN invalid handle (" + std::to_string(GetLastError()) + ")");
// constexpr std::size_t BUFFER_SIZE = 4096; WaitForSingleObject(process_info.hProcess, INFINITE);
// DWORD bytes_read;
// TCHAR buffer[BUFFER_SIZE]; DWORD status{};
// for(;;) GetExitCodeProcess(process_info.hProcess, &status);
//{
// BOOL status = ReadFile(std_in, buffer, BUFFER_SIZE, &bytes_read, nullptr); CloseHandle(process_info.hProcess);
// if(status == FALSE or bytes_read == 0) CloseHandle(process_info.hThread);
// break;
// compare input parent and output child process
// result.insert(result.end(), buffer, buffer + bytes_read); EXPECT(result == binary_data);
//}
// EXPECT(result.data() == string_data);
} }
int main(int argc, const char* argv[]) { test::run(argc, argv); } int main(int argc, const char* argv[]) { test::run(argc, argv); }
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment