GsmMessageSplitter.java

1
package fr.sii.ogham.sms.splitter;
2
3
import static fr.sii.ogham.sms.SmsConstants.SmppSplitConstants.MAXIMUM_BYTES_PER_MESSAGE;
4
import static java.util.Arrays.asList;
5
6
import java.util.ArrayList;
7
import java.util.List;
8
9
import fr.sii.ogham.sms.SmsConstants.SmppSplitConstants.SegmentSizes;
10
import fr.sii.ogham.sms.encoder.EncodedWithHeader;
11
import fr.sii.ogham.sms.encoder.Encoder;
12
import fr.sii.ogham.sms.exception.message.EncodingException;
13
import fr.sii.ogham.sms.exception.message.InvalidReferenceNumberException;
14
import fr.sii.ogham.sms.exception.message.ReferenceNumberGenerationException;
15
import fr.sii.ogham.sms.exception.message.SplitMessageException;
16
17
/**
18
 * Split the message in segments if needed.
19
 * 
20
 * <p>
21
 * If the size of the unencoded Java {@link String} is less than the provided
22
 * maximum size then no split is done. The result is a list of only one segment
23
 * with the encoded message as byte array.
24
 * 
25
 * <p>
26
 * If the size of the unencoded Java {@link String} is greater than the provided
27
 * maximum size then the message is split. Encoded message byte array is cut to
28
 * fit the provided maximum segment size. The result is a list of segments that
29
 * contains the required headers and the partial byte array.
30
 * 
31
 * <p>
32
 * If the message is split, each segment contains a header and a payload. The
33
 * header follows <a href="https://en.wikipedia.org/wiki/User_Data_Header">User
34
 * Data Header</a> specification.
35
 * 
36
 * <p>
37
 * The specification also allows to use extended table. Even if the encoding
38
 * uses only one octet (GSM 7-bit encoding and GSM 8-bit encoding), the
39
 * characters that are present in the extended table must allocate two octets (1
40
 * for ESC character followed with extended character). That's why this splitter
41
 * may need to use a {@link LengthCounter}. If such a character is present then
42
 * the number of characters that could fit in a segment is decreased by one.
43
 * 
44
 * <p>
45
 * Each segment contains a reference number to identify
46
 * <a href="https://en.wikipedia.org/wiki/Concatenated_SMS">concatenated
47
 * messages</a>. The reference number can be encoded on one or two octets (see
48
 * {@link ReferenceNumberGenerator}). This algorithm supports both reference
49
 * numbers encoded on one or two octets.
50
 * 
51
 * 
52
 * <hr>
53
 * <strong><u>Explanation</u></strong>
54
 * 
55
 * 
56
 * <p>
57
 * <strong>One-octet encoding</strong><br>
58
 * If every character of the original string is encoded on one octet and the
59
 * maximum size for segments is 12 octets. Then the maximum unencoded characters
60
 * that can fit in a single segment is also 12.
61
 * 
62
 * <pre>
63
 * {@code 
64
 * String originalMessage = "Hello World!"
65
 * // Not really encoded, just to explain. 
66
 * // Use back-tick to indicate that it is the octet value of the character
67
 * byte[] encoded = [`H`, `e`, `l`, `l`, `o`, ` ` , `W`, `o`, `r`, `l`, `d`, `!`]
68
 * // The message can fit entirely in a single segment
69
 * ┌───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┐
70
 * │`H`│`e`│`l`│`l`│`o`│` `│`W`│`o`│`r`│`l`│`d`│`!`│
71
 * └───┴───┴───┴───┴───┴───┴───┴───┴───┴───┴───┴───┘
72
 * 
73
 * String originalMessage = "Hello World !!"
74
 * // Not really encoded, just to explain. 
75
 * // Use back-tick to indicate that it is the octet value of the character
76
 * byte[] encoded = [`H`, `e`, `l`, `l`, `o`, ` ` , `W`, `o`, `r`, `l`, `d`, ` `, `!`, `!`]
77
 * // The message can't fit entirely in a single segment so it must be split
78
 * // Header (6 octets) is added on each segment
79
 * // So message is split in 3 segments like this
80
 * ┌───┬───┬───┬───┬───┬───╥───┬───┬───┬───┬───┬───┐
81
 * │#05│#00│#03│#??│ 3 │ 1 ║`H`│`e`│`l`│`l`│`o`│` `│
82
 * └───┴───┴───┴───┴───┴───╨───┴───┴───┴───┴───┴───┘
83
 * ┌───┬───┬───┬───┬───┬───╥───┬───┬───┬───┬───┬───┐
84
 * │#05│#00│#03│#??│ 3 │ 2 ║`W`│`o`│`r`│`l`│`d`│` `│
85
 * └───┴───┴───┴───┴───┴───╨───┴───┴───┴───┴───┴───┘
86
 * ┌───┬───┬───┬───┬───┬───╥───┬───┬───┬───┬───┬───┐
87
 * │#05│#00│#03│#??│ 3 │ 3 ║`!`│`!`│   │   │   │   │
88
 * └───┴───┴───┴───┴───┴───╨───┴───┴───┴───┴───┴───┘
89
 *   │   │   │   │   │   │ 
90
 *   │   │   │   │   │ This segment's number
91
 *   │   │   │   │   │ in the sequence
92
 *   │   │   │   │   │ 
93
 *   │   │   │   │ Total number of 
94
 *   │   │   │   │ segments
95
 *   │   │   │   │ 
96
 *   │   │   │ CSMS reference number
97
 *   │   │   │ Generated by
98
 *   │   │   │ ReferenceNumberGenerator
99
 *   │   │   │ 
100
 *   │   │  Length of the header,
101
 *   │   │  excluding the first two
102
 *   │   │  fields
103
 *   │   │
104
 *   │  Information Element Identifier
105
 *   │
106
 *  Length of User Data Header
107
 * }
108
 * </pre>
109
 * 
110
 * 
111
 * <p>
112
 * <strong>Two-octet encoding</strong><br>
113
 * If every character of the original string is encoded on two octets and the
114
 * maximum size for segments is 12 octets. Then the maximum unencoded characters
115
 * that can fit in a single segment is 6 (12 / 2).
116
 * 
117
 * <pre>
118
 * {@code 
119
 * String originalMessage = "Hello!"
120
 * // Each character is encoded on two octets
121
 * byte[] encoded = [0, 72, 0, 101, 0, 108, 0, 108, 0, 111, 0, 33]
122
 * // The message can fit entirely in a single segment
123
 * ┌───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┐
124
 * │ 0 │72 │ 0 │101│ 0 │108│ 0 │108│ 0 │111│ 0 │33 │
125
 * └───┴───┴───┴───┴───┴───┴───┴───┴───┴───┴───┴───┘
126
 * 
127
 * String originalMessage = "Hello !!"
128
 * // Each character is encoded on two octets
129
 * byte[] encoded = [0, 72, 0, 101, 0, 108, 0, 108, 0, 111, 0, 32, 0, 33, 0, 33]
130
 * // The message can't fit entirely in a single segment so it must be split
131
 * // Header (6 octets) is added on each segment
132
 * // So message is split in 3 segments like this
133
 * ┌───┬───┬───┬───┬───┬───╥───┬───┬───┬───┬───┬───┐
134
 * │#05│#00│#03│#??│ 3 │ 1 ║ 0 │72 │ 0 │101│ 0 │108│
135
 * └───┴───┴───┴───┴───┴───╨───┴───┴───┴───┴───┴───┘
136
 * ┌───┬───┬───┬───┬───┬───╥───┬───┬───┬───┬───┬───┐
137
 * │#05│#00│#03│#??│ 3 │ 2 ║ 0 │108│ 0 │111│ 0 │32 │
138
 * └───┴───┴───┴───┴───┴───╨───┴───┴───┴───┴───┴───┘
139
 * ┌───┬───┬───┬───┬───┬───╥───┬───┬───┬───┬───┬───┐
140
 * │#05│#00│#03│#??│ 3 │ 3 ║ 0 │33 │ 0 │33 │   │   │
141
 * └───┴───┴───┴───┴───┴───╨───┴───┴───┴───┴───┴───┘
142
 *   │   │   │   │   │   │ 
143
 *   │   │   │   │   │ This segment's number
144
 *   │   │   │   │   │ in the sequence
145
 *   │   │   │   │   │ 
146
 *   │   │   │   │ Total number of 
147
 *   │   │   │   │ segments
148
 *   │   │   │   │ 
149
 *   │   │   │ CSMS reference number
150
 *   │   │   │ Generated by
151
 *   │   │   │ ReferenceNumberGenerator
152
 *   │   │   │ 
153
 *   │   │  Length of the header,
154
 *   │   │  excluding the first two
155
 *   │   │  fields
156
 *   │   │
157
 *   │  Information Element Identifier
158
 *   │
159
 *  Length of User Data Header
160
 * }
161
 * </pre>
162
 * 
163
 * <p>
164
 * <strong>7-bits encoding</strong><br>
165
 * If every character of the original string is encoded on 7 bits and the
166
 * maximum size for segments is 14 octets. Then the maximum unencoded characters
167
 * that can fit in a single segment is 16.
168
 * 
169
 * <pre>
170
 * {@code 
171
 * String originalMessage = "aaaaaaaaaaaaaaaa"
172
 * The message can fit entirely in a single segment
173
 * encoded on 7 bits 'a' is: 1100001
174
 * originalMessage encoded on 7 bits is:
175
 *   1100001 1100001 1100001 1100001 1100001 1100001 1100001 1100001 1100001 1100001 1100001 1100001 1100001 1100001 1100001 1100001
176
 * originalMessage packed on 8 bits is (/!\ This is not the real packing algorithm but it is simpler to understand):
177
 *   11000011 10000111 00001110 00011100 00111000 01110000 11100001 11000011 10000111 00001110 00011100 00111000 01110000 11100001
178
 *     #c3      #87      #0e      #1c      #38      #70      #e1       #c3      #87      #0e      #1c      #38      #70      #e1  
179
 * byte[] encoded = [#c3, #87, #0e, #1c, #38, #70, #e1, #c3, #87, #0e, #1c, #38, #70, #e1]
180
 * ┌───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┐
181
 * │#c3│#87│#0e│#1c│#38│#70│#e1│#c3│#87│#0e│#1c│#38│#70│#e1│
182
 * └───┴───┴───┴───┴───┴───┴───┴───┴───┴───┴───┴───┴───┴───┘
183
 * 
184
 * String originalMessage = "aaaaaaaaaaaaaaaabbbb"
185
 * The message can't fit entirely in a single segment so it must be split
186
 * Header (6 octets) is added on each segment 
187
 * so each payload can contain 9 characters: (14 octets - 6 header octets) * 8 bits / 7 bits per char
188
 * originalMessage must be split like this (before encoding):
189
 * ┌─────────┬─────────┬─────────┐
190
 * │aaaaaaaaa│aaaaaaabb│bb       │
191
 * └─────────┴─────────┴─────────┘
192
 *   part1     part2     part3
193
 *   
194
 * encoded on 7 bits 'a' is: 1100001
195
 * encoded on 7 bits 'b' is: 1100010
196
 * part1 encoded on 7 bits is:
197
 *   1100001 1100001 1100001 1100001 1100001 1100001 1100001 1100001 1100001
198
 * part2 encoded on 7 bits is:
199
 *   1100001 1100001 1100001 1100001 1100001 1100001 1100001 1100010 1100010
200
 * part3 encoded on 7 bits is:
201
 *   1100010 1100010
202
 * part1 packed on 8 bits is (/!\ This is not the real packing algorithm but it is simpler to understand):
203
 *   11000011 10000111 00001110 00011100 00111000 01110000 11100001 1100001
204
 *     #c3      #87      #0e      #1c      #38      #70      #e1       #c2   
205
 * part2 packed on 8 bits is (/!\ This is not the real packing algorithm but it is simpler to understand):
206
 *   11000011 10000111 00001110 00011100 00111000 01110000 11100010 1100010
207
 *     #c3      #87      #0e      #1c      #38      #70      #e2       #c4   
208
 * part3 packed on 8 bits is (/!\ This is not the real packing algorithm but it is simpler to understand):
209
 *   11000101 100010
210
 *     #c5      #88
211
 * 
212
 * So message is split in 3 segments like this
213
 * ┌───┬───┬───┬───┬───┬───╥───┬───┬───┬───┬───┬───┬───┬───┐
214
 * │#05│#00│#03│#??│ 3 │ 1 ║#c3│#87│#0e│#1c│#38│#70│#e1│#c2│
215
 * └───┴───┴───┴───┴───┴───╨───┴───┴───┴───┴───┴───┴───┴───┘
216
 * ┌───┬───┬───┬───┬───┬───╥───┬───┬───┬───┬───┬───┬───┬───┐
217
 * │#05│#00│#03│#??│ 3 │ 2 ║#c3│#87│#0e│#1c│#38│#70│#e2│#c4│
218
 * └───┴───┴───┴───┴───┴───╨───┴───┴───┴───┴───┴───┴───┴───┘
219
 * ┌───┬───┬───┬───┬───┬───╥───┬───┬───┬───┬───┬───┬───┬───┐
220
 * │#05│#00│#03│#??│ 3 │ 3 ║#c5│#88│   │   │   │   │   │   │
221
 * └───┴───┴───┴───┴───┴───╨───┴───┴───┴───┴───┴───┴───┴───┘
222
 *   │   │   │   │   │   │ 
223
 *   │   │   │   │   │ This segment's number
224
 *   │   │   │   │   │ in the sequence
225
 *   │   │   │   │   │ 
226
 *   │   │   │   │ Total number of 
227
 *   │   │   │   │ segments
228
 *   │   │   │   │ 
229
 *   │   │   │ CSMS reference number
230
 *   │   │   │ Generated by
231
 *   │   │   │ ReferenceNumberGenerator
232
 *   │   │   │ 
233
 *   │   │  Length of the header,
234
 *   │   │  excluding the first two
235
 *   │   │  fields
236
 *   │   │
237
 *   │  Information Element Identifier
238
 *   │
239
 *  Length of User Data Header
240
 * }
241
 * </pre>
242
 * 
243
 * 
244
 * @author Aurélien Baudet
245
 *
246
 */
