SplittableOutputStream.java

1
/*-
2
 * #%L
3
 * io.earcam.utilitarian.io
4
 * %%
5
 * Copyright (C) 2017 earcam
6
 * %%
7
 * SPDX-License-Identifier: (BSD-3-Clause OR EPL-1.0 OR Apache-2.0 OR MIT)
8
 *
9
 * You <b>must</b> choose to accept, in full - any individual or combination of
10
 * the following licenses:
11
 * <ul>
12
 * 	<li><a href="https://opensource.org/licenses/BSD-3-Clause">BSD-3-Clause</a></li>
13
 * 	<li><a href="https://www.eclipse.org/legal/epl-v10.html">EPL-1.0</a></li>
14
 * 	<li><a href="https://www.apache.org/licenses/LICENSE-2.0">Apache-2.0</a></li>
15
 * 	<li><a href="https://opensource.org/licenses/MIT">MIT</a></li>
16
 * </ul>
17
 * #L%
18
 */
19
package io.earcam.utilitarian.io;
20
21
import java.io.ByteArrayOutputStream;
22
import java.io.IOException;
23
import java.io.OutputStream;
24
import java.nio.BufferOverflowException;
25
import java.nio.BufferUnderflowException;
26
import java.util.function.Supplier;
27
28
import javax.annotation.concurrent.NotThreadSafe;
29
30
/**
31
 * <p>
32
 * Deals with structured (e.g. XML) or unstructured data.
33
 * </p>
34
 *
35
 * <p>
36
 * User code must invoke {@link #beginRecord()} before writing {@code byte}s, and subsequently delimit safe
37
 * splitting points by invoking {@link #endRecord()}. The number of {@code byte}s written between the
38
 * call to {@link #beginRecord()} and call to {@link #endRecord()} must not exceed
39
 * {@link #maxSize(long)} - ({@link #header}{@code .length} + {@link #footer}{@code .length})
40
 * </p>
41
 *
42
 * <p>
43
 * A <i>record</i> is defined as any {@code byte}s written between calls to {@link #beginRecord()} and
44
 * {@link #endRecord()}. Should the maximum file size be specified and the length of a single record (plus
45
 * header and footer) exceed the maximum then a {@link BufferOverflowException} is throw.
46
 *
47
 * <p>
48
 * Common usage would be splitting files, in this case the {@link Supplier} is expected to <i>keep
49
 * track</i> of output file names.
50
 * </p>
51
 *
52
 * <p>
53
 * <b>Please note limitation</b>; due to the use of {@link Long} internally, the maximum
54
 * size per-file is limited to {@value java.lang.Long#MAX_VALUE} bytes (which is
55
 * 9,223PB or 9,223,000,000GB) per split {@link OutputStream} .
56
 *
57
 */
