Skip to content

Commit 7491144

Browse files
committed
chore: added tests for client protocol
1 parent 6e322ce commit 7491144

File tree

8 files changed

+105
-13
lines changed

8 files changed

+105
-13
lines changed

src/client/errors.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,11 @@ class ErrorClientInvalidHeader<T> extends ErrorClient<T> {
2323
exitCode = sysexits.USAGE;
2424
}
2525

26+
class ErrorClientProtocolError<T> extends ErrorClient<T> {
27+
static description = 'Data does not match the protocol requirements';
28+
exitCode = sysexits.USAGE;
29+
}
30+
2631
class ErrorClientService<T> extends ErrorClient<T> {}
2732

2833
class ErrorClientServiceRunning<T> extends ErrorClientService<T> {
@@ -51,6 +56,7 @@ export {
5156
ErrorClientAuthFormat,
5257
ErrorClientAuthDenied,
5358
ErrorClientInvalidHeader,
59+
ErrorClientProtocolError,
5460
ErrorClientService,
5561
ErrorClientServiceRunning,
5662
ErrorClientServiceNotRunning,

src/client/handlers/VaultsSecretsRemove.ts

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -35,11 +35,13 @@ class VaultsSecretsRemove extends DuplexHandler<
3535
const { db, vaultManager }: { db: DB; vaultManager: VaultManager } =
3636
this.container;
3737
// Extract the header message from the iterator
38+
const headerMessagePair = await input.next();
3839
const headerMessage:
3940
| SecretsRemoveHeaderMessage
40-
| SecretIdentifierMessageTagged = (await input.next()).value;
41+
| SecretIdentifierMessageTagged = headerMessagePair.value;
42+
// Testing if the header is of the expected format
4143
if (
42-
headerMessage == null ||
44+
headerMessagePair.done ||
4345
headerMessage.type !== 'VaultNamesHeaderMessage'
4446
) {
4547
throw new clientErrors.ErrorClientInvalidHeader();
@@ -72,10 +74,12 @@ class VaultsSecretsRemove extends DuplexHandler<
7274
for (let i = 0; i < efses.length; i++) {
7375
vaultMap.set(headerMessage!.vaultNames[i], efses[i]);
7476
}
77+
let loopRan = false;
7578
for await (const message of input) {
76-
// Ignoring any header messages
79+
loopRan = true;
80+
// Header messages should not be seen anymore
7781
if (message.type === 'VaultNamesHeaderMessage') {
78-
throw new clientErrors.ErrorClientInvalidHeader(
82+
throw new clientErrors.ErrorClientProtocolError(
7983
'The header message cannot be sent multiple times',
8084
);
8185
}
@@ -116,6 +120,12 @@ class VaultsSecretsRemove extends DuplexHandler<
116120
}
117121
}
118122
}
123+
// Content messages must follow header messages
124+
if (!loopRan) {
125+
throw new clientErrors.ErrorClientProtocolError(
126+
'No content messages followed header message',
127+
);
128+
}
119129
},
120130
);
121131
};

src/git/utils.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -218,7 +218,9 @@ async function listObjects({
218218
}
219219
return;
220220
default:
221-
utils.never('Invalid type');
221+
utils.never(
222+
`type must be one of "commit", "tree", "blob", or "tag", got "${type}"`,
223+
);
222224
}
223225
}
224226

src/vaults/VaultInternal.ts

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -596,9 +596,6 @@ class VaultInternal {
596596
await this.createCommit();
597597
} catch (e_) {
598598
e = e_;
599-
}
600-
// This would happen if an error was caught inside the catch block
601-
if (e != null) {
602599
// Error implies dirty state
603600
await this.cleanWorkingDirectory();
604601
}

