Home | History | Annotate | Download | only in res
      1 package org.robolectric.res;
      2 
      3 import static org.assertj.core.api.Assertions.assertThat;
      4 import static org.junit.Assert.assertEquals;
      5 import static org.junit.Assert.fail;
      6 import static org.mockito.Mockito.mock;
      7 import static org.mockito.Mockito.when;
      8 
      9 import com.google.common.base.Strings;
     10 import javax.annotation.Nonnull;
     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.res.android.ConfigDescription;
     16 import org.robolectric.res.android.ResTable_config;
     17 
     18 @RunWith(JUnit4.class)
     19 public class ResBundleTest {
     20   private ResBundle.ResMap resMap = new ResBundle.ResMap();
     21   private ResName resName;
     22 
     23   @Before
     24   public void setUp() throws Exception {
     25     resName = new ResName("a:b/c");
     26   }
     27 
     28   @Test
     29   public void closestMatchIsPicked() {
     30     TypedResource<String> val1 = createStringTypedResource("v16");
     31     resMap.put(resName, val1);
     32     TypedResource<String> val2 = createStringTypedResource("v17");
     33     resMap.put(resName, val2);
     34 
     35     TypedResource v = resMap.pick(resName, from("v18"));
     36     assertThat(v).isEqualTo(val2);
     37   }
     38 
     39   @Test
     40   public void firstValIsPickedWhenNoMatch() {
     41     TypedResource<String> val1 = createStringTypedResource("en");
     42     resMap.put(resName, val1);
     43     TypedResource<String> val2 = createStringTypedResource("fr");
     44     resMap.put(resName, val2);
     45 
     46     TypedResource v = resMap.pick(resName, from("en-v18"));
     47     assertThat(v).isEqualTo(val1);
     48   }
     49 
     50   @Test
     51   public void bestValIsPickedForSdkVersion() {
     52     TypedResource<String> val1 = createStringTypedResource("v16");
     53     resMap.put(resName, val1);
     54     TypedResource<String> val2 = createStringTypedResource("v17");
     55     resMap.put(resName, val2);
     56 
     57     TypedResource v = resMap.pick(resName, from("v26"));
     58     assertThat(v).isEqualTo(val2);
     59   }
     60 
     61   @Test
     62   public void eliminatedValuesAreNotPickedForVersion() {
     63     TypedResource<String> val1 = createStringTypedResource("land-v16");
     64     resMap.put(resName, val1);
     65     TypedResource<String> val2 = createStringTypedResource("v17");
     66     resMap.put(resName, val2);
     67 
     68     TypedResource v = resMap.pick(resName, from("land-v18"));
     69     assertThat(v).isEqualTo(val1);
     70   }
     71 
     72   @Test
     73   public void greaterVersionsAreNotPicked() {
     74     TypedResource<String> val1 = createStringTypedResource("v11");
     75     resMap.put(resName, val1);
     76     TypedResource<String> val2 = createStringTypedResource("v19");
     77     resMap.put(resName, val2);
     78 
     79     TypedResource v = resMap.pick(resName, from("v18"));
     80     assertThat(v).isEqualTo(val1);
     81   }
     82 
     83   @Test
     84   public void greaterVersionsAreNotPickedReordered() {
     85     TypedResource<String> val1 = createStringTypedResource("v19");
     86     resMap.put(resName, val1);
     87     TypedResource<String> val2 = createStringTypedResource("v11");
     88     resMap.put(resName, val2);
     89 
     90     TypedResource v = resMap.pick(resName, from("v18"));
     91     assertThat(v).isEqualTo(val2);
     92   }
     93 
     94   @Test
     95   public void greaterVersionsAreNotPickedMoreQualifiers() {
     96     // List the contradicting qualifier first, in case the algorithm has a tendency
     97     // to pick the first qualifier when none of the qualifiers are a "perfect" match.
     98     TypedResource<String> val1 = createStringTypedResource("anydpi-v21");
     99     resMap.put(resName, val1);
    100     TypedResource<String> val2 = createStringTypedResource("xhdpi-v9");
    101     resMap.put(resName, val2);
    102 
    103     TypedResource v = resMap.pick(resName, from("v18"));
    104     assertThat(v).isEqualTo(val2);
    105   }
    106 
    107   @Test
    108   public void onlyMatchingVersionsQualifiersWillBePicked() {
    109     TypedResource<String> val1 = createStringTypedResource("v16");
    110     resMap.put(resName, val1);
    111     TypedResource<String> val2 = createStringTypedResource("sw600dp-v17");
    112     resMap.put(resName, val2);
    113 
    114     TypedResource v = resMap.pick(resName, from("v18"));
    115     assertThat(v).isEqualTo(val1);
    116   }
    117 
    118   @Test
    119   public void illegalResourceQualifierThrowsException() {
    120     TypedResource<String> val1 = createStringTypedResource("en-v12");
    121     resMap.put(resName, val1);
    122 
    123     try {
    124       resMap.pick(resName, from("nosuchqualifier"));
    125       fail("Expected exception to be caught");
    126     } catch (IllegalArgumentException e) {
    127       assertThat(e).hasMessageStartingWith("Invalid qualifiers \"nosuchqualifier\"");
    128     }
    129   }
    130 
    131   @Test
    132   public void shouldMatchQualifiersPerAndroidSpec() throws Exception {
    133     assertEquals("en-port", asResMap(
    134         "",
    135         "en",
    136         "fr-rCA",
    137         "en-port",
    138         "en-notouch-12key",
    139         "port-ldpi",
    140         "land-notouch-12key").pick(resName,
    141         from("en-rGB-port-hdpi-notouch-12key-v25")).asString());
    142   }
    143 
    144   @Test
    145   public void shouldMatchQualifiersInSizeRange() throws Exception {
    146     assertEquals("sw300dp-port", asResMap(
    147         "",
    148         "sw200dp",
    149         "sw350dp-port",
    150         "sw300dp-port",
    151         "sw300dp").pick(resName,
    152         from("sw320dp-port-v25")).asString());
    153   }
    154 
    155   @Test
    156   public void shouldPreferWidthOverHeight() throws Exception {
    157     assertEquals("sw300dp-w200dp", asResMap(
    158         "",
    159         "sw200dp",
    160         "sw200dp-w300dp",
    161         "sw300dp-w200dp",
    162         "w300dp").pick(resName,
    163         from("sw320dp-w320dp-v25")).asString());
    164   }
    165 
    166   @Test
    167   public void shouldNotOverwriteValuesWithMatchingQualifiers() {
    168     ResBundle bundle = new ResBundle();
    169     XmlContext xmlContext = mock(XmlContext.class);
    170     when(xmlContext.getQualifiers()).thenReturn(Qualifiers.parse("--"));
    171     when(xmlContext.getConfig()).thenReturn(new ResTable_config());
    172     when(xmlContext.getPackageName()).thenReturn("org.robolectric");
    173 
    174     TypedResource firstValue = new TypedResource<>("first_value", ResType.CHAR_SEQUENCE, xmlContext);
    175     TypedResource secondValue = new TypedResource<>("second_value", ResType.CHAR_SEQUENCE, xmlContext);
    176     bundle.put(new ResName("org.robolectric", "string", "resource_name"), firstValue);
    177     bundle.put(new ResName("org.robolectric", "string", "resource_name"), secondValue);
    178 
    179     assertThat(bundle.get(new ResName("org.robolectric", "string", "resource_name"), from("")).getData()).isEqualTo("first_value");
    180   }
    181 
    182   private ResBundle.ResMap asResMap(String... qualifierses) {
    183     ResBundle.ResMap resMap = new ResBundle.ResMap();
    184     for (String qualifiers : qualifierses) {
    185       resMap.put(resName, createStringTypedResource(qualifiers, qualifiers));
    186     }
    187     return resMap;
    188   }
    189 
    190   private static TypedResource<String> createStringTypedResource(String qualifiers) {
    191     return createStringTypedResource("title from resourceLoader1", qualifiers);
    192   }
    193 
    194   @Nonnull
    195   private static TypedResource<String> createStringTypedResource(String str, String qualifiersStr) {
    196     XmlContext mockXmlContext = mock(XmlContext.class);
    197     Qualifiers qualifiers = Qualifiers.parse(qualifiersStr);
    198     when(mockXmlContext.getQualifiers()).thenReturn(qualifiers);
    199     when(mockXmlContext.getConfig()).thenReturn(qualifiers.getConfig());
    200     return new TypedResource<>(str, ResType.CHAR_SEQUENCE, mockXmlContext);
    201   }
    202 
    203   private static ResTable_config from(String qualifiers) {
    204     ResTable_config config = new ResTable_config();
    205     if (!Strings.isNullOrEmpty(qualifiers) &&
    206         !ConfigDescription.parse(qualifiers, config, false)) {
    207       throw new IllegalArgumentException("Invalid qualifiers \"" + qualifiers + "\"");
    208     }
    209     return config;
    210   }
    211 }