InputStreamUtils.java

1
package com.renomad.minum.web;
2
3
import com.renomad.minum.security.ForbiddenUseException;
4
import com.renomad.minum.utils.UtilsException;
5
6
import java.io.ByteArrayOutputStream;
7
import java.io.IOException;
8
import java.io.InputStream;
9
import java.nio.charset.StandardCharsets;
10
import java.util.Objects;
11
12
/**
13
 * Handy helpful utilities for working with input streams.
14
 */
15
final class InputStreamUtils implements IInputStreamUtils {
16
17
    private final int maxReadLineSizeBytes;
18
19
    public InputStreamUtils(int maxReadLineSizeBytes) {
20
        this.maxReadLineSizeBytes = maxReadLineSizeBytes;
21
    }
22
23
    @Override
24
    public String readLine(InputStream inputStream) throws IOException  {
25
        final int NEWLINE_DECIMAL = 10;
26
        final int CARRIAGE_RETURN_DECIMAL = 13;
27
28 1 1. readLine : Replaced integer division with multiplication → SURVIVED
        final var result = new ByteArrayOutputStream(maxReadLineSizeBytes / 3);
29 1 1. readLine : Changed increment from 1 to -1 → KILLED
        for (int i = 0;; i++) {
30 2 1. readLine : changed conditional boundary → SURVIVED
2. readLine : negated conditional → KILLED
            if (i >= maxReadLineSizeBytes) {
31 1 1. readLine : removed call to java/io/InputStream::close → KILLED
                inputStream.close();
32
                throw new ForbiddenUseException("client sent more bytes than allowed for a single line.  max: " + maxReadLineSizeBytes);
33
            }
34
            int a = inputStream.read();
35 2 1. readLine : replaced return value with "" for com/renomad/minum/web/InputStreamUtils::readLine → SURVIVED
2. readLine : negated conditional → KILLED
            if (a == -1) return result.toString(StandardCharsets.UTF_8);
36 1 1. readLine : negated conditional → KILLED
            if (a == CARRIAGE_RETURN_DECIMAL) continue;
37 1 1. readLine : negated conditional → KILLED
            if (a == NEWLINE_DECIMAL) break;
38 1 1. readLine : removed call to java/io/ByteArrayOutputStream::write → KILLED
            result.write(a);
39
        }
40 1 1. readLine : replaced return value with "" for com/renomad/minum/web/InputStreamUtils::readLine → KILLED
        return result.toString(StandardCharsets.UTF_8);
41
    }
42
43
    @Override
44
    public byte[] read(int lengthToRead, InputStream inputStream) {
45
        final int typicalBufferSize = 1024 * 8;
46
        byte[] buf = new byte[Math.min(lengthToRead, typicalBufferSize)]; // 8k buffer is my understanding of a decent size.  Fast, doesn't waste too much space.
47
        byte[] data;
48
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
49
        int read;
50
        int totalRead = 0;
51
        try {
52 2 1. read : changed conditional boundary → KILLED
2. read : negated conditional → KILLED
            while ((read = inputStream.read(buf)) >= 0) {
53 1 1. read : Replaced integer addition with subtraction → KILLED
                totalRead += read;
54 2 1. read : negated conditional → KILLED
2. read : changed conditional boundary → KILLED
                if (totalRead < lengthToRead) {
55
                    // if we haven't gotten everything we wanted, write this to the output and loop again
56 1 1. read : removed call to java/io/ByteArrayOutputStream::write → KILLED
                    baos.write(buf, 0, read);
57
                } else {
58 3 1. read : Replaced integer subtraction with addition → SURVIVED
2. read : Replaced integer subtraction with addition → KILLED
3. read : removed call to java/io/ByteArrayOutputStream::write → KILLED
                    baos.write(buf, 0, read - (totalRead - lengthToRead));
59
                    break;
60
                }
61
            }
62
        } catch (IOException ex) {
63
            throw new UtilsException(ex);
64
        }
65
        data = baos.toByteArray();
66
67 1 1. read : negated conditional → KILLED
        if (data.length != lengthToRead) {
68
            String message = String.format("length of bytes read (%d) must be what we expected (%d)", data.length, lengthToRead);
69
            throw new ForbiddenUseException(message);
70
        }
71 1 1. read : replaced return value with null for com/renomad/minum/web/InputStreamUtils::read → KILLED
        return data;
72
    }
73
74
    @Override
75
    public boolean equals(Object o) {
76 2 1. equals : negated conditional → KILLED
2. equals : replaced boolean return with false for com/renomad/minum/web/InputStreamUtils::equals → KILLED
        if (this == o) return true;
77 3 1. equals : negated conditional → KILLED
2. equals : negated conditional → KILLED
3. equals : replaced boolean return with true for com/renomad/minum/web/InputStreamUtils::equals → KILLED
        if (o == null || getClass() != o.getClass()) return false;
78
        InputStreamUtils that = (InputStreamUtils) o;
79 2 1. equals : negated conditional → KILLED
2. equals : replaced boolean return with true for com/renomad/minum/web/InputStreamUtils::equals → KILLED
        return maxReadLineSizeBytes == that.maxReadLineSizeBytes;
80
    }
81
82
    @Override
83
    public int hashCode() {
84 1 1. hashCode : replaced int return with 0 for com/renomad/minum/web/InputStreamUtils::hashCode → KILLED
        return Objects.hash(maxReadLineSizeBytes);
85
    }
86
}

