| 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 addition with subtraction → KILLED 2. <init> : Replaced long subtraction with addition → 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 : replaced boolean return with false for com/renomad/minum/web/Range::equals → KILLED 2. equals : negated conditional → KILLED |
if (this == o) return true; |
| 106 |
3
1. equals : replaced boolean return with true for com/renomad/minum/web/Range::equals → KILLED 2. equals : negated conditional → KILLED 3. equals : negated conditional → KILLED |
if (o == null || getClass() != o.getClass()) return false; |
| 107 | Range range = (Range) o; | |
| 108 |
6
1. equals : negated conditional → KILLED 2. equals : negated conditional → KILLED 3. equals : negated conditional → KILLED 4. equals : replaced boolean return with true for com/renomad/minum/web/Range::equals → KILLED 5. equals : negated conditional → KILLED 6. equals : negated conditional → KILLED |
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 → KILLED |
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 |