247
public class GsmMessageSplitter implements MessageSplitter {
248
	private static final int MAXIMUM_SEGMENTS = 255;
249
	
250
	private static final int USER_DATA_HEADER_SIZE_ONE_BYTE_REFERENCE_NUMBER = 6;
251
	private static final byte UDHIE_HEADER_LENGTH_ONE_BYTE_REFERENCE_NUMBER = 0x05;
252
	private static final byte UDHIE_IDENTIFIER_SAR_ONE_BYTE_REFERENCE_NUMBER = 0x00;
253
	private static final byte UDHIE_SAR_LENGTH_ONE_BYTE_REFERENCE_NUMBER = 0x03;
254
255
	private static final int USER_DATA_HEADER_SIZE_TWO_BYTES_REFERENCE_NUMBER = 7;
256
	private static final byte UDHIE_HEADER_LENGTH_TWO_BYTES_REFERENCE_NUMBER = 0x06;
257
	private static final byte UDHIE_IDENTIFIER_SAR_TWO_BYTES_REFERENCE_NUMBER = 0x08;
258
	private static final byte UDHIE_SAR_LENGTH_TWO_BYTES_REFERENCE_NUMBER = 0x04;
259
260
	private final Encoder encoder;
261
	private final SegmentSizes segmentSizes;
262
	private final ReferenceNumberGenerator referenceNumberGenerator;
263
	private final LengthCounter lengthCounter;
264
265
	/**
266
	 * The splitter uses the {@link Encoder} to encode each segment.
267
	 * 
268
	 * <p>
269
	 * The algorithm compares the length of the Java String (using
270
	 * {@link String#length()} with
271
	 * {@link SegmentSizes#getMaximumStringLengthToFitInASingleSegment()} to
272
	 * check that the whole string can fit in a single segment. If it can't then
273
	 * split is applied. A reference number is generated (using
274
	 * {@link RandomReferenceNumberGenerator}). The algorithm uses
275
	 * {@link SegmentSizes#getMaximumStringLengthPerSegment()} to compute the
276
	 * remaining of characters that can fit in a segment with a header. The size
277
	 * of the header depends on the size of the reference number. Once the
278
	 * string is split in a segment, it is also encoded using {@link Encoder}.
279
	 * 
280
	 * @param encoder
281
	 *            the encoder to encode message
282
	 * @param segmentSizes
283
	 *            the information about size that can fit in one segment
284
	 *            (depends on encoder)
285
	 */
286
	public GsmMessageSplitter(Encoder encoder, SegmentSizes segmentSizes) {
287
		this(encoder, segmentSizes, new RandomReferenceNumberGenerator());
288
	}
289
290
	/**
291
	 * The splitter uses the {@link Encoder} to encode each segment.
292
	 * 
293
	 * <p>
294
	 * The algorithm compares the length of the Java String (using
295
	 * {@link String#length()} with
296
	 * {@link SegmentSizes#getMaximumStringLengthToFitInASingleSegment()} to
297
	 * check that the whole string can fit in a single segment. If it can't then
298
	 * split is applied. A reference number is generated (using
299
	 * {@link ReferenceNumberGenerator}). The algorithm uses
300
	 * {@link SegmentSizes#getMaximumStringLengthPerSegment()} to compute the
301
	 * remaining of characters that can fit in a segment with a header. The size
302
	 * of the header depends on the size of the reference number. Once the
303
	 * string is split in a segment, it is also encoded using {@link Encoder}.
304
	 * 
305
	 * @param encoder
306
	 *            the encoder to encode message
307
	 * @param segmentSizes
308
	 *            the information about size that can fit in one segment
309
	 *            (depends on encoder)
310
	 * @param referenceNumberGenerator
311
	 *            generates reference numbers
312
	 */
313
	public GsmMessageSplitter(Encoder encoder, SegmentSizes segmentSizes, ReferenceNumberGenerator referenceNumberGenerator) {
314
		this(encoder, segmentSizes, referenceNumberGenerator, String::length);
315
	}
316
317
	/**
318
	 * The splitter uses the {@link Encoder} to encode each segment.
319
	 * 
320
	 * <p>
321
	 * The algorithm compares {@link LengthCounter#count(String)} with
322
	 * {@link SegmentSizes#getMaximumStringLengthToFitInASingleSegment()} to
323
	 * check that the whole string can fit in a single segment. If it can't then
324
	 * split is applied. A reference number is generated (using
325
	 * {@link ReferenceNumberGenerator}). The algorithm uses
326
	 * {@link SegmentSizes#getMaximumStringLengthPerSegment()} to compute the
327
	 * remaining of characters that can fit in a segment with a header. The size
328
	 * of the header depends on the size of the reference number. Once the
329
	 * string is split in a segment, it is also encoded using {@link Encoder}.
330
	 * 
331
	 * @param encoder
332
	 *            the encoder to encode message
333
	 * @param segmentSizes
334
	 *            the information about size that can fit in one segment
335
	 *            (depends on encoder)
336
	 * @param referenceNumberGenerator
337
	 *            generates reference numbers
338
	 * @param lengthCounter
339
	 *            used to count the number of characters in the string (some
340
	 *            characters may not have the same size, using extended
341
	 *            character tables for example)
342
	 */
343
	public GsmMessageSplitter(Encoder encoder, SegmentSizes segmentSizes, ReferenceNumberGenerator referenceNumberGenerator, LengthCounter lengthCounter) {
344
		super();
345
		this.encoder = encoder;
346
		this.segmentSizes = segmentSizes;
347
		this.referenceNumberGenerator = referenceNumberGenerator;
348
		this.lengthCounter = lengthCounter;
349
	}
350
351
	@Override
352
	public List<Segment> split(String message) throws SplitMessageException {
353
		int messageLength = lengthCounter.count(message);
354 9 1. split : changed conditional boundary → NO_COVERAGE
2. split : changed conditional boundary → SURVIVED
3. split : negated conditional → NO_COVERAGE
4. split : changed conditional boundary → TIMED_OUT
5. split : negated conditional → TIMED_OUT
6. split : changed conditional boundary → KILLED
7. split : negated conditional → KILLED
8. split : negated conditional → KILLED
9. split : negated conditional → KILLED
		if (messageLength <= segmentSizes.getMaximumStringLengthToFitInASingleSegment()) {
355 5 1. split : replaced return value with Collections.emptyList for fr/sii/ogham/sms/splitter/GsmMessageSplitter::split → NO_COVERAGE
2. split : replaced return value with Collections.emptyList for fr/sii/ogham/sms/splitter/GsmMessageSplitter::split → TIMED_OUT
3. split : replaced return value with Collections.emptyList for fr/sii/ogham/sms/splitter/GsmMessageSplitter::split → KILLED
4. split : replaced return value with Collections.emptyList for fr/sii/ogham/sms/splitter/GsmMessageSplitter::split → KILLED
5. split : replaced return value with Collections.emptyList for fr/sii/ogham/sms/splitter/GsmMessageSplitter::split → KILLED
			return asList(singleSegment(message));
356
		}
357
358
		// generate new reference number
359
		byte[] referenceNumber = generateReferenceNumber(message);
360
		int maximumStringLengthPerSegment = computeMaximumStringLengthPerSegment(referenceNumber);
361
362
		// split into several messages
363 4 1. split : Replaced double division with multiplication → NO_COVERAGE
2. split : Replaced double division with multiplication → KILLED
3. split : Replaced double division with multiplication → KILLED
4. split : Replaced double division with multiplication → KILLED
		int numberOfSegments = (int) Math.ceil(messageLength / (double) maximumStringLengthPerSegment);
364 6 1. split : changed conditional boundary → SURVIVED
2. split : changed conditional boundary → NO_COVERAGE
3. split : negated conditional → NO_COVERAGE
4. split : negated conditional → KILLED
5. split : negated conditional → KILLED
6. split : negated conditional → KILLED
		if (numberOfSegments > MAXIMUM_SEGMENTS) {
365
			throw new SplitMessageException("Can't split the message because the number of segments is greater than 255", message);
366
		}
367
368
		// prepare list for all of the msg segments
369
		List<Segment> segments = new ArrayList<>(numberOfSegments);
370
371
		int start = 0;
372 10 1. split : changed conditional boundary → NO_COVERAGE
2. split : Changed increment from 1 to -1 → NO_COVERAGE
3. split : negated conditional → NO_COVERAGE
4. split : Changed increment from 1 to -1 → TIMED_OUT
5. split : changed conditional boundary → KILLED
6. split : changed conditional boundary → KILLED
7. split : changed conditional boundary → KILLED
8. split : negated conditional → KILLED
9. split : negated conditional → KILLED
10. split : negated conditional → KILLED
		for (int i = 0; i < numberOfSegments; i++) {
373
			String part = cutToFitInSegment(start, message, maximumStringLengthPerSegment);
374 3 1. split : Replaced integer addition with subtraction → NO_COVERAGE
2. split : Replaced integer addition with subtraction → SURVIVED
3. split : Replaced integer addition with subtraction → KILLED
			segments.add(segmentWithHeader(message, part, numberOfSegments, i + 1, referenceNumber));
375 4 1. split : Replaced integer addition with subtraction → NO_COVERAGE
2. split : Replaced integer addition with subtraction → KILLED
3. split : Replaced integer addition with subtraction → KILLED
4. split : Replaced integer addition with subtraction → KILLED
			start += part.length();
376
		}
377 4 1. split : replaced return value with Collections.emptyList for fr/sii/ogham/sms/splitter/GsmMessageSplitter::split → NO_COVERAGE
2. split : replaced return value with Collections.emptyList for fr/sii/ogham/sms/splitter/GsmMessageSplitter::split → KILLED
3. split : replaced return value with Collections.emptyList for fr/sii/ogham/sms/splitter/GsmMessageSplitter::split → KILLED
4. split : replaced return value with Collections.emptyList for fr/sii/ogham/sms/splitter/GsmMessageSplitter::split → KILLED
		return segments;
378
	}
379
380
	private byte[] generateReferenceNumber(String message) throws SplitMessageException {
381
		try {
382
			byte[] referenceNumber = referenceNumberGenerator.generateReferenceNumber();
383 8 1. generateReferenceNumber : negated conditional → NO_COVERAGE
2. generateReferenceNumber : negated conditional → NO_COVERAGE
3. generateReferenceNumber : negated conditional → KILLED
4. generateReferenceNumber : negated conditional → KILLED
5. generateReferenceNumber : negated conditional → KILLED
6. generateReferenceNumber : negated conditional → KILLED
7. generateReferenceNumber : negated conditional → KILLED
8. generateReferenceNumber : negated conditional → KILLED
			if (referenceNumber == null || referenceNumber.length == 0) {
384
				throw new InvalidReferenceNumberException("Generated reference number byte array can't be null or empty", referenceNumber);
385
			}
386 7 1. generateReferenceNumber : changed conditional boundary → NO_COVERAGE
2. generateReferenceNumber : changed conditional boundary → SURVIVED
3. generateReferenceNumber : negated conditional → NO_COVERAGE
4. generateReferenceNumber : changed conditional boundary → KILLED
5. generateReferenceNumber : negated conditional → KILLED
6. generateReferenceNumber : negated conditional → KILLED
7. generateReferenceNumber : negated conditional → KILLED
			if (referenceNumber.length > 2) {
387
				throw new InvalidReferenceNumberException(GsmMessageSplitter.class.getSimpleName() + " only support one byte or two byte reference number length", referenceNumber);
388
			}
389 4 1. generateReferenceNumber : replaced return value with null for fr/sii/ogham/sms/splitter/GsmMessageSplitter::generateReferenceNumber → NO_COVERAGE
2. generateReferenceNumber : replaced return value with null for fr/sii/ogham/sms/splitter/GsmMessageSplitter::generateReferenceNumber → KILLED
3. generateReferenceNumber : replaced return value with null for fr/sii/ogham/sms/splitter/GsmMessageSplitter::generateReferenceNumber → KILLED
4. generateReferenceNumber : replaced return value with null for fr/sii/ogham/sms/splitter/GsmMessageSplitter::generateReferenceNumber → KILLED
			return referenceNumber;
390
		} catch (ReferenceNumberGenerationException e) {
391
			throw new SplitMessageException("Failed to split message due to reference number generation failure", message, e);
392
		}
393
	}
394
395
	private String cutToFitInSegment(int start, String message, int maximumStringLengthPerSegment) {
396 4 1. cutToFitInSegment : Replaced integer addition with subtraction → NO_COVERAGE
2. cutToFitInSegment : Replaced integer addition with subtraction → KILLED
3. cutToFitInSegment : Replaced integer addition with subtraction → KILLED
4. cutToFitInSegment : Replaced integer addition with subtraction → KILLED
		int end = start + maximumStringLengthPerSegment;
397
		String part = message.substring(start, Math.min(message.length(), end));
398
		int lengthOfPart = lengthCounter.count(part);
399 12 1. cutToFitInSegment : changed conditional boundary → NO_COVERAGE
2. cutToFitInSegment : changed conditional boundary → SURVIVED
3. cutToFitInSegment : changed conditional boundary → NO_COVERAGE
4. cutToFitInSegment : negated conditional → NO_COVERAGE
5. cutToFitInSegment : negated conditional → NO_COVERAGE
6. cutToFitInSegment : changed conditional boundary → KILLED
7. cutToFitInSegment : changed conditional boundary → KILLED
8. cutToFitInSegment : changed conditional boundary → KILLED
9. cutToFitInSegment : negated conditional → KILLED
10. cutToFitInSegment : negated conditional → KILLED
11. cutToFitInSegment : negated conditional → KILLED
12. cutToFitInSegment : negated conditional → KILLED
		while (lengthOfPart > maximumStringLengthPerSegment && end > start) {
400 2 1. cutToFitInSegment : Changed increment from -1 to 1 → NO_COVERAGE
2. cutToFitInSegment : Changed increment from -1 to 1 → TIMED_OUT
			end--;
401
			part = message.substring(start, Math.min(message.length(), end));
402
			lengthOfPart = lengthCounter.count(part);
403
		}
404 4 1. cutToFitInSegment : replaced return value with "" for fr/sii/ogham/sms/splitter/GsmMessageSplitter::cutToFitInSegment → NO_COVERAGE
2. cutToFitInSegment : replaced return value with "" for fr/sii/ogham/sms/splitter/GsmMessageSplitter::cutToFitInSegment → KILLED
3. cutToFitInSegment : replaced return value with "" for fr/sii/ogham/sms/splitter/GsmMessageSplitter::cutToFitInSegment → KILLED
4. cutToFitInSegment : replaced return value with "" for fr/sii/ogham/sms/splitter/GsmMessageSplitter::cutToFitInSegment → KILLED
		return part;
405
	}
406
407
	private Segment segmentWithHeader(String wholeMessage, String part, int numberOfSegments, int segmentNumber, byte[] referenceNumber) throws SplitMessageException {
408
		try {
409
			int headerSize = headerSize(referenceNumber);
410
			byte[] header = new byte[headerSize];
411
412 4 1. segmentWithHeader : negated conditional → NO_COVERAGE
2. segmentWithHeader : negated conditional → KILLED
3. segmentWithHeader : negated conditional → KILLED
4. segmentWithHeader : negated conditional → KILLED
			if (referenceNumber.length == 1) {
413
				// Field 1 (1 octet): Length of User Data Header, in this case
414
				// 05.
415
				header[0] = UDHIE_HEADER_LENGTH_ONE_BYTE_REFERENCE_NUMBER;
416
				// Field 2 (1 octet): Information Element Identifier, equal to
417
				// 00 (Concatenated short messages, 8-bit reference number)
418
				header[1] = UDHIE_IDENTIFIER_SAR_ONE_BYTE_REFERENCE_NUMBER;
419
				// Field 3 (1 octet): Length of the header, excluding the first
420
				// two fields; equal to 03 for one byte reference number
421
				header[2] = UDHIE_SAR_LENGTH_ONE_BYTE_REFERENCE_NUMBER;
422
				// Field 4 (1 octet): 00-FF, CSMS reference number, must be same
423
				// for all the SMS parts in the CSMS.
424
				header[3] = referenceNumber[0];
425
				// Field 5 (1 octet): 00-FF, total number of parts. The value
426
				// shall remain constant for every short message which makes up
427
				// the concatenated short message. If the value is zero then the
428
				// receiving entity shall ignore the whole information element
429
				header[4] = (byte) numberOfSegments;
430
				// Field 6 (1 octet): 00-FF, this part's number in the sequence.
431
				// The value shall start at 1 and increment for every short
432
				// message which makes up the concatenated short message. If the
433
				// value is zero or greater than the value in Field 5 then the
434
				// receiving entity shall ignore the whole information element.
435
				// [ETSI Specification: GSM 03.40 Version 5.3.0: July 1996]
436
				header[5] = (byte) segmentNumber;
437
			} else {
438
				// Field 1 (1 octet): Length of User Data Header, in this case
439
				// 06.
440
				header[0] = UDHIE_HEADER_LENGTH_TWO_BYTES_REFERENCE_NUMBER;
441
				// Field 2 (1 octet): Information Element Identifier, equal to
442
				// 08 (Concatenated short messages, 16-bit reference number)
443
				header[1] = UDHIE_IDENTIFIER_SAR_TWO_BYTES_REFERENCE_NUMBER;
444
				// Field 3 (1 octet): Length of the header, excluding the first
445
				// two fields; equal to 04 for one byte reference number
446
				header[2] = UDHIE_SAR_LENGTH_TWO_BYTES_REFERENCE_NUMBER;
447
				// Field 4 (2 octets): 0000-FFFF, CSMS reference number, must be
448
				// same for all the SMS parts in the CSMS.
449
				header[3] = referenceNumber[0];
450
				header[4] = referenceNumber[1];
451
				// Field 6 (1 octet): 00-FF, total number of parts. The value
452
				// shall remain constant for every short message which makes up
453
				// the concatenated short message. If the value is zero then the
454
				// receiving entity shall ignore the whole information element
455
				header[5] = (byte) numberOfSegments;
456
				// Field 7 (1 octet): 00-FF, this part's number in the sequence.
457
				// The value shall start at 1 and increment for every short
458
				// message which makes up the concatenated short message. If the
459
				// value is zero or greater than the value in Field 5 then the
460
				// receiving entity shall ignore the whole information element.
461
				// [ETSI Specification: GSM 03.40 Version 5.3.0: July 1996]
462
				header[6] = (byte) segmentNumber;
463
			}
464
465 4 1. segmentWithHeader : replaced return value with null for fr/sii/ogham/sms/splitter/GsmMessageSplitter::segmentWithHeader → NO_COVERAGE
2. segmentWithHeader : replaced return value with null for fr/sii/ogham/sms/splitter/GsmMessageSplitter::segmentWithHeader → KILLED
3. segmentWithHeader : replaced return value with null for fr/sii/ogham/sms/splitter/GsmMessageSplitter::segmentWithHeader → KILLED
4. segmentWithHeader : replaced return value with null for fr/sii/ogham/sms/splitter/GsmMessageSplitter::segmentWithHeader → KILLED
			return new EncodedSegment(new EncodedWithHeader(header, encoder.encode(part)));
466
		} catch (EncodingException e) {
467
			throw new SplitMessageException("Failed to generate segment for " + part + " (segment " + segmentNumber + "/" + numberOfSegments + ") due to encoding error", wholeMessage, e);
468
		}
469
	}
470
471
	private int computeMaximumStringLengthPerSegment(byte[] referenceNumber) {
472 16 1. computeMaximumStringLengthPerSegment : Replaced integer subtraction with addition → NO_COVERAGE
2. computeMaximumStringLengthPerSegment : Replaced integer multiplication with division → NO_COVERAGE
3. computeMaximumStringLengthPerSegment : Replaced double division with multiplication → NO_COVERAGE
4. computeMaximumStringLengthPerSegment : replaced int return with 0 for fr/sii/ogham/sms/splitter/GsmMessageSplitter::computeMaximumStringLengthPerSegment → NO_COVERAGE
5. computeMaximumStringLengthPerSegment : Replaced integer subtraction with addition → KILLED
6. computeMaximumStringLengthPerSegment : Replaced integer subtraction with addition → KILLED
7. computeMaximumStringLengthPerSegment : Replaced integer subtraction with addition → KILLED
8. computeMaximumStringLengthPerSegment : Replaced integer multiplication with division → KILLED
9. computeMaximumStringLengthPerSegment : Replaced integer multiplication with division → KILLED
10. computeMaximumStringLengthPerSegment : Replaced integer multiplication with division → KILLED
11. computeMaximumStringLengthPerSegment : Replaced double division with multiplication → KILLED
12. computeMaximumStringLengthPerSegment : Replaced double division with multiplication → KILLED
13. computeMaximumStringLengthPerSegment : Replaced double division with multiplication → KILLED
14. computeMaximumStringLengthPerSegment : replaced int return with 0 for fr/sii/ogham/sms/splitter/GsmMessageSplitter::computeMaximumStringLengthPerSegment → KILLED
15. computeMaximumStringLengthPerSegment : replaced int return with 0 for fr/sii/ogham/sms/splitter/GsmMessageSplitter::computeMaximumStringLengthPerSegment → KILLED
16. computeMaximumStringLengthPerSegment : replaced int return with 0 for fr/sii/ogham/sms/splitter/GsmMessageSplitter::computeMaximumStringLengthPerSegment → KILLED
		return (int) Math.floor((MAXIMUM_BYTES_PER_MESSAGE - headerSize(referenceNumber)) * segmentSizes.getMaximumStringLengthToFitInASingleSegment() / (double) MAXIMUM_BYTES_PER_MESSAGE);
473
	}
474
475
	private static int headerSize(byte[] referenceNumber) {
476 8 1. headerSize : negated conditional → NO_COVERAGE
2. headerSize : replaced int return with 0 for fr/sii/ogham/sms/splitter/GsmMessageSplitter::headerSize → NO_COVERAGE
3. headerSize : negated conditional → KILLED
4. headerSize : negated conditional → KILLED
5. headerSize : negated conditional → KILLED
6. headerSize : replaced int return with 0 for fr/sii/ogham/sms/splitter/GsmMessageSplitter::headerSize → KILLED
7. headerSize : replaced int return with 0 for fr/sii/ogham/sms/splitter/GsmMessageSplitter::headerSize → KILLED
8. headerSize : replaced int return with 0 for fr/sii/ogham/sms/splitter/GsmMessageSplitter::headerSize → KILLED
		return referenceNumber.length == 1 ? USER_DATA_HEADER_SIZE_ONE_BYTE_REFERENCE_NUMBER : USER_DATA_HEADER_SIZE_TWO_BYTES_REFERENCE_NUMBER;
477
	}
478
479
	private Segment singleSegment(String message) throws SplitMessageException {
480
		try {
481 5 1. singleSegment : replaced return value with null for fr/sii/ogham/sms/splitter/GsmMessageSplitter::singleSegment → NO_COVERAGE
2. singleSegment : replaced return value with null for fr/sii/ogham/sms/splitter/GsmMessageSplitter::singleSegment → TIMED_OUT
3. singleSegment : replaced return value with null for fr/sii/ogham/sms/splitter/GsmMessageSplitter::singleSegment → KILLED
4. singleSegment : replaced return value with null for fr/sii/ogham/sms/splitter/GsmMessageSplitter::singleSegment → KILLED
5. singleSegment : replaced return value with null for fr/sii/ogham/sms/splitter/GsmMessageSplitter::singleSegment → KILLED
			return new EncodedSegment(encoder.encode(message));
482
		} catch (EncodingException e) {
483
			throw new SplitMessageException("Failed to generate single segment for " + message + " due to encoding error", message, e);
484
		}
485
	}
486
487
}

