mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 01:38:56 -04:00
[kbn-es] add basic integration tests for exit code/promise handling (#17600)
This commit is contained in:
parent
d9f34f704e
commit
1fd537821f
3 changed files with 340 additions and 1 deletions
|
@ -176,7 +176,7 @@ exports.Cluster = class Cluster {
|
|||
this._process.once('exit', code => {
|
||||
// JVM exits with 143 on SIGTERM and 130 on SIGINT, dont' treat them as errors
|
||||
if (code > 0 && !(code === 143 || code === 130)) {
|
||||
reject(createCliError(`ES exitted with code ${code}`));
|
||||
reject(createCliError(`ES exited with code ${code}`));
|
||||
} else {
|
||||
resolve();
|
||||
}
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
#!/usr/bin/env node
|
||||
|
||||
const { exitCode, start } = JSON.parse(process.argv[2]);
|
||||
|
||||
if (start) {
|
||||
console.log('started');
|
||||
}
|
||||
|
||||
process.exitCode = exitCode;
|
330
packages/kbn-es/src/integration_tests/cluster.test.js
Normal file
330
packages/kbn-es/src/integration_tests/cluster.test.js
Normal file
|
@ -0,0 +1,330 @@
|
|||
const { createToolingLog } = require('@kbn/dev-utils');
|
||||
const execa = require('execa');
|
||||
const { Cluster } = require('../cluster');
|
||||
const {
|
||||
installSource,
|
||||
installSnapshot,
|
||||
installArchive,
|
||||
} = require('../install');
|
||||
|
||||
jest.mock('../install', () => ({
|
||||
installSource: jest.fn(),
|
||||
installSnapshot: jest.fn(),
|
||||
installArchive: jest.fn(),
|
||||
}));
|
||||
|
||||
jest.mock('execa', () => jest.fn());
|
||||
|
||||
const log = createToolingLog('verbose');
|
||||
log.onData = jest.fn();
|
||||
log.on('data', log.onData);
|
||||
|
||||
function sleep(ms) {
|
||||
return new Promise(resolve => setTimeout(resolve, ms));
|
||||
}
|
||||
|
||||
async function ensureNoResolve(promise) {
|
||||
await Promise.race([
|
||||
sleep(100),
|
||||
promise.then(() => {
|
||||
throw new Error('promise was not supposed to resolve');
|
||||
}),
|
||||
]);
|
||||
}
|
||||
|
||||
async function ensureResolve(promise) {
|
||||
return await Promise.race([
|
||||
promise,
|
||||
sleep(100).then(() => {
|
||||
throw new Error(
|
||||
'promise was supposed to resolve with installSource() resolution'
|
||||
);
|
||||
}),
|
||||
]);
|
||||
}
|
||||
|
||||
function mockEsBin({ exitCode, start }) {
|
||||
execa.mockImplementationOnce((cmd, args, options) =>
|
||||
require.requireActual('execa')(
|
||||
process.execPath,
|
||||
[
|
||||
require.resolve('./__fixtures__/es_bin.js'),
|
||||
JSON.stringify({
|
||||
exitCode,
|
||||
start,
|
||||
}),
|
||||
],
|
||||
options
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
beforeEach(() => {
|
||||
jest.resetAllMocks();
|
||||
});
|
||||
|
||||
describe('#installSource()', () => {
|
||||
it('awaits installSource() promise and returns { installPath }', async () => {
|
||||
let resolveInstallSource;
|
||||
installSource.mockImplementationOnce(
|
||||
() =>
|
||||
new Promise(resolve => {
|
||||
resolveInstallSource = () => {
|
||||
resolve({ installPath: 'foo' });
|
||||
};
|
||||
})
|
||||
);
|
||||
|
||||
const cluster = new Cluster(log);
|
||||
const promise = cluster.installSource();
|
||||
await ensureNoResolve(promise);
|
||||
resolveInstallSource();
|
||||
await expect(ensureResolve(promise)).resolves.toEqual({
|
||||
installPath: 'foo',
|
||||
});
|
||||
});
|
||||
|
||||
it('passes through all options+log to installSource()', async () => {
|
||||
installSource.mockResolvedValue({});
|
||||
const cluster = new Cluster(log);
|
||||
await cluster.installSource({ foo: 'bar' });
|
||||
expect(installSource).toHaveBeenCalledTimes(1);
|
||||
expect(installSource).toHaveBeenCalledWith({
|
||||
log,
|
||||
foo: 'bar',
|
||||
});
|
||||
});
|
||||
|
||||
it('rejects if installSource() rejects', async () => {
|
||||
installSource.mockRejectedValue(new Error('foo'));
|
||||
const cluster = new Cluster(log);
|
||||
await expect(cluster.installSource()).rejects.toThrowError('foo');
|
||||
});
|
||||
});
|
||||
|
||||
describe('#installSnapshot()', () => {
|
||||
it('awaits installSnapshot() promise and returns { installPath }', async () => {
|
||||
let resolveInstallSnapshot;
|
||||
installSnapshot.mockImplementationOnce(
|
||||
() =>
|
||||
new Promise(resolve => {
|
||||
resolveInstallSnapshot = () => {
|
||||
resolve({ installPath: 'foo' });
|
||||
};
|
||||
})
|
||||
);
|
||||
|
||||
const cluster = new Cluster(log);
|
||||
const promise = cluster.installSnapshot();
|
||||
await ensureNoResolve(promise);
|
||||
resolveInstallSnapshot();
|
||||
await expect(ensureResolve(promise)).resolves.toEqual({
|
||||
installPath: 'foo',
|
||||
});
|
||||
});
|
||||
|
||||
it('passes through all options+log to installSnapshot()', async () => {
|
||||
installSnapshot.mockResolvedValue({});
|
||||
const cluster = new Cluster(log);
|
||||
await cluster.installSnapshot({ foo: 'bar' });
|
||||
expect(installSnapshot).toHaveBeenCalledTimes(1);
|
||||
expect(installSnapshot).toHaveBeenCalledWith({
|
||||
log,
|
||||
foo: 'bar',
|
||||
});
|
||||
});
|
||||
|
||||
it('rejects if installSnapshot() rejects', async () => {
|
||||
installSnapshot.mockRejectedValue(new Error('foo'));
|
||||
const cluster = new Cluster(log);
|
||||
await expect(cluster.installSnapshot()).rejects.toThrowError('foo');
|
||||
});
|
||||
});
|
||||
|
||||
describe('#installArchive(path)', () => {
|
||||
it('awaits installArchive() promise and returns { installPath }', async () => {
|
||||
let resolveInstallArchive;
|
||||
installArchive.mockImplementationOnce(
|
||||
() =>
|
||||
new Promise(resolve => {
|
||||
resolveInstallArchive = () => {
|
||||
resolve({ installPath: 'foo' });
|
||||
};
|
||||
})
|
||||
);
|
||||
|
||||
const cluster = new Cluster(log);
|
||||
const promise = cluster.installArchive();
|
||||
await ensureNoResolve(promise);
|
||||
resolveInstallArchive();
|
||||
await expect(ensureResolve(promise)).resolves.toEqual({
|
||||
installPath: 'foo',
|
||||
});
|
||||
});
|
||||
|
||||
it('passes through path and all options+log to installArchive()', async () => {
|
||||
installArchive.mockResolvedValue({});
|
||||
const cluster = new Cluster(log);
|
||||
await cluster.installArchive('path', { foo: 'bar' });
|
||||
expect(installArchive).toHaveBeenCalledTimes(1);
|
||||
expect(installArchive).toHaveBeenCalledWith('path', {
|
||||
log,
|
||||
foo: 'bar',
|
||||
});
|
||||
});
|
||||
|
||||
it('rejects if installArchive() rejects', async () => {
|
||||
installArchive.mockRejectedValue(new Error('foo'));
|
||||
const cluster = new Cluster(log);
|
||||
await expect(cluster.installArchive()).rejects.toThrowError('foo');
|
||||
});
|
||||
});
|
||||
|
||||
describe('#start(installPath)', () => {
|
||||
it('rejects when bin/elasticsearch exists with 0 before starting', async () => {
|
||||
mockEsBin({ exitCode: 0, start: false });
|
||||
|
||||
await expect(new Cluster(log).start()).rejects.toThrowError(
|
||||
'ES exited without starting'
|
||||
);
|
||||
});
|
||||
|
||||
it('rejects when bin/elasticsearch exists with 143 before starting', async () => {
|
||||
mockEsBin({ exitCode: 143, start: false });
|
||||
|
||||
await expect(new Cluster(log).start()).rejects.toThrowError(
|
||||
'ES exited without starting'
|
||||
);
|
||||
});
|
||||
|
||||
it('rejects when bin/elasticsearch exists with 130 before starting', async () => {
|
||||
mockEsBin({ exitCode: 130, start: false });
|
||||
|
||||
await expect(new Cluster(log).start()).rejects.toThrowError(
|
||||
'ES exited without starting'
|
||||
);
|
||||
});
|
||||
|
||||
it('rejects when bin/elasticsearch exists with 1 before starting', async () => {
|
||||
mockEsBin({ exitCode: 1, start: false });
|
||||
|
||||
await expect(new Cluster(log).start()).rejects.toThrowError(
|
||||
'ES exited with code 1'
|
||||
);
|
||||
});
|
||||
|
||||
it('resolves when bin/elasticsearch logs "started"', async () => {
|
||||
mockEsBin({ start: true });
|
||||
|
||||
await new Cluster(log).start();
|
||||
});
|
||||
|
||||
it('rejects if #start() was called previously', async () => {
|
||||
mockEsBin({ start: true });
|
||||
|
||||
const cluster = new Cluster(log);
|
||||
await cluster.start();
|
||||
await expect(cluster.start()).rejects.toThrowError(
|
||||
'ES has already been started'
|
||||
);
|
||||
});
|
||||
|
||||
it('rejects if #run() was called previously', async () => {
|
||||
mockEsBin({ start: true });
|
||||
|
||||
const cluster = new Cluster(log);
|
||||
await cluster.run();
|
||||
await expect(cluster.start()).rejects.toThrowError(
|
||||
'ES has already been started'
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#run()', () => {
|
||||
it('resolves when bin/elasticsearch exists with 0', async () => {
|
||||
mockEsBin({ exitCode: 0 });
|
||||
|
||||
await new Cluster(log).run();
|
||||
});
|
||||
|
||||
it('resolves when bin/elasticsearch exists with 143', async () => {
|
||||
mockEsBin({ exitCode: 143 });
|
||||
|
||||
await new Cluster(log).run();
|
||||
});
|
||||
|
||||
it('resolves when bin/elasticsearch exists with 130', async () => {
|
||||
mockEsBin({ exitCode: 130 });
|
||||
|
||||
await new Cluster(log).run();
|
||||
});
|
||||
|
||||
it('rejects when bin/elasticsearch exists with 1', async () => {
|
||||
mockEsBin({ exitCode: 1 });
|
||||
|
||||
await expect(new Cluster(log).run()).rejects.toThrowError(
|
||||
'ES exited with code 1'
|
||||
);
|
||||
});
|
||||
|
||||
it('rejects if #start() was called previously', async () => {
|
||||
mockEsBin({ exitCode: 0, start: true });
|
||||
|
||||
const cluster = new Cluster(log);
|
||||
await cluster.start();
|
||||
await expect(cluster.run()).rejects.toThrowError(
|
||||
'ES has already been started'
|
||||
);
|
||||
});
|
||||
|
||||
it('rejects if #run() was called previously', async () => {
|
||||
mockEsBin({ exitCode: 0 });
|
||||
|
||||
const cluster = new Cluster(log);
|
||||
await cluster.run();
|
||||
await expect(cluster.run()).rejects.toThrowError(
|
||||
'ES has already been started'
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#stop()', () => {
|
||||
it('rejects if #run() or #start() was not called', async () => {
|
||||
const cluster = new Cluster(log);
|
||||
await expect(cluster.stop()).rejects.toThrowError(
|
||||
'ES has not been started'
|
||||
);
|
||||
});
|
||||
|
||||
it('resolves when ES exits with 0', async () => {
|
||||
mockEsBin({ exitCode: 0, start: true });
|
||||
|
||||
const cluster = new Cluster(log);
|
||||
await cluster.start();
|
||||
await cluster.stop();
|
||||
});
|
||||
|
||||
it('resolves when ES exits with 143', async () => {
|
||||
mockEsBin({ exitCode: 143, start: true });
|
||||
|
||||
const cluster = new Cluster(log);
|
||||
await cluster.start();
|
||||
await cluster.stop();
|
||||
});
|
||||
|
||||
it('resolves when ES exits with 130', async () => {
|
||||
mockEsBin({ exitCode: 130, start: true });
|
||||
|
||||
const cluster = new Cluster(log);
|
||||
await cluster.start();
|
||||
await cluster.stop();
|
||||
});
|
||||
|
||||
it('rejects when ES exits with 1', async () => {
|
||||
mockEsBin({ exitCode: 1, start: true });
|
||||
|
||||
const cluster = new Cluster(log);
|
||||
await expect(cluster.run()).rejects.toThrowError('ES exited with code 1');
|
||||
await expect(cluster.stop()).rejects.toThrowError('ES exited with code 1');
|
||||
});
|
||||
});
|
Loading…
Add table
Add a link
Reference in a new issue