BodyProcessor.java

1
package com.renomad.minum.web;
2
3
import com.renomad.minum.logging.ILogger;
4
import com.renomad.minum.security.ForbiddenUseException;
5
import com.renomad.minum.state.Constants;
6
import com.renomad.minum.state.Context;
7
import com.renomad.minum.utils.StringUtils;
8
9
import java.io.ByteArrayOutputStream;
10
import java.io.IOException;
11
import java.io.InputStream;
12
import java.nio.charset.StandardCharsets;
13
import java.util.*;
14
import java.util.regex.Matcher;
15
import java.util.regex.Pattern;
16
17
/**
18
 * This code is responsible for extracting the {@link Body} from
19
 * an HTTP request.
20
 */
21
final class BodyProcessor implements IBodyProcessor {
22
23
    private final ILogger logger;
24
    private final IInputStreamUtils inputStreamUtils;
25
    private final Constants constants;
26
27
    BodyProcessor(Context context) {
28
        this.constants = context.getConstants();
29
        this.logger = context.getLogger();
30
        this.inputStreamUtils = new InputStreamUtils(constants.maxReadLineSizeBytes);
31
    }
32
33
    @Override
34
    public Body extractData(InputStream is, Headers h) {
35
        final var contentType = h.contentType();
36
37 2 1. extractData : negated conditional → KILLED
2. extractData : changed conditional boundary → KILLED
        if (h.contentLength() >= 0) {
38 2 1. extractData : negated conditional → KILLED
2. extractData : changed conditional boundary → KILLED
            if (h.contentLength() >= constants.maxReadSizeBytes) {
39
                throw new ForbiddenUseException("It is disallowed to process a body with a length more than " + constants.maxReadSizeBytes + " bytes");
40
            }
41
        } else {
42
            // we don't process chunked transfer encodings.  just bail.
43
            List<String> transferEncodingHeaders = h.valueByKey("transfer-encoding");
44 1 1. extractData : negated conditional → KILLED
            if (List.of("chunked").equals(transferEncodingHeaders)) {
45
                logger.logDebug(() -> "client sent chunked transfer-encoding.  Minum does not automatically read bodies of this type.");
46
            }
47 1 1. extractData : replaced return value with null for com/renomad/minum/web/BodyProcessor::extractData → KILLED
            return Body.EMPTY;
48
        }
49
50 1 1. extractData : replaced return value with null for com/renomad/minum/web/BodyProcessor::extractData → KILLED
        return extractBodyFromInputStream(h.contentLength(), contentType, is);
51
    }
52
53
    /**
54
     * Handles the parsing of the body data for either form-urlencoded or
55
     * multipart/form-data
56
     *
57
     * @param contentType a mime value which must be either application/x-www-form-urlencoded
58
     *                    or multipart/form-data.  Anything else will cause a new Body to
59
     *                    be created with the body bytes, unparsed.  There are a number of
60
     *                    cases where this makes sense - if the user is sending us plain text,
61
     *                    html, json, or css, we want to simply accept the data and not try to parse it.
62
     */
63
    Body extractBodyFromInputStream(int contentLength, String contentType, InputStream is) {
64
        // if the body is zero bytes long, just return
65 1 1. extractBodyFromInputStream : negated conditional → KILLED
        if (contentLength == 0) {
66
            logger.logDebug(() -> "the length of the body was 0, returning an empty Body");
67 1 1. extractBodyFromInputStream : replaced return value with null for com/renomad/minum/web/BodyProcessor::extractBodyFromInputStream → KILLED
            return Body.EMPTY;
68
        }
69
70 1 1. extractBodyFromInputStream : negated conditional → KILLED
        if (contentType.contains("application/x-www-form-urlencoded")) {
71 1 1. extractBodyFromInputStream : replaced return value with null for com/renomad/minum/web/BodyProcessor::extractBodyFromInputStream → KILLED
            return parseUrlEncodedForm(is, contentLength);
72 1 1. extractBodyFromInputStream : negated conditional → KILLED
        } else if (contentType.contains("multipart/form-data")) {
73
            String boundaryValue = determineBoundaryValue(contentType);
74 1 1. extractBodyFromInputStream : replaced return value with null for com/renomad/minum/web/BodyProcessor::extractBodyFromInputStream → KILLED
            return parseMultipartForm(contentLength, boundaryValue, is);
75
        } else {
76
            logger.logDebug(() -> "did not recognize a key-value pattern content-type, returning the raw bytes for the body.  Content-Type was: " + contentType);
77
            // we can return the whole byte array here because we never read from it
78 1 1. extractBodyFromInputStream : replaced return value with null for com/renomad/minum/web/BodyProcessor::extractBodyFromInputStream → KILLED
            return new Body(Map.of(), inputStreamUtils.read(contentLength, is), List.of(), BodyType.UNRECOGNIZED);
79
        }
80
    }
81
82
    /**
83
     * Parse multipart/form protocol.
84
     * @param contentLength the length of incoming data, found in the "content-length" header
85
     * @param boundaryValue the randomly-generated boundary value between the partitions.  Research
86
     *                      multipart/form data protocol for further information.
87
     * @param inputStream A stream of bytes coming from the socket.
88
     */
89
    private Body parseMultipartForm(int contentLength, String boundaryValue, InputStream inputStream) {
90
91 1 1. parseMultipartForm : negated conditional → KILLED
        if (boundaryValue.isBlank()) {
92
            logger.logDebug(() -> "The boundary value was blank for the multipart input. Returning an empty map");
93 1 1. parseMultipartForm : replaced return value with null for com/renomad/minum/web/BodyProcessor::parseMultipartForm → KILLED
            return new Body(Map.of(), new byte[0], List.of(), BodyType.UNRECOGNIZED);
94
        }
95
96
        List<Partition> partitions = new ArrayList<>();
97
98
        try {
99
            int countOfPartitions = 0;
100
            for (StreamingMultipartPartition p : getMultiPartIterable(inputStream, boundaryValue, contentLength)) {
101 1 1. parseMultipartForm : Changed increment from 1 to -1 → KILLED
                countOfPartitions += 1;
102 2 1. parseMultipartForm : negated conditional → KILLED
2. parseMultipartForm : changed conditional boundary → KILLED
                if (countOfPartitions >= MAX_BODY_KEYS_URL_ENCODED) {
103
                    throw new WebServerException("Error: body had excessive number of partitions (" + countOfPartitions + ").  Maximum allowed: " + MAX_BODY_KEYS_URL_ENCODED);
104
                }
105
                partitions.add(new Partition(p.getHeaders(), p.readAllBytes(), p.getContentDisposition()));
106
            }
107
108
109
        } catch (Exception ex) {
110
            logger.logDebug(() -> "Unable to parse this body. returning what we have so far.  Exception message: " + ex.getMessage());
111
            // we have to return nothing for the raw bytes, because at this point we are halfway through
112
            // reading the inputstream and don't want to return broken data
113 1 1. parseMultipartForm : replaced return value with null for com/renomad/minum/web/BodyProcessor::parseMultipartForm → KILLED
            return new Body(Map.of(), new byte[0], partitions, BodyType.MULTIPART);
114
        }
115 1 1. parseMultipartForm : negated conditional → KILLED
        if (partitions.isEmpty()) {
116 1 1. parseMultipartForm : replaced return value with null for com/renomad/minum/web/BodyProcessor::parseMultipartForm → KILLED
            return new Body(Map.of(), new byte[0], List.of(), BodyType.UNRECOGNIZED);
117
        } else {
118 1 1. parseMultipartForm : replaced return value with null for com/renomad/minum/web/BodyProcessor::parseMultipartForm → KILLED
            return new Body(Map.of(), new byte[0], partitions, BodyType.MULTIPART);
119
        }
120
    }
121
122
    /**
123
     * Given the "content-type" header, determine the boundary value.  A typical
124
     * multipart content-type header might look like this: <pre>Content-Type: multipart/form-data; boundary=i_am_a_boundary</pre>
125
     */
126
    private static String determineBoundaryValue(String contentType) {
127
        String boundaryKey = "boundary=";
128
        String boundaryValue = "";
129
        int indexOfBoundaryKey = contentType.indexOf(boundaryKey);
130 2 1. determineBoundaryValue : negated conditional → KILLED
2. determineBoundaryValue : changed conditional boundary → KILLED
        if (indexOfBoundaryKey > 0) {
131
            // grab all the text after the key to obtain the boundary value
132 1 1. determineBoundaryValue : Replaced integer addition with subtraction → KILLED
            boundaryValue = contentType.substring(indexOfBoundaryKey + boundaryKey.length());
133
        }
134 1 1. determineBoundaryValue : replaced return value with "" for com/renomad/minum/web/BodyProcessor::determineBoundaryValue → KILLED
        return boundaryValue;
135
    }
136
137
138
    /**
139
     * Parse data formatted by application/x-www-form-urlencoded
140
     * See <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/POST">...</a>
141
     * <p>
142
     * See here for the encoding: <a href="https://developer.mozilla.org/en-US/docs/Glossary/percent-encoding">...</a>
143
     * <p>
144
     * for example, {@code valuea=3&valueb=this+is+something}
145
     */
146
    Body parseUrlEncodedForm(InputStream is, int contentLength) {
147 1 1. parseUrlEncodedForm : negated conditional → KILLED
        if (contentLength == 0) {
148 1 1. parseUrlEncodedForm : replaced return value with null for com/renomad/minum/web/BodyProcessor::parseUrlEncodedForm → KILLED
            return Body.EMPTY;
149
        }
150
        final var postedPairs = new HashMap<String, byte[]>();
151
152
        try {
153
            int countOfPartitions = 0;
154
            for (final var keyValue : getUrlEncodedDataIterable(is, contentLength)) {
155 1 1. parseUrlEncodedForm : Changed increment from 1 to -1 → KILLED
                countOfPartitions += 1;
156 2 1. parseUrlEncodedForm : changed conditional boundary → KILLED
2. parseUrlEncodedForm : negated conditional → KILLED
                if (countOfPartitions >= MAX_BODY_KEYS_URL_ENCODED) {
157
                    throw new WebServerException("Error: body had excessive number of partitions ("+countOfPartitions+").  Maximum allowed: " + MAX_BODY_KEYS_URL_ENCODED);
158
                }
159
                String value = new String(keyValue.getUedg().readAllBytes(), StandardCharsets.US_ASCII);
160
                String key = keyValue.getKey();
161
                final var decodedValue = StringUtils.decode(value);
162 1 1. parseUrlEncodedForm : negated conditional → KILLED
                final var convertedValue = decodedValue == null ? "".getBytes(StandardCharsets.UTF_8) : decodedValue.getBytes(StandardCharsets.UTF_8);
163
164
                final var result = postedPairs.put(key, convertedValue);
165
166 1 1. parseUrlEncodedForm : negated conditional → KILLED
                if (result != null) {
167
                    throw new WebServerException("Error: key (" +key + ") was duplicated in the post body - previous version was " + new String(result, StandardCharsets.US_ASCII) + " and recent data was " + decodedValue);
168
                }
169
            }
170
        } catch (Exception ex) {
171
            logger.logDebug(() -> "Unable to parse this body. returning what we have so far.  Exception message: " + ex.getMessage());
172
            // we have to return nothing for the raw bytes, because at this point we are halfway through
173
            // reading the inputstream and don't want to return broken data
174 1 1. parseUrlEncodedForm : replaced return value with null for com/renomad/minum/web/BodyProcessor::parseUrlEncodedForm → KILLED
            return new Body(postedPairs, new byte[0], List.of(), BodyType.UNRECOGNIZED);
175
        }
176
        // we return nothing for the raw bytes because the code for parsing the streaming data
177
        // doesn't begin with a fully-read byte array - it pulls data off the stream one byte
178
        // at a time.
179 1 1. parseUrlEncodedForm : replaced return value with null for com/renomad/minum/web/BodyProcessor::parseUrlEncodedForm → KILLED
        return new Body(postedPairs, new byte[0], List.of(), BodyType.FORM_URL_ENCODED);
180
    }
181
182
    /**
183
     * A regex used to extract the name value from the headers in multipart/form
184
     * For example, in the following code, you can see that the name is "image_uploads"
185
     * <pre>
186
     * {@code
187
     * --i_am_a_boundary
188
     * Content-Type: text/plain
189
     * Content-Disposition: form-data; name="text1"
190
     *
191
     * I am a value that is text
192
     * --i_am_a_boundary
193
     * Content-Type: application/octet-stream
194
     * Content-Disposition: form-data; name="image_uploads"; filename="photo_preview.jpg"
195
     * }
196
     * </pre>
197
     */
198
    private static final Pattern multiformNameRegex = Pattern.compile("\\bname\\b=\"(?<namevalue>.*?)\"");
199
    private static final Pattern multiformFilenameRegex = Pattern.compile("\\bfilename\\b=\"(?<namevalue>.*?)\"");
200
201
    @Override
202
    public Iterable<UrlEncodedKeyValue> getUrlEncodedDataIterable(InputStream inputStream, long contentLength) {
203 2 1. getUrlEncodedDataIterable : replaced return value with Collections.emptyList for com/renomad/minum/web/BodyProcessor::getUrlEncodedDataIterable → KILLED
2. lambda$getUrlEncodedDataIterable$6 : replaced return value with null for com/renomad/minum/web/BodyProcessor::lambda$getUrlEncodedDataIterable$6 → KILLED
        return () -> new Iterator<>() {
204
205
            final CountBytesRead countBytesRead = new CountBytesRead();
206
207
            @Override
208
            public boolean hasNext() {
209 3 1. hasNext : negated conditional → KILLED
2. hasNext : replaced boolean return with true for com/renomad/minum/web/BodyProcessor$1::hasNext → KILLED
3. hasNext : changed conditional boundary → KILLED
                return countBytesRead.getCount() < contentLength;
210
            }
211
212
            @Override
213
            public UrlEncodedKeyValue next() {
214 1 1. next : negated conditional → KILLED
                if (!hasNext()) {
215
                    throw new NoSuchElementException();
216
                }
217
                String key = "";
218
                ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
219
                while(true) {
220
                    int result = 0;
221
                    try {
222
                        result = inputStream.read();
223 1 1. next : removed call to com/renomad/minum/web/CountBytesRead::increment → KILLED
                        countBytesRead.increment();
224
                    } catch (IOException e) {
225
                        throw new WebServerException(e);
226
                    }
227
                    // if this is true, the inputstream is closed
228 1 1. next : negated conditional → KILLED
                    if (result == -1) break;
229
                    byte myByte = (byte) result;
230
                    // if this is true, we're done with the key
231 1 1. next : negated conditional → KILLED
                    if (myByte == '=') {
232
                        // URL encoding is in ASCII only.
233
                        key = byteArrayOutputStream.toString(StandardCharsets.US_ASCII);
234
                        break;
235
                    } else {
236 2 1. next : changed conditional boundary → KILLED
2. next : negated conditional → KILLED
                        if (byteArrayOutputStream.size() >= MAX_KEY_SIZE_BYTES) {
237
                            throw new WebServerException("Maximum size for name attribute is " + MAX_KEY_SIZE_BYTES + " ascii characters");
238
                        }
239 1 1. next : removed call to java/io/ByteArrayOutputStream::write → KILLED
                        byteArrayOutputStream.write(myByte);
240
                    }
241
                }
242
243 1 1. next : negated conditional → KILLED
                if (key.isBlank()) {
244
                    throw new WebServerException("Unable to parse this body. no key found during parsing");
245 1 1. next : negated conditional → KILLED
                } else if (countBytesRead.getCount() == contentLength) {
246
                    // if the only thing sent was the key and there's no further data, return the key with a null input stream
247
                    // that will immediately return
248 1 1. next : replaced return value with null for com/renomad/minum/web/BodyProcessor$1::next → KILLED
                    return new UrlEncodedKeyValue(key, new UrlEncodedDataGetter(InputStream.nullInputStream(), countBytesRead, contentLength));
249
                } else {
250 1 1. next : replaced return value with null for com/renomad/minum/web/BodyProcessor$1::next → KILLED
                    return new UrlEncodedKeyValue(key, new UrlEncodedDataGetter(inputStream, countBytesRead, contentLength));
251
                }
252
            }
253
        };
254
    }
255
256
257
    @Override
258
    public Iterable<StreamingMultipartPartition> getMultiPartIterable(InputStream inputStream, String boundaryValue, int contentLength) {
259 2 1. lambda$getMultiPartIterable$7 : replaced return value with null for com/renomad/minum/web/BodyProcessor::lambda$getMultiPartIterable$7 → KILLED
2. getMultiPartIterable : replaced return value with Collections.emptyList for com/renomad/minum/web/BodyProcessor::getMultiPartIterable → KILLED
        return () -> new Iterator<>() {
260
261
            final CountBytesRead countBytesRead = new CountBytesRead();
262
            boolean hasReadFirstPartition = false;
263
264
            @Override
265
            public boolean hasNext() {
266
                // determining if we have more to read is a little tricky because we have a buffer
267
                // filled by reading ahead, looking for the boundary value
268 4 1. hasNext : changed conditional boundary → SURVIVED
2. hasNext : Replaced integer subtraction with addition → KILLED
3. hasNext : replaced boolean return with true for com/renomad/minum/web/BodyProcessor$2::hasNext → KILLED
4. hasNext : negated conditional → KILLED
                return (contentLength - countBytesRead.getCount()) > boundaryValue.length();
269
            }
270
271
            @Override
272
            public StreamingMultipartPartition next() {
273 1 1. next : negated conditional → KILLED
                if (!hasNext()) {
274
                    throw new NoSuchElementException();
275
                }
276
                // confirm that the boundary value is as expected, as a sanity check,
277
                // and avoid including the boundary value in the first set of headers
278 1 1. next : negated conditional → KILLED
                if (! hasReadFirstPartition) {
279
                    String s;
280
                    try {
281
                        s = inputStreamUtils.readLine(inputStream);
282 2 1. next : Replaced integer addition with subtraction → SURVIVED
2. next : removed call to com/renomad/minum/web/CountBytesRead::incrementBy → KILLED
                        countBytesRead.incrementBy(s.length() + 2);
283
                        hasReadFirstPartition = true;
284 1 1. next : negated conditional → KILLED
                        if (!s.contains(boundaryValue)) {
285
                            throw new IOException("Error: First line must contain the expected boundary value. Expected to find: "+ boundaryValue + " in: " + s);
286
                        }
287
                    } catch (IOException e) {
288
                        throw new WebServerException(e);
289
                    }
290
                }
291
                List<String> allHeaders = Headers.getAllHeaders(inputStream, inputStreamUtils);
292
                int lengthOfHeaders = allHeaders.stream().map(String::length).reduce(0, Integer::sum);
293
                // each line has a CR + LF (that's two bytes) and the headers end with a second pair of CR+LF.
294 2 1. next : Replaced integer addition with subtraction → KILLED
2. next : Replaced integer multiplication with division → KILLED
                int extraCrLfs = (2 * allHeaders.size()) + 2;
295 2 1. next : Replaced integer addition with subtraction → KILLED
2. next : removed call to com/renomad/minum/web/CountBytesRead::incrementBy → KILLED
                countBytesRead.incrementBy(lengthOfHeaders + extraCrLfs);
296
297
                Headers headers = new Headers(allHeaders);
298
299
                List<String> cds = headers.valueByKey("Content-Disposition");
300 1 1. next : negated conditional → KILLED
                if (cds == null) {
301
                    throw new WebServerException("Error: no Content-Disposition header on partition in Multipart/form data");
302
                }
303
                String contentDisposition = String.join(";", cds);
304
305
                Matcher nameMatcher = multiformNameRegex.matcher(contentDisposition);
306
                Matcher filenameMatcher = multiformFilenameRegex.matcher(contentDisposition);
307
308
                String name = "";
309 1 1. next : negated conditional → KILLED
                if (nameMatcher.find()) {
310
                    name = nameMatcher.group("namevalue");
311
                } else {
312
                    throw new WebServerException("Error: No name value set on multipart partition");
313
                }
314
                String filename = "";
315 1 1. next : negated conditional → KILLED
                if (filenameMatcher.find()) {
316
                    filename = filenameMatcher.group("namevalue");
317
                }
318
319
                // at this point our inputstream pointer is at the beginning of the
320
                // body data.  From here until the end it's pure data.
321
322 1 1. next : replaced return value with null for com/renomad/minum/web/BodyProcessor$2::next → KILLED
                return new StreamingMultipartPartition(headers, inputStream, new ContentDisposition(name, filename), boundaryValue, countBytesRead, contentLength);
323
            }
324
325
326
        };
327
    }
328
329
}

