RingBuffer.java

1
package com.renomad.minum.utils;
2
3
import java.lang.reflect.Array;
4
import java.util.Iterator;
5
import java.util.List;
6
import java.util.NoSuchElementException;
7
8
/**
9
 * A minimalist implementation of a ring buffer
10
 * For use with web mechanisms like the multipart body processor
11
 * and the HTML processor.
12
 */
13
public class RingBuffer<T> implements Iterable<T>{
14
15
    /**
16
     * The size of the inner array supporting this class.  Also,
17
     * the most items our RingBuffer can contain.
18
     */
19
    private final int limit;
20
21
    /**
22
     * The last index of the array - just the limit minus 1.
23
     */
24
    private final int lastIndex;
25
26
    /**
27
     * An instance of the class for this generic collection, used to
28
     * help build data structures.
29
     */
30
    private final T[] innerArray;
31
32
    /**
33
     * Index of where we place the next item
34
     */
35
    private int nextIndex;
36
37
    /**
38
     * Build a {@link RingBuffer}
39
     * @param limit the maximum size of the buffer
40
     */
41
    public RingBuffer(int limit, Class<T> clazz) {
42
        this.limit = limit;
43 1 1. <init> : Replaced integer subtraction with addition → KILLED
        this.lastIndex = limit - 1;
44
        @SuppressWarnings("unchecked")
45
        final T[] t = (T[]) Array.newInstance(clazz, limit);
46
        this.innerArray = t;
47
        this.nextIndex = 0;
48
    }
49
50
    /**
51
     * This will move the index forward and
52
     * wrap around at the end.
53
     */
54
    private int incrementIndex(int index) {
55 1 1. incrementIndex : negated conditional → KILLED
        if (index == lastIndex) {
56
            return 0;
57
        } else {
58 2 1. incrementIndex : Replaced integer addition with subtraction → KILLED
2. incrementIndex : replaced int return with 0 for com/renomad/minum/utils/RingBuffer::incrementIndex → KILLED
            return index + 1;
59
        }
60
    }
61
62
    public void add(T item) {
63
        innerArray[nextIndex] = item;
64
        nextIndex = incrementIndex(nextIndex);
65
    }
66
67
    public int getLimit() {
68 1 1. getLimit : replaced int return with 0 for com/renomad/minum/utils/RingBuffer::getLimit → KILLED
        return limit;
69
    }
70
71
    /**
72
     * Returns true if the data in the "myList" parameter is found
73
     * within the RingBuffer.
74
     */
75
    public boolean contains(List<T> myList) {
76 2 1. contains : negated conditional → KILLED
2. contains : negated conditional → KILLED
        if (myList == null || myList.isEmpty()) {
77
            throw new UtilsException("expected a valid non-empty list to search for in the RingBuffer");
78
        }
79
        int myListIndex = 0;
80
        int myListLength = myList.size();
81
        for (var value : this) {
82 1 1. contains : negated conditional → KILLED
            if (myList.get(myListIndex).equals(value)) {
83 1 1. contains : Changed increment from 1 to -1 → KILLED
                myListIndex += 1;
84
            } else {
85
                myListIndex = 0;
86
            }
87
88 1 1. contains : negated conditional → KILLED
            if (myListIndex == myListLength) {
89 1 1. contains : replaced boolean return with false for com/renomad/minum/utils/RingBuffer::contains → KILLED
                return true;
90
            }
91
92
        }
93 1 1. contains : replaced boolean return with true for com/renomad/minum/utils/RingBuffer::contains → KILLED
        return false;
94
    }
95
96
    /**
97
     * Returns true if the data in the "myList" parameter is found
98
     * within the RingBuffer at the index provided.
99
     */
100
    public boolean containsAt(List<T> myList, int index) {
101 2 1. containsAt : negated conditional → KILLED
2. containsAt : negated conditional → KILLED
        if (myList == null || myList.isEmpty()) {
102
            throw new UtilsException("expected a valid non-empty list to search for in the RingBuffer");
103
        }
104 4 1. containsAt : changed conditional boundary → KILLED
2. containsAt : changed conditional boundary → KILLED
3. containsAt : negated conditional → KILLED
4. containsAt : negated conditional → KILLED
        if (index > lastIndex || index < 0) {
105
            throw new UtilsException("expected an index greater than zero and less-than-or-equal to the last index of the buffer (the limit minus one)");
106
        }
107
        int i = 0;
108
        int myListIndex = 0;
109 1 1. containsAt : Replaced integer subtraction with addition → KILLED
        int myListLastIndex = myList.size() - 1;
110
        boolean comparing = false;
111
        var iterator = this.iterator();
112 1 1. containsAt : negated conditional → KILLED
        while (iterator.hasNext()) {
113
            var value = iterator.next();
114 1 1. containsAt : negated conditional → KILLED
            if (i == index) {
115
                comparing = true;
116
            }
117
118 1 1. containsAt : negated conditional → KILLED
            if (comparing) {
119 1 1. containsAt : negated conditional → KILLED
                if (! myList.get(myListIndex).equals(value)) {
120 1 1. containsAt : replaced boolean return with true for com/renomad/minum/utils/RingBuffer::containsAt → KILLED
                    return false;
121
                }
122 1 1. containsAt : negated conditional → KILLED
                if (myListIndex == myListLastIndex) {
123 1 1. containsAt : replaced boolean return with false for com/renomad/minum/utils/RingBuffer::containsAt → KILLED
                    return true;
124
                }
125 1 1. containsAt : Changed increment from 1 to -1 → KILLED
                myListIndex += 1;
126
            }
127
128 1 1. containsAt : Changed increment from 1 to -1 → KILLED
            i += 1;
129
        }
130 1 1. containsAt : replaced boolean return with true for com/renomad/minum/utils/RingBuffer::containsAt → KILLED
        return false;
131
    }
132
133
    @Override
134
    public Iterator<T> iterator() {
135 1 1. iterator : replaced return value with null for com/renomad/minum/utils/RingBuffer::iterator → KILLED
        return new Iterator<>() {
136
137
            /**
138
             * As we loop through the buffer, we have to use a similar
139
             * technique to the "nextIndex" - wrapping around when we
140
             * hit the end
141
             */
142
            int iteratorIndex = nextIndex;
143
            /**
144
             * We'll count as we read values, stopping when we've read every slot.
145
             */
146
            int count = 0;
147
148
            @Override
149
            public boolean hasNext() {
150 3 1. hasNext : replaced boolean return with true for com/renomad/minum/utils/RingBuffer$1::hasNext → TIMED_OUT
2. hasNext : changed conditional boundary → KILLED
3. hasNext : negated conditional → KILLED
                return count < limit;
151
            }
152
153
            @Override
154
            public T next() {
155 1 1. next : negated conditional → KILLED
                if (!hasNext()) {
156
                    throw new NoSuchElementException();
157
                }
158
                var result = innerArray[iteratorIndex];
159
                iteratorIndex = incrementIndex(iteratorIndex);
160 1 1. next : Replaced integer addition with subtraction → TIMED_OUT
                count += 1;
161 1 1. next : replaced return value with null for com/renomad/minum/utils/RingBuffer$1::next → KILLED
                return result;
162
            }
163
        };
164
    }
165
166
    /**
167
     * Returns the value at the slot pointed to by the "nextIndex".  Note that
168
     * this will be null at first while the array starts to get filled.
169
     */
170
    public T atNextIndex() {
171 1 1. atNextIndex : replaced return value with null for com/renomad/minum/utils/RingBuffer::atNextIndex → KILLED
        return innerArray[nextIndex];
172
    }
173
174
}

