UNPKG

pickleparser

Version:

A pure Javascript implemented parser for Python pickle format

141 lines (122 loc) 5.59 kB
import { OP } from '../src/opcode'; import { Parser, ParserOptions } from '../src/parser'; import { BufferReader } from '../src/reader'; describe('Parser', () => { describe('#constructor', () => { it('can be constructed', () => { const parser = new Parser(); expect(parser).toBeDefined(); }); it('has correct defalut options', () => { const parser = new Parser(); // eslint-disable-next-line @typescript-eslint/no-explicit-any const options: ParserOptions = (parser as any)._options; expect(options.unpicklingTypeOfSet).toEqual('array'); expect(options.unpicklingTypeOfDictionary).toEqual('object'); const [module, name] = ['myModule', 'myName']; const pobj = options.nameResolver.resolve(module, name); expect(pobj.prototype).toHaveProperty('__module__', module); expect(pobj.prototype).toHaveProperty('__name__', name); expect(pobj.name).toEqual('PObject'); const pid = '5'; expect(() => options.persistentResolver.resolve(pid)).toThrow(`Unregistered persistent id: \`${pid}\`.`); const extCode = 3; expect(() => options.extensionResolver.resolve(extCode)).toThrow( `Unregistered extension code: \`${extCode.toString(16)}\`.`, ); }); it('correctly load Resolvers', () => { const parser = new Parser({ nameResolver: { resolve(module, name) { return () => [module, name]; }, }, extensionResolver: { resolve(extCode) { return extCode; }, }, persistentResolver: { resolve(pid) { return pid; }, }, }); // eslint-disable-next-line @typescript-eslint/no-explicit-any const options: ParserOptions = (parser as any)._options; const [module, name] = ['myModule', 'myName']; expect((options.nameResolver.resolve(module, name) as () => [string, string])()).toEqual([module, name]); const pid = '5'; expect(options.persistentResolver.resolve(pid)).toEqual(pid); const extCode = 3; expect(options.extensionResolver.resolve(extCode)).toEqual(extCode); }); it('correctly load options', () => { // eslint-disable-next-line @typescript-eslint/no-explicit-any const parser = new Parser({ unpicklingTypeOfSet: 'Set', unpicklingTypeOfDictionary: 'Map', }); // eslint-disable-next-line @typescript-eslint/no-explicit-any const options: ParserOptions = (parser as any)._options; expect(options.unpicklingTypeOfSet).toEqual('Set'); expect(options.unpicklingTypeOfDictionary).toEqual('Map'); }); }); describe('#read', () => { it('correctly read data', () => { const parser = new Parser(); const pkl = new Uint8Array([OP.PROTO, 4, OP.BININT1, 3, OP.STOP]); const reader = new BufferReader(pkl); expect(parser.read(reader)).toEqual(3); }); }); describe('#parse', () => { it('throws an error if the input buffer is empty', () => { const parser = new Parser(); expect(() => parser.parse(new Uint8Array())).toThrow('Unexpected end of file.'); }); it('correctly parse data', () => { const parser = new Parser(); const pkl = new Uint8Array([OP.PROTO, 4, OP.BININT1, 3, OP.STOP]); expect(parser.parse(pkl)).toEqual(3); }); it('correctly load buffers', () => { const expected = [123, 'str']; const parser = new Parser({ buffers: (function* () { yield expected; })(), }); const pkl = new Uint8Array([OP.PROTO, 5, OP.NEXT_BUFFER, OP.STOP]); expect(parser.parse(pkl)).toStrictEqual(expected); }); it('throws errors if buffers not provided', () => { const parser = new Parser(); const pkl = new Uint8Array([OP.PROTO, 5, OP.NEXT_BUFFER, OP.STOP]); expect(() => parser.parse(pkl)).toThrow( 'pickle stream refers to out-of-band data but no *buffers* argument was given', ); }); it('throws errors if not enough buffers', () => { const parser = new Parser({ buffers: (function* () { yield 1; })(), }); const pkl = new Uint8Array([OP.PROTO, 5, OP.NEXT_BUFFER, OP.NEXT_BUFFER, OP.STOP]); expect(() => parser.parse(pkl)).toThrow('not enough out-of-band buffers'); }); it('throws errors w/ unsupported OP code', () => { const parser = new Parser(); const pkl = new Uint8Array([OP.READONLY_BUFFER + 1]); expect(() => parser.parse(pkl)).toThrow("Unsupported opcode '153'."); }); it('throws errors w/ unsupported protocol', () => { const parser = new Parser(); const pkl = new Uint8Array([OP.PROTO, 6, OP.STOP]); expect(() => parser.parse(pkl)).toThrow("Unsupported protocol version '6'."); }); }); });