Mutations

28

1.1
Location : readLine
Killed by : none
Replaced integer division with multiplication → SURVIVED
Covering tests

29

1.1
Location : readLine
Killed by : com.renomad.minum.FunctionalTests
Changed increment from 1 to -1 → KILLED

30

1.1
Location : readLine
Killed by : none
changed conditional boundary → SURVIVED
Covering tests

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

31

1.1
Location : readLine
Killed by : com.renomad.minum.FunctionalTests
removed call to java/io/InputStream::close → KILLED

35

1.1
Location : readLine
Killed by : none
replaced return value with "" for com/renomad/minum/web/InputStreamUtils::readLine → SURVIVED
Covering tests

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

36

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

37

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

38

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

40

1.1
Location : readLine
Killed by : com.renomad.minum.web.RequestTests.test_Request_getMultipartIterable_EdgeCase_No_Valid_Boundary_3(com.renomad.minum.web.RequestTests)
replaced return value with "" for com/renomad/minum/web/InputStreamUtils::readLine → KILLED

52

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

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

53

1.1
Location : read
Killed by : com.renomad.minum.web.WebTests
Replaced integer addition with subtraction → KILLED

54

1.1
Location : read
Killed by : com.renomad.minum.web.InputStreamUtilsTests.testReadingLarge(com.renomad.minum.web.InputStreamUtilsTests)
negated conditional → KILLED

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

56

1.1
Location : read
Killed by : com.renomad.minum.web.InputStreamUtilsTests.testReadingLarge(com.renomad.minum.web.InputStreamUtilsTests)
removed call to java/io/ByteArrayOutputStream::write → KILLED

58

1.1
Location : read
Killed by : none
Replaced integer subtraction with addition → SURVIVED
Covering tests

2.2
Location : read
Killed by : com.renomad.minum.web.RequestTests.test_Request_getUrlEncoded_EdgeCase_ComplaintAfterGetBody(com.renomad.minum.web.RequestTests)
Replaced integer subtraction with addition → KILLED

3.3
Location : read
Killed by : com.renomad.minum.web.RequestTests.test_Request_getUrlEncoded_EdgeCase_ComplaintAfterGetBody(com.renomad.minum.web.RequestTests)
removed call to java/io/ByteArrayOutputStream::write → KILLED

67

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

71

1.1
Location : read
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/InputStreamUtils::read → KILLED

76

1.1
Location : equals
Killed by : com.renomad.minum.web.InputStreamUtilsTests.testEquals(com.renomad.minum.web.InputStreamUtilsTests)
negated conditional → KILLED

2.2
Location : equals
Killed by : com.renomad.minum.web.InputStreamUtilsTests.testEquals(com.renomad.minum.web.InputStreamUtilsTests)
replaced boolean return with false for com/renomad/minum/web/InputStreamUtils::equals → KILLED

77

1.1
Location : equals
Killed by : com.renomad.minum.web.InputStreamUtilsTests.testEquals(com.renomad.minum.web.InputStreamUtilsTests)
negated conditional → KILLED

2.2
Location : equals
Killed by : com.renomad.minum.web.InputStreamUtilsTests.testEquals(com.renomad.minum.web.InputStreamUtilsTests)
negated conditional → KILLED

3.3
Location : equals
Killed by : com.renomad.minum.web.InputStreamUtilsTests.testEquals(com.renomad.minum.web.InputStreamUtilsTests)
replaced boolean return with true for com/renomad/minum/web/InputStreamUtils::equals → KILLED

79

1.1
Location : equals
Killed by : com.renomad.minum.web.InputStreamUtilsTests.testEquals(com.renomad.minum.web.InputStreamUtilsTests)
negated conditional → KILLED

2.2
Location : equals
Killed by : com.renomad.minum.web.InputStreamUtilsTests.testEquals(com.renomad.minum.web.InputStreamUtilsTests)
replaced boolean return with true for com/renomad/minum/web/InputStreamUtils::equals → KILLED

84

1.1
Location : hashCode
Killed by : com.renomad.minum.web.InputStreamUtilsTests.testEquals(com.renomad.minum.web.InputStreamUtilsTests)
replaced int return with 0 for com/renomad/minum/web/InputStreamUtils::hashCode → KILLED

Active mutators

Tests examined


Report generated by PIT 1.17.0