blockstore: tests and fixes for blockstore error cases

This commit is contained in:
Braydon Fuller 2019-03-14 10:28:51 -07:00
parent 0f0cb00c54
commit 747a8e707b
No known key found for this signature in database
GPG Key ID: F24F232D108B3AD4
2 changed files with 143 additions and 4 deletions

View File

@ -47,6 +47,9 @@ class FileBlockStore extends AbstractBlockStore {
this.maxFileLength = options.maxFileLength || 128 * 1024 * 1024;
assert(Number.isSafeInteger(this.maxFileLength),
'Invalid max file length.');
this.network = Network.primary;
if (options.network != null)
@ -319,11 +322,15 @@ class FileBlockStore extends AbstractBlockStore {
await fs.close(fd);
if (mwritten !== mlength)
if (mwritten !== mlength) {
this.writing = false;
throw new Error('Could not write block magic.');
}
if (bwritten !== blength)
if (bwritten !== blength) {
this.writing = false;
throw new Error('Could not write block.');
}
filerecord.blocks += 1;
filerecord.used += length;

View File

@ -64,8 +64,9 @@ describe('BlockStore', function() {
});
it('has unimplemented base methods', async () => {
const methods = ['open', 'close', 'write', 'read',
'prune', 'has'];
const methods = ['open', 'close', 'write', 'writeUndo',
'read', 'readUndo', 'prune', 'pruneUndo',
'has', 'hasUndo', 'ensure'];
const store = new AbstractBlockStore();
@ -277,6 +278,40 @@ describe('BlockStore', function() {
});
});
describe('constructor', function() {
it('will error with invalid location', () => {
let err = null;
try {
new FileBlockStore({
location: 'tmp/.bcoin/blocks',
maxFileLength: 1024
});
} catch (e) {
err = e;
}
assert(err);
assert.equal(err.message, 'Location not absolute.');
});
it('will error with invalid max file length', () => {
let err = null;
try {
new FileBlockStore({
location: location,
maxFileLength: 'notanumber'
});
} catch (e) {
err = e;
}
assert(err);
assert.equal(err.message, 'Invalid max file length.');
});
});
describe('allocate', function() {
it('will fail with length above file max', async () => {
let err = null;
@ -337,6 +372,103 @@ describe('BlockStore', function() {
const filepath = store.filepath(types.UNDO, 99999);
assert.equal(filepath, '/tmp/.bcoin/blocks/blu99999.dat');
});
it('will fail for unknown prefix', () => {
let err = null;
try {
store.filepath(0, 1234);
} catch (e) {
err = e;
}
assert(err);
assert.equal(err.message, 'Unknown file prefix.');
});
});
describe('write', function() {
const write = fs.write;
const open = fs.open;
const close = fs.close;
let allocate = null;
beforeEach(() => {
allocate = store.allocate;
});
afterEach(() => {
// Restore stubbed methods.
fs.write = write;
fs.open = open;
fs.close = close;
store.allocate = allocate;
});
it('will error if total magic bytes not written', async () => {
let err = null;
store.allocate = () => {
return {
fileno: 20,
filerecord: {
used: 0
},
filepath: '/tmp/.bcoin/blocks/blk00020.dat'
};
};
fs.open = () => 7;
fs.close = () => undefined;
fs.write = () => 0;
try {
const hash = random.randomBytes(128);
const block = random.randomBytes(32);
await store.write(hash, block);
} catch (e) {
err = e;
}
assert(err, 'Expected error.');
assert.equal(err.message, 'Could not write block magic.');
});
it('will error if total block bytes not written', async () => {
let err = 0;
let called = 0;
store.allocate = () => {
return {
fileno: 20,
filerecord: {
used: 0
},
filepath: '/tmp/.bcoin/blocks/blk00020.dat'
};
};
fs.open = () => 7;
fs.close = () => undefined;
fs.write = (fd, buffer, offset, length, position) => {
let written = 0;
if (called === 0)
written = length;
called += 1;
return written;
};
try {
const hash = random.randomBytes(128);
const block = random.randomBytes(32);
await store.write(hash, block);
} catch (e) {
err = e;
}
assert(err, 'Expected error.');
assert.equal(err.message, 'Could not write block.');
});
});
});