Mutations

37

1.1
Location : extractData
Killed by : com.renomad.minum.web.RequestTests.test_Request_BodyTooLong(com.renomad.minum.web.RequestTests)
negated conditional → KILLED

2.2
Location : extractData
Killed by : com.renomad.minum.web.WebTests
changed conditional boundary → KILLED

38

1.1
Location : extractData
Killed by : com.renomad.minum.web.RequestTests.test_Request_BodyTooLong(com.renomad.minum.web.RequestTests)
negated conditional → KILLED

2.2
Location : extractData
Killed by : com.renomad.minum.web.WebTests
changed conditional boundary → KILLED

44

1.1
Location : extractData
Killed by : com.renomad.minum.web.BodyProcessorTests
negated conditional → KILLED

47

1.1
Location : extractData
Killed by : com.renomad.minum.web.BodyProcessorTests
replaced return value with null for com/renomad/minum/web/BodyProcessor::extractData → KILLED

50

1.1
Location : extractData
Killed by : com.renomad.minum.web.RequestTests.test_Request_ImproperlyFormedMultipart(com.renomad.minum.web.RequestTests)
replaced return value with null for com/renomad/minum/web/BodyProcessor::extractData → KILLED

65

1.1
Location : extractBodyFromInputStream
Killed by : com.renomad.minum.web.RequestTests.test_Request_ImproperlyFormedMultipart(com.renomad.minum.web.RequestTests)
negated conditional → KILLED

