OLD | NEW |
| (Empty) |
1 // Protocol Buffers - Google's data interchange format | |
2 // Copyright 2008 Google Inc. All rights reserved. | |
3 // https://developers.google.com/protocol-buffers/ | |
4 // | |
5 // Redistribution and use in source and binary forms, with or without | |
6 // modification, are permitted provided that the following conditions are | |
7 // met: | |
8 // | |
9 // * Redistributions of source code must retain the above copyright | |
10 // notice, this list of conditions and the following disclaimer. | |
11 // * Redistributions in binary form must reproduce the above | |
12 // copyright notice, this list of conditions and the following disclaimer | |
13 // in the documentation and/or other materials provided with the | |
14 // distribution. | |
15 // * Neither the name of Google Inc. nor the names of its | |
16 // contributors may be used to endorse or promote products derived from | |
17 // this software without specific prior written permission. | |
18 // | |
19 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | |
20 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | |
21 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | |
22 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | |
23 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | |
24 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | |
25 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | |
26 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | |
27 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
28 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | |
29 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
30 | |
31 package com.google.protobuf; | |
32 | |
33 import protobuf_unittest.NonNestedExtension; | |
34 import protobuf_unittest.NonNestedExtensionLite; | |
35 import java.lang.reflect.Method; | |
36 import java.net.URLClassLoader; | |
37 import java.util.Arrays; | |
38 import java.util.Collections; | |
39 import java.util.HashSet; | |
40 import java.util.Set; | |
41 import junit.framework.Test; | |
42 import junit.framework.TestCase; | |
43 import junit.framework.TestSuite; | |
44 | |
45 /** | |
46 * Tests for {@link ExtensionRegistryFactory} and the {@link ExtensionRegistry}
instances it | |
47 * creates. | |
48 * | |
49 * <p>This test simulates the runtime behaviour of the ExtensionRegistryFactory
by delegating test | |
50 * definitions to two inner classes {@link InnerTest} and {@link InnerLiteTest},
the latter of | |
51 * which is executed using a custom ClassLoader, simulating the ProtoLite enviro
nment. | |
52 * | |
53 * <p>The test mechanism employed here is based on the pattern in | |
54 * {@code com.google.common.util.concurrent.AbstractFutureFallbackAtomicHelperTe
st} | |
55 */ | |
56 public class ExtensionRegistryFactoryTest extends TestCase { | |
57 | |
58 // A classloader which blacklists some non-Lite classes. | |
59 private static final ClassLoader LITE_CLASS_LOADER = getLiteOnlyClassLoader(); | |
60 | |
61 /** | |
62 * Defines the set of test methods which will be run. | |
63 */ | |
64 static interface RegistryTests { | |
65 void testCreate(); | |
66 void testEmpty(); | |
67 void testIsFullRegistry(); | |
68 void testAdd(); | |
69 void testAdd_immutable(); | |
70 } | |
71 | |
72 /** | |
73 * Test implementations for the non-Lite usage of ExtensionRegistryFactory. | |
74 */ | |
75 public static class InnerTest implements RegistryTests { | |
76 | |
77 @Override | |
78 public void testCreate() { | |
79 ExtensionRegistryLite registry = ExtensionRegistryFactory.create(); | |
80 | |
81 assertEquals(registry.getClass(), ExtensionRegistry.class); | |
82 } | |
83 | |
84 @Override | |
85 public void testEmpty() { | |
86 ExtensionRegistryLite emptyRegistry = ExtensionRegistryFactory.createEmpty
(); | |
87 | |
88 assertEquals(emptyRegistry.getClass(), ExtensionRegistry.class); | |
89 assertEquals(emptyRegistry, ExtensionRegistry.EMPTY_REGISTRY); | |
90 } | |
91 | |
92 @Override | |
93 public void testIsFullRegistry() { | |
94 ExtensionRegistryLite registry = ExtensionRegistryFactory.create(); | |
95 assertTrue(ExtensionRegistryFactory.isFullRegistry(registry)); | |
96 } | |
97 | |
98 @Override | |
99 public void testAdd() { | |
100 ExtensionRegistryLite registry1 = ExtensionRegistryLite.newInstance(); | |
101 NonNestedExtensionLite.registerAllExtensions(registry1); | |
102 registry1.add(NonNestedExtensionLite.nonNestedExtensionLite); | |
103 | |
104 ExtensionRegistryLite registry2 = ExtensionRegistryLite.newInstance(); | |
105 NonNestedExtension.registerAllExtensions((ExtensionRegistry) registry2); | |
106 registry2.add(NonNestedExtension.nonNestedExtension); | |
107 | |
108 ExtensionRegistry fullRegistry1 = (ExtensionRegistry) registry1; | |
109 ExtensionRegistry fullRegistry2 = (ExtensionRegistry) registry2; | |
110 | |
111 assertTrue("Test is using a non-lite extension", | |
112 GeneratedMessageLite.GeneratedExtension.class.isAssignableFrom( | |
113 NonNestedExtensionLite.nonNestedExtensionLite.getClass())); | |
114 assertNull("Extension is not registered in masqueraded full registry", | |
115 fullRegistry1.findImmutableExtensionByName("protobuf_unittest.nonNeste
dExtension")); | |
116 GeneratedMessageLite.GeneratedExtension<NonNestedExtensionLite.MessageLite
ToBeExtended, ?> | |
117 extension = registry1.findLiteExtensionByNumber( | |
118 NonNestedExtensionLite.MessageLiteToBeExtended.getDefaultInstance(), 1
); | |
119 assertNotNull("Extension registered in lite registry", extension); | |
120 | |
121 assertTrue("Test is using a non-lite extension", | |
122 GeneratedMessage.GeneratedExtension.class.isAssignableFrom( | |
123 NonNestedExtension.nonNestedExtension.getClass())); | |
124 assertNotNull("Extension is registered in masqueraded full registry", | |
125 fullRegistry2.findImmutableExtensionByName("protobuf_unittest.nonNeste
dExtension")); | |
126 } | |
127 | |
128 @Override | |
129 public void testAdd_immutable() { | |
130 ExtensionRegistryLite registry1 = ExtensionRegistryLite.newInstance().getU
nmodifiable(); | |
131 try { | |
132 NonNestedExtensionLite.registerAllExtensions(registry1); | |
133 fail(); | |
134 } catch (UnsupportedOperationException expected) {} | |
135 try { | |
136 registry1.add(NonNestedExtensionLite.nonNestedExtensionLite); | |
137 fail(); | |
138 } catch (UnsupportedOperationException expected) {} | |
139 | |
140 ExtensionRegistryLite registry2 = ExtensionRegistryLite.newInstance().getU
nmodifiable(); | |
141 try { | |
142 NonNestedExtension.registerAllExtensions((ExtensionRegistry) registry2); | |
143 fail(); | |
144 } catch (IllegalArgumentException expected) {} | |
145 try { | |
146 registry2.add(NonNestedExtension.nonNestedExtension); | |
147 fail(); | |
148 } catch (IllegalArgumentException expected) {} | |
149 } | |
150 } | |
151 | |
152 /** | |
153 * Test implementations for the Lite usage of ExtensionRegistryFactory. | |
154 */ | |
155 public static final class InnerLiteTest implements RegistryTests { | |
156 | |
157 @Override | |
158 public void testCreate() { | |
159 ExtensionRegistryLite registry = ExtensionRegistryFactory.create(); | |
160 | |
161 assertEquals(registry.getClass(), ExtensionRegistryLite.class); | |
162 } | |
163 | |
164 @Override | |
165 public void testEmpty() { | |
166 ExtensionRegistryLite emptyRegistry = ExtensionRegistryFactory.createEmpty
(); | |
167 | |
168 assertEquals(emptyRegistry.getClass(), ExtensionRegistryLite.class); | |
169 assertEquals(emptyRegistry, ExtensionRegistryLite.EMPTY_REGISTRY_LITE); | |
170 } | |
171 | |
172 @Override | |
173 public void testIsFullRegistry() { | |
174 ExtensionRegistryLite registry = ExtensionRegistryFactory.create(); | |
175 assertFalse(ExtensionRegistryFactory.isFullRegistry(registry)); | |
176 } | |
177 | |
178 @Override | |
179 public void testAdd() { | |
180 ExtensionRegistryLite registry = ExtensionRegistryLite.newInstance(); | |
181 NonNestedExtensionLite.registerAllExtensions(registry); | |
182 GeneratedMessageLite.GeneratedExtension<NonNestedExtensionLite.MessageLite
ToBeExtended, ?> | |
183 extension = registry.findLiteExtensionByNumber( | |
184 NonNestedExtensionLite.MessageLiteToBeExtended.getDefaultInstance(
), 1); | |
185 assertNotNull("Extension is registered in Lite registry", extension); | |
186 } | |
187 | |
188 @Override | |
189 public void testAdd_immutable() { | |
190 ExtensionRegistryLite registry = ExtensionRegistryLite.newInstance().getUn
modifiable(); | |
191 try { | |
192 NonNestedExtensionLite.registerAllExtensions(registry); | |
193 fail(); | |
194 } catch (UnsupportedOperationException expected) {} | |
195 } | |
196 } | |
197 | |
198 /** | |
199 * Defines a suite of tests which the JUnit3 runner retrieves by reflection. | |
200 */ | |
201 public static Test suite() { | |
202 TestSuite suite = new TestSuite(); | |
203 for (Method method : RegistryTests.class.getMethods()) { | |
204 suite.addTest(TestSuite.createTest(ExtensionRegistryFactoryTest.class, met
hod.getName())); | |
205 } | |
206 return suite; | |
207 } | |
208 | |
209 /** | |
210 * Sequentially runs first the Lite and then the non-Lite test variant via cla
ssloader | |
211 * manipulation. | |
212 */ | |
213 @Override | |
214 public void runTest() throws Exception { | |
215 ClassLoader storedClassLoader = Thread.currentThread().getContextClassLoader
(); | |
216 Thread.currentThread().setContextClassLoader(LITE_CLASS_LOADER); | |
217 try { | |
218 runTestMethod(LITE_CLASS_LOADER, InnerLiteTest.class); | |
219 } finally { | |
220 Thread.currentThread().setContextClassLoader(storedClassLoader); | |
221 } | |
222 try { | |
223 runTestMethod(storedClassLoader, InnerTest.class); | |
224 } finally { | |
225 Thread.currentThread().setContextClassLoader(storedClassLoader); | |
226 } | |
227 } | |
228 | |
229 private void runTestMethod(ClassLoader classLoader, Class<? extends RegistryTe
sts> testClass) | |
230 throws Exception { | |
231 classLoader.loadClass(ExtensionRegistryFactory.class.getName()); | |
232 Class<?> test = classLoader.loadClass(testClass.getName()); | |
233 String testName = getName(); | |
234 test.getMethod(testName).invoke(test.newInstance()); | |
235 } | |
236 | |
237 /** | |
238 * Constructs a custom ClassLoader blacklisting the classes which are inspecte
d in the SUT | |
239 * to determine the Lite/non-Lite runtime. | |
240 */ | |
241 private static ClassLoader getLiteOnlyClassLoader() { | |
242 ClassLoader testClassLoader = ExtensionRegistryFactoryTest.class.getClassLoa
der(); | |
243 final Set<String> classNamesNotInLite = | |
244 Collections.unmodifiableSet( | |
245 new HashSet<String>( | |
246 Arrays.asList( | |
247 ExtensionRegistryFactory.FULL_REGISTRY_CLASS_NAME, | |
248 ExtensionRegistry.EXTENSION_CLASS_NAME))); | |
249 | |
250 // Construct a URLClassLoader delegating to the system ClassLoader, and look
ing up classes | |
251 // in jar files based on the URLs already configured for this test's UrlClas
sLoader. | |
252 // Certain classes throw a ClassNotFoundException by design. | |
253 return new URLClassLoader(((URLClassLoader) testClassLoader).getURLs(), | |
254 ClassLoader.getSystemClassLoader()) { | |
255 @Override | |
256 public Class<?> loadClass(String name, boolean resolve) throws ClassNotFou
ndException { | |
257 if (classNamesNotInLite.contains(name)) { | |
258 throw new ClassNotFoundException("Class deliberately blacklisted by te
st."); | |
259 } | |
260 Class<?> loadedClass = null; | |
261 try { | |
262 loadedClass = findLoadedClass(name); | |
263 if (loadedClass == null) { | |
264 loadedClass = findClass(name); | |
265 if (resolve) { | |
266 resolveClass(loadedClass); | |
267 } | |
268 } | |
269 } catch (ClassNotFoundException e) { | |
270 loadedClass = super.loadClass(name, resolve); | |
271 } | |
272 return loadedClass; | |
273 } | |
274 }; | |
275 } | |
276 } | |
OLD | NEW |