Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
microsoft
GitHub Repository: microsoft/vscode
Path: blob/main/src/vs/workbench/contrib/output/test/browser/outputChannelModel.test.ts
4780 views
1
/*---------------------------------------------------------------------------------------------
2
* Copyright (c) Microsoft Corporation. All rights reserved.
3
* Licensed under the MIT License. See License.txt in the project root for license information.
4
*--------------------------------------------------------------------------------------------*/
5
6
import * as assert from 'assert';
7
import { parseLogEntryAt } from '../../common/outputChannelModel.js';
8
import { TextModel } from '../../../../../editor/common/model/textModel.js';
9
import { ensureNoDisposablesAreLeakedInTestSuite } from '../../../../../base/test/common/utils.js';
10
import { LogLevel } from '../../../../../platform/log/common/log.js';
11
import { workbenchInstantiationService } from '../../../../test/browser/workbenchTestServices.js';
12
import { TestInstantiationService } from '../../../../../platform/instantiation/test/common/instantiationServiceMock.js';
13
14
suite('Logs Parsing', () => {
15
16
const disposables = ensureNoDisposablesAreLeakedInTestSuite();
17
18
let instantiationService: TestInstantiationService;
19
20
setup(() => {
21
instantiationService = disposables.add(workbenchInstantiationService({}, disposables));
22
});
23
24
test('should parse log entry with all components', () => {
25
const text = '2023-10-15 14:30:45.123 [info] [Git] Initializing repository';
26
const model = createModel(text);
27
const entry = parseLogEntryAt(model, 1);
28
29
assert.strictEqual(entry?.timestamp, new Date('2023-10-15 14:30:45.123').getTime());
30
assert.strictEqual(entry?.logLevel, LogLevel.Info);
31
assert.strictEqual(entry?.category, 'Git');
32
assert.strictEqual(model.getValueInRange(entry?.range), text);
33
});
34
35
test('should parse multi-line log entry', () => {
36
const text = [
37
'2023-10-15 14:30:45.123 [error] [Extension] Failed with error:',
38
'Error: Could not load extension',
39
' at Object.load (/path/to/file:10:5)'
40
].join('\n');
41
const model = createModel(text);
42
const entry = parseLogEntryAt(model, 1);
43
44
assert.strictEqual(entry?.timestamp, new Date('2023-10-15 14:30:45.123').getTime());
45
assert.strictEqual(entry?.logLevel, LogLevel.Error);
46
assert.strictEqual(entry?.category, 'Extension');
47
assert.strictEqual(model.getValueInRange(entry?.range), text);
48
});
49
50
test('should parse log entry without category', () => {
51
const text = '2023-10-15 14:30:45.123 [warning] System is running low on memory';
52
const model = createModel(text);
53
const entry = parseLogEntryAt(model, 1);
54
55
assert.strictEqual(entry?.timestamp, new Date('2023-10-15 14:30:45.123').getTime());
56
assert.strictEqual(entry?.logLevel, LogLevel.Warning);
57
assert.strictEqual(entry?.category, undefined);
58
assert.strictEqual(model.getValueInRange(entry?.range), text);
59
});
60
61
test('should return null for invalid log entry', () => {
62
const model = createModel('Not a valid log entry');
63
const entry = parseLogEntryAt(model, 1);
64
65
assert.strictEqual(entry, null);
66
});
67
68
test('should parse all supported log levels', () => {
69
const levels = {
70
info: LogLevel.Info,
71
trace: LogLevel.Trace,
72
debug: LogLevel.Debug,
73
warning: LogLevel.Warning,
74
error: LogLevel.Error
75
};
76
77
for (const [levelText, expectedLevel] of Object.entries(levels)) {
78
const model = createModel(`2023-10-15 14:30:45.123 [${levelText}] Test message`);
79
const entry = parseLogEntryAt(model, 1);
80
assert.strictEqual(entry?.logLevel, expectedLevel, `Failed for log level: ${levelText}`);
81
}
82
});
83
84
test('should parse timestamp correctly', () => {
85
const timestamps = [
86
'2023-01-01 00:00:00.000',
87
'2023-12-31 23:59:59.999',
88
'2023-06-15 12:30:45.500'
89
];
90
91
for (const timestamp of timestamps) {
92
const model = createModel(`${timestamp} [info] Test message`);
93
const entry = parseLogEntryAt(model, 1);
94
assert.strictEqual(entry?.timestamp, new Date(timestamp).getTime(), `Failed for timestamp: ${timestamp}`);
95
}
96
});
97
98
test('should handle last line of file', () => {
99
const model = createModel([
100
'2023-10-15 14:30:45.123 [info] First message',
101
'2023-10-15 14:30:45.124 [info] Last message',
102
''
103
].join('\n'));
104
105
let actual = parseLogEntryAt(model, 1);
106
assert.strictEqual(actual?.timestamp, new Date('2023-10-15 14:30:45.123').getTime());
107
assert.strictEqual(actual?.logLevel, LogLevel.Info);
108
assert.strictEqual(actual?.category, undefined);
109
assert.strictEqual(model.getValueInRange(actual?.range), '2023-10-15 14:30:45.123 [info] First message');
110
111
actual = parseLogEntryAt(model, 2);
112
assert.strictEqual(actual?.timestamp, new Date('2023-10-15 14:30:45.124').getTime());
113
assert.strictEqual(actual?.logLevel, LogLevel.Info);
114
assert.strictEqual(actual?.category, undefined);
115
assert.strictEqual(model.getValueInRange(actual?.range), '2023-10-15 14:30:45.124 [info] Last message');
116
117
actual = parseLogEntryAt(model, 3);
118
assert.strictEqual(actual, null);
119
});
120
121
test('should parse multi-line log entry with empty lines', () => {
122
const text = [
123
'2025-01-27 09:53:00.450 [info] Found with version <20.18.1>',
124
'Now using node v20.18.1 (npm v10.8.2)',
125
'',
126
'> husky - npm run -s precommit',
127
'> husky - node v20.18.1',
128
'',
129
'Reading git index versions...'
130
].join('\n');
131
const model = createModel(text);
132
const entry = parseLogEntryAt(model, 1);
133
134
assert.strictEqual(entry?.timestamp, new Date('2025-01-27 09:53:00.450').getTime());
135
assert.strictEqual(entry?.logLevel, LogLevel.Info);
136
assert.strictEqual(entry?.category, undefined);
137
assert.strictEqual(model.getValueInRange(entry?.range), text);
138
139
});
140
141
function createModel(content: string): TextModel {
142
return disposables.add(instantiationService.createInstance(TextModel, content, 'log', TextModel.DEFAULT_CREATION_OPTIONS, null));
143
}
144
});
145
146