Mutations

354

1.1
Location : split
Killed by : none
changed conditional boundary → NO_COVERAGE

2.2
Location : split
Killed by : none
changed conditional boundary → SURVIVED

3.3
Location : split
Killed by : oghamcore.it.sms.splitter.GsmMessageSplitterTest
changed conditional boundary → KILLED

4.4
Location : split
Killed by : none
changed conditional boundary → TIMED_OUT

5.5
Location : split
Killed by : oghamcore.it.sms.splitter.GsmMessageSplitterTest
negated conditional → KILLED

6.6
Location : split
Killed by : none
negated conditional → NO_COVERAGE

7.7
Location : split
Killed by : none
negated conditional → TIMED_OUT

8.8
Location : split
Killed by : oghamcloudhopper.it.CloudhopperSmppTest.simple(oghamcloudhopper.it.CloudhopperSmppTest)
negated conditional → KILLED

9.9
Location : split
Killed by : oghamall.it.sms.SmsSMPPGsm7bitTest.longMessage(oghamall.it.sms.SmsSMPPGsm7bitTest)
negated conditional → KILLED

355

1.1
Location : split
Killed by : oghamcore.it.sms.splitter.GsmMessageSplitterTest
replaced return value with Collections.emptyList for fr/sii/ogham/sms/splitter/GsmMessageSplitter::split → KILLED

