daml/compatibility/bazel_tools/daml.cc.tpl
Moritz Kiefer 629ec732dd
Include puppeteer tests in compat tests (#6018)
* Include puppeteer tests in compat tests

This PR adds the puppeteer based tests to the compatibility
tests. This also means that they are now actually compatibility
tests. Before, we only tested the SDK side.

Apart from process management being a nightmare on Windows as usually,
there are two things that might stick out here:

1. I’ve replaced the `sh_binary` wrapper by a `cc_binary`. There is a
   lengthy comment explaining why. I think at the moment, we could
   actually get rid of the wraper completely and add JAVA to path in
   the tests that need it but at least for now, I’d like to keep it
   until we are sure that we don’t need to add more to it (and then
   it’s also in the git history if we do need to resurrect it).
2. These tests are duplicated now similar to the `daml ledger *`
   tests. The reasoning here is different. They depend on the SDK
   tarball either way so performance wise there is no reason to keep
   them. However, we reference the other file in the docs which means
   we cannot change it freely. What we could do is to make this
   sufficiently flexible to handle both the `daml start` case and
   separate `daml sandbox`/`daml json-api` processes and then we can
   reference it in the docs. There is still added complexity for
   Windows but that’s necessary for users as well that want to run
   this on Windows so that seems unavoidable. (I should probably also
   remove my snarky comments 😇) I’d like to kee it duplicated
   for this PR and then we can clean it up afterwards.

changelog_begin
changelog_end

* Bump timeouts

changelog_begin
changelog_end
2020-05-22 14:02:59 +02:00

88 lines
3.1 KiB
Smarty
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "tools/cpp/runfiles/runfiles.h"
#include <codecvt>
#include <iostream>
#include <locale>
#include <memory>
#include <unistd.h>
#if defined(_WIN32)
#include <windows.h>
#endif
using bazel::tools::cpp::runfiles::Runfiles;
/*
NOTE (MK): Why is this not just an sh_binary?
Good question! It turns out that on Windows, an
sh_binary creates a custom executable that then launches
bash. Somehow this seems to result in a double fork
(or the Windows-equivalent) thereof which results in
child processes not being childs of the original process.
This makes it really hard to kill a process including
all child processes which is really important since
otherwise you are left with a running JVM process
if you kill `daml sandbox`.
*/
int main(int argc, char **argv) {
std::string error;
std::unique_ptr<Runfiles> runfiles(Runfiles::Create(argv[0], &error));
if (runfiles == nullptr) {
std::cerr << "Failed to initialize runfiles: " << error << "\n";
exit(1);
}
const char *java_home = getenv("JAVA_HOME");
std::string path_prefix = "";
// NOTE (MK) I dont entirely understand when Bazel defines
// JAVA_HOME and when it doesnt but it looks like it defines
// it in tests but not in genrules which is good enough for us.
if (java_home) {
#if defined(_WIN32)
path_prefix = std::string(java_home) + "/bin;";
#else
path_prefix = std::string(java_home) + "/bin:";
#endif
}
std::string new_path = path_prefix + getenv("PATH");
#if defined(_WIN32)
_putenv_s("PATH", new_path.c_str());
#else
setenv("PATH", new_path.c_str(), 1);
#endif
std::string path =
runfiles->Rlocation("daml-sdk-{SDK_VERSION}/sdk/bin/daml");
#if defined(_WIN32)
// To keep things as simple as possible, we simply take
// the existing command line, strip everything up to the first space
// and replace it. This is obviously not correct if there are spaces
// in the path name but Bazel doesnt like that either so
// it should be good enough.
LPWSTR oldCmdLine = GetCommandLineW();
wchar_t *index = wcschr(oldCmdLine, ' ');
std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>> converter;
std::wstring cmdLine = converter.from_bytes(path.c_str());
cmdLine += std::wstring(index);
const int MAX_CMDLINE_LENGTH = 32768;
wchar_t result[MAX_CMDLINE_LENGTH];
wcsncpy(result, cmdLine.c_str(), MAX_CMDLINE_LENGTH - 1);
result[MAX_CMDLINE_LENGTH - 1] = 0;
PROCESS_INFORMATION processInfo = {0};
STARTUPINFOW startupInfo = {0};
startupInfo.cb = sizeof(startupInfo);
BOOL ok = CreateProcessW(NULL, result, NULL, NULL, TRUE, 0, NULL, NULL,
&startupInfo, &processInfo);
if (!ok) {
std::wcerr << "Cannot launch process: " << cmdLine << "\n";
return GetLastError();
}
WaitForSingleObject(processInfo.hProcess, INFINITE);
DWORD exit_code;
GetExitCodeProcess(processInfo.hProcess, &exit_code);
CloseHandle(processInfo.hProcess);
CloseHandle(processInfo.hThread);
return exit_code;
#else
execvp(path.c_str(), argv);
#endif
}