blob: c8140e5f9e3e6988e77775c656fcc442b6be7fd6 [file] [log] [blame]
/*
* Copyright (C) 2013 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.tools.idea.rendering;
import com.android.ide.common.rendering.api.AttrResourceValue;
import com.android.resources.ResourceType;
import com.google.common.collect.ImmutableList;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.command.WriteCommandAction;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.vfs.VfsUtilCore;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.PsiDocumentManager;
import com.intellij.psi.PsiFile;
import com.intellij.psi.PsiManager;
import org.jetbrains.android.AndroidTestCase;
import org.jetbrains.android.facet.AndroidFacet;
import java.io.IOException;
import java.util.Arrays;
import java.util.Collections;
import static com.android.tools.idea.rendering.ModuleResourceRepositoryTest.getFirstItem;
public class AppResourceRepositoryTest extends AndroidTestCase {
private static final String LAYOUT = "resourceRepository/layout.xml";
private static final String VALUES = "resourceRepository/values.xml";
private static final String VALUES_OVERLAY1 = "resourceRepository/valuesOverlay1.xml";
private static final String VALUES_OVERLAY2 = "resourceRepository/valuesOverlay2.xml";
private static final String VALUES_OVERLAY2_NO = "resourceRepository/valuesOverlay2No.xml";
@Override
public void tearDown() throws Exception {
ResourceFolderRegistry.reset();
super.tearDown();
}
public void testStable() {
assertSame(AppResourceRepository.getAppResources(myFacet, true), AppResourceRepository.getAppResources(myFacet, true));
assertSame(AppResourceRepository.getAppResources(myFacet, true), AppResourceRepository.getAppResources(myModule, true));
}
public void testMerging() {
// Like testOverlayUpdates1, but rather than testing changes to layout resources (file-based resource)
// perform document edits in value-documents
VirtualFile layoutFile = myFixture.copyFileToProject(LAYOUT, "res/layout/layout1.xml");
VirtualFile res1 = myFixture.copyFileToProject(VALUES, "res/values/values.xml").getParent().getParent();
VirtualFile res2 = myFixture.copyFileToProject(VALUES_OVERLAY1, "res2/values/values.xml").getParent().getParent();
VirtualFile res3 = myFixture.copyFileToProject(VALUES_OVERLAY2, "res3/values/nameDoesNotMatter.xml").getParent().getParent();
myFixture.copyFileToProject(VALUES_OVERLAY2_NO, "res3/values-no/values.xml");
assertNotSame(res1, res2);
assertNotSame(res1, res3);
assertNotSame(res2, res3);
// res3 is not used as an overlay here; instead we use it to simulate an AAR library below
final ModuleResourceRepository moduleRepository = ModuleResourceRepository.createForTest(myFacet, Arrays.asList(res1, res2));
final ProjectResourceRepository projectResources = ProjectResourceRepository.createForTest(
myFacet, Collections.<LocalResourceRepository>singletonList(moduleRepository));
final AppResourceRepository appResources = AppResourceRepository.createForTest(
myFacet, Collections.<LocalResourceRepository>singletonList(projectResources), Collections.<FileResourceRepository>emptyList());
assertTrue(appResources.hasResourceItem(ResourceType.STRING, "title_card_flip"));
assertFalse(appResources.hasResourceItem(ResourceType.STRING, "non_existent_title_card_flip"));
assertTrue(projectResources.hasResourceItem(ResourceType.STRING, "title_card_flip"));
assertFalse(projectResources.hasResourceItem(ResourceType.STRING, "non_existent_title_card_flip"));
assertTrue(moduleRepository.hasResourceItem(ResourceType.STRING, "title_card_flip"));
assertFalse(moduleRepository.hasResourceItem(ResourceType.STRING, "non_existent_title_card_flip"));
FileResourceRepository aar1 = FileResourceRepository.get(VfsUtilCore.virtualToIoFile(res3));
appResources.updateRoots(Arrays.asList(projectResources, aar1), Collections.singletonList(aar1));
assertTrue(appResources.hasResourceItem(ResourceType.STRING, "another_unique_string"));
assertTrue(aar1.hasResourceItem(ResourceType.STRING, "another_unique_string"));
assertFalse(projectResources.hasResourceItem(ResourceType.STRING, "another_unique_string"));
assertFalse(moduleRepository.hasResourceItem(ResourceType.STRING, "another_unique_string"));
assertTrue(appResources.hasResourceItem(ResourceType.STRING, "title_card_flip"));
assertFalse(appResources.hasResourceItem(ResourceType.STRING, "non_existent_title_card_flip"));
// Update module resource repository and assert that changes make it all the way up
PsiFile layoutPsiFile = PsiManager.getInstance(getProject()).findFile(layoutFile);
assertNotNull(layoutPsiFile);
assertTrue(moduleRepository.hasResourceItem(ResourceType.ID, "btn_title_refresh"));
final PsiResourceItem item = getFirstItem(moduleRepository, ResourceType.ID, "btn_title_refresh");
final long generation = moduleRepository.getModificationCount();
final long projectGeneration = projectResources.getModificationCount();
final long appGeneration = appResources.getModificationCount();
final PsiDocumentManager documentManager = PsiDocumentManager.getInstance(getProject());
final Document document = documentManager.getDocument(layoutPsiFile);
assertNotNull(document);
WriteCommandAction.runWriteCommandAction(getProject(), new Runnable() {
@Override
public void run() {
String string = "<ImageView style=\"@style/TitleBarSeparator\" />";
int offset = document.getText().indexOf(string);
document.deleteString(offset, offset + string.length());
documentManager.commitDocument(document);
}
});
assertTrue(moduleRepository.isScanPending(layoutPsiFile));
ApplicationManager.getApplication().invokeLater(new Runnable() {
@Override
public void run() {
assertTrue(generation < moduleRepository.getModificationCount());
assertTrue(projectGeneration < projectResources.getModificationCount());
assertTrue(appGeneration < appResources.getModificationCount());
// Should still be defined:
assertTrue(moduleRepository.hasResourceItem(ResourceType.ID, "btn_title_refresh"));
assertTrue(appResources.hasResourceItem(ResourceType.ID, "btn_title_refresh"));
assertTrue(projectResources.hasResourceItem(ResourceType.ID, "btn_title_refresh"));
PsiResourceItem newItem = getFirstItem(appResources, ResourceType.ID, "btn_title_refresh");
assertNotNull(newItem.getSource());
// However, should be a different item
assertNotSame(item, newItem);
}
});
}
public void testGetDeclaredArrayValues() throws IOException {
final AppResourceRepository appResources = createTestAppResourceRepository(myFacet);
ImmutableList.Builder<AttrResourceValue> builder = ImmutableList.builder();
// simple styleable test.
ImmutableList<AttrResourceValue> attrList = builder.add(new AttrResourceValue(ResourceType.ATTR, "some-attr", false)).build();
Integer[] foundValues = appResources.getDeclaredArrayValues(attrList, "Styleable1");
assertOrderedEquals(foundValues, 0x7f010000);
// slightly complex test.
builder = ImmutableList.builder();
attrList = builder
.add(new AttrResourceValue(ResourceType.ATTR, "app_attr1", false),
new AttrResourceValue(ResourceType.ATTR, "app_attr2", false),
new AttrResourceValue(ResourceType.ATTR, "framework-attr1", true),
new AttrResourceValue(ResourceType.ATTR, "app_attr3", false),
new AttrResourceValue(ResourceType.ATTR, "framework_attr2", true)).build();
foundValues = appResources.getDeclaredArrayValues(attrList, "Styleable_with_underscore");
assertOrderedEquals(foundValues, 0x7f010000, 0x7f010068, 0x01010125, 0x7f010069, 0x01010142);
}
static AppResourceRepository createTestAppResourceRepository(AndroidFacet facet) throws IOException {
final ModuleResourceRepository moduleRepository = ModuleResourceRepository.createForTest(facet, Collections.<VirtualFile>emptyList());
final ProjectResourceRepository projectResources = ProjectResourceRepository.createForTest(
facet, Collections.<LocalResourceRepository>singletonList(moduleRepository));
final AppResourceRepository appResources = AppResourceRepository.createForTest(
facet, Collections.<LocalResourceRepository>singletonList(projectResources), Collections.<FileResourceRepository>emptyList());
FileResourceRepository aar = FileResourceRepositoryTest.getTestRepository();
appResources.updateRoots(Arrays.asList(projectResources, aar), Collections.singletonList(aar));
return appResources;
}
// TODO: When we can load gradle projects from unit tests, test that we properly override
// library resources (from AARs) with resources in the main app (e.g. that computeRepositories()
// places the libraries *before* the module resources)
}