summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authordgn <dgn@chromium.org>2015-11-10 07:33:50 -0800
committerCommit bot <commit-bot@chromium.org>2015-11-10 15:34:41 +0000
commit738fa38d347a0f3f71a41c23cb4f03618e071d7c (patch)
tree7077acf341277cc5ea55f56e671b7f1cf102e4f0
parentaf229b2ae84edd77a6c5c40adf5e34c88805d630 (diff)
downloadchromium_src-738fa38d347a0f3f71a41c23cb4f03618e071d7c.zip
chromium_src-738fa38d347a0f3f71a41c23cb4f03618e071d7c.tar.gz
chromium_src-738fa38d347a0f3f71a41c23cb4f03618e071d7c.tar.bz2
Update webview and chrome instrumentation test to use PreTestHooks for policies
- Add utilities to set policies for tests using anotation and pre test hooks - Add AwInstrumentationTestRunner and update ChromeInstrumentationTestRunner to register said hooks - Add classes to simplify building policy bundles BUG=542859 Review URL: https://codereview.chromium.org/1387633002 Cr-Commit-Position: refs/heads/master@{#358829}
-rw-r--r--android_webview/android_webview_tests.gypi3
-rw-r--r--android_webview/javatests/AndroidManifest.xml2
-rw-r--r--android_webview/javatests/DEPS1
-rw-r--r--android_webview/javatests/src/org/chromium/android_webview/test/PolicyUrlFilteringTest.java126
-rw-r--r--android_webview/test/shell/DEPS1
-rw-r--r--android_webview/test/shell/src/org/chromium/android_webview/test/AwInstrumentationTestRunner.java22
-rw-r--r--chrome/chrome_tests.gypi1
-rw-r--r--chrome/test/android/BUILD.gn1
-rw-r--r--chrome/test/android/javatests/src/org/chromium/chrome/test/ChromeInstrumentationTestRunner.java3
-rw-r--r--components/components_tests.gyp9
-rw-r--r--components/policy.gypi14
-rw-r--r--components/policy/android/BUILD.gn20
-rw-r--r--components/policy/android/java/src/org/chromium/policy/AbstractAppRestrictionsProvider.java25
-rw-r--r--components/policy/android/javatests/src/org/chromium/policy/test/PolicyData.java119
-rw-r--r--components/policy/android/javatests/src/org/chromium/policy/test/annotations/Policies.java141
-rw-r--r--components/policy/android/junit/src/org/chromium/policy/test/annotations/PoliciesTest.java94
16 files changed, 501 insertions, 81 deletions
diff --git a/android_webview/android_webview_tests.gypi b/android_webview/android_webview_tests.gypi
index 14c90ca..a5af244 100644
--- a/android_webview/android_webview_tests.gypi
+++ b/android_webview/android_webview_tests.gypi
@@ -11,6 +11,8 @@
'android_webview_java',
'android_webview_pak',
'libdrawgl',
+ '../base/base.gyp:base_java_test_support',
+ '../components/components.gyp:policy_java_test_support'
],
'variables': {
'apk_name': 'AndroidWebView',
@@ -96,6 +98,7 @@
'type': 'none',
'dependencies': [
'../base/base.gyp:base_java_test_support',
+ '../components/components.gyp:policy_java_test_support',
'../content/content_shell_and_tests.gyp:content_java_test_support',
'../net/net.gyp:net_java_test_support',
'../testing/android/on_device_instrumentation.gyp:broker_java',
diff --git a/android_webview/javatests/AndroidManifest.xml b/android_webview/javatests/AndroidManifest.xml
index fb3db24..ed0ae66 100644
--- a/android_webview/javatests/AndroidManifest.xml
+++ b/android_webview/javatests/AndroidManifest.xml
@@ -5,7 +5,7 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="org.chromium.android_webview.test">
<uses-sdk android:minSdkVersion="19" android:targetSdkVersion="23" />
- <instrumentation android:name="org.chromium.base.test.BaseInstrumentationTestRunner"
+ <instrumentation android:name="org.chromium.android_webview.test.AwInstrumentationTestRunner"
android:targetPackage="org.chromium.android_webview.shell"
android:label="Tests for org.chromium.android_webview"/>
<uses-permission android:name="android.permission.RUN_INSTRUMENTATION" />
diff --git a/android_webview/javatests/DEPS b/android_webview/javatests/DEPS
index e2a33b1..24ccfae 100644
--- a/android_webview/javatests/DEPS
+++ b/android_webview/javatests/DEPS
@@ -1,6 +1,7 @@
include_rules = [
"+components/external_video_surface/android/java",
"+components/policy/android/java",
+ "+components/policy/android/javatests",
"+content/public/android/java",
"+content/public/test/android/javatests",
]
diff --git a/android_webview/javatests/src/org/chromium/android_webview/test/PolicyUrlFilteringTest.java b/android_webview/javatests/src/org/chromium/android_webview/test/PolicyUrlFilteringTest.java
index 7c2629e..32bdae7 100644
--- a/android_webview/javatests/src/org/chromium/android_webview/test/PolicyUrlFilteringTest.java
+++ b/android_webview/javatests/src/org/chromium/android_webview/test/PolicyUrlFilteringTest.java
@@ -4,10 +4,8 @@
package org.chromium.android_webview.test;
-import android.os.Bundle;
import android.test.suitebuilder.annotation.MediumTest;
import android.test.suitebuilder.annotation.SmallTest;
-import android.text.TextUtils;
import android.util.Pair;
import org.chromium.android_webview.AwContents;
@@ -17,9 +15,13 @@ import org.chromium.base.ThreadUtils;
import org.chromium.base.test.util.Feature;
import org.chromium.content.browser.test.util.TestCallbackHelperContainer;
import org.chromium.net.test.util.TestWebServer;
+import org.chromium.policy.AbstractAppRestrictionsProvider;
import org.chromium.policy.CombinedPolicyProvider;
+import org.chromium.policy.test.PolicyData;
+import org.chromium.policy.test.annotations.Policies;
import java.util.ArrayList;
+import java.util.Arrays;
/** Tests for the policy based URL filtering. */
public class PolicyUrlFilteringTest extends AwTestBase {
@@ -28,7 +30,8 @@ public class PolicyUrlFilteringTest extends AwTestBase {
private TestWebServer mWebServer;
private String mFooTestUrl;
private String mBarTestUrl;
- private AwPolicyProvider mTestProvider;
+ private static final String sFooTestFilePath = "/foo.html";
+ private static final String sFooWhitelistFilter = "localhost" + sFooTestFilePath;
private static final String sBlacklistPolicyName = "com.android.browser:URLBlacklist";
private static final String sWhitelistPolicyName = "com.android.browser:URLWhitelist";
@@ -36,21 +39,14 @@ public class PolicyUrlFilteringTest extends AwTestBase {
@Override
public void setUp() throws Exception {
super.setUp();
- setTestAwContentsClient(new TestAwContentsClient());
+ mContentsClient = new TestAwContentsClient();
+ mAwContents = createAwTestContainerViewOnMainSync(mContentsClient).getAwContents();
mWebServer = TestWebServer.start();
- mFooTestUrl = mWebServer.setResponse("/foo.html", "<html><body>foo</body></html>",
+ mFooTestUrl = mWebServer.setResponse(sFooTestFilePath, "<html><body>foo</body></html>",
new ArrayList<Pair<String, String>>());
mBarTestUrl = mWebServer.setResponse("/bar.html", "<html><body>bar</body></html>",
new ArrayList<Pair<String, String>>());
- ThreadUtils.runOnUiThreadBlocking(new Runnable() {
- @Override
- public void run() {
- mTestProvider = new AwPolicyProvider(getActivity().getApplicationContext());
- CombinedPolicyProvider.get().registerProvider(mTestProvider);
- }
- });
-
getInstrumentation().waitForIdleSync();
}
@@ -60,97 +56,83 @@ public class PolicyUrlFilteringTest extends AwTestBase {
super.tearDown();
}
- private void setTestAwContentsClient(TestAwContentsClient contentsClient) throws Exception {
- mContentsClient = contentsClient;
- final AwTestContainerView testContainerView =
- createAwTestContainerViewOnMainSync(mContentsClient);
- mAwContents = testContainerView.getAwContents();
- }
-
// Tests transforming the bundle to native policies, reloading the policies and blocking
// the navigation.
@MediumTest
@Feature({"AndroidWebView", "Policy"})
public void testBlacklistedUrl() throws Throwable {
- TestCallbackHelperContainer.OnReceivedErrorHelper onReceivedErrorHelper =
- mContentsClient.getOnReceivedErrorHelper();
- TestCallbackHelperContainer.OnPageFinishedHelper onPageFinishedHelper =
- mContentsClient.getOnPageFinishedHelper();
+ final AwPolicyProvider testProvider =
+ new AwPolicyProvider(getActivity().getApplicationContext());
+ ThreadUtils.runOnUiThreadBlocking(new Runnable() {
+ @Override
+ public void run() {
+ CombinedPolicyProvider.get().registerProvider(testProvider);
+ }
+ });
- loadUrlSync(mAwContents, onPageFinishedHelper, mFooTestUrl);
- assertEquals(mFooTestUrl, onPageFinishedHelper.getUrl());
- assertEquals(0, onReceivedErrorHelper.getCallCount());
+ navigateAndCheckOutcome(mFooTestUrl, 0);
- setFilteringPolicy(new String[] {"localhost"}, new String[] {});
+ setFilteringPolicy(testProvider, new String[] {"localhost"}, new String[] {});
- loadUrlSync(mAwContents, onPageFinishedHelper, mFooTestUrl);
- assertEquals(mFooTestUrl, onPageFinishedHelper.getUrl());
- assertEquals(1, onReceivedErrorHelper.getCallCount());
- assertEquals(ErrorCodeConversionHelper.ERROR_CONNECT, onReceivedErrorHelper.getErrorCode());
+ navigateAndCheckOutcome(mFooTestUrl, 1);
+ assertEquals(ErrorCodeConversionHelper.ERROR_CONNECT,
+ mContentsClient.getOnReceivedErrorHelper().getErrorCode());
}
- // Tests transforming the bundle to native policies, reloading the policies and getting a
- // successful navigation with a whitelist.
+ // Tests getting a successful navigation with a whitelist.
@MediumTest
@Feature({"AndroidWebView", "Policy"})
+ @Policies.Add({
+ @Policies.Item(key = sBlacklistPolicyName, stringArray = {"*"}),
+ @Policies.Item(key = sWhitelistPolicyName, stringArray = {sFooWhitelistFilter})})
public void testWhitelistedUrl() throws Throwable {
- TestCallbackHelperContainer.OnReceivedErrorHelper onReceivedErrorHelper =
- mContentsClient.getOnReceivedErrorHelper();
- TestCallbackHelperContainer.OnPageFinishedHelper onPageFinishedHelper =
- mContentsClient.getOnPageFinishedHelper();
- setFilteringPolicy(new String[] {"*"}, new String[] {mFooTestUrl});
-
- loadUrlSync(mAwContents, onPageFinishedHelper, mFooTestUrl);
- assertEquals(mFooTestUrl, onPageFinishedHelper.getUrl());
- assertEquals(0, onReceivedErrorHelper.getCallCount());
+ navigateAndCheckOutcome(mFooTestUrl, 0);
// Make sure it goes through the blacklist
- loadUrlSync(mAwContents, onPageFinishedHelper, mBarTestUrl);
- assertEquals(mBarTestUrl, onPageFinishedHelper.getUrl());
- assertEquals(1, onReceivedErrorHelper.getCallCount());
- assertEquals(ErrorCodeConversionHelper.ERROR_CONNECT, onReceivedErrorHelper.getErrorCode());
+ navigateAndCheckOutcome(mBarTestUrl, 1);
+ assertEquals(ErrorCodeConversionHelper.ERROR_CONNECT,
+ mContentsClient.getOnReceivedErrorHelper().getErrorCode());
}
// Tests that bad policy values are properly handled
@SmallTest
@Feature({"AndroidWebView", "Policy"})
+ @Policies.Add({
+ @Policies.Item(key = sBlacklistPolicyName, string = "shouldBeAJsonArrayNotAString")})
public void testBadPolicyValue() throws Exception {
- final Bundle newPolicies = new Bundle();
- newPolicies.putString(sBlacklistPolicyName, "shouldBeAJsonArrayNotAString");
- ThreadUtils.runOnUiThreadBlocking(new Runnable() {
- @Override
- public void run() {
- mTestProvider.notifySettingsAvailable(newPolicies);
- }
- });
- getInstrumentation().waitForIdleSync();
+ navigateAndCheckOutcome(mFooTestUrl, 0);
+ // At the moment this test is written, a failure is a crash, a success is no crash.
+ }
+ /**
+ * Synchronously loads the provided URL and checks that the number or reported errors for the
+ * current context is the expected one.
+ */
+ private void navigateAndCheckOutcome(String url, int expectedErrorCount) throws Exception {
+ TestCallbackHelperContainer.OnReceivedErrorHelper onReceivedErrorHelper =
+ mContentsClient.getOnReceivedErrorHelper();
TestCallbackHelperContainer.OnPageFinishedHelper onPageFinishedHelper =
mContentsClient.getOnPageFinishedHelper();
- loadUrlSync(mAwContents, onPageFinishedHelper, mFooTestUrl);
- // At the moment this test is written, a failure is a crash, a success is no crash.
+ loadUrlSync(mAwContents, onPageFinishedHelper, url);
+ assertEquals(url, onPageFinishedHelper.getUrl());
+ assertEquals(expectedErrorCount, onReceivedErrorHelper.getCallCount());
}
- private void setFilteringPolicy(final String[] blacklistUrls, final String[] whitelistUrls) {
- final Bundle newPolicies = new Bundle();
-
- if (blacklistUrls != null && blacklistUrls.length > 0) {
- String blacklistString =
- String.format("[\"%s\"]", TextUtils.join("\",\"", blacklistUrls));
- newPolicies.putString(sBlacklistPolicyName, blacklistString);
- }
+ private void setFilteringPolicy(final AwPolicyProvider testProvider,
+ final String[] blacklistUrls, final String[] whitelistUrls) {
+ final PolicyData[] policies = {
+ new PolicyData.StrArray(sBlacklistPolicyName, blacklistUrls),
+ new PolicyData.StrArray(sWhitelistPolicyName, whitelistUrls)
+ };
- if (whitelistUrls != null && whitelistUrls.length > 0) {
- String whitelistString =
- String.format("[\"%s\"]", TextUtils.join("\",\"", whitelistUrls));
- newPolicies.putString(sWhitelistPolicyName, whitelistString);
- }
+ AbstractAppRestrictionsProvider.setTestRestrictions(
+ PolicyData.asBundle(Arrays.asList(policies)));
ThreadUtils.runOnUiThreadBlocking(new Runnable() {
@Override
public void run() {
- mTestProvider.notifySettingsAvailable(newPolicies);
+ testProvider.refresh();
}
});
diff --git a/android_webview/test/shell/DEPS b/android_webview/test/shell/DEPS
index 0d019e1..2a76d5b 100644
--- a/android_webview/test/shell/DEPS
+++ b/android_webview/test/shell/DEPS
@@ -1,3 +1,4 @@
include_rules = [
+ "+components/policy/android/javatests",
"+content/public/android/java",
]
diff --git a/android_webview/test/shell/src/org/chromium/android_webview/test/AwInstrumentationTestRunner.java b/android_webview/test/shell/src/org/chromium/android_webview/test/AwInstrumentationTestRunner.java
new file mode 100644
index 0000000..84f9ceb
--- /dev/null
+++ b/android_webview/test/shell/src/org/chromium/android_webview/test/AwInstrumentationTestRunner.java
@@ -0,0 +1,22 @@
+// Copyright 2015 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.android_webview.test;
+
+import org.chromium.base.test.BaseInstrumentationTestRunner;
+import org.chromium.base.test.BaseTestResult;
+import org.chromium.policy.test.annotations.Policies;
+
+/**
+ * Instrumentation test runner that allows integrating features defined above base layer
+ * for webview testing.
+ */
+public class AwInstrumentationTestRunner extends BaseInstrumentationTestRunner {
+ @Override
+ protected void addTestHooks(BaseTestResult result) {
+ super.addTestHooks(result);
+
+ result.addPreTestHook(Policies.getRegistrationHook());
+ }
+}
diff --git a/chrome/chrome_tests.gypi b/chrome/chrome_tests.gypi
index fc6b75b..bbf0c97 100644
--- a/chrome/chrome_tests.gypi
+++ b/chrome/chrome_tests.gypi
@@ -3152,6 +3152,7 @@
'chrome_java',
'../base/base.gyp:base_java',
'../base/base.gyp:base_java_test_support',
+ '../components/components.gyp:policy_java_test_support',
'../content/content_shell_and_tests.gyp:content_java_test_support',
'../net/net.gyp:net_java',
'../net/net.gyp:net_java_test_support',
diff --git a/chrome/test/android/BUILD.gn b/chrome/test/android/BUILD.gn
index 6b59c31..1f65910 100644
--- a/chrome/test/android/BUILD.gn
+++ b/chrome/test/android/BUILD.gn
@@ -16,6 +16,7 @@ android_library("chrome_java_test_support") {
"//components/bookmarks/common/android:bookmarks_java",
"//components/invalidation/impl:java",
"//components/policy/android:policy_java",
+ "//components/policy/android:policy_java_test_support",
"//components/web_contents_delegate_android:web_contents_delegate_android_java",
"//content/public/android:content_java",
"//content/public/test/android:content_java_test_support",
diff --git a/chrome/test/android/javatests/src/org/chromium/chrome/test/ChromeInstrumentationTestRunner.java b/chrome/test/android/javatests/src/org/chromium/chrome/test/ChromeInstrumentationTestRunner.java
index 16cfa52..2abc171 100644
--- a/chrome/test/android/javatests/src/org/chromium/chrome/test/ChromeInstrumentationTestRunner.java
+++ b/chrome/test/android/javatests/src/org/chromium/chrome/test/ChromeInstrumentationTestRunner.java
@@ -19,6 +19,7 @@ import org.chromium.base.test.util.Restriction;
import org.chromium.chrome.browser.util.FeatureUtilities;
import org.chromium.chrome.test.util.DisableInTabbedMode;
import org.chromium.net.test.BaseHttpTestServer;
+import org.chromium.policy.test.annotations.Policies;
import org.chromium.ui.base.DeviceFormFactor;
import java.io.File;
@@ -214,6 +215,8 @@ public class ChromeInstrumentationTestRunner extends BaseInstrumentationTestRunn
super.addTestHooks(result);
result.addSkipCheck(new DisableInTabbedModeSkipCheck());
result.addSkipCheck(new ChromeRestrictionSkipCheck());
+
+ result.addPreTestHook(Policies.getRegistrationHook());
}
private class ChromeRestrictionSkipCheck extends RestrictionSkipCheck {
diff --git a/components/components_tests.gyp b/components/components_tests.gyp
index 198e0765..f9975f0 100644
--- a/components/components_tests.gyp
+++ b/components/components_tests.gyp
@@ -1567,17 +1567,12 @@
'type': 'none',
'dependencies': [
'components.gyp:invalidation_java',
+ 'components.gyp:policy_java',
+ 'components.gyp:policy_java_test_support',
'../base/base.gyp:base_java',
'../base/base.gyp:base_java_test_support',
'../testing/android/junit/junit_test.gyp:junit_test_support',
],
- 'conditions': [
- ['configuration_policy == 1', {
- 'dependencies': [
- 'components.gyp:policy_java',
- ],
- }],
- ],
'variables': {
'main_class': 'org.chromium.testing.local.JunitTestMain',
'src_paths': [
diff --git a/components/policy.gypi b/components/policy.gypi
index 7788538..6380877 100644
--- a/components/policy.gypi
+++ b/components/policy.gypi
@@ -427,6 +427,20 @@
},
'includes': [ '../build/java.gypi' ],
},
+ {
+ # GN: //components/policy/android:policy_java_test_support
+ 'target_name': 'policy_java_test_support',
+ 'type': 'none',
+ 'dependencies': [
+ '../base/base.gyp:base_java',
+ '../base/base.gyp:base_java_test_support',
+ 'policy_java'
+ ],
+ 'variables': {
+ 'java_in_dir': 'policy/android/javatests',
+ },
+ 'includes': [ '../build/java.gypi' ],
+ },
],
}],
['OS=="win" and target_arch=="ia32" and configuration_policy==1', {
diff --git a/components/policy/android/BUILD.gn b/components/policy/android/BUILD.gn
index 53bc165..ab1003b 100644
--- a/components/policy/android/BUILD.gn
+++ b/components/policy/android/BUILD.gn
@@ -22,6 +22,20 @@ android_library("policy_java") {
]
}
+# GYP: //components/components.gyp:policy_test_support_java
+android_library("policy_java_test_support") {
+ testonly = true
+ deps = [
+ "//base:base_java",
+ "//base:base_java_test_support",
+ ":policy_java",
+ ]
+ java_files = [
+ "javatests/src/org/chromium/policy/test/annotations/Policies.java",
+ "javatests/src/org/chromium/policy/test/PolicyData.java",
+ ]
+}
+
# GYP: //components/components.gyp:policy_jni_headers
generate_jni("jni_headers") {
visibility = [ "//components/policy/*" ]
@@ -29,13 +43,17 @@ generate_jni("jni_headers") {
jni_package = "policy"
}
+# GYP: //components/components_test.gyp:components_junit_tests
junit_binary("components_policy_junit_tests") {
java_files = [
"junit/src/org/chromium/policy/AbstractAppRestrictionsProviderTest.java",
"junit/src/org/chromium/policy/CombinedPolicyProviderTest.java",
+ "junit/src/org/chromium/policy/test/annotations/PoliciesTest.java",
]
deps = [
- "//base:base_java",
+ ":policy_java_test_support",
":policy_java",
+ "//base:base_java",
+ "//third_party/junit:hamcrest",
]
}
diff --git a/components/policy/android/java/src/org/chromium/policy/AbstractAppRestrictionsProvider.java b/components/policy/android/java/src/org/chromium/policy/AbstractAppRestrictionsProvider.java
index 60b40bd..82b1939 100644
--- a/components/policy/android/java/src/org/chromium/policy/AbstractAppRestrictionsProvider.java
+++ b/components/policy/android/java/src/org/chromium/policy/AbstractAppRestrictionsProvider.java
@@ -15,6 +15,7 @@ import android.os.Parcel;
import android.preference.PreferenceManager;
import android.util.Base64;
+import org.chromium.base.Log;
import org.chromium.base.VisibleForTesting;
import org.chromium.base.metrics.RecordHistogram;
@@ -30,6 +31,11 @@ import java.util.concurrent.Executor;
public abstract class AbstractAppRestrictionsProvider extends PolicyProvider {
private static final String PREFERENCE_KEY = "App Restrictions";
+ private static final String TAG = "policy";
+
+ /** {@link Bundle} holding the restrictions to be used during tests. */
+ private static Bundle sTestRestrictions = null;
+
private final Context mContext;
private final SharedPreferences mSharedPreferences;
private final BroadcastReceiver mAppRestrictionsChangedReceiver = new BroadcastReceiver() {
@@ -79,6 +85,11 @@ public abstract class AbstractAppRestrictionsProvider extends PolicyProvider {
*/
@Override
public void refresh() {
+ if (sTestRestrictions != null) {
+ notifySettingsAvailable(sTestRestrictions);
+ return;
+ }
+
final Bundle cachedResult = getCachedPolicies();
if (cachedResult != null) {
notifySettingsAvailable(cachedResult);
@@ -169,4 +180,18 @@ public abstract class AbstractAppRestrictionsProvider extends PolicyProvider {
void setTaskExecutor(Executor testExecutor) {
mExecutor = testExecutor;
}
+
+ /**
+ * Restrictions to be used during tests. Subsequent attempts to retrieve the restrictions will
+ * return the provided bundle instead.
+ *
+ * Chrome and WebView tests are set up to use annotations for policy testing and reset the
+ * restrictions to an empty bundle if nothing is specified. To stop using a test bundle,
+ * provide {@code null} as value instead.
+ */
+ @VisibleForTesting
+ public static void setTestRestrictions(Bundle policies) {
+ Log.d(TAG, "Test Restrictions: %s", policies.keySet().toArray());
+ sTestRestrictions = policies;
+ }
}
diff --git a/components/policy/android/javatests/src/org/chromium/policy/test/PolicyData.java b/components/policy/android/javatests/src/org/chromium/policy/test/PolicyData.java
new file mode 100644
index 0000000..6b230d8
--- /dev/null
+++ b/components/policy/android/javatests/src/org/chromium/policy/test/PolicyData.java
@@ -0,0 +1,119 @@
+// Copyright 2015 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.policy.test;
+
+import android.os.Bundle;
+
+import junit.framework.Assert;
+
+import org.chromium.base.Log;
+import org.json.JSONArray;
+
+/**
+ * Helper class to transform Java types to {@link Bundle}s usable by the Policy system.
+ *
+ * Use the subclasses to define the data and then transform it using {@link #asBundle(Iterable)}
+ */
+public abstract class PolicyData {
+ private static final String TAG = "policy_test";
+ private final String mKey;
+
+ public PolicyData(String key) {
+ mKey = key;
+ }
+
+ public String getKey() {
+ return mKey;
+ }
+
+ public abstract void putInBundle(Bundle bundle);
+
+ public static Bundle asBundle(Iterable<PolicyData> policies) {
+ Bundle bundle = new Bundle();
+ for (PolicyData data : policies) {
+ Log.d(TAG, "Adding to policy bundle: %s", data);
+ data.putInBundle(bundle);
+ }
+ return bundle;
+ }
+
+ /** {@link PolicyData} for the {@link String} type. */
+ public static class Str extends PolicyData {
+ private final String mValue;
+
+ public Str(String key, String value) {
+ super(key);
+ mValue = value;
+ }
+
+ public String getValue() {
+ return mValue;
+ }
+
+ @Override
+ public void putInBundle(Bundle bundle) {
+ bundle.putString(getKey(), mValue);
+ }
+
+ @Override
+ public String toString() {
+ return String.format("PolicyData.Str{%s=%s}", getKey(), mValue);
+ }
+ }
+
+ /** {@link PolicyData} with no value, for error states. Doesn't put anything in a bundle.*/
+ public static class Undefined extends PolicyData {
+ public Undefined(String key) {
+ super(key);
+ }
+
+ @Override
+ public void putInBundle(Bundle bundle) {
+ Assert.fail(String.format(
+ "Attempted to push the '%s' policy without value to a bundle.", getKey()));
+ }
+
+ @Override
+ public String toString() {
+ return String.format("PolicyData.Undefined{%s}", getKey());
+ }
+ }
+
+ /**
+ * {@link PolicyData} for the {@link String} array type.
+ * Outputs a string encoded as a JSON array.
+ */
+ public static class StrArray extends PolicyData {
+ private final String[] mValue;
+
+ public StrArray(String key, String[] value) {
+ super(key);
+ mValue = value.clone();
+ }
+
+ public String[] getValue() {
+ return mValue.clone();
+ }
+
+ private String valueToString() {
+ // JSONArray(Object[]) requires API 19
+ JSONArray array = new JSONArray();
+ for (String s : mValue) {
+ array.put(s);
+ }
+ return array.toString();
+ }
+
+ @Override
+ public void putInBundle(Bundle bundle) {
+ bundle.putString(getKey(), valueToString());
+ }
+
+ @Override
+ public String toString() {
+ return String.format("PolicyData.StrArray{%s=%s}", getKey(), valueToString());
+ }
+ }
+} \ No newline at end of file
diff --git a/components/policy/android/javatests/src/org/chromium/policy/test/annotations/Policies.java b/components/policy/android/javatests/src/org/chromium/policy/test/annotations/Policies.java
new file mode 100644
index 0000000..11b7be2
--- /dev/null
+++ b/components/policy/android/javatests/src/org/chromium/policy/test/annotations/Policies.java
@@ -0,0 +1,141 @@
+// Copyright 2015 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.policy.test.annotations;
+
+import android.content.Context;
+import android.os.Bundle;
+
+import junit.framework.Assert;
+
+import org.chromium.base.VisibleForTesting;
+import org.chromium.base.test.BaseTestResult.PreTestHook;
+import org.chromium.policy.AbstractAppRestrictionsProvider;
+import org.chromium.policy.test.PolicyData;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Inherited;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+import java.lang.reflect.AnnotatedElement;
+import java.lang.reflect.Method;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * Annotations and utilities for testing code dependent on policies.
+ *
+ * Usage example:
+ * <pre>
+ * @Policies.Add({
+ * @Policies.Item(key="Foo", string="Bar"),
+ * @Policies.Item(key="Baz", stringArray={"Baz"})
+ * })
+ * public class MyTestClass extends BaseActivityInstrumentationTestCase<ContentActivity> {
+ *
+ * public void MyTest1() {
+ * // Will run the Foo and Bar policies set
+ * }
+ *
+ * @Policies.Remove(@Policies.Item(key="Baz"))
+ * public void MyTest2() {
+ * // Will run with only the Foo policy set
+ * }
+ * }
+ * </pre>
+ */
+public final class Policies {
+ /** Items declared here will be added to the list of used policies. */
+ @Inherited
+ @Retention(RetentionPolicy.RUNTIME)
+ @Target({ElementType.METHOD, ElementType.TYPE})
+ public @interface Add {
+ Item[] value();
+ }
+
+ /** Items declared here will be removed from the list of used policies. */
+ @Inherited
+ @Retention(RetentionPolicy.RUNTIME)
+ @Target({ElementType.METHOD, ElementType.TYPE})
+ public @interface Remove {
+ Item[] value();
+ }
+
+ /**
+ * Individual policy item. Identified by a {@link #key}, and optional data values.
+ * At most one value argument (e.g. {@link #string()}, {@link #stringArray()}) can be used. A
+ * test failure will be caused otherwise.
+ */
+ @Inherited
+ @Retention(RetentionPolicy.RUNTIME)
+ @Target({ElementType.METHOD, ElementType.TYPE})
+ public @interface Item {
+ String key();
+
+ String string() default "";
+
+ String[] stringArray() default {};
+ }
+
+ /** Parses the annotations to extract usable information as {@link PolicyData} objects. */
+ private static Map<String, PolicyData> fromItems(Item[] items) {
+ Map<String, PolicyData> result = new HashMap<>();
+ for (Item item : items) {
+ PolicyData data = null;
+
+ if (!item.string().isEmpty()) {
+ Assert.assertNull("There can be at most one type of value for the policy", data);
+ data = new PolicyData.Str(item.key(), item.string());
+ }
+
+ if (item.stringArray().length != 0) {
+ Assert.assertNull("There can be at most one type of value for the policy", data);
+ data = new PolicyData.StrArray(item.key(), item.stringArray());
+ }
+
+ if (data == null) data = new PolicyData.Undefined(item.key());
+ result.put(data.getKey(), data);
+ }
+ return result;
+ }
+
+ /** @see PreTestHook */
+ public static PreTestHook getRegistrationHook() {
+ return new RegistrationHook();
+ }
+
+ @VisibleForTesting
+ static Map<String, PolicyData> getPolicies(AnnotatedElement element) {
+ AnnotatedElement parent = (element instanceof Method)
+ ? ((Method) element).getDeclaringClass()
+ : ((Class<?>) element).getSuperclass();
+ Map<String, PolicyData> flags = (parent == null)
+ ? new HashMap<String, PolicyData>()
+ : getPolicies(parent);
+
+ if (element.isAnnotationPresent(Policies.Add.class)) {
+ flags.putAll(fromItems(element.getAnnotation(Policies.Add.class).value()));
+ }
+
+ if (element.isAnnotationPresent(Policies.Remove.class)) {
+ flags.keySet().removeAll(
+ fromItems(element.getAnnotation(Policies.Remove.class).value()).keySet());
+ }
+
+ return flags;
+ }
+
+ /**
+ * Registration hook for the {@link Policies} annotation family. Before a test, will parse
+ * the declared policies and use them as cached policies.
+ */
+ public static class RegistrationHook implements PreTestHook {
+ @Override
+ public void run(Context targetContext, Method testMethod) {
+ final Bundle policyBundle = PolicyData.asBundle(getPolicies(testMethod).values());
+ AbstractAppRestrictionsProvider.setTestRestrictions(policyBundle);
+ }
+ }
+}
diff --git a/components/policy/android/junit/src/org/chromium/policy/test/annotations/PoliciesTest.java b/components/policy/android/junit/src/org/chromium/policy/test/annotations/PoliciesTest.java
new file mode 100644
index 0000000..7bc08e4
--- /dev/null
+++ b/components/policy/android/junit/src/org/chromium/policy/test/annotations/PoliciesTest.java
@@ -0,0 +1,94 @@
+// Copyright 2015 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.policy.test.annotations;
+
+import static org.hamcrest.CoreMatchers.is;
+import static org.junit.Assert.assertThat;
+
+import org.chromium.policy.test.PolicyData;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.BlockJUnit4ClassRunner;
+
+import java.lang.reflect.Method;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * Unit tests for the {@link Policies} annotations
+ */
+@RunWith(BlockJUnit4ClassRunner.class)
+public class PoliciesTest {
+ @Test
+ public void testGetPolicies() throws NoSuchMethodException {
+ Method method;
+
+ // Simple element, one annotation, no parent
+ assertThat(Policies.getPolicies(SomeClass.class).keySet(), is(makeSet("Ni")));
+
+ // Simple element, removing an annotation just has no effect
+ assertThat(Policies.getPolicies(SomeClassThatRemoves.class).isEmpty(), is(true));
+
+ // Simple element, adds and removes the same element: We process additions, then removals.
+ assertThat(Policies.getPolicies(SomeConfusedClass.class).isEmpty(), is(true));
+
+ // Annotations are inherited
+ method = SomeClass.class.getDeclaredMethod("someMethodWithoutWord");
+ assertThat(Policies.getPolicies(method).keySet(), is(makeSet("Ni")));
+
+ // Annotations add up
+ method = SomeClass.class.getDeclaredMethod("someMethod");
+ assertThat(Policies.getPolicies(method).keySet(), is(makeSet("Ni", "Neee-wom")));
+
+ // Annotations from methods are not inherited
+ method = SomeDerivedClass.class.getDeclaredMethod("someMethod");
+ assertThat(Policies.getPolicies(method).keySet(), is(makeSet("Ni")));
+
+ // Annotations are properly deduped, we get the one closest to the examined element
+ method = SomeClass.class.getDeclaredMethod("someMethodThatDuplicates");
+ Map<String, PolicyData> policies = Policies.getPolicies(method);
+ assertThat(policies.size(), is(1));
+ assertThat(policies.get("Ni"), is(PolicyData.Str.class));
+
+ // Annotations can be removed
+ method = SomeClass.class.getDeclaredMethod("someMethodThatTilRecentlyHadNi");
+ assertThat(Policies.getPolicies(method).keySet(),
+ is(makeSet("Ekke Ekke Ekke Ekke Ptangya Zoooooooom Boing Ni")));
+ }
+
+ private Set<String> makeSet(String... keys) {
+ return new HashSet<String>(Arrays.asList(keys));
+ }
+
+ @Policies.Add(@Policies.Item(key = "Ni"))
+ private static class SomeClass {
+ @SuppressWarnings("unused")
+ void someMethodWithoutWord() {}
+
+ @Policies.Add(@Policies.Item(key = "Neee-wom"))
+ void someMethod() {}
+
+ @Policies.Add(@Policies.Item(key = "Ni", string = "Makes it string, not undefined."))
+ void someMethodThatDuplicates() {}
+
+ @Policies.Remove(@Policies.Item(key = "Ni"))
+ @Policies.Add(@Policies.Item(key = "Ekke Ekke Ekke Ekke Ptangya Zoooooooom Boing Ni"))
+ void someMethodThatTilRecentlyHadNi() {}
+ }
+
+ private static class SomeDerivedClass extends SomeClass {
+ @Override
+ void someMethod() {}
+ }
+
+ @Policies.Remove(@Policies.Item(key = "Ni"))
+ private static class SomeClassThatRemoves {}
+
+ @Policies.Add(@Policies.Item(key = "Ni"))
+ @Policies.Remove(@Policies.Item(key = "Ni"))
+ private static class SomeConfusedClass {}
+}