UNPKG

confusablematcher-js-interop

Version:

TypeScript NAPI Interop for ConfusableMatcher.

1,428 lines (1,302 loc) 55.4 kB
/* cSpell: disable */ import type { IIndexOfOptions, Mapping } from './binding'; import { EDebugFailureReason, EReturnStatus } from './binding'; import { ConfusableMatcher } from './wrapper'; describe('Unit Tests', () => { describe('On Demand', () => { test('Test1', () => { const m = new ConfusableMatcher([ ['N', 'T'], ['I', 'E'], ['C', 'S'], ['E', 'T'], ]); const r = m.indexOfSync('TEST', 'NICE', { matchRepeating: false, startIndex: 0 }); expect(r.status).toEqual(EReturnStatus.MATCH); expect(r.start).toEqual(0); expect(r.size).toEqual(4); }); test('Test2', () => { const m = new ConfusableMatcher([ ['V', 'VA'], ['V', 'VO'], ]); let r = m.indexOfSync('VV', 'VAVOVAVO', { matchRepeating: false, startIndex: 0 }); expect(r.status).toEqual(EReturnStatus.NO_MATCH); r = m.indexOfSync('VAVOVAVO', 'VV', { matchRepeating: false, startIndex: 0 }); expect(r.status).toEqual(EReturnStatus.MATCH); expect(r.start == 0 || r.start == 4).toBeTruthy(); expect(r.size == 3 || r.size == 4).toBeTruthy(); r = m.indexOfSync('VAVOVAVO', 'VV', { matchRepeating: false, startIndex: 4 }); expect(r.status).toEqual(EReturnStatus.MATCH); expect(r.start).toEqual(4); expect(r.size == 3 || r.size == 4).toBeTruthy(); r = m.indexOfSync('VAVOVAVO', 'VV', { matchRepeating: false, startIndex: 2 }); expect(r.status).toEqual(EReturnStatus.MATCH); expect(r.start == 2 || r.start == 4).toBeTruthy(); expect(r.size == 3 || r.size == 4).toBeTruthy(); r = m.indexOfSync('VAVOVAVO', 'VV', { matchRepeating: false, startIndex: 3 }); expect(r.status).toEqual(EReturnStatus.MATCH); expect(r.start).toEqual(4); expect(r.size == 3 || r.size == 4).toBeTruthy(); }); test('Test3', () => { const m = new ConfusableMatcher( [ ['A', '\x02\x03'], ['B', '\xFA\xFF'], ], [], true ); const r = m.indexOfSync('\x02\x03\xFA\xFF', 'AB'); expect(r.status).toEqual(EReturnStatus.MATCH); expect(r.start).toEqual(0); expect(r.size).toEqual(4); }); test('Test4', () => { const m = new ConfusableMatcher( [ ['S', '$'], ['D', '[)'], ], ['_', ' '] ); const r = m.indexOfSync('A__ _ $$$[)D', 'ASD', { matchRepeating: true, startIndex: 0 }); expect(r.status).toEqual(EReturnStatus.MATCH); expect(r.start).toEqual(0); expect(r.size).toEqual(11); }); test('Test5', () => { const m = new ConfusableMatcher([ ['N', '/\\/'], ['N', '/\\'], ['I', '/'], ]); const r = m.indexOfSync('/\\/CE', 'NICE', { matchRepeating: false, startIndex: 0 }); expect(r.status).toEqual(EReturnStatus.MATCH); expect(r.start).toEqual(0); expect(r.size).toEqual(5); }); test('Test6', () => { const m = new ConfusableMatcher([ ['N', '/\\/'], ['V', '\\/'], ['I', '/'], ]); let r = m.indexOfSync('I/\\/AM', 'INAN', { matchRepeating: true, startIndex: 0 }); expect(r.status).toEqual(EReturnStatus.NO_MATCH); r = m.indexOfSync('I/\\/AM', 'INAM', { matchRepeating: true, startIndex: 0 }); expect(r.status).toEqual(EReturnStatus.MATCH); expect(r.start).toEqual(0); expect(r.size).toEqual(6); r = m.indexOfSync('I/\\/AM', 'IIVAM', { matchRepeating: true, startIndex: 0 }); expect(r.status).toEqual(EReturnStatus.MATCH); expect(r.start).toEqual(0); expect(r.size).toEqual(6); }); test('Test7', () => { const s = 'AAAAAAAAASSAFSAFNFNFNISFNSIFSIFJSDFUDSHF ASUF/|/__/|/___%/|/%I%%/|//|/%%%%%NNNN/|/NN__/|/N__𝘪G___%____$__G__𝓰𝘦Ѓ'; const m = new ConfusableMatcher(getDefaultMap(), ['_', '%', '$']); const r = m.indexOfSync(s, 'NIGGER', { matchRepeating: true, startIndex: 0 }); expect(r.status).toEqual(EReturnStatus.MATCH); expect((r.start == 64 && r.size == 50) || (r.start == 89 && r.size == 25)).toBeTruthy(); }); test('Test8', () => { const m = new ConfusableMatcher([], ['[', ']', '̲', '̅']); const r = m.indexOfSync( '[̲̅a̲̅][̲̅b̲̅][̲̅c̲̅][̲̅d̲̅][̲̅e̲̅][̲̅f̲̅][̲̅g̲̅][̲̅h̲̅][̲̅i̲̅][̲̅j̲̅][̲̅k̲̅][̲̅l̲̅][̲̅m̲̅][̲̅n̲̅][̲̅o̲̅][̲̅p̲̅][̲̅q̲̅][̲̅r̲̅][̲̅s̲̅][̲̅t̲̅][̲̅u̲̅][̲̅v̲̅][̲̅w̲̅][̲̅x̲̅][̲̅y̲̅][̲̅z̲̅][̲̅0̲̅][̲̅1̲̅][̲̅2̲̅][̲̅3̲̅][̲̅4̲̅][̲̅5̲̅][̲̅6̲̅][̲̅7̲̅][̲̅8̲̅][̲̅9̲̅][̲̅0̲̅]', 'ABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890', { matchRepeating: false } ); expect(r.status).toEqual(EReturnStatus.MATCH); expect(r.start).toEqual(3); expect(r.size).toEqual(253); }); test('Test9', () => { const m = new ConfusableMatcher([ ['B', 'A'], ['B', 'AB'], ['B', 'ABC'], ['B', 'ABCD'], ['B', 'ABCDE'], ['B', 'ABCDEF'], ['B', 'ABCDEFG'], ['B', 'ABCDEFGH'], ['B', 'ABCDEFGHI'], ['B', 'ABCDEFGHIJ'], ['B', 'ABCDEFGHIJK'], ['B', 'ABCDEFGHIJKL'], ['B', 'ABCDEFGHIJKLM'], ['B', 'ABCDEFGHIJKLMN'], ['B', 'ABCDEFGHIJKLMNO'], ['B', 'ABCDEFGHIJKLMNOP'], ['B', 'ABCDEFGHIJKLMNOPQ'], ['B', 'ABCDEFGHIJKLMNOPQR'], ['B', 'ABCDEFGHIJKLMNOPQRS'], ]); const r = m.indexOfSync('ABCDEFGHIJKLMNOPQRS', 'B', { matchRepeating: false, startFromEnd: false, startIndex: 0, timeoutNs: 10_000_000, }); expect(r.status).toEqual(EReturnStatus.MATCH); expect(r.start == 0 || r.start == 1).toBeTruthy(); expect(r.size).toEqual(1); }); test('Test9.1', () => { const m = new ConfusableMatcher([ ['B', 'A'], ['B', 'AB'], ['B', 'ABC'], ['B', 'ABCD'], ['B', 'ABCDE'], ['B', 'ABCDEF'], ['B', 'ABCDEFG'], ['B', 'ABCDEFGH'], ['B', 'ABCDEFGHI'], ['B', 'ABCDEFGHIJ'], ['B', 'ABCDEFGHIJK'], ['B', 'ABCDEFGHIJKL'], ['B', 'ABCDEFGHIJKLM'], ['B', 'ABCDEFGHIJKLMN'], ['B', 'ABCDEFGHIJKLMNO'], ['B', 'ABCDEFGHIJKLMNOPQ'], ['B', 'ABCDEFGHIJKLMNOPQR'], ['B', 'ABCDEFGHIJKLMNOPQRS'], ['B', 'PQRSTUVWXYZ0123456789'], ['B', 'PQRSTUVWXYZ012345678'], ['B', 'PQRSTUVWXYZ01234567'], ['B', 'PQRSTUVWXYZ0123456'], ['B', 'PQRSTUVWXYZ012345'], ['B', 'PQRSTUVWXYZ01234'], ['B', 'PQRSTUVWXYZ0123'], ['B', 'PQRSTUVWXYZ012'], ['B', 'PQRSTUVWXYZ01'], ['B', 'PQRSTUVWXYZ0'], ['B', 'PQRSTUVWXYZ'], ['B', 'PQRSTUVWXY'], ['B', 'PQRSTUVWX'], ['B', 'PQRSTUVW'], ['B', 'PQRSTUV'], ['B', 'PQRSTU'], ['B', 'PQRST'], ['B', 'PQRS'], ['B', 'PQR'], ['B', 'PQ'], ['B', 'P'], ]); let r = m.indexOfSync('ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789', 'BB', { matchRepeating: false, startFromEnd: false, startIndex: 0, timeoutNs: 10_000_000, }); expect(r.status).toEqual(EReturnStatus.MATCH); expect(r.start).toEqual(0); expect(r.size).toEqual(2); r = m.indexOfSync( 'PQRSTUVWXYZ0123456789PQRSTUVWXYZ0123456789PQRSTUVWXYZ0123456789PQRSTUVWXYZ0123456789PQRSTUVWXYZ0123456789PQRSTUVWXYZ0123456789PQRSTUVWXYZ0123456789PQRSTUVWXYZ0123456789PQRSTUVWXYZ0123456789PQRSTUVWXYZ0123456789PQRSTUVWXYZ0123456789PQRSTUVWXYZ0123456789PQRSTUVWXYZ0123456789PQRSTUVWXYZ0123456789PQRSTUVWXYZ0123456789PQRSTUVWXYZ0123456789PQRSTUVWXYZ0123456789PQRSTUVWXYZ0123456789PQRSTUVWXYZ0123456789PQRSTUVWXYZ0123456789PQRSTUVWXYZ0123456789PQRSTUVWXYZ0123456789PQRSTUVWXYZ0123456789PQRSTUVWXYZ0123456789PQRSTUVWXYZ0123456789PQRSTUVWXYZ0123456789PQRSTUVWXYZ0123456789', 'BBBBBBBBBBBBBBBBBBBBBBBBBBB', { matchRepeating: true, startFromEnd: false, startIndex: 0, timeoutNs: 20_000_000, } ); expect(r.status).toEqual(EReturnStatus.MATCH); expect(r.start).toEqual(0); expect(r.size >= 547 && r.size <= 567).toBeTruthy(); }); test('Test10', () => { const m = new ConfusableMatcher(); let r = m.indexOfSync(':)', '', { matchRepeating: true, startIndex: 0 }); expect(r.status).toEqual(EReturnStatus.MATCH); expect(r.start).toEqual(0); expect(r.size).toEqual(0); r = m.indexOfSync('', ':)', { matchRepeating: true, startIndex: 0 }); expect(r.status).toEqual(EReturnStatus.NO_MATCH); }); test('Test11', () => { const m = new ConfusableMatcher([['A', 'A']]); const r = m.indexOfSync('ABAAA', 'ABAR', { matchRepeating: true, startFromEnd: false, startIndex: 0, timeoutNs: 1_000_000, }); expect(r.status).toEqual(EReturnStatus.NO_MATCH); }); test('Test12', () => { const m = new ConfusableMatcher([]); const r = m.indexOfSync('A', 'A', { matchRepeating: false, startIndex: 0 }); expect(r.status).toEqual(EReturnStatus.MATCH); expect(r.start).toEqual(0); expect(r.size).toEqual(1); }); test('Test12.1', () => { const m = new ConfusableMatcher([], [], false); const r = m.indexOfSync('A', 'A', { matchRepeating: false, startIndex: 0 }); expect(r.status).toEqual(EReturnStatus.NO_MATCH); }); test('Test13', () => { expect(() => new ConfusableMatcher([['', '?']])).toThrow(); expect(() => new ConfusableMatcher([['', '?']])).toThrow(); expect(() => new ConfusableMatcher([['?', '']])).toThrow(); expect(() => new ConfusableMatcher([['', '']])).toThrow(); expect(() => new ConfusableMatcher([['\x00', '?']])).toThrow(); expect(() => new ConfusableMatcher([['?', '\x00']])).toThrow(); expect(() => new ConfusableMatcher([['\x01', '?']])).toThrow(); expect(() => new ConfusableMatcher([['?', '\x01']])).toThrow(); expect(() => new ConfusableMatcher([['\x00', '\x01']])).toThrow(); expect(() => new ConfusableMatcher([['\x00', '\x00']])).toThrow(); expect(() => new ConfusableMatcher([['\x01', '\x00']])).toThrow(); expect(() => new ConfusableMatcher([['\x01', '\x01']])).toThrow(); expect(() => new ConfusableMatcher([['\x01\x00', '\x00\x01']])).toThrow(); expect(() => new ConfusableMatcher([['A\x00', '\x00A']])).toThrow(); expect(() => new ConfusableMatcher([['\x01\x00', '\x00\x01']])).toThrow(); expect(() => new ConfusableMatcher([['A\x00', 'A\x01']])).not.toThrow(); expect(() => new ConfusableMatcher([['A\x01', 'A\x00']])).not.toThrow(); expect(() => new ConfusableMatcher([['A\x00', 'A\x00']])).not.toThrow(); expect(() => new ConfusableMatcher([['A\x01', 'A\x01']])).not.toThrow(); }); test('Test14', () => { const m = new ConfusableMatcher([]); for (let i = 0; i < 1e3; i++) { m.indexOfSync('ASD', 'ZXC', { matchRepeating: true, startIndex: 0 }); m.indexOfSync('ASD', 'ZXC', { matchRepeating: true, startIndex: 0 }); m.indexOfSync('ASD', 'ZXC', { matchRepeating: true, startIndex: 0 }); } }); test('Test15', () => { const m = new ConfusableMatcher([['.', '.']], ['.']); const r = m.indexOfSync('FOLLOWONBOT.COM', 'FOLLOWONBOT.COM', { matchRepeating: true, startIndex: 0 }); expect(r.status).toEqual(EReturnStatus.MATCH); expect(r.start).toEqual(0); expect(r.size).toEqual(15); }); test('Test16', () => { const m = new ConfusableMatcher([ ['N', '/\\/'], ['N', '\\/\\'], ]); const r = m.indexOfSync( '/\\/\\/\\/\\/\\/\\/\\/\\/\\/\\/\\/\\/\\/\\/\\/\\/\\/\\/\\/\\/\\/\\/\\/\\/\\/\\/\\/\\/\\/\\/\\/', 'NNNNNNNNNNNNNNNA', { matchRepeating: true, startIndex: 0 } ); expect(r.status).toEqual(EReturnStatus.TIMEOUT); }); test('Test17', () => { const m = new ConfusableMatcher([ ['N', '_'], ['N', '__'], ]); const r = m.indexOfSync('NNNNN__N_NN___NNNNNN_NN_N__NNNN__N_NNNNNICE', 'NIRE', { matchRepeating: true, startFromEnd: false, startIndex: 0, timeoutNs: 10_000_000, }); expect(r.status).toEqual(EReturnStatus.NO_MATCH); }); test('Test18', () => { const m = new ConfusableMatcher([ ['N', '12345'], ['A', '1'], ['A', '5'], ['A', '234'], ]); const r = m.indexOfSync('N12345M', 'NAM', { matchRepeating: true, startIndex: 0 }); expect(r.status).toEqual(EReturnStatus.MATCH); expect(r.start).toEqual(0); expect(r.size).toEqual(7); }); test('Test19', () => { const m = new ConfusableMatcher([ ['A', '1'], ['B', '1'], ['C', '1'], ]); const r = m.indexOfSync('111111', 'ABC', { matchRepeating: true, startIndex: 0 }); expect(r.status).toEqual(EReturnStatus.MATCH); expect(r.start).toEqual(0); expect(r.size).toEqual(3); }); test('Test20', () => { const m = new ConfusableMatcher( [ ['A', '1'], ['B', '1'], ['C', '1'], ], [], false ); expect('1').toEqual(m.getKeyMappings('A')[0]); expect('1').toEqual(m.getKeyMappings('B')[0]); expect('1').toEqual(m.getKeyMappings('C')[0]); }); test('Test21', () => { const m = new ConfusableMatcher( [ ['1', 'AB'], ['1', 'CD'], ['2', 'EEE'], ], [], false ); const mappings = m.getKeyMappings('1'); expect(mappings[0] === 'AB' || mappings[0] === 'CD').toBeTruthy(); expect(mappings[1] === 'AB' || mappings[1] === 'CD').toBeTruthy(); expect('EEE').toEqual(m.getKeyMappings('2')[0]); }); test('Test22', () => { const COUNT = 500; const KEY = '123'; const m = new ConfusableMatcher( Array.from<unknown, Mapping>({ length: COUNT }, (i, x) => [KEY, x.toString()]), [], false ); expect(m.getKeyMappings(KEY)).toHaveLength(COUNT); }); test('Test23', () => { const s = 'AA BB CC AA FF AA RR'; const m = new ConfusableMatcher(getDefaultMap()); let r = m.indexOfSync(s, 'AA', { matchRepeating: true }); expect(r.status).toEqual(EReturnStatus.MATCH); expect(r.start).toEqual(0); expect(r.size).toEqual(2); r = m.indexOfSync(s, 'AA', { matchRepeating: true, startFromEnd: true, startIndex: s.length - 1 }); expect(r.status).toEqual(EReturnStatus.MATCH); expect(r.start).toEqual(15); expect(r.size).toEqual(2); }); test('Test24', () => { const s = 'DASD'; const m = new ConfusableMatcher(getDefaultMap()); const r = m.indexOfSync(s, 'D', { matchRepeating: true, startFromEnd: true, startIndex: s.length - 1 }); expect(r.status).toEqual(EReturnStatus.MATCH); expect(r.start).toEqual(3); expect(r.size).toEqual(1); }); test('Test25', () => { const s = 'ASASASASASASASASASASASASASASASASASASASASASASASASASASASASASASASASASASASASASASASASASASASASASASASB'; const m = new ConfusableMatcher(getDefaultMap()); let r = m.indexOfSync(s, 'ASB', { matchRepeating: true, startFromEnd: false, startIndex: 0, timeoutNs: 20, }); expect(r.status).toEqual(EReturnStatus.TIMEOUT); r = m.indexOfSync(s, 'ASB', { matchRepeating: true, startFromEnd: true, startIndex: s.length - 1, timeoutNs: 20, }); expect(r.status).toEqual(EReturnStatus.MATCH); expect(r.start).toEqual(92); expect(r.size).toEqual(3); }); test('Test26', () => { const m = new ConfusableMatcher(getDefaultMap()); const r = m.indexOfSync('AAA', 'A', { matchRepeating: true, startIndex: 0 }); expect(r.status).toEqual(EReturnStatus.MATCH); expect(r.start).toEqual(0); expect(r.size).toEqual(3); }); test('Test27', () => { const m = new ConfusableMatcher(getDefaultMap()); const r = m.indexOfSync('BB AAA', 'A', { matchRepeating: true, startIndex: 0 }); expect(r.status).toEqual(EReturnStatus.MATCH); expect(r.start).toEqual(3); expect(r.size).toEqual(3); }); test('Test28', () => { const m = new ConfusableMatcher(getDefaultMap()); const r = m.indexOfSync('N|\\|NC', 'N', { matchRepeating: true, startIndex: 0 }); expect(r.status).toEqual(EReturnStatus.MATCH); expect(r.start).toEqual(0); expect(r.size).toEqual(5); }); test('Test29', () => { const m = new ConfusableMatcher([ ['N', '/\\/'], ['N', '//A'], ['N', '//'], ]); const r = m.indexOfSync('N/\\///AN', 'N', { matchRepeating: true, startIndex: 0 }); expect(r.status).toEqual(EReturnStatus.MATCH); expect(r.start).toEqual(0); expect(r.size).toEqual(8); }); test('Test30', () => { const m = new ConfusableMatcher([['N', '/']]); const r = m.indexOfSync('N////////////////////////////////////////////////', 'N', { matchRepeating: true, startFromEnd: false, startIndex: 0, timeoutNs: 60, }); expect(r.status).toEqual(EReturnStatus.MATCH); expect(r.start).toEqual(0); expect(r.size).toBeGreaterThan(10); }); test('Test31', () => { const opts: Partial<IIndexOfOptions> = { matchOnWordBoundary: true, timeoutNs: 1_000_000, }; const m = new ConfusableMatcher(); let r = m.indexOfSync('X', 'X', { ...opts }); expect(r.status).toEqual(EReturnStatus.MATCH); expect(r.start).toEqual(0); expect(r.size).toEqual(1); r = m.indexOfSync('aX', 'X', { ...opts }); expect(r.status).toEqual(EReturnStatus.WORD_BOUNDARY_FAIL_START); expect(r.start).toEqual(1); expect(r.size).toEqual(1); r = m.indexOfSync('Xa', 'X', { ...opts }); expect(r.status).toEqual(EReturnStatus.WORD_BOUNDARY_FAIL_END); expect(r.start).toEqual(0); expect(r.size).toEqual(1); r = m.indexOfSync('a X', 'X', { ...opts }); expect(r.status).toEqual(EReturnStatus.MATCH); expect(r.start).toEqual(2); expect(r.size).toEqual(1); r = m.indexOfSync('X a', 'X', { ...opts }); expect(r.status).toEqual(EReturnStatus.MATCH); expect(r.start).toEqual(0); expect(r.size).toEqual(1); r = m.indexOfSync('X;duper', 'X', { ...opts }); expect(r.status).toEqual(EReturnStatus.MATCH); expect(r.start).toEqual(0); expect(r.size).toEqual(1); r = m.indexOfSync('yes\uFEFFX', 'X', { ...opts }); expect(r.status).toEqual(EReturnStatus.MATCH); expect(r.start).toEqual(4); expect(r.size).toEqual(1); }); test('Test32', () => { const opts: Partial<IIndexOfOptions> = { matchOnWordBoundary: true, matchRepeating: true, timeoutNs: 1_000_000, }; const m = new ConfusableMatcher(); let r = m.indexOfSync('QQQ', 'Q', { ...opts }); expect(r.status).toEqual(EReturnStatus.MATCH); expect(r.start).toEqual(0); expect(r.size).toEqual(3); r = m.indexOfSync('aQQQ', 'Q', { ...opts }); expect( r.status === EReturnStatus.WORD_BOUNDARY_FAIL_START || r.status === EReturnStatus.WORD_BOUNDARY_FAIL_END ).toBeTruthy(); expect( (r.start === 1 && r.size === 1) || (r.start === 1 && r.size === 2) || (r.start === 1 && r.size === 3) || (r.start === 2 && r.size === 1) || (r.start === 2 && r.size === 2) || (r.start === 3 && r.size === 1) ).toBeTruthy(); r = m.indexOfSync('QQQa', 'Q', { ...opts }); expect( r.status === EReturnStatus.WORD_BOUNDARY_FAIL_START || r.status === EReturnStatus.WORD_BOUNDARY_FAIL_END ).toBeTruthy(); expect( (r.start === 0 && r.size === 1) || (r.start === 0 && r.size === 2) || (r.start === 0 && r.size === 3) || (r.start === 1 && r.size === 1) || (r.start === 1 && r.size === 2) || (r.start === 2 && r.size === 1) ).toBeTruthy(); r = m.indexOfSync('a QQQ', 'Q', { ...opts }); expect(r.status).toEqual(EReturnStatus.MATCH); expect(r.start).toEqual(2); expect(r.size).toEqual(3); r = m.indexOfSync('QQQ a', 'Q', { ...opts }); expect(r.status).toEqual(EReturnStatus.MATCH); expect(r.start).toEqual(0); expect(r.size).toEqual(3); r = m.indexOfSync('QQQ;duper', 'Q', { ...opts }); expect(r.status).toEqual(EReturnStatus.MATCH); expect(r.start).toEqual(0); expect(r.size).toEqual(3); r = m.indexOfSync('yes\u202FQQQ', 'Q', { ...opts }); expect(r.status).toEqual(EReturnStatus.MATCH); expect(r.start).toEqual(4); expect(r.size).toEqual(3); }); test('Test33', () => { const input = 'a QBQQ'; const opts: Partial<IIndexOfOptions> = { matchOnWordBoundary: true, matchRepeating: true, startFromEnd: true, startIndex: input.length - 1, timeoutNs: 1_000_000, }; const m = new ConfusableMatcher([], ['B']); const r = m.indexOfSync(input, 'Q', { ...opts }); expect(r.status).toEqual(EReturnStatus.MATCH); expect(r.start).toEqual(2); expect(r.size).toEqual(4); }); test('Test34', () => { const opts: Partial<IIndexOfOptions> = { matchOnWordBoundary: true, timeoutNs: 1_000_000, }; const m = new ConfusableMatcher(); let r = m.indexOfSync('SUPER', 'SUPER', { ...opts }); expect(r.status).toEqual(EReturnStatus.MATCH); expect(r.start).toEqual(0); expect(r.size).toEqual(5); r = m.indexOfSync('aSUPER', 'SUPER', { ...opts }); expect(r.status).toEqual(EReturnStatus.WORD_BOUNDARY_FAIL_START); expect(r.start).toEqual(1); expect(r.size).toEqual(5); r = m.indexOfSync('SUPERa', 'SUPER', { ...opts }); expect(r.status).toEqual(EReturnStatus.WORD_BOUNDARY_FAIL_END); expect(r.start).toEqual(0); expect(r.size).toEqual(5); r = m.indexOfSync('a SUPER', 'SUPER', { ...opts }); expect(r.status).toEqual(EReturnStatus.MATCH); expect(r.start).toEqual(2); expect(r.size).toEqual(5); r = m.indexOfSync('SUPER a', 'SUPER', { ...opts }); expect(r.status).toEqual(EReturnStatus.MATCH); expect(r.start).toEqual(0); expect(r.size).toEqual(5); r = m.indexOfSync('SUPER;duper', 'SUPER', { ...opts }); expect(r.status).toEqual(EReturnStatus.MATCH); expect(r.start).toEqual(0); expect(r.size).toEqual(5); r = m.indexOfSync('yes\u202FSUPER', 'SUPER', { ...opts }); expect(r.status).toEqual(EReturnStatus.MATCH); expect(r.start).toEqual(4); expect(r.size).toEqual(5); }); test('Test35', () => { const opts: Partial<IIndexOfOptions> = { matchOnWordBoundary: true, timeoutNs: 1_000_000, }; const m = new ConfusableMatcher([[' ', ' ']], [' ']); let r = m.indexOfSync('a Q Q f', 'Q Q', { ...opts }); expect(r.status).toEqual(EReturnStatus.MATCH); expect(r.start).toEqual(2); expect(r.size).toEqual(3); r = m.indexOfSync('aQ Q f', 'Q Q', { ...opts }); expect(r.status).toEqual(EReturnStatus.WORD_BOUNDARY_FAIL_START); expect(r.start).toEqual(1); expect(r.size).toEqual(3); r = m.indexOfSync('a Q Qf', 'Q Q', { ...opts }); expect(r.status).toEqual(EReturnStatus.WORD_BOUNDARY_FAIL_END); expect(r.start).toEqual(2); expect(r.size).toEqual(3); }); test('Test36', () => { const opts: Partial<IIndexOfOptions> = { matchOnWordBoundary: true, timeoutNs: 1_000_000, }; const m = new ConfusableMatcher([[' ', ' ']], [' ']); const r = m.indexOfSync('a Q Q Q f', 'Q Q', { ...opts }); expect(r.status).toEqual(EReturnStatus.MATCH); expect(r.start == 2 || r.start == 3).toBeTruthy(); expect(r.size == 3 || r.size == 4).toBeTruthy(); }); test('Test37', () => { const opts: Partial<IIndexOfOptions> = { matchOnWordBoundary: true, matchRepeating: true, timeoutNs: 1_000_000, }; const m = new ConfusableMatcher([ ['a', 'a'], ['s', 's'], [' ', ' '], ['i', 'i'], ['m', 'm'], ['p', 'p'], ]); const r = m.indexOfSync('as simp', 'simp', { ...opts }); expect(r.status).toEqual(EReturnStatus.MATCH); expect(r.start).toEqual(3); expect(r.size).toEqual(4); }); test('Test38', () => { const opts: Partial<IIndexOfOptions> = { timeoutNs: 1_000_000, }; const m = new ConfusableMatcher(); let r = m.indexOfSync('a', '', { ...opts }); expect(r.status).toEqual(EReturnStatus.MATCH); expect(r.start).toEqual(0); expect(r.size).toEqual(0); r = m.indexOfSync('', '', { ...opts }); expect(r.status).toEqual(EReturnStatus.MATCH); expect(r.start).toEqual(0); expect(r.size).toEqual(0); r = m.indexOfSync('', 'a', { ...opts }); expect(r.status).toEqual(EReturnStatus.NO_MATCH); }); test('Test39', () => { const opts: Partial<IIndexOfOptions> = { matchOnWordBoundary: true, matchRepeating: true, timeoutNs: 1_000_000, }; const m = new ConfusableMatcher([], ['f']); let r = m.indexOfSync('AABC', 'ABC', { ...opts }); expect(r.status).toEqual(EReturnStatus.MATCH); expect(r.start).toEqual(0); expect(r.size).toEqual(4); r = m.indexOfSync('AfABC', 'ABC', { ...opts }); expect(r.status).toEqual(EReturnStatus.MATCH); expect(r.start).toEqual(0); expect(r.size).toEqual(5); r = m.indexOfSync('ABCC', 'ABC', { ...opts }); expect(r.status).toEqual(EReturnStatus.MATCH); expect(r.start).toEqual(0); expect(r.size).toEqual(4); r = m.indexOfSync('ABCfC', 'ABC', { ...opts }); expect(r.status).toEqual(EReturnStatus.MATCH); expect(r.start).toEqual(0); }); test('Test40', () => { const opts: Partial<IIndexOfOptions> = { matchOnWordBoundary: true, matchRepeating: true, startFromEnd: true, timeoutNs: 1_000_000, }; const m = new ConfusableMatcher([], ['f']); let r = m.indexOfSync('AABC', 'ABC', { ...opts, startIndex: 3 }); expect(r.status).toEqual(EReturnStatus.MATCH); expect(r.start).toEqual(0); expect(r.size).toEqual(4); r = m.indexOfSync('AfABC', 'ABC', { ...opts, startIndex: 4 }); expect(r.status).toEqual(EReturnStatus.MATCH); expect(r.start).toEqual(0); expect(r.size).toEqual(5); r = m.indexOfSync('ABCC', 'ABC', { ...opts, startIndex: 3 }); expect(r.status).toEqual(EReturnStatus.MATCH); expect(r.start).toEqual(0); expect(r.size).toEqual(4); r = m.indexOfSync('ABCfC', 'ABC', { ...opts, startIndex: 4 }); expect(r.status).toEqual(EReturnStatus.MATCH); expect(r.start).toEqual(0); expect(r.size).toEqual(5); }); test('Test41', () => { const m = new ConfusableMatcher( [ ['s', 's'], ['i', '1'], ['m', 'm'], ['p', 'p'], ], [' '] ); const r = m.indexOfSync('agdhsjs s 1 mmm ppps dhsjdhsd', 'simps', { matchOnWordBoundary: true, matchRepeating: true, timeoutNs: 1_000_000, }); expect(r.status).toEqual(EReturnStatus.MATCH); expect(r.start).toEqual(8); expect(r.size).toEqual(12); }); test('Test42', () => { const opts: Partial<IIndexOfOptions> = { matchOnWordBoundary: true, matchRepeating: true, timeoutNs: 1_000_000, }; let m = new ConfusableMatcher([], ['░']); let r = m.indexOfSync('░S░I░M░P░', 'SIMP', opts); expect(r.status).toEqual(EReturnStatus.MATCH); expect(r.start).toEqual(1); expect(r.size).toEqual(7); m = new ConfusableMatcher([], ['Ž']); r = m.indexOfSync('ŽSŽIŽMŽPŽ', 'SIMP', opts); expect(r.status).toEqual(EReturnStatus.MATCH); expect(r.start).toEqual(1); expect(r.size).toEqual(8); }); test('Test43', () => { const map: Mapping[] = [ ['S', '░'], ['S', 'Ž'], ]; const opts: Partial<IIndexOfOptions> = { matchOnWordBoundary: true, matchRepeating: true, timeoutNs: 1_000_000, }; let m = new ConfusableMatcher(map, ['░']); let r = m.indexOfSync('░S░I░M░P░', 'SIMP', opts); expect(r.status).toEqual(EReturnStatus.MATCH); expect(r.start).toEqual(0); expect(r.size).toEqual(8); m = new ConfusableMatcher(map, ['Ž']); r = m.indexOfSync('ŽSŽIŽMŽPŽ', 'SIMP', opts); expect(r.status).toEqual(EReturnStatus.MATCH); expect(r.start).toEqual(0); expect(r.size).toEqual(9); }); test('Test44', () => { const m = new ConfusableMatcher([[' ', ' ']]); const r = m.indexOfSync('A B', ' B', { matchOnWordBoundary: true, matchRepeating: true, timeoutNs: 1_000_000, }); expect(r.status).toEqual(EReturnStatus.MATCH); expect(r.start).toEqual(2); expect(r.size).toEqual(2); }); test('Test44.1', () => { const m = new ConfusableMatcher([['M', 'ⓜ']]); const r = m.indexOfSync('SIⓜP', 'SIMP'); expect(r.status).toEqual(EReturnStatus.MATCH); expect(r.start).toEqual(0); expect(r.size).toEqual(4); }); test('Test45', () => { const m = new ConfusableMatcher([], ['X']); const opts: Partial<IIndexOfOptions> = { matchOnWordBoundary: true, matchRepeating: true, timeoutNs: 1_000_000, }; let r = m.indexOfSync('XXABC', 'ABC', opts); expect(r.status).toEqual(EReturnStatus.MATCH); expect(r.start).toEqual(2); expect(r.size).toEqual(3); r = m.indexOfSync('X XABC', 'ABC', opts); expect(r.status).toEqual(EReturnStatus.MATCH); expect(r.start).toEqual(3); expect(r.size).toEqual(3); r = m.indexOfSync('X૰XABC', 'ABC', opts); expect(r.status).toEqual(EReturnStatus.MATCH); expect(r.start).toEqual(3); expect(r.size).toEqual(3); r = m.indexOfSync(' X XABC', 'ABC', opts); expect(r.status).toEqual(EReturnStatus.MATCH); expect(r.start).toEqual(4); expect(r.size).toEqual(3); r = m.indexOfSync(' XXABC', 'ABC', opts); expect(r.status).toEqual(EReturnStatus.MATCH); expect(r.start).toEqual(3); expect(r.size).toEqual(3); r = m.indexOfSync(' XX ABC', 'ABC', opts); expect(r.status).toEqual(EReturnStatus.MATCH); expect(r.start).toEqual(4); expect(r.size).toEqual(3); r = m.indexOfSync('XXXX XXABC', 'ABC', opts); expect(r.status).toEqual(EReturnStatus.MATCH); expect(r.start).toEqual(7); expect(r.size).toEqual(3); }); test('Test46', () => { const m = new ConfusableMatcher([], [], true); const opts: Partial<IIndexOfOptions> = { matchOnWordBoundary: true, matchRepeating: true, timeoutNs: 1_000_000, }; const r = m.indexOfSync('AABBB', 'AAB', opts); expect(r.status).toEqual(EReturnStatus.MATCH); }); }); describe('Pre-Computed', () => { test('Test1', () => { let m = new ConfusableMatcher([], ['░']); const needle = 'SIMP'; const needlePtr = m.computeStringPosPointers(needle); const opts: Partial<IIndexOfOptions> = { matchOnWordBoundary: true, matchRepeating: true, needlePosPointers: needlePtr, timeoutNs: 1_000_000, }; let r = m.indexOfSync('░S░I░M░P░', needle, opts); expect(r.status).toEqual(EReturnStatus.MATCH); expect(r.start).toEqual(1); expect(r.size).toEqual(7); m = new ConfusableMatcher([], ['Ž']); r = m.indexOfSync('ŽSŽIŽMŽPŽ', needle, opts); expect(r.status).toEqual(EReturnStatus.MATCH); expect(r.start).toEqual(1); expect(r.size).toEqual(8); m.freeStringPosPointers(needlePtr); }); }); describe('Debug', () => { it('Should produce debug matches', () => { const opts: Partial<IIndexOfOptions> = { matchOnWordBoundary: true, matchRepeating: true, }; const map: Mapping[] = [ ['N', '/B/'], ['I', '/'], ]; const m = new ConfusableMatcher(map, []); const input = 'I/B/AM'; const needle = 'INAN'; const { failures } = m.indexOfDebugFailuresExSync(input, needle, opts); let x = 0; expect(failures[x].inPos).toEqual(5); expect(failures[x].containsPos).toEqual(3); expect(failures[x++].reason).toEqual(EDebugFailureReason.NO_NEW_PATHS); expect(failures[x].inPos).toEqual(2); expect(failures[x].containsPos).toEqual(1); expect(failures[x++].reason).toEqual(EDebugFailureReason.NO_PATH); expect(failures[x].inPos).toEqual(2); expect(failures[x].containsPos).toEqual(1); expect(failures[x++].reason).toEqual(EDebugFailureReason.NO_PATH); expect(failures[x].inPos).toEqual(4); expect(failures[x].containsPos).toEqual(1); expect(failures[x++].reason).toEqual(EDebugFailureReason.NO_PATH); expect(failures[x].inPos).toEqual(6); expect(failures[x].containsPos).toEqual(0); expect(failures[x++].reason).toEqual(EDebugFailureReason.NO_PATH); }); it('Should produce failure debug strings', () => { const opts: Partial<IIndexOfOptions> = { matchOnWordBoundary: true, matchRepeating: true, }; const map: Mapping[] = [ ['N', '/B/'], ['I', '/'], ]; const m = new ConfusableMatcher(map, []); const input = 'I/B/AM'; const needle = 'INAN'; const failures = m.indexOfDebugFailuresSync(input, needle, opts); let x = 0; expect('No new paths in input /AM̲ (5) comparing NAN̲ (3)').toEqual(failures[x++]); expect('No path in input I/B̲/AM (2) comparing IN̲AN (1)').toEqual(failures[x++]); expect('No path in input I/B̲/AM (2) comparing IN̲AN (1)').toEqual(failures[x++]); expect('No path in input B/A̲M (4) comparing IN̲AN (1)').toEqual(failures[x++]); expect('No path in input /AM ̲ (6) comparing I̲NAN (0)').toEqual(failures[x++]); }); }); }); function getDefaultMap(): Mapping[] { const map: Mapping[] = [ ['N', '/[()[]]/'], ['N', '\u{000000f1}'], ['N', '|\\|'], ['N', '\u{00000245}\u{0000002f}'], ['N', '/IJ'], ['N', '/|/'], ]; for (const n of [ '\u{000004c5}', '\u{000003a0}', '\u{00000418}', '\u{0001d427}', '\u{0001d45b}', '\u{0001d48f}', '\u{0001d4c3}', '\u{0001d4f7}', '\u{0001d52b}', '\u{0001d55f}', '\u{0001d593}', '\u{0001d5c7}', '\u{0001d5fb}', '\u{0001d62f}', '\u{0001d663}', '\u{0001d697}', '\u{00000578}', '\u{0000057c}', '\u{0000ff2e}', '\u{00002115}', '\u{0001d40d}', '\u{0001d441}', '\u{0001d475}', '\u{0001d4a9}', '\u{0001d4dd}', '\u{0001d511}', '\u{0001d579}', '\u{0001d5ad}', '\u{0001d5e1}', '\u{0001d615}', '\u{0001d649}', '\u{0001d67d}', '\u{0000039d}', '\u{0001d6b4}', '\u{0001d6ee}', '\u{0001d728}', '\u{0001d762}', '\u{0001d79c}', '\u{0000a4e0}', '\u{00000143}', '\u{00000145}', '\u{00000147}', '\u{0000014b}', '\u{0000019d}', '\u{000001f8}', '\u{00000220}', '\u{0000039d}', '\u{00001e44}', '\u{00001e46}', '\u{00001e48}', '\u{00001e4a}', '\u{000020a6}', '\u{00001f20}', '\u{00001f21}', '\u{00001f22}', '\u{00001f23}', '\u{00001f24}', '\u{00001f25}', '\u{00001f26}', '\u{00001f27}', '\u{00001f74}', '\u{00001f75}', '\u{00001f90}', '\u{00001f91}', '\u{00001f92}', '\u{00001f93}', '\u{00001f94}', '\u{00001f95}', '\u{00001f96}', '\u{00001f97}', '\u{00001fc2}', '\u{00001fc3}', '\u{00001fc4}', '\u{00001fc6}', '\u{00001fc7}', '\u{000000f1}', '\u{00000144}', '\u{00000146}', '\u{00000148}', '\u{00000149}', '\u{0000014a}', '\u{0000019e}', '\u{000001f9}', '\u{00000235}', '\u{00000272}', '\u{00000273}', '\u{00000274}', '\u{00001d70}', '\u{00001d87}', '\u{00001e45}', '\u{00001e47}', '\u{00001e49}', '\u{00001e4b}', ]) { map.push(['N', n]); } for (const i of [ '\u{00001ec8}', '\u{00000079}', '\u{00000069}', '\u{00000031}', '\u{0000007c}', '\u{0000006c}', '\u{0000006a}', '\u{00000021}', '\u{0000002f}', '\u{0000005c}\u{0000005c}', '\u{0000ff49}', '\u{000000a1}', '\u{00002170}', '\u{00002139}', '\u{00002148}', '\u{0001d422}', '\u{0001d456}', '\u{0001d48a}', '\u{0001d4be}', '\u{0001d4f2}', '\u{0001d526}', '\u{0001d55a}', '\u{0001d58e}', '\u{0001d5c2}', '\u{0001d5f6}', '\u{0001d62a}', '\u{0001d65e}', '\u{0001d692}', '\u{00000131}', '\u{0001d6a4}', '\u{0000026a}', '\u{00000269}', '\u{000003b9}', '\u{00001fbe}', '\u{0000037a}', '\u{0001d6ca}', '\u{0001d704}', '\u{0001d73e}', '\u{0001d778}', '\u{0001d7b2}', '\u{00000456}', '\u{000024be}', '\u{0000a647}', '\u{000004cf}', '\u{0000ab75}', '\u{000013a5}', '\u{00000263}', '\u{00001d8c}', '\u{0000ff59}', '\u{0001d432}', '\u{0001d466}', '\u{0001d49a}', '\u{0001d4ce}', '\u{0001d502}', '\u{0001d536}', '\u{0001d56a}', '\u{0001d59e}', '\u{0001d5d2}', '\u{0001d606}', '\u{0001d63a}', '\u{0001d66e}', '\u{0001d6a2}', '\u{0000028f}', '\u{00001eff}', '\u{0000ab5a}', '\u{000003b3}', '\u{0000213d}', '\u{0001d6c4}', '\u{0001d6fe}', '\u{0001d738}', '\u{0001d772}', '\u{0001d7ac}', '\u{00000443}', '\u{000004af}', '\u{000010e7}', '\u{0000ff39}', '\u{0001d418}', '\u{0001d44c}', '\u{0001d480}', '\u{0001d4b4}', '\u{0001d4e8}', '\u{0001d51c}', '\u{0001d550}', '\u{0001d584}', '\u{0001d5b8}', '\u{0001d5ec}', '\u{0001d620}', '\u{0001d654}', '\u{0001d688}', '\u{000003a5}', '\u{000003d2}', '\u{0001d6bc}', '\u{0001d6f6}', '\u{0001d730}', '\u{0001d76a}', '\u{0001d7a4}', '\u{00002ca8}', '\u{00000423}', '\u{000004ae}', '\u{000013a9}', '\u{000013bd}', '\u{0000a4ec}', '\u{00000176}', '\u{00000178}', '\u{000001b3}', '\u{00000232}', '\u{0000024e}', '\u{0000028f}', '\u{00001e8e}', '\u{00001ef2}', '\u{00001ef4}', '\u{00001ef6}', '\u{00001ef8}', '\u{0000ff39}', '\u{000000cc}', '\u{000000cd}', '\u{000000ce}', '\u{000000cf}', '\u{00000128}', '\u{0000012a}', '\u{0000012c}', '\u{0000012e}', '\u{00000130}', '\u{00000196}', '\u{00000197}', '\u{000001cf}', '\u{00000208}', '\u{0000020a}', '\u{0000026a}', '\u{0000038a}', '\u{00000390}', '\u{00000399}', '\u{000003aa}', '\u{00000406}', '\u{0000040d}', '\u{00000418}', '\u{00000419}', '\u{000004e2}', '\u{000004e4}', '\u{00001e2c}', '\u{00001e2e}', '\u{00001ec8}', '\u{00001eca}', '\u{00001fd8}', '\u{00001fd9}', '\u{00002160}', '\u{0000ff29}', '\u{000030a7}', '\u{000030a8}', '\u{0000ff6a}', '\u{0000ff74}', '\u{000000ec}', '\u{000000ed}', '\u{000000ee}', '\u{000000ef}', '\u{00000129}', '\u{0000012b}', '\u{0000012d}', '\u{0000012f}', '\u{00000131}', '\u{000001d0}', '\u{00000209}', '\u{0000020b}', '\u{00000268}', '\u{00000269}', '\u{00000365}', '\u{000003af}', '\u{000003ca}', '\u{00000438}', '\u{00000439}', '\u{00000456}', '\u{0000045d}', '\u{000004e3}', '\u{000004e5}', '\u{00001e2d}', '\u{00001e2f}', '\u{00001ec9}', '\u{00001ecb}', '\u{00001f30}', '\u{00001f31}', '\u{00001f32}', '\u{00001f33}', '\u{00001f34}', '\u{00001f35}', '\u{00001f36}', '\u{00001f37}', '\u{00001f76}', '\u{00001f77}', '\u{00001fbe}', '\u{00001fd0}', '\u{00001fd1}', '\u{00001fd2}', '\u{00001fd3}', '\u{00001fd6}', '\u{00001fd7}', '\u{0000ff49}', '\u{00001d85}', '\u{00001e37}', '\u{00001e39}', '\u{00001e3b}', '\u{00001e3d}', '\u{000000fd}', '\u{000000ff}', '\u{00000177}', '\u{000001b4}', '\u{00000233}', '\u{0000024f}', '\u{0000028e}', '\u{000002b8}', '\u{00001e8f}', '\u{00001e99}', '\u{00001ef3}', '\u{00001ef5}', '\u{00001ef7}', '\u{00001ef9}', '\u{0000ff59}', ]) { map.push(['I', i]); } for (const g of [ '\u{0000006b}', '\u{00000067}', '\u{00000071}', '\u{00000034}', '\u{00000036}', '\u{00000039}', '\u{0000011f}', '\u{00000d6b}', '\u{0000ff47}', '\u{0000210a}', '\u{0001d420}', '\u{0001d454}', '\u{0001d488}', '\u{0001d4f0}', '\u{0001d524}', '\u{0001d558}', '\u{0001d58c}', '\u{0001d5c0}', '\u{0001d5f4}', '\u{0001d628}', '\u{0001d65c}', '\u{0001d690}', '\u{00000261}', '\u{00001d83}', '\u{0000018d}', '\u{00000581}', '\u{0001d406}', '\u{0001d43a}', '\u{0001d46e}', '\u{0001d4a2}', '\u{0001d4d6}', '\u{0001d50a}', '\u{0001d53e}', '\u{0001d572}', '\u{0001d5a6}', '\u{0001d5da}', '\u{00004e48}', '\u{0001d60e}', '\u{0001d642}', '\u{0001d676}', '\u{0000050c}', '\u{000013c0}', '\u{000013f3}', '\u{0000a4d6}', '\u{0000011c}', '\u{0000011e}', '\u{00000120}', '\u{00000122}', '\u{00000193}', '\u{000001e4}', '\u{000001e6}', '\u{000001f4}', '\u{0000029b}', '\u{00000393}', '\u{00000413}', '\u{00001e20}', '\u{0000ff27}', '\u{000013b6}', '\u{0000011d}', '\u{0000011f}', '\u{00000121}', '\u{00000123}', '\u{000001e5}', '\u{000001e7}', '\u{000001f5}', '\u{00000260}', '\u{00000261}', '\u{00000262}', '\u{00000040}', ]) { map.push(['G', g]); } for (const e of [ '\u{00001ec0}', '\u{000003a3}', '\u{0000039e}',