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 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139
|
#include <TestSupport.h>
#include <ApplicationPool2/Process.h>
#include <Utils/IOUtils.h>
using namespace Passenger;
using namespace Passenger::ApplicationPool2;
using namespace std;
namespace tut {
struct ApplicationPool2_ProcessTest {
BackgroundEventLoop bg;
SocketListPtr sockets;
SocketPair adminSocket;
Pipe errorPipe;
FileDescriptor server1, server2, server3;
ApplicationPool2_ProcessTest() {
bg.start();
struct sockaddr_in addr;
socklen_t len = sizeof(addr);
sockets = boost::make_shared<SocketList>();
server1 = createTcpServer("127.0.0.1", 0);
getsockname(server1, (struct sockaddr *) &addr, &len);
sockets->add("main1",
"tcp://127.0.0.1:" + toString(addr.sin_port),
"session", 3);
server2 = createTcpServer("127.0.0.1", 0);
getsockname(server2, (struct sockaddr *) &addr, &len);
sockets->add("main2",
"tcp://127.0.0.1:" + toString(addr.sin_port),
"session", 3);
server3 = createTcpServer("127.0.0.1", 0);
getsockname(server3, (struct sockaddr *) &addr, &len);
sockets->add("main3",
"tcp://127.0.0.1:" + toString(addr.sin_port),
"session", 3);
adminSocket = createUnixSocketPair();
errorPipe = createPipe();
}
};
DEFINE_TEST_GROUP(ApplicationPool2_ProcessTest);
TEST_METHOD(1) {
// Test initial state.
ProcessPtr process = boost::make_shared<Process>(
123, "", "", adminSocket[0],
errorPipe[0], sockets, 0, 0);
process->dummy = true;
process->requiresShutdown = false;
ensure_equals(process->busyness(), 0);
ensure(!process->isTotallyBusy());
}
TEST_METHOD(2) {
// Test opening and closing sessions.
ProcessPtr process = boost::make_shared<Process>(
123, "", "", adminSocket[0],
errorPipe[0], sockets, 0, 0);
process->dummy = true;
process->requiresShutdown = false;
SessionPtr session = process->newSession();
SessionPtr session2 = process->newSession();
ensure_equals(process->sessions, 2);
process->sessionClosed(session.get());
ensure_equals(process->sessions, 1);
process->sessionClosed(session2.get());
ensure_equals(process->sessions, 0);
}
TEST_METHOD(3) {
// newSession() checks out the socket with the smallest busyness number
// and sessionClosed() restores the session busyness statistics.
ProcessPtr process = boost::make_shared<Process>(
123, "", "", adminSocket[0],
errorPipe[0], sockets, 0, 0);
process->dummy = true;
process->requiresShutdown = false;
// The first 3 newSession() commands check out an idle socket.
SessionPtr session1 = process->newSession();
SessionPtr session2 = process->newSession();
SessionPtr session3 = process->newSession();
ensure(session1->getSocket()->name != session2->getSocket()->name);
ensure(session1->getSocket()->name != session3->getSocket()->name);
ensure(session2->getSocket()->name != session3->getSocket()->name);
// The next 2 newSession() commands check out sockets with sessions == 1.
SessionPtr session4 = process->newSession();
SessionPtr session5 = process->newSession();
ensure(session4->getSocket()->name != session5->getSocket()->name);
// There should now be 1 process with 1 session
// and 2 processes with 2 sessions.
map<int, int> sessionCount;
SocketList::const_iterator it;
for (it = process->sockets->begin(); it != process->sockets->end(); it++) {
sessionCount[it->sessions]++;
}
ensure_equals(sessionCount.size(), 2u);
ensure_equals(sessionCount[1], 1);
ensure_equals(sessionCount[2], 2);
// Closing the first 3 sessions will result in no processes having 1 session
// and 1 process having 2 sessions.
process->sessionClosed(session1.get());
process->sessionClosed(session2.get());
process->sessionClosed(session3.get());
sessionCount.clear();
for (it = process->sockets->begin(); it != process->sockets->end(); it++) {
sessionCount[it->sessions]++;
}
ensure_equals(sessionCount[0], 1);
ensure_equals(sessionCount[1], 2);
}
TEST_METHOD(4) {
// If all sockets are at their full capacity then newSession() will fail.
ProcessPtr process = boost::make_shared<Process>(
123, "", "", adminSocket[0],
errorPipe[0], sockets, 0, 0);
process->dummy = true;
process->requiresShutdown = false;
vector<SessionPtr> sessions;
for (int i = 0; i < 9; i++) {
ensure(!process->isTotallyBusy());
SessionPtr session = process->newSession();
ensure(session != NULL);
sessions.push_back(session);
}
ensure(process->isTotallyBusy());
ensure(process->newSession() == NULL);
}
}
|