1 /* 2 * Copyright (C) 2014 Google, Inc. 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 package com.squareup.javapoet; 17 18 import com.google.testing.compile.CompilationRule; 19 import java.util.Map; 20 import javax.lang.model.element.TypeElement; 21 import javax.lang.model.util.Elements; 22 import org.junit.Rule; 23 import org.junit.Test; 24 import org.junit.runner.RunWith; 25 import org.junit.runners.JUnit4; 26 import org.mockito.Mockito; 27 28 import static com.google.common.truth.Truth.assertThat; 29 import static org.junit.Assert.assertEquals; 30 import static org.junit.Assert.fail; 31 import static org.mockito.Mockito.when; 32 33 @RunWith(JUnit4.class) 34 public final class ClassNameTest { 35 @Rule public CompilationRule compilationRule = new CompilationRule(); 36 bestGuessForString_simpleClass()37 @Test public void bestGuessForString_simpleClass() { 38 assertThat(ClassName.bestGuess(String.class.getName())) 39 .isEqualTo(ClassName.get("java.lang", "String")); 40 } 41 bestGuessNonAscii()42 @Test public void bestGuessNonAscii() { 43 ClassName className = ClassName.bestGuess( 44 "com.\ud835\udc1andro\ud835\udc22d.\ud835\udc00ctiv\ud835\udc22ty"); 45 assertEquals("com.\ud835\udc1andro\ud835\udc22d", className.packageName()); 46 assertEquals("\ud835\udc00ctiv\ud835\udc22ty", className.simpleName()); 47 } 48 49 static class OuterClass { 50 static class InnerClass {} 51 } 52 bestGuessForString_nestedClass()53 @Test public void bestGuessForString_nestedClass() { 54 assertThat(ClassName.bestGuess(Map.Entry.class.getCanonicalName())) 55 .isEqualTo(ClassName.get("java.util", "Map", "Entry")); 56 assertThat(ClassName.bestGuess(OuterClass.InnerClass.class.getCanonicalName())) 57 .isEqualTo(ClassName.get("com.squareup.javapoet", 58 "ClassNameTest", "OuterClass", "InnerClass")); 59 } 60 bestGuessForString_defaultPackage()61 @Test public void bestGuessForString_defaultPackage() { 62 assertThat(ClassName.bestGuess("SomeClass")) 63 .isEqualTo(ClassName.get("", "SomeClass")); 64 assertThat(ClassName.bestGuess("SomeClass.Nested")) 65 .isEqualTo(ClassName.get("", "SomeClass", "Nested")); 66 assertThat(ClassName.bestGuess("SomeClass.Nested.EvenMore")) 67 .isEqualTo(ClassName.get("", "SomeClass", "Nested", "EvenMore")); 68 } 69 bestGuessForString_confusingInput()70 @Test public void bestGuessForString_confusingInput() { 71 assertBestGuessThrows(""); 72 assertBestGuessThrows("."); 73 assertBestGuessThrows(".Map"); 74 assertBestGuessThrows("java"); 75 assertBestGuessThrows("java.util"); 76 assertBestGuessThrows("java.util."); 77 assertBestGuessThrows("java..util.Map.Entry"); 78 assertBestGuessThrows("java.util..Map.Entry"); 79 assertBestGuessThrows("java.util.Map..Entry"); 80 assertBestGuessThrows("com.test.$"); 81 assertBestGuessThrows("com.test.LooksLikeAClass.pkg"); 82 assertBestGuessThrows("!@#$gibberish%^&*"); 83 } 84 assertBestGuessThrows(String s)85 private void assertBestGuessThrows(String s) { 86 try { 87 ClassName.bestGuess(s); 88 fail(); 89 } catch (IllegalArgumentException expected) { 90 } 91 } 92 createNestedClass()93 @Test public void createNestedClass() { 94 ClassName foo = ClassName.get("com.example", "Foo"); 95 ClassName bar = foo.nestedClass("Bar"); 96 assertThat(bar).isEqualTo(ClassName.get("com.example", "Foo", "Bar")); 97 ClassName baz = bar.nestedClass("Baz"); 98 assertThat(baz).isEqualTo(ClassName.get("com.example", "Foo", "Bar", "Baz")); 99 } 100 101 static class $Outer { 102 static class $Inner {} 103 } 104 classNameFromTypeElement()105 @Test public void classNameFromTypeElement() { 106 Elements elements = compilationRule.getElements(); 107 TypeElement object = elements.getTypeElement(Object.class.getCanonicalName()); 108 assertThat(ClassName.get(object).toString()).isEqualTo("java.lang.Object"); 109 TypeElement outer = elements.getTypeElement($Outer.class.getCanonicalName()); 110 assertThat(ClassName.get(outer).toString()).isEqualTo("com.squareup.javapoet.ClassNameTest.$Outer"); 111 TypeElement inner = elements.getTypeElement($Outer.$Inner.class.getCanonicalName()); 112 assertThat(ClassName.get(inner).toString()).isEqualTo("com.squareup.javapoet.ClassNameTest.$Outer.$Inner"); 113 } 114 115 /** 116 * Buck builds with "source-based ABI generation" and those builds don't support 117 * {@link TypeElement#getKind()}. Test to confirm that we don't use that API. 118 */ classNameFromTypeElementDoesntUseGetKind()119 @Test public void classNameFromTypeElementDoesntUseGetKind() { 120 Elements elements = compilationRule.getElements(); 121 TypeElement object = elements.getTypeElement(Object.class.getCanonicalName()); 122 assertThat(ClassName.get(preventGetKind(object)).toString()) 123 .isEqualTo("java.lang.Object"); 124 TypeElement outer = elements.getTypeElement($Outer.class.getCanonicalName()); 125 assertThat(ClassName.get(preventGetKind(outer)).toString()) 126 .isEqualTo("com.squareup.javapoet.ClassNameTest.$Outer"); 127 TypeElement inner = elements.getTypeElement($Outer.$Inner.class.getCanonicalName()); 128 assertThat(ClassName.get(preventGetKind(inner)).toString()) 129 .isEqualTo("com.squareup.javapoet.ClassNameTest.$Outer.$Inner"); 130 } 131 132 /** Returns a new instance like {@code object} that throws on {@code getKind()}. */ preventGetKind(TypeElement object)133 private TypeElement preventGetKind(TypeElement object) { 134 TypeElement spy = Mockito.spy(object); 135 when(spy.getKind()).thenThrow(new AssertionError()); 136 when(spy.getEnclosingElement()).thenAnswer(invocation -> { 137 Object enclosingElement = invocation.callRealMethod(); 138 return enclosingElement instanceof TypeElement 139 ? preventGetKind((TypeElement) enclosingElement) 140 : enclosingElement; 141 }); 142 return spy; 143 } 144 classNameFromClass()145 @Test public void classNameFromClass() { 146 assertThat(ClassName.get(Object.class).toString()) 147 .isEqualTo("java.lang.Object"); 148 assertThat(ClassName.get(OuterClass.InnerClass.class).toString()) 149 .isEqualTo("com.squareup.javapoet.ClassNameTest.OuterClass.InnerClass"); 150 assertThat((ClassName.get(new Object() {}.getClass())).toString()) 151 .isEqualTo("com.squareup.javapoet.ClassNameTest$1"); 152 assertThat((ClassName.get(new Object() { Object inner = new Object() {}; }.inner.getClass())).toString()) 153 .isEqualTo("com.squareup.javapoet.ClassNameTest$2$1"); 154 assertThat((ClassName.get($Outer.class)).toString()) 155 .isEqualTo("com.squareup.javapoet.ClassNameTest.$Outer"); 156 assertThat((ClassName.get($Outer.$Inner.class)).toString()) 157 .isEqualTo("com.squareup.javapoet.ClassNameTest.$Outer.$Inner"); 158 } 159 peerClass()160 @Test public void peerClass() { 161 assertThat(ClassName.get(Double.class).peerClass("Short")) 162 .isEqualTo(ClassName.get(Short.class)); 163 assertThat(ClassName.get("", "Double").peerClass("Short")) 164 .isEqualTo(ClassName.get("", "Short")); 165 assertThat(ClassName.get("a.b", "Combo", "Taco").peerClass("Burrito")) 166 .isEqualTo(ClassName.get("a.b", "Combo", "Burrito")); 167 } 168 fromClassRejectionTypes()169 @Test public void fromClassRejectionTypes() { 170 try { 171 ClassName.get(int.class); 172 fail(); 173 } catch (IllegalArgumentException ignored) { 174 } 175 try { 176 ClassName.get(void.class); 177 fail(); 178 } catch (IllegalArgumentException ignored) { 179 } 180 try { 181 ClassName.get(Object[].class); 182 fail(); 183 } catch (IllegalArgumentException ignored) { 184 } 185 } 186 187 @Test reflectionName()188 public void reflectionName() { 189 assertEquals("java.lang.Object", TypeName.OBJECT.reflectionName()); 190 assertEquals("java.lang.Thread$State", ClassName.get(Thread.State.class).reflectionName()); 191 assertEquals("java.util.Map$Entry", ClassName.get(Map.Entry.class).reflectionName()); 192 assertEquals("Foo", ClassName.get("", "Foo").reflectionName()); 193 assertEquals("Foo$Bar$Baz", ClassName.get("", "Foo", "Bar", "Baz").reflectionName()); 194 assertEquals("a.b.c.Foo$Bar$Baz", ClassName.get("a.b.c", "Foo", "Bar", "Baz").reflectionName()); 195 } 196 } 197