67

1.1
Location : extractBodyFromInputStream
Killed by : com.renomad.minum.web.BodyProcessorTests
replaced return value with null for com/renomad/minum/web/BodyProcessor::extractBodyFromInputStream → KILLED

70

1.1
Location : extractBodyFromInputStream
Killed by : com.renomad.minum.web.RequestTests.test_Request_ImproperlyFormedUrlEncoded(com.renomad.minum.web.RequestTests)
negated conditional → KILLED

71

1.1
Location : extractBodyFromInputStream
Killed by : com.renomad.minum.web.RequestTests.test_Request_ImproperlyFormedUrlEncoded(com.renomad.minum.web.RequestTests)
replaced return value with null for com/renomad/minum/web/BodyProcessor::extractBodyFromInputStream → KILLED

72

1.1
Location : extractBodyFromInputStream
Killed by : com.renomad.minum.web.RequestTests.test_Request_ImproperlyFormedMultipart(com.renomad.minum.web.RequestTests)
negated conditional → KILLED

74

1.1
Location : extractBodyFromInputStream
Killed by : com.renomad.minum.web.RequestTests.test_Request_ImproperlyFormedMultipart(com.renomad.minum.web.RequestTests)
replaced return value with null for com/renomad/minum/web/BodyProcessor::extractBodyFromInputStream → KILLED

