Skip to content

Commit

Permalink
refactor: use custom CronError
Browse files Browse the repository at this point in the history
  • Loading branch information
sheerlox committed Oct 26, 2023
1 parent 0334030 commit 6b36b67
Show file tree
Hide file tree
Showing 5 changed files with 33 additions and 51 deletions.
4 changes: 3 additions & 1 deletion src/errors.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
export class ExclusiveParametersError extends Error {
export class CronError extends Error {}

export class ExclusiveParametersError extends CronError {
constructor(param1: string, param2: string) {
super(`You can't specify both ${param1} and ${param2}`);
}
Expand Down
4 changes: 2 additions & 2 deletions src/job.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { spawn } from 'child_process';
import { ExclusiveParametersError } from './errors';
import { CronError, ExclusiveParametersError } from './errors';
import { CronTime } from './time';
import {
CronCallback,
Expand Down Expand Up @@ -172,7 +172,7 @@ export class CronJob<OC extends CronOnCompleteCommand | null = null, C = null> {

setTime(time: CronTime) {
if (!(time instanceof CronTime)) {
throw new Error('time must be an instance of CronTime.');
throw new CronError('time must be an instance of CronTime.');
}
const wasRunning = this.running;
this.stop();
Expand Down
34 changes: 18 additions & 16 deletions src/time.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import {
TIME_UNITS_LEN,
TIME_UNITS_MAP
} from './constants';
import { ExclusiveParametersError } from './errors';
import { CronError, ExclusiveParametersError } from './errors';
import {
CronJobParams,
DayOfMonthRange,
Expand Down Expand Up @@ -59,7 +59,7 @@ export class CronTime {
if (timeZone) {
const dt = DateTime.fromObject({}, { zone: timeZone });
if (!dt.isValid) {
throw new Error('Invalid timezone.');
throw new CronError('Invalid timezone.');
}

this.timeZone = timeZone;
Expand Down Expand Up @@ -157,13 +157,13 @@ export class CronTime {
date = date.setZone(utcZone);

if (!date.isValid) {
throw new Error('ERROR: You specified an invalid UTC offset.');
throw new CronError('ERROR: You specified an invalid UTC offset.');
}
}

if (this.realDate) {
if (DateTime.local() > date) {
throw new Error('WARNING: Date in past. Will never be fired.');
throw new CronError('WARNING: Date in past. Will never be fired.');
}

return date;
Expand Down Expand Up @@ -240,7 +240,7 @@ export class CronTime {
}

if (!date.isValid) {
throw new Error('ERROR: You specified an invalid date.');
throw new CronError('ERROR: You specified an invalid date.');
}

/**
Expand All @@ -258,7 +258,7 @@ export class CronTime {

// hard stop if the current date is after the maximum match interval
if (date > maxMatch) {
throw new Error(
throw new CronError(
`Something went wrong. No execution date was found in the next 8 years.
Please provide the following string if you would like to help debug:
Time Zone: ${
Expand Down Expand Up @@ -433,7 +433,7 @@ export class CronTime {
let iteration = 0;
do {
if (++iteration > iterationLimit) {
throw new Error(
throw new CronError(
`ERROR: This DST checking related function assumes the input DateTime (${
date.toISO() ?? date.toMillis()
}) is within 24 hours of a DST jump.`
Expand Down Expand Up @@ -583,7 +583,7 @@ export class CronTime {
endMinute: number
) {
if (startHour >= endHour) {
throw new Error(
throw new CronError(
`ERROR: This DST checking related function assumes the forward jump starting hour (${startHour}) is less than the end hour (${endHour})`
);
}
Expand Down Expand Up @@ -707,18 +707,18 @@ export class CronTime {
return ALIASES[alias as keyof typeof ALIASES].toString();
}

throw new Error(`Unknown alias: ${alias}`);
throw new CronError(`Unknown alias: ${alias}`);
});

const units = source.trim().split(/\s+/);

// seconds are optional
if (units.length < TIME_UNITS_LEN - 1) {
throw new Error('Too few fields');
throw new CronError('Too few fields');
}

if (units.length > TIME_UNITS_LEN) {
throw new Error('Too many fields');
throw new CronError('Too many fields');
}

const unitsLen = units.length;
Expand Down Expand Up @@ -756,7 +756,9 @@ export class CronTime {
fields.forEach(field => {
const wildcardIndex = field.indexOf('*');
if (wildcardIndex !== -1 && wildcardIndex !== 0) {
throw new Error(`Field (${field}) has an invalid wildcard expression`);
throw new CronError(
`Field (${field}) has an invalid wildcard expression`
);
}
});

Expand All @@ -776,11 +778,11 @@ export class CronTime {
const wasStepDefined = mStep !== undefined;
const step = parseInt(mStep ?? '1', 10);
if (step === 0) {
throw new Error(`Field (${unit}) has a step of zero`);
throw new CronError(`Field (${unit}) has a step of zero`);
}

if (upper !== undefined && lower > upper) {
throw new Error(`Field (${unit}) has an invalid range`);
throw new CronError(`Field (${unit}) has an invalid range`);
}

const isOutOfRange =
Expand All @@ -789,7 +791,7 @@ export class CronTime {
(upper === undefined && lower > high);

if (isOutOfRange) {
throw new Error(`Field value (${value}) is out of range`);
throw new CronError(`Field value (${value}) is out of range`);
}

// Positive integer higher than constraints[0]
Expand Down Expand Up @@ -820,7 +822,7 @@ export class CronTime {
delete typeObj[7];
}
} else {
throw new Error(`Field (${unit}) cannot be parsed`);
throw new CronError(`Field (${unit}) cannot be parsed`);
}
}
}
Expand Down
15 changes: 10 additions & 5 deletions tests/cron.fuzz.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/* eslint-disable jest/no-standalone-expect */
import { fc, test } from '@fast-check/jest';
import { CronJob } from '../src';
import { isCronError } from './helpers/is_cron_error';
import { CronError } from '../src/errors';

/**
* fuzzing might result in an infinite loop in our code, so Jest will simply timeout.
Expand Down Expand Up @@ -55,7 +55,12 @@ function testCronJob(
expect(job.cronTime.source).toBe(cronTime);
} catch (error) {
const isOk = checkError(error);
if (!isOk) console.error(error);
if (!isOk) {
console.error(error);
console.error(
'Make sure the relevant code is using an instance of CronError (or derived) when throwing.'
);
}
expect(isOk).toBe(true);
}
}
Expand All @@ -75,7 +80,7 @@ test.prop(
{ numRuns: 100_000 }
)(
'CronJob should behave as expected and not error unexpectedly (with matching inputs)',
params => testCronJob(params, isCronError)
params => testCronJob(params, err => err instanceof CronError)
);

test.prop(
Expand All @@ -91,7 +96,7 @@ test.prop(
{ numRuns: 100_000 }
)(
'CronJob should behave as expected and not error unexpectedly (with random inputs)',
params => testCronJob(params, isCronError)
params => testCronJob(params, err => err instanceof CronError)
);

test.prop(
Expand All @@ -111,6 +116,6 @@ test.prop(
testCronJob(
// eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-argument
params as any,
err => err instanceof TypeError || isCronError(err)
err => err instanceof CronError || err instanceof TypeError
)
);
27 changes: 0 additions & 27 deletions tests/helpers/is_cron_error.ts

This file was deleted.

0 comments on commit 6b36b67

Please sign in to comment.