test/cxx/ApplicationPool2/SmartSpawnerTest.cpp in passenger-4.0.60 vs test/cxx/ApplicationPool2/SmartSpawnerTest.cpp in passenger-5.0.0.beta1
- old
+ new
@@ -11,19 +11,16 @@
using namespace Passenger;
using namespace Passenger::ApplicationPool2;
namespace tut {
struct ApplicationPool2_SmartSpawnerTest {
- ServerInstanceDirPtr serverInstanceDir;
- ServerInstanceDir::GenerationPtr generation;
- ProcessPtr process;
+ SpawnObject object;
PipeWatcher::DataCallback gatherOutput;
string gatheredOutput;
boost::mutex gatheredOutputSyncher;
ApplicationPool2_SmartSpawnerTest() {
- createServerInstanceDirAndGeneration(serverInstanceDir, generation);
PipeWatcher::onData = PipeWatcher::DataCallback();
gatherOutput = boost::bind(&ApplicationPool2_SmartSpawnerTest::_gatherOutput, this, _1, _2);
setLogLevel(LVL_ERROR); // TODO: should be LVL_WARN
setPrintAppOutputAsDebuggingMessages(true);
}
@@ -44,17 +41,21 @@
command.push_back(string(buf) + "/support/placebo-preloader.rb");
if (exitImmediately) {
command.push_back("exit-immediately");
}
- return boost::make_shared<SmartSpawner>(
- generation,
- command,
- options,
- make_shared<SpawnerConfig>(*resourceLocator));
+ return boost::make_shared<SmartSpawner>(command,
+ options, createSpawnerConfig());
}
+ SpawnerConfigPtr createSpawnerConfig() {
+ SpawnerConfigPtr config = boost::make_shared<SpawnerConfig>();
+ config->resourceLocator = resourceLocator;
+ config->finalize();
+ return config;
+ }
+
Options createOptions() {
Options options;
options.spawnMethod = "smart";
options.loadShellEnvvars = false;
return options;
@@ -77,20 +78,20 @@
options.appRoot = "stub/rack";
options.startCommand = "ruby\t" "start.rb";
options.startupFile = "start.rb";
boost::shared_ptr<SmartSpawner> spawner = createSpawner(options);
setLogLevel(LVL_CRIT);
- process = spawner->spawn(options);
- process->requiresShutdown = false;
+ object = spawner->spawn(options);
+ object.process->requiresShutdown = false;
kill(spawner->getPreloaderPid(), SIGTERM);
// Give it some time to exit.
usleep(300000);
// No exception at next spawn.
- process = spawner->spawn(options);
- process->requiresShutdown = false;
+ object = spawner->spawn(options);
+ object.process->requiresShutdown = false;
}
TEST_METHOD(81) {
// If the preloader still crashes after the restart then
// SmartSpawner will throw an exception.
@@ -99,12 +100,12 @@
options.startCommand = "ruby\t" "start.rb";
options.startupFile = "start.rb";
setLogLevel(LVL_CRIT);
boost::shared_ptr<SmartSpawner> spawner = createSpawner(options, true);
try {
- process = spawner->spawn(options);
- process->requiresShutdown = false;
+ object = spawner->spawn(options);
+ object.process->requiresShutdown = false;
fail("SpawnException expected");
} catch (const SpawnException &) {
// Pass.
}
}
@@ -115,31 +116,43 @@
// whatever stderr output as error page.
Options options = createOptions();
options.appRoot = "stub/rack";
options.startCommand = "ruby\t" "start.rb";
options.startupFile = "start.rb";
- options.startTimeout = 300;
+ options.startTimeout = 100;
vector<string> preloaderCommand;
preloaderCommand.push_back("bash");
preloaderCommand.push_back("-c");
preloaderCommand.push_back("echo hello world >&2; sleep 60");
- SmartSpawner spawner(
- generation,
- preloaderCommand,
- options,
- make_shared<SpawnerConfig>(*resourceLocator));
+ SmartSpawner spawner(preloaderCommand, options, createSpawnerConfig());
setLogLevel(LVL_CRIT);
try {
- process = spawner.spawn(options);
- process->requiresShutdown = false;
+ object = spawner.spawn(options);
+ object.process->requiresShutdown = false;
fail("SpawnException expected");
} catch (const SpawnException &e) {
ensure_equals(e.getErrorKind(),
SpawnException::PRELOADER_STARTUP_TIMEOUT);
- ensure(e.getErrorPage().find("hello world\n") != string::npos);
+ if (e.getErrorPage().find("hello world\n") == string::npos) {
+ // This might be caused by the machine being too slow.
+ // Try again with a higher timeout.
+ options.startTimeout = 1000;
+ SmartSpawner spawner2(preloaderCommand, options, createSpawnerConfig());
+ try {
+ object = spawner2.spawn(options);
+ object.process->requiresShutdown = false;
+ fail("SpawnException expected");
+ } catch (const SpawnException &e2) {
+ ensure_equals(e2.getErrorKind(),
+ SpawnException::PRELOADER_STARTUP_TIMEOUT);
+ if (e2.getErrorPage().find("hello world\n") == string::npos) {
+ fail(("Unexpected error page:\n" + e2.getErrorPage()).c_str());
+ }
+ }
+ }
}
}
TEST_METHOD(83) {
// If the preloader crashed during startup without returning
@@ -152,20 +165,16 @@
vector<string> preloaderCommand;
preloaderCommand.push_back("bash");
preloaderCommand.push_back("-c");
preloaderCommand.push_back("echo hello world >&2");
- SmartSpawner spawner(
- generation,
- preloaderCommand,
- options,
- make_shared<SpawnerConfig>(*resourceLocator));
+ SmartSpawner spawner(preloaderCommand, options, createSpawnerConfig());
setLogLevel(LVL_CRIT);
try {
- process = spawner.spawn(options);
- process->requiresShutdown = false;
+ object = spawner.spawn(options);
+ object.process->requiresShutdown = false;
fail("SpawnException expected");
} catch (const SpawnException &e) {
ensure_equals(e.getErrorKind(),
SpawnException::PRELOADER_STARTUP_ERROR);
ensure(e.getErrorPage().find("hello world\n") != string::npos);
@@ -173,30 +182,28 @@
}
TEST_METHOD(84) {
// If the preloader encountered an error, then the resulting SpawnException
// takes note of the process's environment variables.
+ string envvars = modp::b64_encode("PASSENGER_FOO\0foo\0",
+ sizeof("PASSENGER_FOO\0foo\0") - 1);
Options options = createOptions();
options.appRoot = "stub/rack";
options.startCommand = "ruby\t" "start.rb";
options.startupFile = "start.rb";
- options.environmentVariables.push_back(make_pair("PASSENGER_FOO", "foo"));
+ options.environmentVariables = envvars;
vector<string> preloaderCommand;
preloaderCommand.push_back("bash");
preloaderCommand.push_back("-c");
preloaderCommand.push_back("echo hello world >&2");
- SmartSpawner spawner(
- generation,
- preloaderCommand,
- options,
- make_shared<SpawnerConfig>(*resourceLocator));
+ SmartSpawner spawner(preloaderCommand, options, createSpawnerConfig());
setLogLevel(LVL_CRIT);
try {
- process = spawner.spawn(options);
- process->requiresShutdown = false;
+ object = spawner.spawn(options);
+ object.process->requiresShutdown = false;
fail("SpawnException expected");
} catch (const SpawnException &e) {
ensure(containsSubstring(e["envvars"], "PASSENGER_FOO=foo\n"));
}
}
@@ -211,31 +218,22 @@
{
vector<string> preloaderCommand;
preloaderCommand.push_back("ruby");
preloaderCommand.push_back(resourceLocator->getHelperScriptsDir() + "/rack-preloader.rb");
- SmartSpawner spawner(
- generation,
- preloaderCommand,
- options,
- make_shared<SpawnerConfig>(*resourceLocator));
- process = spawner.spawn(options);
- process->requiresShutdown = false;
+ SmartSpawner spawner(preloaderCommand, options, createSpawnerConfig());
+ object = spawner.spawn(options);
+ object.process->requiresShutdown = false;
}
- SessionPtr session = process->newSession();
+ SessionPtr session = object.process->newSession();
session->initiate();
const char header[] =
"REQUEST_METHOD\0GET\0"
"PATH_INFO\0/print_stderr\0";
- string data(header, sizeof(header) - 1);
- data.append("PASSENGER_CONNECT_PASSWORD");
- data.append(1, '\0');
- data.append(process->connectPassword);
- data.append(1, '\0');
- writeScalarMessage(session->fd(), data);
+ writeScalarMessage(session->fd(), header, sizeof(header) - 1);
shutdown(session->fd(), SHUT_WR);
readAll(session->fd());
EVENTUALLY(2,
boost::lock_guard<boost::mutex> l(gatheredOutputSyncher);
result = gatheredOutput.find("hello world!\n") != string::npos;