78

1.1
Location : extractBodyFromInputStream
Killed by : com.renomad.minum.web.RequestTests.test_Request_getUrlEncoded_EdgeCase_ComplaintAfterGetBody(com.renomad.minum.web.RequestTests)
replaced return value with null for com/renomad/minum/web/BodyProcessor::extractBodyFromInputStream → KILLED

91

1.1
Location : parseMultipartForm
Killed by : com.renomad.minum.web.RequestTests.test_Request_Multipart_ImproperlyFormed(com.renomad.minum.web.RequestTests)
negated conditional → KILLED

93

1.1
Location : parseMultipartForm
Killed by : com.renomad.minum.web.BodyProcessorTests
replaced return value with null for com/renomad/minum/web/BodyProcessor::parseMultipartForm → KILLED

101

1.1
Location : parseMultipartForm
Killed by : com.renomad.minum.web.RequestTests.test_Request_Multipart_ExcessiveCountOfPartitions(com.renomad.minum.web.RequestTests)
Changed increment from 1 to -1 → KILLED

102

1.1
Location : parseMultipartForm
Killed by : com.renomad.minum.web.RequestTests.test_Request_Multipart_ImproperlyFormed(com.renomad.minum.web.RequestTests)
negated conditional → KILLED

2.2
Location : parseMultipartForm
Killed by : com.renomad.minum.web.RequestTests.test_Request_Multipart_ExcessiveCountOfPartitions(com.renomad.minum.web.RequestTests)
changed conditional boundary → KILLED