Mutations

43

1.1
Location : <init>
Killed by : com.renomad.minum.BugExposureTests.test_RingBuffer_ContainsAt_PatternExtendsBeyondBuffer(com.renomad.minum.BugExposureTests)
Replaced integer subtraction with addition → KILLED

55

1.1
Location : incrementIndex
Killed by : com.renomad.minum.utils.RingBufferTests
negated conditional → KILLED

58

1.1
Location : incrementIndex
Killed by : com.renomad.minum.BugExposureTests.test_RingBuffer_ContainsAt_PatternExtendsBeyondBuffer(com.renomad.minum.BugExposureTests)
Replaced integer addition with subtraction → KILLED

2.2
Location : incrementIndex
Killed by : com.renomad.minum.utils.RingBufferTests
replaced int return with 0 for com/renomad/minum/utils/RingBuffer::incrementIndex → KILLED

68

1.1
Location : getLimit
Killed by : com.renomad.minum.web.BoundaryBugTest
replaced int return with 0 for com/renomad/minum/utils/RingBuffer::getLimit → KILLED

76

1.1
Location : contains
Killed by : com.renomad.minum.utils.RingBufferTests
negated conditional → KILLED

2.2
Location : contains
Killed by : com.renomad.minum.utils.RingBufferTests
negated conditional → KILLED

82

1.1
Location : contains
Killed by : com.renomad.minum.utils.RingBufferTests
negated conditional → KILLED

83

1.1
Location : contains
Killed by : com.renomad.minum.utils.RingBufferTests
Changed increment from 1 to -1 → KILLED

88

1.1
Location : contains
Killed by : com.renomad.minum.utils.RingBufferTests
negated conditional → KILLED

89

1.1
Location : contains
Killed by : com.renomad.minum.utils.RingBufferTests
replaced boolean return with false for com/renomad/minum/utils/RingBuffer::contains → KILLED

93

1.1
Location : contains
Killed by : com.renomad.minum.utils.RingBufferTests
replaced boolean return with true for com/renomad/minum/utils/RingBuffer::contains → KILLED

