1 /*
2  * Copyright (C) 2011 The Guava Authors
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.google.common.base;
18 
19 import com.google.common.annotations.GwtCompatible;
20 import com.google.common.annotations.GwtIncompatible;
21 import com.google.common.collect.ImmutableSet;
22 import com.google.common.testing.EqualsTester;
23 import com.google.common.testing.GcFinalization;
24 import com.google.common.testing.NullPointerTester;
25 import com.google.common.testing.SerializableTester;
26 
27 import junit.framework.TestCase;
28 
29 import java.lang.annotation.Retention;
30 import java.lang.annotation.RetentionPolicy;
31 import java.lang.ref.WeakReference;
32 import java.lang.reflect.Field;
33 import java.net.URLClassLoader;
34 import java.util.HashSet;
35 import java.util.Set;
36 
37 /**
38  * Tests for {@link Enums}.
39  *
40  * @author Steve McKay
41  */
42 @GwtCompatible(emulated = true)
43 public class EnumsTest extends TestCase {
44 
45   private enum TestEnum {
46     CHEETO,
47     HONDA,
48     POODLE,
49   }
50 
51   private enum OtherEnum {}
52 
testValueOfFunction()53   public void testValueOfFunction() {
54     Function<String, TestEnum> function = Enums.valueOfFunction(TestEnum.class);
55     assertEquals(TestEnum.CHEETO, function.apply("CHEETO"));
56     assertEquals(TestEnum.HONDA, function.apply("HONDA"));
57     assertEquals(TestEnum.POODLE, function.apply("POODLE"));
58   }
59 
testValueOfFunction_caseSensitive()60   public void testValueOfFunction_caseSensitive() {
61     Function<String, TestEnum> function = Enums.valueOfFunction(TestEnum.class);
62     assertNull(function.apply("cHEETO"));
63     assertNull(function.apply("Honda"));
64     assertNull(function.apply("poodlE"));
65   }
66 
testValueOfFunction_nullWhenNoMatchingConstant()67   public void testValueOfFunction_nullWhenNoMatchingConstant() {
68     Function<String, TestEnum> function = Enums.valueOfFunction(TestEnum.class);
69     assertNull(function.apply("WOMBAT"));
70   }
71 
testValueOfFunction_equals()72   public void testValueOfFunction_equals() {
73     new EqualsTester()
74         .addEqualityGroup(
75             Enums.valueOfFunction(TestEnum.class), Enums.valueOfFunction(TestEnum.class))
76         .addEqualityGroup(Enums.valueOfFunction(OtherEnum.class))
77         .testEquals();
78   }
79 
80   @GwtIncompatible("SerializableTester")
testValueOfFunction_serialization()81   public void testValueOfFunction_serialization() {
82     Function<String, TestEnum> function = Enums.valueOfFunction(TestEnum.class);
83     SerializableTester.reserializeAndAssert(function);
84   }
85 
testGetIfPresent()86   public void testGetIfPresent() {
87     assertEquals(Optional.of(TestEnum.CHEETO), Enums.getIfPresent(TestEnum.class, "CHEETO"));
88     assertEquals(Optional.of(TestEnum.HONDA), Enums.getIfPresent(TestEnum.class, "HONDA"));
89     assertEquals(Optional.of(TestEnum.POODLE), Enums.getIfPresent(TestEnum.class, "POODLE"));
90 
91     assertTrue(Enums.getIfPresent(TestEnum.class, "CHEETO").isPresent());
92     assertTrue(Enums.getIfPresent(TestEnum.class, "HONDA").isPresent());
93     assertTrue(Enums.getIfPresent(TestEnum.class, "POODLE").isPresent());
94 
95     assertEquals(TestEnum.CHEETO, Enums.getIfPresent(TestEnum.class, "CHEETO").get());
96     assertEquals(TestEnum.HONDA, Enums.getIfPresent(TestEnum.class, "HONDA").get());
97     assertEquals(TestEnum.POODLE, Enums.getIfPresent(TestEnum.class, "POODLE").get());
98   }
99 
testGetIfPresent_caseSensitive()100   public void testGetIfPresent_caseSensitive() {
101     assertFalse(Enums.getIfPresent(TestEnum.class, "cHEETO").isPresent());
102     assertFalse(Enums.getIfPresent(TestEnum.class, "Honda").isPresent());
103     assertFalse(Enums.getIfPresent(TestEnum.class, "poodlE").isPresent());
104   }
105 
testGetIfPresent_whenNoMatchingConstant()106   public void testGetIfPresent_whenNoMatchingConstant() {
107     assertEquals(Optional.absent(), Enums.getIfPresent(TestEnum.class, "WOMBAT"));
108   }
109 
110   @GwtIncompatible("weak references")
testGetIfPresent_doesNotPreventClassUnloading()111   public void testGetIfPresent_doesNotPreventClassUnloading() throws Exception {
112     WeakReference<?> shadowLoaderReference = doTestClassUnloading();
113     GcFinalization.awaitClear(shadowLoaderReference);
114   }
115 
116   // Create a second ClassLoader and use it to get a second version of the TestEnum class.
117   // Run Enums.getIfPresent on that other TestEnum and then return a WeakReference containing the
118   // new ClassLoader. If Enums.getIfPresent does caching that prevents the shadow TestEnum
119   // (and therefore its ClassLoader) from being unloaded, then this WeakReference will never be
120   // cleared.
121   @GwtIncompatible("weak references")
doTestClassUnloading()122   private WeakReference<?> doTestClassUnloading() throws Exception {
123     URLClassLoader myLoader = (URLClassLoader) getClass().getClassLoader();
124     URLClassLoader shadowLoader = new URLClassLoader(myLoader.getURLs(), null);
125     @SuppressWarnings("unchecked")
126     Class<TestEnum> shadowTestEnum =
127         (Class<TestEnum>) Class.forName(TestEnum.class.getName(), false, shadowLoader);
128     assertNotSame(shadowTestEnum, TestEnum.class);
129     Set<TestEnum> shadowConstants = new HashSet<TestEnum>();
130     for (TestEnum constant : TestEnum.values()) {
131       Optional<TestEnum> result = Enums.getIfPresent(shadowTestEnum, constant.name());
132       assertTrue(result.isPresent());
133       shadowConstants.add(result.get());
134     }
135     assertEquals(ImmutableSet.copyOf(shadowTestEnum.getEnumConstants()), shadowConstants);
136     Optional<TestEnum> result = Enums.getIfPresent(shadowTestEnum, "blibby");
137     assertFalse(result.isPresent());
138     return new WeakReference<ClassLoader>(shadowLoader);
139   }
140 
testStringConverter_convert()141   public void testStringConverter_convert() {
142     Converter<String, TestEnum> converter = Enums.stringConverter(TestEnum.class);
143     assertEquals(TestEnum.CHEETO, converter.convert("CHEETO"));
144     assertEquals(TestEnum.HONDA, converter.convert("HONDA"));
145     assertEquals(TestEnum.POODLE, converter.convert("POODLE"));
146     assertNull(converter.convert(null));
147     assertNull(converter.reverse().convert(null));
148   }
149 
testStringConverter_convertError()150   public void testStringConverter_convertError() {
151     Converter<String, TestEnum> converter = Enums.stringConverter(TestEnum.class);
152     try {
153       converter.convert("xxx");
154       fail();
155     } catch (IllegalArgumentException expected) {
156     }
157   }
158 
testStringConverter_reverse()159   public void testStringConverter_reverse() {
160     Converter<String, TestEnum> converter = Enums.stringConverter(TestEnum.class);
161     assertEquals("CHEETO", converter.reverse().convert(TestEnum.CHEETO));
162     assertEquals("HONDA", converter.reverse().convert(TestEnum.HONDA));
163     assertEquals("POODLE", converter.reverse().convert(TestEnum.POODLE));
164   }
165 
166   @GwtIncompatible("NullPointerTester")
testStringConverter_nullPointerTester()167   public void testStringConverter_nullPointerTester() throws Exception {
168     Converter<String, TestEnum> converter = Enums.stringConverter(TestEnum.class);
169     NullPointerTester tester = new NullPointerTester();
170     tester.testAllPublicInstanceMethods(converter);
171   }
172 
testStringConverter_nullConversions()173   public void testStringConverter_nullConversions() {
174     Converter<String, TestEnum> converter = Enums.stringConverter(TestEnum.class);
175     assertNull(converter.convert(null));
176     assertNull(converter.reverse().convert(null));
177   }
178 
179   @GwtIncompatible("Class.getName()")
testStringConverter_toString()180   public void testStringConverter_toString() {
181     assertEquals(
182         "Enums.stringConverter(com.google.common.base.EnumsTest$TestEnum.class)",
183         Enums.stringConverter(TestEnum.class).toString());
184   }
185 
testStringConverter_serialization()186   public void testStringConverter_serialization() {
187     SerializableTester.reserializeAndAssert(Enums.stringConverter(TestEnum.class));
188   }
189 
190   @GwtIncompatible("NullPointerTester")
testNullPointerExceptions()191   public void testNullPointerExceptions() {
192     NullPointerTester tester = new NullPointerTester();
193     tester.testAllPublicStaticMethods(Enums.class);
194   }
195 
196   @Retention(RetentionPolicy.RUNTIME)
197   private @interface ExampleAnnotation {}
198 
199   private enum AnEnum {
200     @ExampleAnnotation FOO,
201     BAR
202   }
203 
204   @GwtIncompatible("reflection")
testGetField()205   public void testGetField() {
206     Field foo = Enums.getField(AnEnum.FOO);
207     assertEquals("FOO", foo.getName());
208     assertTrue(foo.isAnnotationPresent(ExampleAnnotation.class));
209 
210     Field bar = Enums.getField(AnEnum.BAR);
211     assertEquals("BAR", bar.getName());
212     assertFalse(bar.isAnnotationPresent(ExampleAnnotation.class));
213   }
214 }
215