UNPKG

5.64 kBJavaScriptView Raw
1//
2// Copyright (c) Microsoft and contributors. All rights reserved.
3//
4// Licensed under the Apache License, Version 2.0 (the "License");
5// you may not use this file except in compliance with the License.
6// You may obtain a copy of the License at
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12//
13// See the License for the specific language governing permissions and
14// limitations under the License.
15//
16
17'use strict';
18
19var Stream = require('stream');
20var fs = require('fs');
21var os = require('os');
22
23var EOL = '\n';
24var debugStream = null;
25var deleteInput = false;
26var source;
27
28ifFlag('-rm', function () {
29 deleteInput = true;
30});
31
32ifFlag('-debug', function () {
33 debugStream = fs.createWriteStream('filter-debug.log', {flags: 'w'});
34});
35
36if (process.argv.length > 2) {
37 source = fs.createReadStream(process.argv[2], { flags: 'r' });
38 if (deleteInput) {
39 source.on('close', function () {
40 fs.unlinkSync(process.argv[2]);
41 });
42 }
43} else {
44 source = process.stdin;
45}
46
47function ifFlag(flag, ifPresentCallback) {
48 var flagIndex = process.argv.indexOf(flag);
49 if (flagIndex !== -1) {
50 process.argv.splice(flagIndex, 1);
51 ifPresentCallback();
52 }
53}
54
55//
56// Through stream that breaks up input into individual
57// lines of text and writes the lines individually.
58// Makes it easier for downstream filters to operate on
59// a per line basis.
60//
61
62function lineFilter() {
63 var stream = new Stream();
64 stream.readable = true;
65 stream.writable = true;
66
67 var pendingLines = [];
68 var partialLine = null;
69 var done = false;
70
71 stream.write = write;
72 stream.end = end;
73
74 return stream;
75
76 function sendNextLine() {
77 if (pendingLines.length > 0) {
78 var lineToSend = pendingLines.shift();
79 stream.emit('data', lineToSend + EOL);
80 if(debugStream) {
81 debugStream.write('line filter sending line ' + lineToSend + EOL);
82 }
83 process.nextTick(sendNextLine);
84 } else if (done) {
85 if (partialLine !== null) {
86 stream.emit('data', partialLine + EOL);
87 }
88 stream.emit('end');
89 stream.emit('close');
90 }
91 }
92
93 function splitBufferIntoLines(buffer, encoding, completionCallback) {
94 if (typeof buffer !== 'string') {
95 buffer = buffer.toString(encoding);
96 }
97
98 var lines = buffer.split(EOL);
99 var lastLine = lines[lines.length - 1];
100 if (buffer.slice(-(EOL.length)) !== EOL) {
101 lines.pop();
102 } else {
103 lastLine = null;
104 }
105
106 completionCallback(lines, lastLine);
107 }
108
109 function write(buffer, encoding) {
110 var shouldSend = (pendingLines.length === 0);
111
112 splitBufferIntoLines(buffer, encoding, function (fullLines, leftover) {
113 if (fullLines.length > 0 && partialLine !== null) {
114 fullLines[0] = partialLine + fullLines[0];
115 partialLine = null;
116 }
117
118 if (leftover !== null) {
119 partialLine = (partialLine || '') + leftover;
120 }
121 pendingLines = pendingLines.concat(fullLines);
122 });
123
124 if (shouldSend) {
125 process.nextTick(sendNextLine);
126 }
127 }
128
129 function end(buffer, encoding) {
130 if (buffer) {
131 this.write(buffer, encoding);
132 }
133 done = true;
134 }
135}
136
137//
138// A simple transformation stream that reads in
139// test results and filters out extraneous lines -
140// everything before the first XML <testsuite> line.
141// Assumes that the LineFilter above is included
142// so treats every buffer as a single line.
143//
144
145function testResultFilter() {
146 var stream = new Stream();
147 stream.readable = true;
148 stream.writable = true;
149
150 stream.write = write;
151 stream.end = end;
152
153 var xmlFound = false;
154
155 return stream;
156
157 function write(buffer, encoding) {
158 if (typeof buffer !== 'string') {
159 buffer = buffer.toString(encoding);
160 }
161 checkIfXmlFound(buffer);
162 if (xmlFound) {
163 if (debugStream) {
164 debugStream.write('received line ' + buffer + ' and it\'s in the xml\n');
165 }
166 var self = this;
167 process.nextTick(function () { self.emit('data', buffer); });
168 } else if (debugStream) {
169 debugStream.write('received line ' + buffer + ' and it\'s not in the xml\n');
170 }
171 }
172
173 function end(buffer, encoding) {
174 if (buffer) {
175 if (debugStream) {
176 debugStream.write('>>>>> end received with buffer, writing');
177 }
178 this.write(buffer, encoding);
179 }
180 process.nextTick(function () {
181 stream.emit('end');
182 stream.emit('close');
183 });
184 }
185
186 function checkIfXmlFound(line) {
187 if (xmlFound) { return; }
188 var openTag = '<testsuite';
189 if (line.slice(0, openTag.length) === openTag) {
190 xmlFound = true;
191 }
192 }
193}
194
195//
196// Temporary workaround to tweak output report so that
197// Jenkins will render it.
198//
199function changeSkippedFilter() {
200 var stream = new Stream();
201 stream.readable = true;
202 stream.writable = true;
203
204 stream.write = write;
205 stream.end = end;
206 return stream;
207
208 function write(buffer, encoding) {
209 if (typeof buffer !== 'string') {
210 buffer = buffer.toString(encoding);
211 }
212
213 var openTag = '<testsuite';
214 if(buffer.slice(0, openTag.length) === openTag) {
215 buffer = buffer.replace(' skip="', ' skipped="');
216 }
217 this.emit('data', buffer);
218 }
219
220 function end(buffer, encoding) {
221 if (buffer) {
222 this.write(buffer, encoding);
223 }
224 this.emit('end');
225 this.emit('close');
226 }
227}
228
229source.resume();
230source.pipe(lineFilter()).pipe(testResultFilter()).pipe(changeSkippedFilter()).pipe(process.stdout);