Commit 58957f3d by Jamie Madill Committed by Commit Bot

Add option to run each test config in a separate process.

This CL adds a command line option to angle_end2end_tests that will iterate over all test configs. For each config it'll fork a new child process that will run only a single config. This will allow us to isolate each config to a specific child process. Hopefully this will reduce test flakiness due to driver issues with multiple configs. The command line option is "--separate-process-per-config". Note that there are about 25 configs right now. Bug: angleproject:3393 Change-Id: Ia117b371bbe159c1b0d28d82befffeb0f40467a9 Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/1591428 Commit-Queue: Jamie Madill <jmadill@chromium.org> Reviewed-by: 's avatarYuly Novikov <ynovikov@chromium.org>
parent 80147d11
...@@ -28,6 +28,8 @@ bool PrependPathToEnvironmentVar(const char *variableName, const char *path); ...@@ -28,6 +28,8 @@ bool PrependPathToEnvironmentVar(const char *variableName, const char *path);
// Run an application and get the output. Gets a nullptr-terminated set of args to execute the // Run an application and get the output. Gets a nullptr-terminated set of args to execute the
// application with, and returns the stdout and stderr outputs as well as the exit code. // application with, and returns the stdout and stderr outputs as well as the exit code.
// //
// Pass nullptr for stdoutOut/stderrOut if you don't need to capture. exitCodeOut is required.
//
// Returns false if it fails to actually execute the application. // Returns false if it fails to actually execute the application.
bool RunApp(const std::vector<const char *> &args, bool RunApp(const std::vector<const char *> &args,
std::string *stdoutOut, std::string *stdoutOut,
......
...@@ -193,7 +193,11 @@ bool RunApp(const std::vector<const char *> &args, ...@@ -193,7 +193,11 @@ bool RunApp(const std::vector<const char *> &args,
{ {
startInfo.hStdError = GetStdHandle(STD_ERROR_HANDLE); startInfo.hStdError = GetStdHandle(STD_ERROR_HANDLE);
} }
startInfo.dwFlags |= STARTF_USESTDHANDLES;
if (stderrOut || stdoutOut)
{
startInfo.dwFlags |= STARTF_USESTDHANDLES;
}
// Create the child process. // Create the child process.
PROCESS_INFORMATION processInfo = {}; PROCESS_INFORMATION processInfo = {};
......
...@@ -67,9 +67,12 @@ bool IsNativeConfigSupported(const PlatformParameters &param, OSWindow *osWindow ...@@ -67,9 +67,12 @@ bool IsNativeConfigSupported(const PlatformParameters &param, OSWindow *osWindow
// Not yet implemented. // Not yet implemented.
return false; return false;
} }
std::map<PlatformParameters, bool> gParamAvailabilityCache;
} // namespace } // namespace
std::string gSelectedConfig; std::string gSelectedConfig;
bool gSeparateProcessPerConfig = false;
SystemInfo *GetTestSystemInfo() SystemInfo *GetTestSystemInfo()
{ {
...@@ -84,7 +87,8 @@ SystemInfo *GetTestSystemInfo() ...@@ -84,7 +87,8 @@ SystemInfo *GetTestSystemInfo()
// Print complete system info when available. // Print complete system info when available.
// Seems to trip up Android test expectation parsing. // Seems to trip up Android test expectation parsing.
if (!IsAndroid()) // Also don't print info when a config is selected to prevent test spam.
if (!IsAndroid() && gSelectedConfig.empty())
{ {
PrintSystemInfo(*sSystemInfo); PrintSystemInfo(*sSystemInfo);
} }
...@@ -408,48 +412,80 @@ bool IsPlatformAvailable(const PlatformParameters &param) ...@@ -408,48 +412,80 @@ bool IsPlatformAvailable(const PlatformParameters &param)
return false; return false;
} }
static std::map<PlatformParameters, bool> paramAvailabilityCache;
auto iter = paramAvailabilityCache.find(param);
if (iter != paramAvailabilityCache.end())
{
return iter->second;
}
bool result = false; bool result = false;
if (!gSelectedConfig.empty()) auto iter = gParamAvailabilityCache.find(param);
if (iter != gParamAvailabilityCache.end())
{ {
std::stringstream strstr; result = iter->second;
strstr << param;
if (strstr.str() == gSelectedConfig)
{
result = true;
}
} }
else else
{ {
const SystemInfo *systemInfo = GetTestSystemInfo(); if (!gSelectedConfig.empty())
if (systemInfo)
{ {
result = IsConfigWhitelisted(*systemInfo, param); std::stringstream strstr;
strstr << param;
if (strstr.str() == gSelectedConfig)
{
result = true;
}
} }
else else
{ {
result = IsConfigSupported(param); const SystemInfo *systemInfo = GetTestSystemInfo();
if (systemInfo)
{
result = IsConfigWhitelisted(*systemInfo, param);
}
else
{
result = IsConfigSupported(param);
}
} }
gParamAvailabilityCache[param] = result;
// Enable this unconditionally to print available platforms.
if (!gSelectedConfig.empty())
{
if (result)
{
std::cout << "Test Config: " << param << "\n";
}
}
else if (!result)
{
std::cout << "Skipping tests using configuration " << param
<< " because it is not available.\n";
}
}
// Disable all tests in the parent process when running child processes.
if (gSeparateProcessPerConfig)
{
return false;
} }
return result;
}
paramAvailabilityCache[param] = result; std::vector<std::string> GetAvailableTestPlatformNames()
{
std::vector<std::string> platformNames;
if (!result) for (const auto &iter : gParamAvailabilityCache)
{ {
std::cout << "Skipping tests using configuration " << param if (iter.second)
<< " because it is not available." << std::endl; {
std::stringstream strstr;
strstr << iter.first;
platformNames.push_back(strstr.str());
}
} }
// Uncomment this to print available platforms. // Keep the list sorted.
// std::cout << "Platform: " << param << " (" << paramAvailabilityCache.size() << ")\n"; std::sort(platformNames.begin(), platformNames.end());
return result;
return platformNames;
} }
} // namespace angle } // namespace angle
...@@ -122,8 +122,15 @@ bool IsConfigSupported(const PlatformParameters &param); ...@@ -122,8 +122,15 @@ bool IsConfigSupported(const PlatformParameters &param);
// Returns shared test system information. Can be used globally in the tests. // Returns shared test system information. Can be used globally in the tests.
SystemInfo *GetTestSystemInfo(); SystemInfo *GetTestSystemInfo();
// Returns a list of all enabled test platform names. For use in configuration enumeration.
std::vector<std::string> GetAvailableTestPlatformNames();
// Active config (e.g. ES2_Vulkan). // Active config (e.g. ES2_Vulkan).
extern std::string gSelectedConfig; extern std::string gSelectedConfig;
// Use a separate isolated process per test config. This works around driver flakiness when using
// multiple APIs/windows/etc in the same process.
extern bool gSeparateProcessPerConfig;
} // namespace angle } // namespace angle
#endif // ANGLE_TEST_INSTANTIATE_H_ #endif // ANGLE_TEST_INSTANTIATE_H_
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