2.2
Location : split
Killed by : none
replaced return value with Collections.emptyList for fr/sii/ogham/sms/splitter/GsmMessageSplitter::split → NO_COVERAGE

3.3
Location : split
Killed by : oghamall.it.sms.SmsSMPPDefaultsTest.gsm8bitDefaultAlphabet(oghamall.it.sms.SmsSMPPDefaultsTest)
replaced return value with Collections.emptyList for fr/sii/ogham/sms/splitter/GsmMessageSplitter::split → KILLED

4.4
Location : split
Killed by : oghamcloudhopper.it.CloudhopperSmppTest.simple(oghamcloudhopper.it.CloudhopperSmppTest)
replaced return value with Collections.emptyList for fr/sii/ogham/sms/splitter/GsmMessageSplitter::split → KILLED

5.5
Location : split
Killed by : none
replaced return value with Collections.emptyList for fr/sii/ogham/sms/splitter/GsmMessageSplitter::split → TIMED_OUT

363

1.1
Location : split
Killed by : none
Replaced double division with multiplication → NO_COVERAGE

2.2
Location : split
Killed by : oghamall.it.sms.SmsSMPPGsm7bitTest.longMessage(oghamall.it.sms.SmsSMPPGsm7bitTest)
Replaced double division with multiplication → KILLED

