View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *   http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  package org.apache.commons.io.serialization;
20  
21  import static org.junit.jupiter.api.Assertions.assertEquals;
22  import static org.junit.jupiter.api.Assertions.assertThrows;
23  import static org.junit.jupiter.api.Assertions.assertTrue;
24  import static org.junit.jupiter.api.Assertions.fail;
25  
26  import java.io.ByteArrayInputStream;
27  import java.io.ByteArrayOutputStream;
28  import java.io.IOException;
29  import java.io.InputStream;
30  import java.io.InvalidClassException;
31  import java.io.ObjectInputStream;
32  import java.io.ObjectOutputStream;
33  import java.util.UUID;
34  import java.util.regex.Pattern;
35  
36  import org.junit.jupiter.api.BeforeEach;
37  import org.junit.jupiter.api.Test;
38  
39  /**
40   * Tests {@link ValidatingObjectInputStream}.
41   */
42  public class ValidatingObjectInputStreamTest extends AbstractCloseableListTest {
43      private static final ClassNameMatcher ALWAYS_TRUE = className -> true;
44      private MockSerializedClass testObject;
45  
46      private InputStream testStream;
47  
48      private void assertSerialization(final ObjectInputStream ois) throws ClassNotFoundException, IOException {
49          final MockSerializedClass result = (MockSerializedClass) ois.readObject();
50          assertEquals(testObject, result);
51      }
52  
53      @BeforeEach
54      public void setupMockSerializedClass() throws IOException {
55          testObject = new MockSerializedClass(UUID.randomUUID().toString());
56          final ByteArrayOutputStream bos = closeAfterEachTest(new ByteArrayOutputStream());
57          final ObjectOutputStream oos = closeAfterEachTest(new ObjectOutputStream(bos));
58          oos.writeObject(testObject);
59          testStream = closeAfterEachTest(new ByteArrayInputStream(bos.toByteArray()));
60      }
61  
62      @Test
63      public void testAcceptCustomMatcher() throws Exception {
64          assertSerialization(
65                  closeAfterEachTest(new ValidatingObjectInputStream(testStream))
66                  .accept(ALWAYS_TRUE)
67          );
68      }
69  
70      @Test
71      public void testAcceptPattern() throws Exception {
72          assertSerialization(
73                  closeAfterEachTest(new ValidatingObjectInputStream(testStream))
74                  .accept(Pattern.compile(".*MockSerializedClass.*"))
75          );
76      }
77  
78      @Test
79      public void testAcceptWildcard() throws Exception {
80          assertSerialization(
81                  closeAfterEachTest(new ValidatingObjectInputStream(testStream))
82                  .accept("org.apache.commons.io.*")
83          );
84      }
85  
86      @Test
87      public void testCustomInvalidMethod() {
88          final class CustomVOIS extends ValidatingObjectInputStream {
89              CustomVOIS(final InputStream is) throws IOException {
90                  super(is);
91              }
92  
93              @Override
94              protected void invalidClassNameFound(final String className) throws InvalidClassException {
95                  throw new RuntimeException("Custom exception");
96              }
97          }
98  
99          assertThrows(RuntimeException.class,
100                 () -> assertSerialization(
101                 closeAfterEachTest(new CustomVOIS(testStream))
102                 .reject(Integer.class)
103         ));
104     }
105 
106     @Test
107     public void testExceptionIncludesClassName() throws Exception {
108         try {
109             assertSerialization(
110                     closeAfterEachTest(new ValidatingObjectInputStream(testStream)));
111             fail("Expected an InvalidClassException");
112         } catch (final InvalidClassException ice) {
113             final String name = MockSerializedClass.class.getName();
114             assertTrue(ice.getMessage().contains(name), "Expecting message to contain " + name);
115         }
116     }
117 
118     @Test
119     public void testNoAccept() {
120         assertThrows(InvalidClassException.class, () -> assertSerialization(
121                 closeAfterEachTest(new ValidatingObjectInputStream(testStream))));
122     }
123 
124     @Test
125     public void testOurTestClassAcceptedFirst() throws Exception {
126         assertSerialization(
127                 closeAfterEachTest(new ValidatingObjectInputStream(testStream))
128                 .accept(MockSerializedClass.class, Integer.class)
129         );
130     }
131 
132     @Test
133     public void testOurTestClassAcceptedFirstWildcard() throws Exception {
134         assertSerialization(
135                 closeAfterEachTest(new ValidatingObjectInputStream(testStream))
136                 .accept("*MockSerializedClass", "*Integer")
137         );
138     }
139 
140     @Test
141     public void testOurTestClassAcceptedSecond() throws Exception {
142         assertSerialization(
143                 closeAfterEachTest(new ValidatingObjectInputStream(testStream))
144                 .accept(Integer.class, MockSerializedClass.class)
145         );
146     }
147 
148     @Test
149     public void testOurTestClassAcceptedSecondWildcard() throws Exception {
150         assertSerialization(
151                 closeAfterEachTest(new ValidatingObjectInputStream(testStream))
152                 .accept("*Integer", "*MockSerializedClass")
153         );
154     }
155 
156     @Test
157     public void testOurTestClassNotAccepted() {
158         assertThrows(InvalidClassException.class,
159                 () -> assertSerialization(
160                 closeAfterEachTest(new ValidatingObjectInputStream(testStream))
161                 .accept(Integer.class)
162         ));
163     }
164 
165     @Test
166     public void testOurTestClassOnlyAccepted() throws Exception {
167         assertSerialization(
168                 closeAfterEachTest(new ValidatingObjectInputStream(testStream))
169                 .accept(MockSerializedClass.class)
170         );
171     }
172 
173     @Test
174     public void testReject() {
175         assertThrows(InvalidClassException.class,
176                 () -> assertSerialization(
177                 closeAfterEachTest(new ValidatingObjectInputStream(testStream))
178                 .accept(Long.class)
179                 .reject(MockSerializedClass.class, Integer.class)
180         ));
181     }
182 
183     @Test
184     public void testRejectCustomMatcher() {
185         assertThrows(InvalidClassException.class,
186                 () -> assertSerialization(
187                 closeAfterEachTest(new ValidatingObjectInputStream(testStream))
188                 .accept(MockSerializedClass.class)
189                 .reject(ALWAYS_TRUE)
190         ));
191     }
192 
193     @Test
194     public void testRejectOnly() {
195         assertThrows(InvalidClassException.class,
196                 () -> assertSerialization(
197                 closeAfterEachTest(new ValidatingObjectInputStream(testStream))
198                 .reject(Integer.class)
199         ));
200     }
201 
202     @Test
203     public void testRejectPattern() {
204         assertThrows(InvalidClassException.class,
205                 () -> assertSerialization(
206                 closeAfterEachTest(new ValidatingObjectInputStream(testStream))
207                 .accept(MockSerializedClass.class)
208                 .reject(Pattern.compile("org.*"))
209         ));
210     }
211 
212     @Test
213     public void testRejectPrecedence() {
214         assertThrows(InvalidClassException.class,
215                 () -> assertSerialization(
216                 closeAfterEachTest(new ValidatingObjectInputStream(testStream))
217                 .accept(MockSerializedClass.class)
218                 .reject(MockSerializedClass.class, Integer.class)
219         ));
220     }
221 
222     @Test
223     public void testRejectWildcard() {
224         assertThrows(InvalidClassException.class,
225                 () -> assertSerialization(
226                 closeAfterEachTest(new ValidatingObjectInputStream(testStream))
227                 .accept(MockSerializedClass.class)
228                 .reject("org.*")
229         ));
230     }
231 }