58
@SuppressWarnings("squid:S4349") // Sonar: Not applicable IMO
59
@NotThreadSafe
60
public class SplittableOutputStream extends OutputStream implements SplittableOutputStreamBuilder, SplittableOutputStreamBuilder.SplitOutputStreamBuilder {
61
62
	private final Supplier<OutputStream> supplier;
63
	private final byte[] header;
64
	private final byte[] footer;
65
	private final ByteArrayOutputStream buffer = new ByteArrayOutputStream();
66
67
	private OutputStream out = null;
68
	private long maxFileSize = Long.MAX_VALUE;
69
	private long maxRecordCount = Long.MAX_VALUE;
70
	private long bytesCount;
71
	private long recordsCount;
72
73
	private boolean inScope;
74
75
76
	private SplittableOutputStream(Supplier<OutputStream> supplier, byte[] head, byte[] footer)
77
	{
78
		this.supplier = supplier;
79
		this.header = head;
80
		this.footer = footer;
81
	}
82
83
84
	/**
85
	 * Begin building a {@link SplittableOutputStream}
86
	 *
87
	 * @param next a {@link Supplier} of the underlying {@link OutputStream}s
88
	 * @param header written at the start of each {@link OutputStream} (e.g. file header)
89
	 * @param footer written at the end of each {@link OutputStream} (e.g. file footer)
90
	 * @return the builder for further construction
91
	 * @throws IOException rethrows in the unlikely event the underlying ByteArrayOutputStream buffer does
92
	 */
93
	public static SplittableOutputStreamBuilder splittable(Supplier<OutputStream> next, byte[] head, byte[] footer) throws IOException
94
	{
95
		@SuppressWarnings("squid:S2095")  // false positive - it's being returned
96
		SplittableOutputStream splittable = new SplittableOutputStream(next, head, footer);
97 1 1. splittable : removed call to io/earcam/utilitarian/io/SplittableOutputStream::reset → KILLED
		splittable.reset();
98 1 1. splittable : mutated return of Object value for io/earcam/utilitarian/io/SplittableOutputStream::splittable to ( if (x != null) null else throw new RuntimeException ) → KILLED
		return splittable;
99
	}
100
101
102
	private void reset() throws IOException
103
	{
104
		bytesCount = recordsCount = 0L;
105
		byte[] bytes = buffer.toByteArray();
106 1 1. reset : removed call to java/io/ByteArrayOutputStream::reset → KILLED
		buffer.reset();
107 1 1. reset : removed call to java/io/ByteArrayOutputStream::write → KILLED
		buffer.write(header);
108 1 1. reset : removed call to java/io/ByteArrayOutputStream::write → KILLED
		buffer.write(bytes);
109
	}
110
111
112
	@Override
113
	public SplitOutputStreamBuilder maxSize(long bytes)
114
	{
115
		maxFileSize = bytes;
116 1 1. maxSize : removed call to io/earcam/utilitarian/io/SplittableOutputStream::checkSanity → KILLED
		checkSanity(header, footer, maxFileSize);
117 1 1. maxSize : mutated return of Object value for io/earcam/utilitarian/io/SplittableOutputStream::maxSize to ( if (x != null) null else throw new RuntimeException ) → KILLED
		return this;
118
	}
119
120
121
	@Override
122
	public SplitOutputStreamBuilder maxCount(long numberOfRecords)
123
	{
124 1 1. maxCount : removed call to io/earcam/utilitarian/io/SplittableOutputStream::requireNaturalNumber → KILLED
		requireNaturalNumber(numberOfRecords);
125
		maxRecordCount = numberOfRecords;
126 1 1. maxCount : mutated return of Object value for io/earcam/utilitarian/io/SplittableOutputStream::maxCount to ( if (x != null) null else throw new RuntimeException ) → KILLED
		return this;
127
	}
128
129
130
	private void requireNaturalNumber(long number)
131
	{
132 2 1. requireNaturalNumber : changed conditional boundary → KILLED
2. requireNaturalNumber : negated conditional → KILLED
		if(number <= 0) {
133
			throw new IllegalArgumentException("A positive, non-zero value is required.  Received: " + number);
134
		}
135
	}
136
137
138
	@Override
139
	public SplittableOutputStream outputStream() throws IOException
140
	{
141 1 1. outputStream : mutated return of Object value for io/earcam/utilitarian/io/SplittableOutputStream::outputStream to ( if (x != null) null else throw new RuntimeException ) → KILLED
		return this;
142
	}
143
144
145
	private static void checkSanity(byte[] head, byte[] foot, long maxFileSize)
146
	{
147 3 1. checkSanity : changed conditional boundary → SURVIVED
2. checkSanity : Replaced integer addition with subtraction → KILLED
3. checkSanity : negated conditional → KILLED
		if(head.length + foot.length > maxFileSize) {
148
			throw new IllegalArgumentException("header.length + footer.length > maxFileSize: " + head.length + " + " + foot.length + " > " + maxFileSize);
149
		}
150
	}
151
152
153
	@Override
154
	public void write(int b) throws IOException
155
	{
156 1 1. write : removed call to io/earcam/utilitarian/io/SplittableOutputStream::checkBeforeWrite → KILLED
		checkBeforeWrite(1);
157 1 1. write : removed call to java/io/ByteArrayOutputStream::write → KILLED
		buffer.write(b);
158
	}
159
160
161
	private void checkBeforeWrite(int pendingBytes)
162
	{
163 1 1. checkBeforeWrite : negated conditional → KILLED
		if(!inScope) {
164
			throw new IllegalStateException("Record scope not started");
165
		}
166 4 1. checkBeforeWrite : Replaced integer addition with subtraction → SURVIVED
2. checkBeforeWrite : Replaced integer addition with subtraction → SURVIVED
3. checkBeforeWrite : changed conditional boundary → KILLED
4. checkBeforeWrite : negated conditional → KILLED
		if(pendingBytes + header.length + footer.length > maxFileSize) {
167
			throw new BufferOverflowException();
168
		}
169
	}
170
171
172
	@Override
173
	public void write(byte[] bytes) throws IOException
174
	{
175 1 1. write : removed call to io/earcam/utilitarian/io/SplittableOutputStream::checkBeforeWrite → KILLED
		checkBeforeWrite(bytes.length);
176 1 1. write : removed call to java/io/ByteArrayOutputStream::write → KILLED
		buffer.write(bytes);
177
	}
178
179
180
	/**
181
	 * Called to mark the beginning of a <i>record</i> (where a "record" is any block
182
	 * of bytes that can only be treated atomically; in that it's valid to split content
183
	 * at the record's boundaries.
184
	 *
185
	 * @see #endRecord()
186
	 */
187
	public void beginRecord()
188
	{
189 1 1. beginRecord : negated conditional → KILLED
		if(inScope) {
190
			throw new IllegalStateException("Record scope already started");
191
		}
192
		inScope = true;
193
	}
194
195
196
	/**
197
	 * Called to mark the end of a <i>record</i>
198
	 *
199
	 * @throws IOException rethrows anything from the underlying {@link OutputStream}
200
	 *
201
	 * @see #beginRecord()
202
	 */
203
	public void endRecord() throws IOException
204
	{
205 1 1. endRecord : removed call to io/earcam/utilitarian/io/SplittableOutputStream::endScope → KILLED
		endScope();
206 1 1. endRecord : Replaced long addition with subtraction → KILLED
		++recordsCount;
207 2 1. endRecord : negated conditional → KILLED
2. endRecord : negated conditional → KILLED
		if(bufferIsTooLarge() || maxRecordsExceeded()) {
208 1 1. endRecord : removed call to io/earcam/utilitarian/io/SplittableOutputStream::endSplit → KILLED
			endSplit();
209
		}
210 1 1. endRecord : negated conditional → KILLED
		if(recorded()) {
211 1 1. endRecord : removed call to io/earcam/utilitarian/io/SplittableOutputStream::writeBuffer → KILLED
			writeBuffer();
212
		}
213
	}
214
215
216
	private void endScope()
217
	{
218 1 1. endScope : negated conditional → KILLED
		if(!inScope) {
219
			throw new IllegalStateException("Record scope not started, cannot end");
220
		}
221
		inScope = false;
222
	}
223
224
225
	private boolean bufferIsTooLarge()
226
	{
227 5 1. bufferIsTooLarge : changed conditional boundary → KILLED
2. bufferIsTooLarge : Replaced long addition with subtraction → KILLED
3. bufferIsTooLarge : Replaced long addition with subtraction → KILLED
4. bufferIsTooLarge : negated conditional → KILLED
5. bufferIsTooLarge : replaced return of integer sized value with (x == 0 ? 1 : 0) → KILLED
		return bytesCount + footer.length + buffer.size() > maxFileSize;
228
	}
229
230
231
	private boolean maxRecordsExceeded()
232
	{
233 3 1. maxRecordsExceeded : changed conditional boundary → SURVIVED
2. maxRecordsExceeded : negated conditional → KILLED
3. maxRecordsExceeded : replaced return of integer sized value with (x == 0 ? 1 : 0) → KILLED
		return recordsCount > maxRecordCount;
234
	}
235
236
237
	private void endSplit() throws IOException
238
	{
239 1 1. endSplit : negated conditional → KILLED
		if(out != null) {
240 1 1. endSplit : removed call to java/io/OutputStream::write → KILLED
			out.write(footer);
241 1 1. endSplit : removed call to java/io/OutputStream::close → SURVIVED
			out.close();
242
			out = null;
243 1 1. endSplit : removed call to io/earcam/utilitarian/io/SplittableOutputStream::reset → KILLED
			reset();
244
		}
245
	}
246
247
248
	private boolean recorded()
249
	{
250 5 1. recorded : changed conditional boundary → KILLED
2. recorded : negated conditional → KILLED
3. recorded : negated conditional → KILLED
4. recorded : negated conditional → KILLED
5. recorded : replaced return of integer sized value with (x == 0 ? 1 : 0) → KILLED
		return (recordsCount == 1 && buffer.size() > header.length)
251 2 1. recorded : changed conditional boundary → KILLED
2. recorded : negated conditional → KILLED
				|| (recordsCount != 1 && buffer.size() > 0);
252
	}
253
254
255
	private void writeBuffer() throws IOException
256
	{
257 1 1. writeBuffer : removed call to java/io/OutputStream::write → KILLED
		out().write(buffer.toByteArray());
258 1 1. writeBuffer : Replaced long addition with subtraction → KILLED
		bytesCount += buffer.size();
259 1 1. writeBuffer : removed call to java/io/ByteArrayOutputStream::reset → KILLED
		buffer.reset();
260
	}
261
262
263
	private OutputStream out()
264
	{
265 1 1. out : negated conditional → KILLED
		if(out == null) {
266
			out = supplier.get();
267
		}
268 1 1. out : mutated return of Object value for io/earcam/utilitarian/io/SplittableOutputStream::out to ( if (x != null) null else throw new RuntimeException ) → KILLED
		return out;
269
	}
270
271
272
	@Override
273
	public void close() throws IOException
274
	{
275 1 1. close : negated conditional → KILLED
		if(recorded()) {
276
			throw new BufferUnderflowException();
277
		}
278 1 1. close : removed call to io/earcam/utilitarian/io/SplittableOutputStream::endSplit → KILLED
		endSplit();
279 2 1. close : changed conditional boundary → KILLED
2. close : negated conditional → KILLED
		if(buffer.size() > header.length) {
280 1 1. close : removed call to io/earcam/utilitarian/io/SplittableOutputStream::writeBuffer → KILLED
			writeBuffer();
281 1 1. close : removed call to io/earcam/utilitarian/io/SplittableOutputStream::endSplit → SURVIVED
			endSplit();
282
		}
283
	}
284
}

