Skip to content

Commit 88fbb96

Browse files
committed
Reject blank value, type, or subtype in MediaType
Closes #4895
1 parent 6f4dc82 commit 88fbb96

File tree

3 files changed

+54
-23
lines changed

3 files changed

+54
-23
lines changed

documentation/src/docs/asciidoc/release-notes/release-notes-6.0.0-RC3.adoc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ JUnit repository on GitHub.
5050

5151
* `MediaType` now strips leading and trailing whitespace from a supplied `value`, `type`,
5252
or `subtype`.
53+
* `MediaType` now eagerly rejects a _blank_ `value`, `type`, or `subtype`.
5354

5455

5556
[[release-notes-6.0.0-RC3-junit-vintage]]

junit-jupiter-api/src/main/java/org/junit/jupiter/api/extension/MediaType.java

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939
public final class MediaType {
4040

4141
private static final Pattern PATTERN;
42+
4243
static {
4344
// https://datatracker.ietf.org/doc/html/rfc2045#section-5.1
4445
String whitespace = "[ \t]*";
@@ -94,7 +95,7 @@ public final class MediaType {
9495
* <p>Must be valid according to
9596
* <a href="https://tools.ietf.org/html/rfc2045">RFC 2045</a>.
9697
*
97-
* @param value the media type value to parse; never {@code null}
98+
* @param value the media type value to parse; never {@code null} or blank
9899
* @return the parsed media type
99100
* @throws PreconditionViolationException if the value is not a valid media type
100101
*/
@@ -105,33 +106,33 @@ public static MediaType parse(String value) {
105106
/**
106107
* Create a media type with the given type and subtype.
107108
*
108-
* @param type the type; never {@code null}
109-
* @param subtype the subtype; never {@code null}
109+
* @param type the type; never {@code null} or blank
110+
* @param subtype the subtype; never {@code null} or blank
110111
* @return the media type
111112
*/
112113
public static MediaType create(String type, String subtype) {
113-
Preconditions.notNull(type, "type must not be null");
114-
Preconditions.notNull(subtype, "subtype must not be null");
114+
Preconditions.notBlank(type, "type must not be null or blank");
115+
Preconditions.notBlank(subtype, "subtype must not be null or blank");
115116
return new MediaType(type.strip() + "/" + subtype.strip());
116117
}
117118

118119
/**
119120
* Create a media type with the given type, subtype, and charset.
120121
*
121-
* @param type the type; never {@code null}
122-
* @param subtype the subtype; never {@code null}
122+
* @param type the type; never {@code null} or blank
123+
* @param subtype the subtype; never {@code null} or blank
123124
* @param charset the charset; never {@code null}
124125
* @return the media type
125126
*/
126127
public static MediaType create(String type, String subtype, Charset charset) {
127-
Preconditions.notNull(type, "type must not be null");
128-
Preconditions.notNull(subtype, "subtype must not be null");
128+
Preconditions.notBlank(type, "type must not be null or blank");
129+
Preconditions.notBlank(subtype, "subtype must not be null or blank");
129130
Preconditions.notNull(charset, "charset must not be null");
130131
return new MediaType(type.strip() + "/" + subtype.strip() + "; charset=" + charset.name());
131132
}
132133

133134
private MediaType(String value) {
134-
String strippedValue = Preconditions.notNull(value, "value must not be null").strip();
135+
String strippedValue = Preconditions.notBlank(value, "value must not be null or blank").strip();
135136
Matcher matcher = PATTERN.matcher(strippedValue);
136137
Preconditions.condition(matcher.matches(), () -> "Invalid media type: '" + strippedValue + "'");
137138
this.value = strippedValue;

jupiter-tests/src/test/java/org/junit/jupiter/api/extension/MediaTypeTests.java

Lines changed: 42 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,18 @@
1515
import static org.junit.jupiter.api.EqualsAndHashCodeAssertions.assertEqualsAndHashCode;
1616
import static org.junit.platform.commons.test.PreconditionAssertions.assertPreconditionViolationFor;
1717
import static org.junit.platform.commons.test.PreconditionAssertions.assertPreconditionViolationNotNullFor;
18+
import static org.junit.platform.commons.test.PreconditionAssertions.assertPreconditionViolationNotNullOrBlankFor;
1819

20+
import org.jspecify.annotations.Nullable;
1921
import org.junit.jupiter.api.Nested;
2022
import org.junit.jupiter.api.Test;
2123
import org.junit.jupiter.params.ParameterizedTest;
24+
import org.junit.jupiter.params.provider.NullAndEmptySource;
2225
import org.junit.jupiter.params.provider.ValueSource;
2326

27+
/**
28+
* Unit tests for {@link MediaType}.
29+
*/
2430
class MediaTypeTests {
2531

2632
@Test
@@ -35,14 +41,16 @@ void equals() {
3541
@Nested
3642
class ParseTests {
3743

38-
@Test
39-
@SuppressWarnings("DataFlowIssue") // MediaType.parse() parameter is not @Nullable
40-
void parseWithNullMediaType() {
41-
assertPreconditionViolationNotNullFor("value", () -> MediaType.parse(null));
44+
@ParameterizedTest
45+
@NullAndEmptySource
46+
@ValueSource(strings = { " ", " \t " })
47+
@SuppressWarnings("DataFlowIssue") // MediaType.create() parameters are not @Nullable
48+
void parseWithNullOrBlankMediaType(@Nullable String mediaType) {
49+
assertPreconditionViolationNotNullOrBlankFor("value", () -> MediaType.parse(mediaType));
4250
}
4351

4452
@ParameterizedTest
45-
@ValueSource(strings = { "", " ", "/", " / ", "type", "type/", "/subtype" })
53+
@ValueSource(strings = { "/", " / ", "type", "type/", "/subtype" })
4654
void parseWithInvalidMediaType(String mediaType) {
4755
assertPreconditionViolationFor(() -> MediaType.parse(mediaType))//
4856
.withMessage("Invalid media type: '%s'", mediaType.strip());
@@ -59,16 +67,37 @@ void parse(String value) {
5967
@Nested
6068
class CreateTests {
6169

62-
@Test
70+
@ParameterizedTest
71+
@NullAndEmptySource
72+
@ValueSource(strings = { " ", " \t " })
6373
@SuppressWarnings("DataFlowIssue") // MediaType.create() parameters are not @Nullable
64-
void createWithNullType() {
65-
assertPreconditionViolationNotNullFor("type", () -> MediaType.create(null, "json"));
74+
void createWithNullOrBlankType(@Nullable String type) {
75+
assertPreconditionViolationNotNullOrBlankFor("type", () -> MediaType.create(type, "json"));
6676
}
6777

68-
@Test
78+
@ParameterizedTest
79+
@NullAndEmptySource
80+
@ValueSource(strings = { " ", " \t " })
81+
@SuppressWarnings("DataFlowIssue") // MediaType.create() parameters are not @Nullable
82+
void createWithNullOrBlankTypeAndCharset(@Nullable String type) {
83+
assertPreconditionViolationNotNullOrBlankFor("type", () -> MediaType.create(type, "json", UTF_8));
84+
}
85+
86+
@ParameterizedTest
87+
@NullAndEmptySource
88+
@ValueSource(strings = { " ", " \t " })
89+
@SuppressWarnings("DataFlowIssue") // MediaType.create() parameters are not @Nullable
90+
void createWithNullOrBlankSubtype(@Nullable String subtype) {
91+
assertPreconditionViolationNotNullOrBlankFor("subtype", () -> MediaType.create("application", subtype));
92+
}
93+
94+
@ParameterizedTest
95+
@NullAndEmptySource
96+
@ValueSource(strings = { " ", " \t " })
6997
@SuppressWarnings("DataFlowIssue") // MediaType.create() parameters are not @Nullable
70-
void createWithNullSubtype() {
71-
assertPreconditionViolationNotNullFor("subtype", () -> MediaType.create("json", null));
98+
void createWithNullOrBlankSubtypeAndCharset(@Nullable String subtype) {
99+
assertPreconditionViolationNotNullOrBlankFor("subtype",
100+
() -> MediaType.create("application", subtype, UTF_8));
72101
}
73102

74103
@Test
@@ -78,14 +107,14 @@ void createWithNullCharset() {
78107
}
79108

80109
@ParameterizedTest
81-
@ValueSource(strings = { "", " ", "/", " / ", "type/", "/subtype" })
110+
@ValueSource(strings = { "/", " / ", "type/", "/subtype" })
82111
void createWithInvalidType(String type) {
83112
assertPreconditionViolationFor(() -> MediaType.create(type, "json"))//
84113
.withMessage("Invalid media type: '%s/json'", type.strip());
85114
}
86115

87116
@ParameterizedTest
88-
@ValueSource(strings = { "", " ", "/", " / ", "type/", "/subtype" })
117+
@ValueSource(strings = { "/", " / ", "type/", "/subtype" })
89118
void createWithInvalidSubtype(String subtype) {
90119
assertPreconditionViolationFor(() -> MediaType.create("application", subtype))//
91120
.withMessage("Invalid media type: 'application/%s'", subtype.strip());

0 commit comments

Comments
 (0)