mirror of
https://github.com/meteor/meteor.git
synced 2026-05-02 03:01:46 -04:00
96 lines
2.4 KiB
JavaScript
96 lines
2.4 KiB
JavaScript
// Maintains a line-by-line merged log of multiple output channels
|
|
// (eg, stdout and stderr).
|
|
import TestFailure from './test-failure.js';
|
|
|
|
const hasOwn = Object.prototype.hasOwnProperty;
|
|
|
|
export default class OutputLog {
|
|
constructor(run) {
|
|
// each entry is an object withgit p keys 'channel', 'text', and if it is
|
|
// the last entry and there was no newline terminator, 'bare'
|
|
this.lines = [];
|
|
|
|
// map from a channel name to an object representing a partially
|
|
// read line of text on that channel. That object has keys 'text'
|
|
// (text read), 'offset' (cursor position, equal to text.length
|
|
// unless a '\r' has been read).
|
|
this.buffers = {};
|
|
|
|
// a Run, exclusively for inclusion in exceptions
|
|
this.run = run;
|
|
}
|
|
|
|
write(channel, text) {
|
|
if (!hasOwn.call(this.buffers, 'channel')) {
|
|
this.buffers[channel] = { text: '', offset: 0 };
|
|
}
|
|
const b = this.buffers[channel];
|
|
|
|
while (text.length) {
|
|
const m = text.match(/^[^\n\r]+/);
|
|
if (m) {
|
|
// A run of non-control characters.
|
|
b.text = b.text.substr(0, b.offset) +
|
|
m[0] + b.text.substr(b.offset + m[0].length);
|
|
b.offset += m[0].length;
|
|
text = text.substr(m[0].length);
|
|
continue;
|
|
}
|
|
|
|
if (text[0] === '\r') {
|
|
b.offset = 0;
|
|
text = text.substr(1);
|
|
continue;
|
|
}
|
|
|
|
if (text[0] === '\n') {
|
|
this.lines.push({ channel, text: b.text });
|
|
b.text = '';
|
|
b.offset = 0;
|
|
text = text.substr(1);
|
|
continue;
|
|
}
|
|
|
|
throw new Error("conditions should have been exhaustive?");
|
|
}
|
|
}
|
|
|
|
end() {
|
|
Object.keys(this.buffers).forEach((channel) => {
|
|
if (this.buffers[channel].text.length) {
|
|
this.lines.push({
|
|
channel,
|
|
text: this.buffers[channel].text,
|
|
bare: true,
|
|
});
|
|
this.buffers[channel] = { text: '', offset: 0};
|
|
}
|
|
});
|
|
}
|
|
|
|
forbid(pattern, channel) {
|
|
const failure = new TestFailure('forbidden-string-present', {
|
|
run: this.run,
|
|
});
|
|
|
|
this.lines.forEach((line) => {
|
|
if (channel && channel !== line.channel) {
|
|
return;
|
|
}
|
|
|
|
const match = (pattern instanceof RegExp) ?
|
|
(line.text.match(pattern)) : (line.text.indexOf(pattern) !== -1);
|
|
if (match) {
|
|
throw failure;
|
|
}
|
|
});
|
|
}
|
|
|
|
get() {
|
|
return this.lines;
|
|
}
|
|
}
|
|
|
|
import { markThrowingMethods } from "./test-utils.js";
|
|
markThrowingMethods(OutputLog.prototype);
|