Mutations

97

1.1
Location : splittable
Killed by : io.earcam.utilitarian.io.SplittableOutputStreamTest.contentWithOneRecordFitsMaxSizeExactly()
removed call to io/earcam/utilitarian/io/SplittableOutputStream::reset → KILLED

98

1.1
Location : splittable
Killed by : io.earcam.utilitarian.io.SplittableOutputStreamTest.maxSizeCannotBeNegative()
mutated return of Object value for io/earcam/utilitarian/io/SplittableOutputStream::splittable to ( if (x != null) null else throw new RuntimeException ) → KILLED

106

1.1
Location : reset
Killed by : io.earcam.utilitarian.io.SplittableOutputStreamTest.contentWithTwoRecordsFitsMaxSizeExactlyIsSplitWhenMaxRecordsCountIsOne()
removed call to java/io/ByteArrayOutputStream::reset → KILLED

107

1.1
Location : reset
Killed by : io.earcam.utilitarian.io.SplittableOutputStreamTest.contentWithOneRecordFitsMaxSizeExactly()
removed call to java/io/ByteArrayOutputStream::write → KILLED

108

1.1
Location : reset
Killed by : io.earcam.utilitarian.io.SplittableOutputStreamTest.contentWithTwoRecordsFitsMaxSizeExactlyIsSplitWhenMaxRecordsCountIsOne()
removed call to java/io/ByteArrayOutputStream::write → KILLED

