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 |