blob: 0a25b3173c32e4506a59ec87282a74ea3ed94f50 [file] [log] [blame]
// Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
package org.chromium.weblayer.test;
import android.content.Context;
import android.content.res.AssetManager;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.util.SparseArray;
import androidx.test.filters.SmallTest;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.chromium.weblayer.TestWebLayer;
import org.chromium.weblayer.shell.InstrumentationActivity;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.util.HashSet;
import java.util.Locale;
/** Tests that translations work correctly for Java strings inside bundles. */
@RunWith(WebLayerJUnit4ClassRunner.class)
public class BundleLanguageTest {
private static final String WEBLAYER_SPECIFIC_STRING =
"string/infobar_missing_location_permission_text";
private static final String SHARED_STRING = "string/color_picker_dialog_title";
@Rule
public InstrumentationActivityTestRule mActivityTestRule =
new InstrumentationActivityTestRule();
private Context mRemoteContext;
private Context mWebLayerContext;
@Before
public void setUp() throws Exception {
InstrumentationActivity activity = mActivityTestRule.launchShellWithUrl("about:blank");
mRemoteContext = TestWebLayer.getRemoteContext(activity.getApplicationContext());
mWebLayerContext = TestWebLayer.getWebLayerContext(activity.getApplicationContext());
}
@Test
@SmallTest
public void testWebLayerString() throws Exception {
// The bundle tests have both "es" and "fr" splits installed, so each of these should have a
// separate translation.
HashSet<String> translations = new HashSet<>();
for (String locale : new String[] {"en", "es", "fr"}) {
translations.add(getStringForLocale(WEBLAYER_SPECIFIC_STRING, locale));
}
Assert.assertEquals(3, translations.size());
// The "ko" language split is not installed, so should fall back to english.
Assert.assertEquals(getStringForLocale(WEBLAYER_SPECIFIC_STRING, "en"),
getStringForLocale(WEBLAYER_SPECIFIC_STRING, "ko"));
}
@Test
@SmallTest
public void testSharedString() throws Exception {
// This string is shared with WebView, so should have a separate translation for all
// locales, even locales without splits installed.
HashSet<String> translations = new HashSet<>();
for (String locale : new String[] {"en", "es", "fr", "ko"}) {
translations.add(getStringForLocale(SHARED_STRING, locale));
}
Assert.assertEquals(4, translations.size());
}
/**
* Tests that all locale resources have been moved into splits, so the only package ID left in
* the base APK has a dynamic ID.
*/
@Test
@SmallTest
public void testBasePackageIdCorrect() throws Exception {
AssetManager assetManager = createEmptyAssetManager();
addAssetPath(assetManager, mWebLayerContext.getApplicationInfo().sourceDir);
SparseArray<String> packageIds = getPackageIds(assetManager);
Assert.assertEquals(2, packageIds.size());
Assert.assertEquals(packageIds.get(1), "android");
Assert.assertEquals(packageIds.get(2), mWebLayerContext.getPackageName());
}
/** Tests that locale splits only have resources from the hardcoded locale package ID. */
@Test
@SmallTest
public void testLocalePackageIdCorrect() throws Exception {
AssetManager assetManager = createEmptyAssetManager();
for (String path : mWebLayerContext.getApplicationInfo().splitSourceDirs) {
addAssetPath(assetManager, path);
}
SparseArray<String> packageIds = getPackageIds(assetManager);
Assert.assertEquals(2, packageIds.size());
Assert.assertEquals(packageIds.get(1), "android");
Assert.assertEquals(packageIds.get(ResourceUtil.REQUIRED_PACKAGE_IDENTIFIER),
mWebLayerContext.getPackageName() + "_translations");
}
private String getStringForLocale(String name, String locale) {
Resources resources = mRemoteContext.getResources();
Configuration config = resources.getConfiguration();
config.setLocale(new Locale(locale));
resources.updateConfiguration(config, resources.getDisplayMetrics());
return resources.getString(ResourceUtil.getIdentifier(
mRemoteContext, name, mWebLayerContext.getPackageName()));
}
private static AssetManager createEmptyAssetManager() throws ReflectiveOperationException {
Constructor<AssetManager> constructor = AssetManager.class.getDeclaredConstructor();
constructor.setAccessible(true);
return constructor.newInstance();
}
private static void addAssetPath(AssetManager assetManager, String path)
throws ReflectiveOperationException {
Method addAssetPath = AssetManager.class.getMethod("addAssetPath", String.class);
addAssetPath.invoke(assetManager, path);
}
private static SparseArray<String> getPackageIds(AssetManager assetManager)
throws ReflectiveOperationException {
Method getAssignedPackageIdentifiers =
AssetManager.class.getMethod("getAssignedPackageIdentifiers");
return (SparseArray) getAssignedPackageIdentifiers.invoke(assetManager);
}
}