113

1.1
Location : parseMultipartForm
Killed by : com.renomad.minum.web.WebTests
replaced return value with null for com/renomad/minum/web/BodyProcessor::parseMultipartForm → KILLED

115

1.1
Location : parseMultipartForm
Killed by : com.renomad.minum.web.RequestTests.test_Request_ImproperlyFormedMultipart(com.renomad.minum.web.RequestTests)
negated conditional → KILLED

116

1.1
Location : parseMultipartForm
Killed by : com.renomad.minum.web.RequestTests.test_Request_ImproperlyFormedMultipart(com.renomad.minum.web.RequestTests)
replaced return value with null for com/renomad/minum/web/BodyProcessor::parseMultipartForm → KILLED

118

1.1
Location : parseMultipartForm
Killed by : com.renomad.minum.web.RequestTests.test_Request_getMultipartForm_EdgeCase_ComplaintAfterGetBody(com.renomad.minum.web.RequestTests)
replaced return value with null for com/renomad/minum/web/BodyProcessor::parseMultipartForm → KILLED

130

1.1
Location : determineBoundaryValue
Killed by : com.renomad.minum.web.RequestTests.test_Request_Multipart_ImproperlyFormed(com.renomad.minum.web.RequestTests)
negated conditional → KILLED

2.2
Location : determineBoundaryValue
Killed by : com.renomad.minum.web.WebTests
changed conditional boundary → KILLED