3.3
Location : split
Killed by : oghamcore.it.sms.splitter.GsmMessageSplitterTest
Replaced double division with multiplication → KILLED

4.4
Location : split
Killed by : oghamcloudhopper.it.PartialConfigurationTest.splitterEnabledAndAutoGuessEnabledAndGsm7bitEncodingConfiguredAndLongMessageShouldSendTwoMessages(oghamcloudhopper.it.PartialConfigurationTest)
Replaced double division with multiplication → KILLED

364

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

2.2
Location : split
Killed by : none
changed conditional boundary → NO_COVERAGE

3.3
Location : split
Killed by : none
negated conditional → NO_COVERAGE

4.4
Location : split
Killed by : oghamall.it.sms.SmsSMPPGsm7bitTest.longMessage(oghamall.it.sms.SmsSMPPGsm7bitTest)
negated conditional → KILLED

5.5
Location : split
Killed by : oghamcore.it.sms.splitter.GsmMessageSplitterTest
negated conditional → KILLED

6.6
Location : split
Killed by : oghamcloudhopper.it.PartialConfigurationTest.splitterEnabledAndAutoGuessEnabledAndGsm7bitEncodingConfiguredAndLongMessageShouldSendTwoMessages(oghamcloudhopper.it.PartialConfigurationTest)
negated conditional → KILLED