tests/audit/utils.test.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ describe('Audit Utils', () => {
4747
['f'],
4848
['f'],
4949
];
50+
// @ts-ignore: treating TopicSubPath as string for testing
5051
const filtered = auditUtils.filterSubPaths(data).map((v) => v.join('.'));
5152
expect(filtered).toHaveLength(3);
5253
expect(filtered).toInclude('a.b');

tests/client/handlers/nodes.test.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -825,7 +825,6 @@ describe('nodesGetAll', () => {
825825
manifest: {
826826
nodesGetAll: new NodesGetAll({
827827
nodeGraph,
828-
keyRing,
829828
}),
830829
},
831830
host: localhost,

tests/client/handlers/vaults.test.ts

Lines changed: 78 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ import * as keysUtils from '@/keys/utils';
7070
import * as nodesUtils from '@/nodes/utils';
7171
import * as vaultsUtils from '@/vaults/utils';
7272
import * as vaultsErrors from '@/vaults/errors';
73+
import * as clientErrors from '@/client/errors';
7374
import * as networkUtils from '@/network/utils';
7475
import * as utils from '@/utils';
7576
import * as testsUtils from '../../utils';
@@ -2356,6 +2357,80 @@ describe('vaultsSecretsRemove', () => {
23562357
recursive: true,
23572358
});
23582359
});
2360+
test('fails when header is not sent', async () => {
2361+
// Write paths
2362+
const response = await rpcClient.methods.vaultsSecretsRemove();
2363+
const writer = response.writable.getWriter();
2364+
// Not sending the header message
2365+
// Content messages
2366+
await writer.write({
2367+
type: 'SecretIdentifierMessage',
2368+
nameOrId: 'invalid',
2369+
secretName: 'invalid',
2370+
});
2371+
await writer.close();
2372+
// Read response
2373+
const consumeP = async () => {
2374+
for await (const _ of response.readable) {
2375+
// Consume values
2376+
}
2377+
};
2378+
await testsUtils.expectRemoteError(
2379+
consumeP(),
2380+
clientErrors.ErrorClientInvalidHeader,
2381+
);
2382+
});
2383+
test('fails when only the header is sent', async () => {
2384+
const vaultId = await vaultManager.createVault('test-vault');
2385+
const vaultIdEncoded = vaultsUtils.encodeVaultId(vaultId);
2386+
// Write paths
2387+
const response = await rpcClient.methods.vaultsSecretsRemove();
2388+
const writer = response.writable.getWriter();
2389+
// Header message
2390+
await writer.write({
2391+
type: 'VaultNamesHeaderMessage',
2392+
vaultNames: [vaultIdEncoded],
2393+
});
2394+
// Not sending the content messages
2395+
await writer.close();
2396+
// Read response
2397+
const consumeP = async () => {
2398+
for await (const _ of response.readable) {
2399+
// Consume values
2400+
}
2401+
};
2402+
await testsUtils.expectRemoteError(
2403+
consumeP(),
2404+
clientErrors.ErrorClientProtocolError,
2405+
);
2406+
});
2407+
test('fails when the header is sent multiple times', async () => {
2408+
const vaultId = await vaultManager.createVault('test-vault');
2409+
const vaultIdEncoded = vaultsUtils.encodeVaultId(vaultId);
2410+
// Write paths
2411+
const response = await rpcClient.methods.vaultsSecretsRemove();
2412+
const writer = response.writable.getWriter();
2413+
// Header message
2414+
await writer.write({
2415+
type: 'VaultNamesHeaderMessage',
2416+
vaultNames: [vaultIdEncoded],
2417+
});
2418+
await writer.write({
2419+
type: 'VaultNamesHeaderMessage',
2420+
vaultNames: [vaultIdEncoded],
2421+
});
2422+
await writer.close();
2423+
// Read response
2424+
const consumeP = async () => {
2425+
for await (const _ of response.readable) {
2426+
// Consume values
2427+
}
2428+
};
2429+
await testsUtils.expectRemoteError(
2430+
consumeP(),
2431+
clientErrors.ErrorClientProtocolError,
2432+
);
2433+
});
23592434
test('fails with invalid vault name', async () => {
23602435
// Write paths
23612436
const response = await rpcClient.methods.vaultsSecretsRemove();
@@ -2374,7 +2449,9 @@ describe('vaultsSecretsRemove', () => {
23742449
await writer.close();
23752450
// Read response
23762451
const consumeP = async () => {
2377-
for await (const _ of response.readable);
2452+
for await (const _ of response.readable) {
2453+
// Consume values
2454+
}
23782455
};
23792456
await testsUtils.expectRemoteError(
23802457
consumeP(),

tests/git/utils.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,8 @@ type NegotiationTestData =
9090
* @param rest - Random buffer data to be appended to the end to simulate more lines in the stream.
9191
*/
9292
function generateGitNegotiationLine(data: NegotiationTestData, rest: Buffer) {
93-
switch (data.type) {
93+
const type = data.type;
94+
switch (type) {
9495
case 'want': {
9596
// Generate a `want` line that includes `want`, the `objectId` and capabilities
9697
const line = Buffer.concat([
@@ -123,9 +124,8 @@ function generateGitNegotiationLine(data: NegotiationTestData, rest: Buffer) {
123124
// Generate an empty buffer to simulate the stream running out of data to process
124125
return Buffer.alloc(0);
125126
default:
126-
// @ts-ignore: if we're here then data isn't the type we expect
127127
utils.never(
128-
`data.type must be "want", "have", "SEPARATOR", "done", "none", got "${data.type}"`,
128+
`data.type must be "want", "have", "SEPARATOR", "done", "none", got "${type}"`,
129129
);
130130
}
131131
}

0 commit comments

Comments
 (0)