132

1.1
Location : determineBoundaryValue
Killed by : com.renomad.minum.web.RequestTests.test_Request_Multipart_ImproperlyFormed(com.renomad.minum.web.RequestTests)
Replaced integer addition with subtraction → KILLED

134

1.1
Location : determineBoundaryValue
Killed by : com.renomad.minum.web.RequestTests.test_Request_Multipart_ImproperlyFormed(com.renomad.minum.web.RequestTests)
replaced return value with "" for com/renomad/minum/web/BodyProcessor::determineBoundaryValue → KILLED

147

1.1
Location : parseUrlEncodedForm
Killed by : com.renomad.minum.web.RequestTests.test_Request_ImproperlyFormedUrlEncoded(com.renomad.minum.web.RequestTests)
negated conditional → KILLED

148

1.1
Location : parseUrlEncodedForm
Killed by : com.renomad.minum.web.WebTests
replaced return value with null for com/renomad/minum/web/BodyProcessor::parseUrlEncodedForm → KILLED

155

1.1
Location : parseUrlEncodedForm
Killed by : com.renomad.minum.web.RequestTests.test_Request_UrlEncoded_ExcessiveCountOfKeyValuePairs(com.renomad.minum.web.RequestTests)
Changed increment from 1 to -1 → KILLED

156

1.1
Location : parseUrlEncodedForm
Killed by : com.renomad.minum.web.RequestTests.test_Request_UrlEncoded_ExcessiveCountOfKeyValuePairs(com.renomad.minum.web.RequestTests)
changed conditional boundary → KILLED

2.2
Location : parseUrlEncodedForm
Killed by : com.renomad.minum.web.RequestTests.test_Request_UrlEncoded_ExcessiveCountOfKeyValuePairs(com.renomad.minum.web.RequestTests)
negated conditional → KILLED

