package org.robolectric.res; import javax.annotation.Nonnull; import org.junit.Before; import org.junit.Test; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.Assert.assertEquals; import static org.junit.Assert.fail; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; public class ResBundleTest { private ResBundle.ResMap resMap = new ResBundle.ResMap(); private ResName resName; @Before public void setUp() throws Exception { resName = new ResName("a:b/c"); } @Test public void closestMatchIsPicked() { TypedResource<String> val1 = createStringTypedResource("v16"); resMap.put(resName, val1); TypedResource<String> val2 = createStringTypedResource("v17"); resMap.put(resName, val2); TypedResource v = resMap.pick(resName, "v18"); assertThat(v).isEqualTo(val2); } @Test public void firstValIsPickedWhenNoMatch() { TypedResource<String> val1 = createStringTypedResource("en"); resMap.put(resName, val1); TypedResource<String> val2 = createStringTypedResource("fr"); resMap.put(resName, val2); TypedResource v = resMap.pick(resName, "v18"); assertThat(v).isEqualTo(val1); } @Test public void firstValIsPickedWhenNoQualifiersGiven() { TypedResource<String> val1 = createStringTypedResource("v16"); resMap.put(resName, val1); TypedResource<String> val2 = createStringTypedResource("v17"); resMap.put(resName, val2); TypedResource v = resMap.pick(resName, ""); assertThat(v).isEqualTo(val1); } @Test public void firstValIsPickedWhenNoVersionQualifiersGiven() { TypedResource<String> val1 = createStringTypedResource("v16"); resMap.put(resName, val1); TypedResource<String> val2 = createStringTypedResource("v17"); resMap.put(resName, val2); TypedResource v = resMap.pick(resName, "en"); assertThat(v).isEqualTo(val1); } @Test public void eliminatedValuesAreNotPickedForVersion() { TypedResource<String> val1 = createStringTypedResource("en-v16"); resMap.put(resName, val1); TypedResource<String> val2 = createStringTypedResource("v17"); resMap.put(resName, val2); TypedResource v = resMap.pick(resName, "en-v18"); assertThat(v).isEqualTo(val1); } @Test public void greaterVersionsAreNotPicked() { TypedResource<String> val1 = createStringTypedResource("v11"); resMap.put(resName, val1); TypedResource<String> val2 = createStringTypedResource("v19"); resMap.put(resName, val2); TypedResource v = resMap.pick(resName, "v18"); assertThat(v).isEqualTo(val1); } @Test public void greaterVersionsAreNotPickedReordered() { TypedResource<String> val1 = createStringTypedResource("v19"); resMap.put(resName, val1); TypedResource<String> val2 = createStringTypedResource("v11"); resMap.put(resName, val2); TypedResource v = resMap.pick(resName, "v18"); assertThat(v).isEqualTo(val2); } @Test public void greaterVersionsAreNotPickedMoreQualifiers() { // List the contradicting qualifier first, in case the algorithm has a tendency // to pick the first qualifier when none of the qualifiers are a "perfect" match. TypedResource<String> val1 = createStringTypedResource("anydpi-v21"); resMap.put(resName, val1); TypedResource<String> val2 = createStringTypedResource("xhdpi-v9"); resMap.put(resName, val2); TypedResource v = resMap.pick(resName, "v18"); assertThat(v).isEqualTo(val2); } @Test public void onlyMatchingVersionsQualifiersWillBePicked() { TypedResource<String> val1 = createStringTypedResource("v16"); resMap.put(resName, val1); TypedResource<String> val2 = createStringTypedResource("sw600dp-v17"); resMap.put(resName, val2); TypedResource v = resMap.pick(resName, "v18"); assertThat(v).isEqualTo(val1); } @Test public void illegalResourceQualifierThrowsException() { TypedResource<String> val1 = createStringTypedResource("v11-en-v12"); resMap.put(resName, val1); try { resMap.pick(resName, "v18"); fail("Expected exception to be caught"); } catch (IllegalStateException e) { assertThat(e).hasMessageStartingWith("A resource file was found that had two API level qualifiers: "); } } @Test public void shouldMatchQualifiersPerAndroidSpec() throws Exception { assertEquals("en-port", asResMap( "", "en", "fr-rCA", "en-port", "en-notouch-12key", "port-ldpi", "port-notouch-12key").pick(resName, "en-GB-port-hdpi-notouch-12key").asString()); } @Test public void shouldMatchQualifiersInSizeRange() throws Exception { assertEquals("sw300dp-port", asResMap( "", "sw200dp", "sw350dp-port", "sw300dp-port", "sw300dp").pick(resName, "sw320dp-port").asString()); } @Test public void shouldPreferWidthOverHeight() throws Exception { assertEquals("sw300dp-sh200dp", asResMap( "", "sw200dp", "sw200dp-sh300dp", "sw300dp-sh200dp", "sh300dp").pick(resName, "sw320dp-sh320dp").asString()); } @Test public void shouldNotOverwriteValuesWithMatchingQualifiers() { ResBundle bundle = new ResBundle(); XmlContext xmlContext = mock(XmlContext.class); when(xmlContext.getQualifiers()).thenReturn("--"); when(xmlContext.getPackageName()).thenReturn("org.robolectric"); TypedResource firstValue = new TypedResource<>("first_value", ResType.CHAR_SEQUENCE, xmlContext); TypedResource secondValue = new TypedResource<>("second_value", ResType.CHAR_SEQUENCE, xmlContext); bundle.put(new ResName("org.robolectric", "string", "resource_name"), firstValue); bundle.put(new ResName("org.robolectric", "string", "resource_name"), secondValue); assertThat(bundle.get(new ResName("org.robolectric", "string", "resource_name"), "").getData()).isEqualTo("first_value"); } private ResBundle.ResMap asResMap(String... qualifierses) { ResBundle.ResMap resMap = new ResBundle.ResMap(); for (String qualifiers : qualifierses) { resMap.put(resName, createStringTypedResource(qualifiers, qualifiers)); } return resMap; } private static TypedResource<String> createStringTypedResource(String qualifiers) { return createStringTypedResource("title from resourceLoader1", qualifiers); } @Nonnull private static TypedResource<String> createStringTypedResource(String str, String qualifiers) { XmlContext mockXmlContext = mock(XmlContext.class); when(mockXmlContext.getQualifiers()).thenReturn(qualifiers); return new TypedResource<>(str, ResType.CHAR_SEQUENCE, mockXmlContext); } }