You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
vore-rpg/src/testing/Assertions.ts

58 lines
2.3 KiB

export enum AssertionMode {
SKIP = "SKIP",
LOG = "LOG",
THROW = "THROW",
}
/** Configurations for the different assertion modes. */
export namespace AssertionConfig {
/** The types of the assertion configurations. */
export type Type = typeof Skip|typeof Throw|ReturnType<typeof Log>
/** An assertion configuration suitable for production, that skips assertions without evaluating them. */
export const Skip = {mode: AssertionMode.SKIP} as const
/** An assertion configuration suitable for testing, that throws an exception when an assertion fails. */
export const Throw = {mode: AssertionMode.THROW} as const
/** An assertion configuration suitable for debugging, that logs an exception when an assertion fails but allows the program to continue. */
export function Log(logger: (message?: unknown, ...params: unknown[]) => void) {
return {mode: AssertionMode.LOG, logger} as const
}
}
/** Assertion class for test-only checks on preconditions and postconditions. */
export class Assertions {
config: AssertionConfig.Type = AssertionConfig.Skip
/** General assert method. Checks that the condition is true. */
check<T>(value: T, condition: (value: T) => boolean, message: (value: T) => string): T {
if (this.config.mode === AssertionMode.SKIP) {
return value
}
const result = condition(value)
if (result) {
return value
}
const err = Error(message(value))
if (this.config.mode === AssertionMode.THROW) {
throw err
} else {
// All we can do is stand by and watch in horror...
this.config.logger(err)
return value
}
}
/** Checks that the value is an integer. */
checkInteger(value: number, message: (value: number) => string): number {
return this.check(value, Number.isSafeInteger, message)
}
/** Checks that the value is an integer and either positive or zero. */
checkPositiveIntegerOrZero(value: number, message: (value: number) => string): number {
return this.check(value, (value) => {
return Number.isSafeInteger(value) && value >= 0
}, message)
}
}
/** Global assertion object for use by other modules. */
export const assertion = new Assertions();