116

1.1
Location : maxSize
Killed by : io.earcam.utilitarian.io.SplittableOutputStreamTest.maxSizeCannotBeNegative()
removed call to io/earcam/utilitarian/io/SplittableOutputStream::checkSanity → KILLED

117

1.1
Location : maxSize
Killed by : io.earcam.utilitarian.io.SplittableOutputStreamTest.cannotWriteByteArrayUnlessStarted()
mutated return of Object value for io/earcam/utilitarian/io/SplittableOutputStream::maxSize to ( if (x != null) null else throw new RuntimeException ) → KILLED

124

1.1
Location : maxCount
Killed by : io.earcam.utilitarian.io.SplittableOutputStreamTest.maxRecordsCannotBeZero()
removed call to io/earcam/utilitarian/io/SplittableOutputStream::requireNaturalNumber → KILLED

126

1.1
Location : maxCount
Killed by : io.earcam.utilitarian.io.SplittableOutputStreamTest.contentWithTwoRecordsFitsMaxSizeExactlyIsSplitWhenMaxRecordsCountIsOne()
mutated return of Object value for io/earcam/utilitarian/io/SplittableOutputStream::maxCount to ( if (x != null) null else throw new RuntimeException ) → KILLED

132

1.1
Location : requireNaturalNumber
Killed by : io.earcam.utilitarian.io.SplittableOutputStreamTest.maxRecordsCannotBeZero()
changed conditional boundary → KILLED

