forked from seald/nedb
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathloadAndCrash.test.js
executable file
·133 lines (113 loc) · 3.48 KB
/
loadAndCrash.test.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
/* eslint-env mocha */
/* global DEBUG */
/**
* Load and modify part of fs to ensure writeFile will crash after writing 5000 bytes
*/
const fs = require('fs')
function rethrow () {
// Only enable in debug mode. A backtrace uses ~1000 bytes of heap space and
// is fairly slow to generate.
if (DEBUG) {
const backtrace = new Error()
return function (err) {
if (err) {
backtrace.stack = err.name + ': ' + err.message +
backtrace.stack.substr(backtrace.name.length)
throw backtrace
}
}
}
return function (err) {
if (err) {
throw err // Forgot a callback but don't know where? Use NODE_DEBUG=fs
}
}
}
function maybeCallback (cb) {
return typeof cb === 'function' ? cb : rethrow()
}
function isFd (path) {
return (path >>> 0) === path
}
function assertEncoding (encoding) {
if (encoding && !Buffer.isEncoding(encoding)) {
throw new Error('Unknown encoding: ' + encoding)
}
}
let onePassDone = false
function writeAll (fd, isUserFd, buffer, offset, length, position, callback_) {
const callback = maybeCallback(arguments[arguments.length - 1])
if (onePassDone) { process.exit(1) } // Crash on purpose before rewrite done
const l = Math.min(5000, length) // Force write by chunks of 5000 bytes to ensure data will be incomplete on crash
// write(fd, buffer, offset, length, position, callback)
fs.write(fd, buffer, offset, l, position, function (writeErr, written) {
if (writeErr) {
if (isUserFd) {
if (callback) callback(writeErr)
} else {
fs.close(fd, function () {
if (callback) callback(writeErr)
})
}
} else {
onePassDone = true
if (written === length) {
if (isUserFd) {
if (callback) callback(null)
} else {
fs.close(fd, callback)
}
} else {
offset += written
length -= written
if (position !== null) {
position += written
}
writeAll(fd, isUserFd, buffer, offset, length, position, callback)
}
}
})
}
fs.writeFile = function (path, data, options, callback_) {
const callback = maybeCallback(arguments[arguments.length - 1])
if (!options || typeof options === 'function') {
options = { encoding: 'utf8', mode: 438, flag: 'w' } // Mode 438 == 0o666 (compatibility with older Node releases)
} else if (typeof options === 'string') {
options = { encoding: options, mode: 438, flag: 'w' } // Mode 438 == 0o666 (compatibility with older Node releases)
} else if (typeof options !== 'object') {
throw new Error(`throwOptionsError${options}`)
}
assertEncoding(options.encoding)
const flag = options.flag || 'w'
if (isFd(path)) {
writeFd(path, true)
return
}
fs.open(path, flag, options.mode, function (openErr, fd) {
if (openErr) {
if (callback) callback(openErr)
} else {
writeFd(fd, false)
}
})
function writeFd (fd, isUserFd) {
const buffer = (data instanceof Buffer) ? data : Buffer.from('' + data, options.encoding || 'utf8')
const position = /a/.test(flag) ? null : 0
writeAll(fd, isUserFd, buffer, 0, buffer.length, position, callback)
}
}
fs.createWriteStream = function (path) {
let content = ''
return {
write (data) {
content += data
},
close (callback) {
fs.writeFile(path, content, callback)
}
}
}
// End of fs modification
const Nedb = require('../lib/datastore.js')
const db = new Nedb({ filename: 'workspace/lac.db' })
db.loadDatabase()