Skip to content

Commit

Permalink
feat: process execution standardisation
Browse files Browse the repository at this point in the history
Standardised process execution for bin tests using `pkExec` and `pkSpawn`.

- All usage of `pkExec`/`pkSpawn` calls underlying default `WithoutShell` or override `WithShell` methods
- Combined `env` and `cwd` options into an `ExecOpts` object and added `command` and `shell` options
- Refactored `pkSpawnNs` and `pkExecNs` to use standardised methods
- Replaced all usage of `exec`/`execFile` with `spawn`
- error handling for generic exec/spawn + using new generic spawn in NAT utils
- ignore coverage from `src/proto`
- removed spawnfile
- added a check for if spawning process doesn't properly start
  • Loading branch information
emmacasolin authored and tegefaulkes committed Aug 10, 2022
1 parent 94ec1d2 commit 3da7b53
Show file tree
Hide file tree
Showing 51 changed files with 2,242 additions and 1,810 deletions.
4 changes: 4 additions & 0 deletions .eslintrc
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,10 @@
{
"name": "global",
"message": "Use `globalThis` instead"
},
{
"name": "window",
"message": "Use `globalThis` instead"
}
],
"require-yield": 0,
Expand Down
2 changes: 1 addition & 1 deletion jest.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ module.exports = {
reportTestSuiteErrors: 'true',
}],
],
collectCoverageFrom: ['src/**/*.{ts,tsx,js,jsx}', '!src/**/*.d.ts'],
collectCoverageFrom: ['src/**/*.{ts,tsx,js,jsx}', '!src/**/*.d.ts', '!src/proto/*'],
coverageReporters: ['text', 'cobertura'],
globals,
// Global setup script executed once before all test files
Expand Down
4 changes: 2 additions & 2 deletions src/bin/agent/CommandStart.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import type PolykeyAgent from '../../PolykeyAgent';
import type { RecoveryCode } from '../../keys/types';
import type { PolykeyWorkerManagerInterface } from '../../workers/types';
import path from 'path';
import child_process from 'child_process';
import childProcess from 'child_process';
import process from 'process';
import CommandPolykey from '../CommandPolykey';
import * as binUtils from '../utils';
Expand Down Expand Up @@ -130,7 +130,7 @@ class CommandStart extends CommandPolykey {
);
stdio[2] = agentErrFile.fd;
}
const agentProcess = child_process.fork(
const agentProcess = childProcess.fork(
path.join(__dirname, '../polykey-agent'),
[],
{
Expand Down
8 changes: 4 additions & 4 deletions tests/agent/service/notificationsSend.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ import * as utilsPB from '@/proto/js/polykey/v1/utils/utils_pb';
import * as notificationsPB from '@/proto/js/polykey/v1/notifications/notifications_pb';
import * as nodesUtils from '@/nodes/utils';
import * as notificationsUtils from '@/notifications/utils';
import { expectRemoteError } from '../../utils';
import * as testUtils from '../../utils';
import { globalRootKeyPems } from '../../fixtures/globalRootKeyPems';

describe('notificationsSend', () => {
Expand Down Expand Up @@ -225,7 +225,7 @@ describe('notificationsSend', () => {
};
const request1 = new notificationsPB.AgentNotification();
request1.setContent(notification1.toString());
await expectRemoteError(
await testUtils.expectRemoteError(
grpcClient.notificationsSend(request1),
notificationsErrors.ErrorNotificationsParse,
);
Expand Down Expand Up @@ -253,7 +253,7 @@ describe('notificationsSend', () => {
.sign(privateKey);
const request2 = new notificationsPB.AgentNotification();
request2.setContent(signedNotification);
await expectRemoteError(
await testUtils.expectRemoteError(
grpcClient.notificationsSend(request2),
notificationsErrors.ErrorNotificationsValidationFailed,
);
Expand All @@ -279,7 +279,7 @@ describe('notificationsSend', () => {
);
const request = new notificationsPB.AgentNotification();
request.setContent(signedNotification);
await expectRemoteError(
await testUtils.expectRemoteError(
grpcClient.notificationsSend(request),
notificationsErrors.ErrorNotificationsPermissionsNotFound,
);
Expand Down
52 changes: 21 additions & 31 deletions tests/bin/agent/lock.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import { mocked } from 'jest-mock';
import Logger, { LogLevel, StreamHandler } from '@matrixai/logger';
import Session from '@/sessions/Session';
import config from '@/config';
import * as execUtils from '../../utils/exec';
import * as testUtils from '../../utils';
import { globalRootKeyPems } from '../../fixtures/globalRootKeyPems';

Expand All @@ -18,7 +17,7 @@ describe('lock', () => {
let agentPassword: string;
let agentClose: () => Promise<void>;
beforeEach(async () => {
({ agentDir, agentPassword, agentClose } = await execUtils.setupTestAgent(
({ agentDir, agentPassword, agentClose } = await testUtils.setupTestAgent(
globalRootKeyPems[0],
logger,
));
Expand All @@ -29,21 +28,19 @@ describe('lock', () => {
testUtils.testIf(
testUtils.isTestPlatformEmpty || testUtils.isTestPlatformDocker,
)('lock deletes the session token', async () => {
await execUtils.pkStdio(
['agent', 'unlock'],
{
await testUtils.pkExec(['agent', 'unlock'], {
env: {
PK_NODE_PATH: agentDir,
PK_PASSWORD: agentPassword,
},
agentDir,
);
const { exitCode } = await execUtils.pkStdio(
['agent', 'lock'],
{
cwd: agentDir,
});
const { exitCode } = await testUtils.pkExec(['agent', 'lock'], {
env: {
PK_NODE_PATH: agentDir,
},
agentDir,
);
cwd: agentDir,
});
expect(exitCode).toBe(0);
const session = await Session.createSession({
sessionTokenPath: path.join(agentDir, config.defaults.tokenBase),
Expand All @@ -61,30 +58,23 @@ describe('lock', () => {
mockedPrompts.mockImplementation(async (_opts: any) => {
return { password };
});
await execUtils.pkStdio(
['agent', 'unlock'],
{
await testUtils.pkStdio(['agent', 'unlock'], {
env: {
PK_NODE_PATH: agentDir,
PK_PASSWORD: agentPassword,
},
agentDir,
);
cwd: agentDir,
});
// Session token is deleted
await execUtils.pkStdio(
['agent', 'lock'],
{
PK_NODE_PATH: agentDir,
},
agentDir,
);
await testUtils.pkStdio(['agent', 'lock'], {
env: { PK_NODE_PATH: agentDir },
cwd: agentDir,
});
// Will prompt to reauthenticate
await execUtils.pkStdio(
['agent', 'status'],
{
PK_NODE_PATH: agentDir,
},
agentDir,
);
await testUtils.pkStdio(['agent', 'status'], {
env: { PK_NODE_PATH: agentDir },
cwd: agentDir,
});
// Prompted for password 1 time
expect(mockedPrompts.mock.calls.length).toBe(1);
mockedPrompts.mockClear();
Expand Down
84 changes: 36 additions & 48 deletions tests/bin/agent/lockall.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import Logger, { LogLevel, StreamHandler } from '@matrixai/logger';
import Session from '@/sessions/Session';
import config from '@/config';
import * as errors from '@/errors';
import * as execUtils from '../../utils/exec';
import * as testUtils from '../../utils';
import { globalRootKeyPems } from '../../fixtures/globalRootKeyPems';

Expand All @@ -24,7 +23,7 @@ describe('lockall', () => {
let agentPassword;
let agentClose;
beforeEach(async () => {
({ agentDir, agentPassword, agentClose } = await execUtils.setupTestAgent(
({ agentDir, agentPassword, agentClose } = await testUtils.setupTestAgent(
globalRootKeyPems[0],
logger,
));
Expand All @@ -35,21 +34,17 @@ describe('lockall', () => {
testUtils.testIf(
testUtils.isTestPlatformEmpty || testUtils.isTestPlatformDocker,
)('lockall deletes the session token', async () => {
await execUtils.pkStdio(
['agent', 'unlock'],
{
await testUtils.pkExec(['agent', 'unlock'], {
env: {
PK_NODE_PATH: agentDir,
PK_PASSWORD: agentPassword,
},
agentDir,
);
const { exitCode } = await execUtils.pkStdio(
['agent', 'lockall'],
{
PK_NODE_PATH: agentDir,
},
agentDir,
);
cwd: agentDir,
});
const { exitCode } = await testUtils.pkExec(['agent', 'lockall'], {
env: { PK_NODE_PATH: agentDir },
cwd: agentDir,
});
expect(exitCode).toBe(0);
const session = await Session.createSession({
sessionTokenPath: path.join(agentDir, config.defaults.tokenBase),
Expand All @@ -63,33 +58,26 @@ describe('lockall', () => {
'lockall ensures reauthentication is required',
async () => {
const password = agentPassword;
await execUtils.pkStdio(
['agent', 'unlock'],
{
await testUtils.pkStdio(['agent', 'unlock'], {
env: {
PK_NODE_PATH: agentDir,
PK_PASSWORD: agentPassword,
},
agentDir,
);
await execUtils.pkStdio(
['agent', 'lockall'],
{
PK_NODE_PATH: agentDir,
},
agentDir,
);
cwd: agentDir,
});
await testUtils.pkStdio(['agent', 'lockall'], {
env: { PK_NODE_PATH: agentDir },
cwd: agentDir,
});
// Token is deleted, reauthentication is required
mockedPrompts.mockClear();
mockedPrompts.mockImplementation(async (_opts: any) => {
return { password };
});
await execUtils.pkStdio(
['agent', 'status'],
{
PK_NODE_PATH: agentDir,
},
agentDir,
);
await testUtils.pkStdio(['agent', 'status'], {
env: { PK_NODE_PATH: agentDir },
cwd: agentDir,
});
// Prompted for password 1 time
expect(mockedPrompts.mock.calls.length).toBe(1);
mockedPrompts.mockClear();
Expand All @@ -98,39 +86,39 @@ describe('lockall', () => {
testUtils.testIf(
testUtils.isTestPlatformEmpty || testUtils.isTestPlatformDocker,
)('lockall causes old session tokens to fail', async () => {
await execUtils.pkStdio(
['agent', 'unlock'],
{
await testUtils.pkExec(['agent', 'unlock'], {
env: {
PK_NODE_PATH: agentDir,
PK_PASSWORD: agentPassword,
},
agentDir,
);
cwd: agentDir,
});
const session = await Session.createSession({
sessionTokenPath: path.join(agentDir, config.defaults.tokenBase),
fs,
logger,
});
const token = await session.readToken();
await session.stop();
await execUtils.pkStdio(
['agent', 'lockall'],
{
await testUtils.pkExec(['agent', 'lockall'], {
env: {
PK_NODE_PATH: agentDir,
PK_PASSWORD: agentPassword,
},
agentDir,
);
cwd: agentDir,
});
// Old token is invalid
const { exitCode, stderr } = await execUtils.pkStdio(
const { exitCode, stderr } = await testUtils.pkExec(
['agent', 'status', '--format', 'json'],
{
PK_NODE_PATH: agentDir,
PK_TOKEN: token,
env: {
PK_NODE_PATH: agentDir,
PK_TOKEN: token,
},
cwd: agentDir,
},
agentDir,
);
execUtils.expectProcessError(exitCode, stderr, [
testUtils.expectProcessError(exitCode, stderr, [
new errors.ErrorClientAuthDenied(),
]);
});
Expand Down
Loading

0 comments on commit 3da7b53

Please sign in to comment.