| 2013 | )"; |
| 2014 | |
| 2015 | static void test_template_py(testing & t, const std::string & name, const std::string & tmpl, const json & vars, const std::string & expect) { |
| 2016 | t.test(name, [&tmpl, &vars, &expect](testing & t) { |
| 2017 | // Prepare arguments |
| 2018 | json merged; |
| 2019 | merged["tmpl"] = json(tmpl); |
| 2020 | merged["vars"] = vars; |
| 2021 | |
| 2022 | #ifdef _WIN32 |
| 2023 | const char * python_executable = "python.exe"; |
| 2024 | #else |
| 2025 | const char * python_executable = "python3"; |
| 2026 | #endif |
| 2027 | |
| 2028 | const char * command_line[] = {python_executable, "-c", py_script.c_str(), NULL}; |
| 2029 | |
| 2030 | struct subprocess_s subprocess; |
| 2031 | int options = subprocess_option_combined_stdout_stderr |
| 2032 | | subprocess_option_no_window |
| 2033 | | subprocess_option_inherit_environment |
| 2034 | | subprocess_option_search_user_path; |
| 2035 | int result = subprocess_create(command_line, options, &subprocess); |
| 2036 | |
| 2037 | if (result != 0) { |
| 2038 | t.log("Failed to create subprocess, error code: " + std::to_string(result)); |
| 2039 | t.assert_true("subprocess creation", false); |
| 2040 | return; |
| 2041 | } |
| 2042 | FILE * p_stdin = subprocess_stdin(&subprocess); |
| 2043 | |
| 2044 | // Write input |
| 2045 | std::string input = merged.dump(); |
| 2046 | auto written = fwrite(input.c_str(), 1, input.size(), p_stdin); |
| 2047 | if (written != input.size()) { |
| 2048 | t.log("Failed to write complete input to subprocess stdin"); |
| 2049 | t.assert_true("subprocess stdin write", false); |
| 2050 | subprocess_destroy(&subprocess); |
| 2051 | return; |
| 2052 | } |
| 2053 | fflush(p_stdin); |
| 2054 | fclose(p_stdin); // Close stdin to signal EOF to the Python process |
| 2055 | subprocess.stdin_file = nullptr; |
| 2056 | |
| 2057 | // Read output |
| 2058 | std::string output; |
| 2059 | char buffer[1024]; |
| 2060 | FILE * p_stdout = subprocess_stdout(&subprocess); |
| 2061 | while (fgets(buffer, sizeof(buffer), p_stdout)) { |
| 2062 | output += buffer; |
| 2063 | } |
| 2064 | |
| 2065 | int process_return; |
| 2066 | subprocess_join(&subprocess, &process_return); |
| 2067 | subprocess_destroy(&subprocess); |
| 2068 | |
| 2069 | if (process_return != 0) { |
| 2070 | t.log("Python script failed with exit code: " + std::to_string(process_return)); |
| 2071 | t.log("Output: " + output); |
| 2072 | t.assert_true("python execution", false); |
no test coverage detected