2.2
Location : requireNaturalNumber
Killed by : io.earcam.utilitarian.io.SplittableOutputStreamTest.maxRecordsCannotBeZero()
negated conditional → KILLED

141

1.1
Location : outputStream
Killed by : io.earcam.utilitarian.io.SplittableOutputStreamTest.cannotWriteByteArrayUnlessStarted()
mutated return of Object value for io/earcam/utilitarian/io/SplittableOutputStream::outputStream to ( if (x != null) null else throw new RuntimeException ) → KILLED

147

1.1
Location : checkSanity
Killed by : none
changed conditional boundary → SURVIVED

2.2
Location : checkSanity
Killed by : io.earcam.utilitarian.io.SplittableOutputStreamTest.maxSizeCannotBeZero()
Replaced integer addition with subtraction → KILLED

3.3
Location : checkSanity
Killed by : io.earcam.utilitarian.io.SplittableOutputStreamTest.maxSizeCannotBeNegative()
negated conditional → KILLED

156

1.1
Location : write
Killed by : io.earcam.utilitarian.io.SplittableOutputStreamTest.cannotWriteByteUnlessStarted()
removed call to io/earcam/utilitarian/io/SplittableOutputStream::checkBeforeWrite → KILLED

157

1.1
Location : write
Killed by : io.earcam.utilitarian.io.SplittableOutputStreamTest.contentWithTwoRecordsFitsMaxSizeExactly()
removed call to java/io/ByteArrayOutputStream::write → KILLED

163

1.1
Location : checkBeforeWrite
Killed by : io.earcam.utilitarian.io.SplittableOutputStreamTest.cannotWriteByteArrayUnlessStarted()
negated conditional → KILLED

166

1.1
Location : checkBeforeWrite
Killed by : io.earcam.utilitarian.io.SplittableOutputStreamTest.contentWithOneRecordFitsMaxSizeExactly()
changed conditional boundary → KILLED

2.2
Location : checkBeforeWrite
Killed by : none
Replaced integer addition with subtraction → SURVIVED

3.3
Location : checkBeforeWrite
Killed by : none
Replaced integer addition with subtraction → SURVIVED

4.4
Location : checkBeforeWrite
Killed by : io.earcam.utilitarian.io.SplittableOutputStreamTest.whenRecordSizePlusHeadAndFootExceedsMaxSizeThenThrowsBufferOverflow()
negated conditional → KILLED

175

1.1
Location : write
Killed by : io.earcam.utilitarian.io.SplittableOutputStreamTest.cannotWriteByteArrayUnlessStarted()
removed call to io/earcam/utilitarian/io/SplittableOutputStream::checkBeforeWrite → KILLED

176

1.1
Location : write
Killed by : io.earcam.utilitarian.io.SplittableOutputStreamTest.contentWithOneRecordFitsMaxSizeExactly()
removed call to java/io/ByteArrayOutputStream::write → KILLED

189

1.1
Location : beginRecord
Killed by : io.earcam.utilitarian.io.SplittableOutputStreamTest.whenRecordSizePlusHeadAndFootExceedsMaxSizeThenThrowsBufferOverflow()
negated conditional → KILLED

205

1.1
Location : endRecord
Killed by : io.earcam.utilitarian.io.SplittableOutputStreamTest.invokingEndWhenNotStartedThrowsIllegalState()
removed call to io/earcam/utilitarian/io/SplittableOutputStream::endScope → KILLED

