|
16 | 16 |
|
17 | 17 | package org.springframework.security;
|
18 | 18 |
|
| 19 | +import java.io.ByteArrayInputStream; |
| 20 | +import java.io.ByteArrayOutputStream; |
19 | 21 | import java.io.File;
|
20 | 22 | import java.io.FileInputStream;
|
21 | 23 | import java.io.FileOutputStream;
|
|
35 | 37 | import java.util.Collection;
|
36 | 38 | import java.util.Date;
|
37 | 39 | import java.util.HashMap;
|
| 40 | +import java.util.HashSet; |
38 | 41 | import java.util.List;
|
39 | 42 | import java.util.Map;
|
40 | 43 | import java.util.Set;
|
41 | 44 | import java.util.stream.Collectors;
|
42 | 45 | import java.util.stream.Stream;
|
43 | 46 |
|
| 47 | +import org.apache.commons.lang3.ObjectUtils; |
44 | 48 | import org.apereo.cas.client.validation.AssertionImpl;
|
45 | 49 | import org.instancio.Instancio;
|
46 | 50 | import org.instancio.InstancioApi;
|
|
192 | 196 | import org.springframework.security.web.firewall.RequestRejectedException;
|
193 | 197 | import org.springframework.security.web.server.firewall.ServerExchangeRejectedException;
|
194 | 198 | import org.springframework.security.web.session.HttpSessionCreatedEvent;
|
| 199 | +import org.springframework.util.ReflectionUtils; |
195 | 200 |
|
196 | 201 | import static org.assertj.core.api.Assertions.assertThat;
|
197 | 202 | import static org.assertj.core.api.Assertions.fail;
|
@@ -512,6 +517,52 @@ class SpringSecurityCoreVersionSerializableTests {
|
512 | 517 | (r) -> new HttpSessionCreatedEvent(new MockHttpSession()));
|
513 | 518 | }
|
514 | 519 |
|
| 520 | + @ParameterizedTest |
| 521 | + @MethodSource("getClassesToSerialize") |
| 522 | + void serializeAndDeserializeAreEqual(Class<?> clazz) throws Exception { |
| 523 | + Object expected = instancioWithDefaults(clazz).create(); |
| 524 | + assertThat(expected).isInstanceOf(clazz); |
| 525 | + try (ByteArrayOutputStream out = new ByteArrayOutputStream(); |
| 526 | + ObjectOutputStream objectOutputStream = new ObjectOutputStream(out)) { |
| 527 | + objectOutputStream.writeObject(expected); |
| 528 | + objectOutputStream.flush(); |
| 529 | + |
| 530 | + try (ByteArrayInputStream in = new ByteArrayInputStream(out.toByteArray()); |
| 531 | + ObjectInputStream objectInputStream = new ObjectInputStream(in)) { |
| 532 | + Object deserialized = objectInputStream.readObject(); |
| 533 | + // Ignore transient fields Event classes extend from EventObject which has |
| 534 | + // transient source property |
| 535 | + Set<String> transientFieldNames = new HashSet(); |
| 536 | + Set<Class<?>> visitedClasses = new HashSet(); |
| 537 | + collectTransientFieldNames(transientFieldNames, visitedClasses, clazz); |
| 538 | + assertThat(deserialized).usingRecursiveComparison() |
| 539 | + .ignoringFields(transientFieldNames.toArray(new String[0])) |
| 540 | + // RuntimeExceptions do not fully work but ensure the message does |
| 541 | + .withComparatorForType((lhs, rhs) -> ObjectUtils.compare(lhs.getMessage(), rhs.getMessage()), |
| 542 | + RuntimeException.class) |
| 543 | + .isEqualTo(expected); |
| 544 | + } |
| 545 | + } |
| 546 | + } |
| 547 | + |
| 548 | + private static void collectTransientFieldNames(Set<String> transientFieldNames, Set<Class<?>> visitedClasses, |
| 549 | + Class<?> clazz) { |
| 550 | + if (!visitedClasses.add(clazz) || clazz.isPrimitive()) { |
| 551 | + return; |
| 552 | + } |
| 553 | + ReflectionUtils.doWithFields(clazz, (field) -> { |
| 554 | + if (Modifier.isTransient(field.getModifiers())) { |
| 555 | + transientFieldNames.add(field.getName()); |
| 556 | + } |
| 557 | + collectTransientFieldNames(transientFieldNames, visitedClasses, field.getType()); |
| 558 | + }); |
| 559 | + } |
| 560 | + |
| 561 | + @Test |
| 562 | + void debug() throws Exception { |
| 563 | + serializeAndDeserializeAreEqual(JaasAuthenticationFailedEvent.class); |
| 564 | + } |
| 565 | + |
515 | 566 | @ParameterizedTest
|
516 | 567 | @MethodSource("getClassesToSerialize")
|
517 | 568 | @Disabled("This method should only be used to serialize the classes once")
|
|
0 commit comments