101

1.1
Location : containsAt
Killed by : com.renomad.minum.BugExposureTests.test_RingBuffer_ContainsAt_PatternExtendsBeyondBuffer(com.renomad.minum.BugExposureTests)
negated conditional → KILLED

2.2
Location : containsAt
Killed by : com.renomad.minum.BugExposureTests.test_RingBuffer_ContainsAt_PatternExtendsBeyondBuffer(com.renomad.minum.BugExposureTests)
negated conditional → KILLED

104

1.1
Location : containsAt
Killed by : com.renomad.minum.utils.RingBufferTests
changed conditional boundary → KILLED

2.2
Location : containsAt
Killed by : com.renomad.minum.BugExposureTests.test_RingBuffer_ContainsAt_PatternExtendsBeyondBuffer(com.renomad.minum.BugExposureTests)
changed conditional boundary → KILLED

3.3
Location : containsAt
Killed by : com.renomad.minum.BugExposureTests.test_RingBuffer_ContainsAt_PatternExtendsBeyondBuffer(com.renomad.minum.BugExposureTests)
negated conditional → KILLED

4.4
Location : containsAt
Killed by : com.renomad.minum.BugExposureTests.test_RingBuffer_ContainsAt_PatternExtendsBeyondBuffer(com.renomad.minum.BugExposureTests)
negated conditional → KILLED

109

1.1
Location : containsAt
Killed by : com.renomad.minum.utils.RingBufferTests
Replaced integer subtraction with addition → KILLED

112

1.1
Location : containsAt
Killed by : com.renomad.minum.utils.RingBufferTests
negated conditional → KILLED

114

1.1
Location : containsAt
Killed by : com.renomad.minum.utils.RingBufferTests
negated conditional → KILLED

118

1.1
Location : containsAt
Killed by : com.renomad.minum.utils.RingBufferTests
negated conditional → KILLED

119

1.1
Location : containsAt
Killed by : com.renomad.minum.utils.RingBufferTests
negated conditional → KILLED

120

1.1
Location : containsAt
Killed by : com.renomad.minum.utils.RingBufferTests
replaced boolean return with true for com/renomad/minum/utils/RingBuffer::containsAt → KILLED

122

1.1
Location : containsAt
Killed by : com.renomad.minum.BugExposureTests.test_RingBuffer_ContainsAt_PatternExtendsBeyondBuffer(com.renomad.minum.BugExposureTests)
negated conditional → KILLED

123

1.1
Location : containsAt
Killed by : com.renomad.minum.utils.RingBufferTests
replaced boolean return with false for com/renomad/minum/utils/RingBuffer::containsAt → KILLED

125

1.1
Location : containsAt
Killed by : com.renomad.minum.utils.RingBufferTests
Changed increment from 1 to -1 → KILLED

128

1.1
Location : containsAt
Killed by : com.renomad.minum.utils.RingBufferTests
Changed increment from 1 to -1 → KILLED

130

1.1
Location : containsAt
Killed by : com.renomad.minum.BugExposureTests.test_RingBuffer_ContainsAt_PatternExtendsBeyondBuffer(com.renomad.minum.BugExposureTests)
replaced boolean return with true for com/renomad/minum/utils/RingBuffer::containsAt → KILLED

135

1.1
Location : iterator
Killed by : com.renomad.minum.BugExposureTests.test_RingBuffer_ContainsAt_PatternExtendsBeyondBuffer(com.renomad.minum.BugExposureTests)
replaced return value with null for com/renomad/minum/utils/RingBuffer::iterator → KILLED

150

1.1
Location : hasNext
Killed by : com.renomad.minum.utils.RingBufferTests
changed conditional boundary → KILLED

2.2
Location : hasNext
Killed by : com.renomad.minum.utils.RingBufferTests
negated conditional → KILLED

3.3
Location : hasNext
Killed by : none
replaced boolean return with true for com/renomad/minum/utils/RingBuffer$1::hasNext → TIMED_OUT

155

1.1
Location : next
Killed by : com.renomad.minum.BugExposureTests.test_RingBuffer_ContainsAt_PatternExtendsBeyondBuffer(com.renomad.minum.BugExposureTests)
negated conditional → KILLED

160

1.1
Location : next
Killed by : none
Replaced integer addition with subtraction → TIMED_OUT

161

1.1
Location : next
Killed by : com.renomad.minum.utils.RingBufferTests
replaced return value with null for com/renomad/minum/utils/RingBuffer$1::next → KILLED

171

1.1
Location : atNextIndex
Killed by : com.renomad.minum.web.BoundaryBugTest
replaced return value with null for com/renomad/minum/utils/RingBuffer::atNextIndex → KILLED

Active mutators

Tests examined


Report generated by PIT 1.17.0