372

1.1
Location : split
Killed by : none
changed conditional boundary → NO_COVERAGE

2.2
Location : split
Killed by : oghamall.it.sms.SmsSMPPGsm7bitTest.longMessage(oghamall.it.sms.SmsSMPPGsm7bitTest)
changed conditional boundary → KILLED

3.3
Location : split
Killed by : oghamcloudhopper.it.PartialConfigurationTest.splitterEnabledAndAutoGuessEnabledAndGsm7bitEncodingConfiguredAndLongMessageShouldSendTwoMessages(oghamcloudhopper.it.PartialConfigurationTest)
changed conditional boundary → KILLED

4.4
Location : split
Killed by : oghamcore.it.sms.splitter.GsmMessageSplitterTest
changed conditional boundary → KILLED

5.5
Location : split
Killed by : none
Changed increment from 1 to -1 → NO_COVERAGE

6.6
Location : split
Killed by : none
Changed increment from 1 to -1 → TIMED_OUT

7.7
Location : split
Killed by : oghamcore.it.sms.splitter.GsmMessageSplitterTest
negated conditional → KILLED

8.8
Location : split
Killed by : none
negated conditional → NO_COVERAGE

9.9
Location : split
Killed by : oghamall.it.sms.SmsSMPPGsm7bitTest.longMessage(oghamall.it.sms.SmsSMPPGsm7bitTest)
negated conditional → KILLED

10.10
Location : split
Killed by : oghamcloudhopper.it.PartialConfigurationTest.splitterEnabledAndAutoGuessEnabledAndGsm7bitEncodingConfiguredAndLongMessageShouldSendTwoMessages(oghamcloudhopper.it.PartialConfigurationTest)
negated conditional → KILLED

374

1.1
Location : split
Killed by : oghamcore.it.sms.splitter.GsmMessageSplitterTest
Replaced integer addition with subtraction → KILLED

2.2
Location : split
Killed by : none
Replaced integer addition with subtraction → NO_COVERAGE

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

375

1.1
Location : split
Killed by : none
Replaced integer addition with subtraction → NO_COVERAGE

2.2
Location : split
Killed by : oghamall.it.sms.SmsSMPPGsm7bitTest.longMessage(oghamall.it.sms.SmsSMPPGsm7bitTest)
Replaced integer addition with subtraction → KILLED

3.3
Location : split
Killed by : oghamcore.it.sms.splitter.GsmMessageSplitterTest
Replaced integer addition with subtraction → KILLED

4.4
Location : split
Killed by : oghamcloudhopper.it.PartialConfigurationTest.splitterEnabledAndAutoGuessEnabledAndGsm7bitEncodingConfiguredAndLongMessageShouldSendTwoMessages(oghamcloudhopper.it.PartialConfigurationTest)
Replaced integer addition with subtraction → KILLED

377

1.1
Location : split
Killed by : oghamcloudhopper.it.PartialConfigurationTest.splitterEnabledAndAutoGuessEnabledAndGsm7bitEncodingConfiguredAndLongMessageShouldSendTwoMessages(oghamcloudhopper.it.PartialConfigurationTest)
replaced return value with Collections.emptyList for fr/sii/ogham/sms/splitter/GsmMessageSplitter::split → KILLED

2.2
Location : split
Killed by : oghamall.it.sms.SmsSMPPGsm7bitTest.longMessage(oghamall.it.sms.SmsSMPPGsm7bitTest)
replaced return value with Collections.emptyList for fr/sii/ogham/sms/splitter/GsmMessageSplitter::split → KILLED

3.3
Location : split
Killed by : none
replaced return value with Collections.emptyList for fr/sii/ogham/sms/splitter/GsmMessageSplitter::split → NO_COVERAGE

4.4
Location : split
Killed by : oghamcore.it.sms.splitter.GsmMessageSplitterTest
replaced return value with Collections.emptyList for fr/sii/ogham/sms/splitter/GsmMessageSplitter::split → KILLED

383

1.1
Location : generateReferenceNumber
Killed by : none
negated conditional → NO_COVERAGE

2.2
Location : generateReferenceNumber
Killed by : oghamcore.it.sms.splitter.GsmMessageSplitterTest
negated conditional → KILLED

3.3
Location : generateReferenceNumber
Killed by : oghamcloudhopper.it.PartialConfigurationTest.splitterEnabledAndAutoGuessEnabledAndGsm7bitEncodingConfiguredAndLongMessageShouldSendTwoMessages(oghamcloudhopper.it.PartialConfigurationTest)
negated conditional → KILLED

4.4
Location : generateReferenceNumber
Killed by : oghamall.it.sms.SmsSMPPGsm7bitTest.longMessage(oghamall.it.sms.SmsSMPPGsm7bitTest)
negated conditional → KILLED

5.5
Location : generateReferenceNumber
Killed by : none
negated conditional → NO_COVERAGE

6.6
Location : generateReferenceNumber
Killed by : oghamcore.it.sms.splitter.GsmMessageSplitterTest
negated conditional → KILLED

7.7
Location : generateReferenceNumber
Killed by : oghamcloudhopper.it.PartialConfigurationTest.splitterEnabledAndAutoGuessEnabledAndGsm7bitEncodingConfiguredAndLongMessageShouldSendTwoMessages(oghamcloudhopper.it.PartialConfigurationTest)
negated conditional → KILLED

8.8
Location : generateReferenceNumber
Killed by : oghamall.it.sms.SmsSMPPGsm7bitTest.longMessage(oghamall.it.sms.SmsSMPPGsm7bitTest)
negated conditional → KILLED

386

1.1
Location : generateReferenceNumber
Killed by : none
changed conditional boundary → NO_COVERAGE

2.2
Location : generateReferenceNumber
Killed by : oghamcore.it.sms.splitter.GsmMessageSplitterTest
changed conditional boundary → KILLED

