2023-04-10 15:36:59 +00:00
|
|
|
/**
|
|
|
|
* Copyright (c) HashiCorp, Inc.
|
|
|
|
* SPDX-License-Identifier: MPL-2.0
|
|
|
|
*/
|
|
|
|
|
2017-12-15 21:39:18 +00:00
|
|
|
import EmberObject from '@ember/object';
|
|
|
|
import RSVP from 'rsvp';
|
|
|
|
import { run } from '@ember/runloop';
|
2017-11-21 19:22:17 +00:00
|
|
|
import sinon from 'sinon';
|
2019-03-13 00:04:16 +00:00
|
|
|
import { module, test } from 'qunit';
|
2017-11-21 19:22:17 +00:00
|
|
|
import _Log from 'nomad-ui/utils/classes/log';
|
|
|
|
|
2019-03-13 00:04:16 +00:00
|
|
|
import { settled } from '@ember/test-helpers';
|
|
|
|
|
2017-11-21 19:22:17 +00:00
|
|
|
let startSpy, stopSpy, initSpy, fetchSpy;
|
|
|
|
|
|
|
|
const MockStreamer = EmberObject.extend({
|
|
|
|
init() {
|
2020-06-09 21:03:28 +00:00
|
|
|
this.poll = {
|
|
|
|
isRunning: false,
|
|
|
|
};
|
|
|
|
|
2017-11-21 19:22:17 +00:00
|
|
|
initSpy(...arguments);
|
|
|
|
},
|
|
|
|
|
|
|
|
start() {
|
2021-02-17 21:01:44 +00:00
|
|
|
this.poll.isRunning = true;
|
2017-11-21 19:22:17 +00:00
|
|
|
startSpy(...arguments);
|
|
|
|
},
|
|
|
|
|
|
|
|
stop() {
|
2021-02-17 21:01:44 +00:00
|
|
|
this.poll.isRunning = true;
|
2017-11-21 19:22:17 +00:00
|
|
|
stopSpy(...arguments);
|
|
|
|
},
|
|
|
|
|
|
|
|
step(chunk) {
|
2021-02-17 21:01:44 +00:00
|
|
|
if (this.poll.isRunning) {
|
|
|
|
this.write(chunk);
|
2017-11-21 19:22:17 +00:00
|
|
|
}
|
|
|
|
},
|
|
|
|
});
|
|
|
|
|
|
|
|
const Log = _Log.extend({
|
|
|
|
init() {
|
|
|
|
this._super();
|
2021-12-28 16:08:12 +00:00
|
|
|
const props = this.logStreamer.getProperties(
|
|
|
|
'url',
|
|
|
|
'params',
|
|
|
|
'logFetch',
|
|
|
|
'write'
|
|
|
|
);
|
2017-11-21 19:22:17 +00:00
|
|
|
this.set('logStreamer', MockStreamer.create(props));
|
|
|
|
},
|
|
|
|
});
|
|
|
|
|
2021-12-28 14:45:20 +00:00
|
|
|
module('Unit | Util | Log', function (hooks) {
|
|
|
|
hooks.beforeEach(function () {
|
2017-11-21 19:22:17 +00:00
|
|
|
initSpy = sinon.spy();
|
|
|
|
startSpy = sinon.spy();
|
|
|
|
stopSpy = sinon.spy();
|
|
|
|
fetchSpy = sinon.spy();
|
2019-03-13 00:04:16 +00:00
|
|
|
});
|
2017-11-21 19:22:17 +00:00
|
|
|
|
2021-12-28 14:45:20 +00:00
|
|
|
const makeMocks = (output) => ({
|
2019-03-13 00:04:16 +00:00
|
|
|
url: '/test-url/',
|
|
|
|
params: {
|
|
|
|
a: 'param',
|
|
|
|
another: 'one',
|
|
|
|
},
|
2021-12-28 14:45:20 +00:00
|
|
|
logFetch: function () {
|
2019-03-13 00:04:16 +00:00
|
|
|
fetchSpy(...arguments);
|
|
|
|
return RSVP.Promise.resolve({
|
|
|
|
text() {
|
|
|
|
return output;
|
|
|
|
},
|
|
|
|
});
|
|
|
|
},
|
|
|
|
});
|
2017-11-21 19:22:17 +00:00
|
|
|
|
2021-12-28 14:45:20 +00:00
|
|
|
test('logStreamer is created on init', async function (assert) {
|
2019-03-13 00:04:16 +00:00
|
|
|
const log = Log.create(makeMocks(''));
|
2017-11-21 19:22:17 +00:00
|
|
|
|
2019-03-13 00:04:16 +00:00
|
|
|
assert.ok(log.get('logStreamer'), 'logStreamer property is defined');
|
|
|
|
assert.ok(initSpy.calledOnce, 'logStreamer init was called');
|
|
|
|
});
|
2017-11-21 19:22:17 +00:00
|
|
|
|
2021-12-28 14:45:20 +00:00
|
|
|
test('gotoHead builds the correct URL', async function (assert) {
|
2021-12-28 19:30:38 +00:00
|
|
|
assert.expect(1);
|
|
|
|
|
2019-03-13 00:04:16 +00:00
|
|
|
const mocks = makeMocks('');
|
2019-06-26 21:52:41 +00:00
|
|
|
const expectedUrl = `${mocks.url}?a=param&another=one&offset=0&origin=start`;
|
2019-03-13 00:04:16 +00:00
|
|
|
const log = Log.create(mocks);
|
2017-11-21 19:22:17 +00:00
|
|
|
|
2019-03-13 00:04:16 +00:00
|
|
|
run(() => {
|
|
|
|
log.get('gotoHead').perform();
|
2021-12-28 16:08:12 +00:00
|
|
|
assert.ok(
|
|
|
|
fetchSpy.calledWith(expectedUrl),
|
|
|
|
`gotoHead URL was ${expectedUrl}`
|
|
|
|
);
|
2019-03-13 00:04:16 +00:00
|
|
|
});
|
2017-11-21 19:22:17 +00:00
|
|
|
});
|
|
|
|
|
2021-12-28 14:45:20 +00:00
|
|
|
test('When gotoHead returns too large of a log, the log is truncated', async function (assert) {
|
|
|
|
const longLog = Array(50001).fill('a').join('');
|
2019-06-26 21:52:41 +00:00
|
|
|
const encodedLongLog = `{"Offset":0,"Data":"${window.btoa(longLog)}"}`;
|
2019-03-13 00:04:16 +00:00
|
|
|
const truncationMessage =
|
|
|
|
'\n\n---------- TRUNCATED: Click "tail" to view the bottom of the log ----------';
|
2017-11-21 19:22:17 +00:00
|
|
|
|
2019-06-26 21:52:41 +00:00
|
|
|
const mocks = makeMocks(encodedLongLog);
|
2019-03-13 00:04:16 +00:00
|
|
|
const log = Log.create(mocks);
|
2017-11-21 19:22:17 +00:00
|
|
|
|
2019-03-13 00:04:16 +00:00
|
|
|
run(() => {
|
|
|
|
log.get('gotoHead').perform();
|
|
|
|
});
|
2017-11-21 19:22:17 +00:00
|
|
|
|
2019-03-14 18:35:46 +00:00
|
|
|
await settled();
|
2019-06-26 21:52:41 +00:00
|
|
|
assert.ok(
|
2021-12-28 14:45:20 +00:00
|
|
|
log.get('output').toString().endsWith(truncationMessage),
|
2019-06-26 21:52:41 +00:00
|
|
|
'Truncation message is shown'
|
|
|
|
);
|
2019-03-14 18:35:46 +00:00
|
|
|
assert.equal(
|
2019-04-27 15:21:26 +00:00
|
|
|
log.get('output').toString().length,
|
2019-03-14 18:35:46 +00:00
|
|
|
50000 + truncationMessage.length,
|
|
|
|
'Output is truncated the appropriate amount'
|
|
|
|
);
|
2017-11-21 19:22:17 +00:00
|
|
|
});
|
|
|
|
|
2021-12-28 14:45:20 +00:00
|
|
|
test('gotoTail builds the correct URL', async function (assert) {
|
2021-12-28 19:30:38 +00:00
|
|
|
assert.expect(1);
|
|
|
|
|
2019-03-13 00:04:16 +00:00
|
|
|
const mocks = makeMocks('');
|
2019-06-26 21:52:41 +00:00
|
|
|
const expectedUrl = `${mocks.url}?a=param&another=one&offset=50000&origin=end`;
|
2019-03-13 00:04:16 +00:00
|
|
|
const log = Log.create(mocks);
|
2017-11-21 19:22:17 +00:00
|
|
|
|
2019-03-13 00:04:16 +00:00
|
|
|
run(() => {
|
|
|
|
log.get('gotoTail').perform();
|
2021-12-28 16:08:12 +00:00
|
|
|
assert.ok(
|
|
|
|
fetchSpy.calledWith(expectedUrl),
|
|
|
|
`gotoTail URL was ${expectedUrl}`
|
|
|
|
);
|
2019-03-13 00:04:16 +00:00
|
|
|
});
|
2017-11-21 19:22:17 +00:00
|
|
|
});
|
|
|
|
|
2021-12-28 14:45:20 +00:00
|
|
|
test('startStreaming starts the log streamer', async function (assert) {
|
2019-03-13 00:04:16 +00:00
|
|
|
const log = Log.create(makeMocks(''));
|
2017-11-21 19:22:17 +00:00
|
|
|
|
2019-03-13 00:04:16 +00:00
|
|
|
log.startStreaming();
|
|
|
|
assert.ok(startSpy.calledOnce, 'Streaming started');
|
2021-12-28 16:08:12 +00:00
|
|
|
assert.equal(
|
|
|
|
log.get('logPointer'),
|
|
|
|
'tail',
|
|
|
|
'Streaming points the log to the tail'
|
|
|
|
);
|
2019-03-13 00:04:16 +00:00
|
|
|
});
|
2017-11-21 19:22:17 +00:00
|
|
|
|
2021-12-28 14:45:20 +00:00
|
|
|
test('When the log streamer calls `write`, the output is appended', async function (assert) {
|
2019-03-13 00:04:16 +00:00
|
|
|
const log = Log.create(makeMocks(''));
|
|
|
|
const chunk1 = 'Hello';
|
|
|
|
const chunk2 = ' World';
|
|
|
|
const chunk3 = '\n\nEOF';
|
2017-11-21 19:22:17 +00:00
|
|
|
|
2019-03-13 00:04:16 +00:00
|
|
|
log.startStreaming();
|
|
|
|
assert.equal(log.get('output'), '', 'No output yet');
|
2017-11-21 19:22:17 +00:00
|
|
|
|
2019-03-13 00:04:16 +00:00
|
|
|
log.get('logStreamer').step(chunk1);
|
|
|
|
assert.equal(log.get('output'), chunk1, 'First chunk written');
|
2017-11-21 19:22:17 +00:00
|
|
|
|
2019-03-13 00:04:16 +00:00
|
|
|
log.get('logStreamer').step(chunk2);
|
|
|
|
assert.equal(log.get('output'), chunk1 + chunk2, 'Second chunk written');
|
2017-11-21 19:22:17 +00:00
|
|
|
|
2019-03-13 00:04:16 +00:00
|
|
|
log.get('logStreamer').step(chunk3);
|
2021-12-28 16:08:12 +00:00
|
|
|
assert.equal(
|
|
|
|
log.get('output'),
|
|
|
|
chunk1 + chunk2 + chunk3,
|
|
|
|
'Third chunk written'
|
|
|
|
);
|
2019-03-13 00:04:16 +00:00
|
|
|
});
|
2017-11-21 19:22:17 +00:00
|
|
|
|
2021-12-28 14:45:20 +00:00
|
|
|
test('stop stops the log streamer', async function (assert) {
|
2019-03-13 00:04:16 +00:00
|
|
|
const log = Log.create(makeMocks(''));
|
2017-11-21 19:22:17 +00:00
|
|
|
|
2019-03-13 00:04:16 +00:00
|
|
|
log.stop();
|
|
|
|
assert.ok(stopSpy.calledOnce, 'Streaming stopped');
|
|
|
|
});
|
2017-11-21 19:22:17 +00:00
|
|
|
});
|