Skip to content

Commit 886e015

Browse files
committed
test: add testing for new util
1 parent bc3b392 commit 886e015

File tree

3 files changed

+77
-17
lines changed

3 files changed

+77
-17
lines changed

packages/core/src/shared/clients/clientWrapper.ts

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -40,8 +40,7 @@ export abstract class ClientWrapper<C extends AwsClient> implements vscode.Dispo
4040
const makeRequest = withPerfLogOnFail(
4141
'API Request',
4242
() => this.getClient().send(new command(commandOptions)),
43-
truncateProps(commandOptions, 20, ['nextToken']),
44-
mapNameToCode
43+
truncateProps(commandOptions, 20, ['nextToken'])
4544
)
4645

4746
return makeRequest()
@@ -74,7 +73,3 @@ export abstract class ClientWrapper<C extends AwsClient> implements vscode.Dispo
7473
this.client?.destroy()
7574
}
7675
}
77-
78-
function mapNameToCode<E extends Error>(e: E): E & { code: string } {
79-
return { ...e, message: e.message, name: e.name, stack: e.stack, code: e.message }
80-
}

packages/core/src/shared/logger/perfLogger.ts

Lines changed: 26 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -31,34 +31,49 @@ export class PerfLog {
3131

3232
/**
3333
* Call a function f and if it fails, log the error with performance information included.
34-
* @param action label of action in the error log.
34+
* @param action label of action to include in the error log.
3535
* @param f action to attempt.
36-
* @param params params that were passed to f.
37-
* @param errMap optional mapping to apply to error to potentially add information.
36+
* @param params params that were passed to f. Defaults to empty.
37+
* @param getCode optional mapping to extract code from error. Defaults to name of error.
3838
* @returns result of f
3939
*/
40-
export function withPerfLogOnFail<Result, E extends Error = never>(
40+
export function withPerfLogOnFail<Result>(
41+
action: string,
42+
f: () => Result,
43+
params?: object,
44+
getCode?: (e: Error) => string
45+
): () => Result
46+
export function withPerfLogOnFail<Result>(
47+
action: string,
48+
f: () => Promise<Result>,
49+
params?: object,
50+
getCode?: (e: Error) => string
51+
): () => Promise<Result>
52+
export function withPerfLogOnFail<Result>(
4153
action: string,
4254
f: () => Result | Promise<Result>,
43-
params: object = {},
44-
errMap?: (e: Error) => E
55+
params?: object,
56+
getCode?: (e: Error) => string
4557
) {
46-
return async function () {
58+
return function () {
4759
const perflog = new PerfLog(action)
4860
try {
49-
return await f()
61+
return f()
5062
} catch (e) {
5163
if (e instanceof Error) {
52-
const errWithoutStack = errMap ? errMap(e) : { ...e }
64+
const errWithoutStack = { ...e, name: e.name, message: e.message }
5365
delete errWithoutStack['stack']
5466
const timecost = perflog.elapsed().toFixed(1)
5567
getLogger().error(
5668
`${action} failed (time: %dms) \nparams: %O\nerror: %O`,
5769
timecost,
58-
params,
70+
params ?? {},
5971
errWithoutStack
6072
)
61-
throw new ToolkitError(`${action}: ${e.message}`, { code: e.message, cause: e })
73+
throw new ToolkitError(`${action}: ${errWithoutStack.message}`, {
74+
code: getCode ? getCode(errWithoutStack) : errWithoutStack.name,
75+
cause: errWithoutStack,
76+
})
6277
}
6378
throw e
6479
}
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
/*!
2+
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
6+
import assert from 'assert'
7+
import { withPerfLogOnFail } from '../../../shared/logger/perfLogger'
8+
import { assertLogsContain } from '../../globalSetup.test'
9+
import { ToolkitError } from '../../../shared'
10+
11+
describe('withPerfLogOnFail', function () {
12+
it('only logs when function throws an error', function () {
13+
const happyFunction = withPerfLogOnFail('happyFunction', () => 5)
14+
const errorFunction = withPerfLogOnFail('errorFunction', () => {
15+
throw new Error('error')
16+
})
17+
assert.ok(happyFunction() === 5)
18+
assert.throws(() => assertLogsContain('happyFunction', false, 'error'))
19+
20+
assert.throws(() => errorFunction())
21+
assertLogsContain('errorFunction', false, 'error')
22+
})
23+
24+
it('wraps underlying error in a ToolkitError', function () {
25+
const errorFunction = withPerfLogOnFail('errorFunction', () => {
26+
throw new Error('error')
27+
})
28+
assert.throws(() => errorFunction(), ToolkitError)
29+
})
30+
31+
it('accepts custom error code mappings', function () {
32+
const errorFunction = withPerfLogOnFail(
33+
'errorFunction',
34+
() => {
35+
throw new Error('error')
36+
},
37+
{},
38+
(e) => e.message.slice(0, 3)
39+
)
40+
try {
41+
errorFunction()
42+
assert.fail('should have thrown')
43+
} catch (e) {
44+
if (!(e instanceof ToolkitError)) {
45+
assert.fail('should have thrown a ToolkitError')
46+
}
47+
assert.equal(e.code, 'err')
48+
}
49+
})
50+
})

0 commit comments

Comments
 (0)