162

1.1
Location : parseUrlEncodedForm
Killed by : com.renomad.minum.web.BodyProcessorTests
negated conditional → KILLED

166

1.1
Location : parseUrlEncodedForm
Killed by : com.renomad.minum.web.RequestTests.test_Request_UrlEncoded_ExcessiveCountOfKeyValuePairs(com.renomad.minum.web.RequestTests)
negated conditional → KILLED

174

1.1
Location : parseUrlEncodedForm
Killed by : com.renomad.minum.web.RequestTests.test_Request_ImproperlyFormedUrlEncoded(com.renomad.minum.web.RequestTests)
replaced return value with null for com/renomad/minum/web/BodyProcessor::parseUrlEncodedForm → KILLED

179

1.1
Location : parseUrlEncodedForm
Killed by : com.renomad.minum.web.BodyProcessorTests
replaced return value with null for com/renomad/minum/web/BodyProcessor::parseUrlEncodedForm → KILLED

203

1.1
Location : getUrlEncodedDataIterable
Killed by : com.renomad.minum.web.RequestTests.test_Request_getUrlEncoded_EdgeCase_ContentLengthTooLong(com.renomad.minum.web.RequestTests)
replaced return value with Collections.emptyList for com/renomad/minum/web/BodyProcessor::getUrlEncodedDataIterable → KILLED

2.2
Location : lambda$getUrlEncodedDataIterable$6
Killed by : com.renomad.minum.web.RequestTests.test_Request_getUrlEncoded_EdgeCase_Empty(com.renomad.minum.web.RequestTests)
replaced return value with null for com/renomad/minum/web/BodyProcessor::lambda$getUrlEncodedDataIterable$6 → KILLED

209

1.1
Location : hasNext
Killed by : com.renomad.minum.web.RequestTests.test_Request_getUrlEncoded_EdgeCase_Empty(com.renomad.minum.web.RequestTests)
negated conditional → KILLED

2.2
Location : hasNext
Killed by : com.renomad.minum.web.RequestTests.test_Request_getUrlEncoded_EdgeCase_Empty(com.renomad.minum.web.RequestTests)
replaced boolean return with true for com/renomad/minum/web/BodyProcessor$1::hasNext → KILLED

3.3
Location : hasNext
Killed by : com.renomad.minum.web.RequestTests.test_Request_getUrlEncoded_EdgeCase_Empty(com.renomad.minum.web.RequestTests)
changed conditional boundary → KILLED

214

1.1
Location : next
Killed by : com.renomad.minum.web.RequestTests.test_Request_getUrlEncoded_EdgeCase_Empty(com.renomad.minum.web.RequestTests)
negated conditional → KILLED

223

1.1
Location : next
Killed by : com.renomad.minum.web.RequestTests.test_Request_getUrlEncoded_EdgeCase_ContentLengthNotLongEnough(com.renomad.minum.web.RequestTests)
removed call to com/renomad/minum/web/CountBytesRead::increment → KILLED

228

1.1
Location : next
Killed by : com.renomad.minum.web.RequestTests.test_Request_getUrlEncoded_EdgeCase_ContentLengthTooLong(com.renomad.minum.web.RequestTests)
negated conditional → KILLED

231

1.1
Location : next
Killed by : com.renomad.minum.web.RequestTests.test_Request_getUrlEncoded_EdgeCase_ContentLengthTooLong(com.renomad.minum.web.RequestTests)
negated conditional → KILLED

236

1.1
Location : next
Killed by : com.renomad.minum.FunctionalTests
changed conditional boundary → KILLED

2.2
Location : next
Killed by : com.renomad.minum.web.RequestTests.test_Request_getUrlEncoded_EdgeCase_ContentLengthTooLong(com.renomad.minum.web.RequestTests)
negated conditional → KILLED

239

1.1
Location : next
Killed by : com.renomad.minum.web.RequestTests.test_Request_getUrlEncoded_EdgeCase_ContentLengthTooLong(com.renomad.minum.web.RequestTests)
removed call to java/io/ByteArrayOutputStream::write → KILLED

243

1.1
Location : next
Killed by : com.renomad.minum.web.RequestTests.test_Request_getUrlEncoded_EdgeCase_ContentLengthTooLong(com.renomad.minum.web.RequestTests)
negated conditional → KILLED

245

1.1
Location : next
Killed by : com.renomad.minum.web.RequestTests.test_Request_getUrlEncoded_EdgeCase_ContentLengthNotLongEnough(com.renomad.minum.web.RequestTests)
negated conditional → KILLED

248

1.1
Location : next
Killed by : com.renomad.minum.web.WebTests
replaced return value with null for com/renomad/minum/web/BodyProcessor$1::next → KILLED