3.3
Location : generateReferenceNumber
Killed by : none
changed conditional boundary → SURVIVED

4.4
Location : generateReferenceNumber
Killed by : oghamall.it.sms.SmsSMPPGsm7bitTest.longMessage(oghamall.it.sms.SmsSMPPGsm7bitTest)
negated conditional → KILLED

5.5
Location : generateReferenceNumber
Killed by : oghamcloudhopper.it.PartialConfigurationTest.splitterEnabledAndAutoGuessEnabledAndGsm7bitEncodingConfiguredAndLongMessageShouldSendTwoMessages(oghamcloudhopper.it.PartialConfigurationTest)
negated conditional → KILLED

6.6
Location : generateReferenceNumber
Killed by : oghamcore.it.sms.splitter.GsmMessageSplitterTest
negated conditional → KILLED

7.7
Location : generateReferenceNumber
Killed by : none
negated conditional → NO_COVERAGE

389

1.1
Location : generateReferenceNumber
Killed by : none
replaced return value with null for fr/sii/ogham/sms/splitter/GsmMessageSplitter::generateReferenceNumber → NO_COVERAGE

2.2
Location : generateReferenceNumber
Killed by : oghamcore.it.sms.splitter.GsmMessageSplitterTest
replaced return value with null for fr/sii/ogham/sms/splitter/GsmMessageSplitter::generateReferenceNumber → KILLED

3.3
Location : generateReferenceNumber
Killed by : oghamall.it.sms.SmsSMPPGsm7bitTest.longMessage(oghamall.it.sms.SmsSMPPGsm7bitTest)
replaced return value with null for fr/sii/ogham/sms/splitter/GsmMessageSplitter::generateReferenceNumber → KILLED

4.4
Location : generateReferenceNumber
Killed by : oghamcloudhopper.it.PartialConfigurationTest.splitterEnabledAndAutoGuessEnabledAndGsm7bitEncodingConfiguredAndLongMessageShouldSendTwoMessages(oghamcloudhopper.it.PartialConfigurationTest)
replaced return value with null for fr/sii/ogham/sms/splitter/GsmMessageSplitter::generateReferenceNumber → KILLED

396

1.1
Location : cutToFitInSegment
Killed by : oghamall.it.sms.SmsSMPPGsm7bitTest.longMessage(oghamall.it.sms.SmsSMPPGsm7bitTest)
Replaced integer addition with subtraction → KILLED

2.2
Location : cutToFitInSegment
Killed by : none
Replaced integer addition with subtraction → NO_COVERAGE

3.3
Location : cutToFitInSegment
Killed by : oghamcloudhopper.it.PartialConfigurationTest.splitterEnabledAndAutoGuessEnabledAndGsm7bitEncodingConfiguredAndLongMessageShouldSendTwoMessages(oghamcloudhopper.it.PartialConfigurationTest)
Replaced integer addition with subtraction → KILLED

4.4
Location : cutToFitInSegment
Killed by : oghamcore.it.sms.splitter.GsmMessageSplitterTest
Replaced integer addition with subtraction → KILLED

399

1.1
Location : cutToFitInSegment
Killed by : oghamcore.it.sms.splitter.GsmMessageSplitterTest
changed conditional boundary → KILLED

2.2
Location : cutToFitInSegment
Killed by : none
changed conditional boundary → NO_COVERAGE

3.3
Location : cutToFitInSegment
Killed by : oghamcloudhopper.it.PartialConfigurationTest.splitterEnabledAndAutoGuessEnabledAndGsm7bitEncodingConfiguredAndLongMessageShouldSendTwoMessages(oghamcloudhopper.it.PartialConfigurationTest)
changed conditional boundary → KILLED

4.4
Location : cutToFitInSegment
Killed by : oghamall.it.sms.SmsSMPPGsm7bitTest.longMessage(oghamall.it.sms.SmsSMPPGsm7bitTest)
changed conditional boundary → KILLED

5.5
Location : cutToFitInSegment
Killed by : none
changed conditional boundary → SURVIVED

6.6
Location : cutToFitInSegment
Killed by : none
changed conditional boundary → NO_COVERAGE

7.7
Location : cutToFitInSegment
Killed by : oghamcloudhopper.it.PartialConfigurationTest.splitterEnabledAndAutoGuessEnabledAndGsm7bitEncodingConfiguredAndLongMessageShouldSendTwoMessages(oghamcloudhopper.it.PartialConfigurationTest)
negated conditional → KILLED

8.8
Location : cutToFitInSegment
Killed by : oghamcore.it.sms.splitter.GsmMessageSplitterTest
negated conditional → KILLED

9.9
Location : cutToFitInSegment
Killed by : oghamall.it.sms.SmsSMPPGsm7bitTest.longMessage(oghamall.it.sms.SmsSMPPGsm7bitTest)
negated conditional → KILLED

10.10
Location : cutToFitInSegment
Killed by : none
negated conditional → NO_COVERAGE

11.11
Location : cutToFitInSegment
Killed by : oghamcore.it.sms.splitter.GsmMessageSplitterTest
negated conditional → KILLED

12.12
Location : cutToFitInSegment
Killed by : none
negated conditional → NO_COVERAGE

400

1.1
Location : cutToFitInSegment
Killed by : none
Changed increment from -1 to 1 → TIMED_OUT

2.2
Location : cutToFitInSegment
Killed by : none
Changed increment from -1 to 1 → NO_COVERAGE

404

1.1
Location : cutToFitInSegment
Killed by : oghamcore.it.sms.splitter.GsmMessageSplitterTest
replaced return value with "" for fr/sii/ogham/sms/splitter/GsmMessageSplitter::cutToFitInSegment → KILLED

2.2
Location : cutToFitInSegment
Killed by : none
replaced return value with "" for fr/sii/ogham/sms/splitter/GsmMessageSplitter::cutToFitInSegment → NO_COVERAGE

3.3
Location : cutToFitInSegment
Killed by : oghamall.it.sms.SmsSMPPGsm7bitTest.longMessage(oghamall.it.sms.SmsSMPPGsm7bitTest)
replaced return value with "" for fr/sii/ogham/sms/splitter/GsmMessageSplitter::cutToFitInSegment → KILLED

4.4
Location : cutToFitInSegment
Killed by : oghamcloudhopper.it.PartialConfigurationTest.splitterEnabledAndAutoGuessEnabledAndGsm7bitEncodingConfiguredAndLongMessageShouldSendTwoMessages(oghamcloudhopper.it.PartialConfigurationTest)
replaced return value with "" for fr/sii/ogham/sms/splitter/GsmMessageSplitter::cutToFitInSegment → KILLED

412

1.1
Location : segmentWithHeader
Killed by : oghamcore.it.sms.splitter.GsmMessageSplitterTest
negated conditional → KILLED

2.2
Location : segmentWithHeader
Killed by : oghamcloudhopper.it.PartialConfigurationTest.splitterEnabledAndAutoGuessEnabledAndGsm7bitEncodingConfiguredAndLongMessageShouldSendTwoMessages(oghamcloudhopper.it.PartialConfigurationTest)
negated conditional → KILLED

3.3
Location : segmentWithHeader
Killed by : oghamall.it.sms.SmsSMPPGsm7bitTest.longMessage(oghamall.it.sms.SmsSMPPGsm7bitTest)
negated conditional → KILLED

4.4
Location : segmentWithHeader
Killed by : none
negated conditional → NO_COVERAGE

465

1.1
Location : segmentWithHeader
Killed by : oghamcloudhopper.it.PartialConfigurationTest.splitterEnabledAndAutoGuessEnabledAndGsm7bitEncodingConfiguredAndLongMessageShouldSendTwoMessages(oghamcloudhopper.it.PartialConfigurationTest)
replaced return value with null for fr/sii/ogham/sms/splitter/GsmMessageSplitter::segmentWithHeader → KILLED

