blob: 9138d8ebe843ea357c3e45e81cd8197a46db5660 [file] [log] [blame] [raw]
RabsRincon6ef87b52018-02-27 14:58:21 +01001// Copyright (c) 2017, Matt Godbolt
Matt Godbolta272ea92017-12-10 16:52:53 -06002// All rights reserved.
3//
4// Redistribution and use in source and binary forms, with or without
5// modification, are permitted provided that the following conditions are met:
6//
7// * Redistributions of source code must retain the above copyright notice,
8// this list of conditions and the following disclaimer.
9// * Redistributions in binary form must reproduce the above copyright
10// notice, this list of conditions and the following disclaimer in the
11// documentation and/or other materials provided with the distribution.
12//
13// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
14// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
17// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
23// POSSIBILITY OF SUCH DAMAGE.
24
25const chai = require('chai'),
RabsRincone5677832018-07-02 08:57:21 +020026 utils = require('../lib/utils'),
RabsRinconbdc447f2018-08-20 11:10:23 +020027 logger = require('../lib/logger').logger,
28 fs = require('fs-extra');
Matt Godbolta272ea92017-12-10 16:52:53 -060029
30chai.should();
31
32describe('Splits lines', () => {
33 it('handles empty input', () => {
34 utils.splitLines('').should.deep.equals([]);
35 });
36 it('handles a single line with no newline', () => {
37 utils.splitLines('A line').should.deep.equals(['A line']);
38 });
39 it('handles a single line with a newline', () => {
40 utils.splitLines('A line\n').should.deep.equals(['A line']);
41 });
42 it('handles multiple lines', () => {
43 utils.splitLines('A line\nAnother line\n').should.deep.equals(['A line', 'Another line']);
44 });
45 it('handles multiple lines ending on a non-newline', () => {
46 utils.splitLines('A line\nAnother line\nLast line').should.deep.equals(
47 ['A line', 'Another line', 'Last line']);
48 });
49 it('handles empty lines', () => {
50 utils.splitLines('A line\n\nA line after an empty').should.deep.equals(
51 ['A line', '', 'A line after an empty']);
52 });
53 it('handles a single empty line', () => {
54 utils.splitLines('\n').should.deep.equals(['']);
55 });
56 it('handles multiple empty lines', () => {
57 utils.splitLines('\n\n\n').should.deep.equals(['', '', '']);
58 });
59 it('handles \\r\\n lines', () => {
60 utils.splitLines('Some\r\nLines\r\n').should.deep.equals(['Some', 'Lines']);
61 });
62});
63
64describe('Expands tabs', () => {
65 it('leaves non-tabs alone', () => {
66 utils.expandTabs('This has no tabs at all').should.equals('This has no tabs at all');
67 });
68 it('at beginning of line', () => {
69 utils.expandTabs('\tOne tab').should.equals(' One tab');
70 utils.expandTabs('\t\tTwo tabs').should.equals(' Two tabs');
71 });
72 it('mid-line', () => {
73 utils.expandTabs('0\t1234567A').should.equals('0 1234567A');
74 utils.expandTabs('01\t234567A').should.equals('01 234567A');
75 utils.expandTabs('012\t34567A').should.equals('012 34567A');
76 utils.expandTabs('0123\t4567A').should.equals('0123 4567A');
77 utils.expandTabs('01234\t567A').should.equals('01234 567A');
78 utils.expandTabs('012345\t67A').should.equals('012345 67A');
79 utils.expandTabs('0123456\t7A').should.equals('0123456 7A');
80 utils.expandTabs('01234567\tA').should.equals('01234567 A');
81 });
82});
83
84describe('Parses compiler output', () => {
85 it('handles simple cases', () => {
86 utils.parseOutput('Line one\nLine two', 'bob.cpp').should.deep.equals([
87 {text: 'Line one'},
88 {text: 'Line two'}
89 ]);
90 utils.parseOutput('Line one\nbob.cpp:1 Line two', 'bob.cpp').should.deep.equals([
91 {text: 'Line one'},
92 {
93 tag: {column: 0, line: 1, text: "Line two"},
94 text: '<source>:1 Line two'
95 }
96 ]);
97 utils.parseOutput('Line one\nbob.cpp:1:5: Line two', 'bob.cpp').should.deep.equals([
98 {text: 'Line one'},
99 {
100 tag: {column: 5, line: 1, text: "Line two"},
101 text: '<source>:1:5: Line two'
102 }
103 ]);
104 });
105 it('handles windows output', () => {
106 utils.parseOutput('bob.cpp(1) Oh noes', 'bob.cpp').should.deep.equals([
107 {
108 tag: {column: 0, line: 1, text: 'Oh noes'},
109 text: '<source>(1) Oh noes'
110 }
111 ]);
112 });
113 it('replaces all references to input source', () => {
114 utils.parseOutput('bob.cpp:1 error in bob.cpp', 'bob.cpp').should.deep.equals([
115 {
116 tag: {column: 0, line: 1, text: 'error in <source>'},
117 text: '<source>:1 error in <source>'
118 }
119 ]);
120 });
Matt Godbolt3baf2a22017-12-19 08:00:34 -0600121 it('treats <stdin> as if it were the compiler source', () => {
122 utils.parseOutput('<stdin>:120:25: error: variable or field \'transform_data\' declared void', 'bob.cpp')
123 .should.deep.equals([
124 {
125 tag: {
126 column: 25,
127 line: 120,
128 text: 'error: variable or field \'transform_data\' declared void'
129 },
130 text: '<source>:120:25: error: variable or field \'transform_data\' declared void'
131 }
132 ]);
133 });
Matt Godbolta272ea92017-12-10 16:52:53 -0600134});
135
Partouff0f74522018-03-15 17:46:24 +0100136describe('Pascal compiler output', () => {
137 it('recognize fpc identifier not found error', () => {
138 utils.parseOutput('output.pas(13,23) Error: Identifier not found "adsadasd"', 'output.pas').should.deep.equals([
139 {
140 tag: {
141 column: 23,
142 line: 13,
143 text: 'Error: Identifier not found "adsadasd"'
144 },
145 text: '<source>(13,23) Error: Identifier not found "adsadasd"'
146 }
147 ]);
148 });
149
150 it('recognize fpc exiting error', () => {
151 utils.parseOutput('output.pas(17) Fatal: There were 1 errors compiling module, stopping', 'output.pas').should.deep.equals([
152 {
153 tag: {
154 column: 0,
155 line: 17,
156 text: 'Fatal: There were 1 errors compiling module, stopping'
157 },
158 text: '<source>(17) Fatal: There were 1 errors compiling module, stopping'
159 }
160 ]);
161 });
Partoufa58689b2018-03-15 18:03:21 +0100162
163 it('removes the temp path', () => {
164 utils.parseOutput('Compiling /tmp/path/prog.dpr\noutput.pas(17) Fatal: There were 1 errors compiling module, stopping', 'output.pas', '/tmp/path/').should.deep.equals([
165 {
166 text: 'Compiling prog.dpr'
167 },
168 {
169 tag: {
170 column: 0,
171 line: 17,
172 text: 'Fatal: There were 1 errors compiling module, stopping'
173 },
174 text: '<source>(17) Fatal: There were 1 errors compiling module, stopping'
175 }
176 ]);
177 });
Partouff0f74522018-03-15 17:46:24 +0100178});
179
Matt Godbolta272ea92017-12-10 16:52:53 -0600180describe('Pads right', () => {
181 it('works', () => {
182 utils.padRight('abcd', 8).should.equal('abcd ');
183 utils.padRight('a', 8).should.equal('a ');
184 utils.padRight('', 8).should.equal(' ');
185 utils.padRight('abcd', 4).should.equal('abcd');
186 utils.padRight('abcd', 2).should.equal('abcd');
187 });
188});
RabsRincon12026f62018-06-28 02:23:38 +0200189
Kārlis Seņko40f6e0e2019-01-08 00:41:07 +0200190describe('Trim right', () => {
191 it('works', () => {
192 utils.trimRight(' ').should.equal('');
193 utils.trimRight('').should.equal('');
194 utils.trimRight(' ab ').should.equal(' ab');
195 utils.trimRight(' a b ').should.equal(' a b');
196 utils.trimRight('a ').should.equal('a');
197 });
198});
199
RabsRincon12026f62018-06-28 02:23:38 +0200200describe('Anonymizes all kind of IPs', () => {
201 it('Ignores localhost', () => {
202 utils.anonymizeIp('localhost').should.equal('localhost');
203 utils.anonymizeIp('localhost:42').should.equal('localhost:42');
204 });
205 it('Removes last octet from IPv4 addresses', () => {
206 utils.anonymizeIp('127.0.0.0').should.equal('127.0.0.0');
207 utils.anonymizeIp('127.0.0.10').should.equal('127.0.0.0');
208 utils.anonymizeIp('127.0.0.255').should.equal('127.0.0.0');
209 });
RabsRincondd2ab6d2018-07-04 17:54:23 +0200210 it('Removes last 3 hextets from IPv6 addresses', () => {
RabsRincon12026f62018-06-28 02:23:38 +0200211 // Not necessarily valid addresses, we're interested in the format
212 utils.anonymizeIp('ffff:aaaa:dead:beef').should.equal('ffff:0:0:0');
213 utils.anonymizeIp('bad:c0de::').should.equal('bad:0:0:0');
214 utils.anonymizeIp(':1d7e::c0fe').should.equal(':0:0:0');
215 });
216});
RabsRincone5677832018-07-02 08:57:21 +0200217
218describe('Logger functionality', () => {
219 it('has info stream with a write function', () => {
220 logger.stream.write.should.a("function");
221 });
RabsRincon1e053fd2018-07-04 18:52:13 +0200222 it('has warning stream with a write function', () => {
RabsRincone5677832018-07-02 08:57:21 +0200223 logger.warnStream.write.should.a("function");
224 });
RabsRincon1e053fd2018-07-04 18:52:13 +0200225 it('has error stream with a write function', () => {
RabsRincone5677832018-07-02 08:57:21 +0200226 logger.errStream.write.should.a("function");
227 });
228});
RabsRincon1e053fd2018-07-04 18:52:13 +0200229
230describe('Hash interface', () => {
231 it('correctly hashes strings', () => {
232 const version = 'Compiler Explorer Tests Version 0';
233 utils.getHash('cream cheese', version).should.equal('cfff2d1f7a213e314a67cce8399160ae884f794a3ee9d4a01cd37a8c22c67d94');
234 utils.getHash('large eggs', version).should.equal('9144dec50b8df5bc5cc24ba008823cafd6616faf2f268af84daf49ac1d24feb0');
235 utils.getHash('sugar', version).should.equal('afa3c89d0f6a61de6805314c9bd7c52d020425a3a3c7bbdfa7c0daec594e5ef1');
236 });
237 it('correctly hashes objects', () => {
Matt Godbolt2e7fc5f2019-03-21 21:28:43 -0500238 utils.getHash({
239 toppings: [
240 {name: 'raspberries', optional: false},
241 {name: 'ground cinnamon', optional: true}
242 ]
243 }).should.equal('e205d63abd5db363086621fdc62c4c23a51b733bac5855985a8b56642d570491');
RabsRincon1e053fd2018-07-04 18:52:13 +0200244 });
245});
RabsRinconbdc447f2018-08-20 11:10:23 +0200246
247describe('GoldenLayout utils', () => {
248 it('finds every editor & compiler', () => {
249 fs.readJson('test/example-states/default-state.json')
250 .then(state => {
251 const contents = utils.glGetMainContents(state.content);
252 contents.should.deep.equal({
253 editors: [
254 {source: 'Editor 1', language: 'c++'},
255 {source: 'Editor 2', language: 'c++'},
256 {source: 'Editor 3', language: 'c++'},
257 {source: 'Editor 4', language: 'c++'}
258 ],
259 compilers: [
260 {compiler: 'clang_trunk'},
261 {compiler: 'gsnapshot'},
262 {compiler: 'clang_trunk'},
263 {compiler: 'gsnapshot'},
264 {compiler: 'rv32clang'}
265 ]
Matt Godbolt2e7fc5f2019-03-21 21:28:43 -0500266 });
RabsRinconbdc447f2018-08-20 11:10:23 +0200267 });
Matt Godbolt2e7fc5f2019-03-21 21:28:43 -0500268 });
RabsRinconbdc447f2018-08-20 11:10:23 +0200269});
Andre Meyering061dcd32018-07-07 14:57:56 +0200270
Matt Godbolt2e7fc5f2019-03-21 21:28:43 -0500271describe('squashes horizontal whitespace', () => {
Andre Meyering061dcd32018-07-07 14:57:56 +0200272 it('handles empty input', () => {
Matt Godbolt2e7fc5f2019-03-21 21:28:43 -0500273 utils.squashHorizontalWhitespace('').should.equals('');
274 utils.squashHorizontalWhitespace(' ').should.equals('');
275 utils.squashHorizontalWhitespace(' ').should.equals('');
Andre Meyering061dcd32018-07-07 14:57:56 +0200276 });
277 it('handles leading spaces', () => {
Matt Godbolt2e7fc5f2019-03-21 21:28:43 -0500278 utils.squashHorizontalWhitespace(' abc').should.equals(' abc');
279 utils.squashHorizontalWhitespace(' abc').should.equals(' abc');
280 utils.squashHorizontalWhitespace(' abc').should.equals(' abc');
Andre Meyering061dcd32018-07-07 14:57:56 +0200281 });
282 it('handles interline spaces', () => {
Matt Godbolt2e7fc5f2019-03-21 21:28:43 -0500283 utils.squashHorizontalWhitespace('abc abc').should.equals('abc abc');
284 utils.squashHorizontalWhitespace('abc abc').should.equals('abc abc');
285 utils.squashHorizontalWhitespace('abc abc').should.equals('abc abc');
Andre Meyering061dcd32018-07-07 14:57:56 +0200286 });
287 it('handles leading and interline spaces', () => {
Matt Godbolt2e7fc5f2019-03-21 21:28:43 -0500288 utils.squashHorizontalWhitespace(' abc abc').should.equals(' abc abc');
289 utils.squashHorizontalWhitespace(' abc abc').should.equals(' abc abc');
290 utils.squashHorizontalWhitespace(' abc abc').should.equals(' abc abc');
291 utils.squashHorizontalWhitespace(' abc abc').should.equals(' abc abc');
Andre Meyering061dcd32018-07-07 14:57:56 +0200292 });
293});