250

1.1
Location : next
Killed by : com.renomad.minum.web.RequestTests.test_Request_getUrlEncoded_EdgeCase_ContentLengthTooLong(com.renomad.minum.web.RequestTests)
replaced return value with null for com/renomad/minum/web/BodyProcessor$1::next → KILLED

259

1.1
Location : lambda$getMultiPartIterable$7
Killed by : com.renomad.minum.web.RequestTests.test_Request_getMultipartIterable_EdgeCase_Empty(com.renomad.minum.web.RequestTests)
replaced return value with null for com/renomad/minum/web/BodyProcessor::lambda$getMultiPartIterable$7 → KILLED

2.2
Location : getMultiPartIterable
Killed by : com.renomad.minum.web.RequestTests.test_Request_getMultipartIterable_EdgeCase_No_Valid_Boundary_3(com.renomad.minum.web.RequestTests)
replaced return value with Collections.emptyList for com/renomad/minum/web/BodyProcessor::getMultiPartIterable → KILLED

268

1.1
Location : hasNext
Killed by : com.renomad.minum.web.RequestTests.testReadingEmptyStreamingMultipart(com.renomad.minum.web.RequestTests)
Replaced integer subtraction with addition → KILLED

2.2
Location : hasNext
Killed by : com.renomad.minum.web.RequestTests.test_Request_getMultipartIterable_EdgeCase_Empty(com.renomad.minum.web.RequestTests)
replaced boolean return with true for com/renomad/minum/web/BodyProcessor$2::hasNext → KILLED

3.3
Location : hasNext
Killed by : none
changed conditional boundary → SURVIVED
Covering tests

4.4
Location : hasNext
Killed by : com.renomad.minum.web.RequestTests.test_Request_getMultipartIterable_EdgeCase_Empty(com.renomad.minum.web.RequestTests)
negated conditional → KILLED

273

1.1
Location : next
Killed by : com.renomad.minum.web.RequestTests.test_Request_getMultipartIterable_EdgeCase_Empty(com.renomad.minum.web.RequestTests)
negated conditional → KILLED

278

1.1
Location : next
Killed by : com.renomad.minum.web.RequestTests.test_Request_getMultipartIterable_EdgeCase_No_Valid_Boundary_3(com.renomad.minum.web.RequestTests)
negated conditional → KILLED

282

1.1
Location : next
Killed by : com.renomad.minum.web.RequestTests.testReadingEmptyStreamingMultipart(com.renomad.minum.web.RequestTests)
removed call to com/renomad/minum/web/CountBytesRead::incrementBy → KILLED

2.2
Location : next
Killed by : none
Replaced integer addition with subtraction → SURVIVED
Covering tests

284

1.1
Location : next
Killed by : com.renomad.minum.web.RequestTests.test_Request_getMultipartIterable_EdgeCase_No_Valid_Boundary_3(com.renomad.minum.web.RequestTests)
negated conditional → KILLED

294

1.1
Location : next
Killed by : com.renomad.minum.web.RequestTests.testReadingEmptyStreamingMultipart(com.renomad.minum.web.RequestTests)
Replaced integer addition with subtraction → KILLED

2.2
Location : next
Killed by : com.renomad.minum.web.RequestTests.testReadingStreamingMultipart_AlternateCase_UsingBuffer(com.renomad.minum.web.RequestTests)
Replaced integer multiplication with division → KILLED

295

1.1
Location : next
Killed by : com.renomad.minum.web.RequestTests.testReadingEmptyStreamingMultipart(com.renomad.minum.web.RequestTests)
Replaced integer addition with subtraction → KILLED

2.2
Location : next
Killed by : com.renomad.minum.web.RequestTests.testReadingEmptyStreamingMultipart(com.renomad.minum.web.RequestTests)
removed call to com/renomad/minum/web/CountBytesRead::incrementBy → KILLED

300

1.1
Location : next
Killed by : com.renomad.minum.web.RequestTests.testReadingEmptyStreamingMultipart(com.renomad.minum.web.RequestTests)
negated conditional → KILLED

309

1.1
Location : next
Killed by : com.renomad.minum.web.RequestTests.testReadingEmptyStreamingMultipart(com.renomad.minum.web.RequestTests)
negated conditional → KILLED

315

1.1
Location : next
Killed by : com.renomad.minum.web.RequestTests.testReadingEmptyStreamingMultipart(com.renomad.minum.web.RequestTests)
negated conditional → KILLED

322

1.1
Location : next
Killed by : com.renomad.minum.web.RequestTests.testReadingEmptyStreamingMultipart(com.renomad.minum.web.RequestTests)
replaced return value with null for com/renomad/minum/web/BodyProcessor$2::next → KILLED

Active mutators

Tests examined


Report generated by PIT 1.17.0