206

1.1
Location : endRecord
Killed by : io.earcam.utilitarian.io.SplittableOutputStreamTest.whenNoRecordsAreWrittenThenSupplierIsNeverCalled()
Replaced long addition with subtraction → KILLED

207

1.1
Location : endRecord
Killed by : io.earcam.utilitarian.io.SplittableOutputStreamTest.contentWithTwoRecordsFitsMaxSizeExactly()
negated conditional → KILLED

2.2
Location : endRecord
Killed by : io.earcam.utilitarian.io.SplittableOutputStreamTest.contentWithTwoRecordsFitsMaxSizeExactly()
negated conditional → KILLED

208

1.1
Location : endRecord
Killed by : io.earcam.utilitarian.io.SplittableOutputStreamTest.contentWithTwoRecordsFitsMaxSizeExactlyIsSplitWhenMaxRecordsCountIsOne()
removed call to io/earcam/utilitarian/io/SplittableOutputStream::endSplit → KILLED

210

1.1
Location : endRecord
Killed by : io.earcam.utilitarian.io.SplittableOutputStreamTest.contentWithOneRecordFitsMaxSizeExactly()
negated conditional → KILLED

211

1.1
Location : endRecord
Killed by : io.earcam.utilitarian.io.SplittableOutputStreamTest.contentWithOneRecordFitsMaxSizeExactly()
removed call to io/earcam/utilitarian/io/SplittableOutputStream::writeBuffer → KILLED

218

1.1
Location : endScope
Killed by : io.earcam.utilitarian.io.SplittableOutputStreamTest.invokingEndWhenNotStartedThrowsIllegalState()
negated conditional → KILLED

227

1.1
Location : bufferIsTooLarge
Killed by : io.earcam.utilitarian.io.SplittableOutputStreamTest.contentWithTwoRecordsFitsMaxSizeExactly()
changed conditional boundary → KILLED

2.2
Location : bufferIsTooLarge
Killed by : io.earcam.utilitarian.io.SplittableOutputStreamTest.exampleThreeUnevenSplits()
Replaced long addition with subtraction → KILLED

3.3
Location : bufferIsTooLarge
Killed by : io.earcam.utilitarian.io.SplittableOutputStreamTest.regressionEnsureLastRecordWritten()
Replaced long addition with subtraction → KILLED

4.4
Location : bufferIsTooLarge
Killed by : io.earcam.utilitarian.io.SplittableOutputStreamTest.contentWithTwoRecordsFitsMaxSizeExactly()
negated conditional → KILLED

5.5
Location : bufferIsTooLarge
Killed by : io.earcam.utilitarian.io.SplittableOutputStreamTest.contentWithTwoRecordsFitsMaxSizeExactly()
replaced return of integer sized value with (x == 0 ? 1 : 0) → KILLED

233

1.1
Location : maxRecordsExceeded
Killed by : none
changed conditional boundary → SURVIVED

2.2
Location : maxRecordsExceeded
Killed by : io.earcam.utilitarian.io.SplittableOutputStreamTest.contentWithTwoRecordsFitsMaxSizeExactly()
negated conditional → KILLED

3.3
Location : maxRecordsExceeded
Killed by : io.earcam.utilitarian.io.SplittableOutputStreamTest.contentWithTwoRecordsFitsMaxSizeExactly()
replaced return of integer sized value with (x == 0 ? 1 : 0) → KILLED

239

1.1
Location : endSplit
Killed by : io.earcam.utilitarian.io.SplittableOutputStreamTest.contentWithOneRecordFitsMaxSizeExactly()
negated conditional → KILLED

240

1.1
Location : endSplit
Killed by : io.earcam.utilitarian.io.SplittableOutputStreamTest.contentWithOneRecordFitsMaxSizeExactly()
removed call to java/io/OutputStream::write → KILLED

241

1.1
Location : endSplit
Killed by : none
removed call to java/io/OutputStream::close → SURVIVED

243

1.1
Location : endSplit
Killed by : io.earcam.utilitarian.io.SplittableOutputStreamTest.contentWithTwoRecordsFitsMaxSizeExactlyIsSplitWhenMaxRecordsCountIsOne()
removed call to io/earcam/utilitarian/io/SplittableOutputStream::reset → KILLED

