mirror of
https://github.com/meteor/meteor.git
synced 2026-05-02 03:01:46 -04:00
* implement tests to tweak socket files behaviors and group config
* re-run checks
* better test coverage on UNIX_SOCKET_PATH and UNIX_SOCKET_GROUP usage
* create socker file as part of the tests
* replace @vlasky/whomst dependency to use a unix-standard way to get gid from group name
* ensure test cross-compatibility on unix/macos
* clean
* register cleanup
* ensure close properly the net server instantiated
* temporary comment a test to see if CI passes
* Revert "temporary comment a test to see if CI passes"
This reverts commit 22b6517860.
* verify if new test is the culprit
* establish port
* establish port
* silent one test to see if CI fixed
* activate other test within the testAsyncMulti as may be the culprit on CI failure
* try set permissions as well
* print /etc/group
* use travis group
* ensure use proper group on travis CI to fix tests
* silent get group info logs
---------
Co-authored-by: Denilson <denilsonh2014@gmail.com>
149 lines
4.2 KiB
JavaScript
149 lines
4.2 KiB
JavaScript
import { writeFileSync, unlinkSync, statSync, readFileSync } from 'fs';
|
|
import { createServer } from 'net';
|
|
import { createServer as createServerHttp } from 'http';
|
|
import {
|
|
removeExistingSocketFile,
|
|
registerSocketFileCleanup,
|
|
} from './socket_file.js';
|
|
import { EventEmitter } from 'events';
|
|
import { tmpdir, userInfo, platform } from 'os';
|
|
import { main, getGroupInfo } from './webapp_server';
|
|
import express from 'express';
|
|
|
|
const testSocketFile = `${tmpdir()}/socket_file_tests`;
|
|
|
|
const getChownInfo = async (filePath) => {
|
|
try {
|
|
const stats = await statSync(filePath);
|
|
return { uid: stats.uid, gid: stats.gid };
|
|
} catch (error) {
|
|
console.error(`Error fetching ownership info for ${filePath}:`, error.message);
|
|
return null;
|
|
}
|
|
};
|
|
|
|
const isMacOS = () => {
|
|
return platform() === 'darwin';
|
|
};
|
|
|
|
const removeTestSocketFile = () => {
|
|
try {
|
|
unlinkSync(testSocketFile);
|
|
} catch (error) {
|
|
// Do nothing
|
|
}
|
|
}
|
|
|
|
Tinytest.add("socket file - don't remove a non-socket file", test => {
|
|
writeFileSync(testSocketFile, "");
|
|
test.throws(
|
|
() => { removeExistingSocketFile(testSocketFile); },
|
|
/An existing file was found/
|
|
);
|
|
removeTestSocketFile()
|
|
});
|
|
|
|
Tinytest.addAsync(
|
|
'socket file - remove a previously existing socket file',
|
|
(test, done) => {
|
|
removeTestSocketFile();
|
|
const server = createServer();
|
|
server.listen(testSocketFile);
|
|
|
|
server.on('listening', Meteor.bindEnvironment(() => {
|
|
test.isNotUndefined(statSync(testSocketFile));
|
|
removeExistingSocketFile(testSocketFile);
|
|
test.throws(
|
|
() => { statSync(testSocketFile); },
|
|
/ENOENT/
|
|
);
|
|
server.close();
|
|
done();
|
|
}));
|
|
}
|
|
);
|
|
|
|
Tinytest.add(
|
|
'socket file - no existing socket file, nothing to remove',
|
|
test => {
|
|
removeTestSocketFile();
|
|
removeExistingSocketFile(testSocketFile);
|
|
}
|
|
);
|
|
|
|
Tinytest.add('socket file - remove socket file on exit', test => {
|
|
const testEventEmitter = new EventEmitter();
|
|
registerSocketFileCleanup(testSocketFile, testEventEmitter);
|
|
['exit', 'SIGINT', 'SIGHUP', 'SIGTERM'].forEach(signal => {
|
|
writeFileSync(testSocketFile, "");
|
|
test.isNotUndefined(statSync(testSocketFile));
|
|
testEventEmitter.emit(signal);
|
|
test.throws(
|
|
() => { statSync(testSocketFile); },
|
|
/ENOENT/
|
|
);
|
|
});
|
|
});
|
|
|
|
function prepareServer() {
|
|
removeTestSocketFile();
|
|
removeExistingSocketFile(testSocketFile);
|
|
const testEventEmitter = new EventEmitter();
|
|
registerSocketFileCleanup(testSocketFile, testEventEmitter);
|
|
const server = createServer();
|
|
server.listen(testSocketFile);
|
|
const app = express();
|
|
const httpServer = createServerHttp(app);
|
|
return { httpServer, server };
|
|
}
|
|
|
|
function closeServer({ httpServer, server }) {
|
|
return new Promise((resolve) => {
|
|
httpServer.on(
|
|
"listening",
|
|
Meteor.bindEnvironment(() => {
|
|
process.env.UNIX_SOCKET_PATH = "";
|
|
process.env.UNIX_SOCKET_GROUP = "";
|
|
removeExistingSocketFile(testSocketFile);
|
|
server.close();
|
|
httpServer.close();
|
|
resolve();
|
|
})
|
|
);
|
|
});
|
|
}
|
|
|
|
testAsyncMulti(
|
|
"socket usage - use socket file for inter-process communication",
|
|
[
|
|
async (test) => {
|
|
// use UNIX_SOCKET_PATH
|
|
const { httpServer, server } = prepareServer();
|
|
|
|
process.env.UNIX_SOCKET_PATH = testSocketFile;
|
|
const result = await main({ httpServer });
|
|
|
|
test.equal(result, "DAEMON");
|
|
const currentGid = userInfo({ encoding: "utf8" })?.gid;
|
|
test.equal((await getChownInfo(testSocketFile))?.gid, currentGid);
|
|
|
|
return closeServer({ httpServer, server });
|
|
},
|
|
async (test) => {
|
|
// use UNIX_SOCKET_PATH and UNIX_SOCKET_GROUP
|
|
const { httpServer, server } = prepareServer();
|
|
|
|
const groupToUse = Boolean(process.env.TRAVIS) && 'travis' || (isMacOS() ? 'staff' : 'root');
|
|
process.env.UNIX_SOCKET_PATH = testSocketFile;
|
|
process.env.UNIX_SOCKET_GROUP = groupToUse;
|
|
process.env.UNIX_SOCKET_PERMISSIONS = '777';
|
|
const result = await main({ httpServer });
|
|
|
|
test.equal(result, "DAEMON");
|
|
test.equal((await getChownInfo(testSocketFile))?.gid, getGroupInfo(process.env.UNIX_SOCKET_GROUP)?.gid);
|
|
|
|
return closeServer({ httpServer, server });
|
|
},
|
|
]
|
|
);
|