-
-
Notifications
You must be signed in to change notification settings - Fork 6.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add jest-serializer module #5609
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
**/__mocks__/** | ||
**/__tests__/** | ||
src |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,86 @@ | ||
# jest-serializer | ||
|
||
Module for serializing and deserializing object into memory and disk. By | ||
default, the `v8` implementations are used, but if not present, it defaults to | ||
`JSON` implementation. The V8 serializer has the advantage of being able to | ||
serialize `Map`, `Set`, `undefined`, circular references, etc. It is also a | ||
more compact format to be stored and sent over the wire. | ||
|
||
## Install | ||
|
||
```sh | ||
$ yarn add jest-serializer | ||
``` | ||
|
||
## API | ||
|
||
Three kinds of API groups are exposed: | ||
|
||
### In-memory serialization: `serialize` and `deserialize` | ||
|
||
This set of functions take or return a `Buffer`. All the process happens in | ||
memory. This is useful when willing to transfer over HTTP, TCP or via UNIX | ||
pipes. | ||
|
||
```javascript | ||
import serializer from 'jest-serializer'; | ||
|
||
const myObject = { | ||
foo: 'bar', | ||
baz: [0, true, '2', [], {}], | ||
}; | ||
|
||
const buffer = serializer.serialize(myObject); | ||
const myCopyObject = serializer.deserialize(buffer); | ||
``` | ||
|
||
### Synchronous persistent filesystem: `readFileSync` and `writeFileSync` | ||
|
||
This set of functions allow to send to disk a serialization result and retrieve | ||
it back, in a synchronous way. It mimics the `fs` API so it looks familiar. | ||
|
||
```javascript | ||
import serializer from 'jest-serializer'; | ||
|
||
const myObject = { | ||
foo: 'bar', | ||
baz: [0, true, '2', [], {}], | ||
}; | ||
|
||
const myFile = '/tmp/obj'; | ||
|
||
serializer.writeFileSync(myFile, myObject); | ||
const myCopyObject = serializer.readFileSync(myFile); | ||
``` | ||
|
||
### Asynchronous persistent filesystem: `readFile` and `writeFile` | ||
|
||
Pretty similar to the synchronous one, but providing a callback. It also mimics | ||
the `fs` API. | ||
|
||
```javascript | ||
import serializer from 'jest-serializer'; | ||
|
||
const myObject = { | ||
foo: 'bar', | ||
baz: [0, true, '2', [], {}], | ||
}; | ||
|
||
const myFile = '/tmp/obj'; | ||
|
||
serializer.writeFile(myFile, myObject, (err) => { | ||
if (err) { | ||
console.error(err); | ||
return; | ||
} | ||
|
||
serializer.readFile(myFile, (err, data) => { | ||
if (err) { | ||
console.error(err); | ||
return; | ||
} | ||
|
||
const myCopyObject = data; | ||
}); | ||
}); | ||
``` |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
{ | ||
"name": "jest-serializer", | ||
"version": "22.3.0", | ||
"repository": { | ||
"type": "git", | ||
"url": "https://github.com/facebook/jest.git" | ||
}, | ||
"license": "MIT", | ||
"main": "build/index.js", | ||
"dependencies": { | ||
"merge-stream": "^1.0.1" | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Where is used this dependency? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Nowhere 😳I just copy-pasted the |
||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,92 @@ | ||
/** | ||
* Copyright (c) 2018-present, Facebook, Inc. All rights reserved. | ||
* | ||
* This source code is licensed under the MIT license found in the | ||
* LICENSE file in the root directory of this source tree. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Some Flow maybe? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ah, pardon this is a test (so it's not necessary to flow it, but I like to mix these) |
||
*/ | ||
|
||
'use strict'; | ||
|
||
import fs from 'fs'; | ||
import os from 'os'; | ||
import path from 'path'; | ||
import v8 from 'v8'; | ||
|
||
import serializer from '..'; | ||
|
||
const v8s = [ | ||
{ | ||
deserialize: v8.deserialize, | ||
serialize: v8.serialize, | ||
}, | ||
{ | ||
deserialize: undefined, | ||
serialize: undefined, | ||
}, | ||
]; | ||
|
||
const objs = [ | ||
3, | ||
null, | ||
[0, true, '2', [3.14, {}, null]], | ||
{key1: 'foo', key2: 'bar', key3: {array: [null, {}]}}, | ||
]; | ||
|
||
const file = path.join(os.tmpdir(), '__jest-serialize-test__'); | ||
|
||
afterEach(() => { | ||
try { | ||
fs.unlinkSync(file); | ||
} catch (err) { | ||
// Do nothing if file does not exist. | ||
} | ||
}); | ||
|
||
// We execute the same suite of tests over multiple objects ("objs") and over | ||
// multiple mocks of the V8 object ("v8s") so that we verify that all possible | ||
// encodings and cases work. | ||
v8s.forEach((mockV8, i) => { | ||
describe('Using V8 implementation ' + i, () => { | ||
jest.mock('v8', () => mockV8); | ||
|
||
it('throws the error with an invalid serialization', done => { | ||
// No chance this is a valid serialization, neither in JSON nor V8. | ||
const invalidBuffer = Buffer.from([0x00, 0x55, 0xaa, 0xff]); | ||
|
||
fs.writeFileSync(file, invalidBuffer); | ||
|
||
expect(() => serializer.deserialize(invalidBuffer)).toThrow(); | ||
expect(() => serializer.readFileSync(file)).toThrow(); | ||
|
||
serializer.readFile(file, err => { | ||
expect(err).toBeDefined(); | ||
done(); | ||
}); | ||
}); | ||
|
||
objs.forEach((obj, i) => { | ||
describe('Object ' + i, () => { | ||
it('serializes/deserializes in memory', () => { | ||
const buf = serializer.serialize(obj); | ||
|
||
expect(buf).toBeInstanceOf(Buffer); | ||
expect(serializer.deserialize(buf)).toEqual(obj); | ||
}); | ||
|
||
it('serializes/deserializes in disk, synchronously', () => { | ||
serializer.writeFileSync(file, obj); | ||
expect(serializer.readFileSync(file)).toEqual(obj); | ||
}); | ||
|
||
it('serializes/deserializes in disk, asynchronously', done => { | ||
serializer.writeFile(file, obj, err => { | ||
serializer.readFile(file, (err, data) => { | ||
expect(data).toEqual(obj); | ||
done(); | ||
}); | ||
}); | ||
}); | ||
}); | ||
}); | ||
}); | ||
}); |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,107 @@ | ||
/** | ||
* Copyright (c) 2018-present, Facebook, Inc. All rights reserved. | ||
* | ||
* This source code is licensed under the MIT license found in the | ||
* LICENSE file in the root directory of this source tree. | ||
* | ||
* @flow | ||
*/ | ||
|
||
'use strict'; | ||
|
||
import fs from 'fs'; | ||
import v8 from 'v8'; | ||
|
||
import type {Path} from 'types/Config'; | ||
|
||
type IOCallback = (?Error, ?any) => void; | ||
|
||
// JSON and V8 serializers are both stable when it comes to compatibility. The | ||
// current JSON specification is well defined in RFC 8259, and V8 ensures that | ||
// the versions are compatible by encoding the serialization version in the own | ||
// generated buffer. | ||
|
||
// In memory functions. | ||
|
||
export function serialize(content: any): Buffer { | ||
return v8.serialize | ||
? v8.serialize(content) | ||
: Buffer.from(JSON.stringify(content)); | ||
} | ||
|
||
export function deserialize(buffer: Buffer): any { | ||
return v8.deserialize | ||
? v8.deserialize(buffer) | ||
: Buffer.from(JSON.stringify(buffer.toString('utf8'))); | ||
} | ||
|
||
// Synchronous filesystem functions. | ||
|
||
export function readFileSync(file: Path): any { | ||
return v8.deserialize | ||
? v8.deserialize(fs.readFileSync(file)) | ||
: JSON.parse(fs.readFileSync(file, 'utf8')); | ||
} | ||
|
||
export function writeFileSync(file: Path, content: any) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. can you call this |
||
return v8.serialize | ||
? fs.writeFileSync(file, v8.serialize(content)) | ||
: fs.writeFileSync(file, JSON.stringify(content), 'utf8'); | ||
} | ||
|
||
// Asynchronous filesystem functions. | ||
|
||
export function readFile(file: Path, callback: IOCallback) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. if we expose an async API, I'd prefer it to be promise instead of callback based There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I just killed the async one 😜. But you are right; it should have been The reason for killing it is because we don't really need it anywhere: neither in |
||
if (v8.deserialize) { | ||
fs.readFile(file, (err, data) => { | ||
if (err) { | ||
callback(err); | ||
return; | ||
} | ||
|
||
try { | ||
callback(null, v8.deserialize(data)); | ||
} catch (error) { | ||
callback(error); | ||
} | ||
}); | ||
} else { | ||
fs.readFile(file, 'utf8', (err, data) => { | ||
if (err) { | ||
callback(err); | ||
return; | ||
} | ||
|
||
try { | ||
callback(null, JSON.parse(data)); | ||
} catch (error) { | ||
callback(error); | ||
} | ||
}); | ||
} | ||
} | ||
|
||
export function writeFile(file: Path, content: any, callback: IOCallback) { | ||
if (v8.serialize) { | ||
try { | ||
fs.writeFile(file, v8.serialize(content), callback); | ||
} catch (err) { | ||
callback(err); | ||
} | ||
} else { | ||
try { | ||
fs.writeFile(file, JSON.stringify(content), callback); | ||
} catch (err) { | ||
callback(err); | ||
} | ||
} | ||
} | ||
|
||
export default { | ||
deserialize, | ||
readFile, | ||
readFileSync, | ||
serialize, | ||
writeFile, | ||
writeFileSync, | ||
}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Destructuring maybe?