Skip to content

Commit 4424dff

Browse files
authored
Migrate Protobuf extension tests to JUnit 5 (#18392)
* Switch to latest protobuf v3 Can't switch to v4 yet since confluent < 8.x uses the v3 libraries too. Might as well switch them all together when bumping to Kafka v4. * Migrate to JUnit5 * Fix tests * More cleanup * Adjust license version * Update correct license * Remove old protobuf suppression
1 parent de00f5b commit 4424dff

10 files changed

+267
-190
lines changed

extensions-core/protobuf-extensions/pom.xml

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -167,8 +167,23 @@
167167

168168
<!-- test -->
169169
<dependency>
170-
<groupId>junit</groupId>
171-
<artifactId>junit</artifactId>
170+
<groupId>org.junit.jupiter</groupId>
171+
<artifactId>junit-jupiter</artifactId>
172+
<scope>test</scope>
173+
</dependency>
174+
<dependency>
175+
<groupId>org.junit.jupiter</groupId>
176+
<artifactId>junit-jupiter-api</artifactId>
177+
<scope>test</scope>
178+
</dependency>
179+
<dependency>
180+
<groupId>org.junit.jupiter</groupId>
181+
<artifactId>junit-jupiter-engine</artifactId>
182+
<scope>test</scope>
183+
</dependency>
184+
<dependency>
185+
<groupId>org.junit.jupiter</groupId>
186+
<artifactId>junit-jupiter-params</artifactId>
172187
<scope>test</scope>
173188
</dependency>
174189
<dependency>
@@ -188,11 +203,6 @@
188203
<type>test-jar</type>
189204
<scope>test</scope>
190205
</dependency>
191-
<dependency>
192-
<groupId>nl.jqno.equalsverifier</groupId>
193-
<artifactId>equalsverifier</artifactId>
194-
<scope>test</scope>
195-
</dependency>
196206
</dependencies>
197207

198208
<build>

extensions-core/protobuf-extensions/src/test/java/org/apache/druid/data/input/protobuf/FileBasedProtobufBytesDecoderTest.java

Lines changed: 74 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -19,78 +19,111 @@
1919

2020
package org.apache.druid.data.input.protobuf;
2121

22-
import com.google.protobuf.Descriptors;
23-
import nl.jqno.equalsverifier.EqualsVerifier;
2422
import org.apache.druid.java.util.common.parsers.ParseException;
25-
import org.junit.Rule;
26-
import org.junit.Test;
27-
import org.junit.rules.ExpectedException;
23+
import org.junit.jupiter.api.Test;
24+
25+
import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
26+
import static org.junit.jupiter.api.Assertions.assertEquals;
27+
import static org.junit.jupiter.api.Assertions.assertNotEquals;
28+
import static org.junit.jupiter.api.Assertions.assertThrows;
2829

2930
public class FileBasedProtobufBytesDecoderTest
3031
{
31-
@Rule
32-
public ExpectedException expectedException = ExpectedException.none();
33-
32+
/**
33+
* Configure parser with desc file, and specify which file name to use.
34+
*/
3435
@Test
3536
public void testShortMessageType()
3637
{
37-
//configure parser with desc file, and specify which file name to use
38-
@SuppressWarnings("unused") // expected to create parser without exception
39-
FileBasedProtobufBytesDecoder decoder = new FileBasedProtobufBytesDecoder("prototest.desc", "ProtoTestEvent");
40-
decoder.initDescriptor();
38+
final var decoder = new FileBasedProtobufBytesDecoder("prototest.desc", "ProtoTestEvent");
39+
40+
assertDoesNotThrow(decoder::initDescriptor);
4141
}
4242

43+
/**
44+
* Configure parser with desc file, and specify which file name to use
45+
*/
4346
@Test
4447
public void testLongMessageType()
4548
{
46-
//configure parser with desc file, and specify which file name to use
47-
@SuppressWarnings("unused") // expected to create parser without exception
48-
FileBasedProtobufBytesDecoder decoder = new FileBasedProtobufBytesDecoder("prototest.desc", "prototest.ProtoTestEvent");
49-
decoder.initDescriptor();
49+
final var decoder = new FileBasedProtobufBytesDecoder(
50+
"prototest.desc",
51+
"prototest.ProtoTestEvent"
52+
);
53+
54+
assertDoesNotThrow(decoder::initDescriptor);
5055
}
5156

52-
@Test(expected = ParseException.class)
57+
@Test
5358
public void testBadProto()
5459
{
55-
//configure parser with desc file
56-
@SuppressWarnings("unused") // expected exception
57-
FileBasedProtobufBytesDecoder decoder = new FileBasedProtobufBytesDecoder("prototest.desc", "BadName");
58-
decoder.initDescriptor();
60+
assertThrows(
61+
ParseException.class,
62+
() -> {
63+
// configure parser with desc file
64+
final var decoder = new FileBasedProtobufBytesDecoder("prototest.desc", "BadName");
65+
decoder.initDescriptor();
66+
}
67+
);
5968
}
6069

61-
@Test(expected = ParseException.class)
70+
@Test
6271
public void testMalformedDescriptorUrl()
6372
{
64-
//configure parser with non existent desc file
65-
@SuppressWarnings("unused") // expected exception
66-
FileBasedProtobufBytesDecoder decoder = new FileBasedProtobufBytesDecoder("file:/nonexist.desc", "BadName");
67-
decoder.initDescriptor();
73+
assertThrows(
74+
ParseException.class,
75+
() -> {
76+
// configure parser with non existent desc file
77+
final var decoder = new FileBasedProtobufBytesDecoder("file:/nonexist.desc", "BadName");
78+
decoder.initDescriptor();
79+
}
80+
);
6881
}
6982

83+
/**
84+
* For the backward compatibility, protoMessageType allows null when the desc file has only one message type.
85+
*/
7086
@Test
7187
public void testSingleDescriptorNoMessageType()
7288
{
73-
// For the backward compatibility, protoMessageType allows null when the desc file has only one message type.
74-
@SuppressWarnings("unused") // expected to create parser without exception
75-
FileBasedProtobufBytesDecoder decoder = new FileBasedProtobufBytesDecoder("prototest.desc", null);
76-
decoder.initDescriptor();
89+
final var decoder = new FileBasedProtobufBytesDecoder("prototest.desc", null);
90+
91+
assertDoesNotThrow(decoder::initDescriptor);
7792
}
7893

7994
@Test
8095
public void testEquals()
8196
{
82-
FileBasedProtobufBytesDecoder decoder = new FileBasedProtobufBytesDecoder("prototest.desc", "ProtoTestEvent");
83-
decoder.initDescriptor();
84-
Descriptors.Descriptor descriptorA = decoder.getDescriptor();
97+
// Test basic equality
98+
final var decoder1 = new FileBasedProtobufBytesDecoder(
99+
"prototest.desc",
100+
"ProtoTestEvent"
101+
);
102+
final var decoder2 = new FileBasedProtobufBytesDecoder(
103+
"prototest.desc",
104+
"ProtoTestEvent"
105+
);
106+
final var decoder3 = new FileBasedProtobufBytesDecoder(
107+
"prototest.desc",
108+
"ProtoTestEvent.Foo"
109+
);
110+
final var decoder4 = new FileBasedProtobufBytesDecoder(
111+
"prototest.desc",
112+
null
113+
);
114+
115+
// Symmetry: x.equals(y) == y.equals(x)
116+
assertEquals(decoder1, decoder2);
117+
assertEquals(decoder2, decoder1);
85118

86-
decoder = new FileBasedProtobufBytesDecoder("prototest.desc", "ProtoTestEvent.Foo");
87-
decoder.initDescriptor();
88-
Descriptors.Descriptor descriptorB = decoder.getDescriptor();
119+
// Inequality tests
120+
assertNotEquals(decoder1, decoder3); // different protoMessageType (short vs long form)
121+
assertNotEquals(decoder1, decoder4); // different protoMessageType (non-null vs null)
122+
assertNotEquals(null, decoder1);
89123

90-
EqualsVerifier.forClass(FileBasedProtobufBytesDecoder.class)
91-
.usingGetClass()
92-
.withIgnoredFields("descriptor")
93-
.withPrefabValues(Descriptors.Descriptor.class, descriptorA, descriptorB)
94-
.verify();
124+
// HashCode consistency
125+
assertEquals(decoder1.hashCode(), decoder2.hashCode());
126+
assertNotEquals(decoder1.hashCode(), decoder3.hashCode());
127+
assertNotEquals(decoder1.hashCode(), decoder4.hashCode());
95128
}
96129
}

extensions-core/protobuf-extensions/src/test/java/org/apache/druid/data/input/protobuf/InlineDescriptorProtobufBytesDecoderTest.java

Lines changed: 87 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -20,104 +20,145 @@
2020
package org.apache.druid.data.input.protobuf;
2121

2222
import com.google.common.io.Files;
23-
import com.google.protobuf.Descriptors;
24-
import nl.jqno.equalsverifier.EqualsVerifier;
2523
import org.apache.druid.java.util.common.IAE;
2624
import org.apache.druid.java.util.common.StringUtils;
2725
import org.apache.druid.java.util.common.parsers.ParseException;
28-
import org.junit.Before;
29-
import org.junit.Test;
26+
import org.junit.jupiter.api.BeforeEach;
27+
import org.junit.jupiter.api.Test;
3028

3129
import java.io.File;
30+
import java.net.URL;
31+
32+
import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
33+
import static org.junit.jupiter.api.Assertions.assertEquals;
34+
import static org.junit.jupiter.api.Assertions.assertNotEquals;
35+
import static org.junit.jupiter.api.Assertions.assertNotNull;
36+
import static org.junit.jupiter.api.Assertions.assertThrows;
3237

3338
public class InlineDescriptorProtobufBytesDecoderTest
3439
{
3540
private String descString;
3641

37-
@Before
42+
@BeforeEach
3843
public void initDescriptorString() throws Exception
3944
{
40-
File descFile = new File(this.getClass()
41-
.getClassLoader()
42-
.getResource("prototest.desc")
43-
.toURI());
45+
final URL resource = this.getClass()
46+
.getClassLoader()
47+
.getResource("prototest.desc");
48+
assertNotNull(resource);
49+
50+
final var descFile = new File(resource.toURI());
4451
descString = StringUtils.encodeBase64String(Files.toByteArray(descFile));
4552
}
4653

4754
@Test
4855
public void testShortMessageType()
4956
{
50-
@SuppressWarnings("unused") // expected to create parser without exception
51-
InlineDescriptorProtobufBytesDecoder decoder = new InlineDescriptorProtobufBytesDecoder(
57+
final var decoder = new InlineDescriptorProtobufBytesDecoder(
5258
descString,
5359
"ProtoTestEvent"
5460
);
55-
decoder.initDescriptor();
61+
62+
assertDoesNotThrow(decoder::initDescriptor);
5663
}
5764

5865
@Test
5966
public void testLongMessageType()
6067
{
61-
@SuppressWarnings("unused") // expected to create parser without exception
62-
InlineDescriptorProtobufBytesDecoder decoder = new InlineDescriptorProtobufBytesDecoder(
68+
final var decoder = new InlineDescriptorProtobufBytesDecoder(
6369
descString,
6470
"prototest.ProtoTestEvent"
6571
);
66-
decoder.initDescriptor();
72+
73+
assertDoesNotThrow(decoder::initDescriptor);
6774
}
6875

69-
@Test(expected = ParseException.class)
76+
@Test
7077
public void testBadProto()
7178
{
72-
@SuppressWarnings("unused") // expected exception
73-
InlineDescriptorProtobufBytesDecoder decoder = new InlineDescriptorProtobufBytesDecoder(descString, "BadName");
74-
decoder.initDescriptor();
79+
assertThrows(
80+
ParseException.class,
81+
() -> {
82+
final var decoder = new InlineDescriptorProtobufBytesDecoder(descString, "BadName");
83+
84+
decoder.initDescriptor();
85+
}
86+
);
7587
}
7688

77-
@Test(expected = IAE.class)
89+
@Test
7890
public void testMalformedDescriptorBase64()
7991
{
80-
@SuppressWarnings("unused") // expected exception
81-
InlineDescriptorProtobufBytesDecoder decoder = new InlineDescriptorProtobufBytesDecoder("invalidString", "BadName");
82-
decoder.initDescriptor();
92+
assertThrows(
93+
IAE.class,
94+
() -> {
95+
final var decoder = new InlineDescriptorProtobufBytesDecoder("invalidString", "BadName");
96+
97+
decoder.initDescriptor();
98+
}
99+
);
83100
}
84101

85-
@Test(expected = ParseException.class)
102+
@Test
86103
public void testMalformedDescriptorValidBase64InvalidDescriptor()
87104
{
88-
@SuppressWarnings("unused") // expected exception
89-
InlineDescriptorProtobufBytesDecoder decoder = new InlineDescriptorProtobufBytesDecoder(
90-
"aGVsbG8gd29ybGQ=",
91-
"BadName"
105+
assertThrows(
106+
ParseException.class,
107+
() -> {
108+
final var decoder = new InlineDescriptorProtobufBytesDecoder(
109+
"aGVsbG8gd29ybGQ=",
110+
"BadName"
111+
);
112+
113+
decoder.initDescriptor();
114+
}
92115
);
93-
decoder.initDescriptor();
94116
}
95117

118+
/**
119+
* For the backward compatibility, protoMessageType allows null when the desc file has only one message type.
120+
*/
96121
@Test
97122
public void testSingleDescriptorNoMessageType()
98123
{
99-
// For the backward compatibility, protoMessageType allows null when the desc file has only one message type.
100-
@SuppressWarnings("unused") // expected to create parser without exception
101-
InlineDescriptorProtobufBytesDecoder decoder = new InlineDescriptorProtobufBytesDecoder(descString, null);
102-
decoder.initDescriptor();
124+
final var decoder = new InlineDescriptorProtobufBytesDecoder(descString, null);
125+
assertDoesNotThrow(decoder::initDescriptor);
103126
}
104127

105128
@Test
106129
public void testEquals()
107130
{
108-
InlineDescriptorProtobufBytesDecoder decoder = new InlineDescriptorProtobufBytesDecoder(descString, "ProtoTestEvent");
109-
decoder.initDescriptor();
110-
Descriptors.Descriptor descriptorA = decoder.getDescriptor();
111-
112-
decoder = new InlineDescriptorProtobufBytesDecoder(descString, "ProtoTestEvent.Foo");
113-
decoder.initDescriptor();
114-
Descriptors.Descriptor descriptorB = decoder.getDescriptor();
115-
116-
EqualsVerifier.forClass(InlineDescriptorProtobufBytesDecoder.class)
117-
.usingGetClass()
118-
.withIgnoredFields("descriptor")
119-
.withPrefabValues(Descriptors.Descriptor.class, descriptorA, descriptorB)
120-
.verify();
131+
// Test basic equality
132+
final var decoder1 = new InlineDescriptorProtobufBytesDecoder(
133+
descString,
134+
"ProtoTestEvent"
135+
);
136+
final var decoder2 = new InlineDescriptorProtobufBytesDecoder(
137+
descString,
138+
"ProtoTestEvent"
139+
);
140+
final var decoder3 = new InlineDescriptorProtobufBytesDecoder(
141+
descString,
142+
"ProtoTestEvent.Foo"
143+
);
144+
final var decoder4 = new InlineDescriptorProtobufBytesDecoder(
145+
descString,
146+
null
147+
);
148+
149+
// Symmetry: x.equals(y) == y.equals(x)
150+
assertEquals(decoder1, decoder2);
151+
assertEquals(decoder2, decoder1);
152+
153+
// Inequality tests
154+
assertNotEquals(decoder1, decoder3); // different protoMessageType
155+
assertNotEquals(decoder1, decoder4); // different protoMessageType (non-null vs null)
156+
assertNotEquals(null, decoder1);
157+
158+
// HashCode consistency
159+
assertEquals(decoder1.hashCode(), decoder2.hashCode());
160+
assertNotEquals(decoder1.hashCode(), decoder3.hashCode());
161+
assertNotEquals(decoder1.hashCode(), decoder4.hashCode());
121162
}
122163

123164
}

0 commit comments

Comments
 (0)