Skip to content

Commit 20f2768

Browse files
committed
Update Java 17 test class ...
- samples only for standard features - markdown javadoc for JEPs - move sealed classes test to Java 17 - extend tests
1 parent aa34de3 commit 20f2768

File tree

4 files changed

+127
-84
lines changed

4 files changed

+127
-84
lines changed
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
package pl.mperor.lab.java.sealed;
2+
3+
public record ImplicitlyFinal() implements Sealed {
4+
5+
public String implicitlyFinalMethod() {
6+
return "implicitly final";
7+
}
8+
}

src/main/java/pl/mperor/lab/java/sealed/Sealed.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
package pl.mperor.lab.java.sealed;
22

3-
public sealed interface Sealed permits AlsoSealed, Final, NonSealed {
3+
public sealed interface Sealed permits AlsoSealed, Final, ImplicitlyFinal, NonSealed {
44

55
default String sealedMethod() {
66
return "sealed";

src/test/java/pl/mperor/lab/java/Java15.java

Lines changed: 0 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -9,46 +9,4 @@
99
*/
1010
public class Java15 {
1111

12-
@Test
13-
public void testSealedClassesAndInterfaces() {
14-
Assertions.assertTrue(Sealed.class.isSealed());
15-
Assertions.assertFalse(NonSealed.class.isSealed());
16-
Assertions.assertFalse(Final.class.isSealed());
17-
Assertions.assertTrue(AlsoSealed.class.isSealed());
18-
Assertions.assertFalse(AlsoFinal.class.isSealed());
19-
20-
Assertions.assertEquals("final", switchSealed(new Final()));
21-
Assertions.assertEquals("non-sealed", switchSealed(new NonSealed()));
22-
Assertions.assertEquals("sealed", switchSealed(new AlsoSealed()));
23-
24-
SealedClient client = new SealedClient(new NonSealedChild());
25-
Assertions.assertEquals("non-sealed", client.call());
26-
}
27-
28-
private static String switchSealed(Sealed sealed) {
29-
return switch (sealed) {
30-
case AlsoSealed a -> a.alsoSealedMethod();
31-
case Final f -> f.finalMethod();
32-
case NonSealed ns -> ns.nonSealedMethod();
33-
};
34-
}
35-
36-
private static class NonSealedChild extends NonSealed {
37-
}
38-
39-
// not permitted
40-
// private static class SealedChild implements Sealed {
41-
// }
42-
public static class SealedClient {
43-
private Sealed s;
44-
45-
public SealedClient(Sealed s) {
46-
this.s = s;
47-
}
48-
49-
public String call() {
50-
return switchSealed(s);
51-
}
52-
}
53-
5412
}

src/test/java/pl/mperor/lab/java/Java17.java

Lines changed: 118 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -2,21 +2,82 @@
22

33
import org.junit.jupiter.api.Assertions;
44
import org.junit.jupiter.api.Test;
5-
import org.junit.jupiter.api.condition.DisabledOnJre;
6-
import org.junit.jupiter.api.condition.JRE;
5+
import pl.mperor.lab.java.lang.JavaBean;
6+
import pl.mperor.lab.java.sealed.*;
77

8+
import java.applet.Applet;
9+
import java.io.*;
810
import java.lang.reflect.Field;
911
import java.lang.reflect.InaccessibleObjectException;
1012
import java.util.HexFormat;
11-
import java.util.ServiceLoader;
12-
import java.util.random.RandomGenerator;
13+
import java.util.Set;
1314
import java.util.random.RandomGeneratorFactory;
1415

15-
/**
16-
* Java 17 (September 2021)
17-
*/
16+
/// Java 17™ (September 2021)
17+
/// [JDK 17](https://openjdk.org/projects/jdk/17)
18+
///
19+
/// - STANDARD FEATURES:
20+
/// - 409: Sealed Classes
21+
/// - 403: Strongly Encapsulate JDK Internals
22+
/// - 356: Enhanced Pseudo-Random Number Generators
23+
/// - 306: Restore Always-Strict Floating-Point Semantics
24+
/// - 398: Deprecate the Applet API for Removal
25+
/// - 411: Deprecate the Security Manager for Removal
26+
/// - 407: Remove RMI Activation
27+
/// - 410: Remove the Experimental AOT and JIT Compiler
28+
/// - 415: Context-Specific Deserialization Filters
29+
/// - 382: New macOS Rendering Pipeline
30+
/// - 391: macOS/AArch64 Port
31+
///
32+
/// - PREVIEW & INCUBATOR:
33+
/// - 406: Pattern Matching for switch (Preview)
34+
/// - 412: Foreign Function & Memory API (Incubator)
35+
/// - 414: Vector API (Second Incubator)
1836
public class Java17 {
1937

38+
@Test
39+
public void testSealedClassesAndInterfaces() {
40+
Assertions.assertTrue(Sealed.class.isSealed());
41+
Assertions.assertFalse(NonSealed.class.isSealed());
42+
Assertions.assertFalse(Final.class.isSealed());
43+
Assertions.assertTrue(AlsoSealed.class.isSealed());
44+
Assertions.assertFalse(AlsoFinal.class.isSealed());
45+
Assertions.assertFalse(ImplicitlyFinal.class.isSealed());
46+
47+
Assertions.assertEquals("final", switchSealed(new Final()));
48+
Assertions.assertEquals("non-sealed", switchSealed(new NonSealed()));
49+
Assertions.assertEquals("sealed", switchSealed(new AlsoSealed()));
50+
Assertions.assertEquals("implicitly final", switchSealed(new ImplicitlyFinal()));
51+
52+
SealedClient client = new SealedClient(new NonSealedChild());
53+
Assertions.assertEquals("non-sealed", client.call());
54+
}
55+
56+
private static String switchSealed(Sealed sealed) {
57+
return switch (sealed) {
58+
case AlsoSealed a -> a.alsoSealedMethod();
59+
case Final f -> f.finalMethod();
60+
case NonSealed ns -> ns.nonSealedMethod();
61+
case ImplicitlyFinal r -> r.implicitlyFinalMethod();
62+
};
63+
}
64+
65+
private static class NonSealedChild extends NonSealed {}
66+
67+
private static class NotPermittedSealedChild /* implements Sealed */ {}
68+
69+
private static class SealedClient {
70+
private Sealed s;
71+
72+
public SealedClient(Sealed s) {
73+
this.s = s;
74+
}
75+
76+
public String call() {
77+
return switchSealed(s);
78+
}
79+
}
80+
2081
@Test
2182
public void testStronglyEncapsulatedInternals() {
2283
Assertions.assertThrows(InaccessibleObjectException.class, () -> deepLookIntoStringBytes("Hello"));
@@ -28,48 +89,20 @@ private static byte[] deepLookIntoStringBytes(String string) throws IllegalAcces
2889
return (byte[]) valueField.get(string);
2990
}
3091

31-
@Test
32-
public void testSwitchPatternMatching() {
33-
Assertions.assertEquals("String: Hello", switchOverClasses("Hello"));
34-
Assertions.assertEquals("int: 1", switchOverClasses(1));
35-
Assertions.assertEquals("long: 13", switchOverClasses(13L));
36-
Assertions.assertEquals("boolean: true", switchOverClasses(true));
37-
Assertions.assertEquals("null", switchOverClasses(null));
38-
record Person(String name, String surname) {
39-
@Override
40-
public String toString() {
41-
return "%s %s".formatted(name, surname);
42-
}
43-
}
44-
Assertions.assertEquals("Object: John Doe", switchOverClasses(new Person("John", "Doe")));
45-
}
46-
47-
private static String switchOverClasses(Object obj) {
48-
return switch (obj) {
49-
case String s -> String.format("String: %s", s);
50-
case Integer i -> String.format("int: %d", i);
51-
case Long l -> String.format("long: %d", l);
52-
case Boolean b -> String.format("boolean: %s", b);
53-
case null -> "null";
54-
default -> "Object: " + obj;
55-
};
56-
}
57-
58-
@DisabledOnJre(JRE.JAVA_23)
5992
@Test
6093
public void testRandomGeneratorFactory() {
61-
var generators = ServiceLoader.load(RandomGenerator.class).stream()
62-
.map(provider -> provider.type().getCanonicalName())
94+
var defaultRandomGenerator = RandomGeneratorFactory.getDefault().create();
95+
Assertions.assertEquals("jdk.internal.random.L32X64MixRandom", defaultRandomGenerator.getClass().getCanonicalName());
96+
97+
var generators = RandomGeneratorFactory.all()
98+
.map(fac -> fac.create().getClass().getCanonicalName())
6399
.peek(System.out::println)
64100
.toList();
65-
66101
Assertions.assertTrue(generators.contains("java.util.Random"));
67-
var defaultRandomGenerator = RandomGeneratorFactory.getDefault().create();
68-
Assertions.assertEquals("jdk.random.L32X64MixRandom", defaultRandomGenerator.getClass().getCanonicalName());
69102
}
70103

71104
@Test
72-
void testHexFormat() {
105+
public void testHexFormat() {
73106
HexFormat hexFormat = HexFormat.of();
74107
String hex = hexFormat.formatHex(new byte[]{0x1A, 0x2B, 0x3C});
75108
Assertions.assertEquals("1a2b3c", hex);
@@ -78,4 +111,48 @@ void testHexFormat() {
78111
Assertions.assertEquals(16 + 10, HexFormat.fromHexDigits("1a"));
79112
}
80113

114+
@Test
115+
public void testAlwaysStrictFloatingPointSemantics() {
116+
Assertions.assertEquals(4, strictPower(2, 2));
117+
}
118+
119+
// warning: [strictfp] as of release 17, all floating-point expressions are evaluated strictly and 'strictfp' is not required
120+
@SuppressWarnings("strictfp")
121+
public static strictfp double strictPower(double a, double b) {
122+
return Math.pow(a, b);
123+
}
124+
125+
@SuppressWarnings("removal")
126+
@Test
127+
public void testDeprecated() {
128+
// warning: [removal] Applet in java.applet has been deprecated and marked for removal
129+
Applet appletDeprecatedForRemoval;
130+
// warning: [removal] SecurityManager in java.lang has been deprecated and marked for removal
131+
SecurityManager securityManager = System.getSecurityManager();
132+
}
133+
134+
@Test
135+
public void testRmiActivation() {
136+
Assertions.assertFalse(ModuleLayer.boot().findModule("java.rmi").stream().map(Module::getPackages)
137+
.flatMap(Set::stream)
138+
.anyMatch("java.rmi.activation"::equals));
139+
}
140+
141+
@Test
142+
public void testDeserializationFilters() throws IOException, ClassNotFoundException {
143+
var file = new File("src/test/resources/bean");
144+
145+
var basePackageFilter = ObjectInputFilter.Config.createFilter("java.base/*;!*");
146+
try (ObjectInputStream in = new ObjectInputStream(new FileInputStream(file))) {
147+
in.setObjectInputFilter(basePackageFilter);
148+
Assertions.assertThrows(InvalidClassException.class, () -> in.readObject());
149+
}
150+
151+
ObjectInputFilter onlyJavaBeansFilter = ObjectInputFilter.allowFilter(JavaBean.class::equals, ObjectInputFilter.Status.REJECTED);
152+
try (ObjectInputStream in = new ObjectInputStream(new FileInputStream(file))) {
153+
in.setObjectInputFilter(onlyJavaBeansFilter);
154+
Assertions.assertNotNull(in.readObject());
155+
}
156+
}
157+
81158
}

0 commit comments

Comments
 (0)