File: DirectSpawnerTest.cpp

package info (click to toggle)
ruby-passenger 4.0.53-1
  • links: PTS, VCS
  • area: main
  • in suites: jessie, jessie-kfreebsd
  • size: 28,668 kB
  • ctags: 70,512
  • sloc: cpp: 264,280; ruby: 25,606; sh: 22,815; ansic: 18,277; python: 767; makefile: 99; perl: 20
file content (121 lines) | stat: -rw-r--r-- 3,978 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
#include <TestSupport.h>
#include <ApplicationPool2/DirectSpawner.h>
#include <json/json.h>
#include <fcntl.h>

using namespace Passenger;
using namespace Passenger::ApplicationPool2;

namespace tut {
	struct ApplicationPool2_DirectSpawnerTest {
		ServerInstanceDirPtr serverInstanceDir;
		ServerInstanceDir::GenerationPtr generation;
		ProcessPtr process;
		PipeWatcher::DataCallback gatherOutput;
		string gatheredOutput;
		boost::mutex gatheredOutputSyncher;

		ApplicationPool2_DirectSpawnerTest() {
			createServerInstanceDirAndGeneration(serverInstanceDir, generation);
			PipeWatcher::onData = PipeWatcher::DataCallback();
			gatherOutput = boost::bind(&ApplicationPool2_DirectSpawnerTest::_gatherOutput, this, _1, _2);
			setLogLevel(LVL_ERROR); // TODO: change to LVL_WARN
			setPrintAppOutputAsDebuggingMessages(true);
		}

		~ApplicationPool2_DirectSpawnerTest() {
			setLogLevel(DEFAULT_LOG_LEVEL);
			setPrintAppOutputAsDebuggingMessages(false);
			unlink("stub/wsgi/passenger_wsgi.pyc");
			PipeWatcher::onData = PipeWatcher::DataCallback();
		}

		boost::shared_ptr<DirectSpawner> createSpawner(const Options &options) {
			return boost::make_shared<DirectSpawner>(
				generation, make_shared<SpawnerConfig>(*resourceLocator));
		}

		Options createOptions() {
			Options options;
			options.spawnMethod = "direct";
			options.loadShellEnvvars = false;
			return options;
		}

		void _gatherOutput(const char *data, unsigned int size) {
			boost::lock_guard<boost::mutex> l(gatheredOutputSyncher);
			gatheredOutput.append(data, size);
		}
	};

	DEFINE_TEST_GROUP_WITH_LIMIT(ApplicationPool2_DirectSpawnerTest, 90);

	#include "SpawnerTestCases.cpp"

	TEST_METHOD(80) {
		// If the application didn't start within the timeout
		// then whatever was written to stderr is used as the
		// SpawnException error page.
		Options options = createOptions();
		options.appRoot      = "stub";
		options.startCommand = "perl\t" "-e\t" "print STDERR \"hello world\\n\"; sleep(60)";
		options.startupFile  = ".";
		options.startTimeout = 300;

		DirectSpawner spawner(generation, make_shared<SpawnerConfig>(*resourceLocator));
		setLogLevel(LVL_CRIT);

		try {
			process = spawner.spawn(options);
			process->requiresShutdown = false;
			fail("Timeout expected");
		} catch (const SpawnException &e) {
			ensure_equals(e.getErrorKind(),
				SpawnException::APP_STARTUP_TIMEOUT);
			ensure(e.getErrorPage().find("hello world\n") != string::npos);
		}
	}

	TEST_METHOD(81) {
		// If the application crashed during startup without returning
		// a proper error response, then its stderr output is used
		// as error response instead.
		Options options = createOptions();
		options.appRoot      = "stub";
		options.startCommand = "perl\t" "-e\t" "print STDERR \"hello world\\n\"";
		options.startupFile  = ".";

		DirectSpawner spawner(generation, make_shared<SpawnerConfig>(*resourceLocator));
		setLogLevel(LVL_CRIT);

		try {
			process = spawner.spawn(options);
			process->requiresShutdown = false;
			fail("SpawnException expected");
		} catch (const SpawnException &e) {
			ensure_equals(e.getErrorKind(),
				SpawnException::APP_STARTUP_ERROR);
			ensure(e.getErrorPage().find("hello world\n") != string::npos);
		}
	}

	TEST_METHOD(82) {
		SHOW_EXCEPTION_BACKTRACE(
		// Test that everything works correctly if the app re-execs() itself.
		// https://code.google.com/p/phusion-passenger/issues/detail?id=842#c19
		Options options = createOptions();
		options.appRoot      = "stub/rack";
		options.startCommand = "ruby\t" "start.rb\t" "--execself";
		options.startupFile  = "start.rb";
		SpawnerPtr spawner = createSpawner(options);
		process = spawner->spawn(options);
		process->requiresShutdown = false;
		ensure_equals(process->sockets->size(), 1u);

		Connection conn = process->sockets->front().checkoutConnection();
		ScopeGuard guard(boost::bind(checkin, process, &conn));
		writeExact(conn.fd, "ping\n");
		ensure_equals(readAll(conn.fd), "pong\n");
		);
	}
}