Remove Google-specific (or only-used-by-Google-code) classes.

Fix a small typo in Context javadoc.
This commit is contained in:
Dan Egnor
2009-12-30 19:29:03 -08:00
parent 2c3058a88f
commit e38d58bf89
11 changed files with 3 additions and 1678 deletions

View File

@ -1314,7 +1314,7 @@ public abstract class Context {
/**
* Use with {@link #getSystemService} to retrieve a
* {@blink android.appwidget.AppWidgetManager} for accessing AppWidgets.
* {@link android.appwidget.AppWidgetManager} for accessing AppWidgets.
*
* @hide
* @see #getSystemService
@ -1323,7 +1323,7 @@ public abstract class Context {
/**
* Use with {@link #getSystemService} to retrieve an
* {@blink android.backup.IBackupManager IBackupManager} for communicating
* {@link android.backup.IBackupManager IBackupManager} for communicating
* with the backup mechanism.
* @hide
*
@ -1333,7 +1333,7 @@ public abstract class Context {
/**
* Use with {@link #getSystemService} to retrieve a
* {@blink android.os.DropBox DropBox} instance for recording
* {@link android.os.DropBox DropBox} instance for recording
* diagnostic logs.
* @see #getSystemService
*/

View File

@ -1,289 +0,0 @@
// Copyright 2009 The Android Open Source Project
package com.android.internal.net;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.SQLException;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.util.Log;
import org.apache.commons.codec.binary.Base64;
import org.apache.harmony.xnet.provider.jsse.SSLClientSessionCache;
import java.util.HashMap;
import java.util.Map;
import javax.net.ssl.SSLSession;
/**
* Hook into harmony SSL cache to persist the SSL sessions.
*
* Current implementation is suitable for saving a small number of hosts -
* like google services. It can be extended with expiration and more features
* to support more hosts.
*
* {@hide}
*/
public class DbSSLSessionCache implements SSLClientSessionCache {
private static final String TAG = "DbSSLSessionCache";
/**
* Table where sessions are stored.
*/
public static final String SSL_CACHE_TABLE = "ssl_sessions";
private static final String SSL_CACHE_ID = "_id";
/**
* Key is host:port - port is not optional.
*/
private static final String SSL_CACHE_HOSTPORT = "hostport";
/**
* Base64-encoded DER value of the session.
*/
private static final String SSL_CACHE_SESSION = "session";
/**
* Time when the record was added - should be close to the time
* of the initial session negotiation.
*/
private static final String SSL_CACHE_TIME_SEC = "time_sec";
public static final String DATABASE_NAME = "ssl_sessions.db";
public static final int DATABASE_VERSION = 2;
/** public for testing
*/
public static final int SSL_CACHE_ID_COL = 0;
public static final int SSL_CACHE_HOSTPORT_COL = 1;
public static final int SSL_CACHE_SESSION_COL = 2;
public static final int SSL_CACHE_TIME_SEC_COL = 3;
public static final int MAX_CACHE_SIZE = 256;
private final Map<String, byte[]> mExternalCache =
new HashMap<String, byte[]>();
private DatabaseHelper mDatabaseHelper;
private boolean mNeedsCacheLoad = true;
public static final String[] PROJECTION = new String[] {
SSL_CACHE_ID,
SSL_CACHE_HOSTPORT,
SSL_CACHE_SESSION,
SSL_CACHE_TIME_SEC
};
private static final Map<String,DbSSLSessionCache> sInstances =
new HashMap<String,DbSSLSessionCache>();
/**
* Returns a singleton instance of the DbSSLSessionCache that should be used for this
* context's package.
*
* @param context The context that should be used for getting/creating the singleton instance.
* @return The singleton instance for the context's package.
*/
public static synchronized DbSSLSessionCache getInstanceForPackage(Context context) {
String packageName = context.getPackageName();
if (sInstances.containsKey(packageName)) {
return sInstances.get(packageName);
}
DbSSLSessionCache cache = new DbSSLSessionCache(context);
sInstances.put(packageName, cache);
return cache;
}
/**
* Create a SslSessionCache instance, using the specified context to
* initialize the database.
*
* This constructor will use the default database - created for the application
* context.
*
* @param activityContext
*/
private DbSSLSessionCache(Context activityContext) {
Context appContext = activityContext.getApplicationContext();
mDatabaseHelper = new DatabaseHelper(appContext);
}
/**
* Create a SslSessionCache that uses a specific database.
*
*
* @param database
*/
public DbSSLSessionCache(DatabaseHelper database) {
this.mDatabaseHelper = database;
}
public void putSessionData(SSLSession session, byte[] der) {
if (mDatabaseHelper == null) {
return;
}
synchronized (this.getClass()) {
SQLiteDatabase db = mDatabaseHelper.getWritableDatabase();
if (mExternalCache.size() == MAX_CACHE_SIZE) {
// remove oldest.
// TODO: check if the new one is in cached already ( i.e. update ).
Cursor byTime = mDatabaseHelper.getReadableDatabase().query(SSL_CACHE_TABLE,
PROJECTION, null, null, null, null, SSL_CACHE_TIME_SEC);
if (byTime.moveToFirst()) {
// TODO: can I do byTime.deleteRow() ?
String hostPort = byTime.getString(SSL_CACHE_HOSTPORT_COL);
db.delete(SSL_CACHE_TABLE,
SSL_CACHE_HOSTPORT + "= ?" , new String[] { hostPort });
mExternalCache.remove(hostPort);
} else {
Log.w(TAG, "No rows found");
// something is wrong, clear it
clear();
}
}
// Serialize native session to standard DER encoding
long t0 = System.currentTimeMillis();
String b64 = new String(Base64.encodeBase64(der));
String key = session.getPeerHost() + ":" + session.getPeerPort();
ContentValues values = new ContentValues();
values.put(SSL_CACHE_HOSTPORT, key);
values.put(SSL_CACHE_SESSION, b64);
values.put(SSL_CACHE_TIME_SEC, System.currentTimeMillis() / 1000);
mExternalCache.put(key, der);
try {
db.insert(SSL_CACHE_TABLE, null /*nullColumnHack */ , values);
} catch(SQLException ex) {
// Ignore - nothing we can do to recover, and caller shouldn't
// be affected.
Log.w(TAG, "Ignoring SQL exception when caching session", ex);
}
if (Log.isLoggable(TAG, Log.DEBUG)) {
long t1 = System.currentTimeMillis();
Log.d(TAG, "New SSL session " + session.getPeerHost() +
" DER len: " + der.length + " " + (t1 - t0));
}
}
}
public byte[] getSessionData(String host, int port) {
// Current (simple) implementation does a single lookup to DB, then saves
// all entries to the cache.
// This works for google services - i.e. small number of certs.
// If we extend this to all processes - we should hold a separate cache
// or do lookups to DB each time.
if (mDatabaseHelper == null) {
return null;
}
synchronized(this.getClass()) {
if (mNeedsCacheLoad) {
// Don't try to load again, if something is wrong on the first
// request it'll likely be wrong each time.
mNeedsCacheLoad = false;
long t0 = System.currentTimeMillis();
Cursor cur = null;
try {
cur = mDatabaseHelper.getReadableDatabase().query(SSL_CACHE_TABLE,
PROJECTION, null, null, null, null, null);
if (cur.moveToFirst()) {
do {
String hostPort = cur.getString(SSL_CACHE_HOSTPORT_COL);
String value = cur.getString(SSL_CACHE_SESSION_COL);
if (hostPort == null || value == null) {
continue;
}
// TODO: blob support ?
byte[] der = Base64.decodeBase64(value.getBytes());
mExternalCache.put(hostPort, der);
} while (cur.moveToNext());
}
} catch (SQLException ex) {
Log.d(TAG, "Error loading SSL cached entries ", ex);
} finally {
if (cur != null) {
cur.close();
}
if (Log.isLoggable(TAG, Log.DEBUG)) {
long t1 = System.currentTimeMillis();
Log.d(TAG, "LOADED CACHED SSL " + (t1 - t0) + " ms");
}
}
}
String key = host + ":" + port;
return mExternalCache.get(key);
}
}
/**
* Reset the database and internal state.
* Used for testing or to free space.
*/
public void clear() {
synchronized(this) {
try {
mExternalCache.clear();
mNeedsCacheLoad = true;
mDatabaseHelper.getWritableDatabase().delete(SSL_CACHE_TABLE,
null, null);
} catch (SQLException ex) {
Log.d(TAG, "Error removing SSL cached entries ", ex);
// ignore - nothing we can do about it
}
}
}
public byte[] getSessionData(byte[] id) {
// We support client side only - the cache will do nothing for
// server-side sessions.
return null;
}
/** Visible for testing.
*/
public static class DatabaseHelper extends SQLiteOpenHelper {
public DatabaseHelper(Context context) {
super(context, DATABASE_NAME, null /* factory */, DATABASE_VERSION);
}
@Override
public void onCreate(SQLiteDatabase db) {
db.execSQL("CREATE TABLE " + SSL_CACHE_TABLE + " (" +
SSL_CACHE_ID + " INTEGER PRIMARY KEY AUTOINCREMENT," +
SSL_CACHE_HOSTPORT + " TEXT UNIQUE ON CONFLICT REPLACE," +
SSL_CACHE_SESSION + " TEXT," +
SSL_CACHE_TIME_SEC + " INTEGER" +
");");
// No index - we load on startup, index would slow down inserts.
// If we want to scale this to lots of rows - we could use
// index, but then we'll hit DB a bit too often ( including
// negative hits )
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
db.execSQL("DROP TABLE IF EXISTS " + SSL_CACHE_TABLE );
onCreate(db);
}
}
}

View File

@ -1,84 +0,0 @@
/*
* Copyright (C) 2009 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.google.android.net;
import android.net.TrafficStats;
import android.os.SystemClock;
import android.os.SystemProperties;
import android.util.EventLog;
import org.apache.http.HttpEntity;
import org.apache.http.entity.HttpEntityWrapper;
import java.io.FilterInputStream;
import java.io.IOException;
import java.io.InputStream;
public class NetworkStatsEntity extends HttpEntityWrapper {
private static final int HTTP_STATS_EVENT = 52001;
private class NetworkStatsInputStream extends FilterInputStream {
public NetworkStatsInputStream(InputStream wrapped) {
super(wrapped);
}
@Override
public void close() throws IOException {
try {
super.close();
} finally {
long processingTime = SystemClock.elapsedRealtime() - mProcessingStartTime;
long tx = TrafficStats.getUidTxBytes(mUid);
long rx = TrafficStats.getUidRxBytes(mUid);
EventLog.writeEvent(HTTP_STATS_EVENT, mUa, mResponseLatency, processingTime,
tx - mStartTx, rx - mStartRx);
}
}
}
private final String mUa;
private final int mUid;
private final long mStartTx;
private final long mStartRx;
private final long mResponseLatency;
private final long mProcessingStartTime;
public NetworkStatsEntity(HttpEntity orig, String ua,
int uid, long startTx, long startRx, long responseLatency,
long processingStartTime) {
super(orig);
this.mUa = ua;
this.mUid = uid;
this.mStartTx = startTx;
this.mStartRx = startRx;
this.mResponseLatency = responseLatency;
this.mProcessingStartTime = processingStartTime;
}
public static boolean shouldLogNetworkStats() {
return "1".equals(SystemProperties.get("googlehttpclient.logstats"));
}
@Override
public InputStream getContent() throws IOException {
InputStream orig = super.getContent();
return new NetworkStatsInputStream(orig);
}
}

View File

@ -1,62 +0,0 @@
package com.google.android.net;
import org.apache.harmony.xnet.provider.jsse.SSLClientSessionCache;
import org.apache.harmony.xnet.provider.jsse.FileClientSessionCache;
import android.content.Context;
import android.provider.Settings;
import android.util.Log;
import java.io.File;
import java.io.IOException;
import com.android.internal.net.DbSSLSessionCache;
/**
* Factory that returns the appropriate implementation of a {@link SSLClientSessionCache} based
* on gservices.
*
* @hide
*/
// TODO: return a proxied implementation that is updated as the gservices value changes.
public final class SSLClientSessionCacheFactory {
private static final String TAG = "SSLClientSessionCacheFactory";
public static final String DB = "db";
public static final String FILE = "file";
// utility class
private SSLClientSessionCacheFactory() {}
/**
* Returns a new {@link SSLClientSessionCache} based on the persistent cache that's specified,
* if any, in gservices. If no cache is specified, returns null.
* @param context The application context used for the per-process persistent cache.
* @return A new {@link SSLClientSessionCache}, or null if no persistent cache is configured.
*/
public static SSLClientSessionCache getCache(Context context) {
String type = Settings.Gservices.getString(context.getContentResolver(),
Settings.Gservices.SSL_SESSION_CACHE);
if (type != null) {
if (DB.equals(type)) {
return DbSSLSessionCache.getInstanceForPackage(context);
} else if (FILE.equals(type)) {
File dir = context.getFilesDir();
File cacheDir = new File(dir, "sslcache");
if (!cacheDir.exists()) {
cacheDir.mkdir();
}
try {
return FileClientSessionCache.usingDirectory(cacheDir);
} catch (IOException ioe) {
Log.w(TAG, "Unable to create FileClientSessionCache in " + cacheDir.getName(), ioe);
return null;
}
} else {
Log.w(TAG, "Ignoring unrecognized type: '" + type + "'");
}
}
return null;
}
}

View File

@ -1,236 +0,0 @@
/*
* Copyright (C) 2008 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.google.android.net;
import android.content.ContentResolver;
import android.database.Cursor;
import android.provider.Checkin;
import android.provider.Settings;
import android.util.Config;
import android.util.Log;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* A set of rules rewriting and blocking URLs. Used to offer a point of
* control for redirecting HTTP requests, often to the Android proxy server.
*
* <p>Each rule has the following format:
*
* <pre><em>url-prefix</em> [REWRITE <em>new-prefix</em>] [BLOCK]</pre>
*
* <p>Any URL which starts with <em>url-prefix</em> will trigger the rule.
* If BLOCK is specified, requests to that URL will be blocked and fail.
* If REWRITE is specified, the matching prefix will be removed and replaced
* with <em>new-prefix</em>. (If both are specified, BLOCK wins.) Case is
* insensitive for the REWRITE and BLOCK keywords, but sensitive for URLs.
*
* <p>In Gservices, the value of any key that starts with "url:" will be
* interpreted as a rule. The full name of the key is unimportant (but can
* be used to document the intent of the rule, and must be unique).
* Example gservices keys:
*
* <pre>
* url:use_proxy_for_calendar = "http://www.google.com/calendar/ REWRITE http://android.clients.google.com/proxy/calendar/"
* url:stop_crash_reports = "http://android.clients.google.com/crash/ BLOCK"
* url:use_ssl_for_contacts = "http://www.google.com/m8/ REWRITE https://www.google.com/m8/"
* </pre>
*/
public class UrlRules {
public static final String TAG = "UrlRules";
public static final boolean LOCAL_LOGV = Config.LOGV || false;
/** Thrown when the rewrite rules can't be parsed. */
public static class RuleFormatException extends Exception {
public RuleFormatException(String msg) { super(msg); }
}
/** A single rule specifying actions for URLs matching a certain prefix. */
public static class Rule implements Comparable {
/** Name assigned to the rule (for logging and debugging). */
public final String mName;
/** Prefix required to match this rule. */
public final String mPrefix;
/** Text to replace mPrefix with (null to leave alone). */
public final String mRewrite;
/** True if matching URLs should be blocked. */
public final boolean mBlock;
/** Default rule that does nothing. */
public static final Rule DEFAULT = new Rule();
/** Parse a rewrite rule as given in a Gservices value. */
public Rule(String name, String rule) throws RuleFormatException {
mName = name;
String[] words = PATTERN_SPACE_PLUS.split(rule);
if (words.length == 0) throw new RuleFormatException("Empty rule");
mPrefix = words[0];
String rewrite = null;
boolean block = false;
for (int pos = 1; pos < words.length; ) {
String word = words[pos].toLowerCase();
if (word.equals("rewrite") && pos + 1 < words.length) {
rewrite = words[pos + 1];
pos += 2;
} else if (word.equals("block")) {
block = true;
pos += 1;
} else {
throw new RuleFormatException("Illegal rule: " + rule);
}
// TODO: Parse timeout specifications, etc.
}
mRewrite = rewrite;
mBlock = block;
}
/** Create the default Rule. */
private Rule() {
mName = "DEFAULT";
mPrefix = "";
mRewrite = null;
mBlock = false;
}
/**
* Apply the rule to a particular URL (assumed to match the rule).
* @param url to rewrite or modify.
* @return modified URL, or null if the URL is blocked.
*/
public String apply(String url) {
if (mBlock) {
return null;
} else if (mRewrite != null) {
return mRewrite + url.substring(mPrefix.length());
} else {
return url;
}
}
/** More generic rules are greater than more specific rules. */
public int compareTo(Object o) {
return ((Rule) o).mPrefix.compareTo(mPrefix);
}
}
/** Cached rule set from Gservices. */
private static UrlRules sCachedRules = new UrlRules(new Rule[] {});
private static final Pattern PATTERN_SPACE_PLUS = Pattern.compile(" +");
private static final Pattern RULE_PATTERN = Pattern.compile("\\W");
/** Gservices digest when sCachedRules was cached. */
private static String sCachedDigest = null;
/** Currently active set of Rules. */
private final Rule[] mRules;
/** Regular expression with one capturing group for each Rule. */
private final Pattern mPattern;
/**
* Create a rewriter from an array of Rules. Normally used only for
* testing. Instead, use {@link #getRules} to get rules from Gservices.
* @param rules to use.
*/
public UrlRules(Rule[] rules) {
// Sort the rules to put the most specific rules first.
Arrays.sort(rules);
// Construct a regular expression, escaping all the prefix strings.
StringBuilder pattern = new StringBuilder("(");
for (int i = 0; i < rules.length; ++i) {
if (i > 0) pattern.append(")|(");
pattern.append(RULE_PATTERN.matcher(rules[i].mPrefix).replaceAll("\\\\$0"));
}
mPattern = Pattern.compile(pattern.append(")").toString());
mRules = rules;
}
/**
* Match a string against every Rule and find one that matches.
* @param uri to match against the Rules in the rewriter.
* @return the most specific matching Rule, or Rule.DEFAULT if none match.
*/
public Rule matchRule(String url) {
Matcher matcher = mPattern.matcher(url);
if (matcher.lookingAt()) {
for (int i = 0; i < mRules.length; ++i) {
if (matcher.group(i + 1) != null) {
return mRules[i]; // Rules are sorted most specific first.
}
}
}
return Rule.DEFAULT;
}
/**
* Get the (possibly cached) UrlRules based on the rules in Gservices.
* @param resolver to use for accessing the Gservices database.
* @return an updated UrlRules instance
*/
public static synchronized UrlRules getRules(ContentResolver resolver) {
String digest = Settings.Gservices.getString(resolver,
Settings.Gservices.PROVISIONING_DIGEST);
if (sCachedDigest != null && sCachedDigest.equals(digest)) {
// The digest is the same, so the rules are the same.
if (LOCAL_LOGV) Log.v(TAG, "Using cached rules for digest: " + digest);
return sCachedRules;
}
if (LOCAL_LOGV) Log.v(TAG, "Scanning for Gservices \"url:*\" rules");
Cursor cursor = resolver.query(Settings.Gservices.CONTENT_URI,
new String[] {
Settings.Gservices.NAME,
Settings.Gservices.VALUE
},
Settings.Gservices.NAME + " like \"url:%\"", null,
Settings.Gservices.NAME);
try {
ArrayList<Rule> rules = new ArrayList<Rule>();
while (cursor.moveToNext()) {
try {
String name = cursor.getString(0).substring(4); // "url:X"
String value = cursor.getString(1);
if (value == null || value.length() == 0) continue;
if (LOCAL_LOGV) Log.v(TAG, " Rule " + name + ": " + value);
rules.add(new Rule(name, value));
} catch (RuleFormatException e) {
// Oops, Gservices has an invalid rule! Skip it.
Log.e(TAG, "Invalid rule from Gservices", e);
Checkin.logEvent(resolver,
Checkin.Events.Tag.GSERVICES_ERROR, e.toString());
}
}
sCachedRules = new UrlRules(rules.toArray(new Rule[rules.size()]));
sCachedDigest = digest;
if (LOCAL_LOGV) Log.v(TAG, "New rules stored for digest: " + digest);
} finally {
cursor.close();
}
return sCachedRules;
}
}

View File

@ -691,8 +691,6 @@ com.google.android.mms.ContentType
com.google.android.mms.pdu.CharacterSets
com.google.android.mms.pdu.PduPart
com.google.android.mms.pdu.PduPersister
com.google.android.net.UrlRules
com.google.android.net.UrlRules$Rule
com.ibm.icu4jni.charset.CharsetDecoderICU
com.ibm.icu4jni.charset.CharsetEncoderICU
com.ibm.icu4jni.charset.CharsetICU

View File

@ -1,13 +0,0 @@
package com.android.unit_tests;
import junit.framework.TestSuite;
public class ApacheHttpTests {
public static TestSuite suite() {
TestSuite suite = new TestSuite(ApacheHttpTests.class.getName());
suite.addTestSuite(TestHttpService.class);
return suite;
}
}

View File

@ -1,54 +0,0 @@
package com.android.unit_tests;
import com.google.android.net.SSLClientSessionCacheFactory;
import com.android.internal.net.DbSSLSessionCache;
import android.test.AndroidTestCase;
import android.test.suitebuilder.annotation.MediumTest;
import android.content.ContentResolver;
import android.content.Context;
import android.provider.Settings;
import org.apache.harmony.xnet.provider.jsse.SSLClientSessionCache;
/**
* Unit test for {@link SSLClientSessionCacheFactory}.
*/
@MediumTest
public final class SSLClientSessionCacheFactoryTest extends AndroidTestCase {
protected void tearDown() throws Exception {
setSslSessionCacheValue(getContext(), "");
super.tearDown();
}
private static void setSslSessionCacheValue(Context context, String value) {
ContentResolver resolver = context.getContentResolver();
Settings.Gservices.putString(resolver, Settings.Gservices.SSL_SESSION_CACHE, value);
}
private static SSLClientSessionCache getCache(Context context, String type) {
setSslSessionCacheValue(context, type);
return SSLClientSessionCacheFactory.getCache(context);
}
public void testGetDbCache() throws Exception {
Context context = getContext();
SSLClientSessionCache cache = getCache(context, "db");
assertNotNull(cache);
assertTrue(cache instanceof DbSSLSessionCache);
}
public void testGetFileCache() throws Exception {
Context context = getContext();
SSLClientSessionCache cache = getCache(context, "file");
assertNotNull(cache);
// yuck =)
assertEquals("org.apache.harmony.xnet.provider.jsse.FileClientSessionCache$Impl",
cache.getClass().getName());
}
public void testGetNoCache() throws Exception {
Context context = getContext();
SSLClientSessionCache cache = getCache(context, "none");
assertNull(cache);
}
}

View File

@ -1,207 +0,0 @@
/*
* $HeadURL: http://svn.apache.org/repos/asf/jakarta/httpcomponents/httpcore/tags/4.0-alpha6/module-main/src/test/java/org/apache/http/mockup/TestHttpServer.java $
* $Revision: 576077 $
* $Date: 2007-09-16 04:50:22 -0700 (Sun, 16 Sep 2007) $
*
* ====================================================================
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*
*/
package com.android.unit_tests;
import java.io.IOException;
import java.io.InterruptedIOException;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
import org.apache.http.ConnectionClosedException;
import org.apache.http.ConnectionReuseStrategy;
import org.apache.http.HttpException;
import org.apache.http.HttpResponseFactory;
import org.apache.http.HttpServerConnection;
import org.apache.http.impl.DefaultConnectionReuseStrategy;
import org.apache.http.impl.DefaultHttpResponseFactory;
import org.apache.http.impl.DefaultHttpServerConnection;
import org.apache.http.params.BasicHttpParams;
import org.apache.http.params.CoreConnectionPNames;
import org.apache.http.params.HttpParams;
import org.apache.http.params.CoreProtocolPNames;
import org.apache.http.protocol.BasicHttpProcessor;
import org.apache.http.protocol.HttpContext;
import org.apache.http.protocol.BasicHttpContext;
import org.apache.http.protocol.HttpExpectationVerifier;
import org.apache.http.protocol.HttpRequestHandler;
import org.apache.http.protocol.HttpRequestHandlerRegistry;
import org.apache.http.protocol.HttpService;
import org.apache.http.protocol.ResponseConnControl;
import org.apache.http.protocol.ResponseContent;
import org.apache.http.protocol.ResponseDate;
import org.apache.http.protocol.ResponseServer;
public class TestHttpServer {
private final HttpParams params;
private final BasicHttpProcessor httpproc;
private final ConnectionReuseStrategy connStrategy;
private final HttpResponseFactory responseFactory;
private final HttpRequestHandlerRegistry reqistry;
private final ServerSocket serversocket;
private HttpExpectationVerifier expectationVerifier;
private Thread listener;
private volatile boolean shutdown;
public TestHttpServer() throws IOException {
super();
this.params = new BasicHttpParams();
this.params
.setIntParameter(CoreConnectionPNames.SO_TIMEOUT, 20000)
.setIntParameter(CoreConnectionPNames.SOCKET_BUFFER_SIZE, 8 * 1024)
.setBooleanParameter(CoreConnectionPNames.STALE_CONNECTION_CHECK, false)
.setBooleanParameter(CoreConnectionPNames.TCP_NODELAY, true)
.setParameter(CoreProtocolPNames.ORIGIN_SERVER, "TEST-SERVER/1.1");
this.httpproc = new BasicHttpProcessor();
this.httpproc.addInterceptor(new ResponseDate());
this.httpproc.addInterceptor(new ResponseServer());
this.httpproc.addInterceptor(new ResponseContent());
this.httpproc.addInterceptor(new ResponseConnControl());
this.connStrategy = new DefaultConnectionReuseStrategy();
this.responseFactory = new DefaultHttpResponseFactory();
this.reqistry = new HttpRequestHandlerRegistry();
this.serversocket = new ServerSocket(0);
}
public void registerHandler(
final String pattern,
final HttpRequestHandler handler) {
this.reqistry.register(pattern, handler);
}
public void setExpectationVerifier(final HttpExpectationVerifier expectationVerifier) {
this.expectationVerifier = expectationVerifier;
}
private HttpServerConnection acceptConnection() throws IOException {
Socket socket = this.serversocket.accept();
DefaultHttpServerConnection conn = new DefaultHttpServerConnection();
conn.bind(socket, this.params);
return conn;
}
public int getPort() {
return this.serversocket.getLocalPort();
}
public InetAddress getInetAddress() {
return this.serversocket.getInetAddress();
}
public void start() {
if (this.listener != null) {
throw new IllegalStateException("Listener already running");
}
this.listener = new Thread(new Runnable() {
public void run() {
while (!shutdown && !Thread.interrupted()) {
try {
// Set up HTTP connection
HttpServerConnection conn = acceptConnection();
// Set up the HTTP service
HttpService httpService = new HttpService(
httpproc,
connStrategy,
responseFactory);
httpService.setParams(params);
httpService.setExpectationVerifier(expectationVerifier);
httpService.setHandlerResolver(reqistry);
// Start worker thread
Thread t = new WorkerThread(httpService, conn);
t.setDaemon(true);
t.start();
} catch (InterruptedIOException ex) {
break;
} catch (IOException e) {
break;
}
}
}
});
this.listener.start();
}
public void shutdown() {
if (this.shutdown) {
return;
}
this.shutdown = true;
try {
this.serversocket.close();
} catch (IOException ignore) {}
this.listener.interrupt();
try {
this.listener.join(1000);
} catch (InterruptedException ignore) {}
}
static class WorkerThread extends Thread {
private final HttpService httpservice;
private final HttpServerConnection conn;
public WorkerThread(
final HttpService httpservice,
final HttpServerConnection conn) {
super();
this.httpservice = httpservice;
this.conn = conn;
}
public void run() {
HttpContext context = new BasicHttpContext(null);
try {
while (!Thread.interrupted() && this.conn.isOpen()) {
this.httpservice.handleRequest(this.conn, context);
}
} catch (ConnectionClosedException ex) {
} catch (IOException ex) {
System.err.println("I/O error: " + ex.getMessage());
} catch (HttpException ex) {
System.err.println("Unrecoverable HTTP protocol violation: " + ex.getMessage());
} finally {
try {
this.conn.shutdown();
} catch (IOException ignore) {}
}
}
}
}

View File

@ -1,608 +0,0 @@
/*
* $HeadURL: http://svn.apache.org/repos/asf/jakarta/httpcomponents/httpcore/tags/4.0-alpha6/module-main/src/test/java/org/apache/http/protocol/TestHttpServiceAndExecutor.java $
* $Revision: 576073 $
* $Date: 2007-09-16 03:53:13 -0700 (Sun, 16 Sep 2007) $
* ====================================================================
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*
*/
package com.android.unit_tests;
import org.apache.http.protocol.HttpExpectationVerifier;
import org.apache.http.protocol.HttpRequestHandler;
import android.test.PerformanceTestCase;
import android.test.suitebuilder.annotation.LargeTest;
import android.test.suitebuilder.annotation.MediumTest;
import junit.framework.TestCase;
import org.apache.http.Header;
import org.apache.http.HttpConnectionMetrics;
import org.apache.http.HttpEntity;
import org.apache.http.HttpEntityEnclosingRequest;
import org.apache.http.HttpException;
import org.apache.http.HttpHost;
import org.apache.http.HttpRequest;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.HttpVersion;
import org.apache.http.entity.ByteArrayEntity;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.DefaultHttpClientConnection;
import org.apache.http.message.BasicHttpEntityEnclosingRequest;
import org.apache.http.message.BasicHttpRequest;
import org.apache.http.params.CoreProtocolPNames;
import org.apache.http.protocol.HttpContext;
import org.apache.http.util.EncodingUtils;
import org.apache.http.util.EntityUtils;
import java.io.IOException;
import java.net.Socket;
import java.net.URI;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
public class TestHttpService extends TestCase implements PerformanceTestCase {
public boolean isPerformanceOnly() {
// TODO Auto-generated method stub
return false;
}
public int startPerformance(Intermediates intermediates) {
// TODO Auto-generated method stub
return 0;
}
private TestHttpServer server;
private TestHttpClient client;
protected void setUp() throws Exception {
this.server = new TestHttpServer();
this.client = new TestHttpClient();
}
protected void tearDown() throws Exception {
if (server != null) {
this.server.shutdown();
}
}
/**
* This test case executes a series of simple GET requests
*/
@LargeTest
public void testSimpleBasicHttpRequests() throws Exception {
int reqNo = 20;
Random rnd = new Random();
// Prepare some random data
final List testData = new ArrayList(reqNo);
for (int i = 0; i < reqNo; i++) {
int size = rnd.nextInt(5000);
byte[] data = new byte[size];
rnd.nextBytes(data);
testData.add(data);
}
// Initialize the server-side request handler
this.server.registerHandler("*", new HttpRequestHandler() {
public void handle(
final HttpRequest request,
final HttpResponse response,
final HttpContext context) throws HttpException, IOException {
String s = request.getRequestLine().getUri();
if (s.startsWith("/?")) {
s = s.substring(2);
}
int index = Integer.parseInt(s);
byte[] data = (byte []) testData.get(index);
ByteArrayEntity entity = new ByteArrayEntity(data);
response.setEntity(entity);
}
});
this.server.start();
DefaultHttpClientConnection conn = new DefaultHttpClientConnection();
HttpHost host = new HttpHost("localhost", this.server.getPort());
try {
for (int r = 0; r < reqNo; r++) {
if (!conn.isOpen()) {
Socket socket = new Socket(host.getHostName(), host.getPort());
conn.bind(socket, this.client.getParams());
}
BasicHttpRequest get = new BasicHttpRequest("GET", "/?" + r);
HttpResponse response = this.client.execute(get, host, conn);
byte[] received = EntityUtils.toByteArray(response.getEntity());
byte[] expected = (byte[]) testData.get(r);
assertEquals(expected.length, received.length);
for (int i = 0; i < expected.length; i++) {
assertEquals(expected[i], received[i]);
}
if (!this.client.keepAlive(response)) {
conn.close();
}
}
//Verify the connection metrics
HttpConnectionMetrics cm = conn.getMetrics();
assertEquals(reqNo, cm.getRequestCount());
assertEquals(reqNo, cm.getResponseCount());
} finally {
conn.close();
this.server.shutdown();
}
}
/**
* This test case executes a series of simple POST requests with content length
* delimited content.
*/
@LargeTest
public void testSimpleHttpPostsWithContentLength() throws Exception {
int reqNo = 20;
Random rnd = new Random();
// Prepare some random data
List testData = new ArrayList(reqNo);
for (int i = 0; i < reqNo; i++) {
int size = rnd.nextInt(5000);
byte[] data = new byte[size];
rnd.nextBytes(data);
testData.add(data);
}
// Initialize the server-side request handler
this.server.registerHandler("*", new HttpRequestHandler() {
public void handle(
final HttpRequest request,
final HttpResponse response,
final HttpContext context) throws HttpException, IOException {
if (request instanceof HttpEntityEnclosingRequest) {
HttpEntity incoming = ((HttpEntityEnclosingRequest) request).getEntity();
byte[] data = EntityUtils.toByteArray(incoming);
ByteArrayEntity outgoing = new ByteArrayEntity(data);
outgoing.setChunked(false);
response.setEntity(outgoing);
} else {
StringEntity outgoing = new StringEntity("No content");
response.setEntity(outgoing);
}
}
});
this.server.start();
DefaultHttpClientConnection conn = new DefaultHttpClientConnection();
HttpHost host = new HttpHost("localhost", this.server.getPort());
try {
for (int r = 0; r < reqNo; r++) {
if (!conn.isOpen()) {
Socket socket = new Socket(host.getHostName(), host.getPort());
conn.bind(socket, this.client.getParams());
}
BasicHttpEntityEnclosingRequest post = new BasicHttpEntityEnclosingRequest("POST", "/");
byte[] data = (byte[]) testData.get(r);
ByteArrayEntity outgoing = new ByteArrayEntity(data);
post.setEntity(outgoing);
HttpResponse response = this.client.execute(post, host, conn);
byte[] received = EntityUtils.toByteArray(response.getEntity());
byte[] expected = (byte[]) testData.get(r);
assertEquals(expected.length, received.length);
for (int i = 0; i < expected.length; i++) {
assertEquals(expected[i], received[i]);
}
if (!this.client.keepAlive(response)) {
conn.close();
}
}
//Verify the connection metrics
HttpConnectionMetrics cm = conn.getMetrics();
assertEquals(reqNo, cm.getRequestCount());
assertEquals(reqNo, cm.getResponseCount());
} finally {
conn.close();
this.server.shutdown();
}
}
/**
* This test case executes a series of simple POST requests with chunk
* coded content content.
*/
@LargeTest
public void testSimpleHttpPostsChunked() throws Exception {
int reqNo = 20;
Random rnd = new Random();
// Prepare some random data
List testData = new ArrayList(reqNo);
for (int i = 0; i < reqNo; i++) {
int size = rnd.nextInt(20000);
byte[] data = new byte[size];
rnd.nextBytes(data);
testData.add(data);
}
// Initialize the server-side request handler
this.server.registerHandler("*", new HttpRequestHandler() {
public void handle(
final HttpRequest request,
final HttpResponse response,
final HttpContext context) throws HttpException, IOException {
if (request instanceof HttpEntityEnclosingRequest) {
HttpEntity incoming = ((HttpEntityEnclosingRequest) request).getEntity();
byte[] data = EntityUtils.toByteArray(incoming);
ByteArrayEntity outgoing = new ByteArrayEntity(data);
outgoing.setChunked(true);
response.setEntity(outgoing);
} else {
StringEntity outgoing = new StringEntity("No content");
response.setEntity(outgoing);
}
}
});
this.server.start();
DefaultHttpClientConnection conn = new DefaultHttpClientConnection();
HttpHost host = new HttpHost("localhost", this.server.getPort());
try {
for (int r = 0; r < reqNo; r++) {
if (!conn.isOpen()) {
Socket socket = new Socket(host.getHostName(), host.getPort());
conn.bind(socket, this.client.getParams());
}
BasicHttpEntityEnclosingRequest post = new BasicHttpEntityEnclosingRequest("POST", "/");
byte[] data = (byte[]) testData.get(r);
ByteArrayEntity outgoing = new ByteArrayEntity(data);
outgoing.setChunked(true);
post.setEntity(outgoing);
HttpResponse response = this.client.execute(post, host, conn);
byte[] received = EntityUtils.toByteArray(response.getEntity());
byte[] expected = (byte[]) testData.get(r);
assertEquals(expected.length, received.length);
for (int i = 0; i < expected.length; i++) {
assertEquals(expected[i], received[i]);
}
if (!this.client.keepAlive(response)) {
conn.close();
}
}
//Verify the connection metrics
HttpConnectionMetrics cm = conn.getMetrics();
assertEquals(reqNo, cm.getRequestCount());
assertEquals(reqNo, cm.getResponseCount());
} finally {
conn.close();
this.server.shutdown();
}
}
/**
* This test case executes a series of simple HTTP/1.0 POST requests.
*/
@LargeTest
public void testSimpleHttpPostsHTTP10() throws Exception {
int reqNo = 20;
Random rnd = new Random();
// Prepare some random data
List testData = new ArrayList(reqNo);
for (int i = 0; i < reqNo; i++) {
int size = rnd.nextInt(5000);
byte[] data = new byte[size];
rnd.nextBytes(data);
testData.add(data);
}
// Initialize the server-side request handler
this.server.registerHandler("*", new HttpRequestHandler() {
public void handle(
final HttpRequest request,
final HttpResponse response,
final HttpContext context) throws HttpException, IOException {
if (request instanceof HttpEntityEnclosingRequest) {
HttpEntity incoming = ((HttpEntityEnclosingRequest) request).getEntity();
byte[] data = EntityUtils.toByteArray(incoming);
ByteArrayEntity outgoing = new ByteArrayEntity(data);
outgoing.setChunked(false);
response.setEntity(outgoing);
} else {
StringEntity outgoing = new StringEntity("No content");
response.setEntity(outgoing);
}
}
});
this.server.start();
// Set protocol level to HTTP/1.0
this.client.getParams().setParameter(
CoreProtocolPNames.PROTOCOL_VERSION, HttpVersion.HTTP_1_0);
DefaultHttpClientConnection conn = new DefaultHttpClientConnection();
HttpHost host = new HttpHost("localhost", this.server.getPort());
try {
for (int r = 0; r < reqNo; r++) {
if (!conn.isOpen()) {
Socket socket = new Socket(host.getHostName(), host.getPort());
conn.bind(socket, this.client.getParams());
}
BasicHttpEntityEnclosingRequest post = new BasicHttpEntityEnclosingRequest("POST", "/");
byte[] data = (byte[]) testData.get(r);
ByteArrayEntity outgoing = new ByteArrayEntity(data);
post.setEntity(outgoing);
HttpResponse response = this.client.execute(post, host, conn);
assertEquals(HttpVersion.HTTP_1_0, response.getStatusLine().getProtocolVersion());
byte[] received = EntityUtils.toByteArray(response.getEntity());
byte[] expected = (byte[]) testData.get(r);
assertEquals(expected.length, received.length);
for (int i = 0; i < expected.length; i++) {
assertEquals(expected[i], received[i]);
}
if (!this.client.keepAlive(response)) {
conn.close();
}
}
//Verify the connection metrics
HttpConnectionMetrics cm = conn.getMetrics();
assertEquals(reqNo, cm.getRequestCount());
assertEquals(reqNo, cm.getResponseCount());
} finally {
conn.close();
this.server.shutdown();
}
}
/**
* This test case executes a series of simple POST requests using
* the 'expect: continue' handshake.
*/
@LargeTest
public void testHttpPostsWithExpectContinue() throws Exception {
int reqNo = 20;
Random rnd = new Random();
// Prepare some random data
List testData = new ArrayList(reqNo);
for (int i = 0; i < reqNo; i++) {
int size = rnd.nextInt(5000);
byte[] data = new byte[size];
rnd.nextBytes(data);
testData.add(data);
}
// Initialize the server-side request handler
this.server.registerHandler("*", new HttpRequestHandler() {
public void handle(
final HttpRequest request,
final HttpResponse response,
final HttpContext context) throws HttpException, IOException {
if (request instanceof HttpEntityEnclosingRequest) {
HttpEntity incoming = ((HttpEntityEnclosingRequest) request).getEntity();
byte[] data = EntityUtils.toByteArray(incoming);
ByteArrayEntity outgoing = new ByteArrayEntity(data);
outgoing.setChunked(true);
response.setEntity(outgoing);
} else {
StringEntity outgoing = new StringEntity("No content");
response.setEntity(outgoing);
}
}
});
this.server.start();
// Activate 'expect: continue' handshake
this.client.getParams().setBooleanParameter(CoreProtocolPNames.USE_EXPECT_CONTINUE, true);
DefaultHttpClientConnection conn = new DefaultHttpClientConnection();
HttpHost host = new HttpHost("localhost", this.server.getPort());
try {
for (int r = 0; r < reqNo; r++) {
if (!conn.isOpen()) {
Socket socket = new Socket(host.getHostName(), host.getPort());
conn.bind(socket, this.client.getParams());
}
BasicHttpEntityEnclosingRequest post = new BasicHttpEntityEnclosingRequest("POST", "/");
byte[] data = (byte[]) testData.get(r);
ByteArrayEntity outgoing = new ByteArrayEntity(data);
outgoing.setChunked(true);
post.setEntity(outgoing);
HttpResponse response = this.client.execute(post, host, conn);
byte[] received = EntityUtils.toByteArray(response.getEntity());
byte[] expected = (byte[]) testData.get(r);
assertEquals(expected.length, received.length);
for (int i = 0; i < expected.length; i++) {
assertEquals(expected[i], received[i]);
}
if (!this.client.keepAlive(response)) {
conn.close();
}
}
//Verify the connection metrics
HttpConnectionMetrics cm = conn.getMetrics();
assertEquals(reqNo, cm.getRequestCount());
assertEquals(reqNo, cm.getResponseCount());
} finally {
conn.close();
this.server.shutdown();
}
}
/**
* This test case executes a series of simple POST requests that do not
* meet the target server expectations.
*/
@LargeTest
public void testHttpPostsWithExpectationVerification() throws Exception {
int reqNo = 3;
// Initialize the server-side request handler
this.server.registerHandler("*", new HttpRequestHandler() {
public void handle(
final HttpRequest request,
final HttpResponse response,
final HttpContext context) throws HttpException, IOException {
StringEntity outgoing = new StringEntity("No content");
response.setEntity(outgoing);
}
});
this.server.setExpectationVerifier(new HttpExpectationVerifier() {
public void verify(
final HttpRequest request,
final HttpResponse response,
final HttpContext context) throws HttpException {
Header someheader = request.getFirstHeader("Secret");
if (someheader != null) {
int secretNumber;
try {
secretNumber = Integer.parseInt(someheader.getValue());
} catch (NumberFormatException ex) {
response.setStatusCode(HttpStatus.SC_BAD_REQUEST);
return;
}
if (secretNumber < 2) {
response.setStatusCode(HttpStatus.SC_EXPECTATION_FAILED);
ByteArrayEntity outgoing = new ByteArrayEntity(
EncodingUtils.getAsciiBytes("Wrong secret number"));
response.setEntity(outgoing);
}
}
}
});
this.server.start();
// Activate 'expect: continue' handshake
this.client.getParams().setBooleanParameter(CoreProtocolPNames.USE_EXPECT_CONTINUE, true);
DefaultHttpClientConnection conn = new DefaultHttpClientConnection();
HttpHost host = new HttpHost("localhost", this.server.getPort());
try {
for (int r = 0; r < reqNo; r++) {
if (!conn.isOpen()) {
Socket socket = new Socket(host.getHostName(), host.getPort());
conn.bind(socket, this.client.getParams());
}
BasicHttpEntityEnclosingRequest post = new BasicHttpEntityEnclosingRequest("POST", "/");
post.addHeader("Secret", Integer.toString(r));
ByteArrayEntity outgoing = new ByteArrayEntity(
EncodingUtils.getAsciiBytes("No content"));
post.setEntity(outgoing);
HttpResponse response = this.client.execute(post, host, conn);
HttpEntity entity = response.getEntity();
assertNotNull(entity);
entity.consumeContent();
if (r < 2) {
assertEquals(HttpStatus.SC_EXPECTATION_FAILED, response.getStatusLine().getStatusCode());
} else {
assertEquals(HttpStatus.SC_OK, response.getStatusLine().getStatusCode());
}
if (!this.client.keepAlive(response)) {
conn.close();
}
}
//Verify the connection metrics
HttpConnectionMetrics cm = conn.getMetrics();
assertEquals(reqNo, cm.getRequestCount());
assertEquals(reqNo, cm.getResponseCount());
} finally {
conn.close();
this.server.shutdown();
}
}
}

View File

@ -1,120 +0,0 @@
/*
* Copyright (C) 2008 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.unit_tests;
import android.content.ContentResolver;
import android.provider.Settings;
import android.test.AndroidTestCase;
import android.test.suitebuilder.annotation.MediumTest;
import android.test.suitebuilder.annotation.SmallTest;
import com.google.android.net.UrlRules;
import static com.google.android.net.UrlRules.Rule;
/** Test loading and matching URL rewrite rules for UrlRules. */
public class UrlRulesTest extends AndroidTestCase {
@SmallTest
public void testEmptyRules() {
UrlRules rules = new UrlRules(new Rule[] { });
assertTrue(rules.matchRule("http://foo.bar/") == Rule.DEFAULT);
}
@SmallTest
public void testInvalidRule() throws Exception {
try {
new Rule("rule", "foo bar");
} catch (Exception e) {
// Re-throw any exception except the one we're looking for.
if (!e.toString().contains("Illegal rule: foo bar")) throw e;
}
}
@SmallTest
public void testRewriteRule() throws UrlRules.RuleFormatException {
Rule rule = new Rule("test_rule",
"http://foo.bar/ rewrite http://bar.foo/");
assertEquals("test_rule", rule.mName);
assertEquals("http://foo.bar/", rule.mPrefix);
assertEquals("http://bar.foo/", rule.mRewrite);
assertFalse(rule.mBlock);
assertEquals("http://bar.foo/bat", rule.apply("http://foo.bar/bat"));
}
@SmallTest
public void testBlockRule() throws UrlRules.RuleFormatException {
Rule rule = new Rule("test_rule",
"http://foo.bar/ block");
assertEquals("test_rule", rule.mName);
assertEquals("http://foo.bar/", rule.mPrefix);
assertTrue(rule.mRewrite == null);
assertTrue(rule.mBlock);
assertTrue(rule.apply("http://foo.bar/bat") == null);
}
@SmallTest
public void testMatchRule() throws UrlRules.RuleFormatException {
UrlRules rules = new UrlRules(new Rule[] {
new Rule("12", "http://one.two/ rewrite http://buckle.my.shoe/"),
new Rule("34", "http://three.four/ rewrite http://close.the.door/"),
new Rule("56", "http://five.six/ rewrite http://pick.up.sticks/"),
});
assertTrue(rules.matchRule("https://one.two/") == Rule.DEFAULT);
assertTrue(rules.matchRule("http://one.two") == Rule.DEFAULT);
assertEquals("12", rules.matchRule("http://one.two/foo").mName);
String u = "http://five.six/bar";
assertEquals("http://pick.up.sticks/bar", rules.matchRule(u).apply(u));
}
@SmallTest
public void testAmbiguousMatch() throws UrlRules.RuleFormatException {
// Rule is the longest match wins.
UrlRules rules = new UrlRules(new Rule[] {
new Rule("1", "http://xyz/one rewrite http://rewrite/"),
new Rule("123", "http://xyz/onetwothree rewrite http://rewrite/"),
new Rule("12", "http://xyz/onetwo rewrite http://rewrite/"),
});
assertEquals("1", rules.matchRule("http://xyz/one").mName);
assertEquals("1", rules.matchRule("http://xyz/one...").mName);
assertEquals("12", rules.matchRule("http://xyz/onetwo...").mName);
assertEquals("123", rules.matchRule("http://xyz/onetwothree...").mName);
}
@MediumTest
public void testGservicesRules() {
// TODO: use a MockContentProvider/MockContentResolver instead.
ContentResolver r = getContext().getContentResolver();
// Update the digest, so the UrlRules cache is reloaded.
Settings.Gservices.putString(r, "digest", "testGservicesRules");
Settings.Gservices.putString(r, "url:blank_test", "");
Settings.Gservices.putString(r, "url:test",
"http://foo.bar/ rewrite http://bar.foo/");
UrlRules rules = UrlRules.getRules(r); // Don't crash, please. :)
assertTrue(rules.matchRule("http://bar.foo/") == Rule.DEFAULT);
Rule rule = rules.matchRule("http://foo.bar/bat");
assertEquals("test", rule.mName);
assertEquals("http://foo.bar/", rule.mPrefix);
assertEquals("http://bar.foo/", rule.mRewrite);
assertFalse(rule.mBlock);
}
}