Skip to content

Commit 26b3d3d

Browse files
committed
chore: wrap tests in describe() and run concurrently
1 parent a7aed58 commit 26b3d3d

10 files changed

+689
-578
lines changed

test/unit/deployment-files.spec.ts

Lines changed: 18 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -7,19 +7,24 @@ import { config } from '../../src/common/config';
77
* Note that these checks are also performed at runtime on the deployed snyk-monitor, see the integration tests.
88
*/
99

10-
test('ensure the security properties of the deployment files are unchanged', async () => {
11-
expect(config.IMAGE_STORAGE_ROOT).toEqual('/var/tmp');
12-
13-
const deploymentFiles = ['./snyk-monitor-deployment.yaml'];
14-
15-
for (const filePath of deploymentFiles) {
16-
const fileContent = readFileSync(filePath, 'utf8');
17-
const deployment: V1Deployment = parse(fileContent);
18-
19-
validateSecureConfiguration(deployment);
20-
validateVolumeMounts(deployment);
21-
validateEnvironmentVariables(deployment);
22-
}
10+
describe('deployment files tests', () => {
11+
test.concurrent(
12+
'ensure the security properties of the deployment files are unchanged',
13+
async () => {
14+
expect(config.IMAGE_STORAGE_ROOT).toEqual('/var/tmp');
15+
16+
const deploymentFiles = ['./snyk-monitor-deployment.yaml'];
17+
18+
for (const filePath of deploymentFiles) {
19+
const fileContent = readFileSync(filePath, 'utf8');
20+
const deployment: V1Deployment = parse(fileContent);
21+
22+
validateSecureConfiguration(deployment);
23+
validateVolumeMounts(deployment);
24+
validateEnvironmentVariables(deployment);
25+
}
26+
},
27+
);
2328
});
2429

2530
export function validateEnvironmentVariables(deployment: V1Deployment) {

test/unit/scanner/image-registry-credentials.spec.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import * as credentials from '../../../src/scanner/images/credentials';
22

33
describe('ECR image parsing tests', () => {
4-
test('ecrRegionFromFullImageName()', async () => {
4+
test.concurrent('ecrRegionFromFullImageName()', async () => {
55
const imageFullNameTemplate = 'aws_account_id.dkr.ecr.region.amazonaws.com/my-web-app:latest';
66
const ecrRegionTemplate = credentials.ecrRegionFromFullImageName(imageFullNameTemplate);
77
expect(ecrRegionTemplate).toEqual('region');
@@ -16,7 +16,7 @@ describe('ECR image parsing tests', () => {
1616
expect(() => {credentials.ecrRegionFromFullImageName('aws_account_id.dkr.ecr.region.amazonaws.com');}).toThrow();
1717
});
1818

19-
test('isEcrSource()', async () => {
19+
test.concurrent('isEcrSource()', async () => {
2020
const sourceCredentialsForRandomImageName = credentials.isEcrSource('derka');
2121
expect(sourceCredentialsForRandomImageName).toEqual(false);
2222

test/unit/scanner/index.spec.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import * as scanner from '../../../src/scanner';
22
import { IWorkload } from '../../../src/transmitter/types';
33

44
describe('scanner module tests', () => {
5-
test('getUniqueImages()', async () => {
5+
test.concurrent('getUniqueImages()', async () => {
66
const workload: Partial<IWorkload>[] = [
77
// 1.DCR
88
{

test/unit/scanner/skopeo.spec.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import * as skopeo from '../../../src/scanner/images/skopeo';
22

33
describe('skopeo module tests', () => {
4-
test('getCredentialParameters()', async () => {
4+
test.concurrent('getCredentialParameters()', async () => {
55
const noCredentials = undefined;
66
const credentialParametersForNoCredentials = skopeo.getCredentialParameters(noCredentials);
77
expect(credentialParametersForNoCredentials).toEqual([]);
Lines changed: 209 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,209 @@
1+
import * as http from 'http';
2+
import * as kubernetesApiWrappers from '../../../src/supervisor/kuberenetes-api-wrappers';
3+
4+
describe('kubernetes api wrappers', () => {
5+
test.concurrent('calculateSleepSeconds', async () => {
6+
const responseWithoutHeaders = {};
7+
expect(
8+
kubernetesApiWrappers.calculateSleepSeconds(
9+
responseWithoutHeaders as http.IncomingMessage,
10+
),
11+
).toEqual(kubernetesApiWrappers.DEFAULT_SLEEP_SEC);
12+
13+
const responseWithNegativeSeconds = { headers: { 'Retry-After': -3 } };
14+
expect(
15+
kubernetesApiWrappers.calculateSleepSeconds(
16+
(responseWithNegativeSeconds as unknown) as http.IncomingMessage,
17+
),
18+
).toEqual(kubernetesApiWrappers.DEFAULT_SLEEP_SEC);
19+
20+
const responseWithZeroSeconds = { headers: { 'Retry-After': 0 } };
21+
expect(
22+
kubernetesApiWrappers.calculateSleepSeconds(
23+
(responseWithZeroSeconds as unknown) as http.IncomingMessage,
24+
),
25+
).toEqual(kubernetesApiWrappers.DEFAULT_SLEEP_SEC);
26+
27+
const responseWithDate = {
28+
headers: { 'Retry-After': 'Fri, 31 Dec 1999 23:59:59 GMT' },
29+
};
30+
expect(
31+
kubernetesApiWrappers.calculateSleepSeconds(
32+
(responseWithDate as unknown) as http.IncomingMessage,
33+
),
34+
).toEqual(kubernetesApiWrappers.DEFAULT_SLEEP_SEC);
35+
36+
const responseWithHighSecondsMock = { headers: { 'Retry-After': 55 } };
37+
expect(
38+
kubernetesApiWrappers.calculateSleepSeconds(
39+
(responseWithHighSecondsMock as unknown) as http.IncomingMessage,
40+
),
41+
).toEqual(kubernetesApiWrappers.MAX_SLEEP_SEC);
42+
43+
const responseWithSecondsMock = { headers: { 'Retry-After': 4 } };
44+
expect(
45+
kubernetesApiWrappers.calculateSleepSeconds(
46+
(responseWithSecondsMock as unknown) as http.IncomingMessage,
47+
),
48+
).toEqual(4);
49+
});
50+
51+
test.concurrent(
52+
'retryKubernetesApiRequest for ECONNREFUSED error',
53+
async () => {
54+
const retryableErrorResponse = { code: 'ECONNREFUSED' };
55+
56+
await expect(async () =>
57+
kubernetesApiWrappers.retryKubernetesApiRequest(() =>
58+
Promise.reject(retryableErrorResponse),
59+
),
60+
).rejects.toEqual({ code: 'ECONNREFUSED' });
61+
62+
let failures = 0;
63+
const functionThatFailsJustEnoughTimes = () => {
64+
if (failures < kubernetesApiWrappers.ATTEMPTS_MAX - 1) {
65+
failures += 1;
66+
return Promise.reject(retryableErrorResponse);
67+
}
68+
return Promise.resolve('egg');
69+
};
70+
71+
const successfulResponse = await kubernetesApiWrappers.retryKubernetesApiRequest(
72+
functionThatFailsJustEnoughTimes,
73+
);
74+
expect(successfulResponse).toEqual('egg');
75+
76+
failures = 0;
77+
const functionThatFailsOneTooManyTimes = () => {
78+
if (failures < kubernetesApiWrappers.ATTEMPTS_MAX) {
79+
failures += 1;
80+
return Promise.reject(retryableErrorResponse);
81+
}
82+
return Promise.resolve('egg');
83+
};
84+
85+
await expect(async () =>
86+
kubernetesApiWrappers.retryKubernetesApiRequest(
87+
functionThatFailsOneTooManyTimes,
88+
),
89+
).rejects.toEqual({ code: 'ECONNREFUSED' });
90+
},
91+
);
92+
93+
test.concurrent('retryKubernetesApiRequest for ETIMEDOUT error', async () => {
94+
const retryableErrorResponse = { code: 'ETIMEDOUT' };
95+
96+
await expect(async () =>
97+
kubernetesApiWrappers.retryKubernetesApiRequest(() =>
98+
Promise.reject(retryableErrorResponse),
99+
),
100+
).rejects.toEqual({ code: 'ETIMEDOUT' });
101+
102+
let failures = 0;
103+
const functionThatFailsJustEnoughTimes = () => {
104+
if (failures < kubernetesApiWrappers.ATTEMPTS_MAX - 1) {
105+
failures += 1;
106+
return Promise.reject(retryableErrorResponse);
107+
}
108+
return Promise.resolve('egg');
109+
};
110+
111+
const successfulResponse = await kubernetesApiWrappers.retryKubernetesApiRequest(
112+
functionThatFailsJustEnoughTimes,
113+
);
114+
expect(successfulResponse).toEqual('egg');
115+
116+
failures = 0;
117+
const functionThatFailsOneTooManyTimes = () => {
118+
if (failures < kubernetesApiWrappers.ATTEMPTS_MAX) {
119+
failures += 1;
120+
return Promise.reject(retryableErrorResponse);
121+
}
122+
return Promise.resolve('egg');
123+
};
124+
125+
await expect(async () =>
126+
kubernetesApiWrappers.retryKubernetesApiRequest(
127+
functionThatFailsOneTooManyTimes,
128+
),
129+
).rejects.toEqual({ code: 'ETIMEDOUT' });
130+
});
131+
132+
test.concurrent(
133+
'retryKubernetesApiRequest for retryable errors',
134+
async () => {
135+
const retryableErrorResponse = { response: { statusCode: 429 } };
136+
137+
await expect(async () =>
138+
kubernetesApiWrappers.retryKubernetesApiRequest(() =>
139+
Promise.reject(retryableErrorResponse),
140+
),
141+
).rejects.toEqual({ response: { statusCode: 429 } });
142+
143+
let failures = 0;
144+
const functionThatFailsJustEnoughTimes = () => {
145+
if (failures < kubernetesApiWrappers.ATTEMPTS_MAX - 1) {
146+
failures += 1;
147+
return Promise.reject(retryableErrorResponse);
148+
}
149+
return Promise.resolve('egg');
150+
};
151+
152+
const successfulResponse = await kubernetesApiWrappers.retryKubernetesApiRequest(
153+
functionThatFailsJustEnoughTimes,
154+
);
155+
expect(successfulResponse).toEqual('egg');
156+
157+
failures = 0;
158+
const functionThatFailsOneTooManyTimes = () => {
159+
if (failures < kubernetesApiWrappers.ATTEMPTS_MAX) {
160+
failures += 1;
161+
return Promise.reject(retryableErrorResponse);
162+
}
163+
return Promise.resolve('egg');
164+
};
165+
166+
await expect(async () =>
167+
kubernetesApiWrappers.retryKubernetesApiRequest(
168+
functionThatFailsOneTooManyTimes,
169+
),
170+
).rejects.toEqual({ response: { statusCode: 429 } });
171+
},
172+
);
173+
174+
test.concurrent(
175+
'retryKubernetesApiRequest for non-retryable errors',
176+
async () => {
177+
const nonRetryableErrorResponse = { response: { statusCode: 500 } };
178+
179+
let failures = 0;
180+
const functionThatFails = () => {
181+
failures += 1;
182+
return Promise.reject(nonRetryableErrorResponse);
183+
};
184+
185+
await expect(async () =>
186+
kubernetesApiWrappers.retryKubernetesApiRequest(functionThatFails),
187+
).rejects.toEqual({ response: { statusCode: 500 } });
188+
expect(failures).toEqual(1);
189+
},
190+
);
191+
192+
test.concurrent(
193+
'retryKubernetesApiRequest for errors without response',
194+
async () => {
195+
const errorWithoutResponse = "there's butter on my face!";
196+
197+
let failures = 0;
198+
const functionThatFails = () => {
199+
failures += 1;
200+
return Promise.reject(new Error(errorWithoutResponse));
201+
};
202+
203+
await expect(async () =>
204+
kubernetesApiWrappers.retryKubernetesApiRequest(functionThatFails),
205+
).rejects.toThrow(new Error(errorWithoutResponse));
206+
expect(failures).toEqual(1);
207+
},
208+
);
209+
});

0 commit comments

Comments
 (0)