1 | package com.renomad.minum.web; | |
2 | ||
3 | import java.util.List; | |
4 | import java.util.Objects; | |
5 | import java.util.regex.Matcher; | |
6 | import java.util.regex.Pattern; | |
7 | ||
8 | final class Range { | |
9 | ||
10 | private static final Pattern rangeHeaderPattern = Pattern.compile("^bytes=(?<first>[0-9]{0,13})-(?<second>[0-9]{0,13})$"); | |
11 | private final Long rangeFirstPart; | |
12 | private final Long rangeSecondPart; | |
13 | private final Long length; | |
14 | private final Long offset; | |
15 | private final boolean hasRangeHeader; | |
16 | ||
17 | public Range(Headers requestHeaders, long fullLength) { | |
18 | List<String> rangeHeaders = requestHeaders.valueByKey("range"); | |
19 |
1
1. <init> : negated conditional → KILLED |
if (rangeHeaders == null) { |
20 | hasRangeHeader = false; | |
21 | rangeFirstPart = null; | |
22 | rangeSecondPart = null; | |
23 | length = fullLength; | |
24 | offset = 0L; | |
25 | } else { | |
26 | hasRangeHeader = true; | |
27 |
2
1. <init> : negated conditional → KILLED 2. <init> : changed conditional boundary → KILLED |
if (rangeHeaders.size() > 1) { |
28 | throw new InvalidRangeException("Error: Request contained more than one Range header"); | |
29 | } | |
30 | // the "Range:" header provides a desired range, and can request multiple ranges. | |
31 | // this server does not currently handle multiple ranges, so if that is requested we | |
32 | // will ignore the range header and return a 200 with the entire contents. | |
33 | Matcher matcher = rangeHeaderPattern.matcher(rangeHeaders.getFirst()); | |
34 |
1
1. <init> : negated conditional → KILLED |
if (matcher.matches()) { |
35 | String firstPart = matcher.group("first"); | |
36 | String secondPart = matcher.group("second"); | |
37 | ||
38 |
1
1. <init> : negated conditional → KILLED |
if (!firstPart.isEmpty()) { |
39 | rangeFirstPart = Long.parseLong(firstPart); | |
40 | } else { | |
41 | rangeFirstPart = null; | |
42 | } | |
43 | ||
44 |
1
1. <init> : negated conditional → KILLED |
if (!secondPart.isEmpty()) { |
45 | rangeSecondPart = Long.parseLong(secondPart); | |
46 | } else { | |
47 | rangeSecondPart = null; | |
48 | } | |
49 | ||
50 | // options | |
51 | // 1: there's a first and second part | |
52 | // 2: only a second part | |
53 | // 3: only a first part | |
54 | // 4: (invalid) the first part is larger than the second part | |
55 | // 5: (invalid) either of the range values are invalid longs | |
56 |
2
1. <init> : negated conditional → KILLED 2. <init> : negated conditional → KILLED |
if (rangeFirstPart != null && rangeSecondPart != null) { |
57 |
2
1. <init> : changed conditional boundary → SURVIVED 2. <init> : negated conditional → KILLED |
if (rangeFirstPart > rangeSecondPart) { |
58 | throw new InvalidRangeException("Error: The value of the first part of the range was larger than the second."); | |
59 | } else { | |
60 |
2
1. <init> : Replaced long subtraction with addition → TIMED_OUT 2. <init> : Replaced long addition with subtraction → KILLED |
length = (rangeSecondPart - rangeFirstPart) + 1; |
61 | offset = rangeFirstPart; | |
62 | } | |
63 |
1
1. <init> : negated conditional → KILLED |
} else if (rangeFirstPart != null) { |
64 | offset = rangeFirstPart; | |
65 |
1
1. <init> : Replaced long subtraction with addition → KILLED |
length = fullLength - offset; |
66 |
1
1. <init> : negated conditional → KILLED |
} else if (rangeSecondPart != null) { |
67 |
1
1. <init> : Replaced long subtraction with addition → KILLED |
offset = fullLength - rangeSecondPart; |
68 | length = rangeSecondPart; | |
69 | } else { | |
70 | length = fullLength; | |
71 | offset = 0L; | |
72 | } | |
73 | ||
74 | } else { | |
75 | rangeFirstPart = null; | |
76 | rangeSecondPart = null; | |
77 | length = fullLength; | |
78 | offset = 0L; | |
79 | } | |
80 | } | |
81 | } | |
82 | ||
83 | public Long getRangeFirstPart() { | |
84 |
1
1. getRangeFirstPart : replaced Long return value with 0L for com/renomad/minum/web/Range::getRangeFirstPart → KILLED |
return rangeFirstPart; |
85 | } | |
86 | ||
87 | public Long getRangeSecondPart() { | |
88 |
1
1. getRangeSecondPart : replaced Long return value with 0L for com/renomad/minum/web/Range::getRangeSecondPart → KILLED |
return rangeSecondPart; |
89 | } | |
90 | ||
91 | public Long getLength() { | |
92 |
1
1. getLength : replaced Long return value with 0L for com/renomad/minum/web/Range::getLength → KILLED |
return length; |
93 | } | |
94 | ||
95 | public Long getOffset() { | |
96 |
1
1. getOffset : replaced Long return value with 0L for com/renomad/minum/web/Range::getOffset → KILLED |
return offset; |
97 | } | |
98 | ||
99 | public boolean hasRangeHeader() { | |
100 |
2
1. hasRangeHeader : replaced boolean return with true for com/renomad/minum/web/Range::hasRangeHeader → KILLED 2. hasRangeHeader : replaced boolean return with false for com/renomad/minum/web/Range::hasRangeHeader → KILLED |
return hasRangeHeader; |
101 | } | |
102 | ||
103 | @Override | |
104 | public boolean equals(Object o) { | |
105 |
2
1. equals : negated conditional → TIMED_OUT 2. equals : replaced boolean return with false for com/renomad/minum/web/Range::equals → KILLED |
if (this == o) return true; |
106 |
3
1. equals : replaced boolean return with true for com/renomad/minum/web/Range::equals → TIMED_OUT 2. equals : negated conditional → TIMED_OUT 3. equals : negated conditional → KILLED |
if (o == null || getClass() != o.getClass()) return false; |
107 | Range range = (Range) o; | |
108 |
6
1. equals : negated conditional → TIMED_OUT 2. equals : negated conditional → TIMED_OUT 3. equals : negated conditional → TIMED_OUT 4. equals : replaced boolean return with true for com/renomad/minum/web/Range::equals → TIMED_OUT 5. equals : negated conditional → TIMED_OUT 6. equals : negated conditional → TIMED_OUT |
return hasRangeHeader == range.hasRangeHeader && Objects.equals(rangeFirstPart, range.rangeFirstPart) && Objects.equals(rangeSecondPart, range.rangeSecondPart) && Objects.equals(length, range.length) && Objects.equals(offset, range.offset); |
109 | } | |
110 | ||
111 | @Override | |
112 | public int hashCode() { | |
113 |
1
1. hashCode : replaced int return with 0 for com/renomad/minum/web/Range::hashCode → TIMED_OUT |
return Objects.hash(rangeFirstPart, rangeSecondPart, length, offset, hasRangeHeader); |
114 | } | |
115 | ||
116 | @Override | |
117 | public String toString() { | |
118 |
1
1. toString : replaced return value with "" for com/renomad/minum/web/Range::toString → KILLED |
return "Range{" + |
119 | "rangeFirstPart=" + rangeFirstPart + | |
120 | ", rangeSecondPart=" + rangeSecondPart + | |
121 | ", length=" + length + | |
122 | ", offset=" + offset + | |
123 | ", hasRangeHeader=" + hasRangeHeader + | |
124 | '}'; | |
125 | } | |
126 | } | |
Mutations | ||
19 |
1.1 |
|
27 |
1.1 2.2 |
|
34 |
1.1 |
|
38 |
1.1 |
|
44 |
1.1 |
|
56 |
1.1 2.2 |
|
57 |
1.1 2.2 |
|
60 |
1.1 2.2 |
|
63 |
1.1 |
|
65 |
1.1 |
|
66 |
1.1 |
|
67 |
1.1 |
|
84 |
1.1 |
|
88 |
1.1 |
|
92 |
1.1 |
|
96 |
1.1 |
|
100 |
1.1 2.2 |
|
105 |
1.1 2.2 |
|
106 |
1.1 2.2 3.3 |
|
108 |
1.1 2.2 3.3 4.4 5.5 6.6 |
|
113 |
1.1 |
|
118 |
1.1 |