1 package org.robolectric.internal.bytecode; 2 3 import static com.google.common.truth.Truth.assertThat; 4 5 import com.google.common.collect.ImmutableList; 6 import com.google.common.collect.ImmutableMultimap; 7 import java.util.ArrayList; 8 import java.util.Collections; 9 import java.util.List; 10 import java.util.Map; 11 import org.junit.Before; 12 import org.junit.Test; 13 import org.junit.runner.RunWith; 14 import org.junit.runners.JUnit4; 15 import org.robolectric.android.AndroidSdkShadowMatcher; 16 import org.robolectric.annotation.Implements; 17 import org.robolectric.internal.ShadowProvider; 18 import org.robolectric.sandbox.ShadowMatcher; 19 import org.robolectric.shadows.ShadowActivity; 20 21 @RunWith(JUnit4.class) 22 public class ShadowMapTest { 23 24 private static final String A = A.class.getName(); 25 private static final String A1 = A1.class.getName(); 26 private static final String A2 = A2.class.getName(); 27 private static final String B = B.class.getName(); 28 private static final String B1 = B1.class.getName(); 29 private static final String B2 = B2.class.getName(); 30 private static final String C1 = C1.class.getName(); 31 private static final String C2 = C2.class.getName(); 32 private static final String C3 = C3.class.getName(); 33 private static final String X = X.class.getName(); 34 35 private ShadowMap baseShadowMap; 36 37 @Before setUp()38 public void setUp() throws Exception { 39 List<ShadowProvider> shadowProviders = 40 Collections.singletonList( 41 new ShadowProvider() { 42 @Override 43 public void reset() {} 44 45 @Override 46 public String[] getProvidedPackageNames() { 47 return new String[0]; 48 } 49 50 @Override 51 public List<Map.Entry<String, String>> getShadows() { 52 return Collections.emptyList(); 53 } 54 }); 55 baseShadowMap = ShadowMap.createFromShadowProviders(shadowProviders); 56 } 57 shouldLookUpShadowClassesByNamingConvention()58 @Test public void shouldLookUpShadowClassesByNamingConvention() throws Exception { 59 ShadowMap map = baseShadowMap.newBuilder().build(); 60 assertThat(map.getShadowInfo(Activity.class, ShadowMatcher.MATCH_ALL)).isNull(); 61 } 62 shouldNotReturnMismatchedClassesJustBecauseTheSimpleNameMatches()63 @Test public void shouldNotReturnMismatchedClassesJustBecauseTheSimpleNameMatches() throws Exception { 64 ShadowMap map = baseShadowMap.newBuilder() 65 .addShadowClasses(ShadowActivity.class) 66 .build(); 67 assertThat(map.getShadowInfo(android.app.Activity.class, ShadowMatcher.MATCH_ALL).shadowClassName) 68 .isEqualTo(ShadowActivity.class.getName()); 69 } 70 getInvalidatedClasses_disjoin()71 @Test public void getInvalidatedClasses_disjoin() { 72 ShadowMap current = baseShadowMap.newBuilder().addShadowClass(A1, A2, true, false).build(); 73 ShadowMap previous = baseShadowMap.newBuilder().addShadowClass(B1, B2, true, false).build(); 74 75 assertThat(current.getInvalidatedClasses(previous)).containsExactly(A1, B1); 76 } 77 getInvalidatedClasses_overlap()78 @Test public void getInvalidatedClasses_overlap() { 79 ShadowMap current = 80 baseShadowMap 81 .newBuilder() 82 .addShadowClass(A1, A2, true, false) 83 .addShadowClass(C1, C2, true, false) 84 .build(); 85 ShadowMap previous = 86 baseShadowMap 87 .newBuilder() 88 .addShadowClass(A1, A2, true, false) 89 .addShadowClass(C1, C3, true, false) 90 .build(); 91 92 assertThat(current.getInvalidatedClasses(previous)).containsExactly(C1); 93 } 94 equalsHashCode()95 @Test public void equalsHashCode() throws Exception { 96 ShadowMap a = baseShadowMap.newBuilder().addShadowClass(A, B, true, false).build(); 97 ShadowMap b = baseShadowMap.newBuilder().addShadowClass(A, B, true, false).build(); 98 assertThat(a).isEqualTo(b); 99 assertThat(a.hashCode()).isEqualTo(b.hashCode()); 100 101 ShadowMap c = b.newBuilder().build(); 102 assertThat(c).isEqualTo(b); 103 assertThat(c.hashCode()).isEqualTo(b.hashCode()); 104 105 ShadowMap d = baseShadowMap.newBuilder().addShadowClass(A, X, true, false).build(); 106 assertThat(d).isNotEqualTo(a); 107 assertThat(d.hashCode()).isNotEqualTo(b.hashCode()); 108 } 109 110 @Test builtinShadowsForSameClass_differentSdkVersions()111 public void builtinShadowsForSameClass_differentSdkVersions() { 112 ImmutableMultimap<String, String> builtinShadows = 113 ImmutableMultimap.of( 114 Activity.class.getCanonicalName(), 115 ShadowActivity29.class.getName(), 116 Activity.class.getCanonicalName(), 117 ShadowActivity30.class.getName()); 118 ImmutableList<ShadowProvider> shadowProviders = 119 ImmutableList.of( 120 new ShadowProvider() { 121 @Override 122 public void reset() {} 123 124 @Override 125 public String[] getProvidedPackageNames() { 126 return new String[0]; 127 } 128 129 @Override 130 public List<Map.Entry<String, String>> getShadows() { 131 return new ArrayList<>(builtinShadows.entries()); 132 } 133 }); 134 ShadowMatcher sdk29 = new AndroidSdkShadowMatcher(29); 135 ShadowMatcher sdk30 = new AndroidSdkShadowMatcher(30); 136 ShadowMap map = ShadowMap.createFromShadowProviders(shadowProviders); 137 assertThat(map.getShadowInfo(Activity.class, sdk29).shadowClassName) 138 .isEqualTo(ShadowActivity29.class.getName()); 139 assertThat(map.getShadowInfo(Activity.class, sdk30).shadowClassName) 140 .isEqualTo(ShadowActivity30.class.getName()); 141 } 142 143 static class Activity {} 144 145 static class A {} 146 static class A1 {} 147 static class A2 {} 148 static class B {} 149 static class B1 {} 150 static class B2 {} 151 static class C1 {} 152 static class C2 {} 153 static class C3 {} 154 static class X {} 155 156 @Implements(value = Activity.class, maxSdk = 29) 157 static class ShadowActivity29 {} 158 159 @Implements(value = Activity.class, minSdk = 30) 160 static class ShadowActivity30 {} 161 } 162