2.2
Location : segmentWithHeader
Killed by : oghamall.it.sms.SmsSMPPGsm7bitTest.longMessage(oghamall.it.sms.SmsSMPPGsm7bitTest)
replaced return value with null for fr/sii/ogham/sms/splitter/GsmMessageSplitter::segmentWithHeader → KILLED

3.3
Location : segmentWithHeader
Killed by : oghamcore.it.sms.splitter.GsmMessageSplitterTest
replaced return value with null for fr/sii/ogham/sms/splitter/GsmMessageSplitter::segmentWithHeader → KILLED

4.4
Location : segmentWithHeader
Killed by : none
replaced return value with null for fr/sii/ogham/sms/splitter/GsmMessageSplitter::segmentWithHeader → NO_COVERAGE

472

1.1
Location : computeMaximumStringLengthPerSegment
Killed by : oghamall.it.sms.SmsSMPPGsm7bitTest.longMessage(oghamall.it.sms.SmsSMPPGsm7bitTest)
Replaced integer subtraction with addition → KILLED

2.2
Location : computeMaximumStringLengthPerSegment
Killed by : oghamcore.it.sms.splitter.GsmMessageSplitterTest
Replaced integer subtraction with addition → KILLED

3.3
Location : computeMaximumStringLengthPerSegment
Killed by : oghamcloudhopper.it.PartialConfigurationTest.splitterEnabledAndAutoGuessEnabledAndGsm7bitEncodingConfiguredAndLongMessageShouldSendTwoMessages(oghamcloudhopper.it.PartialConfigurationTest)
Replaced integer subtraction with addition → KILLED

4.4
Location : computeMaximumStringLengthPerSegment
Killed by : none
Replaced integer subtraction with addition → NO_COVERAGE

5.5
Location : computeMaximumStringLengthPerSegment
Killed by : oghamall.it.sms.SmsSMPPGsm7bitTest.longMessage(oghamall.it.sms.SmsSMPPGsm7bitTest)
Replaced integer multiplication with division → KILLED

6.6
Location : computeMaximumStringLengthPerSegment
Killed by : oghamcloudhopper.it.PartialConfigurationTest.splitterEnabledAndAutoGuessEnabledAndGsm7bitEncodingConfiguredAndLongMessageShouldSendTwoMessages(oghamcloudhopper.it.PartialConfigurationTest)
Replaced integer multiplication with division → KILLED

7.7
Location : computeMaximumStringLengthPerSegment
Killed by : oghamcore.it.sms.splitter.GsmMessageSplitterTest
Replaced integer multiplication with division → KILLED

8.8
Location : computeMaximumStringLengthPerSegment
Killed by : none
Replaced integer multiplication with division → NO_COVERAGE

9.9
Location : computeMaximumStringLengthPerSegment
Killed by : oghamcloudhopper.it.PartialConfigurationTest.splitterEnabledAndAutoGuessEnabledAndGsm7bitEncodingConfiguredAndLongMessageShouldSendTwoMessages(oghamcloudhopper.it.PartialConfigurationTest)
Replaced double division with multiplication → KILLED

10.10
Location : computeMaximumStringLengthPerSegment
Killed by : oghamall.it.sms.SmsSMPPGsm7bitTest.longMessage(oghamall.it.sms.SmsSMPPGsm7bitTest)
Replaced double division with multiplication → KILLED

11.11
Location : computeMaximumStringLengthPerSegment
Killed by : none
Replaced double division with multiplication → NO_COVERAGE

12.12
Location : computeMaximumStringLengthPerSegment
Killed by : oghamcore.it.sms.splitter.GsmMessageSplitterTest
Replaced double division with multiplication → KILLED

13.13
Location : computeMaximumStringLengthPerSegment
Killed by : none
replaced int return with 0 for fr/sii/ogham/sms/splitter/GsmMessageSplitter::computeMaximumStringLengthPerSegment → NO_COVERAGE

14.14
Location : computeMaximumStringLengthPerSegment
Killed by : oghamall.it.sms.SmsSMPPGsm7bitTest.longMessage(oghamall.it.sms.SmsSMPPGsm7bitTest)
replaced int return with 0 for fr/sii/ogham/sms/splitter/GsmMessageSplitter::computeMaximumStringLengthPerSegment → KILLED

15.15
Location : computeMaximumStringLengthPerSegment
Killed by : oghamcloudhopper.it.PartialConfigurationTest.splitterEnabledAndAutoGuessEnabledAndGsm7bitEncodingConfiguredAndLongMessageShouldSendTwoMessages(oghamcloudhopper.it.PartialConfigurationTest)
replaced int return with 0 for fr/sii/ogham/sms/splitter/GsmMessageSplitter::computeMaximumStringLengthPerSegment → KILLED

16.16
Location : computeMaximumStringLengthPerSegment
Killed by : oghamcore.it.sms.splitter.GsmMessageSplitterTest
replaced int return with 0 for fr/sii/ogham/sms/splitter/GsmMessageSplitter::computeMaximumStringLengthPerSegment → KILLED

476

1.1
Location : headerSize
Killed by : none
negated conditional → NO_COVERAGE

2.2
Location : headerSize
Killed by : oghamall.it.sms.SmsSMPPGsm7bitTest.longMessage(oghamall.it.sms.SmsSMPPGsm7bitTest)
negated conditional → KILLED

3.3
Location : headerSize
Killed by : oghamcore.it.sms.splitter.GsmMessageSplitterTest
negated conditional → KILLED

4.4
Location : headerSize
Killed by : oghamcloudhopper.it.PartialConfigurationTest.splitterEnabledAndAutoGuessEnabledAndGsm7bitEncodingConfiguredAndLongMessageShouldSendTwoMessages(oghamcloudhopper.it.PartialConfigurationTest)
negated conditional → KILLED

5.5
Location : headerSize
Killed by : oghamall.it.sms.SmsSMPPGsm7bitTest.longMessage(oghamall.it.sms.SmsSMPPGsm7bitTest)
replaced int return with 0 for fr/sii/ogham/sms/splitter/GsmMessageSplitter::headerSize → KILLED

6.6
Location : headerSize
Killed by : oghamcloudhopper.it.PartialConfigurationTest.splitterEnabledAndAutoGuessEnabledAndGsm7bitEncodingConfiguredAndLongMessageShouldSendTwoMessages(oghamcloudhopper.it.PartialConfigurationTest)
replaced int return with 0 for fr/sii/ogham/sms/splitter/GsmMessageSplitter::headerSize → KILLED

7.7
Location : headerSize
Killed by : none
replaced int return with 0 for fr/sii/ogham/sms/splitter/GsmMessageSplitter::headerSize → NO_COVERAGE

8.8
Location : headerSize
Killed by : oghamcore.it.sms.splitter.GsmMessageSplitterTest
replaced int return with 0 for fr/sii/ogham/sms/splitter/GsmMessageSplitter::headerSize → KILLED

481

1.1
Location : singleSegment
Killed by : none
replaced return value with null for fr/sii/ogham/sms/splitter/GsmMessageSplitter::singleSegment → TIMED_OUT

2.2
Location : singleSegment
Killed by : none
replaced return value with null for fr/sii/ogham/sms/splitter/GsmMessageSplitter::singleSegment → NO_COVERAGE

3.3
Location : singleSegment
Killed by : oghamall.it.sms.SmsSMPPDefaultsTest.gsm8bitDefaultAlphabet(oghamall.it.sms.SmsSMPPDefaultsTest)
replaced return value with null for fr/sii/ogham/sms/splitter/GsmMessageSplitter::singleSegment → KILLED

4.4
Location : singleSegment
Killed by : oghamcloudhopper.it.CloudhopperSmppTest.simple(oghamcloudhopper.it.CloudhopperSmppTest)
replaced return value with null for fr/sii/ogham/sms/splitter/GsmMessageSplitter::singleSegment → KILLED

5.5
Location : singleSegment
Killed by : oghamcore.it.sms.splitter.GsmMessageSplitterTest
replaced return value with null for fr/sii/ogham/sms/splitter/GsmMessageSplitter::singleSegment → KILLED

Active mutators

Tests examined


Report generated by PIT OGHAM