3 let assert = require('assert');
4 let childProcess = require('child_process');
5 let fs = require('fs');
6 let path = require('path');
8 let Config = require('../../tools/js/config.js');
9 let Database = require('../../tools/js/database.js');
10 let RemoteAPI = require('../../tools/js/remote.js').RemoteAPI;
16 this._testConfigPath = Config.path('testServer.config');
17 this._dataDirectory = Config.path('dataDirectory');
18 this._backupDataPath = null;
19 this._pidWaitStart = null;
20 this._shouldLog = false;
21 this._pgsqlDirectory = null;
24 this._databaseName = Config.value('testDatabaseName');
25 this._databaseUser = Config.value('database.username');
26 this._databaseHost = Config.value('database.host');
27 this._databasePort = Config.value('database.port');
28 this._database = null;
35 let testConfigContent = this.testConfig();
36 fs.writeFileSync(this._testConfigPath, JSON.stringify(testConfigContent, null, ' '));
38 this._ensureTestDatabase();
39 this._ensureDataDirectory();
41 return this._startApache();
46 this._restoreDataDirectory();
48 return this._stopApache();
59 assert(this._databaseName);
61 this._database = new Database(this._databaseName);
62 return this._database;
68 'siteTitle': 'Test Dashboard',
70 'jsonCacheMaxAge': 600,
71 'dataDirectory': Config.value('dataDirectory'),
73 'host': Config.value('database.host'),
74 'port': Config.value('database.port'),
75 'username': Config.value('database.username'),
76 'password': Config.value('database.password'),
77 'name': Config.value('testDatabaseName'),
79 'uploadFileLimitInMB': 2,
80 'uploadUserQuotaInMB': 5,
81 'uploadTotalQuotaInMB': 6,
82 'uploadDirectory': Config.value('dataDirectory') + '/uploaded',
83 'universalSlavePassword': null,
84 'maintenanceMode': false,
85 'clusterStart': [2000, 1, 1, 0, 0],
86 'clusterSize': [0, 2, 0],
87 'defaultDashboard': [[]],
93 _ensureDataDirectory()
95 let backupPath = path.resolve(this._dataDirectory, '../original-data');
96 if (fs.existsSync(this._dataDirectory)) {
97 assert.ok(!fs.existsSync(backupPath), `Both ${this._dataDirectory} and ${backupPath} exist. Cannot make a backup of data`);
98 fs.renameSync(this._dataDirectory, backupPath);
99 this._backupDataPath = backupPath;
100 } else if (fs.existsSync(backupPath)) // Assume this is a backup from the last failed run
101 this._backupDataPath = backupPath;
102 fs.mkdirSync(this._dataDirectory, 0o755);
103 fs.mkdirSync(path.resolve(this._dataDirectory, 'uploaded'), 0o755);
106 _restoreDataDirectory()
108 childProcess.execFileSync('rm', ['-rf', this._dataDirectory]);
109 if (this._backupDataPath)
110 fs.renameSync(this._backupDataPath, this._dataDirectory);
115 let fileList = fs.readdirSync(this._dataDirectory);
116 for (let filename of fileList) {
117 if (filename != 'uploaded')
118 fs.unlinkSync(path.resolve(this._dataDirectory, filename));
120 fileList = fs.readdirSync(path.resolve(this._dataDirectory, 'uploaded'));
121 for (let filename of fileList)
122 fs.unlinkSync(path.resolve(this._dataDirectory, 'uploaded', filename));
125 _ensureTestDatabase()
128 this._executePgsqlCommand('dropdb');
130 this._executePgsqlCommand('createdb');
131 this._executePgsqlCommand('psql', ['--command', `grant all privileges on database "${this._databaseName}" to "${this._databaseUser}";`]);
138 this._database.disconnect();
139 this._database = null;
141 let initFilePath = Config.pathFromRoot('init-database.sql');
142 this._executePgsqlCommand('psql', ['--username', this._databaseUser, '--file', initFilePath],
143 {stdio: ['ignore', 'ignore', 'ignore']});
146 _executePgsqlCommand(command, args, options)
148 if (!this._pgsqlDirectory)
149 this._pgsqlDirectory = this._determinePgsqlDirectory();
150 childProcess.execFileSync(path.resolve(this._pgsqlDirectory, command),
151 [this._databaseName, '--host', this._databaseHost, '--port', this._databasePort].concat(args || []), options);
154 _determinePgsqlDirectory()
157 let initdbLocation = childProcess.execFileSync('which', ['initdb']);
158 return path.dirname(initdbLocation);
160 let serverPgsqlLocation = '/Applications/Server.app/Contents/ServerRoot/usr/bin/';
161 childProcess.execFileSync(path.resolve(serverPgsqlLocation, 'initdb'), ['--version']);
162 return serverPgsqlLocation;
168 let pidFile = Config.path('testServer.httpdPID');
169 let httpdConfig = Config.path('testServer.httpdConfig');
170 let port = Config.value('testServer.port');
171 let errorLog = Config.path('testServer.httpdErrorLog');
172 let mutexFile = Config.path('testServer.httpdMutexDir');
173 let phpVersion = childProcess.execFileSync('php', ['-v'], {stdio: ['pipe', 'pipe', 'ignore']}).toString().includes('PHP 5') ? 'PHP5' : 'PHP7';
175 if (!fs.existsSync(mutexFile))
176 fs.mkdirSync(mutexFile, 0o755);
180 '-c', `SetEnv ORG_WEBKIT_PERF_CONFIG_PATH ${this._testConfigPath}`,
181 '-c', `Listen ${port}`,
182 '-c', `PidFile ${pidFile}`,
183 '-c', `ErrorLog ${errorLog}`,
184 '-c', `Mutex file:${mutexFile}`,
185 '-c', `DocumentRoot ${Config.serverRoot()}`,
191 childProcess.execFileSync('httpd', args);
198 this._pidWaitStart = Date.now();
199 this._pidFile = pidFile;
201 this._remote = new RemoteAPI(this._server);
203 return new Promise(this._waitForPid.bind(this, true));
211 let pid = fs.readFileSync(this._pidFile, 'utf-8').trim();
214 console.log('Stopping', pid);
216 childProcess.execFileSync('kill', ['-TERM', pid]);
218 this._pidWaitStart = Date.now();
219 return new Promise(this._waitForPid.bind(this, false));
222 _waitForPid(shouldExist, resolve, reject)
224 if (fs.existsSync(this._pidFile) != shouldExist) {
225 if (Date.now() - this._pidWaitStart > 8000)
228 setTimeout(this._waitForPid.bind(this, shouldExist, resolve, reject), 100);
244 beforeEach(function () {
247 self.cleanDataDirectory();
248 originalRemote = global.RemoteAPI;
249 global.RemoteAPI = self._remote;
250 self._remote.clearCookies();
252 if (global.PrivilegedAPI) {
253 global.PrivilegedAPI._token = null;
254 global.PrivilegedAPI._expiration = null;
260 global.RemoteAPI = originalRemote;
266 if (!global.TestServer)
267 global.TestServer = new TestServer;
269 if (typeof module != 'undefined')
270 module.exports = global.TestServer;