250

1.1
Location : recorded
Killed by : io.earcam.utilitarian.io.SplittableOutputStreamTest.whenNoRecordsAreWrittenThenSupplierIsNeverCalled()
changed conditional boundary → KILLED

2.2
Location : recorded
Killed by : io.earcam.utilitarian.io.SplittableOutputStreamTest.contentWithTwoRecordsFitsMaxSizeExactlyIsSplitWhenMaxRecordsCountIsOne()
negated conditional → KILLED

3.3
Location : recorded
Killed by : io.earcam.utilitarian.io.SplittableOutputStreamTest.whenNoRecordsAreWrittenThenSupplierIsNeverCalled()
negated conditional → KILLED

4.4
Location : recorded
Killed by : io.earcam.utilitarian.io.SplittableOutputStreamTest.givenRecordPartWrittenWhenClosedThenThrowsUnderflow()
negated conditional → KILLED

5.5
Location : recorded
Killed by : io.earcam.utilitarian.io.SplittableOutputStreamTest.givenRecordPartWrittenWhenClosedThenThrowsUnderflow()
replaced return of integer sized value with (x == 0 ? 1 : 0) → KILLED

251

1.1
Location : recorded
Killed by : io.earcam.utilitarian.io.SplittableOutputStreamTest.contentWithTwoRecordsFitsMaxSizeExactly()
changed conditional boundary → KILLED

2.2
Location : recorded
Killed by : io.earcam.utilitarian.io.SplittableOutputStreamTest.givenRecordPartWrittenWhenClosedThenThrowsUnderflow()
negated conditional → KILLED

257

1.1
Location : writeBuffer
Killed by : io.earcam.utilitarian.io.SplittableOutputStreamTest.contentWithOneRecordFitsMaxSizeExactly()
removed call to java/io/OutputStream::write → KILLED

258

1.1
Location : writeBuffer
Killed by : io.earcam.utilitarian.io.SplittableOutputStreamTest.exampleTwoExactSplits()
Replaced long addition with subtraction → KILLED

259

1.1
Location : writeBuffer
Killed by : io.earcam.utilitarian.io.SplittableOutputStreamTest.contentWithOneRecordFitsMaxSizeExactly()
removed call to java/io/ByteArrayOutputStream::reset → KILLED

265

1.1
Location : out
Killed by : io.earcam.utilitarian.io.SplittableOutputStreamTest.contentWithOneRecordFitsMaxSizeExactly()
negated conditional → KILLED

268

1.1
Location : out
Killed by : io.earcam.utilitarian.io.SplittableOutputStreamTest.contentWithOneRecordFitsMaxSizeExactly()
mutated return of Object value for io/earcam/utilitarian/io/SplittableOutputStream::out to ( if (x != null) null else throw new RuntimeException ) → KILLED

275

1.1
Location : close
Killed by : io.earcam.utilitarian.io.SplittableOutputStreamTest.givenRecordPartWrittenWhenClosedThenThrowsUnderflow()
negated conditional → KILLED

278

1.1
Location : close
Killed by : io.earcam.utilitarian.io.SplittableOutputStreamTest.contentWithOneRecordFitsMaxSizeExactly()
removed call to io/earcam/utilitarian/io/SplittableOutputStream::endSplit → KILLED

279

1.1
Location : close
Killed by : io.earcam.utilitarian.io.SplittableOutputStreamTest.contentWithOneRecordFitsMaxSizeExactly()
changed conditional boundary → KILLED

2.2
Location : close
Killed by : io.earcam.utilitarian.io.SplittableOutputStreamTest.contentWithOneRecordFitsMaxSizeExactly()
negated conditional → KILLED

280

1.1
Location : close
Killed by : io.earcam.utilitarian.io.SplittableOutputStreamTest.regressionEnsureLastRecordWritten()
removed call to io/earcam/utilitarian/io/SplittableOutputStream::writeBuffer → KILLED

281

1.1
Location : close
Killed by : none
removed call to io/earcam/utilitarian/io/SplittableOutputStream::endSplit → SURVIVED

Active mutators

Tests examined


Report generated by PIT 1.4.3