summaryrefslogtreecommitdiffstats
path: root/tests/CoreTests
diff options
context:
space:
mode:
Diffstat (limited to 'tests/CoreTests')
-rw-r--r--tests/CoreTests/Android.mk2
-rw-r--r--tests/CoreTests/MODULE_LICENSE_APACHE20
-rw-r--r--tests/CoreTests/android/Android.mk15
-rw-r--r--tests/CoreTests/android/AndroidManifest.xml55
-rw-r--r--tests/CoreTests/android/content/ObserverNodeTest.java92
-rw-r--r--tests/CoreTests/android/content/SyncStorageEngineTest.java66
-rw-r--r--tests/CoreTests/android/core/AbstractJDBCDriverTest.java211
-rw-r--r--tests/CoreTests/android/core/ArrayListTest.java94
-rw-r--r--tests/CoreTests/android/core/AtParserTest.java348
-rw-r--r--tests/CoreTests/android/core/BooleanTest.java46
-rw-r--r--tests/CoreTests/android/core/BufferedInputStreamTest.java81
-rw-r--r--tests/CoreTests/android/core/BufferedOutputStreamTest.java50
-rw-r--r--tests/CoreTests/android/core/BufferedReaderTest.java66
-rw-r--r--tests/CoreTests/android/core/BufferedWriterTest.java53
-rw-r--r--tests/CoreTests/android/core/ByteArrayInputStreamTest.java43
-rw-r--r--tests/CoreTests/android/core/ByteArrayOutputStreamTest.java43
-rw-r--r--tests/CoreTests/android/core/CharArrayReaderTest.java42
-rw-r--r--tests/CoreTests/android/core/CharArrayWriterTest.java48
-rw-r--r--tests/CoreTests/android/core/ChecksumTest.java97
-rw-r--r--tests/CoreTests/android/core/ClassLoaderTest.java243
-rw-r--r--tests/CoreTests/android/core/ClassTest.java337
-rw-r--r--tests/CoreTests/android/core/CoreTests.java66
-rw-r--r--tests/CoreTests/android/core/CryptoTest.java137
-rw-r--r--tests/CoreTests/android/core/DataInputStreamTest.java107
-rw-r--r--tests/CoreTests/android/core/DataOutputStreamTest.java51
-rw-r--r--tests/CoreTests/android/core/DatabaseSessionCache.java312
-rw-r--r--tests/CoreTests/android/core/DatagramTest.java192
-rw-r--r--tests/CoreTests/android/core/DeflateTest.java199
-rw-r--r--tests/CoreTests/android/core/EnumTest.java64
-rw-r--r--tests/CoreTests/android/core/FileTest.java38
-rw-r--r--tests/CoreTests/android/core/FloatDoubleTest.java152
-rw-r--r--tests/CoreTests/android/core/GZIPStreamTest.java114
-rw-r--r--tests/CoreTests/android/core/HashMapPerfTest.java93
-rw-r--r--tests/CoreTests/android/core/HashMapTest.java281
-rw-r--r--tests/CoreTests/android/core/HttpConstants.java157
-rw-r--r--tests/CoreTests/android/core/IOUtil.java193
-rw-r--r--tests/CoreTests/android/core/InetAddrTest.java100
-rw-r--r--tests/CoreTests/android/core/InputStreamReaderTest.java114
-rw-r--r--tests/CoreTests/android/core/JavaTests.java86
-rw-r--r--tests/CoreTests/android/core/LineNumberReaderTest.java79
-rw-r--r--tests/CoreTests/android/core/LocaleTest.java199
-rw-r--r--tests/CoreTests/android/core/LowLevelNetRunner.java46
-rw-r--r--tests/CoreTests/android/core/MathTest.java831
-rw-r--r--tests/CoreTests/android/core/MiscRegressionTest.java506
-rw-r--r--tests/CoreTests/android/core/NIOTest.java694
-rw-r--r--tests/CoreTests/android/core/OutputStreamWriterTest.java48
-rw-r--r--tests/CoreTests/android/core/ParseIntTest.java110
-rw-r--r--tests/CoreTests/android/core/PipedStreamTest.java303
-rw-r--r--tests/CoreTests/android/core/PrintWriterTest.java75
-rw-r--r--tests/CoreTests/android/core/PushbackInputStreamTest.java57
-rw-r--r--tests/CoreTests/android/core/PushbackReaderTest.java57
-rw-r--r--tests/CoreTests/android/core/ReflectArrayTest.java136
-rw-r--r--tests/CoreTests/android/core/RegexTest.java288
-rw-r--r--tests/CoreTests/android/core/RequestAPITest.java483
-rw-r--r--tests/CoreTests/android/core/SQLiteJDBCDriverTest.java137
-rw-r--r--tests/CoreTests/android/core/SSLPerformanceTest.java432
-rw-r--r--tests/CoreTests/android/core/SSLSocketTest.java1089
-rw-r--r--tests/CoreTests/android/core/Sha1Test.java69
-rw-r--r--tests/CoreTests/android/core/SocketTest.java288
-rw-r--r--tests/CoreTests/android/core/StreamTokenizerTest.java96
-rw-r--r--tests/CoreTests/android/core/StrictMathTest.java855
-rw-r--r--tests/CoreTests/android/core/StringReaderTest.java40
-rw-r--r--tests/CoreTests/android/core/StringTest.java149
-rw-r--r--tests/CoreTests/android/core/StringWriterTest.java42
-rw-r--r--tests/CoreTests/android/core/TestEventHandler.java811
-rw-r--r--tests/CoreTests/android/core/TestWebData.java132
-rw-r--r--tests/CoreTests/android/core/TestWebServer.java871
-rw-r--r--tests/CoreTests/android/core/TreeMapTest.java105
-rw-r--r--tests/CoreTests/android/core/URITest.java55
-rw-r--r--tests/CoreTests/android/core/URLTest.java200
-rw-r--r--tests/CoreTests/android/core/ZipFileTest.java200
-rw-r--r--tests/CoreTests/android/core/ZipStreamTest.java171
-rw-r--r--tests/CoreTests/android/database/MatrixCursorTest.java146
-rw-r--r--tests/CoreTests/android/graphics/ColorStateListTest.java68
-rw-r--r--tests/CoreTests/android/graphics/drawable/StateListDrawableTest.java98
-rw-r--r--tests/CoreTests/android/location/LocationManagerProximityTest.java282
-rw-r--r--tests/CoreTests/android/location/LocationTest.java230
-rw-r--r--tests/CoreTests/android/res/color/color1.xml20
-rw-r--r--tests/CoreTests/android/res/color/color_no_default.xml19
-rw-r--r--tests/CoreTests/android/res/values/colors.xml24
-rw-r--r--tests/CoreTests/android/test/AndroidTestRunnerTest.java294
-rw-r--r--tests/CoreTests/android/test/InstrumentationTestRunnerTest.java272
-rw-r--r--tests/CoreTests/android/test/StubTestBrowserActivity.java33
-rw-r--r--tests/CoreTests/android/test/TestBrowserActivityTest.java270
-rw-r--r--tests/CoreTests/android/test/TestBrowserControllerImplTest.java134
-rw-r--r--tests/CoreTests/android/test/TestBrowserTests.java22
-rw-r--r--tests/CoreTests/android/test/TestCaseUtilTest.java100
-rw-r--r--tests/CoreTests/android/test/suitebuilder/AssignableFromTest.java85
-rw-r--r--tests/CoreTests/android/test/suitebuilder/InstrumentationTestSuiteBuilderTest.java116
-rw-r--r--tests/CoreTests/android/test/suitebuilder/ListTestCaseNames.java102
-rw-r--r--tests/CoreTests/android/test/suitebuilder/SmokeTestSuiteBuilderTest.java34
-rw-r--r--tests/CoreTests/android/test/suitebuilder/TestSuiteBuilderTest.java218
-rw-r--r--tests/CoreTests/android/test/suitebuilder/UnitTestSuiteBuilderTest.java109
-rw-r--r--tests/CoreTests/android/test/suitebuilder/annotation/HasAnnotationTest.java76
-rw-r--r--tests/CoreTests/android/test/suitebuilder/annotation/HasClassAnnotationTest.java57
-rw-r--r--tests/CoreTests/android/test/suitebuilder/annotation/HasMethodAnnotationTest.java56
-rw-r--r--tests/CoreTests/android/test/suitebuilder/examples/OuterTest.java37
-rw-r--r--tests/CoreTests/android/test/suitebuilder/examples/error/ErrorTest.java30
-rw-r--r--tests/CoreTests/android/test/suitebuilder/examples/error/FailingTest.java30
-rw-r--r--tests/CoreTests/android/test/suitebuilder/examples/instrumentation/InstrumentationTest.java26
-rw-r--r--tests/CoreTests/android/test/suitebuilder/examples/nested/Level1Test.java26
-rw-r--r--tests/CoreTests/android/test/suitebuilder/examples/nested/nested/Level2Test.java26
-rw-r--r--tests/CoreTests/android/test/suitebuilder/examples/simple/AnotherSimpleTest.java26
-rw-r--r--tests/CoreTests/android/test/suitebuilder/examples/simple/SimpleTest.java30
-rw-r--r--tests/CoreTests/android/test/suitebuilder/examples/smoke/NonSmokeTest.java26
-rw-r--r--tests/CoreTests/android/test/suitebuilder/examples/smoke/SmokeTest.java28
-rw-r--r--tests/CoreTests/android/test/suitebuilder/examples/subclass/SubclassTest.java24
-rw-r--r--tests/CoreTests/android/test/suitebuilder/examples/subclass/SuperclassTest.java26
-rw-r--r--tests/CoreTests/android/test/suitebuilder/examples/suppress/PartiallySuppressedTest.java33
-rw-r--r--tests/CoreTests/android/test/suitebuilder/examples/suppress/SuppressedTest.java29
-rw-r--r--tests/CoreTests/android/util/DayOfMonthCursorTest.java157
-rw-r--r--tests/CoreTests/android/util/FloatMathTest.java55
-rw-r--r--tests/CoreTests/android/util/MonthDisplayHelperTest.java211
-rw-r--r--tests/CoreTests/android/util/StateSetTest.java182
-rw-r--r--tests/CoreTests/android/view/FocusFinderTest.java576
-rw-r--r--tests/CoreTests/android/view/MockView.java25
-rw-r--r--tests/CoreTests/android/view/ViewGroupAttributesTest.java83
-rw-r--r--tests/CoreTests/android/webkit/CookieTest.java188
-rw-r--r--tests/CoreTests/com/android/internal/telephony/ATResponseParserTest.java113
-rw-r--r--tests/CoreTests/com/android/internal/telephony/PhoneNumberUtilsTest.java326
-rw-r--r--tests/CoreTests/com/android/internal/telephony/PhoneNumberWatcherTest.java65
-rw-r--r--tests/CoreTests/com/android/internal/telephony/TelephonyTests.java53
-rw-r--r--tests/CoreTests/com/android/internal/telephony/TestPhoneNotifier.java53
-rw-r--r--tests/CoreTests/com/android/internal/telephony/gsm/AdnRecordTest.java176
-rw-r--r--tests/CoreTests/com/android/internal/telephony/gsm/GSMPhoneTest.java1938
-rw-r--r--tests/CoreTests/com/android/internal/telephony/gsm/GSMTestHandler.java118
-rw-r--r--tests/CoreTests/com/android/internal/telephony/gsm/GsmAlphabetTest.java309
-rw-r--r--tests/CoreTests/com/android/internal/telephony/gsm/SMSDispatcherTest.java97
-rw-r--r--tests/CoreTests/com/android/internal/telephony/gsm/SimPhoneBookTest.java106
-rw-r--r--tests/CoreTests/com/android/internal/telephony/gsm/SimSmsTest.java60
-rw-r--r--tests/CoreTests/com/android/internal/telephony/gsm/SimUtilsTest.java79
-rw-r--r--tests/CoreTests/com/android/internal/util/PredicatesTest.java74
-rwxr-xr-xtests/CoreTests/run_core_test.sh6
-rwxr-xr-xtests/CoreTests/run_junit.sh9
134 files changed, 22463 insertions, 0 deletions
diff --git a/tests/CoreTests/Android.mk b/tests/CoreTests/Android.mk
new file mode 100644
index 0000000..8338432
--- /dev/null
+++ b/tests/CoreTests/Android.mk
@@ -0,0 +1,2 @@
+include $(call all-subdir-makefiles)
+
diff --git a/tests/CoreTests/MODULE_LICENSE_APACHE2 b/tests/CoreTests/MODULE_LICENSE_APACHE2
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/CoreTests/MODULE_LICENSE_APACHE2
diff --git a/tests/CoreTests/android/Android.mk b/tests/CoreTests/android/Android.mk
new file mode 100644
index 0000000..e6b5c45
--- /dev/null
+++ b/tests/CoreTests/android/Android.mk
@@ -0,0 +1,15 @@
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := tests
+
+LOCAL_SRC_FILES := \
+ $(call all-subdir-java-files)
+LOCAL_SRC_FILES += \
+ $(call all-java-files-under, ../com)
+
+LOCAL_JAVA_LIBRARIES := android.test.runner
+
+LOCAL_PACKAGE_NAME := CoreTests
+
+include $(BUILD_PACKAGE)
diff --git a/tests/CoreTests/android/AndroidManifest.xml b/tests/CoreTests/android/AndroidManifest.xml
new file mode 100644
index 0000000..4809f844
--- /dev/null
+++ b/tests/CoreTests/android/AndroidManifest.xml
@@ -0,0 +1,55 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="android.core">
+ <uses-permission android:name="android.permission.RECEIVE_SMS"/>
+ <uses-permission android:name="android.permission.INTERNET" />
+ <uses-permission android:name="android.permission.READ_CONTACTS" />
+ <uses-permission android:name="android.permission.WRITE_CONTACTS" />
+ <uses-permission android:name="android.permission.WAKE_LOCK" />
+ <uses-permission android:name="android.permission.CHANGE_CONFIGURATION" />
+ <uses-permission android:name="android.permission.WRITE_APN_SETTINGS" />
+ <uses-permission android:name="android.permission.BROADCAST_STICKY" />
+
+ <!-- location test permissions -->
+ <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
+ <uses-permission android:name="android.permission.ACCESS_MOCK_LOCATION"/>
+ <uses-permission android:name="android.permission.WRITE_SETTINGS"/>
+ <uses-permission android:name="android.permission.WRITE_SECURE_SETTINGS"/>
+
+ <application>
+ <uses-library android:name="android.test.runner" />
+ <activity android:name="StubTestBrowserActivity" android:label="Stubbed Test Browser">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN"/>
+ <category android:name="android.intent.category.FOR_TESTS_ONLY"/>
+ </intent-filter>
+ </activity>
+
+ <activity android:name="android.test.TestBrowserTests" android:label="Test Browser Tests">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN"/>
+ <category android:name="android.intent.category.UNIT_TEST"/>
+ </intent-filter>
+ </activity>
+ </application>
+
+ <instrumentation
+ android:name="android.test.InstrumentationTestRunner"
+ android:targetPackage="android.core"
+ android:label="Core Tests" />
+</manifest>
diff --git a/tests/CoreTests/android/content/ObserverNodeTest.java b/tests/CoreTests/android/content/ObserverNodeTest.java
new file mode 100644
index 0000000..68cc75b
--- /dev/null
+++ b/tests/CoreTests/android/content/ObserverNodeTest.java
@@ -0,0 +1,92 @@
+/*
+ * Copyright (C) 2007 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 android.content;
+
+import java.util.ArrayList;
+
+import android.content.ContentService.ObserverCall;
+import android.content.ContentService.ObserverNode;
+import android.database.ContentObserver;
+import android.net.Uri;
+import android.os.Handler;
+import android.test.AndroidTestCase;
+import android.util.Log;
+
+public class ObserverNodeTest extends AndroidTestCase {
+ static class TestObserver extends ContentObserver {
+ public TestObserver() {
+ super(new Handler());
+ }
+ }
+
+ public void testUri() {
+ ObserverNode root = new ObserverNode("");
+ Uri[] uris = new Uri[] {
+ Uri.parse("content://c/a/"),
+ Uri.parse("content://c/"),
+ Uri.parse("content://x/"),
+ Uri.parse("content://c/b/"),
+ Uri.parse("content://c/a/a1/1/"),
+ Uri.parse("content://c/a/a1/2/"),
+ Uri.parse("content://c/b/1/"),
+ Uri.parse("content://c/b/2/"),
+ };
+
+ int[] nums = new int[] {4, 7, 1, 4, 2, 2, 3, 3};
+
+ // special case
+ root.addObserver(uris[0], new TestObserver().getContentObserver(), false);
+ for(int i = 1; i < uris.length; i++) {
+ root.addObserver(uris[i], new TestObserver().getContentObserver(), true);
+ }
+
+ ArrayList<ObserverCall> calls = new ArrayList<ObserverCall>();
+
+ for (int i = nums.length - 1; i >=0; --i) {
+ root.collectObservers(uris[i], 0, null, false, calls);
+ assertEquals(nums[i], calls.size());
+ calls.clear();
+ }
+ }
+
+ public void testUriNotNotify() {
+ ObserverNode root = new ObserverNode("");
+ Uri[] uris = new Uri[] {
+ Uri.parse("content://c/"),
+ Uri.parse("content://x/"),
+ Uri.parse("content://c/a/"),
+ Uri.parse("content://c/b/"),
+ Uri.parse("content://c/a/1/"),
+ Uri.parse("content://c/a/2/"),
+ Uri.parse("content://c/b/1/"),
+ Uri.parse("content://c/b/2/"),
+ };
+ int[] nums = new int[] {7, 1, 3, 3, 1, 1, 1, 1};
+
+ for(int i = 0; i < uris.length; i++) {
+ root.addObserver(uris[i], new TestObserver().getContentObserver(), false);
+ }
+
+ ArrayList<ObserverCall> calls = new ArrayList<ObserverCall>();
+
+ for (int i = uris.length - 1; i >=0; --i) {
+ root.collectObservers(uris[i], 0, null, false, calls);
+ assertEquals(nums[i], calls.size());
+ calls.clear();
+ }
+ }
+}
diff --git a/tests/CoreTests/android/content/SyncStorageEngineTest.java b/tests/CoreTests/android/content/SyncStorageEngineTest.java
new file mode 100644
index 0000000..36805b1
--- /dev/null
+++ b/tests/CoreTests/android/content/SyncStorageEngineTest.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2007 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 android.content;
+
+import android.test.AndroidTestCase;
+import android.test.RenamingDelegatingContext;
+import android.test.mock.MockContext;
+import android.test.mock.MockContentResolver;
+import android.provider.Sync;
+
+public class SyncStorageEngineTest extends AndroidTestCase {
+
+ /**
+ * Test that we handle the case of a history row being old enough to purge before the
+ * correcponding sync is finished. This can happen if the clock changes while we are syncing.
+ */
+ public void testPurgeActiveSync() throws Exception {
+ final String account = "a@example.com";
+ final String authority = "testprovider";
+
+ MockContentResolver mockResolver = new MockContentResolver();
+
+ SyncStorageEngine engine = SyncStorageEngine.newTestInstance(
+ new TestContext(mockResolver, getContext()));
+
+ long time0 = 1000;
+ long historyId = engine.insertStartSyncEvent(
+ account, authority, time0, Sync.History.SOURCE_LOCAL);
+ long time1 = time0 + SyncStorageEngine.MILLIS_IN_4WEEKS * 2;
+ engine.stopSyncEvent(historyId, time1 - time0, "yay", 0, 0);
+ }
+}
+
+class TestContext extends ContextWrapper {
+
+ ContentResolver mResolver;
+
+ public TestContext(ContentResolver resolver, Context realContext) {
+ super(new RenamingDelegatingContext(new MockContext(), realContext, "test."));
+ mResolver = resolver;
+ }
+
+ @Override
+ public void enforceCallingOrSelfPermission(String permission, String message) {
+ }
+
+
+ @Override
+ public ContentResolver getContentResolver() {
+ return mResolver;
+ }
+}
diff --git a/tests/CoreTests/android/core/AbstractJDBCDriverTest.java b/tests/CoreTests/android/core/AbstractJDBCDriverTest.java
new file mode 100644
index 0000000..e381a5e
--- /dev/null
+++ b/tests/CoreTests/android/core/AbstractJDBCDriverTest.java
@@ -0,0 +1,211 @@
+/*
+ * 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 android.core;
+
+import java.io.File;
+import java.sql.Connection;
+import java.sql.DriverManager;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Statement;
+
+import junit.framework.TestCase;
+import android.test.suitebuilder.annotation.MediumTest;
+
+/**
+ * Tests for the most commonly used methods of sql like creating a connection,
+ * inserting, selecting, updating.
+ */
+public abstract class AbstractJDBCDriverTest extends TestCase {
+
+ @MediumTest
+ public void testJDBCDriver() throws Exception {
+ Connection firstConnection = null;
+ Connection secondConnection = null;
+ File dbFile = getDbFile();
+ String connectionURL = getConnectionURL();
+ Statement firstStmt = null;
+ Statement secondStmt = null;
+ try {
+ Class.forName(getJDBCDriverClassName());
+ firstConnection = DriverManager.getConnection(connectionURL);
+ secondConnection = DriverManager.getConnection(connectionURL);
+
+ String[] ones = {"hello!", "goodbye"};
+ short[] twos = {10, 20};
+ String[] onesUpdated = new String[ones.length];
+ for (int i = 0; i < ones.length; i++) {
+ onesUpdated[i] = ones[i] + twos[i];
+ }
+ firstStmt = firstConnection.createStatement();
+ firstStmt.execute("create table tbl1(one varchar(10), two smallint)");
+ secondStmt = secondConnection.createStatement();
+
+ autoCommitInsertSelectTest(firstStmt, ones, twos);
+ updateSelectCommitSelectTest(firstStmt, secondStmt, ones, onesUpdated, twos);
+ updateSelectRollbackSelectTest(firstStmt, secondStmt, onesUpdated, ones, twos);
+ } finally {
+ closeConnections(firstConnection, secondConnection, dbFile, firstStmt, secondStmt);
+ }
+ }
+
+ protected abstract String getJDBCDriverClassName();
+ protected abstract String getConnectionURL();
+ protected abstract File getDbFile();
+
+ private void closeConnections(Connection firstConnection, Connection secondConnection,
+ File dbFile, Statement firstStmt, Statement secondStmt) {
+ String failText = null;
+ try {
+ if (firstStmt != null) {
+ firstStmt.execute("drop table tbl1");
+ }
+ } catch (SQLException e) {
+ failText = e.getLocalizedMessage();
+ }
+ try {
+ if (firstStmt != null) {
+ firstStmt.close();
+ }
+ } catch (SQLException e) {
+ failText = e.getLocalizedMessage();
+ }
+ try {
+ if (firstConnection != null) {
+ firstConnection.close();
+ }
+ } catch (SQLException e) {
+ failText = e.getLocalizedMessage();
+ }
+ try {
+ if (secondStmt != null) {
+ secondStmt.close();
+ }
+ } catch (SQLException e) {
+ failText = e.getLocalizedMessage();
+ }
+ try {
+ if (secondConnection != null) {
+ secondConnection.close();
+ }
+ } catch (SQLException e) {
+ failText = e.getLocalizedMessage();
+ }
+ dbFile.delete();
+ assertNull(failText, failText);
+ }
+
+ /**
+ * Inserts the values from 'ones' with the values from 'twos' into 'tbl1'
+ * @param stmt the statement to use for the inserts.
+ * @param ones the string values to insert into tbl1.
+ * @param twos the corresponding numerical values to insert into tbl1.
+ * @throws SQLException in case of a problem during insert.
+ */
+ private void autoCommitInsertSelectTest(Statement stmt, String[] ones,
+ short[] twos) throws SQLException {
+ for (int i = 0; i < ones.length; i++) {
+ stmt.execute("insert into tbl1 values('" + ones[i] + "'," + twos[i]
+ + ")");
+ }
+ assertAllFromTbl1(stmt, ones, twos);
+ }
+
+ /**
+ * Asserts that all values that where added to tbl1 are actually in tbl1.
+ * @param stmt the statement to use for the select.
+ * @param ones the string values that where added.
+ * @param twos the numerical values that where added.
+ * @throws SQLException in case of a problem during select.
+ */
+ private void assertAllFromTbl1(Statement stmt, String[] ones, short[] twos)
+ throws SQLException {
+ ResultSet rs = stmt.executeQuery("select * from tbl1");
+ int i = 0;
+ for (; rs.next(); i++) {
+ assertTrue(i < ones.length);
+ assertEquals(ones[i], rs.getString("one"));
+ assertEquals(twos[i], rs.getShort("two"));
+ }
+ assertEquals(i, ones.length);
+ }
+
+ /**
+ * Tests the results of an update followed bz a select on a diffrent statement.
+ * After that the first statement commits its update. and now the second
+ * statement should also be able to see the changed values in a select.
+ * @param firstStmt the statement to use for the update and commit.
+ * @param secondStmt the statement that should be used to check if the commit works
+ * @param ones the original string values.
+ * @param onesUpdated the updated string values.
+ * @param twos the numerical values.
+ * @throws SQLException in case of a problem during any of the executed commands.
+ */
+ private void updateSelectCommitSelectTest(Statement firstStmt,
+ Statement secondStmt, String[] ones, String[] onesUpdated,
+ short[] twos) throws SQLException {
+ firstStmt.getConnection().setAutoCommit(false);
+ try {
+ updateOnes(firstStmt, onesUpdated, twos);
+ assertAllFromTbl1(secondStmt, ones, twos);
+ firstStmt.getConnection().commit();
+ assertAllFromTbl1(secondStmt, onesUpdated, twos);
+ } finally {
+ firstStmt.getConnection().setAutoCommit(true);
+ }
+ }
+
+ /**
+ * Tests if an update followed by a select works. After that a rollback will
+ * be made and again a select should show that the rollback worked.
+ * @param firstStmt the statement to use for the update and the rollback
+ * @param secondStmt the statement to use for checking if the rollback worked as intended.
+ * @param ones the original string values.
+ * @param onesUpdated the updated string values.
+ * @param twos the nomerical values.
+ * @throws SQLException in case of a problem during any command.
+ */
+ private void updateSelectRollbackSelectTest(Statement firstStmt,
+ Statement secondStmt, String[] ones, String[] onesUpdated,
+ short[] twos) throws SQLException {
+ firstStmt.getConnection().setAutoCommit(false);
+ try {
+ updateOnes(firstStmt, onesUpdated, twos);
+ assertAllFromTbl1(secondStmt, ones, twos);
+ firstStmt.getConnection().rollback();
+ assertAllFromTbl1(secondStmt, ones, twos);
+ } finally {
+ firstStmt.getConnection().setAutoCommit(true);
+ }
+ }
+
+ /**
+ * updates the sring values. the original values are stored in 'ones'
+ * and the updated values in 'ones_updated'
+ * @param stmt the statement to use for the update.
+ * @param onesUpdated the new string values.
+ * @param twos the numerical values.
+ * @throws SQLException in case of a problem during update.
+ */
+ private void updateOnes(Statement stmt, String[] onesUpdated, short[] twos)
+ throws SQLException {
+ for (int i = 0; i < onesUpdated.length; i++) {
+ stmt.execute("UPDATE tbl1 SET one = '" + onesUpdated[i]
+ + "' WHERE two = " + twos[i]);
+ }
+ }
+}
diff --git a/tests/CoreTests/android/core/ArrayListTest.java b/tests/CoreTests/android/core/ArrayListTest.java
new file mode 100644
index 0000000..763bf99
--- /dev/null
+++ b/tests/CoreTests/android/core/ArrayListTest.java
@@ -0,0 +1,94 @@
+/*
+ * 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 android.core;
+
+import junit.framework.TestCase;
+
+import java.util.ArrayList;
+import android.test.suitebuilder.annotation.SmallTest;
+
+/**
+ * This test case tests several often used functionality of ArrayLists.
+ */
+public class ArrayListTest extends TestCase {
+
+ @SuppressWarnings("unchecked")
+ @SmallTest
+ public void testArrayList() throws Exception {
+ ArrayList array = new ArrayList();
+ assertEquals(0, array.size());
+ assertTrue(array.isEmpty());
+
+ array.add(new Integer(0));
+ array.add(0, new Integer(1));
+ array.add(1, new Integer(2));
+ array.add(new Integer(3));
+ array.add(new Integer(1));
+
+ assertEquals(5, array.size());
+ assertFalse(array.isEmpty());
+
+ assertEquals(1, ((Integer) array.get(0)).intValue());
+ assertEquals(2, ((Integer) array.get(1)).intValue());
+ assertEquals(0, ((Integer) array.get(2)).intValue());
+ assertEquals(3, ((Integer) array.get(3)).intValue());
+ assertEquals(1, ((Integer) array.get(4)).intValue());
+
+ assertFalse(array.contains(null));
+ assertTrue(array.contains(new Integer(2)));
+ assertEquals(0, array.indexOf(new Integer(1)));
+ assertEquals(4, array.lastIndexOf(new Integer(1)));
+ assertTrue(array.indexOf(new Integer(5)) < 0);
+ assertTrue(array.lastIndexOf(new Integer(5)) < 0);
+
+
+ array.remove(1);
+ array.remove(1);
+
+ assertEquals(3, array.size());
+ assertFalse(array.isEmpty());
+ assertEquals(1, ((Integer) array.get(0)).intValue());
+ assertEquals(3, ((Integer) array.get(1)).intValue());
+ assertEquals(1, ((Integer) array.get(2)).intValue());
+
+ assertFalse(array.contains(null));
+ assertFalse(array.contains(new Integer(2)));
+ assertEquals(0, array.indexOf(new Integer(1)));
+ assertEquals(2, array.lastIndexOf(new Integer(1)));
+ assertTrue(array.indexOf(new Integer(5)) < 0);
+ assertTrue(array.lastIndexOf(new Integer(5)) < 0);
+
+ array.clear();
+
+ assertEquals(0, array.size());
+ assertTrue(array.isEmpty());
+ assertTrue(array.indexOf(new Integer(5)) < 0);
+ assertTrue(array.lastIndexOf(new Integer(5)) < 0);
+
+ ArrayList al = new ArrayList();
+
+ assertFalse(al.remove(null));
+ assertFalse(al.remove("string"));
+
+ al.add("string");
+ al.add(null);
+
+ assertTrue(al.remove(null));
+ assertTrue(al.remove("string"));
+ }
+}
+
diff --git a/tests/CoreTests/android/core/AtParserTest.java b/tests/CoreTests/android/core/AtParserTest.java
new file mode 100644
index 0000000..09cb6e9
--- /dev/null
+++ b/tests/CoreTests/android/core/AtParserTest.java
@@ -0,0 +1,348 @@
+/*
+ * Copyright (C) 2007 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 android.core;
+
+import android.bluetooth.AtCommandHandler;
+import android.bluetooth.AtCommandResult;
+import android.bluetooth.AtParser;
+
+import java.util.*;
+import junit.framework.*;
+
+public class AtParserTest extends TestCase {
+
+ /* An AtCommandHandler instrumented for testing purposes
+ */
+ private class HandlerTest extends AtCommandHandler {
+ boolean mBasicCalled, mActionCalled, mReadCalled, mTestCalled,
+ mSetCalled;
+ int mBasicReturn, mActionReturn, mReadReturn, mTestReturn, mSetReturn;
+ Object[] mSetArgs;
+ String mBasicArgs;
+
+ HandlerTest() {
+ this(AtCommandResult.ERROR, AtCommandResult.ERROR,
+ AtCommandResult.ERROR, AtCommandResult.ERROR,
+ AtCommandResult.ERROR);
+ }
+
+ HandlerTest(int a, int b, int c, int d, int e) {
+ mBasicReturn = a;
+ mActionReturn = b;
+ mReadReturn = c;
+ mSetReturn = d;
+ mTestReturn = e;
+ reset();
+ }
+ public void reset() {
+ mBasicCalled = false;
+ mActionCalled = false;
+ mReadCalled = false;
+ mSetCalled = false;
+ mTestCalled = false;
+ mSetArgs = null;
+ mBasicArgs = null;
+ }
+ public boolean wasCalled() { // helper
+ return mBasicCalled || mActionCalled || mReadCalled ||
+ mTestCalled || mSetCalled;
+ }
+ @Override
+ public AtCommandResult handleBasicCommand(String args) {
+ mBasicCalled = true;
+ mBasicArgs = args;
+ return new AtCommandResult(mBasicReturn);
+ }
+ @Override
+ public AtCommandResult handleActionCommand() {
+ mActionCalled = true;
+ return new AtCommandResult(mActionReturn);
+ }
+ @Override
+ public AtCommandResult handleReadCommand() {
+ mReadCalled = true;
+ return new AtCommandResult(mReadReturn);
+ }
+ @Override
+ public AtCommandResult handleSetCommand(Object[] args) {
+ mSetCalled = true;
+ mSetArgs = args;
+ return new AtCommandResult(mSetReturn);
+ }
+ @Override
+ public AtCommandResult handleTestCommand() {
+ mTestCalled = true;
+ return new AtCommandResult(mTestReturn);
+ }
+ }
+
+ private AtParser mParser;
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ mParser = new AtParser();
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ }
+
+
+ /* Test that the right method is being called
+ */
+/* public void testBasic1() throws Exception {
+ HandlerTest D = new HandlerTest(0, 1, 1, 1, 1);
+ HandlerTest A = new HandlerTest(0, 1, 1, 1, 1);
+ mParser.register('D', D);
+ mParser.register('A', A);
+
+ assertTrue(Arrays.equals(
+ new String[]{"OK"},
+ mParser.process(" A T D = ? T 1 2 3 4 ").toStrings()));
+ assertTrue(D.mBasicCalled);
+ assertFalse(D.mActionCalled);
+ assertFalse(D.mTestCalled);
+ assertFalse(D.mSetCalled);
+ assertFalse(D.mReadCalled);
+ assertFalse(A.wasCalled());
+ assertEquals("=?T1234", D.mBasicArgs);
+ }
+*/
+ /* Test some crazy strings
+ *//*
+ public void testBasic2() throws Exception {
+ HandlerTest A = new HandlerTest(0, 1, 1, 1, 1);
+ mParser.register('A', A);
+
+ assertTrue(Arrays.equals(
+ new String[]{},
+ mParser.process(" ").toStrings()));
+
+ assertTrue(Arrays.equals(
+ new String[]{"OK"},
+ mParser.process(" a T a t \"\" 1 2 3 a 4 ")
+ .toStrings()));
+ assertEquals("T\"\"123A4", A.mBasicArgs);
+
+ assertTrue(Arrays.equals(
+ new String[]{"OK"},
+ mParser.process(" a T a t \"foo BaR12Z\" 1 2 3 a 4 ")
+ .toStrings()));
+ assertEquals("T\"foo BaR12Z\"123A4", A.mBasicArgs);
+
+ assertTrue(Arrays.equals(
+ new String[]{"OK"},
+ mParser.process("ATA\"").toStrings()));
+ assertEquals("\"\"", A.mBasicArgs);
+
+ assertTrue(Arrays.equals(
+ new String[]{"OK"},
+ mParser.process("ATA\"a").toStrings()));
+ assertEquals("\"a\"", A.mBasicArgs);
+
+ assertTrue(Arrays.equals(
+ new String[]{"OK"},
+ mParser.process("ATa\" ").toStrings()));
+ assertEquals("\" \"", A.mBasicArgs);
+
+ assertTrue(Arrays.equals(
+ new String[]{"OK"},
+ mParser.process("ATA \"one \" two \"t hr ee ")
+ .toStrings()));
+ assertEquals("\"one \"TWO\"t hr ee \"", A.mBasicArgs);
+ }*/
+
+ /* Simple extended commands
+ *//*
+ public void testExt1() throws Exception {
+ HandlerTest A = new HandlerTest(1, 0, 0, 0, 0);
+ mParser.register("+A", A);
+
+ assertTrue(Arrays.equals(
+ new String[]{"ERROR"},
+ mParser.process("AT+B").toStrings()));
+ assertFalse(A.wasCalled());
+
+ assertTrue(Arrays.equals(
+ new String[]{"OK"},
+ mParser.process("AT+A").toStrings()));
+ assertTrue(A.mActionCalled);
+ A.mActionCalled = false;
+ assertFalse(A.wasCalled());
+ A.reset();
+
+ assertTrue(Arrays.equals(
+ new String[]{"OK"},
+ mParser.process("AT+A=").toStrings()));
+ assertTrue(A.mSetCalled);
+ A.mSetCalled = false;
+ assertFalse(A.wasCalled());
+ assertEquals(1, A.mSetArgs.length);
+ A.reset();
+
+ assertTrue(Arrays.equals(
+ new String[]{"OK"},
+ mParser.process("AT+A=?").toStrings()));
+ assertTrue(A.mTestCalled);
+ A.mTestCalled = false;
+ assertFalse(A.wasCalled());
+ A.reset();
+
+ assertTrue(Arrays.equals(
+ new String[]{"OK"},
+ mParser.process("AT+A?").toStrings()));
+ assertTrue(A.mReadCalled);
+ A.mReadCalled = false;
+ assertFalse(A.wasCalled());
+ A.reset();
+ }
+*/
+
+
+ /* Test chained commands
+ *//*
+ public void testChain1() throws Exception {
+ HandlerTest A = new HandlerTest(0, 1, 1, 1, 1);
+ HandlerTest B = new HandlerTest(1, 0, 0, 0, 0);
+ HandlerTest C = new HandlerTest(1, 1, 1, 1, 1);
+ mParser.register('A', A);
+ mParser.register("+B", B);
+ mParser.register("+C", C);
+
+ assertTrue(Arrays.equals(
+ new String[]{"ERROR"},
+ mParser.process("AT+B;+C").toStrings()));
+ assertTrue(B.mActionCalled);
+ assertTrue(C.mActionCalled);
+ B.reset();
+ C.reset();
+
+ assertTrue(Arrays.equals(
+ new String[]{"ERROR"},
+ mParser.process("AT+C;+B").toStrings()));
+ assertFalse(B.wasCalled());
+ assertTrue(C.mActionCalled);
+ B.reset();
+ C.reset();
+ }*/
+
+ /* Test Set command
+ *//*
+ public void testSet1() throws Exception {
+ HandlerTest A = new HandlerTest(1, 1, 1, 0, 1);
+ mParser.register("+AAAA", A);
+ Object[] expectedResult;
+
+ assertTrue(Arrays.equals(
+ new String[]{"OK"},
+ mParser.process("AT+AAAA=1").toStrings()));
+ expectedResult = new Object[]{(Integer)1};
+ assertTrue(Arrays.equals(expectedResult, A.mSetArgs));
+ A.reset();
+
+ assertTrue(Arrays.equals(
+ new String[]{"OK"},
+ mParser.process("AT+AAAA=1,2,3").toStrings()));
+ expectedResult = new Object[]{(Integer)1, (Integer)2, (Integer)3};
+ assertTrue(Arrays.equals(expectedResult, A.mSetArgs));
+ A.reset();
+
+ assertTrue(Arrays.equals(
+ new String[]{"OK"},
+ mParser.process("AT+AAAA=3,0,0,1").toStrings()));
+ expectedResult = new Object[]{(Integer)3, (Integer)0, (Integer)0,
+ (Integer)1};
+ assertTrue(Arrays.equals(expectedResult, A.mSetArgs));
+ A.reset();
+
+ assertTrue(Arrays.equals(
+ new String[]{"OK"},
+ mParser.process("AT+AAAA=\"foo\",1,\"b,ar").toStrings()));
+ expectedResult = new Object[]{"\"foo\"", 1, "\"b,ar\""};
+ assertTrue(Arrays.equals(expectedResult, A.mSetArgs));
+ A.reset();
+
+ assertTrue(Arrays.equals(
+ new String[]{"OK"},
+ mParser.process("AT+AAAA=").toStrings()));
+ expectedResult = new Object[]{""};
+ assertTrue(Arrays.equals(expectedResult, A.mSetArgs));
+ A.reset();
+
+ assertTrue(Arrays.equals(
+ new String[]{"OK"},
+ mParser.process("AT+AAAA=,").toStrings()));
+ expectedResult = new Object[]{"", ""};
+ assertTrue(Arrays.equals(expectedResult, A.mSetArgs));
+ A.reset();
+
+ assertTrue(Arrays.equals(
+ new String[]{"OK"},
+ mParser.process("AT+AAAA=,,,").toStrings()));
+ expectedResult = new Object[]{"", "", "", ""};
+ assertTrue(Arrays.equals(expectedResult, A.mSetArgs));
+ A.reset();
+
+ assertTrue(Arrays.equals(
+ new String[]{"OK"},
+ mParser.process("AT+AAAA=,1,,\"foo\",").toStrings()));
+ expectedResult = new Object[]{"", 1, "", "\"foo\"", ""};
+ assertEquals(5, A.mSetArgs.length);
+ assertTrue(Arrays.equals(expectedResult, A.mSetArgs));
+ A.reset();
+ }*/
+
+ /* Test repeat command "A/"
+ *//*
+ public void testRepeat() throws Exception {
+ HandlerTest A = new HandlerTest(0, 0, 0, 0, 0);
+ mParser.register('A', A);
+
+ // Try repeated command on fresh parser
+ assertTrue(Arrays.equals(
+ new String[]{},
+ mParser.process("A/").toStrings()));
+ assertFalse(A.wasCalled());
+ A.reset();
+
+ assertTrue(Arrays.equals(
+ new String[]{"OK"},
+ mParser.process("ATA").toStrings()));
+ assertTrue(A.mBasicCalled);
+ assertEquals("", A.mBasicArgs);
+ A.reset();
+
+ // Now repeat the command
+ assertTrue(Arrays.equals(
+ new String[]{"OK"},
+ mParser.process("A/").toStrings()));
+ assertTrue(A.mBasicCalled);
+ assertEquals("", A.mBasicArgs);
+ A.reset();
+
+ // Multiple repeats
+ assertTrue(Arrays.equals(
+ new String[]{"OK"},
+ mParser.process("A/").toStrings()));
+ assertTrue(A.mBasicCalled);
+ assertEquals("", A.mBasicArgs);
+ A.reset();
+
+ }*/
+}
diff --git a/tests/CoreTests/android/core/BooleanTest.java b/tests/CoreTests/android/core/BooleanTest.java
new file mode 100644
index 0000000..211947e
--- /dev/null
+++ b/tests/CoreTests/android/core/BooleanTest.java
@@ -0,0 +1,46 @@
+/*
+ * 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 android.core;
+
+import junit.framework.TestCase;
+import android.test.suitebuilder.annotation.SmallTest;
+
+/**
+ * Tests some basic functionality of Booleans.
+ */
+public class BooleanTest extends TestCase {
+
+ @SmallTest
+ public void testBoolean() throws Exception {
+ Boolean a = new Boolean(true);
+ Boolean b = new Boolean("True");
+ Boolean c = new Boolean(false);
+ Boolean d = new Boolean("Yes");
+
+ assertEquals(a, b);
+ assertEquals(c, d);
+ assertTrue(a.booleanValue());
+ assertFalse(c.booleanValue());
+ assertEquals("true", a.toString());
+ assertEquals("false", c.toString());
+ assertEquals(Boolean.TRUE, a);
+ assertEquals(Boolean.FALSE, c);
+ assertSame(Boolean.valueOf(true), Boolean.TRUE);
+ assertSame(Boolean.valueOf(false), Boolean.FALSE);
+ }
+}
+
diff --git a/tests/CoreTests/android/core/BufferedInputStreamTest.java b/tests/CoreTests/android/core/BufferedInputStreamTest.java
new file mode 100644
index 0000000..1ad95a1
--- /dev/null
+++ b/tests/CoreTests/android/core/BufferedInputStreamTest.java
@@ -0,0 +1,81 @@
+/*
+ * 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 android.core;
+
+import junit.framework.TestCase;
+
+import java.io.BufferedInputStream;
+import java.io.ByteArrayInputStream;
+import android.test.suitebuilder.annotation.SmallTest;
+
+/**
+ * Tests to verify that simple functionality works for BufferedInputStreams.
+ */
+public class BufferedInputStreamTest extends TestCase {
+
+ @SmallTest
+ public void testBufferedInputStream() throws Exception {
+ String str = "AbCdEfGhIjKlM\nOpQrStUvWxYz";
+ ByteArrayInputStream aa = new ByteArrayInputStream(str.getBytes());
+ ByteArrayInputStream ba = new ByteArrayInputStream(str.getBytes());
+ ByteArrayInputStream ca = new ByteArrayInputStream(str.getBytes());
+ ByteArrayInputStream da = new ByteArrayInputStream(str.getBytes());
+ ByteArrayInputStream ea = new ByteArrayInputStream(str.getBytes());
+
+ BufferedInputStream a = new BufferedInputStream(aa, 6);
+ try {
+ assertEquals(str, IOUtil.read(a));
+ } finally {
+ a.close();
+ }
+
+ BufferedInputStream b = new BufferedInputStream(ba, 7);
+ try {
+ assertEquals("AbCdEfGhIj", IOUtil.read(b, 10));
+ } finally {
+ b.close();
+ }
+
+ BufferedInputStream c = new BufferedInputStream(ca, 9);
+ try {
+ assertEquals("bdfhjl\nprtvxz", IOUtil.skipRead(c));
+ } finally {
+ c.close();
+ }
+
+ BufferedInputStream d = new BufferedInputStream(da, 9);
+ try {
+ assertEquals('A', d.read());
+ d.mark(15);
+ assertEquals('b', d.read());
+ assertEquals('C', d.read());
+ d.reset();
+ assertEquals('b', d.read());
+ } finally {
+ d.close();
+ }
+
+ BufferedInputStream e = new BufferedInputStream(ea, 11);
+ try {
+ // test that we can ask for more than is present, and that we'll get
+ // back only what is there.
+ assertEquals(str, IOUtil.read(e, 10000));
+ } finally {
+ e.close();
+ }
+ }
+}
diff --git a/tests/CoreTests/android/core/BufferedOutputStreamTest.java b/tests/CoreTests/android/core/BufferedOutputStreamTest.java
new file mode 100644
index 0000000..cd8ec08
--- /dev/null
+++ b/tests/CoreTests/android/core/BufferedOutputStreamTest.java
@@ -0,0 +1,50 @@
+/*
+ * 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 android.core;
+
+import junit.framework.TestCase;
+
+import java.io.BufferedOutputStream;
+import java.io.ByteArrayOutputStream;
+import android.test.suitebuilder.annotation.SmallTest;
+
+/**
+ * Tests to verify that simple functionality works for BufferedOutputStreams.
+ */
+public class BufferedOutputStreamTest extends TestCase {
+
+ @SmallTest
+ public void testBufferedOutputStream() throws Exception {
+ String str = "AbCdEfGhIjKlMnOpQrStUvWxYz";
+ ByteArrayOutputStream aa = new ByteArrayOutputStream();
+ BufferedOutputStream a = new BufferedOutputStream(aa, 15);
+ try {
+ a.write(str.getBytes(), 0, 26);
+ a.write('A');
+
+ assertEquals(26, aa.size());
+ assertEquals(aa.toString(), str);
+
+ a.flush();
+
+ assertEquals(27, aa.size());
+ assertEquals("AbCdEfGhIjKlMnOpQrStUvWxYzA", aa.toString());
+ } finally {
+ a.close();
+ }
+ }
+}
diff --git a/tests/CoreTests/android/core/BufferedReaderTest.java b/tests/CoreTests/android/core/BufferedReaderTest.java
new file mode 100644
index 0000000..a94ca02
--- /dev/null
+++ b/tests/CoreTests/android/core/BufferedReaderTest.java
@@ -0,0 +1,66 @@
+/*
+ * 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 android.core;
+
+import junit.framework.TestCase;
+
+import java.io.BufferedReader;
+import java.io.StringReader;
+import android.test.suitebuilder.annotation.MediumTest;
+
+/**
+ * Tests to verify that simple functionality works for BufferedReaders.
+ */
+public class BufferedReaderTest extends TestCase {
+
+ @MediumTest
+ public void testBufferedReader() throws Exception {
+ String str = "AbCdEfGhIjKlMnOpQrStUvWxYz";
+ StringReader aa = new StringReader(str);
+ StringReader ba = new StringReader(str);
+ StringReader ca = new StringReader(str);
+ StringReader da = new StringReader(str);
+
+ BufferedReader a = new BufferedReader(aa, 5);
+ try {
+ assertEquals(str, IOUtil.read(a));
+ } finally {
+ a.close();
+ }
+
+ BufferedReader b = new BufferedReader(ba, 15);
+ try {
+ assertEquals("AbCdEfGhIj", IOUtil.read(b, 10));
+ } finally {
+ b.close();
+ }
+
+ BufferedReader c = new BufferedReader(ca);
+ try {
+ assertEquals("bdfhjlnprtvxz", IOUtil.skipRead(c));
+ } finally {
+ c.close();
+ }
+
+ BufferedReader d = new BufferedReader(da);
+ try {
+ assertEquals("AbCdEfGdEfGhIjKlMnOpQrStUvWxYz", IOUtil.markRead(d, 3, 4));
+ } finally {
+ d.close();
+ }
+ }
+}
diff --git a/tests/CoreTests/android/core/BufferedWriterTest.java b/tests/CoreTests/android/core/BufferedWriterTest.java
new file mode 100644
index 0000000..12dfcef
--- /dev/null
+++ b/tests/CoreTests/android/core/BufferedWriterTest.java
@@ -0,0 +1,53 @@
+/*
+ * 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 android.core;
+
+import junit.framework.TestCase;
+
+import java.io.BufferedWriter;
+import java.io.StringWriter;
+import android.test.suitebuilder.annotation.SmallTest;
+
+/**
+ * Some basic tests for BufferedWriter.
+ */
+public class BufferedWriterTest extends TestCase {
+
+ @SmallTest
+ public void testBufferedWriter() throws Exception {
+ String str = "AbCdEfGhIjKlMnOpQrStUvWxYz";
+ StringWriter aa = new StringWriter();
+
+ BufferedWriter a = new BufferedWriter(aa, 20);
+ try {
+ a.write(str.toCharArray(), 0, 26);
+ a.write('X');
+ a.flush();
+ assertEquals("AbCdEfGhIjKlMnOpQrStUvWxYzX", aa.toString());
+
+ a.write("alphabravodelta", 5, 5);
+ a.flush();
+ assertEquals("AbCdEfGhIjKlMnOpQrStUvWxYzXbravo", aa.toString());
+ a.newLine();
+ a.write("I'm on a new line.");
+ a.flush();
+ assertEquals("AbCdEfGhIjKlMnOpQrStUvWxYzXbravo\nI\'m on a new line.", aa.toString());
+ } finally {
+ a.close();
+ }
+ }
+}
diff --git a/tests/CoreTests/android/core/ByteArrayInputStreamTest.java b/tests/CoreTests/android/core/ByteArrayInputStreamTest.java
new file mode 100644
index 0000000..d964102
--- /dev/null
+++ b/tests/CoreTests/android/core/ByteArrayInputStreamTest.java
@@ -0,0 +1,43 @@
+/*
+ * 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 android.core;
+
+import junit.framework.TestCase;
+
+import java.io.ByteArrayInputStream;
+import android.test.suitebuilder.annotation.SmallTest;
+
+/**
+ * Tests to verify that simple functionality works for ByteArrayInputStreams.
+ */
+public class ByteArrayInputStreamTest extends TestCase {
+
+ @SmallTest
+ public void testByteArrayInputStream() throws Exception {
+ String str = "AbCdEfGhIjKlMnOpQrStUvWxYz";
+
+ ByteArrayInputStream a = new ByteArrayInputStream(str.getBytes());
+ ByteArrayInputStream b = new ByteArrayInputStream(str.getBytes());
+ ByteArrayInputStream c = new ByteArrayInputStream(str.getBytes());
+ ByteArrayInputStream d = new ByteArrayInputStream(str.getBytes());
+
+ assertEquals(str, IOUtil.read(a));
+ assertEquals("AbCdEfGhIj", IOUtil.read(b, 10));
+ assertEquals("bdfhjlnprtvxz", IOUtil.skipRead(c));
+ assertEquals("AbCdEfGdEfGhIjKlMnOpQrStUvWxYz", IOUtil.markRead(d, 3, 4));
+ }
+}
diff --git a/tests/CoreTests/android/core/ByteArrayOutputStreamTest.java b/tests/CoreTests/android/core/ByteArrayOutputStreamTest.java
new file mode 100644
index 0000000..e605214
--- /dev/null
+++ b/tests/CoreTests/android/core/ByteArrayOutputStreamTest.java
@@ -0,0 +1,43 @@
+/*
+ * 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 android.core;
+
+import junit.framework.TestCase;
+
+import java.io.ByteArrayOutputStream;
+import android.test.suitebuilder.annotation.SmallTest;
+
+/**
+ * A basic test for ByteArrayOutputStraem.
+ */
+public class ByteArrayOutputStreamTest extends TestCase {
+
+ @SmallTest
+ public void testByteArrayOutputStream() throws Exception {
+ String str = "AbCdEfGhIjKlMnOpQrStUvWxYz";
+ ByteArrayOutputStream a = new ByteArrayOutputStream();
+ ByteArrayOutputStream b = new ByteArrayOutputStream(10);
+
+ a.write(str.getBytes(), 0, 26);
+ a.write('X');
+ a.writeTo(b);
+
+ assertEquals(27, a.size());
+ assertEquals("AbCdEfGhIjKlMnOpQrStUvWxYzX", a.toString());
+ assertEquals("AbCdEfGhIjKlMnOpQrStUvWxYzX", b.toString());
+ }
+}
diff --git a/tests/CoreTests/android/core/CharArrayReaderTest.java b/tests/CoreTests/android/core/CharArrayReaderTest.java
new file mode 100644
index 0000000..50a217a
--- /dev/null
+++ b/tests/CoreTests/android/core/CharArrayReaderTest.java
@@ -0,0 +1,42 @@
+/*
+ * 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 android.core;
+
+import junit.framework.TestCase;
+
+import java.io.CharArrayReader;
+import android.test.suitebuilder.annotation.SmallTest;
+
+/**
+ * Basic tests for CharArrayReader.
+ */
+public class CharArrayReaderTest extends TestCase {
+
+ @SmallTest
+ public void testCharArrayReader() throws Exception {
+ String str = "AbCdEfGhIjKlMnOpQrStUvWxYz";
+ CharArrayReader a = new CharArrayReader(str.toCharArray());
+ CharArrayReader b = new CharArrayReader(str.toCharArray());
+ CharArrayReader c = new CharArrayReader(str.toCharArray());
+ CharArrayReader d = new CharArrayReader(str.toCharArray());
+
+ assertEquals(str, IOUtil.read(a));
+ assertEquals("AbCdEfGhIj", IOUtil.read(b, 10));
+ assertEquals("bdfhjlnprtvxz", IOUtil.skipRead(c));
+ assertEquals("AbCdEfGdEfGhIjKlMnOpQrStUvWxYz", IOUtil.markRead(d, 3, 4));
+ }
+}
diff --git a/tests/CoreTests/android/core/CharArrayWriterTest.java b/tests/CoreTests/android/core/CharArrayWriterTest.java
new file mode 100644
index 0000000..0aae1e4
--- /dev/null
+++ b/tests/CoreTests/android/core/CharArrayWriterTest.java
@@ -0,0 +1,48 @@
+/*
+ * 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 android.core;
+
+import junit.framework.TestCase;
+
+import java.io.CharArrayWriter;
+import android.test.suitebuilder.annotation.SmallTest;
+
+/**
+ * Basic tests for CharArrayWriter.
+ */
+public class CharArrayWriterTest extends TestCase {
+
+ @SmallTest
+ public void testCharArrayWriter() throws Exception {
+ String str = "AbCdEfGhIjKlMnOpQrStUvWxYz";
+ CharArrayWriter a = new CharArrayWriter();
+ CharArrayWriter b = new CharArrayWriter();
+
+ a.write(str, 0, 26);
+ a.write('X');
+ a.writeTo(b);
+
+ assertEquals(27, a.size());
+ assertEquals("AbCdEfGhIjKlMnOpQrStUvWxYzX", a.toString());
+
+ b.write("alphabravodelta", 5, 5);
+ b.append('X');
+ assertEquals("AbCdEfGhIjKlMnOpQrStUvWxYzXbravoX", b.toString());
+ b.append("omega");
+ assertEquals("AbCdEfGhIjKlMnOpQrStUvWxYzXbravoXomega", b.toString());
+ }
+}
diff --git a/tests/CoreTests/android/core/ChecksumTest.java b/tests/CoreTests/android/core/ChecksumTest.java
new file mode 100644
index 0000000..24fb739
--- /dev/null
+++ b/tests/CoreTests/android/core/ChecksumTest.java
@@ -0,0 +1,97 @@
+/*
+ * 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 android.core;
+
+import junit.framework.TestCase;
+
+import java.util.zip.Adler32;
+import java.util.zip.CRC32;
+import android.test.suitebuilder.annotation.SmallTest;
+
+/**
+ * tests for CRC32 and Adler32 checksum algorithms.
+ */
+public class ChecksumTest extends TestCase {
+
+ @SmallTest
+ public void testChecksum() throws Exception {
+ /*
+ * Values computed experimentally, using C interfaces.
+ */
+ adler32Test(mTestString, 0x9de210dbL);
+ cRC32Test(mTestString, 0x939f04afL);
+
+ // Test for issue 1016037
+ wrongChecksumWithAdler32Test();
+ }
+
+ private void adler32Test(byte[] values, long expected) {
+ Adler32 adler = new Adler32();
+
+ // try it all at once
+ adler.update(values);
+ assertEquals(adler.getValue(), expected);
+
+ // try resetting and computing one byte at a time
+ adler.reset();
+ for (int i = 0; i < values.length; i++) {
+ adler.update(values[i]);
+ }
+ assertEquals(adler.getValue(), expected);
+ }
+
+ private void cRC32Test(byte[] values, long expected) {
+ CRC32 crc = new CRC32();
+
+ // try it all at once
+ crc.update(values);
+ assertEquals(crc.getValue(), expected);
+
+ // try resetting and computing one byte at a time
+ crc.reset();
+ for (int i = 0; i < values.length; i++) {
+ crc.update(values[i]);
+ }
+ assertEquals(crc.getValue(), expected);
+ }
+
+ // "The quick brown fox jumped over the lazy dogs\n"
+ private static byte[] mTestString = {
+ 0x54, 0x68, 0x65, 0x20, 0x71, 0x75, 0x69, 0x63,
+ 0x6b, 0x20, 0x62, 0x72, 0x6f, 0x77, 0x6e, 0x20,
+ 0x66, 0x6f, 0x78, 0x20, 0x6a, 0x75, 0x6d, 0x70,
+ 0x65, 0x64, 0x20, 0x6f, 0x76, 0x65, 0x72, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x6c, 0x61, 0x7a, 0x79,
+ 0x20, 0x64, 0x6f, 0x67, 0x73, 0x2e, 0x0a
+ };
+
+
+ // Test for issue 1016037
+ private void wrongChecksumWithAdler32Test() {
+ byte[] bytes = {1, 0, 5, 0, 15, 0, 1, 11, 0, 1};
+ Adler32 adler = new Adler32();
+ adler.update(bytes);
+ long arrayChecksum = adler.getValue();
+ adler.reset();
+ for (int i = 0; i < bytes.length; i++) {
+ adler.update(bytes[i]);
+ }
+ assertEquals("Checksums not equal: expected: " + arrayChecksum +
+ " actual: " + adler.getValue(), arrayChecksum, adler.getValue());
+ }
+}
+
diff --git a/tests/CoreTests/android/core/ClassLoaderTest.java b/tests/CoreTests/android/core/ClassLoaderTest.java
new file mode 100644
index 0000000..5e7f5a4
--- /dev/null
+++ b/tests/CoreTests/android/core/ClassLoaderTest.java
@@ -0,0 +1,243 @@
+/*
+ * 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 android.core;
+
+import junit.framework.TestCase;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+
+import android.test.suitebuilder.annotation.Suppress;
+
+/**
+ * Test for basic ClassLoader functionality.
+ */
+@Suppress
+public class ClassLoaderTest extends TestCase {
+ /*
+ package my.pkg;
+ public class CLTest {
+ public CLTest() {}
+
+ public String test() { return "This is test 1"; }
+ }
+ */
+ static private byte[] test1class = {
+ (byte) 0xca, (byte) 0xfe, (byte) 0xba, (byte) 0xbe,
+ (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x31,
+ (byte) 0x00, (byte) 0x11, (byte) 0x0a, (byte) 0x00,
+ (byte) 0x04, (byte) 0x00, (byte) 0x0d, (byte) 0x08,
+ (byte) 0x00, (byte) 0x0e, (byte) 0x07, (byte) 0x00,
+ (byte) 0x0f, (byte) 0x07, (byte) 0x00, (byte) 0x10,
+ (byte) 0x01, (byte) 0x00, (byte) 0x06, (byte) 0x3c,
+ (byte) 0x69, (byte) 0x6e, (byte) 0x69, (byte) 0x74,
+ (byte) 0x3e, (byte) 0x01, (byte) 0x00, (byte) 0x03,
+ (byte) 0x28, (byte) 0x29, (byte) 0x56, (byte) 0x01,
+ (byte) 0x00, (byte) 0x04, (byte) 0x43, (byte) 0x6f,
+ (byte) 0x64, (byte) 0x65, (byte) 0x01, (byte) 0x00,
+ (byte) 0x0f, (byte) 0x4c, (byte) 0x69, (byte) 0x6e,
+ (byte) 0x65, (byte) 0x4e, (byte) 0x75, (byte) 0x6d,
+ (byte) 0x62, (byte) 0x65, (byte) 0x72, (byte) 0x54,
+ (byte) 0x61, (byte) 0x62, (byte) 0x6c, (byte) 0x65,
+ (byte) 0x01, (byte) 0x00, (byte) 0x04, (byte) 0x74,
+ (byte) 0x65, (byte) 0x73, (byte) 0x74, (byte) 0x01,
+ (byte) 0x00, (byte) 0x14, (byte) 0x28, (byte) 0x29,
+ (byte) 0x4c, (byte) 0x6a, (byte) 0x61, (byte) 0x76,
+ (byte) 0x61, (byte) 0x2f, (byte) 0x6c, (byte) 0x61,
+ (byte) 0x6e, (byte) 0x67, (byte) 0x2f, (byte) 0x53,
+ (byte) 0x74, (byte) 0x72, (byte) 0x69, (byte) 0x6e,
+ (byte) 0x67, (byte) 0x3b, (byte) 0x01, (byte) 0x00,
+ (byte) 0x0a, (byte) 0x53, (byte) 0x6f, (byte) 0x75,
+ (byte) 0x72, (byte) 0x63, (byte) 0x65, (byte) 0x46,
+ (byte) 0x69, (byte) 0x6c, (byte) 0x65, (byte) 0x01,
+ (byte) 0x00, (byte) 0x0b, (byte) 0x43, (byte) 0x4c,
+ (byte) 0x54, (byte) 0x65, (byte) 0x73, (byte) 0x74,
+ (byte) 0x2e, (byte) 0x6a, (byte) 0x61, (byte) 0x76,
+ (byte) 0x61, (byte) 0x0c, (byte) 0x00, (byte) 0x05,
+ (byte) 0x00, (byte) 0x06, (byte) 0x01, (byte) 0x00,
+ (byte) 0x0e, (byte) 0x54, (byte) 0x68, (byte) 0x69,
+ (byte) 0x73, (byte) 0x20, (byte) 0x69, (byte) 0x73,
+ (byte) 0x20, (byte) 0x74, (byte) 0x65, (byte) 0x73,
+ (byte) 0x74, (byte) 0x20, (byte) 0x31, (byte) 0x01,
+ (byte) 0x00, (byte) 0x0d, (byte) 0x6d, (byte) 0x79,
+ (byte) 0x2f, (byte) 0x70, (byte) 0x6b, (byte) 0x67,
+ (byte) 0x2f, (byte) 0x43, (byte) 0x4c, (byte) 0x54,
+ (byte) 0x65, (byte) 0x73, (byte) 0x74, (byte) 0x01,
+ (byte) 0x00, (byte) 0x10, (byte) 0x6a, (byte) 0x61,
+ (byte) 0x76, (byte) 0x61, (byte) 0x2f, (byte) 0x6c,
+ (byte) 0x61, (byte) 0x6e, (byte) 0x67, (byte) 0x2f,
+ (byte) 0x4f, (byte) 0x62, (byte) 0x6a, (byte) 0x65,
+ (byte) 0x63, (byte) 0x74, (byte) 0x00, (byte) 0x21,
+ (byte) 0x00, (byte) 0x03, (byte) 0x00, (byte) 0x04,
+ (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
+ (byte) 0x00, (byte) 0x02, (byte) 0x00, (byte) 0x01,
+ (byte) 0x00, (byte) 0x05, (byte) 0x00, (byte) 0x06,
+ (byte) 0x00, (byte) 0x01, (byte) 0x00, (byte) 0x07,
+ (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x1d,
+ (byte) 0x00, (byte) 0x01, (byte) 0x00, (byte) 0x01,
+ (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x05,
+ (byte) 0x2a, (byte) 0xb7, (byte) 0x00, (byte) 0x01,
+ (byte) 0xb1, (byte) 0x00, (byte) 0x00, (byte) 0x00,
+ (byte) 0x01, (byte) 0x00, (byte) 0x08, (byte) 0x00,
+ (byte) 0x00, (byte) 0x00, (byte) 0x06, (byte) 0x00,
+ (byte) 0x01, (byte) 0x00, (byte) 0x00, (byte) 0x00,
+ (byte) 0x04, (byte) 0x00, (byte) 0x01, (byte) 0x00,
+ (byte) 0x09, (byte) 0x00, (byte) 0x0a, (byte) 0x00,
+ (byte) 0x01, (byte) 0x00, (byte) 0x07, (byte) 0x00,
+ (byte) 0x00, (byte) 0x00, (byte) 0x1b, (byte) 0x00,
+ (byte) 0x01, (byte) 0x00, (byte) 0x01, (byte) 0x00,
+ (byte) 0x00, (byte) 0x00, (byte) 0x03, (byte) 0x12,
+ (byte) 0x02, (byte) 0xb0, (byte) 0x00, (byte) 0x00,
+ (byte) 0x00, (byte) 0x01, (byte) 0x00, (byte) 0x08,
+ (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x06,
+ (byte) 0x00, (byte) 0x01, (byte) 0x00, (byte) 0x00,
+ (byte) 0x00, (byte) 0x06, (byte) 0x00, (byte) 0x01,
+ (byte) 0x00, (byte) 0x0b, (byte) 0x00, (byte) 0x00,
+ (byte) 0x00, (byte) 0x02, (byte) 0x00, (byte) 0x0c
+ };
+
+ /*
+ package my.pkg;
+ public class CLTest {
+ public CLTest() {}
+
+ public String test() { return "This is test 2"; }
+ }
+ */
+ static private byte[] test2class = {
+ (byte) 0xca, (byte) 0xfe, (byte) 0xba, (byte) 0xbe,
+ (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x31,
+ (byte) 0x00, (byte) 0x11, (byte) 0x0a, (byte) 0x00,
+ (byte) 0x04, (byte) 0x00, (byte) 0x0d, (byte) 0x08,
+ (byte) 0x00, (byte) 0x0e, (byte) 0x07, (byte) 0x00,
+ (byte) 0x0f, (byte) 0x07, (byte) 0x00, (byte) 0x10,
+ (byte) 0x01, (byte) 0x00, (byte) 0x06, (byte) 0x3c,
+ (byte) 0x69, (byte) 0x6e, (byte) 0x69, (byte) 0x74,
+ (byte) 0x3e, (byte) 0x01, (byte) 0x00, (byte) 0x03,
+ (byte) 0x28, (byte) 0x29, (byte) 0x56, (byte) 0x01,
+ (byte) 0x00, (byte) 0x04, (byte) 0x43, (byte) 0x6f,
+ (byte) 0x64, (byte) 0x65, (byte) 0x01, (byte) 0x00,
+ (byte) 0x0f, (byte) 0x4c, (byte) 0x69, (byte) 0x6e,
+ (byte) 0x65, (byte) 0x4e, (byte) 0x75, (byte) 0x6d,
+ (byte) 0x62, (byte) 0x65, (byte) 0x72, (byte) 0x54,
+ (byte) 0x61, (byte) 0x62, (byte) 0x6c, (byte) 0x65,
+ (byte) 0x01, (byte) 0x00, (byte) 0x04, (byte) 0x74,
+ (byte) 0x65, (byte) 0x73, (byte) 0x74, (byte) 0x01,
+ (byte) 0x00, (byte) 0x14, (byte) 0x28, (byte) 0x29,
+ (byte) 0x4c, (byte) 0x6a, (byte) 0x61, (byte) 0x76,
+ (byte) 0x61, (byte) 0x2f, (byte) 0x6c, (byte) 0x61,
+ (byte) 0x6e, (byte) 0x67, (byte) 0x2f, (byte) 0x53,
+ (byte) 0x74, (byte) 0x72, (byte) 0x69, (byte) 0x6e,
+ (byte) 0x67, (byte) 0x3b, (byte) 0x01, (byte) 0x00,
+ (byte) 0x0a, (byte) 0x53, (byte) 0x6f, (byte) 0x75,
+ (byte) 0x72, (byte) 0x63, (byte) 0x65, (byte) 0x46,
+ (byte) 0x69, (byte) 0x6c, (byte) 0x65, (byte) 0x01,
+ (byte) 0x00, (byte) 0x0b, (byte) 0x43, (byte) 0x4c,
+ (byte) 0x54, (byte) 0x65, (byte) 0x73, (byte) 0x74,
+ (byte) 0x2e, (byte) 0x6a, (byte) 0x61, (byte) 0x76,
+ (byte) 0x61, (byte) 0x0c, (byte) 0x00, (byte) 0x05,
+ (byte) 0x00, (byte) 0x06, (byte) 0x01, (byte) 0x00,
+ (byte) 0x0e, (byte) 0x54, (byte) 0x68, (byte) 0x69,
+ (byte) 0x73, (byte) 0x20, (byte) 0x69, (byte) 0x73,
+ (byte) 0x20, (byte) 0x74, (byte) 0x65, (byte) 0x73,
+ (byte) 0x74, (byte) 0x20, (byte) 0x32, (byte) 0x01,
+ (byte) 0x00, (byte) 0x0d, (byte) 0x6d, (byte) 0x79,
+ (byte) 0x2f, (byte) 0x70, (byte) 0x6b, (byte) 0x67,
+ (byte) 0x2f, (byte) 0x43, (byte) 0x4c, (byte) 0x54,
+ (byte) 0x65, (byte) 0x73, (byte) 0x74, (byte) 0x01,
+ (byte) 0x00, (byte) 0x10, (byte) 0x6a, (byte) 0x61,
+ (byte) 0x76, (byte) 0x61, (byte) 0x2f, (byte) 0x6c,
+ (byte) 0x61, (byte) 0x6e, (byte) 0x67, (byte) 0x2f,
+ (byte) 0x4f, (byte) 0x62, (byte) 0x6a, (byte) 0x65,
+ (byte) 0x63, (byte) 0x74, (byte) 0x00, (byte) 0x21,
+ (byte) 0x00, (byte) 0x03, (byte) 0x00, (byte) 0x04,
+ (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
+ (byte) 0x00, (byte) 0x02, (byte) 0x00, (byte) 0x01,
+ (byte) 0x00, (byte) 0x05, (byte) 0x00, (byte) 0x06,
+ (byte) 0x00, (byte) 0x01, (byte) 0x00, (byte) 0x07,
+ (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x1d,
+ (byte) 0x00, (byte) 0x01, (byte) 0x00, (byte) 0x01,
+ (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x05,
+ (byte) 0x2a, (byte) 0xb7, (byte) 0x00, (byte) 0x01,
+ (byte) 0xb1, (byte) 0x00, (byte) 0x00, (byte) 0x00,
+ (byte) 0x01, (byte) 0x00, (byte) 0x08, (byte) 0x00,
+ (byte) 0x00, (byte) 0x00, (byte) 0x06, (byte) 0x00,
+ (byte) 0x01, (byte) 0x00, (byte) 0x00, (byte) 0x00,
+ (byte) 0x04, (byte) 0x00, (byte) 0x01, (byte) 0x00,
+ (byte) 0x09, (byte) 0x00, (byte) 0x0a, (byte) 0x00,
+ (byte) 0x01, (byte) 0x00, (byte) 0x07, (byte) 0x00,
+ (byte) 0x00, (byte) 0x00, (byte) 0x1b, (byte) 0x00,
+ (byte) 0x01, (byte) 0x00, (byte) 0x01, (byte) 0x00,
+ (byte) 0x00, (byte) 0x00, (byte) 0x03, (byte) 0x12,
+ (byte) 0x02, (byte) 0xb0, (byte) 0x00, (byte) 0x00,
+ (byte) 0x00, (byte) 0x01, (byte) 0x00, (byte) 0x08,
+ (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x06,
+ (byte) 0x00, (byte) 0x01, (byte) 0x00, (byte) 0x00,
+ (byte) 0x00, (byte) 0x06, (byte) 0x00, (byte) 0x01,
+ (byte) 0x00, (byte) 0x0b, (byte) 0x00, (byte) 0x00,
+ (byte) 0x00, (byte) 0x02, (byte) 0x00, (byte) 0x0c
+ };
+
+ /*
+ * Custom class loader.
+ */
+ private class MyLoader extends ClassLoader {
+ public MyLoader(byte[] data) {
+ super();
+ mData = data;
+ }
+
+ protected Class<?> findClass(String name) throws ClassNotFoundException {
+ assertEquals("my.pkg.CLTest", name);
+ return defineClass(name, mData, 0, mData.length);
+ }
+
+ byte[] mData;
+ }
+
+
+ /*
+ * Simple test: manually load two class files that have the same class
+ * name but different contents.
+ */
+ public void testClassLoader() throws Exception {
+ Class test1, test2;
+ MyLoader loader1 = new MyLoader(test1class);
+ MyLoader loader2 = new MyLoader(test2class);
+
+ test1 = loader1.loadClass("my.pkg.CLTest");
+ test2 = loader2.loadClass("my.pkg.CLTest");
+
+ methodTest(test1, "This is test 1");
+ methodTest(test2, "This is test 2");
+ }
+
+ /*
+ * Invoke the test() method and verify that the string returned
+ * matches what we expect.
+ */
+ private static void methodTest(Class clazz, String expect)
+ throws NoSuchMethodException, InstantiationException,
+ IllegalAccessException, InvocationTargetException {
+ Method meth = clazz.getMethod("test", (Class[]) null);
+ Object obj = clazz.newInstance();
+ Object result = meth.invoke(obj, (Object[]) null);
+
+ assertEquals(result, expect);
+ }
+}
+
diff --git a/tests/CoreTests/android/core/ClassTest.java b/tests/CoreTests/android/core/ClassTest.java
new file mode 100644
index 0000000..cc1b4ca
--- /dev/null
+++ b/tests/CoreTests/android/core/ClassTest.java
@@ -0,0 +1,337 @@
+/*
+ * 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 android.core;
+
+import android.test.suitebuilder.annotation.MediumTest;
+import android.test.suitebuilder.annotation.SmallTest;
+import android.widget.Button;
+import junit.framework.TestCase;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.util.HashSet;
+import java.util.Set;
+
+
+class ClassWithPrivateConstructor {
+ private ClassWithPrivateConstructor() {
+ }
+}
+
+public class ClassTest extends TestCase {
+
+ @SmallTest
+ public void testClass() throws Exception {
+ // Now, never mind the fact that most of this stuff has to work
+ // for the test harness to get this far....
+
+ //System.out.println("Class.forName()");
+ Class helloClass = Class.forName(ClassTest.class.getName());
+
+ //System.out.println("Class.newInstance()");
+ Object instance = helloClass.newInstance();
+ assertNotNull(instance);
+
+ //System.out.println("Class.forName() nonexisting class");
+ try {
+ Class.forName("this.class.DoesNotExist");
+ fail("unexpected success");
+ } catch (ClassNotFoundException ex) {
+ // expected
+ }
+
+ //System.out.println("Class.newInstance() private constructor");
+ try {
+ Class.forName("android.core.ClassWithPrivateConstructor").newInstance();
+ fail("unexpected success");
+ } catch (IllegalAccessException ex) {
+ // this is expected
+ }
+
+ //System.out.println("Class.getDeclaredMethod()");
+
+ Method method = helloClass.getDeclaredMethod("method", (Class[]) null);
+
+ method.invoke(new ClassTest(), (Object[]) null);
+
+ //System.out.println("Class.getDeclaredMethod() w/ args");
+
+ method = helloClass.getDeclaredMethod("methodWithArgs", Object.class);
+
+ Object invokeArgs[] = new Object[1];
+ invokeArgs[0] = "Hello";
+ Object ret = method.invoke(new ClassTest(), invokeArgs);
+ assertEquals(ret, invokeArgs[0]);
+
+ //System.out.println("Class.getDeclaredMethod() -- private");
+
+ method = helloClass.getDeclaredMethod("privateMethod", (Class[]) null);
+
+ method.invoke(new ClassTest(), (Object[]) null);
+ //fail("unexpected success");
+ // TODO: I think this actually *should* succeed, because the
+ // call to the private method is being made from the same class.
+ // This needs to be replaced with a private call to a different
+ // class.
+
+ //System.out.println("Class.getSuperclass");
+ Class objectClass = Class.forName("java.lang.Object");
+ assertEquals(helloClass.getSuperclass().getSuperclass().getSuperclass(), objectClass);
+
+ //System.out.println("Class.isAssignableFrom");
+ assertTrue(objectClass.isAssignableFrom(helloClass));
+ assertFalse(helloClass.isAssignableFrom(objectClass));
+
+ //System.out.println("Class.getConstructor");
+
+ Constructor constructor = helloClass.getConstructor((Class[]) null);
+ assertNotNull(constructor);
+
+ //System.out.println("Class.getModifiers");
+
+ assertTrue(Modifier.isPublic(helloClass.getModifiers()));
+ //System.out.println("Modifiers: " + Modifier.toString(helloClass.getModifiers()));
+
+ //System.out.println("Class.getMethod");
+
+ helloClass.getMethod("method", (Class[]) null);
+
+ try {
+ Class[] argTypes = new Class[1];
+ argTypes[0] = helloClass;
+ helloClass.getMethod("method", argTypes);
+ fail("unexpected success");
+ } catch (NoSuchMethodException ex) {
+ // exception expected
+ }
+
+ // Test for public tracker issue 14
+ SimpleClass obj = new SimpleClass();
+ Field field = obj.getClass().getDeclaredField("str");
+ field.set(obj, null);
+ }
+
+ public class SimpleClass {
+ public String str;
+ }
+
+ public Object methodWithArgs(Object o) {
+ return o;
+ }
+
+ boolean methodInvoked;
+
+ public void method() {
+ methodInvoked = true;
+ }
+
+ boolean privateMethodInvoked;
+
+ public void privateMethod() {
+ privateMethodInvoked = true;
+ }
+
+ // Regression for 1018067: Class.getMethods() returns the same method over
+ // and over again from all base classes
+ @MediumTest
+ public void testClassGetMethodsNoDupes() {
+ Method[] methods = Button.class.getMethods();
+ Set<String> set = new HashSet<String>();
+
+ for (int i = 0; i < methods.length; i++) {
+ String signature = methods[i].toString();
+
+ int par = signature.indexOf('(');
+ int dot = signature.lastIndexOf('.', par);
+
+ signature = signature.substring(dot + 1);
+
+ assertFalse("Duplicate " + signature, set.contains(signature));
+ set.add(signature);
+ }
+ }
+
+ interface MyInterface {
+ void foo();
+ }
+
+ interface MyOtherInterface extends MyInterface {
+ void bar();
+ }
+
+ abstract class MyClass implements MyOtherInterface {
+ public void gabba() {
+ }
+
+ public void hey() {
+ }
+ }
+
+ // Check if we also reflect methods from interfaces
+ @SmallTest
+ public void testGetMethodsInterfaces() {
+ Method[] methods = MyInterface.class.getMethods();
+ assertTrue("Interface method must be there", hasMethod(methods, ".foo("));
+
+ methods = MyOtherInterface.class.getMethods();
+ assertTrue("Interface method must be there", hasMethod(methods, ".foo("));
+ assertTrue("Interface method must be there", hasMethod(methods, ".bar("));
+
+ methods = MyClass.class.getMethods();
+ assertTrue("Interface method must be there", hasMethod(methods, ".foo("));
+ assertTrue("Interface method must be there", hasMethod(methods, ".bar("));
+
+ assertTrue("Declared method must be there", hasMethod(methods, ".gabba("));
+ assertTrue("Declared method must be there", hasMethod(methods, ".hey("));
+
+ assertTrue("Inherited method must be there", hasMethod(methods, ".toString("));
+ }
+
+ private boolean hasMethod(Method[] methods, String signature) {
+ for (int i = 0; i < methods.length; i++) {
+ if (methods[i].toString().contains(signature)) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ // Test for Class.getPackage();
+ @SmallTest
+ public void testClassGetPackage() {
+ assertNotNull("Package must be non-null", getClass().getPackage());
+ assertEquals("Package must have expected name", "android.core", getClass().getPackage().getName());
+ assertEquals("Package must have expected title", "Unknown", getClass().getPackage().getSpecificationTitle());
+
+ Package p = java.lang.Object.class.getPackage();
+ assertNotNull("Package must be non-null", p);
+ assertEquals("Package must have expected name", "java.lang", p.getName());
+ assertSame("Package object must be same for each call", p, java.lang.Object.class.getPackage());
+ }
+
+ // Regression test for #1123708: Problem with getCanonicalName(),
+ // getSimpleName(), and getPackage().
+ //
+ // A couple of interesting cases need to be checked: Top-level classes,
+ // member classes, local classes, and anonymous classes. Also, boundary
+ // cases with '$' in the class names are checked, since the '$' is used
+ // as the separator between outer and inner class, so this might lead
+ // to problems (it did in the previous implementation).
+ //
+ // Caution: Adding local or anonymous classes elsewhere in this
+ // file might affect the test.
+ private class MemberClass {
+ // This space intentionally left blank.
+ }
+
+ private class Mi$o$oup {
+ // This space intentionally left blank.
+ }
+
+ @SmallTest
+ public void testVariousClassNames() {
+ Class<?> clazz = this.getClass();
+ String pkg = (clazz.getPackage() == null ? "" : clazz.getPackage().getName() + ".");
+
+ // Simple, top-level class
+
+ assertEquals("Top-level class name must be correct", pkg + "ClassTest", clazz.getName());
+ assertEquals("Top-level class simple name must be correct", "ClassTest", clazz.getSimpleName());
+ assertEquals("Top-level class canonical name must be correct", pkg + "ClassTest", clazz.getCanonicalName());
+
+ clazz = MemberClass.class;
+
+ assertEquals("Member class name must be correct", pkg + "ClassTest$MemberClass", clazz.getName());
+ assertEquals("Member class simple name must be correct", "MemberClass", clazz.getSimpleName());
+ assertEquals("Member class canonical name must be correct", pkg + "ClassTest.MemberClass", clazz.getCanonicalName());
+
+ class LocalClass {
+ // This space intentionally left blank.
+ }
+
+ clazz = LocalClass.class;
+
+ assertEquals("Local class name must be correct", pkg + "ClassTest$1LocalClass", clazz.getName());
+ assertEquals("Local class simple name must be correct", "LocalClass", clazz.getSimpleName());
+ assertNull("Local class canonical name must be null", clazz.getCanonicalName());
+
+ clazz = new Object() { }.getClass();
+
+ assertEquals("Anonymous class name must be correct", pkg + "ClassTest$1", clazz.getName());
+ assertEquals("Anonymous class simple name must be empty", "", clazz.getSimpleName());
+ assertNull("Anonymous class canonical name must be null", clazz.getCanonicalName());
+
+ // Weird special cases with dollar in name.
+
+ clazz = Mou$$aka.class;
+
+ assertEquals("Top-level class name must be correct", pkg + "Mou$$aka", clazz.getName());
+ assertEquals("Top-level class simple name must be correct", "Mou$$aka", clazz.getSimpleName());
+ assertEquals("Top-level class canonical name must be correct", pkg + "Mou$$aka", clazz.getCanonicalName());
+
+ clazz = Mi$o$oup.class;
+
+ assertEquals("Member class name must be correct", pkg + "ClassTest$Mi$o$oup", clazz.getName());
+ assertEquals("Member class simple name must be correct", "Mi$o$oup", clazz.getSimpleName());
+ assertEquals("Member class canonical name must be correct", pkg + "ClassTest.Mi$o$oup", clazz.getCanonicalName());
+
+ class Ma$hedPotatoe$ {
+ // This space intentionally left blank.
+ }
+
+ clazz = Ma$hedPotatoe$.class;
+
+ assertEquals("Member class name must be correct", pkg + "ClassTest$1Ma$hedPotatoe$", clazz.getName());
+ assertEquals("Member class simple name must be correct", "Ma$hedPotatoe$", clazz.getSimpleName());
+ assertNull("Member class canonical name must be null", clazz.getCanonicalName());
+ }
+
+ @SmallTest
+ public void testLocalMemberClass() {
+ Class<?> clazz = this.getClass();
+
+ assertFalse("Class must not be member", clazz.isMemberClass());
+ assertFalse("Class must not be local", clazz.isLocalClass());
+
+ clazz = MemberClass.class;
+
+ assertTrue("Class must be member", clazz.isMemberClass());
+ assertFalse("Class must not be local", clazz.isLocalClass());
+
+ class OtherLocalClass {
+ // This space intentionally left blank.
+ }
+
+ clazz = OtherLocalClass.class;
+
+ assertFalse("Class must not be member", clazz.isMemberClass());
+ assertTrue("Class must be local", clazz.isLocalClass());
+
+ clazz = new Object() { }.getClass();
+
+ assertFalse("Class must not be member", clazz.isMemberClass());
+ assertFalse("Class must not be local", clazz.isLocalClass());
+ }
+
+}
+
+class Mou$$aka {
+ // This space intentionally left blank.
+}
diff --git a/tests/CoreTests/android/core/CoreTests.java b/tests/CoreTests/android/core/CoreTests.java
new file mode 100644
index 0000000..e4f835c
--- /dev/null
+++ b/tests/CoreTests/android/core/CoreTests.java
@@ -0,0 +1,66 @@
+/*
+ * 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 android.core;
+
+import com.android.internal.telephony.TelephonyTests;
+
+import junit.framework.TestSuite;
+
+import android.graphics.ColorStateListTest;
+import android.location.LocationManagerProximityTest;
+import android.location.LocationTest;
+import android.test.AndroidTestRunnerTest;
+import android.test.InstrumentationTestRunnerTest;
+import android.util.*;
+import android.view.FocusFinderTest;
+import android.view.ViewGroupAttributesTest;
+import android.webkit.*;
+
+public class CoreTests extends TestSuite {
+
+ /**
+ * To run these tests:
+ * $ mmm java/tests && adb sync
+ * $ adb shell am instrument -w \
+ * -e class android.core.CoreTests \
+ * android.core/android.test.InstrumentationTestRunner
+ */
+ public static TestSuite suite() {
+ TestSuite suite = new TestSuite(CoreTests.class.getName());
+
+ // Re-enable StateListDrawableTest when we are running in the
+ // framework-test directory which allows access to package private
+ // access for MockView
+ // suite.addTestSuite(StateListDrawableTest.class);
+ suite.addTestSuite(DayOfMonthCursorTest.class);
+ suite.addTestSuite(MonthDisplayHelperTest.class);
+ suite.addTestSuite(StateSetTest.class);
+ suite.addTestSuite(ColorStateListTest.class);
+ suite.addTestSuite(FocusFinderTest.class);
+ suite.addTestSuite(ViewGroupAttributesTest.class);
+ suite.addTest(TelephonyTests.suite());
+ suite.addTestSuite(FloatMathTest.class);
+ suite.addTest(JavaTests.suite());
+ suite.addTestSuite(LocationTest.class);
+ suite.addTestSuite(LocationManagerProximityTest.class);
+ suite.addTestSuite(AndroidTestRunnerTest.class);
+ suite.addTestSuite(InstrumentationTestRunnerTest.class);
+ suite.addTestSuite(CookieTest.class);
+
+ return suite;
+ }
+}
diff --git a/tests/CoreTests/android/core/CryptoTest.java b/tests/CoreTests/android/core/CryptoTest.java
new file mode 100644
index 0000000..f00d49f
--- /dev/null
+++ b/tests/CoreTests/android/core/CryptoTest.java
@@ -0,0 +1,137 @@
+/*
+ * 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 android.core;
+
+import junit.framework.Assert;
+import junit.framework.TestCase;
+
+import org.apache.harmony.xnet.provider.jsse.OpenSSLMessageDigest;
+import org.bouncycastle.crypto.Digest;
+import org.bouncycastle.crypto.ExtendedDigest;
+import org.bouncycastle.crypto.digests.MD2Digest;
+import org.bouncycastle.crypto.digests.MD4Digest;
+import org.bouncycastle.crypto.digests.MD5Digest;
+import org.bouncycastle.crypto.digests.SHA1Digest;
+import android.test.suitebuilder.annotation.LargeTest;
+import android.test.suitebuilder.annotation.MediumTest;
+
+/**
+ * Implements unit tests for our JNI wrapper around OpenSSL. We use the
+ * existing Bouncy Castle implementation as our test oracle.
+ */
+public class CryptoTest extends TestCase {
+
+ /**
+ * Processes the two given message digests for the same data and checks
+ * the results. Requirement is that the results must be equal, the digest
+ * implementations must have the same properties, and the new implementation
+ * must be faster than the old one.
+ *
+ * @param oldDigest The old digest implementation, provided by Bouncy Castle
+ * @param newDigest The new digest implementation, provided by OpenSSL
+ */
+ public void doTestMessageDigest(Digest oldDigest, Digest newDigest) {
+ final int ITERATIONS = 10;
+
+ byte[] data = new byte[1024];
+
+ byte[] oldHash = new byte[oldDigest.getDigestSize()];
+ byte[] newHash = new byte[newDigest.getDigestSize()];
+
+ Assert.assertEquals("Hash names must be equal", oldDigest.getAlgorithmName(), newDigest.getAlgorithmName());
+ Assert.assertEquals("Hash sizes must be equal", oldHash.length, newHash.length);
+ Assert.assertEquals("Hash block sizes must be equal", ((ExtendedDigest)oldDigest).getByteLength(), ((ExtendedDigest)newDigest).getByteLength());
+ for (int i = 0; i < data.length; i++) {
+ data[i] = (byte)i;
+ }
+
+ long oldTime = 0;
+ long newTime = 0;
+
+ for (int j = 0; j < ITERATIONS; j++) {
+ long t0 = System.currentTimeMillis();
+ for (int i = 0; i < 4; i++) {
+ oldDigest.update(data, 0, data.length);
+ }
+ int oldLength = oldDigest.doFinal(oldHash, 0);
+ long t1 = System.currentTimeMillis();
+
+ oldTime = oldTime + (t1 - t0);
+
+ long t2 = System.currentTimeMillis();
+ for (int i = 0; i < 4; i++) {
+ newDigest.update(data, 0, data.length);
+ }
+ int newLength = newDigest.doFinal(newHash, 0);
+ long t3 = System.currentTimeMillis();
+
+ newTime = newTime + (t3 - t2);
+
+ Assert.assertEquals("Hash sizes must be equal", oldLength, newLength);
+
+ for (int i = 0; i < oldLength; i++) {
+ Assert.assertEquals("Hashes[" + i + "] must be equal", oldHash[i], newHash[i]);
+ }
+ }
+
+ android.util.Log.d("CryptoTest", "Time for " + ITERATIONS + " x old hash processing: " + oldTime + " ms");
+ android.util.Log.d("CryptoTest", "Time for " + ITERATIONS + " x new hash processing: " + newTime + " ms");
+
+ // Assert.assertTrue("New hash should be faster", newTime < oldTime);
+ }
+
+ /**
+ * Tests the MD2 implementation.
+ */
+ @LargeTest
+ public void testMD2() {
+ Digest oldDigest = new MD2Digest();
+ Digest newDigest = OpenSSLMessageDigest.getInstance("MD2");
+ doTestMessageDigest(oldDigest, newDigest);
+ }
+
+ /**
+ * Tests the MD4 implementation.
+ */
+ @MediumTest
+ public void testMD4() {
+ Digest oldDigest = new MD4Digest();
+ Digest newDigest = OpenSSLMessageDigest.getInstance("MD4");
+ doTestMessageDigest(oldDigest, newDigest);
+ }
+
+ /**
+ * Tests the MD5 implementation.
+ */
+ @MediumTest
+ public void testMD5() {
+ Digest oldDigest = new MD5Digest();
+ Digest newDigest = OpenSSLMessageDigest.getInstance("MD5");
+ doTestMessageDigest(oldDigest, newDigest);
+ }
+
+ /**
+ * Tests the SHA-1 implementation.
+ */
+ @MediumTest
+ public void testSHA1() {
+ Digest oldDigest = new SHA1Digest();
+ Digest newDigest = OpenSSLMessageDigest.getInstance("SHA-1");
+ doTestMessageDigest(oldDigest, newDigest);
+ }
+
+}
diff --git a/tests/CoreTests/android/core/DataInputStreamTest.java b/tests/CoreTests/android/core/DataInputStreamTest.java
new file mode 100644
index 0000000..ca801d6
--- /dev/null
+++ b/tests/CoreTests/android/core/DataInputStreamTest.java
@@ -0,0 +1,107 @@
+/*
+ * 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 android.core;
+
+import junit.framework.TestCase;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import android.test.suitebuilder.annotation.SmallTest;
+
+public class DataInputStreamTest extends TestCase {
+
+ @SmallTest
+ public void testDataInputStream() throws Exception {
+ String str = "AbCdEfGhIjKlM\nOpQ\rStUvWxYz";
+ ByteArrayInputStream aa = new ByteArrayInputStream(str.getBytes());
+ ByteArrayInputStream ba = new ByteArrayInputStream(str.getBytes());
+ ByteArrayInputStream ca = new ByteArrayInputStream(str.getBytes());
+ ByteArrayInputStream da = new ByteArrayInputStream(str.getBytes());
+
+ DataInputStream a = new DataInputStream(aa);
+ try {
+ assertEquals(str, IOUtil.read(a));
+ } finally {
+ a.close();
+ }
+
+ DataInputStream b = new DataInputStream(ba);
+ try {
+ assertEquals("AbCdEfGhIj", IOUtil.read(b, 10));
+ } finally {
+ b.close();
+ }
+
+ DataInputStream c = new DataInputStream(ca);
+ try {
+ assertEquals("bdfhjl\np\rtvxz", IOUtil.skipRead(c));
+ } finally {
+ c.close();
+ }
+
+ DataInputStream d = new DataInputStream(da);
+ try {
+ assertEquals("AbCdEfGhIjKlM", d.readLine());
+ assertEquals("OpQ", d.readLine());
+ assertEquals("StUvWxYz", d.readLine());
+ } finally {
+ d.close();
+ }
+
+ ByteArrayOutputStream e = new ByteArrayOutputStream();
+ DataOutputStream f = new DataOutputStream(e);
+ try {
+ f.writeBoolean(true);
+ f.writeByte('a');
+ f.writeBytes("BCD");
+ f.writeChar('e');
+ f.writeChars("FGH");
+ f.writeUTF("ijklm");
+ f.writeDouble(1);
+ f.writeFloat(2);
+ f.writeInt(3);
+ f.writeLong(4);
+ f.writeShort(5);
+ } finally {
+ f.close();
+ }
+
+ ByteArrayInputStream ga = new ByteArrayInputStream(e.toByteArray());
+ DataInputStream g = new DataInputStream(ga);
+
+ try {
+ assertTrue(g.readBoolean());
+ assertEquals('a', g.readByte());
+ assertEquals(2, g.skipBytes(2));
+ assertEquals('D', g.readByte());
+ assertEquals('e', g.readChar());
+ assertEquals('F', g.readChar());
+ assertEquals('G', g.readChar());
+ assertEquals('H', g.readChar());
+ assertEquals("ijklm", g.readUTF());
+ assertEquals(1, g.readDouble(), 0);
+ assertEquals(2f, g.readFloat(), 0f);
+ assertEquals(3, g.readInt());
+ assertEquals(4, g.readLong());
+ assertEquals(5, g.readShort());
+ } finally {
+ g.close();
+ }
+ }
+}
diff --git a/tests/CoreTests/android/core/DataOutputStreamTest.java b/tests/CoreTests/android/core/DataOutputStreamTest.java
new file mode 100644
index 0000000..95502b3
--- /dev/null
+++ b/tests/CoreTests/android/core/DataOutputStreamTest.java
@@ -0,0 +1,51 @@
+/*
+ * 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 android.core;
+
+import junit.framework.TestCase;
+
+import java.io.ByteArrayOutputStream;
+import java.io.DataOutputStream;
+import android.test.suitebuilder.annotation.SmallTest;
+
+/**
+ * Basic tests for DataOutputStreams.
+ */
+public class DataOutputStreamTest extends TestCase {
+
+ @SmallTest
+ public void testDataOutputStream() throws Exception {
+ String str = "AbCdEfGhIjKlMnOpQrStUvWxYz";
+ ByteArrayOutputStream aa = new ByteArrayOutputStream();
+ DataOutputStream a = new DataOutputStream(aa);
+
+ try {
+ a.write(str.getBytes(), 0, 26);
+ a.write('A');
+
+ assertEquals(27, aa.size());
+ assertEquals("AbCdEfGhIjKlMnOpQrStUvWxYzA", aa.toString());
+
+ a.writeByte('B');
+ assertEquals("AbCdEfGhIjKlMnOpQrStUvWxYzAB", aa.toString());
+ a.writeBytes("BYTES");
+ assertEquals("AbCdEfGhIjKlMnOpQrStUvWxYzABBYTES", aa.toString());
+ } finally {
+ a.close();
+ }
+ }
+}
diff --git a/tests/CoreTests/android/core/DatabaseSessionCache.java b/tests/CoreTests/android/core/DatabaseSessionCache.java
new file mode 100644
index 0000000..c344d9c
--- /dev/null
+++ b/tests/CoreTests/android/core/DatabaseSessionCache.java
@@ -0,0 +1,312 @@
+// Copyright 2009 The Android Open Source Project
+
+package android.core;
+
+import android.database.Cursor;
+import android.database.SQLException;
+import android.database.sqlite.SQLiteDatabase;
+import android.database.sqlite.SQLiteOpenHelper;
+import android.util.Log;
+import android.content.ContentValues;
+import android.content.Context;
+
+import org.apache.commons.codec.binary.Base64;
+import org.apache.harmony.xnet.provider.jsse.SSLClientSessionCache;
+
+import java.util.LinkedHashMap;
+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 DatabaseSessionCache implements SSLClientSessionCache {
+ private static final String TAG = "SslSessionCache";
+ static DatabaseHelper sDefaultDatabaseHelper;
+
+ private DatabaseHelper mDatabaseHelper;
+
+ /**
+ * 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 = 1;
+
+ /** 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;
+
+ private static final String SAVE_ON_ADD = "save_on_add";
+
+ static boolean sHookInitializationDone = false;
+
+ public static final int MAX_CACHE_SIZE = 256;
+
+ private static final Map<String, byte[]> mExternalCache =
+ new LinkedHashMap<String, byte[]>(MAX_CACHE_SIZE, 0.75f, true) {
+ @Override
+ public boolean removeEldestEntry(
+ Map.Entry<String, byte[]> eldest) {
+ boolean shouldDelete = this.size() > MAX_CACHE_SIZE;
+
+ // TODO: delete from DB
+ return shouldDelete;
+ }
+ };
+ static boolean mNeedsCacheLoad = true;
+
+ public static final String[] PROJECTION = new String[] {
+ SSL_CACHE_ID,
+ SSL_CACHE_HOSTPORT,
+ SSL_CACHE_SESSION,
+ SSL_CACHE_TIME_SEC
+ };
+
+ /**
+ * This class needs to be installed as a hook, if the security property
+ * is set. Getting the right classloader may be fun since we don't use
+ * Provider to get its classloader, but in android this is in same
+ * loader with AndroidHttpClient.
+ *
+ * This constructor will use the default database. You must
+ * call init() before to specify the context used for the database and
+ * check settings.
+ */
+ public DatabaseSessionCache() {
+ Log.v(TAG, "Instance created.");
+ // May be null if caching is disabled - no sessions will be persisted.
+ this.mDatabaseHelper = sDefaultDatabaseHelper;
+ }
+
+ /**
+ * Create a SslSessionCache instance, using the specified context to
+ * initialize the database.
+ *
+ * This constructor will use the default database - created the first
+ * time.
+ *
+ * @param activityContext
+ */
+ public DatabaseSessionCache(Context activityContext) {
+ // Static init - only one initialization will happen.
+ // Each SslSessionCache is using the same DB.
+ init(activityContext);
+ // May be null if caching is disabled - no sessions will be persisted.
+ this.mDatabaseHelper = sDefaultDatabaseHelper;
+ }
+
+ /**
+ * Create a SslSessionCache that uses a specific database.
+ *
+ * @param database
+ */
+ public DatabaseSessionCache(DatabaseHelper database) {
+ this.mDatabaseHelper = database;
+ }
+
+// public static boolean enabled(Context androidContext) {
+// String sslCache = Settings.Gservices.getString(androidContext.getContentResolver(),
+// Settings.Gservices.SSL_SESSION_CACHE);
+//
+// if (Log.isLoggable(TAG, Log.DEBUG)) {
+// Log.d(TAG, "enabled " + sslCache + " " + androidContext.getPackageName());
+// }
+//
+// return SAVE_ON_ADD.equals(sslCache);
+// }
+
+ /**
+ * You must call this method to enable SSL session caching for an app.
+ */
+ public synchronized static void init(Context activityContext) {
+ // It is possible that multiple provider will try to install this hook.
+ // We want a single db per VM.
+ if (sHookInitializationDone) {
+ return;
+ }
+
+
+// // More values can be added in future to provide different
+// // behaviours, like 'batch save'.
+// if (enabled(activityContext)) {
+ Context appContext = activityContext.getApplicationContext();
+ sDefaultDatabaseHelper = new DatabaseHelper(appContext);
+
+ // Set default SSLSocketFactory
+ // The property is defined in the javadocs for javax.net.SSLSocketFactory
+ // (no constant defined there)
+ // This should cover all code using SSLSocketFactory.getDefault(),
+ // including native http client and apache httpclient.
+ // MCS is using its own custom factory - will need special code.
+// Security.setProperty("ssl.SocketFactory.provider",
+// SslSocketFactoryWithCache.class.getName());
+// }
+
+ // Won't try again.
+ sHookInitializationDone = true;
+ }
+
+ public void putSessionData(SSLSession session, byte[] der) {
+ if (mDatabaseHelper == null) {
+ return;
+ }
+ if (mExternalCache.size() > MAX_CACHE_SIZE) {
+ // remove oldest.
+ Cursor byTime = mDatabaseHelper.getWritableDatabase().query(SSL_CACHE_TABLE,
+ PROJECTION, null, null, null, null, SSL_CACHE_TIME_SEC);
+ byTime.moveToFirst();
+ // TODO: can I do byTime.deleteRow() ?
+ String hostPort = byTime.getString(SSL_CACHE_HOSTPORT_COL);
+
+ mDatabaseHelper.getWritableDatabase().delete(SSL_CACHE_TABLE,
+ SSL_CACHE_HOSTPORT + "= ?" , new String[] { hostPort });
+ }
+ // 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);
+
+ synchronized (this.getClass()) {
+ mExternalCache.put(key, der);
+
+ try {
+ mDatabaseHelper.getWritableDatabase().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);
+ }
+ }
+
+ public byte[] getSessionData(byte[] id) {
+ // We support client side only - the cache will do nothing on client.
+ 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" +
+ ");");
+ db.execSQL("CREATE INDEX ssl_sessions_idx1 ON ssl_sessions (" +
+ SSL_CACHE_HOSTPORT + ");");
+ }
+
+ @Override
+ public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
+ db.execSQL("DROP TABLE IF EXISTS " + SSL_CACHE_TABLE );
+ onCreate(db);
+ }
+
+ }
+
+} \ No newline at end of file
diff --git a/tests/CoreTests/android/core/DatagramTest.java b/tests/CoreTests/android/core/DatagramTest.java
new file mode 100644
index 0000000..355a267
--- /dev/null
+++ b/tests/CoreTests/android/core/DatagramTest.java
@@ -0,0 +1,192 @@
+/*
+ * 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 android.core;
+
+import junit.framework.TestCase;
+
+import java.io.IOException;
+import java.net.DatagramPacket;
+import java.net.DatagramSocket;
+import java.net.InetAddress;
+import java.net.SocketTimeoutException;
+import android.test.suitebuilder.annotation.LargeTest;
+
+/**
+ * Implements some simple tests for datagrams. Not as excessive as the core
+ * tests, but good enough for the harness.
+ */
+public class DatagramTest extends TestCase {
+
+ /**
+ * Helper class that listens to incoming datagrams and reflects them to the
+ * sender. Incoming datagram is interpreted as a String. It is uppercased
+ * before being sent back.
+ */
+
+ class Reflector extends Thread {
+ // Helper class for reflecting incoming datagrams.
+ DatagramSocket socket;
+
+ boolean alive = true;
+
+ byte[] buffer = new byte[256];
+
+ DatagramPacket packet;
+
+ /**
+ * Main loop. Receives datagrams and reflects them.
+ */
+ @Override
+ public void run() {
+ try {
+ while (alive) {
+ try {
+ packet.setLength(buffer.length);
+ socket.receive(packet);
+ String s = stringFromPacket(packet);
+ // System.out.println(s + " (from " + packet.getAddress() + ":" + packet.getPort() + ")");
+
+ try {
+ Thread.sleep(100);
+ } catch (InterruptedException ex) {
+ // Ignore.
+ }
+
+ stringToPacket(s.toUpperCase(), packet);
+
+ packet.setAddress(InetAddress.getLocalHost());
+ packet.setPort(2345);
+
+ socket.send(packet);
+ } catch (java.io.InterruptedIOException e) {
+ }
+ }
+ } catch (java.io.IOException ex) {
+ ex.printStackTrace();
+ } finally {
+ socket.close();
+ }
+ }
+
+ /**
+ * Creates a new Relfector object for the given local address and port.
+ */
+ public Reflector(int port, InetAddress address) {
+ try {
+ packet = new DatagramPacket(buffer, buffer.length);
+ socket = new DatagramSocket(port, address);
+ } catch (IOException ex) {
+ throw new RuntimeException(
+ "Creating datagram reflector failed", ex);
+ }
+ }
+ }
+
+ /**
+ * Converts a given datagram packet's contents to a String.
+ */
+ static String stringFromPacket(DatagramPacket packet) {
+ return new String(packet.getData(), 0, packet.getLength());
+ }
+
+ /**
+ * Converts a given String into a datagram packet.
+ */
+ static void stringToPacket(String s, DatagramPacket packet) {
+ byte[] bytes = s.getBytes();
+ System.arraycopy(bytes, 0, packet.getData(), 0, bytes.length);
+ packet.setLength(bytes.length);
+ }
+
+ /**
+ * Implements the main part of the Datagram test.
+ */
+ @LargeTest
+ public void testDatagram() throws Exception {
+
+ Reflector reflector = null;
+ DatagramSocket socket = null;
+
+ try {
+ // Setup the reflector, so we have a partner to send to
+ reflector = new Reflector(1234, InetAddress.getLocalHost());
+ reflector.start();
+
+ byte[] buffer = new byte[256];
+
+ DatagramPacket packet = new DatagramPacket(buffer, buffer.length);
+ socket = new DatagramSocket(2345, InetAddress.getLocalHost());
+
+ // Send ten simple packets and check for the expected responses.
+ for (int i = 1; i <= 10; i++) {
+ String s = "Hello, Android world #" + i + "!";
+ stringToPacket(s, packet);
+
+ packet.setAddress(InetAddress.getLocalHost());
+ packet.setPort(1234);
+
+ socket.send(packet);
+
+ try {
+ Thread.sleep(100);
+ } catch (InterruptedException ex) {
+ // Ignore.
+ }
+
+ packet.setLength(buffer.length);
+ socket.receive(packet);
+ String t = stringFromPacket(packet);
+ // System.out.println(t + " (from " + packet.getAddress() + ":" + packet.getPort() + ")");
+
+ assertEquals(s.toUpperCase(), t);
+ }
+ } finally {
+ if (reflector != null) {
+ reflector.alive = false;
+ }
+
+ if (socket != null) {
+ socket.close();
+ }
+ }
+ }
+
+ // Regression test for issue 1018003: DatagramSocket ignored a set timeout.
+ @LargeTest
+ public void testDatagramSocketSetSOTimeout() throws Exception {
+ DatagramSocket sock = null;
+ int timeout = 5000;
+ long start = System.currentTimeMillis();
+ try {
+ sock = new DatagramSocket();
+ DatagramPacket pack = new DatagramPacket(new byte[100], 100);
+ sock.setSoTimeout(timeout);
+ sock.receive(pack);
+ } catch (SocketTimeoutException e) {
+ // expected
+ long delay = System.currentTimeMillis() - start;
+ if (Math.abs(delay - timeout) > 1000) {
+ fail("timeout was not accurate. expected: " + timeout
+ + " actual: " + delay + " miliseconds.");
+ }
+ } finally {
+ if (sock != null) {
+ sock.close();
+ }
+ }
+ }
+}
diff --git a/tests/CoreTests/android/core/DeflateTest.java b/tests/CoreTests/android/core/DeflateTest.java
new file mode 100644
index 0000000..d68d697
--- /dev/null
+++ b/tests/CoreTests/android/core/DeflateTest.java
@@ -0,0 +1,199 @@
+/*
+ * 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 android.core;
+
+import junit.framework.TestCase;
+
+import java.io.UnsupportedEncodingException;
+import java.util.zip.DataFormatException;
+import java.util.zip.Deflater;
+import java.util.zip.Inflater;
+import android.test.suitebuilder.annotation.LargeTest;
+
+public class DeflateTest extends TestCase {
+
+ @LargeTest
+ public void testDeflate() throws Exception {
+ simpleTest();
+
+ bigTest(0, 1738149618);
+ bigTest(1, 934350518);
+ bigTest(2, -532869390);
+ }
+
+ /*
+ * Simple inflate/deflate test, taken from the reference docs for the
+ * Inflater/Deflater classes.
+ */
+ private void simpleTest()
+ throws UnsupportedEncodingException, DataFormatException {
+ // Encode a String into bytes
+ String inputString = "blahblahblah??";
+ byte[] input = inputString.getBytes("UTF-8");
+
+ // Compress the bytes
+ byte[] output = new byte[100];
+ Deflater compresser = new Deflater();
+ compresser.setInput(input);
+ compresser.finish();
+ int compressedDataLength = compresser.deflate(output);
+
+ // Decompress the bytes
+ Inflater decompresser = new Inflater();
+ decompresser.setInput(output, 0, compressedDataLength);
+ byte[] result = new byte[100];
+ int resultLength = decompresser.inflate(result);
+
+ // Decode the bytes into a String
+ String outputString = new String(result, 0, resultLength, "UTF-8");
+
+ assertEquals(inputString, outputString);
+ assertEquals(compresser.getAdler(), decompresser.getAdler());
+
+ decompresser.end();
+ }
+
+ /*
+ * "step" determines how compressible the data is.
+ *
+ * Note we must set "nowrap" to false, or the Adler-32 doesn't get
+ * computed.
+ */
+ private void bigTest(int step, int expectedAdler)
+ throws UnsupportedEncodingException, DataFormatException {
+ byte[] input = new byte[128 * 1024];
+ byte[] comp = new byte[128 * 1024 + 512];
+ byte[] output = new byte[128 * 1024 + 512];
+ Inflater inflater = new Inflater(false);
+ Deflater deflater = new Deflater(Deflater.BEST_COMPRESSION, false);
+
+ createSample(input, step);
+
+ compress(deflater, input, comp);
+ expand(inflater, comp, (int) deflater.getBytesWritten(), output);
+
+ assertEquals(inflater.getBytesWritten(), input.length);
+ assertEquals(deflater.getAdler(), inflater.getAdler());
+ assertEquals(deflater.getAdler(), expectedAdler);
+ }
+
+ /*
+ * Create a large data sample.
+ * stepStep = 0 --> >99% compression
+ * stepStep = 1 --> ~30% compression
+ * stepStep = 2 --> no compression
+ */
+ private void createSample(byte[] sample, int stepStep) {
+ byte val, step;
+ int i, j, offset;
+
+ assertTrue(sample.length >= 128 * 1024);
+
+ val = 0;
+ step = 1;
+ offset = 0;
+ for (i = 0; i < (128 * 1024) / 256; i++) {
+ for (j = 0; j < 256; j++) {
+ sample[offset++] = val;
+ val += step;
+ }
+
+ step += stepStep;
+ }
+ }
+
+ private static final int LOCAL_BUF_SIZE = 256;
+
+ /*
+ * Compress all data in "in" to "out". We use a small window on input
+ * and output to exercise that part of the code.
+ *
+ * It's the caller's responsibility to ensure that "out" has enough
+ * space.
+ */
+ private void compress(Deflater deflater, byte[] inBuf, byte[] outBuf) {
+ int inCount = inBuf.length; // use all
+ int inPosn;
+ int outPosn;
+
+ inPosn = outPosn = 0;
+
+ //System.out.println("### starting compress");
+
+ while (!deflater.finished()) {
+ int want = -1, got;
+
+ // only read if the input buffer is empty
+ if (deflater.needsInput() && inCount != 0) {
+ want = (inCount < LOCAL_BUF_SIZE) ? inCount : LOCAL_BUF_SIZE;
+
+ deflater.setInput(inBuf, inPosn, want);
+
+ inCount -= want;
+ inPosn += want;
+ if (inCount == 0) {
+ deflater.finish();
+ }
+ }
+
+ // deflate to current position in output buffer
+ int compCount;
+
+ compCount = deflater.deflate(outBuf, outPosn, LOCAL_BUF_SIZE);
+ outPosn += compCount;
+
+ //System.out.println("Compressed " + want + ", output " + compCount);
+ }
+ }
+
+ /*
+ * Expand data from "inBuf" to "outBuf". Uses a small window to better
+ * exercise the code.
+ */
+ private void expand(Inflater inflater, byte[] inBuf, int inCount,
+ byte[] outBuf) throws DataFormatException {
+ int inPosn;
+ int outPosn;
+
+ inPosn = outPosn = 0;
+
+ //System.out.println("### starting expand, inCount is " + inCount);
+
+ while (!inflater.finished()) {
+ int want = -1, got;
+
+ // only read if the input buffer is empty
+ if (inflater.needsInput() && inCount != 0) {
+ want = (inCount < LOCAL_BUF_SIZE) ? inCount : LOCAL_BUF_SIZE;
+
+ inflater.setInput(inBuf, inPosn, want);
+
+ inCount -= want;
+ inPosn += want;
+ }
+
+ // inflate to current position in output buffer
+ int compCount;
+
+ compCount = inflater.inflate(outBuf, outPosn, LOCAL_BUF_SIZE);
+ outPosn += compCount;
+
+ //System.out.println("Expanded " + want + ", output " + compCount);
+ }
+ }
+}
+
diff --git a/tests/CoreTests/android/core/EnumTest.java b/tests/CoreTests/android/core/EnumTest.java
new file mode 100644
index 0000000..d479491
--- /dev/null
+++ b/tests/CoreTests/android/core/EnumTest.java
@@ -0,0 +1,64 @@
+/*
+ * 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 android.core;
+
+import junit.framework.TestCase;
+import android.test.suitebuilder.annotation.SmallTest;
+
+/**
+ * Tests basic behavior of enums.
+ */
+public class EnumTest extends TestCase {
+ enum MyEnum {
+ ZERO, ONE, TWO, THREE, FOUR {boolean isFour() {
+ return true;
+ }};
+
+ boolean isFour() {
+ return false;
+ }
+ }
+
+ enum MyEnumTwo {
+ FIVE, SIX
+ }
+
+ @SmallTest
+ public void testEnum() throws Exception {
+ assertTrue(MyEnum.ZERO.compareTo(MyEnum.ONE) < 0);
+ assertEquals(MyEnum.ZERO, MyEnum.ZERO);
+ assertTrue(MyEnum.TWO.compareTo(MyEnum.ONE) > 0);
+ assertTrue(MyEnum.FOUR.compareTo(MyEnum.ONE) > 0);
+
+ assertEquals("ONE", MyEnum.ONE.name());
+ assertSame(MyEnum.ONE.getDeclaringClass(), MyEnum.class);
+ assertSame(MyEnum.FOUR.getDeclaringClass(), MyEnum.class);
+
+ assertTrue(MyEnum.FOUR.isFour());
+
+ MyEnum e;
+
+ e = MyEnum.ZERO;
+
+ switch (e) {
+ case ZERO:
+ break;
+ default:
+ fail("wrong switch");
+ }
+ }
+}
diff --git a/tests/CoreTests/android/core/FileTest.java b/tests/CoreTests/android/core/FileTest.java
new file mode 100644
index 0000000..980452e
--- /dev/null
+++ b/tests/CoreTests/android/core/FileTest.java
@@ -0,0 +1,38 @@
+/*
+ * 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 android.core;
+
+import junit.framework.TestCase;
+
+import java.io.File;
+import android.test.suitebuilder.annotation.SmallTest;
+
+/**
+ * Checks creation and deletion of a file.
+ */
+public class FileTest extends TestCase {
+
+ @SmallTest
+ public void testFile() throws Exception {
+
+ File file = File.createTempFile(String.valueOf(System.currentTimeMillis()), null, null);
+
+ assertTrue(file.exists());
+ assertTrue(file.delete());
+ assertFalse(file.exists());
+ }
+}
diff --git a/tests/CoreTests/android/core/FloatDoubleTest.java b/tests/CoreTests/android/core/FloatDoubleTest.java
new file mode 100644
index 0000000..8c8455b
--- /dev/null
+++ b/tests/CoreTests/android/core/FloatDoubleTest.java
@@ -0,0 +1,152 @@
+/*
+ * 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 android.core;
+
+import junit.framework.TestCase;
+import android.test.suitebuilder.annotation.SmallTest;
+
+/**
+ * Tests for basic functionality of floats and doubles.
+ */
+public class FloatDoubleTest extends TestCase {
+
+ @SmallTest
+ public void testFloatDouble() throws Exception {
+ Double d = Double.valueOf(1.0);
+ Float f = Float.valueOf(1.0f);
+ Object o = new Object();
+
+ assertFalse(f.equals(d));
+ assertFalse(d.equals(f));
+ assertFalse(f.equals(o));
+ assertFalse(d.equals(o));
+ assertFalse(f.equals(null));
+ assertFalse(d.equals(null));
+ }
+
+ @SmallTest
+ public void testFloat() throws Exception {
+ float pz = 0.0f;
+ float nz = -0.0f;
+
+ float pzero = 1.0f / Float.POSITIVE_INFINITY;
+ float nzero = 1.0f / Float.NEGATIVE_INFINITY;
+
+ // Everything compares as '=='
+ assertTrue(pz == pz);
+ assertTrue(pz == nz);
+ assertTrue(pz == pzero);
+ assertTrue(pz == nzero);
+
+ assertTrue(nz == pz);
+ assertTrue(nz == nz);
+ assertTrue(nz == pzero);
+ assertTrue(nz == nzero);
+
+ assertTrue(pzero == pz);
+ assertTrue(pzero == nz);
+ assertTrue(pzero == pzero);
+ assertTrue(pzero == nzero);
+
+ assertTrue(nzero == pz);
+ assertTrue(nzero == nz);
+ assertTrue(nzero == pzero);
+ assertTrue(nzero == nzero);
+
+ // +-0 are distinct as Floats
+ assertEquals(Float.valueOf(pz), Float.valueOf(pz));
+ assertTrue(!Float.valueOf(pz).equals(Float.valueOf(nz)));
+ assertEquals(Float.valueOf(pz), Float.valueOf(pzero));
+ assertTrue(!Float.valueOf(pz).equals(Float.valueOf(nzero)));
+
+ assertTrue(!Float.valueOf(nz).equals(Float.valueOf(pz)));
+ assertEquals(Float.valueOf(nz), Float.valueOf(nz));
+ assertTrue(!Float.valueOf(nz).equals(Float.valueOf(pzero)));
+ assertEquals(Float.valueOf(nz), Float.valueOf(nzero));
+
+ assertEquals(Float.valueOf(pzero), Float.valueOf(pz));
+ assertTrue(!Float.valueOf(pzero).equals(Float.valueOf(nz)));
+ assertEquals(Float.valueOf(pzero), Float.valueOf(pzero));
+ assertTrue(!Float.valueOf(pzero).equals(Float.valueOf(nzero)));
+
+ assertTrue(!Float.valueOf(nzero).equals(Float.valueOf(pz)));
+ assertEquals(Float.valueOf(nzero), Float.valueOf(nz));
+ assertTrue(!Float.valueOf(nzero).equals(Float.valueOf(pzero)));
+ assertEquals(Float.valueOf(nzero), Float.valueOf(nzero));
+
+ // Nan's compare as equal
+ Float sqrtm2 = Float.valueOf((float) Math.sqrt(-2.0f));
+ Float sqrtm3 = Float.valueOf((float) Math.sqrt(-3.0f));
+ assertEquals(sqrtm2, sqrtm3);
+ }
+
+ @SmallTest
+ public void testDouble() throws Exception {
+ double pz = 0.0;
+ double nz = -0.0;
+
+ double pzero = 1.0 / Double.POSITIVE_INFINITY;
+ double nzero = 1.0 / Double.NEGATIVE_INFINITY;
+
+ // Everything compares as '=='
+ assertTrue(pz == pz);
+ assertTrue(pz == nz);
+ assertTrue(pz == pzero);
+ assertTrue(pz == nzero);
+
+ assertTrue(nz == pz);
+ assertTrue(nz == nz);
+ assertTrue(nz == pzero);
+ assertTrue(nz == nzero);
+
+ assertTrue(pzero == pz);
+ assertTrue(pzero == nz);
+ assertTrue(pzero == pzero);
+ assertTrue(pzero == nzero);
+
+ assertTrue(nzero == pz);
+ assertTrue(nzero == nz);
+ assertTrue(nzero == pzero);
+ assertTrue(nzero == nzero);
+
+ // +-0 are distinct as Doubles
+ assertEquals(Double.valueOf(pz), Double.valueOf(pz));
+ assertTrue(!Double.valueOf(pz).equals(Double.valueOf(nz)));
+ assertEquals(Double.valueOf(pz), Double.valueOf(pzero));
+ assertTrue(!Double.valueOf(pz).equals(Double.valueOf(nzero)));
+
+ assertTrue(!Double.valueOf(nz).equals(Double.valueOf(pz)));
+ assertEquals(Double.valueOf(nz), Double.valueOf(nz));
+ assertTrue(!Double.valueOf(nz).equals(Double.valueOf(pzero)));
+ assertEquals(Double.valueOf(nz), Double.valueOf(nzero));
+
+ assertEquals(Double.valueOf(pzero), Double.valueOf(pz));
+ assertTrue(!Double.valueOf(pzero).equals(Double.valueOf(nz)));
+ assertEquals(Double.valueOf(pzero), Double.valueOf(pzero));
+ assertTrue(!Double.valueOf(pzero).equals(Double.valueOf(nzero)));
+
+ assertTrue(!Double.valueOf(nzero).equals(Double.valueOf(pz)));
+ assertEquals(Double.valueOf(nzero), Double.valueOf(nz));
+ assertTrue(!Double.valueOf(nzero).equals(Double.valueOf(pzero)));
+ assertEquals(Double.valueOf(nzero), Double.valueOf(nzero));
+
+ // Nan's compare as equal
+ Double sqrtm2 = Double.valueOf(Math.sqrt(-2.0));
+ Double sqrtm3 = Double.valueOf(Math.sqrt(-3.0));
+ assertEquals(sqrtm2, sqrtm3);
+ }
+}
diff --git a/tests/CoreTests/android/core/GZIPStreamTest.java b/tests/CoreTests/android/core/GZIPStreamTest.java
new file mode 100644
index 0000000..dd56fb7
--- /dev/null
+++ b/tests/CoreTests/android/core/GZIPStreamTest.java
@@ -0,0 +1,114 @@
+/*
+ * 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 android.core;
+
+import junit.framework.TestCase;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.util.zip.GZIPInputStream;
+import java.util.zip.GZIPOutputStream;
+import android.test.suitebuilder.annotation.MediumTest;
+
+/**
+ * Deflates and inflates some test data with GZipStreams
+ */
+public class GZIPStreamTest extends TestCase {
+
+ @MediumTest
+ public void testGZIPStream() throws Exception {
+ ByteArrayOutputStream bytesOut = new ByteArrayOutputStream();
+ createGZIP(bytesOut);
+
+ byte[] zipData;
+ zipData = bytesOut.toByteArray();
+
+ /*
+ FileOutputStream outFile = new FileOutputStream("/tmp/foo.gz");
+ outFile.write(zipData, 0, zipData.length);
+ outFile.close();
+ */
+
+ /*
+ FileInputStream inFile = new FileInputStream("/tmp/foo.gz");
+ int inputLength = inFile.available();
+ zipData = new byte[inputLength];
+ if (inFile.read(zipData) != inputLength)
+ throw new RuntimeException();
+ inFile.close();
+ */
+
+ ByteArrayInputStream bytesIn = new ByteArrayInputStream(zipData);
+ scanGZIP(bytesIn);
+ }
+
+ /*
+ * stepStep == 0 --> >99% compression
+ * stepStep == 1 --> ~30% compression
+ * stepStep == 2 --> no compression
+ */
+ static byte[] makeSampleFile(int stepStep) throws IOException {
+ byte[] sample = new byte[128 * 1024];
+ byte val, step;
+ int i, j, offset;
+
+ val = 0;
+ step = 1;
+ offset = 0;
+ for (i = 0; i < (128 * 1024) / 256; i++) {
+ for (j = 0; j < 256; j++) {
+ sample[offset++] = val;
+ val += step;
+ }
+
+ step += stepStep;
+ }
+
+ return sample;
+ }
+
+ static void createGZIP(ByteArrayOutputStream bytesOut) throws IOException {
+ GZIPOutputStream out = new GZIPOutputStream(bytesOut);
+ try {
+ byte[] input = makeSampleFile(1);
+ out.write(input, 0, input.length);
+ //out.finish();
+ } finally {
+ out.close();
+ }
+ }
+
+ static void scanGZIP(ByteArrayInputStream bytesIn) throws IOException {
+ GZIPInputStream in = new GZIPInputStream(bytesIn);
+ try {
+ ByteArrayOutputStream contents = new ByteArrayOutputStream();
+ byte[] buf = new byte[4096];
+ int len, totalLen = 0;
+
+ while ((len = in.read(buf)) > 0) {
+ contents.write(buf, 0, len);
+ totalLen += len;
+ }
+
+ assertEquals(totalLen, 128 * 1024);
+ } finally {
+ in.close();
+ }
+ }
+}
+
diff --git a/tests/CoreTests/android/core/HashMapPerfTest.java b/tests/CoreTests/android/core/HashMapPerfTest.java
new file mode 100644
index 0000000..8475222
--- /dev/null
+++ b/tests/CoreTests/android/core/HashMapPerfTest.java
@@ -0,0 +1,93 @@
+/*
+ * 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 android.core;
+
+import android.os.SystemClock;
+import android.test.suitebuilder.annotation.LargeTest;
+import junit.framework.TestCase;
+
+import java.util.HashMap;
+import java.util.Random;
+
+/**
+ * Tests basic functionality of HashMaps and prints the time needed to System.out
+ */
+public class HashMapPerfTest extends TestCase {
+
+ private static final Random sRandom = new Random(1);
+
+ class StringThing {
+
+ String mId;
+
+ public StringThing() {
+ int len = sRandom.nextInt(20) + 1;
+ char[] chars = new char[len];
+ chars[0] = 't';
+ for (int i = 1; i < len; i++) {
+ chars[i] = (char) ('q' + sRandom.nextInt(4));
+ }
+ mId = new String(chars, 0, len);
+ }
+
+ public String getId() {
+ return mId;
+ }
+ }
+
+ private static final int NUM_ELTS = 1000;
+ private static final int ITERS = 100;
+
+ String[] keyCopies = new String[NUM_ELTS];
+
+ private static final boolean lookupByOriginals = false;
+
+ @LargeTest
+ public void testHashMapPerformance() throws Exception {
+ StringThing[] st = new StringThing[NUM_ELTS];
+ for (int i = 0; i < NUM_ELTS; i++) {
+ st[i] = new StringThing();
+ keyCopies[i] = st[i].getId();
+ }
+
+ // android.os.Debug.startMethodTracing();
+ long start = SystemClock.uptimeMillis();
+ for (int i = 0; i < ITERS; i++) {
+ HashMap<String, StringThing> map = new HashMap<String, StringThing>();
+ for (int j = 0; j < NUM_ELTS; j++) {
+ StringThing s = st[i];
+ map.put(s.getId(), s);
+ }
+ for (int j = 0; j < NUM_ELTS; j++) {
+ if (lookupByOriginals) {
+ StringThing s = st[i];
+ map.get(s.getId());
+ } else {
+ map.get(keyCopies[j]);
+ }
+ }
+ }
+ long finish = SystemClock.uptimeMillis();
+ // android.os.Debug.stopMethodTracing();
+
+ // This should be an assertion instead
+
+// System.out.println("time (" + NUM_ELTS +
+// ", elts, " + ITERS +
+// " iters) = " + (finish - start));
+ }
+}
diff --git a/tests/CoreTests/android/core/HashMapTest.java b/tests/CoreTests/android/core/HashMapTest.java
new file mode 100644
index 0000000..99b2a47
--- /dev/null
+++ b/tests/CoreTests/android/core/HashMapTest.java
@@ -0,0 +1,281 @@
+/*
+ * 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 android.core;
+
+import junit.framework.TestCase;
+
+import java.util.HashMap;
+import java.util.Iterator;
+import android.test.suitebuilder.annotation.SmallTest;
+
+/**
+ * Test cases for Hashmap.
+ */
+public class HashMapTest extends TestCase {
+ private static final Integer ONE = new Integer(1);
+ private static final Integer TWO = new Integer(2);
+ private static final Integer THREE = new Integer(3);
+ private static final Integer FOUR = new Integer(4);
+
+ private void addItems(HashMap map) {
+ map.put("one", ONE);
+ map.put("two", TWO);
+ map.put("three", THREE);
+ map.put("four", FOUR);
+
+ assertEquals(4, map.size());
+
+ assertEquals(ONE, map.get("one"));
+ assertEquals(TWO, map.get("two"));
+ assertEquals(THREE, map.get("three"));
+ assertEquals(FOUR, map.get("four"));
+ }
+
+ /**
+ * checks if simple adding elements works.
+ */
+ @SmallTest
+ public void testAdd() throws Exception {
+ HashMap map = new HashMap();
+ addItems(map);
+ }
+
+ /**
+ * checks if clearing the map works.
+ */
+ @SmallTest
+ public void testClear() throws Exception {
+ HashMap map = new HashMap();
+
+ addItems(map);
+ map.clear();
+ assertEquals(0, map.size());
+ }
+
+ /**
+ * checks if removing an elemt works.
+ */
+ @SmallTest
+ public void testRemove() throws Exception {
+ HashMap map = new HashMap();
+
+ addItems(map);
+ map.remove("three");
+ assertNull(map.get("three"));
+ }
+
+ /**
+ * does some manipulation with a filled HashMap and checks
+ * if they work as intended
+ */
+ @SmallTest
+ public void testManipulate() throws Exception {
+ HashMap map = new HashMap();
+
+ assertTrue(map.isEmpty());
+ assertEquals(0, map.size());
+ assertNull(map.get(null));
+ assertNull(map.get("one"));
+ assertFalse(map.containsKey("one"));
+ assertFalse(map.containsValue(new Integer(1)));
+ assertNull(map.remove(null));
+ assertNull(map.remove("one"));
+
+ assertNull(map.put(null, new Integer(-1)));
+ assertNull(map.put("one", new Integer(1)));
+ assertNull(map.put("two", new Integer(2)));
+ assertNull(map.put("three", new Integer(3)));
+ assertEquals(-1, ((Integer) map.put(null, new Integer(0))).intValue());
+
+ assertEquals(0, ((Integer) map.get(null)).intValue());
+ assertEquals(1, ((Integer) map.get("one")).intValue());
+ assertEquals(2, ((Integer) map.get("two")).intValue());
+ assertEquals(3, ((Integer) map.get("three")).intValue());
+
+ assertTrue(map.containsKey(null));
+ assertTrue(map.containsKey("one"));
+ assertTrue(map.containsKey("two"));
+ assertTrue(map.containsKey("three"));
+
+ assertTrue(map.containsValue(new Integer(0)));
+ assertTrue(map.containsValue(new Integer(1)));
+ assertTrue(map.containsValue(new Integer(2)));
+ assertTrue(map.containsValue(new Integer(3)));
+
+ assertEquals(0, ((Integer) map.remove(null)).intValue());
+ assertEquals(1, ((Integer) map.remove("one")).intValue());
+ assertEquals(2, ((Integer) map.remove("two")).intValue());
+ assertEquals(3, ((Integer) map.remove("three")).intValue());
+
+ assertTrue(map.isEmpty());
+ assertEquals(0, map.size());
+ assertNull(map.get(null));
+ assertNull(map.get("one"));
+ assertFalse(map.containsKey("one"));
+ assertFalse(map.containsValue(new Integer(1)));
+ assertNull(map.remove(null));
+ assertNull(map.remove("one"));
+ }
+
+ /**
+ * checks if the key iterator of HashMaps work.
+ */
+ @SmallTest
+ public void testKeyIterator() throws Exception {
+ HashMap map = new HashMap();
+
+ boolean[] slots = new boolean[4];
+
+ addItems(map);
+
+ Iterator iter = map.keySet().iterator();
+
+ while (iter.hasNext()) {
+ int slot = 0;
+ Object key = iter.next();
+
+ if (key.equals("one"))
+ slot = 0;
+ else if (key.equals("two"))
+ slot = 1;
+ else if (key.equals("three"))
+ slot = 2;
+ else if (key.equals("four"))
+ slot = 3;
+ else
+ fail("Unkown key in hashmap");
+
+ if (slots[slot])
+ fail("key returned more than once");
+ else
+ slots[slot] = true;
+ }
+
+ assertTrue(slots[0]);
+ assertTrue(slots[1]);
+ assertTrue(slots[2]);
+ assertTrue(slots[3]);
+ }
+
+ /**
+ * checks if the value iterator works.
+ */
+ @SmallTest
+ public void testValueIterator() throws Exception {
+ HashMap map = new HashMap();
+
+ boolean[] slots = new boolean[4];
+
+ addItems(map);
+
+ Iterator iter = map.values().iterator();
+
+ while (iter.hasNext()) {
+ int slot = 0;
+ Object value = iter.next();
+
+ if (value.equals(ONE))
+ slot = 0;
+ else if (value.equals(TWO))
+ slot = 1;
+ else if (value.equals(THREE))
+ slot = 2;
+ else if (value.equals(FOUR))
+ slot = 3;
+ else
+ fail("Unkown value in hashmap");
+
+ if (slots[slot])
+ fail("value returned more than once");
+ else
+ slots[slot] = true;
+ }
+
+ assertTrue(slots[0]);
+ assertTrue(slots[1]);
+ assertTrue(slots[2]);
+ assertTrue(slots[3]);
+ }
+
+ /**
+ * checks if the entry iterator works for HashMaps.
+ */
+ @SmallTest
+ public void testEntryIterator() throws Exception {
+ HashMap map = new HashMap();
+
+ boolean[] slots = new boolean[4];
+
+ addItems(map);
+
+ Iterator iter = map.entrySet().iterator();
+
+ while (iter.hasNext()) {
+ int slot = 0;
+ Object entry = iter.next();
+
+ if (entry.toString().equals("one=1"))
+ slot = 0;
+ else if (entry.toString().equals("two=2"))
+ slot = 1;
+ else if (entry.toString().equals("three=3"))
+ slot = 2;
+ else if (entry.toString().equals("four=4"))
+ slot = 3;
+ else
+ fail("Unkown entry in hashmap");
+
+ if (slots[slot])
+ fail("entry returned more than once");
+ else
+ slots[slot] = true;
+ }
+
+ assertTrue(slots[0]);
+ assertTrue(slots[1]);
+ assertTrue(slots[2]);
+ assertTrue(slots[3]);
+ }
+
+ /**
+ * checks if the HashMap equals method works.
+ */
+ @SmallTest
+ public void testEquals() throws Exception {
+ HashMap map1 = new HashMap();
+ HashMap map2 = new HashMap();
+ HashMap map3 = new HashMap();
+
+ map1.put("one", "1");
+ map1.put("two", "2");
+ map1.put("three", "3");
+
+ map2.put("one", new String("1"));
+ map2.put(new String("two"), "2");
+ map2.put(new String("three"), new String("3"));
+
+ assertTrue(map1.equals(map2));
+
+ map3.put("one", "1");
+ map3.put("two", "1");
+ map3.put("three", "1");
+
+ assertFalse(map1.equals(map3));
+ assertFalse(map2.equals(map3));
+ }
+}
+
diff --git a/tests/CoreTests/android/core/HttpConstants.java b/tests/CoreTests/android/core/HttpConstants.java
new file mode 100644
index 0000000..d655d52
--- /dev/null
+++ b/tests/CoreTests/android/core/HttpConstants.java
@@ -0,0 +1,157 @@
+/*
+ * Copyright (C) 2007 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 android.core;
+
+interface HttpConstants {
+ /** 2XX: generally "OK" */
+ public static final int HTTP_OK = 200;
+ public static final int HTTP_CREATED = 201;
+ public static final int HTTP_ACCEPTED = 202;
+ public static final int HTTP_NOT_AUTHORITATIVE = 203;
+ public static final int HTTP_NO_CONTENT = 204;
+ public static final int HTTP_RESET = 205;
+ public static final int HTTP_PARTIAL = 206;
+
+ /** 3XX: relocation/redirect */
+ public static final int HTTP_MULT_CHOICE = 300;
+ public static final int HTTP_MOVED_PERM = 301;
+ public static final int HTTP_MOVED_TEMP = 302;
+ public static final int HTTP_SEE_OTHER = 303;
+ public static final int HTTP_NOT_MODIFIED = 304;
+ public static final int HTTP_USE_PROXY = 305;
+
+ /** 4XX: client error */
+ public static final int HTTP_BAD_REQUEST = 400;
+ public static final int HTTP_UNAUTHORIZED = 401;
+ public static final int HTTP_PAYMENT_REQUIRED = 402;
+ public static final int HTTP_FORBIDDEN = 403;
+ public static final int HTTP_NOT_FOUND = 404;
+ public static final int HTTP_BAD_METHOD = 405;
+ public static final int HTTP_NOT_ACCEPTABLE = 406;
+ public static final int HTTP_PROXY_AUTH = 407;
+ public static final int HTTP_CLIENT_TIMEOUT = 408;
+ public static final int HTTP_CONFLICT = 409;
+ public static final int HTTP_GONE = 410;
+ public static final int HTTP_LENGTH_REQUIRED = 411;
+ public static final int HTTP_PRECON_FAILED = 412;
+ public static final int HTTP_ENTITY_TOO_LARGE = 413;
+ public static final int HTTP_REQ_TOO_LONG = 414;
+ public static final int HTTP_UNSUPPORTED_TYPE = 415;
+
+ /** 5XX: server error */
+ public static final int HTTP_SERVER_ERROR = 500;
+ public static final int HTTP_INTERNAL_ERROR = 501;
+ public static final int HTTP_BAD_GATEWAY = 502;
+ public static final int HTTP_UNAVAILABLE = 503;
+ public static final int HTTP_GATEWAY_TIMEOUT = 504;
+ public static final int HTTP_VERSION = 505;
+
+ /** Method IDs */
+ public static final int UNKNOWN_METHOD = 0;
+ public static final int GET_METHOD = 1;
+ public static final int HEAD_METHOD = 2;
+ public static final int POST_METHOD = 3;
+
+ public static final String[] requestHeaders = {
+ "cache-control",
+ "connection",
+ "date",
+ "pragma",
+ "trailer",
+ "transfer-encoding",
+ "upgrade",
+ "via",
+ "warning",
+ "accept",
+ "accept-charset",
+ "accept-encoding",
+ "accept-language",
+ "authorization",
+ "expect",
+ "from",
+ "host",
+ "if-match",
+ "if-modified-since",
+ "if-none-match",
+ "if-range",
+ "if-unmodified-since",
+ "max-forwards",
+ "proxy-authentication",
+ "range",
+ "referer",
+ "te",
+ "user-agent",
+ "keep-alive",
+ "allow",
+ "content-encoding",
+ "content-language",
+ "content-length",
+ "content-location",
+ "content-md5",
+ "content-range",
+ "content-type",
+ "expires",
+ "last-modified",
+ "location",
+ "server"
+
+ };
+
+ public static final int REQ_UNKNOWN = -1;
+ public static final int REQ_CACHE_CONTROL = 0;
+ public static final int REQ_CONNECTION = 1;
+ public static final int REQ_DATE = 2;
+ public static final int REQ_PRAGMA = 3;
+ public static final int REQ_TRAILER = 4;
+ public static final int REQ_TRANSFER_ENCODING = 5;
+ public static final int REQ_UPGRADE = 6;
+ public static final int REQ_VIA = 7;
+ public static final int REQ_WARNING = 8;
+ public static final int REQ_ACCEPT = 9;
+ public static final int REQ_ACCEPT_CHARSET = 10;
+ public static final int REQ_ACCEPT_ENCODING = 11;
+ public static final int REQ_ACCEPT_LANGUAGE = 12;
+ public static final int REQ_AUTHORIZATION = 13;
+ public static final int REQ_EXPECT = 14;
+ public static final int REQ_FROM = 15;
+ public static final int REQ_HOST = 16;
+ public static final int REQ_IF_MATCH = 17;
+ public static final int REQ_IF_MODIFIED_SINCE = 18;
+ public static final int REQ_IF_NONE_MATCH = 19;
+ public static final int REQ_IF_RANGE = 20;
+ public static final int REQ_IF_UNMODIFIED_SINCE = 21;
+ public static final int REQ_MAX_FORWARDS = 22;
+ public static final int REQ_PROXY_AUTHENTICATION = 23;
+ public static final int REQ_RANGE = 24;
+ public static final int REQ_REFERER = 25;
+ public static final int REQ_TE = 26;
+ public static final int REQ_USER_AGENT = 27;
+ public static final int REQ_KEEP_ALIVE = 28;
+ public static final int REQ_ALLOW = 29;
+ public static final int REQ_CONTENT_ENCODING = 30;
+ public static final int REQ_CONTENT_LANGUAGE = 31;
+ public static final int REQ_CONTENT_LENGTH = 32;
+ public static final int REQ_CONTENT_LOCATION = 33;
+ public static final int REQ_CONTENT_MD5 = 34;
+ public static final int REQ_CONTENT_RANGE = 35;
+ public static final int REQ_CONTENT_TYPE = 36;
+ public static final int REQ_EXPIRES = 37;
+ public static final int REQ_LAST_MODIFIED = 38;
+ public static final int REQ_LOCATION = 39;
+ public static final int REQ_SERVER = 40;
+
+}
diff --git a/tests/CoreTests/android/core/IOUtil.java b/tests/CoreTests/android/core/IOUtil.java
new file mode 100644
index 0000000..6f69418
--- /dev/null
+++ b/tests/CoreTests/android/core/IOUtil.java
@@ -0,0 +1,193 @@
+/*
+ * Copyright (C) 2007 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 android.core;
+
+import java.io.InputStream;
+import java.io.IOException;
+import java.io.Reader;
+import java.io.InputStreamReader;
+
+public final class IOUtil {
+
+ private IOUtil() {
+ }
+
+ /**
+ * returns the content of an InputStream as a String.
+ *
+ * @param a the input stream.
+ * @return the string
+ * @throws java.io.IOException
+ */
+ public static String read(InputStream a) throws IOException {
+ int r;
+ StringBuilder builder = new StringBuilder();
+ do {
+ r = a.read();
+ if (r != -1)
+ builder.append((char) r);
+ } while (r != -1);
+ return builder.toString();
+ }
+
+ /**
+ * reads characters from a reader and returns them as a string.
+ *
+ * @param a the reader.
+ * @return the string.
+ * @throws IOException
+ */
+ public static String read(Reader a) throws IOException {
+ int r;
+ StringBuilder builder = new StringBuilder();
+ do {
+ r = a.read();
+ if (r != -1)
+ builder.append((char) r);
+ } while (r != -1);
+ return builder.toString();
+ }
+
+ /**
+ * returns the content of an InputStream as a String. It reads x characters.
+ *
+ * @param a the input stream.
+ * @param x number of characters to read.
+ * @return the string
+ * @throws IOException
+ */
+ public static String read(InputStream a, int x) throws IOException {
+ byte[] b = new byte[x];
+ int len = a.read(b, 0, x);
+ if (len < 0) {
+ return "";
+ }
+ return new String(b, 0, len);
+ }
+
+ /**
+ * reads a number of characters from a reader and returns them as a string.
+ *
+ * @param a the reader.
+ * @param x the number of characters to read.
+ * @return the string.
+ * @throws IOException
+ */
+ public static String read(Reader a, int x) throws IOException {
+ char[] b = new char[x];
+ int len = a.read(b, 0, x);
+ if (len < 0) {
+ return "";
+ }
+ return new String(b, 0, len);
+ }
+
+ /**
+ * returns the content of the input stream as a String. It only appends
+ * every second character.
+ *
+ * @param a the input stream.
+ * @return the string created from every second character of the input stream.
+ * @throws IOException
+ */
+ public static String skipRead(InputStream a) throws IOException {
+ int r;
+ StringBuilder builder = new StringBuilder();
+ do {
+ a.skip(1);
+ r = a.read();
+ if (r != -1)
+ builder.append((char) r);
+ } while (r != -1);
+ return builder.toString();
+ }
+
+ /**
+ * reads every second characters from a reader and returns them as a string.
+ *
+ * @param a the reader.
+ * @return the string.
+ * @throws IOException
+ */
+ public static String skipRead(Reader a) throws IOException {
+ int r;
+ StringBuilder builder = new StringBuilder();
+ do {
+ a.skip(1);
+ r = a.read();
+ if (r != -1)
+ builder.append((char) r);
+ } while (r != -1);
+ return builder.toString();
+ }
+
+ /**
+ * reads characters from a InputStream, skips back y characters and continues
+ * reading from that new position up to the end.
+ *
+ * @param a the InputStream.
+ * @param x the position of the mark. the marks position is x+y
+ * @param y the number of characters to jump back after the position x+y was reached.
+ * @return the string.
+ * @throws IOException
+ */
+ public static String markRead(InputStream a, int x, int y) throws IOException {
+ int m = 0;
+ int r;
+ StringBuilder builder = new StringBuilder();
+ do {
+ m++;
+ r = a.read();
+ if (m == x)
+ a.mark((x + y));
+ if (m == (x + y))
+ a.reset();
+
+ if (r != -1)
+ builder.append((char) r);
+ } while (r != -1);
+ return builder.toString();
+ }
+
+ /**
+ * reads characters from a reader, skips back y characters and continues
+ * reading from that new position up to the end.
+ *
+ * @param a the reader.
+ * @param x the position of the mark. the marks position is x+y
+ * @param y the number of characters to jump back after the position x+y was reached.
+ * @return the string.
+ * @throws IOException
+ */
+ public static String markRead(Reader a, int x, int y) throws IOException {
+ int m = 0;
+ int r;
+ StringBuilder builder = new StringBuilder();
+ do {
+ m++;
+ r = a.read();
+ if (m == x)
+ a.mark((x + y));
+ if (m == (x + y))
+ a.reset();
+
+ if (r != -1)
+ builder.append((char) r);
+ } while (r != -1);
+ return builder.toString();
+ }
+}
diff --git a/tests/CoreTests/android/core/InetAddrTest.java b/tests/CoreTests/android/core/InetAddrTest.java
new file mode 100644
index 0000000..c7b89e1
--- /dev/null
+++ b/tests/CoreTests/android/core/InetAddrTest.java
@@ -0,0 +1,100 @@
+/*
+ * 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 android.core;
+
+import junit.framework.TestCase;
+
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+import java.util.Random;
+
+import android.test.suitebuilder.annotation.Suppress;
+
+/**
+ * Tests InetAddr class by checking methods to resolve domains to IP addresses
+ * and by checking if the class returns correct addresses for local host address
+ * and host name.
+ */
+@Suppress
+public class InetAddrTest extends TestCase {
+ private static final String[] HOSTS = {
+ "localhost", "www.google.com", "www.slashdot.org", "www.wikipedia.org",
+ "www.paypal.com", "www.cnn.com", "www.yahoo.com", "www.amazon.com",
+ "www.ebay.com", "www.android.com"
+ };
+
+ public void testInetAddr() throws Exception {
+ byte[] raw;
+
+ InetAddress ia = InetAddress.getByName("localhost");
+
+ raw = ia.getAddress();
+
+ assertEquals(127, raw[0]);
+ assertEquals(0, raw[1]);
+ assertEquals(0, raw[2]);
+ assertEquals(1, raw[3]);
+
+ ia = InetAddress.getByName("127.0.0.1");
+
+ raw = ia.getAddress();
+
+ assertEquals(127, raw[0]);
+ assertEquals(0, raw[1]);
+ assertEquals(0, raw[2]);
+ assertEquals(1, raw[3]);
+
+ ia = InetAddress.getByName(null);
+
+ try {
+ InetAddress.getByName(".0.0.1");
+ fail("expected ex");
+ } catch (UnknownHostException ex) {
+ // expected
+ }
+
+ try {
+ InetAddress.getByName("thereisagoodchancethisdomaindoesnotexist.weirdtld");
+ fail("expected ex");
+ } catch (UnknownHostException ex) {
+ // expected
+ }
+
+ try {
+ InetAddress.getByName("127.0.0.");
+ fail("expected ex");
+ } catch (UnknownHostException ex) {
+ // expected
+ }
+
+ Random random = new Random();
+ int count = 0;
+ for (int i = 0; i < 100; i++) {
+ int index = random.nextInt(HOSTS.length);
+ try {
+ InetAddress.getByName(HOSTS[index]);
+ count++;
+ try {
+ Thread.sleep(50);
+ } catch (InterruptedException ex) {
+ }
+ } catch (UnknownHostException ex) {
+ }
+ }
+ assertEquals("Not all host lookups succeeded", 100, count);
+ }
+}
diff --git a/tests/CoreTests/android/core/InputStreamReaderTest.java b/tests/CoreTests/android/core/InputStreamReaderTest.java
new file mode 100644
index 0000000..1e8d87c
--- /dev/null
+++ b/tests/CoreTests/android/core/InputStreamReaderTest.java
@@ -0,0 +1,114 @@
+/*
+ * 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 android.core;
+
+import junit.framework.TestCase;
+
+import java.io.ByteArrayInputStream;
+import java.io.InputStreamReader;
+import android.test.suitebuilder.annotation.SmallTest;
+
+/**
+ * Checks basic InputStreamReader functionality.
+ */
+public class InputStreamReaderTest extends TestCase {
+
+ /**
+ * Checks if ASCII encoding works with InputStreamReader
+ */
+ @SmallTest
+ public void testAscii() throws Exception {
+ String str = "AbCdEfGhIjKlMnOpQrStUvWxYzX";
+ ByteArrayInputStream aa = new ByteArrayInputStream(str.getBytes("ISO8859_1"));
+ InputStreamReader a = new InputStreamReader(aa, "ISO8859_1");
+
+ try {
+ int x = a.read();
+ assertEquals('A', x);
+ char[] c = new char[26];
+ x = a.read(c, 0, 26);
+ assertTrue(a.getEncoding().equalsIgnoreCase("ISO8859_1"));
+ assertEquals(26, x);
+ assertEquals("bCdEfGhIjKlMnOpQrStUvWxYzX", String.valueOf(c));
+ } finally {
+ a.close();
+ }
+ }
+
+ /**
+ * Checks if Utf8 encoding works with InputStreamReader
+ */
+ @SmallTest
+ public void testUtf8() throws Exception {
+ String str = "AbCdEfGhIjKlMnOpQrStUvWxYzX" +
+ "\u00a3\u00c5\u00c9"; // total of 30 characters
+ ByteArrayInputStream aa =
+ new ByteArrayInputStream(str.getBytes());
+
+ InputStreamReader a = new InputStreamReader(aa);
+
+ try {
+ assertEquals("UTF8", a.getEncoding());
+
+ int x = a.read();
+ assertEquals('A', x);
+
+ char[] c = new char[29];
+ x = a.read(c, 0, 3);
+ assertEquals(3, x);
+ assertEquals("bCd", new String(c, 0, 3));
+
+ x = a.read(c, 3, 26);
+ assertEquals(26, x);
+ assertEquals("EfGhIjKlMnOpQrStUvWxYzX\u00a3\u00c5\u00c9", new String(c, 3, 26));
+ } finally {
+ a.close();
+ }
+ }
+
+ /**
+ * Checks if several encodings works with InputStreamReader
+ */
+ @SmallTest
+ public void testStringy() throws Exception {
+ String src = "The quick brown fox\u00A0\u00FF" +
+ "\uFFFC\uD7C5\uDC03bloof";
+
+ String[] enc = new String[]{
+ "utf-8", "us-ascii", "iso-8859-1", "utf-16be", "utf-16le",
+ "utf-16",
+ };
+
+ for (int i = 0; i < enc.length; i++) {
+ byte[] ba = src.getBytes(enc[i]);
+
+ String s1 = new String(ba, enc[i]);
+
+ ByteArrayInputStream bais = new ByteArrayInputStream(ba);
+ InputStreamReader r = new InputStreamReader(bais, enc[i]);
+ try {
+ char[] ca = new char[600];
+ int n = r.read(ca, 0, 600);
+
+ String s2 = new String(ca, 0, n);
+ assertEquals(s1, s2);
+ } finally {
+ r.close();
+ }
+ }
+ }
+}
diff --git a/tests/CoreTests/android/core/JavaTests.java b/tests/CoreTests/android/core/JavaTests.java
new file mode 100644
index 0000000..bd8cbf0
--- /dev/null
+++ b/tests/CoreTests/android/core/JavaTests.java
@@ -0,0 +1,86 @@
+/*
+ * 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 android.core;
+
+import junit.framework.TestSuite;
+
+public class JavaTests {
+ public static TestSuite suite() {
+ TestSuite suite = new TestSuite(JavaTests.class.getName());
+
+ //Disabling until bug http://b/issue?id=1200337 is resolved
+ //suite.addTestSuite(RequestAPITest.class);
+ suite.addTestSuite(MathTest.class);
+ suite.addTestSuite(StrictMathTest.class);
+ suite.addTestSuite(HashMapPerfTest.class);
+ suite.addTestSuite(TreeMapTest.class);
+ suite.addTestSuite(FloatDoubleTest.class);
+ suite.addTestSuite(Sha1Test.class);
+ suite.addTestSuite(NIOTest.class);
+ suite.addTestSuite(ReflectArrayTest.class);
+ //Commenting out until we find a better way to exclude from continuous testing.
+ //suite.addTestSuite(URLTest.class);
+ suite.addTestSuite(URITest.class);
+ suite.addTestSuite(RegexTest.class);
+ suite.addTestSuite(HashMapTest.class);
+ suite.addTestSuite(ArrayListTest.class);
+ suite.addTestSuite(BooleanTest.class);
+ suite.addTestSuite(StringTest.class);
+ suite.addTestSuite(BufferedReaderTest.class);
+ suite.addTestSuite(CharArrayReaderTest.class);
+ suite.addTestSuite(PushbackReaderTest.class);
+ suite.addTestSuite(StringReaderTest.class);
+ suite.addTestSuite(StreamTokenizerTest.class);
+ suite.addTestSuite(ByteArrayInputStreamTest.class);
+ suite.addTestSuite(DataInputStreamTest.class);
+ suite.addTestSuite(BufferedInputStreamTest.class);
+ suite.addTestSuite(PushbackInputStreamTest.class);
+ suite.addTestSuite(ByteArrayOutputStreamTest.class);
+ suite.addTestSuite(DataOutputStreamTest.class);
+ suite.addTestSuite(BufferedOutputStreamTest.class);
+ suite.addTestSuite(CharArrayWriterTest.class);
+ suite.addTestSuite(StringWriterTest.class);
+ suite.addTestSuite(PrintWriterTest.class);
+ suite.addTestSuite(BufferedWriterTest.class);
+ suite.addTestSuite(ClassTest.class);
+ //To be unccommented when Bug #799327 is fixed.
+ //suite.addTestSuite(ClassLoaderTest.class);
+ suite.addTestSuite(LineNumberReaderTest.class);
+ suite.addTestSuite(InputStreamReaderTest.class);
+ suite.addTestSuite(OutputStreamWriterTest.class);
+ suite.addTestSuite(EnumTest.class);
+ suite.addTestSuite(ParseIntTest.class);
+ suite.addTestSuite(PipedStreamTest.class);
+ suite.addTestSuite(LocaleTest.class);
+ //Commenting out until we find a better way to exclude from continuous testing.
+ //suite.addTestSuite(InetAddrTest.class);
+ suite.addTestSuite(SocketTest.class);
+ suite.addTestSuite(ChecksumTest.class);
+ suite.addTestSuite(DeflateTest.class);
+ suite.addTestSuite(ZipStreamTest.class);
+ suite.addTestSuite(GZIPStreamTest.class);
+ suite.addTestSuite(ZipFileTest.class);
+ suite.addTestSuite(FileTest.class);
+ suite.addTestSuite(SQLiteJDBCDriverTest.class);
+ suite.addTestSuite(AtParserTest.class);
+ suite.addTestSuite(DatagramTest.class);
+ suite.addTestSuite(CryptoTest.class);
+ suite.addTestSuite(MiscRegressionTest.class);
+
+ return suite;
+ }
+}
diff --git a/tests/CoreTests/android/core/LineNumberReaderTest.java b/tests/CoreTests/android/core/LineNumberReaderTest.java
new file mode 100644
index 0000000..6380ebe
--- /dev/null
+++ b/tests/CoreTests/android/core/LineNumberReaderTest.java
@@ -0,0 +1,79 @@
+/*
+ * 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 android.core;
+
+import junit.framework.TestCase;
+
+import java.io.LineNumberReader;
+import java.io.StringReader;
+import android.test.suitebuilder.annotation.MediumTest;
+
+/**
+ * Checks basic functionality for LineNumberReader.
+ */
+public class LineNumberReaderTest extends TestCase {
+
+ @MediumTest
+ public void testLineNumberReader() throws Exception {
+ String str = "AbCdEfGhIjKlM\nOpQrStUvWxYz";
+
+ StringReader aa = new StringReader(str);
+ StringReader ba = new StringReader(str);
+ StringReader ca = new StringReader(str);
+ StringReader da = new StringReader(str);
+ StringReader ea = new StringReader(str);
+
+ LineNumberReader a = new LineNumberReader(aa);
+ try {
+ assertEquals(0, a.getLineNumber());
+ assertEquals(str, IOUtil.read(a));
+ assertEquals(1, a.getLineNumber());
+ a.setLineNumber(5);
+ assertEquals(5, a.getLineNumber());
+ } finally {
+ a.close();
+ }
+
+ LineNumberReader b = new LineNumberReader(ba);
+ try {
+ assertEquals("AbCdEfGhIj", IOUtil.read(b, 10));
+ } finally {
+ b.close();
+ }
+
+ LineNumberReader c = new LineNumberReader(ca);
+ try {
+ assertEquals("bdfhjl\nprtvxz", IOUtil.skipRead(c));
+ } finally {
+ c.close();
+ }
+
+ LineNumberReader d = new LineNumberReader(da);
+ try {
+ assertEquals("AbCdEfGdEfGhIjKlM\nOpQrStUvWxYz", IOUtil.markRead(d, 3, 4));
+ } finally {
+ d.close();
+ }
+
+ LineNumberReader e = new LineNumberReader(ea);
+ try {
+ assertEquals("AbCdEfGhIjKlM", e.readLine());
+ } finally {
+ e.close();
+ }
+ }
+}
diff --git a/tests/CoreTests/android/core/LocaleTest.java b/tests/CoreTests/android/core/LocaleTest.java
new file mode 100644
index 0000000..700cf1d
--- /dev/null
+++ b/tests/CoreTests/android/core/LocaleTest.java
@@ -0,0 +1,199 @@
+/*
+ * 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 android.core;
+
+import junit.framework.TestCase;
+
+import java.nio.charset.Charset;
+import java.text.DateFormatSymbols;
+import java.util.Calendar;
+import java.util.Currency;
+import java.util.Locale;
+import java.util.Set;
+import java.util.TimeZone;
+import android.test.suitebuilder.annotation.MediumTest;
+import android.test.suitebuilder.annotation.SmallTest;
+import android.test.suitebuilder.annotation.LargeTest;
+
+/**
+ * Test some locale-dependent stuff for Android. This test mainly ensures that
+ * our ICU configuration is correct and contains all the needed locales and
+ * resource bundles.
+ */
+public class LocaleTest extends TestCase {
+
+ // Test basic Locale infrastructure.
+ @SmallTest
+ public void testLocale() throws Exception {
+ Locale locale = new Locale("en");
+ assertEquals("en", locale.toString());
+
+ locale = new Locale("en", "US");
+ assertEquals("en_US", locale.toString());
+
+ locale = new Locale("en", "", "POSIX");
+ assertEquals("en__POSIX", locale.toString());
+
+ locale = new Locale("en", "US", "POSIX");
+ assertEquals("en_US_POSIX", locale.toString());
+ }
+
+ // Test some must-have locales.
+ @LargeTest
+ public void testResourceBundles() throws Exception {
+ Locale eng = new Locale("en", "US");
+ DateFormatSymbols engSymbols = new DateFormatSymbols(eng);
+
+ Locale deu = new Locale("de", "DE");
+ DateFormatSymbols deuSymbols = new DateFormatSymbols(deu);
+
+ TimeZone berlin = TimeZone.getTimeZone("Europe/Berlin");
+
+ assertEquals("January", engSymbols.getMonths()[0]);
+ assertEquals("Januar", deuSymbols.getMonths()[0]);
+
+ assertEquals("Sunday", engSymbols.getWeekdays()[Calendar.SUNDAY]);
+ assertEquals("Sonntag", deuSymbols.getWeekdays()[Calendar.SUNDAY]);
+
+ assertEquals("Central European Time",
+ berlin.getDisplayName(false, TimeZone.LONG, eng));
+ assertEquals("Central European Summer Time",
+ berlin.getDisplayName(true, TimeZone.LONG, eng));
+
+ assertEquals("Mitteleurop\u00E4ische Zeit",
+ berlin.getDisplayName(false, TimeZone.LONG, deu));
+ assertEquals("Mitteleurop\u00E4ische Sommerzeit",
+ berlin.getDisplayName(true, TimeZone.LONG, deu));
+
+ assertTrue(engSymbols.getZoneStrings().length > 100);
+ }
+
+ // Regression test for 1118570: Create test cases for tracking ICU config
+ // changes. This one makes sure we have all necessary locales installed.
+ @MediumTest
+ public void testICULocales() {
+ String[] locales = new String[] {
+ // List of locales currently required for Android.
+ "en_US", "es_US", "en_GB", "fr_FR", "de_DE", "de_AT", "cs_CZ", "nl_NL" };
+
+ String[] mondays = new String[] {
+ "Monday", "lunes", "Monday", "lundi", "Montag", "Montag", "pond\u011bl\u00ed", "maandag" };
+
+ String[] currencies = new String[] {
+ "USD", "USD", "GBP", "EUR", "EUR", "EUR", "CZK", "EUR"};
+
+ for (int i = 0; i < locales.length; i++) {
+ Locale l = new Locale(locales[i].substring(0, 2), locales[i].substring(3));
+
+ // Check language part of locale.
+ DateFormatSymbols d = new DateFormatSymbols(l);
+ assertEquals("Monday name for " + locales[i] + " must match",
+ mondays[i], d.getWeekdays()[2]);
+
+ // Check country part of locale.
+ Currency c = Currency.getInstance(l);
+ assertEquals("Currency code for " + locales[i] + " must match",
+ currencies[i], c.getCurrencyCode());
+ }
+ }
+
+ // Regression test for 1118570: Create test cases for tracking ICU config
+ // changes. This one makes sure we have the necessary converters installed
+ // and don't lose the changes to the converter alias table.
+ @MediumTest
+ public void testICUConverters() {
+ // List of encodings currently required for Android.
+ String[] encodings = new String[] {
+ // Encoding required by the language specification.
+ "US-ASCII",
+ "UTF-8",
+ "UTF-16",
+ "UTF-16BE",
+ "UTF-16LE",
+ "ISO-8859-1",
+
+ // Additional encodings included in standard ICU
+ "ISO-8859-2",
+ "ISO-8859-3",
+ "ISO-8859-4",
+ "ISO-8859-5",
+ "ISO-8859-6",
+ "ISO-8859-7",
+ "ISO-8859-8",
+ "ISO-8859-8-I",
+ "ISO-8859-9",
+ "ISO-8859-10",
+ "ISO-8859-11",
+ "ISO-8859-13",
+ "ISO-8859-14",
+ "ISO-8859-15",
+ "ISO-8859-16",
+ "ISO-2022-JP",
+ "Windows-950",
+ "Windows-1250",
+ "Windows-1251",
+ "Windows-1252",
+ "Windows-1253",
+ "Windows-1254",
+ "Windows-1255",
+ "Windows-1256",
+ "Windows-1257",
+ "Windows-1258",
+ "Big5",
+ "CP864",
+ "CP874",
+ "EUC-CN",
+ "EUC-JP",
+ "KOI8-R",
+ "Macintosh",
+ "GBK",
+ "GB2312",
+ "EUC-KR",
+
+ // Additional encoding not included in standard ICU.
+ "GSM0338" };
+
+ for (int i = 0; i < encodings.length; i++) {
+ assertTrue("Charset " + encodings[i] + " must be supported",
+ Charset.isSupported(encodings[i]));
+
+ Charset cs = Charset.forName(encodings[i]);
+ android.util.Log.d("LocaleTest", cs.name());
+
+ Set<String> aliases = cs.aliases();
+ for (String s: aliases) {
+ android.util.Log.d("LocaleTest", " - " + s);
+ }
+ }
+
+ // Test for valid encoding that is not included in Android. IBM-37 is
+ // a perfect candidate for this, as it is being used for mainframes and
+ // thus somewhat out of the scope of Android.
+ assertFalse("Charset IBM-37 must not be supported",
+ Charset.isSupported("IBM-37"));
+
+ // Test for a bogus encoding.
+ assertFalse("Charset KLINGON must not be supported",
+ Charset.isSupported("KLINGON"));
+
+ // Make sure our local change to the real translation table used for
+ // EUC-JP doesn't get lost.
+ Charset cs = Charset.forName("EUC-JP");
+ assertTrue("EUC-JP must use 'ibm-954_P101-2007'", cs.aliases().contains("ibm-954_P101-2007"));
+ }
+
+}
diff --git a/tests/CoreTests/android/core/LowLevelNetRunner.java b/tests/CoreTests/android/core/LowLevelNetRunner.java
new file mode 100644
index 0000000..812ceb5
--- /dev/null
+++ b/tests/CoreTests/android/core/LowLevelNetRunner.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2007 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 android.core;
+
+/**
+ * Provides synchronization handling for low level Request API tests
+ */
+public class LowLevelNetRunner extends Thread {
+
+ private int count = 0;
+
+ LowLevelNetRunner() {
+ }
+
+ public void incrementRunCount() {
+ count++;
+ }
+
+ /**
+ * Decrement the run count. If this returns to zero notify any
+ * test waiting.
+ */
+ public void decrementRunCount() {
+ count--;
+ if (count <= 0) {
+ synchronized (RequestAPITest.syncObj) {
+ RequestAPITest.syncObj.notifyAll();
+ }
+ }
+ }
+
+} /* LowLevelNetRunner*/
diff --git a/tests/CoreTests/android/core/MathTest.java b/tests/CoreTests/android/core/MathTest.java
new file mode 100644
index 0000000..50009db
--- /dev/null
+++ b/tests/CoreTests/android/core/MathTest.java
@@ -0,0 +1,831 @@
+/*
+ * 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.
+ */
+
+package android.core;
+
+import junit.framework.Assert;
+import junit.framework.TestCase;
+import android.test.suitebuilder.annotation.SmallTest;
+import android.test.suitebuilder.annotation.MediumTest;
+
+public class MathTest extends TestCase {
+
+ private final double HYP = Math.sqrt(2.0);
+
+ private final double OPP = 1.0;
+
+ private final double ADJ = 1.0;
+
+ /* Required to make previous preprocessor flags work - do not remove */
+ int unused = 0;
+
+ public static void assertEquals(String message, double expected, double actual, double delta) {
+ if (delta == 0D) {
+ Assert.assertEquals(message, expected, actual, Math.ulp(expected));
+ } else {
+ Assert.assertEquals(message, expected, actual, delta);
+ }
+ }
+
+ public static void assertEquals(String message, float expected, float actual, float delta) {
+ if (delta == 0F) {
+ Assert.assertEquals(message, expected, actual, Math.ulp(expected));
+ } else {
+ Assert.assertEquals(message, expected, actual, delta);
+ }
+ }
+
+ /**
+ * @tests java.lang.Math#abs(double)
+ */
+ @SmallTest
+ public void testAbsD() {
+ // Test for method double java.lang.Math.abs(double)
+
+ assertTrue("Incorrect double abs value",
+ (Math.abs(-1908.8976) == 1908.8976));
+ assertTrue("Incorrect double abs value",
+ (Math.abs(1908.8976) == 1908.8976));
+ }
+
+ /**
+ * @tests java.lang.Math#abs(float)
+ */
+ @SmallTest
+ public void testAbsF() {
+ // Test for method float java.lang.Math.abs(float)
+ assertTrue("Incorrect float abs value",
+ (Math.abs(-1908.8976f) == 1908.8976f));
+ assertTrue("Incorrect float abs value",
+ (Math.abs(1908.8976f) == 1908.8976f));
+ }
+
+ /**
+ * @tests java.lang.Math#abs(int)
+ */
+ @SmallTest
+ public void testAbsI() {
+ // Test for method int java.lang.Math.abs(int)
+ assertTrue("Incorrect int abs value", (Math.abs(-1908897) == 1908897));
+ assertTrue("Incorrect int abs value", (Math.abs(1908897) == 1908897));
+ }
+
+ /**
+ * @tests java.lang.Math#abs(long)
+ */
+ @SmallTest
+ public void testAbsJ() {
+ // Test for method long java.lang.Math.abs(long)
+ assertTrue("Incorrect long abs value",
+ (Math.abs(-19088976000089L) == 19088976000089L));
+ assertTrue("Incorrect long abs value",
+ (Math.abs(19088976000089L) == 19088976000089L));
+ }
+
+ /**
+ * @tests java.lang.Math#acos(double)
+ */
+ @SmallTest
+ public void testAcosD() {
+ // Test for method double java.lang.Math.acos(double)
+ double r = Math.cos(Math.acos(ADJ / HYP));
+ long lr = Double.doubleToLongBits(r);
+ long t = Double.doubleToLongBits(ADJ / HYP);
+ assertTrue("Returned incorrect arc cosine", lr == t || (lr + 1) == t
+ || (lr - 1) == t);
+ }
+
+ /**
+ * @tests java.lang.Math#asin(double)
+ */
+ @SmallTest
+ public void testAsinD() {
+ // Test for method double java.lang.Math.asin(double)
+ double r = Math.sin(Math.asin(OPP / HYP));
+ long lr = Double.doubleToLongBits(r);
+ long t = Double.doubleToLongBits(OPP / HYP);
+ assertTrue("Returned incorrect arc sine", lr == t || (lr + 1) == t
+ || (lr - 1) == t);
+ }
+
+ /**
+ * @tests java.lang.Math#atan(double)
+ */
+ @SmallTest
+ public void testAtanD() {
+ // Test for method double java.lang.Math.atan(double)
+ double answer = Math.tan(Math.atan(1.0));
+ assertTrue("Returned incorrect arc tangent: " + answer, answer <= 1.0
+ && answer >= 9.9999999999999983E-1);
+ }
+
+ /**
+ * @tests java.lang.Math#atan2(double, double)
+ */
+ @SmallTest
+ public void testAtan2DD() {
+ // Test for method double java.lang.Math.atan2(double, double)
+ double answer = Math.atan(Math.tan(1.0));
+ assertTrue("Returned incorrect arc tangent: " + answer, answer <= 1.0
+ && answer >= 9.9999999999999983E-1);
+ }
+
+ /**
+ * @tests java.lang.Math#cbrt(double)
+ */
+ @SmallTest
+ public void testCbrtD() {
+ //Test for special situations
+ assertTrue("Should return Double.NaN", Double.isNaN(Math
+ .cbrt(Double.NaN)));
+ assertEquals("Should return Double.POSITIVE_INFINITY",
+ Double.POSITIVE_INFINITY, Math
+ .cbrt(Double.POSITIVE_INFINITY), 0D);
+ assertEquals("Should return Double.NEGATIVE_INFINITY",
+ Double.NEGATIVE_INFINITY, Math
+ .cbrt(Double.NEGATIVE_INFINITY), 0D);
+ assertEquals(Double.doubleToLongBits(0.0), Double.doubleToLongBits(Math
+ .cbrt(0.0)));
+ assertEquals(Double.doubleToLongBits(+0.0), Double.doubleToLongBits(Math
+ .cbrt(+0.0)));
+ assertEquals(Double.doubleToLongBits(-0.0), Double.doubleToLongBits(Math
+ .cbrt(-0.0)));
+
+ assertEquals("Should return 3.0", 3.0, Math.cbrt(27.0), 0D);
+ assertEquals("Should return 23.111993172558684", 23.111993172558684,
+ Math.cbrt(12345.6), 0D);
+ assertEquals("Should return 5.643803094122362E102",
+ 5.643803094122362E102, Math.cbrt(Double.MAX_VALUE), 0D);
+ assertEquals("Should return 0.01", 0.01, Math.cbrt(0.000001), 0D);
+
+ assertEquals("Should return -3.0", -3.0, Math.cbrt(-27.0), 0D);
+ assertEquals("Should return -23.111993172558684", -23.111993172558684,
+ Math.cbrt(-12345.6), 0D);
+ assertEquals("Should return 1.7031839360032603E-108",
+ 1.7031839360032603E-108, Math.cbrt(Double.MIN_VALUE), 0D);
+ assertEquals("Should return -0.01", -0.01, Math.cbrt(-0.000001), 0D);
+ }
+
+ /**
+ * @tests java.lang.Math#ceil(double)
+ */
+ @SmallTest
+ public void testCeilD() {
+ // Test for method double java.lang.Math.ceil(double)
+ assertEquals("Incorrect ceiling for double",
+ 79, Math.ceil(78.89), 0);
+ assertEquals("Incorrect ceiling for double",
+ -78, Math.ceil(-78.89), 0);
+ }
+
+ /**
+ * @tests java.lang.Math#cos(double)
+ */
+ @SmallTest
+ public void testCosD() {
+ // Test for method double java.lang.Math.cos(double)
+ assertEquals("Incorrect answer", 1.0, Math.cos(0), 0D);
+ assertEquals("Incorrect answer", 0.5403023058681398, Math.cos(1), 0D);
+ }
+
+ /**
+ * @tests java.lang.Math#cosh(double)
+ */
+ @SmallTest
+ public void testCoshD() {
+ // Test for special situations
+ assertTrue(Double.isNaN(Math.cosh(Double.NaN)));
+ assertEquals("Should return POSITIVE_INFINITY",
+ Double.POSITIVE_INFINITY, Math.cosh(Double.POSITIVE_INFINITY), 0D);
+ assertEquals("Should return POSITIVE_INFINITY",
+ Double.POSITIVE_INFINITY, Math.cosh(Double.NEGATIVE_INFINITY), 0D);
+ assertEquals("Should return 1.0", 1.0, Math.cosh(+0.0), 0D);
+ assertEquals("Should return 1.0", 1.0, Math.cosh(-0.0), 0D);
+
+ assertEquals("Should return POSITIVE_INFINITY",
+ Double.POSITIVE_INFINITY, Math.cosh(1234.56), 0D);
+ assertEquals("Should return POSITIVE_INFINITY",
+ Double.POSITIVE_INFINITY, Math.cosh(-1234.56), 0D);
+ assertEquals("Should return 1.0000000000005", 1.0000000000005, Math
+ .cosh(0.000001), 0D);
+ assertEquals("Should return 1.0000000000005", 1.0000000000005, Math
+ .cosh(-0.000001), 0D);
+ assertEquals("Should return 5.212214351945598", 5.212214351945598, Math
+ .cosh(2.33482), 0D);
+
+ assertEquals("Should return POSITIVE_INFINITY",
+ Double.POSITIVE_INFINITY, Math.cosh(Double.MAX_VALUE), 0D);
+ assertEquals("Should return 1.0", 1.0, Math.cosh(Double.MIN_VALUE), 0D);
+ }
+
+ /**
+ * @tests java.lang.Math#exp(double)
+ */
+ @SmallTest
+ public void testExpD() {
+ // Test for method double java.lang.Math.exp(double)
+ assertTrue("Incorrect answer returned for simple power", Math.abs(Math
+ .exp(4D)
+ - Math.E * Math.E * Math.E * Math.E) < 0.1D);
+ assertTrue("Incorrect answer returned for larger power", Math.log(Math
+ .abs(Math.exp(5.5D)) - 5.5D) < 10.0D);
+ }
+
+ /**
+ * @tests java.lang.Math#expm1(double)
+ */
+ @SmallTest
+ public void testExpm1D() {
+ // Test for special cases
+ assertTrue("Should return NaN", Double.isNaN(Math.expm1(Double.NaN)));
+ assertEquals("Should return POSITIVE_INFINITY",
+ Double.POSITIVE_INFINITY, Math.expm1(Double.POSITIVE_INFINITY), 0D);
+ assertEquals("Should return -1.0", -1.0, Math
+ .expm1(Double.NEGATIVE_INFINITY), 0D);
+ assertEquals(Double.doubleToLongBits(0.0), Double.doubleToLongBits(Math
+ .expm1(0.0)));
+ assertEquals(Double.doubleToLongBits(+0.0), Double
+ .doubleToLongBits(Math.expm1(+0.0)));
+ assertEquals(Double.doubleToLongBits(-0.0), Double
+ .doubleToLongBits(Math.expm1(-0.0)));
+
+ assertEquals("Should return -9.999950000166666E-6",
+ -9.999950000166666E-6, Math.expm1(-0.00001), 0D);
+ assertEquals("Should return 1.0145103074469635E60",
+ 1.0145103074469635E60, Math.expm1(138.16951162), 0D);
+ assertEquals("Should return POSITIVE_INFINITY",
+ Double.POSITIVE_INFINITY, Math
+ .expm1(123456789123456789123456789.4521584223), 0D);
+ assertEquals("Should return POSITIVE_INFINITY",
+ Double.POSITIVE_INFINITY, Math.expm1(Double.MAX_VALUE), 0D);
+ assertEquals("Should return MIN_VALUE", Double.MIN_VALUE, Math
+ .expm1(Double.MIN_VALUE), 0D);
+ }
+
+ /**
+ * @tests java.lang.Math#floor(double)
+ */
+ @SmallTest
+ public void testFloorD() {
+ // Test for method double java.lang.Math.floor(double)
+ assertEquals("Incorrect floor for double",
+ 78, Math.floor(78.89), 0);
+ assertEquals("Incorrect floor for double",
+ -79, Math.floor(-78.89), 0);
+ }
+
+ /**
+ * @tests java.lang.Math#hypot(double, double)
+ */
+ @SmallTest
+ public void testHypotDD() {
+ // Test for special cases
+ assertEquals("Should return POSITIVE_INFINITY",
+ Double.POSITIVE_INFINITY, Math.hypot(Double.POSITIVE_INFINITY,
+ 1.0), 0D);
+ assertEquals("Should return POSITIVE_INFINITY",
+ Double.POSITIVE_INFINITY, Math.hypot(Double.NEGATIVE_INFINITY,
+ 123.324), 0D);
+ assertEquals("Should return POSITIVE_INFINITY",
+ Double.POSITIVE_INFINITY, Math.hypot(-758.2587,
+ Double.POSITIVE_INFINITY), 0D);
+ assertEquals("Should return POSITIVE_INFINITY",
+ Double.POSITIVE_INFINITY, Math.hypot(5687.21,
+ Double.NEGATIVE_INFINITY), 0D);
+ assertEquals("Should return POSITIVE_INFINITY",
+ Double.POSITIVE_INFINITY, Math.hypot(Double.POSITIVE_INFINITY,
+ Double.NEGATIVE_INFINITY), 0D);
+ assertEquals("Should return POSITIVE_INFINITY",
+ Double.POSITIVE_INFINITY, Math.hypot(Double.NEGATIVE_INFINITY,
+ Double.POSITIVE_INFINITY), 0D);
+ assertTrue("Should be NaN", Double.isNaN(Math.hypot(Double.NaN,
+ 2342301.89843)));
+ assertTrue("Should be NaN", Double.isNaN(Math.hypot(-345.2680,
+ Double.NaN)));
+
+ assertEquals("Should return 2396424.905416697", 2396424.905416697, Math
+ .hypot(12322.12, -2396393.2258), 0D);
+ assertEquals("Should return 138.16958070558556", 138.16958070558556,
+ Math.hypot(-138.16951162, 0.13817035864), 0D);
+ assertEquals("Should return 1.7976931348623157E308",
+ 1.7976931348623157E308, Math.hypot(Double.MAX_VALUE, 211370.35), 0D);
+ assertEquals("Should return 5413.7185", 5413.7185, Math.hypot(
+ -5413.7185, Double.MIN_VALUE), 0D);
+ }
+
+ /**
+ * @tests java.lang.Math#IEEEremainder(double, double)
+ */
+ @SmallTest
+ public void testIEEEremainderDD() {
+ // Test for method double java.lang.Math.IEEEremainder(double, double)
+ assertEquals("Incorrect remainder returned",
+ 0.0, Math.IEEEremainder(1.0, 1.0), 0D);
+ assertTrue("Incorrect remainder returned", Math.IEEEremainder(1.32,
+ 89.765) >= 1.4705063220631647E-2
+ || Math.IEEEremainder(1.32, 89.765) >= 1.4705063220631649E-2);
+ }
+
+ /**
+ * @tests java.lang.Math#log(double)
+ */
+ @SmallTest
+ public void testLogD() {
+ // Test for method double java.lang.Math.log(double)
+ for (double d = 10; d >= -10; d -= 0.5) {
+ double answer = Math.log(Math.exp(d));
+ assertTrue("Answer does not equal expected answer for d = " + d
+ + " answer = " + answer, Math.abs(answer - d) <= Math
+ .abs(d * 0.00000001));
+ }
+ }
+
+ /**
+ * @tests java.lang.Math#log10(double)
+ */
+ @SuppressWarnings("boxing")
+ @SmallTest
+ public void testLog10D() {
+ // Test for special cases
+ assertTrue(Double.isNaN(Math.log10(Double.NaN)));
+ assertTrue(Double.isNaN(Math.log10(-2541.05745687234187532)));
+ assertTrue(Double.isNaN(Math.log10(-0.1)));
+ assertEquals(Double.POSITIVE_INFINITY, Math.log10(Double.POSITIVE_INFINITY));
+ assertEquals(Double.NEGATIVE_INFINITY, Math.log10(0.0));
+ assertEquals(Double.NEGATIVE_INFINITY, Math.log10(+0.0));
+ assertEquals(Double.NEGATIVE_INFINITY, Math.log10(-0.0));
+
+ assertEquals(3.0, Math.log10(1000.0));
+ assertEquals(14.0, Math.log10(Math.pow(10, 14)));
+ assertEquals(3.7389561269540406, Math.log10(5482.2158));
+ assertEquals(14.661551142893833, Math.log10(458723662312872.125782332587));
+ assertEquals(-0.9083828622192334, Math.log10(0.12348583358871));
+ assertEquals(308.25471555991675, Math.log10(Double.MAX_VALUE));
+ assertEquals(-323.3062153431158, Math.log10(Double.MIN_VALUE));
+ }
+
+ /**
+ * @tests java.lang.Math#log1p(double)
+ */
+ @SmallTest
+ public void testLog1pD() {
+ // Test for special cases
+ assertTrue("Should return NaN", Double.isNaN(Math.log1p(Double.NaN)));
+ assertTrue("Should return NaN", Double.isNaN(Math.log1p(-32.0482175)));
+ assertEquals("Should return POSITIVE_INFINITY",
+ Double.POSITIVE_INFINITY, Math.log1p(Double.POSITIVE_INFINITY), 0D);
+ assertEquals(Double.doubleToLongBits(0.0), Double.doubleToLongBits(Math
+ .log1p(0.0)));
+ assertEquals(Double.doubleToLongBits(+0.0), Double
+ .doubleToLongBits(Math.log1p(+0.0)));
+ assertEquals(Double.doubleToLongBits(-0.0), Double
+ .doubleToLongBits(Math.log1p(-0.0)));
+
+ assertEquals("Should return -0.2941782295312541", -0.2941782295312541,
+ Math.log1p(-0.254856327), 0D);
+ assertEquals("Should return 7.368050685564151", 7.368050685564151, Math
+ .log1p(1583.542), 0D);
+ assertEquals("Should return 0.4633708685409921", 0.4633708685409921,
+ Math.log1p(0.5894227), 0D);
+ assertEquals("Should return 709.782712893384", 709.782712893384, Math
+ .log1p(Double.MAX_VALUE), 0D);
+ assertEquals("Should return Double.MIN_VALUE", Double.MIN_VALUE, Math
+ .log1p(Double.MIN_VALUE), 0D);
+ }
+
+ /**
+ * @tests java.lang.Math#max(double, double)
+ */
+ @SmallTest
+ public void testMaxDD() {
+ // Test for method double java.lang.Math.max(double, double)
+ assertEquals("Incorrect double max value", 1908897.6000089, Math.max(-1908897.6000089,
+ 1908897.6000089), 0D);
+ assertEquals("Incorrect double max value",
+ 1908897.6000089, Math.max(2.0, 1908897.6000089), 0D);
+ assertEquals("Incorrect double max value", -2.0, Math.max(-2.0,
+ -1908897.6000089), 0D);
+
+ }
+
+ /**
+ * @tests java.lang.Math#max(float, float)
+ */
+ @SmallTest
+ public void testMaxFF() {
+ // Test for method float java.lang.Math.max(float, float)
+ assertTrue("Incorrect float max value", Math.max(-1908897.600f,
+ 1908897.600f) == 1908897.600f);
+ assertTrue("Incorrect float max value",
+ Math.max(2.0f, 1908897.600f) == 1908897.600f);
+ assertTrue("Incorrect float max value",
+ Math.max(-2.0f, -1908897.600f) == -2.0f);
+ }
+
+ /**
+ * @tests java.lang.Math#max(int, int)
+ */
+ @SmallTest
+ public void testMaxII() {
+ // Test for method int java.lang.Math.max(int, int)
+ assertEquals("Incorrect int max value",
+ 19088976, Math.max(-19088976, 19088976));
+ assertEquals("Incorrect int max value",
+ 19088976, Math.max(20, 19088976));
+ assertEquals("Incorrect int max value", -20, Math.max(-20, -19088976));
+ }
+
+ /**
+ * @tests java.lang.Math#max(long, long)
+ */
+ @SmallTest
+ public void testMaxJJ() {
+ // Test for method long java.lang.Math.max(long, long)
+ assertEquals("Incorrect long max value", 19088976000089L, Math.max(-19088976000089L,
+ 19088976000089L));
+ assertEquals("Incorrect long max value",
+ 19088976000089L, Math.max(20, 19088976000089L));
+ assertEquals("Incorrect long max value",
+ -20, Math.max(-20, -19088976000089L));
+ }
+
+ /**
+ * @tests java.lang.Math#min(double, double)
+ */
+ @SmallTest
+ public void testMinDD() {
+ // Test for method double java.lang.Math.min(double, double)
+ assertEquals("Incorrect double min value", -1908897.6000089, Math.min(-1908897.6000089,
+ 1908897.6000089), 0D);
+ assertEquals("Incorrect double min value",
+ 2.0, Math.min(2.0, 1908897.6000089), 0D);
+ assertEquals("Incorrect double min value", -1908897.6000089, Math.min(-2.0,
+ -1908897.6000089), 0D);
+ }
+
+ /**
+ * @tests java.lang.Math#min(float, float)
+ */
+ @SmallTest
+ public void testMinFF() {
+ // Test for method float java.lang.Math.min(float, float)
+ assertTrue("Incorrect float min value", Math.min(-1908897.600f,
+ 1908897.600f) == -1908897.600f);
+ assertTrue("Incorrect float min value",
+ Math.min(2.0f, 1908897.600f) == 2.0f);
+ assertTrue("Incorrect float min value",
+ Math.min(-2.0f, -1908897.600f) == -1908897.600f);
+ }
+
+ /**
+ * @tests java.lang.Math#min(int, int)
+ */
+ @SmallTest
+ public void testMinII() {
+ // Test for method int java.lang.Math.min(int, int)
+ assertEquals("Incorrect int min value",
+ -19088976, Math.min(-19088976, 19088976));
+ assertEquals("Incorrect int min value", 20, Math.min(20, 19088976));
+ assertEquals("Incorrect int min value",
+ -19088976, Math.min(-20, -19088976));
+
+ }
+
+ /**
+ * @tests java.lang.Math#min(long, long)
+ */
+ @SmallTest
+ public void testMinJJ() {
+ // Test for method long java.lang.Math.min(long, long)
+ assertEquals("Incorrect long min value", -19088976000089L, Math.min(-19088976000089L,
+ 19088976000089L));
+ assertEquals("Incorrect long min value",
+ 20, Math.min(20, 19088976000089L));
+ assertEquals("Incorrect long min value",
+ -19088976000089L, Math.min(-20, -19088976000089L));
+ }
+
+ /**
+ * @tests java.lang.Math#pow(double, double)
+ */
+ @SmallTest
+ public void testPowDD() {
+ // Test for method double java.lang.Math.pow(double, double)
+ assertTrue("pow returned incorrect value",
+ (long) Math.pow(2, 8) == 256l);
+ assertTrue("pow returned incorrect value",
+ Math.pow(2, -8) == 0.00390625d);
+ assertEquals("Incorrect root returned1",
+ 2, Math.sqrt(Math.pow(Math.sqrt(2), 4)), 0);
+ }
+
+ /**
+ * @tests java.lang.Math#rint(double)
+ */
+ @SmallTest
+ public void testRintD() {
+ // Test for method double java.lang.Math.rint(double)
+ assertEquals("Failed to round properly - up to odd",
+ 3.0, Math.rint(2.9), 0D);
+ assertTrue("Failed to round properly - NaN", Double.isNaN(Math
+ .rint(Double.NaN)));
+ assertEquals("Failed to round properly down to even",
+ 2.0, Math.rint(2.1), 0D);
+ assertTrue("Failed to round properly " + 2.5 + " to even", Math
+ .rint(2.5) == 2.0);
+ }
+
+ /**
+ * @tests java.lang.Math#round(double)
+ */
+ @SmallTest
+ public void testRoundD() {
+ // Test for method long java.lang.Math.round(double)
+ assertEquals("Incorrect rounding of a float", -91, Math.round(-90.89d));
+ }
+
+ /**
+ * @tests java.lang.Math#round(float)
+ */
+ @SmallTest
+ public void testRoundF() {
+ // Test for method int java.lang.Math.round(float)
+ assertEquals("Incorrect rounding of a float", -91, Math.round(-90.89f));
+ }
+
+ /**
+ * @tests java.lang.Math#signum(double)
+ */
+ @SmallTest
+ public void testSignumD() {
+ assertTrue(Double.isNaN(Math.signum(Double.NaN)));
+ assertTrue(Double.isNaN(Math.signum(Double.NaN)));
+ assertEquals(Double.doubleToLongBits(0.0), Double.doubleToLongBits(Math
+ .signum(0.0)));
+ assertEquals(Double.doubleToLongBits(+0.0), Double
+ .doubleToLongBits(Math.signum(+0.0)));
+ assertEquals(Double.doubleToLongBits(-0.0), Double
+ .doubleToLongBits(Math.signum(-0.0)));
+
+ assertEquals(1.0, Math.signum(253681.2187962), 0D);
+ assertEquals(-1.0, Math.signum(-125874693.56), 0D);
+ assertEquals(1.0, Math.signum(1.2587E-308), 0D);
+ assertEquals(-1.0, Math.signum(-1.2587E-308), 0D);
+
+ assertEquals(1.0, Math.signum(Double.MAX_VALUE), 0D);
+ assertEquals(1.0, Math.signum(Double.MIN_VALUE), 0D);
+ assertEquals(-1.0, Math.signum(-Double.MAX_VALUE), 0D);
+ assertEquals(-1.0, Math.signum(-Double.MIN_VALUE), 0D);
+ assertEquals(1.0, Math.signum(Double.POSITIVE_INFINITY), 0D);
+ assertEquals(-1.0, Math.signum(Double.NEGATIVE_INFINITY), 0D);
+ }
+
+ /**
+ * @tests java.lang.Math#signum(float)
+ */
+ @SmallTest
+ public void testSignumF() {
+ assertTrue(Float.isNaN(Math.signum(Float.NaN)));
+ assertEquals(Float.floatToIntBits(0.0f), Float
+ .floatToIntBits(Math.signum(0.0f)));
+ assertEquals(Float.floatToIntBits(+0.0f), Float
+ .floatToIntBits(Math.signum(+0.0f)));
+ assertEquals(Float.floatToIntBits(-0.0f), Float
+ .floatToIntBits(Math.signum(-0.0f)));
+
+ assertEquals(1.0f, Math.signum(253681.2187962f), 0f);
+ assertEquals(-1.0f, Math.signum(-125874693.56f), 0f);
+ assertEquals(1.0f, Math.signum(1.2587E-11f), 0f);
+ assertEquals(-1.0f, Math.signum(-1.2587E-11f), 0f);
+
+ assertEquals(1.0f, Math.signum(Float.MAX_VALUE), 0f);
+ assertEquals(1.0f, Math.signum(Float.MIN_VALUE), 0f);
+ assertEquals(-1.0f, Math.signum(-Float.MAX_VALUE), 0f);
+ assertEquals(-1.0f, Math.signum(-Float.MIN_VALUE), 0f);
+ assertEquals(1.0f, Math.signum(Float.POSITIVE_INFINITY), 0f);
+ assertEquals(-1.0f, Math.signum(Float.NEGATIVE_INFINITY), 0f);
+ }
+
+ /**
+ * @tests java.lang.Math#sin(double)
+ */
+ @SmallTest
+ public void testSinD() {
+ // Test for method double java.lang.Math.sin(double)
+ assertEquals("Incorrect answer", 0.0, Math.sin(0), 0D);
+ assertEquals("Incorrect answer", 0.8414709848078965, Math.sin(1), 0D);
+ }
+
+ /**
+ * @tests java.lang.Math#sinh(double)
+ */
+ @SmallTest
+ public void testSinhD() {
+ // Test for special situations
+ assertTrue("Should return NaN", Double.isNaN(Math.sinh(Double.NaN)));
+ assertEquals("Should return POSITIVE_INFINITY",
+ Double.POSITIVE_INFINITY, Math.sinh(Double.POSITIVE_INFINITY), 0D);
+ assertEquals("Should return NEGATIVE_INFINITY",
+ Double.NEGATIVE_INFINITY, Math.sinh(Double.NEGATIVE_INFINITY), 0D);
+ assertEquals(Double.doubleToLongBits(0.0), Double.doubleToLongBits(Math
+ .sinh(0.0)));
+ assertEquals(Double.doubleToLongBits(+0.0), Double
+ .doubleToLongBits(Math.sinh(+0.0)));
+ assertEquals(Double.doubleToLongBits(-0.0), Double
+ .doubleToLongBits(Math.sinh(-0.0)));
+
+ assertEquals("Should return POSITIVE_INFINITY",
+ Double.POSITIVE_INFINITY, Math.sinh(1234.56), 0D);
+ assertEquals("Should return NEGATIVE_INFINITY",
+ Double.NEGATIVE_INFINITY, Math.sinh(-1234.56), 0D);
+ assertEquals("Should return 1.0000000000001666E-6",
+ 1.0000000000001666E-6, Math.sinh(0.000001), 0D);
+ assertEquals("Should return -1.0000000000001666E-6",
+ -1.0000000000001666E-6, Math.sinh(-0.000001), 0D);
+ assertEquals("Should return 5.115386441963859", 5.115386441963859, Math
+ .sinh(2.33482), 0D);
+ assertEquals("Should return POSITIVE_INFINITY",
+ Double.POSITIVE_INFINITY, Math.sinh(Double.MAX_VALUE), 0D);
+ assertEquals("Should return 4.9E-324", 4.9E-324, Math
+ .sinh(Double.MIN_VALUE), 0D);
+ }
+
+ /**
+ * @tests java.lang.Math#sqrt(double)
+ */
+ @SmallTest
+ public void testSqrtD() {
+ // Test for method double java.lang.Math.sqrt(double)
+ assertEquals("Incorrect root returned2", 7, Math.sqrt(49), 0);
+ }
+
+ /**
+ * @tests java.lang.Math#tan(double)
+ */
+ @SmallTest
+ public void testTanD() {
+ // Test for method double java.lang.Math.tan(double)
+ assertEquals("Incorrect answer", 0.0, Math.tan(0), 0D);
+ assertEquals("Incorrect answer", 1.5574077246549023, Math.tan(1), 0D);
+
+ }
+
+ /**
+ * @tests java.lang.Math#tanh(double)
+ */
+ @SmallTest
+ public void testTanhD() {
+ // Test for special situations
+ assertTrue("Should return NaN", Double.isNaN(Math.tanh(Double.NaN)));
+ assertEquals("Should return +1.0", +1.0, Math
+ .tanh(Double.POSITIVE_INFINITY), 0D);
+ assertEquals("Should return -1.0", -1.0, Math
+ .tanh(Double.NEGATIVE_INFINITY), 0D);
+ assertEquals(Double.doubleToLongBits(0.0), Double.doubleToLongBits(Math
+ .tanh(0.0)));
+ assertEquals(Double.doubleToLongBits(+0.0), Double
+ .doubleToLongBits(Math.tanh(+0.0)));
+ assertEquals(Double.doubleToLongBits(-0.0), Double
+ .doubleToLongBits(Math.tanh(-0.0)));
+
+ assertEquals("Should return 1.0", 1.0, Math.tanh(1234.56), 0D);
+ assertEquals("Should return -1.0", -1.0, Math.tanh(-1234.56), 0D);
+ assertEquals("Should return 9.999999999996666E-7",
+ 9.999999999996666E-7, Math.tanh(0.000001), 0D);
+ assertEquals("Should return 0.981422884124941", 0.981422884124941, Math
+ .tanh(2.33482), 0D);
+ assertEquals("Should return 1.0", 1.0, Math.tanh(Double.MAX_VALUE), 0D);
+ assertEquals("Should return 4.9E-324", 4.9E-324, Math
+ .tanh(Double.MIN_VALUE), 0D);
+ }
+
+ /**
+ * @tests java.lang.Math#random()
+ */
+ @MediumTest
+ public void testRandom() {
+ // There isn't a place for these tests so just stick them here
+ assertEquals("Wrong value E",
+ 4613303445314885481L, Double.doubleToLongBits(Math.E));
+ assertEquals("Wrong value PI",
+ 4614256656552045848L, Double.doubleToLongBits(Math.PI));
+
+ for (int i = 500; i >= 0; i--) {
+ double d = Math.random();
+ assertTrue("Generated number is out of range: " + d, d >= 0.0
+ && d < 1.0);
+ }
+ }
+
+ /**
+ * @tests java.lang.Math#toRadians(double)
+ */
+ @MediumTest
+ public void testToRadiansD() {
+ for (double d = 500; d >= 0; d -= 1.0) {
+ double converted = Math.toDegrees(Math.toRadians(d));
+ assertTrue("Converted number not equal to original. d = " + d,
+ converted >= d * 0.99999999 && converted <= d * 1.00000001);
+ }
+ }
+
+ /**
+ * @tests java.lang.Math#toDegrees(double)
+ */
+ @MediumTest
+ public void testToDegreesD() {
+ for (double d = 500; d >= 0; d -= 1.0) {
+ double converted = Math.toRadians(Math.toDegrees(d));
+ assertTrue("Converted number not equal to original. d = " + d,
+ converted >= d * 0.99999999 && converted <= d * 1.00000001);
+ }
+ }
+
+ /**
+ * @tests java.lang.Math#ulp(double)
+ */
+ @SuppressWarnings("boxing")
+ @SmallTest
+ public void testUlpD() {
+ // Test for special cases
+ assertTrue("Should return NaN", Double.isNaN(Math.ulp(Double.NaN)));
+ assertEquals("Returned incorrect value", Double.POSITIVE_INFINITY, Math
+ .ulp(Double.POSITIVE_INFINITY), 0D);
+ assertEquals("Returned incorrect value", Double.POSITIVE_INFINITY, Math
+ .ulp(Double.NEGATIVE_INFINITY), 0D);
+ assertEquals("Returned incorrect value", Double.MIN_VALUE, Math
+ .ulp(0.0), 0D);
+ assertEquals("Returned incorrect value", Double.MIN_VALUE, Math
+ .ulp(+0.0), 0D);
+ assertEquals("Returned incorrect value", Double.MIN_VALUE, Math
+ .ulp(-0.0), 0D);
+ assertEquals("Returned incorrect value", Math.pow(2, 971), Math
+ .ulp(Double.MAX_VALUE), 0D);
+ assertEquals("Returned incorrect value", Math.pow(2, 971), Math
+ .ulp(-Double.MAX_VALUE), 0D);
+
+ assertEquals("Returned incorrect value", Double.MIN_VALUE, Math
+ .ulp(Double.MIN_VALUE), 0D);
+ assertEquals("Returned incorrect value", Double.MIN_VALUE, Math
+ .ulp(-Double.MIN_VALUE), 0D);
+
+ assertEquals("Returned incorrect value", 2.220446049250313E-16, Math
+ .ulp(1.0), 0D);
+ assertEquals("Returned incorrect value", 2.220446049250313E-16, Math
+ .ulp(-1.0), 0D);
+ assertEquals("Returned incorrect value", 2.2737367544323206E-13, Math
+ .ulp(1153.0), 0D);
+ }
+
+ /**
+ * @tests java.lang.Math#ulp(float)
+ */
+ @SuppressWarnings("boxing")
+ @SmallTest
+ public void testUlpf() {
+ // Test for special cases
+ assertTrue("Should return NaN", Float.isNaN(Math.ulp(Float.NaN)));
+ assertEquals("Returned incorrect value", Float.POSITIVE_INFINITY, Math
+ .ulp(Float.POSITIVE_INFINITY), 0f);
+ assertEquals("Returned incorrect value", Float.POSITIVE_INFINITY, Math
+ .ulp(Float.NEGATIVE_INFINITY), 0f);
+ assertEquals("Returned incorrect value", Float.MIN_VALUE, Math
+ .ulp(0.0f), 0f);
+ assertEquals("Returned incorrect value", Float.MIN_VALUE, Math
+ .ulp(+0.0f), 0f);
+ assertEquals("Returned incorrect value", Float.MIN_VALUE, Math
+ .ulp(-0.0f), 0f);
+ assertEquals("Returned incorrect value", 2.028241E31f, Math
+ .ulp(Float.MAX_VALUE), 0f);
+ assertEquals("Returned incorrect value", 2.028241E31f, Math
+ .ulp(-Float.MAX_VALUE), 0f);
+
+ assertEquals("Returned incorrect value", 1.4E-45f, Math
+ .ulp(Float.MIN_VALUE), 0f);
+ assertEquals("Returned incorrect value", 1.4E-45f, Math
+ .ulp(-Float.MIN_VALUE), 0f);
+
+ assertEquals("Returned incorrect value", 1.1920929E-7f, Math.ulp(1.0f),
+ 0f);
+ assertEquals("Returned incorrect value", 1.1920929E-7f,
+ Math.ulp(-1.0f), 0f);
+ assertEquals("Returned incorrect value", 1.2207031E-4f, Math
+ .ulp(1153.0f), 0f);
+ assertEquals("Returned incorrect value", 5.6E-45f, Math
+ .ulp(9.403954E-38f), 0f);
+ }
+}
diff --git a/tests/CoreTests/android/core/MiscRegressionTest.java b/tests/CoreTests/android/core/MiscRegressionTest.java
new file mode 100644
index 0000000..8fe064c
--- /dev/null
+++ b/tests/CoreTests/android/core/MiscRegressionTest.java
@@ -0,0 +1,506 @@
+/*
+ * 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 android.core;
+
+import junit.framework.Assert;
+import junit.framework.TestCase;
+
+import java.io.File;
+import java.io.InputStream;
+import java.io.ObjectInputStream;
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.security.KeyStore;
+import java.security.cert.Certificate;
+import java.util.Arrays;
+import java.util.ConcurrentModificationException;
+import java.util.Enumeration;
+import java.util.Iterator;
+import java.util.LinkedHashMap;
+import java.util.Random;
+import java.util.jar.JarEntry;
+import java.util.jar.JarFile;
+import java.util.logging.Logger;
+import java.util.zip.Deflater;
+import java.util.zip.Inflater;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipFile;
+import android.test.suitebuilder.annotation.MediumTest;
+import android.test.suitebuilder.annotation.SmallTest;
+import android.test.suitebuilder.annotation.LargeTest;
+
+public class MiscRegressionTest extends TestCase {
+
+ // Regression test for #857840: want JKS key store
+ @SmallTest
+ public void testDefaultKeystore() {
+ String type = KeyStore.getDefaultType();
+ Assert.assertEquals("Default keystore type must be Bouncy Castle", "BKS", type);
+
+ try {
+ KeyStore store = KeyStore.getInstance(KeyStore.getDefaultType());
+ Assert.assertNotNull("Keystore must not be null", store);
+ } catch (Exception ex) {
+ throw new RuntimeException(ex);
+ }
+
+ try {
+ KeyStore store = KeyStore.getInstance("BKS");
+ Assert.assertNotNull("Keystore must not be null", store);
+ } catch (Exception ex) {
+ throw new RuntimeException(ex);
+ }
+ }
+
+ // Regression test for #1061945: negative Shorts do not
+ // serialize/deserialize correctly
+ @SmallTest
+ public void testShortSerialization() throws Exception {
+ // create an instance of ObjectInputStream
+ String x = new String("serialize_foobar");
+ java.io.ByteArrayOutputStream baos = new java.io.ByteArrayOutputStream();
+ (new java.io.ObjectOutputStream(baos)).writeObject(x);
+ ObjectInputStream ois = new java.io.ObjectInputStream(
+ new java.io.ByteArrayInputStream(baos.toByteArray()));
+
+ // get the setField(...,, short val) method in question
+ Class<ObjectInputStream> oClass = ObjectInputStream.class;
+ Method m = oClass.getDeclaredMethod("setField", new Class[] { Object.class, Class.class, String.class, short.class});
+ // compose args
+ short start = 123;
+ short origval = -1; // 0xffff
+ Short obj = new Short(start);
+ Class<Short> declaringClass = Short.class;
+ String fieldDescName = "value";
+
+ // test the initial value
+ assertEquals(obj.shortValue(), start);
+ // invoke native method to set the field "value" of type short to the newval
+ m.setAccessible(true); // since the method is private
+ m.invoke(ois, new Object[]{ obj, declaringClass, fieldDescName, new Short(origval)} );
+ // test the set value
+ short res = obj.shortValue();
+ assertEquals("Read and written values must be equal", origval, res);
+ }
+
+ // Regression test for #951285: Suitable LogHandler should be chosen
+ // depending on the environment.
+ @MediumTest
+ public void testAndroidLogHandler() throws Exception {
+ Logger.global.severe("This has logging Level.SEVERE, should become ERROR");
+ Logger.global.warning("This has logging Level.WARNING, should become WARN");
+ Logger.global.info("This has logging Level.INFO, should become INFO");
+ Logger.global.config("This has logging Level.CONFIG, should become DEBUG");
+ Logger.global.fine("This has logging Level.FINE, should become VERBOSE");
+ Logger.global.finer("This has logging Level.FINER, should become VERBOSE");
+ Logger.global.finest("This has logging Level.FINEST, should become VERBOSE");
+ }
+
+ // Regression test for #1045939: Different output for Method.toString()
+ @SmallTest
+ public void testMethodToString() {
+ try {
+ Method m1 = Object.class.getMethod("notify", new Class[] { });
+ Method m2 = Object.class.getMethod("toString", new Class[] { });
+ Method m3 = Object.class.getMethod("wait", new Class[] { long.class, int.class });
+ Method m4 = Object.class.getMethod("equals", new Class[] { Object.class });
+ Method m5 = String.class.getMethod("valueOf", new Class[] { char[].class });
+ Method m6 = Runtime.class.getMethod("exec", new Class[] { String[].class });
+
+ assertEquals("Method.toString() must match expectations",
+ "public final native void java.lang.Object.notify()",
+ m1.toString());
+
+ assertEquals("Method.toString() must match expectations",
+ "public java.lang.String java.lang.Object.toString()",
+ m2.toString());
+
+ assertEquals("Method.toString() must match expectations",
+ "public final native void java.lang.Object.wait(long,int) throws java.lang.InterruptedException",
+ m3.toString());
+
+ assertEquals("Method.toString() must match expectations",
+ "public boolean java.lang.Object.equals(java.lang.Object)",
+ m4.toString());
+
+ assertEquals("Method.toString() must match expectations",
+ "public static java.lang.String java.lang.String.valueOf(char[])",
+ m5.toString());
+
+ assertEquals("Method.toString() must match expectations",
+ "public java.lang.Process java.lang.Runtime.exec(java.lang.String[]) throws java.io.IOException",
+ m6.toString());
+
+ } catch (Exception ex) {
+ throw new RuntimeException(ex);
+ }
+
+ }
+
+ // Regression test for #1062200: Enum fails to deserialize. Actual problem
+ // was that Class.isEnum() erroneously returned true for indirect
+ // descendants of Enum.
+ enum TrafficLights {
+ RED,
+ YELLOW {},
+ GREEN {
+ @SuppressWarnings("unused")
+ int i;
+ @SuppressWarnings("unused")
+ void foobar() {}
+ };
+ }
+
+ @SmallTest
+ public void testClassIsEnum() {
+ Class<?> trafficClass = TrafficLights.class;
+
+ Class<?> redClass = TrafficLights.RED.getClass();
+ Class<?> yellowClass = TrafficLights.YELLOW.getClass();
+ Class<?> greenClass = TrafficLights.GREEN.getClass();
+
+ Assert.assertSame("Classes must be equal", trafficClass, redClass);
+ Assert.assertNotSame("Classes must be different", trafficClass, yellowClass);
+ Assert.assertNotSame("Classes must be different", trafficClass, greenClass);
+ Assert.assertNotSame("Classes must be different", yellowClass, greenClass);
+
+ Assert.assertTrue("Must be an enum", trafficClass.isEnum());
+ Assert.assertTrue("Must be an enum", redClass.isEnum());
+ Assert.assertFalse("Must not be an enum", yellowClass.isEnum());
+ Assert.assertFalse("Must not be an enum", greenClass.isEnum());
+
+ Assert.assertNotNull("Must have enum constants", trafficClass.getEnumConstants());
+ Assert.assertNull("Must not have enum constants", yellowClass.getEnumConstants());
+ Assert.assertNull("Must not have enum constants", greenClass.getEnumConstants());
+ }
+
+ // Regression test for #1046174: JarEntry.getCertificates() is really slow.
+ public void checkJarCertificates(File file) {
+ try {
+ JarFile jarFile = new JarFile(file);
+ JarEntry je = jarFile.getJarEntry("AndroidManifest.xml");
+ byte[] readBuffer = new byte[1024];
+
+ long t0 = System.currentTimeMillis();
+
+ // We must read the stream for the JarEntry to retrieve
+ // its certificates.
+ InputStream is = jarFile.getInputStream(je);
+ while (is.read(readBuffer, 0, readBuffer.length) != -1) {
+ // not using
+ }
+ is.close();
+ Certificate[] certs = je != null ? je.getCertificates() : null;
+
+ long t1 = System.currentTimeMillis();
+ android.util.Log.d("TestHarness", "loadCertificates() took " + (t1 - t0) + " ms");
+ if (certs == null) {
+ android.util.Log.d("TestHarness", "We have no certificates");
+ } else {
+ android.util.Log.d("TestHarness", "We have " + certs.length + " certificates");
+ }
+ } catch (Exception ex) {
+ throw new RuntimeException(ex);
+ }
+ }
+
+ @LargeTest
+ public void testJarCertificates() {
+ File[] files = new File("/system/app").listFiles();
+ for (int i = 0; i < files.length; i++) {
+ checkJarCertificates(files[i]);
+ }
+ }
+
+ // Regression test for #1120750: Reflection for static long fields is broken
+ private static final long MY_LONG = 5073258162644648461L;
+
+ @SmallTest
+ public void testLongFieldReflection() {
+ try {
+ Field field = getClass().getDeclaredField("MY_LONG");
+ assertEquals(5073258162644648461L, field.getLong(null));
+ } catch (Exception ex) {
+ throw new RuntimeException(ex);
+ }
+ }
+
+ // Regression test for Harmony LinkedHashMap bug. Copied from core, just
+ // to make sure it doesn't get lost.
+ @SmallTest
+ public void testLinkedHashMap() {
+ // we want to test the LinkedHashMap in access ordering mode.
+ LinkedHashMap map = new LinkedHashMap<String, String>(10, 0.75f, true);
+
+ map.put("key1", "value1");
+ map.put("key2", "value2");
+ map.put("key3", "value3");
+
+ Iterator iterator = map.keySet().iterator();
+ String id = (String) iterator.next();
+ map.get(id);
+ try {
+ iterator.next();
+ // A LinkedHashMap is supposed to throw this Exception when a
+ // iterator.next() Operation takes place after a get
+ // Operation. This is because the get Operation is considered
+ // a structural modification if the LinkedHashMap is in
+ // access order mode.
+ fail("expected ConcurrentModificationException was not thrown.");
+ } catch(ConcurrentModificationException e) {
+ // expected
+ }
+
+ LinkedHashMap mapClone = (LinkedHashMap) map.clone();
+
+ iterator = map.keySet().iterator();
+ id = (String) iterator.next();
+ mapClone.get(id);
+ try {
+ iterator.next();
+ } catch(ConcurrentModificationException e) {
+ fail("expected ConcurrentModificationException was not thrown.");
+ }
+ }
+
+ // Regression test for #1212257: Boot-time package scan is slow. Not
+ // expected to fail. Please see log if you are interested in the results.
+ @LargeTest
+ public void testZipStressManifest() {
+ android.util.Log.d("MiscRegressionTest", "ZIP stress test started");
+
+ long time0 = System.currentTimeMillis();
+
+ try {
+ File[] files = new File("/system/app").listFiles();
+
+ byte[] buffer = new byte[512];
+
+ if (files != null) {
+ for (int i = 0; i < files.length; i++) {
+ android.util.Log.d("MiscRegressionTest",
+ "ZIP stress test processing " + files[i] + "...");
+
+ ZipFile zip = new ZipFile(files[i]);
+
+ ZipEntry entry = zip.getEntry("AndroidManifest.xml");
+ InputStream stream = zip.getInputStream(entry);
+
+ int j = stream.read(buffer);
+ while (j != -1) {
+ j = stream.read(buffer);
+ }
+
+ stream.close();
+ }
+ }
+ } catch (Exception ex) {
+ throw new RuntimeException(ex);
+ }
+
+ long time1 = System.currentTimeMillis();
+
+ android.util.Log.d("MiscRegressionTest", "ZIP stress test finished, " +
+ "time was " + (time1- time0) + "ms");
+ }
+
+ @LargeTest
+ public void testZipStressAllFiles() {
+ android.util.Log.d("MiscRegressionTest", "ZIP stress test started");
+
+ long time0 = System.currentTimeMillis();
+
+ try {
+ File[] files = new File("/system/app").listFiles();
+
+ byte[] buffer = new byte[512];
+
+ if (files != null) {
+ for (int i = 0; i < files.length; i++) {
+ android.util.Log.d("MiscRegressionTest",
+ "ZIP stress test processing " + files[i] + "...");
+
+ ZipFile zip = new ZipFile(files[i]);
+
+ Enumeration<? extends ZipEntry> entries = zip.entries();
+ while (entries.hasMoreElements()) {
+ InputStream stream = zip.getInputStream(entries.nextElement());
+
+ int j = stream.read(buffer);
+ while (j != -1) {
+ j = stream.read(buffer);
+ }
+
+ stream.close();
+ }
+ }
+ }
+ } catch (Exception ex) {
+ throw new RuntimeException(ex);
+ }
+
+ long time1 = System.currentTimeMillis();
+
+ android.util.Log.d("MiscRegressionTest", "ZIP stress test finished, " +
+ "time was " + (time1- time0) + "ms");
+ }
+
+ @SmallTest
+ public void testOsEncodingProperty() {
+ long time0 = System.currentTimeMillis();
+ String[] files = new File("/system/app").list();
+ long time1 = System.currentTimeMillis();
+ android.util.Log.d("MiscRegressionTest", "File.list() test finished, " +
+ "time was " + (time1- time0) + "ms");
+ }
+
+ // -------------------------------------------------------------------------
+ // Regression test for #1185084: Native memory allocated by
+ // java.util.zip.Deflater in system_server. The fix reduced some internal
+ // ZLIB buffers in size, so this test is trying to execute a lot of
+ // deflating to ensure that things are still working properly.
+ private void assertEquals(byte[] a, byte[] b) {
+ assertEquals("Arrays must have same length", a.length, b.length);
+
+ for (int i = 0; i < a.length; i++) {
+ assertEquals("Array elements #" + i + " must be equal", a[i], b[i]);
+ }
+ }
+
+ @LargeTest
+ public void testZipDeflateInflateStress() {
+
+ final int DATA_SIZE = 16384;
+
+ Random random = new Random(42); // Seed makes test reproducible
+
+ try {
+ // Outer loop selects "mode" of test.
+ for (int j = 1; j <=2 ; j++) {
+
+ byte[] input = new byte[DATA_SIZE];
+
+ if (j == 1) {
+ // Totally random content
+ random.nextBytes(input);
+ } else {
+ // Random contents with longer repetitions
+ int pos = 0;
+ while (pos < input.length) {
+ byte what = (byte)random.nextInt(256);
+ int howMany = random.nextInt(32);
+ if (pos + howMany >= input.length) {
+ howMany = input.length - pos;
+ }
+ Arrays.fill(input, pos, pos + howMany, what);
+ pos += howMany;
+ }
+ }
+
+ // Inner loop tries all 9 compression levels.
+ for (int i = 1; i <= 9; i++) {
+ android.util.Log.d("MiscRegressionTest", "ZipDeflateInflateStress test (" + j + "," + i + ")...");
+
+ byte[] zipped = new byte[2 * DATA_SIZE]; // Just to make sure...
+
+ Deflater deflater = new Deflater(i);
+ deflater.setInput(input);
+ deflater.finish();
+
+ deflater.deflate(zipped);
+
+ byte[] output = new byte[DATA_SIZE];
+
+ Inflater inflater = new Inflater();
+ inflater.setInput(zipped);
+ inflater.finished();
+
+ inflater.inflate(output);
+
+ assertEquals(input, output);
+ }
+ }
+ } catch (Exception ex) {
+ throw new RuntimeException(ex);
+ }
+ }
+
+ // -------------------------------------------------------------------------
+ // Regression test for #1252043: Thread.getStackTrace() is broken
+ class MyThread extends Thread {
+ public MyThread(String name) {
+ super(name);
+ }
+
+ @Override
+ public void run() {
+ doSomething();
+ }
+
+ public void doSomething() {
+ for (int i = 0; i < 20;) {
+ try {
+ Thread.sleep(100);
+ } catch (InterruptedException ex) {
+ }
+ }
+ }
+ }
+
+ class MyOtherThread extends Thread {
+ public int visibleTraces;
+
+ public MyOtherThread(ThreadGroup group, String name) {
+ super(group, name);
+ }
+
+ @Override
+ public void run() {
+ visibleTraces = Thread.getAllStackTraces().size();
+ }
+ }
+
+ @LargeTest
+ public void testThreadGetStackTrace() {
+ MyThread t1 = new MyThread("t1");
+ t1.start();
+
+ try {
+ Thread.sleep(1000);
+ } catch (InterruptedException ex) {
+ }
+
+ StackTraceElement[] traces = t1.getStackTrace();
+ StackTraceElement trace = traces[traces.length - 2];
+
+ // Expect to find MyThread.doSomething in the trace
+ assertTrue("Must find MyThread.doSomething in trace",
+ trace.getClassName().endsWith("$MyThread") &&
+ trace.getMethodName().equals("doSomething"));
+
+ ThreadGroup g1 = new ThreadGroup("1");
+ MyOtherThread t2 = new MyOtherThread(g1, "t2");
+ t2.start();
+ try {
+ t2.join();
+ } catch (InterruptedException ex) {
+ }
+
+ // Expect to see the traces of all threads (not just t2)
+ assertTrue("Must have traces for all threads", t2.visibleTraces > 1);
+ }
+}
diff --git a/tests/CoreTests/android/core/NIOTest.java b/tests/CoreTests/android/core/NIOTest.java
new file mode 100644
index 0000000..fd279ca
--- /dev/null
+++ b/tests/CoreTests/android/core/NIOTest.java
@@ -0,0 +1,694 @@
+/*
+ * 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 android.core;
+
+import junit.framework.TestCase;
+
+import java.nio.Buffer;
+import java.nio.BufferOverflowException;
+import java.nio.BufferUnderflowException;
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.nio.FloatBuffer;
+import java.nio.IntBuffer;
+import java.nio.ShortBuffer;
+import android.test.suitebuilder.annotation.SmallTest;
+
+/**
+ * Tests for some buffers from the java.nio package.
+ */
+public class NIOTest extends TestCase {
+
+ void checkBuffer(Buffer b) {
+ assertTrue(0 <= b.position());
+ assertTrue(b.position() <= b.limit());
+ assertTrue(b.limit() <= b.capacity());
+ }
+
+ @SmallTest
+ public void testNIO() throws Exception {
+ ByteBuffer b;
+
+ // Test byte array-based buffer
+ b = ByteBuffer.allocate(12);
+ byteBufferTest(b);
+
+ // Test native heap-allocated buffer
+ b = ByteBuffer.allocateDirect(12);
+ byteBufferTest(b);
+
+ // Test short array-based buffer
+ short[] shortArray = new short[8];
+ ShortBuffer sb = ShortBuffer.wrap(shortArray);
+ shortBufferTest(sb);
+
+ // Test int array-based buffer
+ int[] intArray = new int[8];
+ IntBuffer ib = IntBuffer.wrap(intArray);
+ intBufferTest(ib);
+
+ // Test float array-based buffer
+ float[] floatArray = new float[8];
+ FloatBuffer fb = FloatBuffer.wrap(floatArray);
+ floatBufferTest(fb);
+ }
+
+ private void byteBufferTest(ByteBuffer b) {
+ checkBuffer(b);
+
+ // Bounds checks
+ try {
+ b.put(-1, (byte) 0);
+ fail("expected exception not thrown");
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+
+ try {
+ b.put(b.limit(), (byte) 0);
+ fail("expected exception not thrown");
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+
+ // IndexOutOfBoundsException: offset < 0
+ try {
+ byte[] data = new byte[8];
+ b.position(0);
+ b.put(data, -1, 2);
+ fail("expected exception not thrown");
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+
+ // IndexOutOfBoundsException: length > array.length - offset
+ try {
+ byte[] data = new byte[8];
+ b.position(0);
+ b.put(data, 1, 8);
+ fail("expected exception not thrown");
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+
+ // BufferOverflowException: length > remaining()
+ try {
+ byte[] data = new byte[8];
+ b.position(b.limit() - 2);
+ b.put(data, 0, 3);
+ fail("expected exception not thrown");
+ } catch (BufferOverflowException e) {
+ // expected
+ }
+
+ // Fill buffer with bytes A0 A1 A2 A3 ...
+ b.position(0);
+ for (int i = 0; i < b.capacity(); i++) {
+ b.put((byte) (0xA0 + i));
+ }
+ try {
+ b.put((byte) 0xFF);
+ fail("expected exception not thrown");
+ } catch (BufferOverflowException e) {
+ // expected
+ }
+
+ b.position(0);
+ assertEquals((byte) 0xA7, b.get(7));
+ try {
+ b.get(12);
+ fail("expected exception not thrown");
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ try {
+ b.get(-10);
+ fail("expected exception not thrown");
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+
+ b.position(0);
+ b.order(ByteOrder.LITTLE_ENDIAN);
+ assertEquals((byte) 0xA0, b.get());
+ assertEquals((byte) 0xA1, b.get());
+ assertEquals((byte) 0xA2, b.get());
+ assertEquals((byte) 0xA3, b.get());
+ assertEquals((byte) 0xA4, b.get());
+ assertEquals((byte) 0xA5, b.get());
+ assertEquals((byte) 0xA6, b.get());
+ assertEquals((byte) 0xA7, b.get());
+ assertEquals((byte) 0xA8, b.get());
+ assertEquals((byte) 0xA9, b.get());
+ assertEquals((byte) 0xAA, b.get());
+ assertEquals((byte) 0xAB, b.get());
+ try {
+ b.get();
+ fail("expected exception not thrown");
+ } catch (BufferUnderflowException e) {
+ // expected
+ }
+
+ b.position(0);
+ b.order(ByteOrder.BIG_ENDIAN);
+ assertEquals((byte) 0xA0, b.get());
+ assertEquals((byte) 0xA1, b.get());
+ assertEquals((byte) 0xA2, b.get());
+ assertEquals((byte) 0xA3, b.get());
+ assertEquals((byte) 0xA4, b.get());
+ assertEquals((byte) 0xA5, b.get());
+ assertEquals((byte) 0xA6, b.get());
+ assertEquals((byte) 0xA7, b.get());
+ assertEquals((byte) 0xA8, b.get());
+ assertEquals((byte) 0xA9, b.get());
+ assertEquals((byte) 0xAA, b.get());
+ assertEquals((byte) 0xAB, b.get());
+ try {
+ b.get();
+ fail("expected exception not thrown");
+ } catch (BufferUnderflowException e) {
+ // expected
+ }
+
+ b.position(6);
+ b.limit(10);
+ assertEquals((byte) 0xA6, b.get());
+
+ // Check sliced buffer
+ b.position(6);
+
+ ByteBuffer bb = b.slice();
+ checkBuffer(bb);
+
+ assertEquals(0, bb.position());
+ assertEquals(4, bb.limit());
+ assertEquals(4, bb.capacity());
+
+ assertEquals((byte) 0xA6, bb.get());
+ assertEquals((byte) 0xA7, bb.get());
+ assertEquals((byte) 0xA8, bb.get());
+ assertEquals((byte) 0xA9, bb.get());
+ try {
+ bb.get();
+ fail("expected exception not thrown");
+ } catch (BufferUnderflowException e) {
+ // expected
+ }
+
+ // Reset position and limit
+ b.position(0);
+ b.limit(b.capacity());
+
+ // Check 'getShort'
+ b.order(ByteOrder.LITTLE_ENDIAN);
+ b.position(0);
+ assertEquals((short) 0xA1A0, b.getShort());
+ assertEquals((short) 0xA3A2, b.getShort());
+ assertEquals((short) 0xA5A4, b.getShort());
+ assertEquals((short) 0xA7A6, b.getShort());
+ assertEquals((short) 0xA9A8, b.getShort());
+ assertEquals((short) 0xABAA, b.getShort());
+ try {
+ bb.getShort();
+ fail("expected exception not thrown");
+ } catch (BufferUnderflowException e) {
+ // expected
+ }
+
+ b.order(ByteOrder.BIG_ENDIAN);
+ b.position(0);
+ assertEquals((short) 0xA0A1, b.getShort());
+ assertEquals((short) 0xA2A3, b.getShort());
+ assertEquals((short) 0xA4A5, b.getShort());
+ assertEquals((short) 0xA6A7, b.getShort());
+ assertEquals((short) 0xA8A9, b.getShort());
+ assertEquals((short) 0xAAAB, b.getShort());
+ try {
+ bb.getShort();
+ fail("expected exception not thrown");
+ } catch (BufferUnderflowException e) {
+ // expected
+ }
+
+ // Check 'getInt'
+ b.order(ByteOrder.LITTLE_ENDIAN);
+ b.position(0);
+ assertEquals(0xA3A2A1A0, b.getInt());
+ assertEquals(0xA7A6A5A4, b.getInt());
+ assertEquals(0xABAAA9A8, b.getInt());
+ try {
+ bb.getInt();
+ fail("expected exception not thrown");
+ } catch (BufferUnderflowException e) {
+ // expected
+ }
+
+ b.order(ByteOrder.BIG_ENDIAN);
+ b.position(0);
+ assertEquals(0xA0A1A2A3, b.getInt());
+ assertEquals(0xA4A5A6A7, b.getInt());
+ assertEquals(0xA8A9AAAB, b.getInt());
+ try {
+ bb.getInt();
+ fail("expected exception not thrown");
+ } catch (BufferUnderflowException e) {
+ // expected
+ }
+
+ // Check 'getFloat'
+ b.order(ByteOrder.LITTLE_ENDIAN);
+ b.position(0);
+ assertEquals(0xA3A2A1A0, Float.floatToIntBits(b.getFloat()));
+ assertEquals(0xA7A6A5A4, Float.floatToIntBits(b.getFloat()));
+ assertEquals(0xABAAA9A8, Float.floatToIntBits(b.getFloat()));
+ try {
+ b.getFloat();
+ fail("expected exception not thrown");
+ } catch (BufferUnderflowException e) {
+ // expected
+ }
+
+ b.order(ByteOrder.BIG_ENDIAN);
+ b.position(0);
+ assertEquals(0xA0A1A2A3, Float.floatToIntBits(b.getFloat()));
+ assertEquals(0xA4A5A6A7, Float.floatToIntBits(b.getFloat()));
+ assertEquals(0xA8A9AAAB, Float.floatToIntBits(b.getFloat()));
+ try {
+ b.getFloat();
+ fail("expected exception not thrown");
+ } catch (BufferUnderflowException e) {
+ // expected
+ }
+
+ // Check 'getDouble(int position)'
+ b.order(ByteOrder.LITTLE_ENDIAN);
+ assertEquals(0xA7A6A5A4A3A2A1A0L, Double.doubleToLongBits(b.getDouble(0)));
+ assertEquals(0xA8A7A6A5A4A3A2A1L, Double.doubleToLongBits(b.getDouble(1)));
+ try {
+ b.getDouble(-1);
+ fail("expected exception not thrown");
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ try {
+ b.getDouble(5);
+ fail("expected exception not thrown");
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+
+ b.order(ByteOrder.BIG_ENDIAN);
+ assertEquals(0xA0A1A2A3A4A5A6A7L, Double.doubleToLongBits(b.getDouble(0)));
+ assertEquals(0xA1A2A3A4A5A6A7A8L, Double.doubleToLongBits(b.getDouble(1)));
+ try {
+ b.getDouble(-1);
+ fail("expected exception not thrown");
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ try {
+ b.getDouble(5);
+ fail("expected exception not thrown");
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+
+ // Slice and check 'getInt'
+ b.position(1);
+ b.limit(5);
+ b.order(ByteOrder.LITTLE_ENDIAN);
+ bb = b.slice();
+ assertEquals(4, bb.capacity());
+ assertEquals(0xA4A3A2A1, bb.getInt(0));
+
+ bb.order(ByteOrder.LITTLE_ENDIAN);
+ ShortBuffer sb = bb.asShortBuffer();
+
+ checkBuffer(sb);
+ assertEquals(2, sb.capacity());
+ assertEquals((short) 0xA2A1, sb.get());
+ assertEquals((short) 0xA4A3, sb.get());
+
+ bb.order(ByteOrder.BIG_ENDIAN);
+ sb = bb.asShortBuffer();
+
+ checkBuffer(sb);
+ assertEquals(2, sb.capacity());
+ assertEquals((short) 0xA1A2, sb.get());
+ assertEquals((short) 0xA3A4, sb.get());
+
+ bb.order(ByteOrder.LITTLE_ENDIAN);
+ IntBuffer ib = bb.asIntBuffer();
+
+ checkBuffer(ib);
+ assertEquals(1, ib.capacity());
+ assertEquals(0xA4A3A2A1, ib.get());
+
+ bb.order(ByteOrder.BIG_ENDIAN);
+ ib = bb.asIntBuffer();
+
+ checkBuffer(ib);
+ assertEquals(1, ib.capacity());
+ assertEquals(0xA1A2A3A4, ib.get());
+
+ bb.order(ByteOrder.LITTLE_ENDIAN);
+ FloatBuffer fb = bb.asFloatBuffer();
+
+ checkBuffer(fb);
+ assertEquals(1, fb.capacity());
+ assertEquals(0xA4A3A2A1, Float.floatToIntBits(fb.get()));
+
+ bb.order(ByteOrder.BIG_ENDIAN);
+ fb = bb.asFloatBuffer();
+
+ checkBuffer(fb);
+ assertEquals(1, fb.capacity());
+ assertEquals(0xA1A2A3A4, Float.floatToIntBits(fb.get()));
+ }
+
+ private void shortBufferTest(ShortBuffer sb) {
+ checkBuffer(sb);
+
+ try {
+ sb.put(-1, (short) 0);
+ fail("expected exception not thrown");
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+
+ try {
+ sb.put(sb.limit(), (short) 0);
+ fail("expected exception not thrown");
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+
+ // IndexOutOfBoundsException: offset < 0
+ try {
+ short[] data = new short[8];
+ sb.position(0);
+ sb.put(data, -1, 2);
+ fail("expected exception not thrown");
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+
+ // IndexOutOfBoundsException: length > array.length - offset
+ try {
+ short[] data = new short[8];
+ sb.position(0);
+ sb.put(data, 1, 8);
+ fail("expected exception not thrown");
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+
+ // BufferOverflowException: length > remaining()
+ try {
+ short[] data = new short[8];
+ sb.position(sb.limit() - 2);
+ sb.put(data, 0, 3);
+ fail("expected exception not thrown");
+ } catch (BufferOverflowException e) {
+ // expected
+ }
+
+ short[] data = {0, 10, 20, 30, 40, 50, 60, 70};
+ sb.position(0);
+ sb.put(data);
+
+ try {
+ sb.get();
+ fail("expected exception not thrown");
+ } catch (BufferUnderflowException e) {
+ // expected
+ }
+
+ sb.position(0);
+ assertEquals((short) 0, sb.get());
+ assertEquals((short) 10, sb.get());
+ assertEquals((short) 20, sb.get());
+ assertEquals((short) 30, sb.get());
+ assertEquals((short) 40, sb.get());
+ assertEquals((short) 50, sb.get());
+ assertEquals((short) 60, sb.get());
+ assertEquals((short) 70, sb.get());
+ try {
+ sb.get();
+ fail("expected exception not thrown");
+ } catch (BufferUnderflowException e) {
+ // expected
+ }
+ sb.position(1);
+ sb.put((short) 11);
+ assertEquals((short) 11, sb.get(1));
+
+ short[] ss1 = {33, 44, 55, 66};
+ sb.position(3);
+ sb.put(ss1);
+ sb.position(0);
+ assertEquals((short) 0, sb.get());
+ assertEquals((short) 11, sb.get());
+ assertEquals((short) 20, sb.get());
+ assertEquals((short) 33, sb.get());
+ assertEquals((short) 44, sb.get());
+ assertEquals((short) 55, sb.get());
+ assertEquals((short) 66, sb.get());
+ assertEquals((short) 70, sb.get());
+
+ short[] ss2 = {10, 22, 30};
+ sb.position(2);
+ sb.put(ss2, 1, 1);
+ sb.position(0);
+ assertEquals((short) 0, sb.get());
+ assertEquals((short) 11, sb.get());
+ assertEquals((short) 22, sb.get());
+ assertEquals((short) 33, sb.get());
+ assertEquals((short) 44, sb.get());
+ assertEquals((short) 55, sb.get());
+ assertEquals((short) 66, sb.get());
+ assertEquals((short) 70, sb.get());
+ }
+
+ private void intBufferTest(IntBuffer ib) {
+ checkBuffer(ib);
+
+ try {
+ ib.put(-1, (int) 0);
+ fail("expected exception not thrown");
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+
+ try {
+ ib.put(ib.limit(), (int) 0);
+ fail("expected exception not thrown");
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+
+ // IndexOutOfBoundsException: offset < 0
+ try {
+ int[] data = new int[8];
+ ib.position(0);
+ ib.put(data, -1, 2);
+ fail("expected exception not thrown");
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+
+ // IndexOutOfBoundsException: length > array.length - offset
+ try {
+ int[] data = new int[8];
+ ib.position(0);
+ ib.put(data, 1, 8);
+ fail("expected exception not thrown");
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+
+ // BufferOverflowException: length > remaining()
+ try {
+ int[] data = new int[8];
+ ib.position(ib.limit() - 2);
+ ib.put(data, 0, 3);
+ fail("expected exception not thrown");
+ } catch (BufferOverflowException e) {
+ // expected
+ }
+
+ int[] data = {0, 10, 20, 30, 40, 50, 60, 70};
+ ib.position(0);
+ ib.put(data);
+
+ try {
+ ib.get();
+ fail("expected exception not thrown");
+ } catch (BufferUnderflowException e) {
+ // expected
+ }
+
+ ib.position(0);
+ assertEquals((int) 0, ib.get());
+ assertEquals((int) 10, ib.get());
+ assertEquals((int) 20, ib.get());
+ assertEquals((int) 30, ib.get());
+ assertEquals((int) 40, ib.get());
+ assertEquals((int) 50, ib.get());
+ assertEquals((int) 60, ib.get());
+ assertEquals((int) 70, ib.get());
+ try {
+ ib.get();
+ fail("expected exception not thrown");
+ } catch (BufferUnderflowException e) {
+ // expected
+ }
+ ib.position(1);
+ ib.put((int) 11);
+ assertEquals((int) 11, ib.get(1));
+
+ int[] ss1 = {33, 44, 55, 66};
+ ib.position(3);
+ ib.put(ss1);
+ ib.position(0);
+ assertEquals((int) 0, ib.get());
+ assertEquals((int) 11, ib.get());
+ assertEquals((int) 20, ib.get());
+ assertEquals((int) 33, ib.get());
+ assertEquals((int) 44, ib.get());
+ assertEquals((int) 55, ib.get());
+ assertEquals((int) 66, ib.get());
+ assertEquals((int) 70, ib.get());
+
+ int[] ss2 = {10, 22, 30};
+ ib.position(2);
+ ib.put(ss2, 1, 1);
+ ib.position(0);
+ assertEquals((int) 0, ib.get());
+ assertEquals((int) 11, ib.get());
+ assertEquals((int) 22, ib.get());
+ assertEquals((int) 33, ib.get());
+ assertEquals((int) 44, ib.get());
+ assertEquals((int) 55, ib.get());
+ assertEquals((int) 66, ib.get());
+ assertEquals((int) 70, ib.get());
+ }
+
+ void floatBufferTest(FloatBuffer fb) {
+ checkBuffer(fb);
+
+ try {
+ fb.put(-1, (float) 0);
+ fail("expected exception not thrown");
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+
+ try {
+ fb.put(fb.limit(), (float) 0);
+ fail("expected exception not thrown");
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+
+ // IndexOutOfBoundsException: offset < 0
+ try {
+ float[] data = new float[8];
+ fb.position(0);
+ fb.put(data, -1, 2);
+ fail("expected exception not thrown");
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+
+ // IndexOutOfBoundsException: length > array.length - offset
+ try {
+ float[] data = new float[8];
+ fb.position(0);
+ fb.put(data, 1, 8);
+ fail("expected exception not thrown");
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+
+ // BufferOverflowException: length > remaining()
+ try {
+ float[] data = new float[8];
+ fb.position(fb.limit() - 2);
+ fb.put(data, 0, 3);
+ fail("expected exception not thrown");
+ } catch (BufferOverflowException e) {
+ // expected
+ }
+
+ float[] data = {0, 10, 20, 30, 40, 50, 60, 70};
+ fb.position(0);
+ fb.put(data);
+
+ try {
+ fb.get();
+ fail("expected exception not thrown");
+ } catch (BufferUnderflowException e) {
+ // expected
+ }
+
+ fb.position(0);
+ assertEquals((float) 0, fb.get());
+ assertEquals((float) 10, fb.get());
+ assertEquals((float) 20, fb.get());
+ assertEquals((float) 30, fb.get());
+ assertEquals((float) 40, fb.get());
+ assertEquals((float) 50, fb.get());
+ assertEquals((float) 60, fb.get());
+ assertEquals((float) 70, fb.get());
+ try {
+ fb.get();
+ fail("expected exception not thrown");
+ } catch (BufferUnderflowException e) {
+ // expected
+ }
+ fb.position(1);
+ fb.put((float) 11);
+ assertEquals((float) 11, fb.get(1));
+
+ float[] ss1 = {33, 44, 55, 66};
+ fb.position(3);
+ fb.put(ss1);
+ fb.position(0);
+ assertEquals((float) 0, fb.get());
+ assertEquals((float) 11, fb.get());
+ assertEquals((float) 20, fb.get());
+ assertEquals((float) 33, fb.get());
+ assertEquals((float) 44, fb.get());
+ assertEquals((float) 55, fb.get());
+ assertEquals((float) 66, fb.get());
+ assertEquals((float) 70, fb.get());
+
+ float[] ss2 = {10, 22, 30};
+ fb.position(2);
+ fb.put(ss2, 1, 1);
+ fb.position(0);
+ assertEquals((float) 0, fb.get());
+ assertEquals((float) 11, fb.get());
+ assertEquals((float) 22, fb.get());
+ assertEquals((float) 33, fb.get());
+ assertEquals((float) 44, fb.get());
+ assertEquals((float) 55, fb.get());
+ assertEquals((float) 66, fb.get());
+ assertEquals((float) 70, fb.get());
+ }
+}
diff --git a/tests/CoreTests/android/core/OutputStreamWriterTest.java b/tests/CoreTests/android/core/OutputStreamWriterTest.java
new file mode 100644
index 0000000..1c0901e
--- /dev/null
+++ b/tests/CoreTests/android/core/OutputStreamWriterTest.java
@@ -0,0 +1,48 @@
+/*
+ * 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 android.core;
+
+import junit.framework.TestCase;
+
+import java.io.ByteArrayOutputStream;
+import java.io.OutputStreamWriter;
+import android.test.suitebuilder.annotation.SmallTest;
+
+/**
+ * Tests basic functionality of an OutputStreamWriter.
+ */
+public class OutputStreamWriterTest extends TestCase {
+
+ @SmallTest
+ public void testOutputStreamWriter() throws Exception {
+ String str = "AbCdEfGhIjKlMnOpQrStUvWxYz";
+ ByteArrayOutputStream aa = new ByteArrayOutputStream();
+ OutputStreamWriter a = new OutputStreamWriter(aa, "ISO8859_1");
+ try {
+ a.write(str, 0, 4);
+ a.write('A');
+ // We have to flush the OutputStreamWriter to guarantee
+ // that the results will appear in the underlying OutputStream
+ a.flush();
+ assertEquals("ISO8859_1", a.getEncoding());
+ assertEquals(5, aa.size());
+ assertEquals("AbCdA", aa.toString());
+ } finally {
+ a.close();
+ }
+ }
+}
diff --git a/tests/CoreTests/android/core/ParseIntTest.java b/tests/CoreTests/android/core/ParseIntTest.java
new file mode 100644
index 0000000..0e3b0c6
--- /dev/null
+++ b/tests/CoreTests/android/core/ParseIntTest.java
@@ -0,0 +1,110 @@
+/*
+ * 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 android.core;
+
+import junit.framework.TestCase;
+import android.test.suitebuilder.annotation.SmallTest;
+
+/**
+ * Tests for functionality of class Integer to parse integers.
+ */
+public class ParseIntTest extends TestCase {
+
+ @SmallTest
+ public void testParseInt() throws Exception {
+ assertEquals(0, Integer.parseInt("0", 10));
+ assertEquals(473, Integer.parseInt("473", 10));
+ assertEquals(0, Integer.parseInt("-0", 10));
+ assertEquals(-255, Integer.parseInt("-FF", 16));
+ assertEquals(102, Integer.parseInt("1100110", 2));
+ assertEquals(2147483647, Integer.parseInt("2147483647", 10));
+ assertEquals(-2147483648, Integer.parseInt("-2147483648", 10));
+
+ try {
+ Integer.parseInt("2147483648", 10);
+ fail();
+ } catch (NumberFormatException e) {
+ // ok
+ }
+
+ try {
+ Integer.parseInt("-2147483649", 10);
+ fail();
+ } catch (NumberFormatException e) {
+ // ok
+ }
+
+ // One digit too many
+ try {
+ Integer.parseInt("21474836470", 10);
+ fail();
+ } catch (NumberFormatException e) {
+ // ok
+ }
+
+ try {
+ Integer.parseInt("-21474836480", 10);
+ fail();
+ } catch (NumberFormatException e) {
+ // ok
+ }
+
+ try {
+ Integer.parseInt("21474836471", 10);
+ fail();
+ } catch (NumberFormatException e) {
+ // ok
+ }
+
+ try {
+ Integer.parseInt("-21474836481", 10);
+ fail();
+ } catch (NumberFormatException e) {
+ // ok
+ }
+
+ try {
+ Integer.parseInt("214748364710", 10);
+ fail();
+ } catch (NumberFormatException e) {
+ // ok
+ }
+
+ try {
+ Integer.parseInt("-214748364811", 10);
+ fail();
+ } catch (NumberFormatException e) {
+ // ok
+ }
+
+ try {
+ Integer.parseInt("99", 8);
+ fail();
+ } catch (NumberFormatException e) {
+ // ok
+ }
+
+ try {
+ Integer.parseInt("Kona", 10);
+ fail();
+ } catch (NumberFormatException e) {
+ // ok
+ }
+
+ assertEquals(411787, Integer.parseInt("Kona", 27));
+ }
+}
diff --git a/tests/CoreTests/android/core/PipedStreamTest.java b/tests/CoreTests/android/core/PipedStreamTest.java
new file mode 100644
index 0000000..564b337
--- /dev/null
+++ b/tests/CoreTests/android/core/PipedStreamTest.java
@@ -0,0 +1,303 @@
+/*
+ * Copyright (C) 2007 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 android.core;
+
+import junit.framework.TestCase;
+
+import java.io.PipedInputStream;
+import java.io.PipedOutputStream;
+import android.test.suitebuilder.annotation.MediumTest;
+import android.test.suitebuilder.annotation.SmallTest;
+
+class Fibonacci {
+ int n1 = -1;
+ int n2;
+
+ public int next() {
+ if (n1 < 0) {
+ n1 = 0;
+ return 0;
+ } else if (n1 == 0) {
+ n2 = 0;
+ n1 = 1;
+ return 1;
+ } else {
+ int ret = n1 + n2;
+ n2 = n1;
+ n1 = ret;
+ return ret;
+ }
+ }
+}
+
+
+public class PipedStreamTest extends TestCase {
+
+ private abstract static class TestThread extends Thread {
+ public abstract void runTest() throws Exception;
+
+ public final void run() {
+ try {
+ runTest();
+ } catch (Throwable e) {
+ android.util.Log.e("PST", "Got exception " + e, e);
+ android.util.Log.e("PST", android.util.Log.getStackTraceString(e));
+ exception = e;
+ }
+ }
+
+ Throwable exception;
+ int countRead = 0;
+ }
+
+ @MediumTest
+ public void testA() throws Exception {
+
+ final PipedInputStream in = new PipedInputStream();
+ final PipedOutputStream out = new PipedOutputStream(in);
+
+ assertEquals(0, in.available());
+
+ TestThread reader, writer;
+
+ reader = new TestThread() {
+ Fibonacci fib = new Fibonacci();
+
+ @Override
+ public void runTest() throws Exception {
+ int readInt;
+ byte readByte;
+
+ for (; ;) {
+ readInt = in.read();
+
+ if (readInt == -1) {
+ return;
+ }
+
+ readByte = (byte) readInt;
+ assertEquals(readByte, (byte) fib.next());
+ countRead++;
+ }
+ }
+ };
+
+ reader.start();
+
+ writer = new TestThread() {
+ Fibonacci fib = new Fibonacci();
+
+ @Override
+ public void runTest() throws Exception {
+ for (int i = 0; i < 2000; i++) {
+ int toWrite = fib.next();
+ out.write(toWrite);
+ }
+ out.close();
+ }
+ };
+
+ writer.start();
+
+
+ for (; ;) {
+ try {
+ reader.join(60 * 1000);
+ writer.join(1 * 1000);
+ break;
+ } catch (InterruptedException ex) {
+ }
+ }
+
+ assertEquals(2000, reader.countRead);
+
+ if (writer.exception != null) {
+ throw new Exception(writer.exception);
+ }
+ if (reader.exception != null) {
+ throw new Exception(reader.exception);
+ }
+ }
+
+ @MediumTest
+ public void testB() throws Exception {
+ final PipedInputStream in = new PipedInputStream();
+ final PipedOutputStream out = new PipedOutputStream(in);
+
+ assertEquals(0, in.available());
+
+ TestThread reader, writer;
+
+ reader = new TestThread() {
+ Fibonacci fib = new Fibonacci();
+
+ @Override
+ public void runTest() throws Exception {
+ byte readBytes[] = new byte[5];
+ int ret;
+
+ for (; ;) {
+ int nread = 0;
+ while (nread < 5) {
+ ret = in.read(readBytes, nread, readBytes.length - nread);
+
+ if (ret == -1) {
+ return;
+ }
+ nread += ret;
+ }
+
+ assertEquals(5, nread);
+
+ int readInt = (((int) readBytes[0] & 0xff) << 24)
+ | (((int) readBytes[1] & 0xff) << 16)
+ | (((int) readBytes[2] & 0xff) << 8)
+ | (((int) readBytes[3] & 0xff) << 0);
+
+
+ assertEquals(readInt, fib.next());
+ assertEquals(0, readBytes[4]);
+ countRead++;
+ }
+ }
+ };
+
+ reader.start();
+
+ writer = new TestThread() {
+ Fibonacci fib = new Fibonacci();
+
+ @Override
+ public void runTest() throws Exception {
+ byte writeBytes[] = new byte[5];
+ for (int i = 0; i < 2000; i++) {
+ int toWrite = fib.next();
+ writeBytes[0] = (byte) (toWrite >> 24);
+ writeBytes[1] = (byte) (toWrite >> 16);
+ writeBytes[2] = (byte) (toWrite >> 8);
+ writeBytes[3] = (byte) (toWrite >> 0);
+ writeBytes[4] = 0;
+ out.write(writeBytes, 0, writeBytes.length);
+ }
+ out.close();
+ }
+ };
+
+ writer.start();
+
+
+ for (; ;) {
+ try {
+ reader.join(60 * 1000);
+ writer.join(1 * 1000);
+ break;
+ } catch (InterruptedException ex) {
+ }
+ }
+
+ assertEquals(2000, reader.countRead);
+
+ if (writer.exception != null) {
+ throw new Exception(writer.exception);
+ }
+ if (reader.exception != null) {
+ throw new Exception(reader.exception);
+ }
+ }
+
+ @SmallTest
+ public void testC() throws Exception {
+ final PipedInputStream in = new PipedInputStream();
+ final PipedOutputStream out = new PipedOutputStream(in);
+
+ assertEquals(0, in.available());
+
+ TestThread reader, writer;
+
+ reader = new TestThread() {
+ Fibonacci fib = new Fibonacci();
+
+ @Override
+ public void runTest() throws Exception {
+ byte readBytes[] = new byte[1024 * 2];
+ int ret;
+
+ for (; ;) {
+ int nread = 0;
+ while (nread < readBytes.length) {
+ ret = in.read(readBytes, nread, readBytes.length - nread);
+
+ if (ret == -1) {
+ return;
+ }
+ nread += ret;
+ }
+
+ assertEquals(nread, readBytes.length);
+
+ for (int i = 0; i < (readBytes.length - 4); i += 4) {
+ int readInt = (((int) readBytes[i + 0] & 0xff) << 24)
+ | (((int) readBytes[i + 1] & 0xff) << 16)
+ | (((int) readBytes[i + 2] & 0xff) << 8)
+ | (((int) readBytes[i + 3] & 0xff) << 0);
+
+ assertEquals(readInt, fib.next());
+ }
+ }
+ }
+ };
+
+ reader.start();
+
+ writer = new TestThread() {
+ Fibonacci fib = new Fibonacci();
+
+ @Override
+ public void runTest() throws Exception {
+ byte writeBytes[] = new byte[1024 * 2];
+ for (int i = 0; i < (writeBytes.length - 4); i += 4) {
+ int toWrite = fib.next();
+ writeBytes[i + 0] = (byte) (toWrite >> 24);
+ writeBytes[i + 1] = (byte) (toWrite >> 16);
+ writeBytes[i + 2] = (byte) (toWrite >> 8);
+ writeBytes[i + 3] = (byte) (toWrite >> 0);
+ }
+ out.write(writeBytes, 0, writeBytes.length);
+ out.close();
+ }
+ };
+
+ writer.start();
+
+
+ for (; ;) {
+ try {
+ reader.join(60 * 1000);
+ writer.join(1 * 100);
+ break;
+ } catch (InterruptedException ex) {
+ }
+ }
+
+ if (writer.exception != null) {
+ throw new Exception(writer.exception);
+ }
+ if (reader.exception != null) {
+ throw new Exception(reader.exception);
+ }
+ }
+}
diff --git a/tests/CoreTests/android/core/PrintWriterTest.java b/tests/CoreTests/android/core/PrintWriterTest.java
new file mode 100644
index 0000000..09ee389
--- /dev/null
+++ b/tests/CoreTests/android/core/PrintWriterTest.java
@@ -0,0 +1,75 @@
+/*
+ * 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 android.core;
+
+import junit.framework.TestCase;
+
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import android.test.suitebuilder.annotation.SmallTest;
+
+public class PrintWriterTest extends TestCase {
+
+ @SmallTest
+ public void testPrintWriter() throws Exception {
+ String str = "AbCdEfGhIjKlMnOpQrStUvWxYz";
+ StringWriter aa = new StringWriter();
+ PrintWriter a = new PrintWriter(aa);
+
+ try {
+ a.write(str, 0, 26);
+ a.write('X');
+
+ assertEquals("AbCdEfGhIjKlMnOpQrStUvWxYzX", aa.toString());
+
+ a.write("alphabravodelta", 5, 5);
+ a.append('X');
+ assertEquals("AbCdEfGhIjKlMnOpQrStUvWxYzXbravoX", aa.toString());
+ a.append("omega");
+ assertEquals("AbCdEfGhIjKlMnOpQrStUvWxYzXbravoXomega", aa.toString());
+ a.print("ZZZ");
+ assertEquals("AbCdEfGhIjKlMnOpQrStUvWxYzXbravoXomegaZZZ", aa.toString());
+ } finally {
+ a.close();
+ }
+
+ StringWriter ba = new StringWriter();
+ PrintWriter b = new PrintWriter(ba);
+ try {
+ b.print(true);
+ b.print((char) 'A');
+ b.print("BCD".toCharArray());
+ b.print((double) 1.2);
+ b.print((float) 3);
+ b.print((int) 4);
+ b.print((long) 5);
+ assertEquals("trueABCD1.23.045", ba.toString());
+ b.println();
+ b.println(true);
+ b.println((char) 'A');
+ b.println("BCD".toCharArray());
+ b.println((double) 1.2);
+ b.println((float) 3);
+ b.println((int) 4);
+ b.println((long) 5);
+ b.print("THE END");
+ assertEquals("trueABCD1.23.045\ntrue\nA\nBCD\n1.2\n3.0\n4\n5\nTHE END", ba.toString());
+ } finally {
+ b.close();
+ }
+ }
+}
diff --git a/tests/CoreTests/android/core/PushbackInputStreamTest.java b/tests/CoreTests/android/core/PushbackInputStreamTest.java
new file mode 100644
index 0000000..44cfd8a
--- /dev/null
+++ b/tests/CoreTests/android/core/PushbackInputStreamTest.java
@@ -0,0 +1,57 @@
+/*
+ * 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 android.core;
+
+import junit.framework.TestCase;
+
+import java.io.ByteArrayInputStream;
+import java.io.PushbackInputStream;
+import android.test.suitebuilder.annotation.SmallTest;
+
+public class PushbackInputStreamTest extends TestCase {
+
+ @SmallTest
+ public void testPushbackInputStream() throws Exception {
+ String str = "AbCdEfGhIjKlM\nOpQrStUvWxYz";
+ ByteArrayInputStream aa = new ByteArrayInputStream(str.getBytes());
+ ByteArrayInputStream ba = new ByteArrayInputStream(str.getBytes());
+ ByteArrayInputStream ca = new ByteArrayInputStream(str.getBytes());
+
+ PushbackInputStream a = new PushbackInputStream(aa, 7);
+ try {
+ a.unread("push".getBytes());
+ assertEquals("pushAbCdEfGhIjKlM\nOpQrStUvWxYz", IOUtil.read(a));
+ } finally {
+ a.close();
+ }
+
+ PushbackInputStream b = new PushbackInputStream(ba, 9);
+ try {
+ b.unread('X');
+ assertEquals("XAbCdEfGhI", IOUtil.read(b, 10));
+ } finally {
+ b.close();
+ }
+
+ PushbackInputStream c = new PushbackInputStream(ca);
+ try {
+ assertEquals("bdfhjl\nprtvxz", IOUtil.skipRead(c));
+ } finally {
+ c.close();
+ }
+ }
+}
diff --git a/tests/CoreTests/android/core/PushbackReaderTest.java b/tests/CoreTests/android/core/PushbackReaderTest.java
new file mode 100644
index 0000000..ef62c28
--- /dev/null
+++ b/tests/CoreTests/android/core/PushbackReaderTest.java
@@ -0,0 +1,57 @@
+/*
+ * 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 android.core;
+
+import junit.framework.TestCase;
+
+import java.io.PushbackReader;
+import java.io.StringReader;
+import android.test.suitebuilder.annotation.SmallTest;
+
+public class PushbackReaderTest extends TestCase {
+
+ @SmallTest
+ public void testPushbackReader() throws Exception {
+ String str = "AbCdEfGhIjKlMnOpQrStUvWxYz";
+ StringReader aa = new StringReader(str);
+ StringReader ba = new StringReader(str);
+ StringReader ca = new StringReader(str);
+
+ PushbackReader a = new PushbackReader(aa, 5);
+ try {
+ a.unread("PUSH".toCharArray());
+ assertEquals("PUSHAbCdEfGhIjKlMnOpQrStUvWxYz", IOUtil.read(a));
+ } finally {
+ a.close();
+ }
+
+ PushbackReader b = new PushbackReader(ba, 15);
+ try {
+ b.unread('X');
+ assertEquals("XAbCdEfGhI", IOUtil.read(b, 10));
+ } finally {
+ b.close();
+ }
+
+ PushbackReader c = new PushbackReader(ca);
+ try {
+ assertEquals("bdfhjlnprtvxz", IOUtil.skipRead(c));
+ } finally {
+ c.close();
+ }
+ }
+}
diff --git a/tests/CoreTests/android/core/ReflectArrayTest.java b/tests/CoreTests/android/core/ReflectArrayTest.java
new file mode 100644
index 0000000..20ee8a4
--- /dev/null
+++ b/tests/CoreTests/android/core/ReflectArrayTest.java
@@ -0,0 +1,136 @@
+/*
+ * 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 android.core;
+
+import junit.framework.TestCase;
+
+import java.lang.reflect.Array;
+import android.test.suitebuilder.annotation.SmallTest;
+
+/**
+ * Test java.lang.reflect.Array methods.
+ */
+public class ReflectArrayTest extends TestCase {
+
+ @SmallTest
+ public void testSingleInt() throws Exception {
+ Object intArray = Array.newInstance(Integer.TYPE, 2);
+
+ int[] array = (int[]) intArray;
+ array[0] = 5;
+ Array.setInt(intArray, 1, 6);
+
+ assertEquals(5, Array.getInt(intArray, 0));
+ assertEquals(6, array[1]);
+
+ try {
+ array[2] = 27;
+ fail("store should have failed");
+ } catch (ArrayIndexOutOfBoundsException abe) {
+ // expected
+ }
+
+ assertEquals(2, array.length);
+ assertEquals(Array.getLength(intArray), array.length);
+
+ try {
+ int[][] wrongArray = (int[][]) intArray;
+ fail("cast should have failed");
+ } catch (ClassCastException cce) {
+ // expected
+ }
+
+ intArray = Array.newInstance(Integer.TYPE, 0);
+ assertEquals(0, Array.getLength(intArray));
+ }
+
+ @SmallTest
+ public void testSingle() throws Exception {
+ Object strArray = Array.newInstance(String.class, 2);
+
+ String[] array = (String[]) strArray;
+ array[0] = "entry zero";
+ Array.set(strArray, 1, "entry one");
+
+ //System.out.println("array: " + array);
+
+ assertEquals("entry zero", Array.get(strArray, 0));
+ assertEquals("entry one", array[1]);
+
+ assertEquals(2, array.length);
+ assertEquals(Array.getLength(strArray), array.length);
+ }
+
+ @SmallTest
+ public void testMultiInt() throws Exception {
+ int[] dimensions = {3, 2, 1};
+ Object intIntIntArray = Array.newInstance(Integer.TYPE, dimensions);
+ int[][][] array3 = (int[][][]) intIntIntArray;
+
+ array3[0][0][0] = 123;
+ array3[2][1][0] = 456;
+
+ try {
+ array3[2][1][1] = 768;
+ fail("store should have failed");
+ } catch (ArrayIndexOutOfBoundsException abe) {
+ // expected
+ }
+
+ //System.out.println("array3: " + array3);
+ }
+
+ @SmallTest
+ public void testMulti() throws Exception {
+ int[] dimensions = {1, 2, 3};
+ Object strStrStrArray = Array.newInstance(String.class, dimensions);
+ String[][][] array3 = (String[][][]) strStrStrArray;
+
+ array3[0][0][0] = "zero zero zero";
+ array3[0][1][2] = "zero one two";
+
+ try {
+ array3[1][0][0] = "bad store";
+ fail("store should have failed");
+ } catch (ArrayIndexOutOfBoundsException abe) {
+ // expected
+ }
+
+ try {
+ String[][] array2 = (String[][]) strStrStrArray;
+ fail("expecting bad cast");
+ } catch (ClassCastException cce) {
+ // expected
+ }
+ //System.out.println("array3: " + array3);
+
+
+ int[] dimensions2 = {1, 2};
+ strStrStrArray = Array.newInstance(String[].class, dimensions2);
+ array3 = (String[][][]) strStrStrArray;
+ array3[0][1] = new String[3];
+ array3[0][1][2] = "zero one two";
+ try {
+ array3[1][0][0] = "bad store";
+ fail("store should have failed");
+ } catch (ArrayIndexOutOfBoundsException abe) {
+ // expected
+ }
+ //System.out.println("array3: " + array3);
+ }
+}
+
diff --git a/tests/CoreTests/android/core/RegexTest.java b/tests/CoreTests/android/core/RegexTest.java
new file mode 100644
index 0000000..a7f79e8
--- /dev/null
+++ b/tests/CoreTests/android/core/RegexTest.java
@@ -0,0 +1,288 @@
+/*
+ * 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 android.core;
+
+import android.test.suitebuilder.annotation.SmallTest;
+import android.text.util.Regex;
+
+import junit.framework.TestCase;
+
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * Tests basic functionality of Pattern and Matcher classes.
+ */
+public class RegexTest extends TestCase {
+
+ @SmallTest
+ public void testMatches() throws Exception {
+ /* Tests class Matcher */
+
+ Pattern p = Pattern.compile("bcd");
+ Matcher m = p.matcher("bcd");
+ assertTrue("Should match.", m.matches());
+
+ /* Pattern in the middle */
+ p = Pattern.compile("bcd");
+ m = p.matcher("abcdefg");
+ assertFalse("Should not match.", m.matches());
+
+ /* Pattern at the head */
+ m = p.matcher("bcdefg");
+ assertFalse("Should not match.", m.matches());
+
+ /* Pattern at the tail */
+ m = p.matcher("abcd");
+ assertFalse("Should not match.", m.matches());
+
+ /* Make sure matches() doesn't change after calls to find() */
+ p = Pattern.compile(".*");
+ m = p.matcher("abc");
+ assertTrue(m.matches());
+ assertTrue(m.find());
+ assertTrue(m.matches());
+
+ p = Pattern.compile(".");
+ m = p.matcher("abc");
+ assertFalse(m.matches());
+ assertTrue(m.find());
+ assertFalse(m.matches());
+
+ /* Make sure matches() agrees after a reset() */
+ m.reset("z");
+ assertTrue(m.matches());
+
+ m.reset("xyz");
+ assertFalse(m.matches());
+
+ /* Tests class Pattern */
+
+ assertFalse("Erroneously matched partial string. " +
+ "See http://b/issue?id=754601", Pattern.matches("er", "xer"));
+ assertFalse("Erroneously matched partial string. " +
+ "See http://b/issue?id=754601", Pattern.matches("xe", "xer"));
+ assertTrue("Generic regex should match.",
+ Pattern.matches(".*", "bcd"));
+ assertTrue("Grouped regex should match.",
+ Pattern.matches("(b(c(d)))", "bcd"));
+ assertTrue("Grouped regex should match.",
+ Pattern.matches("(b)(c)(d)", "bcd"));
+ }
+
+ @SmallTest
+ public void testGroupCount() throws Exception {
+ Pattern p = Pattern.compile(
+ "\\b(?:\\+?1)?"
+ + "(?:[ -\\.])?"
+ + "\\(?(\\d{3})?\\)?"
+ + "(?:[ -\\.\\/])?"
+ + "(\\d{3})"
+ + "(?:[ -\\.])?"
+ + "(\\d{4})\\b"
+ );
+
+ Matcher m = p.matcher("1 (919) 555-1212");
+
+ assertEquals("groupCount is incorrect, see http://b/issue?id=759412",
+ 3, m.groupCount());
+ }
+
+ @SmallTest
+ public void testGroups() throws Exception {
+ Pattern p = Pattern.compile("(b)([c|d])(z*)");
+ Matcher m = p.matcher("abcdefg");
+
+ /* Must call find() first, otherwise group*() are undefined. */
+ assertTrue(m.find());
+
+ assertEquals(3, m.groupCount());
+
+ assertEquals("bc", m.group(0));
+ assertEquals("b", m.group(1));
+ assertEquals("c", m.group(2));
+ assertEquals("", m.group(3));
+ }
+
+ @SmallTest
+ public void testFind() throws Exception {
+ Pattern p = Pattern.compile(".");
+ Matcher m = p.matcher("abc");
+
+ assertTrue(m.find());
+ assertEquals("a", m.group(0));
+
+ assertTrue(m.find());
+ assertEquals("b", m.group(0));
+
+ assertTrue(m.find());
+ assertEquals("c", m.group(0));
+
+ assertFalse(m.find());
+ }
+
+ @SmallTest
+ public void testReplaceAll() throws Exception {
+ // Begins with non-matching text, ends with matching text
+ Pattern p = Pattern.compile("a*b");
+ Matcher m = p.matcher("fooaabfooaabfooabfoob");
+
+ String r = m.replaceAll("-");
+ assertEquals("foo-foo-foo-foo-", r);
+
+ // Begins with matching text, ends with non-matching text
+ p = Pattern.compile("a*b");
+ m = p.matcher("aabfooaabfooabfoobfoo");
+
+ r = m.replaceAll("-");
+ assertEquals("-foo-foo-foo-foo", r);
+ }
+
+ @SmallTest
+ public void testReplaceFirst() throws Exception {
+ // Begins with non-matching text, ends with matching text
+ Pattern p = Pattern.compile("a*b");
+ Matcher m = p.matcher("fooaabfooaabfooabfoob");
+
+ String r = m.replaceFirst("-");
+ assertEquals("foo-fooaabfooabfoob", r);
+
+ // Begins with matching text, ends with non-matching text
+ p = Pattern.compile("a*b");
+ m = p.matcher("aabfooaabfooabfoobfoo");
+
+ r = m.replaceFirst("-");
+ assertEquals("-fooaabfooabfoobfoo", r);
+ }
+
+ @SmallTest
+ public void testSplit() throws Exception {
+ Pattern p = Pattern.compile(":");
+ String[] strings;
+
+ strings = p.split("boo:and:foo");
+ assertEquals(3, strings.length);
+ assertEquals("boo", strings[0]);
+ assertEquals("and", strings[1]);
+ assertEquals("foo", strings[2]);
+
+ strings = p.split("boo:and:foo", 2);
+ assertEquals(2, strings.length);
+ assertEquals("boo", strings[0]);
+ assertEquals("and:foo", strings[1]);
+
+ strings = p.split("boo:and:foo", 5);
+ assertEquals(3, strings.length);
+ assertEquals("boo", strings[0]);
+ assertEquals("and", strings[1]);
+ assertEquals("foo", strings[2]);
+
+ strings = p.split("boo:and:foo", -2);
+ assertEquals(3, strings.length);
+ assertEquals("boo", strings[0]);
+ assertEquals("and", strings[1]);
+ assertEquals("foo", strings[2]);
+
+ p = Pattern.compile("o");
+
+ strings = p.split("boo:and:foo");
+ assertEquals(3, strings.length);
+ assertEquals("b", strings[0]);
+ assertEquals("", strings[1]);
+ assertEquals(":and:f", strings[2]);
+
+ strings = p.split("boo:and:foo", 5);
+ assertEquals(5, strings.length);
+ assertEquals("b", strings[0]);
+ assertEquals("", strings[1]);
+ assertEquals(":and:f", strings[2]);
+ assertEquals("", strings[3]);
+ assertEquals("", strings[4]);
+
+ strings = p.split("boo:and:foo", -2);
+ assertEquals(5, strings.length);
+ assertEquals("b", strings[0]);
+ assertEquals("", strings[1]);
+ assertEquals(":and:f", strings[2]);
+ assertEquals("", strings[3]);
+ assertEquals("", strings[4]);
+
+ strings = p.split("boo:and:foo", 0);
+ assertEquals(3, strings.length);
+ assertEquals("b", strings[0]);
+ assertEquals("", strings[1]);
+ assertEquals(":and:f", strings[2]);
+ }
+
+ // -------------------------------------------------------------------
+ // Regression test for #1172774: Bug in Regex.java
+ // Regression test for #1216887: Regular expression match is very slow
+ public static final Pattern TOP_LEVEL_DOMAIN_PATTERN = Pattern.compile(
+ "((aero|arpa|asia|a[cdefgilmnoqrstuwxz])"
+ + "|(biz|b[abdefghijmnorstvwyz])"
+ + "|(cat|com|coop|c[acdfghiklmnoruvxyz])"
+ + "|d[ejkmoz]"
+ + "|(edu|e[cegrstu])"
+ + "|f[ijkmor]"
+ + "|(gov|g[abdefghilmnpqrstuwy])"
+ + "|h[kmnrtu]"
+ + "|(info|int|i[delmnoqrst])"
+ + "|(jobs|j[emop])"
+ + "|k[eghimnrwyz]"
+ + "|l[abcikrstuvy]"
+ + "|(mil|mobi|museum|m[acdghklmnopqrstuvwxyz])"
+ + "|(name|net|n[acefgilopruz])"
+ + "|(org|om)"
+ + "|(pro|p[aefghklmnrstwy])"
+ + "|qa"
+ + "|r[eouw]"
+ + "|s[abcdeghijklmnortuvyz]"
+ + "|(tel|travel|t[cdfghjklmnoprtvwz])"
+ + "|u[agkmsyz]"
+ + "|v[aceginu]"
+ + "|w[fs]"
+ + "|y[etu]"
+ + "|z[amw])");
+
+ public static final Pattern EMAIL_ADDRESS_PATTERN = Pattern.compile(
+ "[\\+a-zA-Z0-9\\.\\_\\%\\-]+\\@"
+ + "(("
+ + "[a-zA-Z0-9]\\.|"
+ + "([a-zA-Z0-9][a-zA-Z0-9\\-]*[a-zA-Z0-9]\\.)+)"
+ + TOP_LEVEL_DOMAIN_PATTERN
+ + ")");
+
+ @SmallTest
+ public void testMonsterRegexCorrectness() {
+ assertTrue(EMAIL_ADDRESS_PATTERN.matcher("a+b@gmail.com").matches());
+ }
+
+ @SmallTest
+ public void testMonsterRegexPerformance() {
+ android.util.Log.e("RegexTest", "RegEx performance test started.");
+ long t0 = System.currentTimeMillis();
+ Matcher m = EMAIL_ADDRESS_PATTERN.matcher("donot repeate@RC8jjjjjjjjjjjjjjj");
+ assertFalse(m.find());
+ long t1 = System.currentTimeMillis();
+ android.util.Log.e("RegexTest", "RegEx performance test finished, " +
+ "took " + (t1 - t0) + " ms.");
+ }
+
+ //
+ // -------------------------------------------------------------------
+
+}
diff --git a/tests/CoreTests/android/core/RequestAPITest.java b/tests/CoreTests/android/core/RequestAPITest.java
new file mode 100644
index 0000000..d89f5ae
--- /dev/null
+++ b/tests/CoreTests/android/core/RequestAPITest.java
@@ -0,0 +1,483 @@
+/*
+ * Copyright (C) 2007 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 android.core;
+
+import android.net.http.RequestHandle;
+import android.net.http.RequestQueue;
+import android.test.AndroidTestCase;
+import android.test.suitebuilder.annotation.Suppress;
+import android.util.Log;
+import android.webkit.CookieSyncManager;
+import com.google.android.collect.Maps;
+
+import java.io.ByteArrayInputStream;
+import java.io.InputStream;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * Container class for all RequestAPI tests
+ */
+//http://b/issue?id=1200337
+@Suppress
+public class RequestAPITest extends AndroidTestCase implements HttpConstants {
+ private static final String LOGTAG = "http";
+
+ /*
+ Other tests to write
+ GET, HEAD, POST with differing parameters to RequestQueue
+ More reuse and pipelining tests - testing for server closing unexpectedly
+ */
+
+ // Sync object for synchronizing end of each test that does communications
+ public static Object syncObj = new Object();
+
+ private RequestQueue mRequestQueue;
+ private TestWebServer mTestWebServer;
+
+ protected void setUp() throws Exception {
+ super.setUp();
+ Log.d(LOGTAG, "Base setup context = " + mContext);
+ mRequestQueue = new RequestQueue(mContext);
+ CookieSyncManager.createInstance(mContext);
+
+ mTestWebServer = new TestWebServer();
+ mTestWebServer.initServer(8080, true);
+ }
+
+ protected void tearDown() throws Exception {
+ Log.d(LOGTAG, "Base tearDown");
+ mTestWebServer.close();
+ Log.d(LOGTAG, "Base teardown done");
+
+ super.tearDown();
+ }
+
+ public void verifyFailure(Map<String, String> headers) {
+ try {
+ RequestHandle handle =
+ mRequestQueue.queueRequest(
+ "http://localhost:8080/test1", "GET", headers, null,
+ null, 0, false);
+
+ handle.waitUntilComplete();
+ fail("expected exception not thrown");
+ } catch (RuntimeException e) {
+ // expected
+ }
+ }
+
+ public void testRequestAddNullHeader() throws Exception {
+ /**
+ * Test Request.addHeader throws a NullPointerException if a null
+ * header is attempted to be set
+ */
+ Log.d(LOGTAG, "testRequestAddNullHeader start ");
+ Map<String, String> headers = Maps.newHashMap();
+ headers.put(null, null);
+ verifyFailure(headers);
+ Log.d(LOGTAG, "testRequestAddNullHeader - returning");
+ }
+
+ public void testRequestAddNullValue() throws Exception {
+ /**
+ * Test Request.addHeader throws a RuntimeException if a null
+ * value is attempted to be set
+ */
+ Log.d(LOGTAG, "testRequestAddNullValue start ");
+ Map<String, String> headers = Maps.newHashMap();
+ headers.put("TestHeader", null);
+ verifyFailure(headers);
+ Log.d(LOGTAG, "testRequestAddNullValue - returning");
+ }
+
+ public void testRequestAddEmptyValue() throws Exception {
+ /**
+ * Test Request.addEmptyValue throws a RuntimeException if an empty
+ * header is attempted to be set
+ */
+ Log.d(LOGTAG, "testRequestAddEmptyValue start ");
+ Map<String, String> headers = Maps.newHashMap();
+ headers.put("TestHeader", "");
+ verifyFailure(headers);
+ Log.d(LOGTAG, "testRequestAddEmptyValue - returning");
+ }
+
+ public void verifySuccess(Map<String, String> headers) {
+ mTestWebServer.setKeepAlive(false);
+ RequestHandle handle = mRequestQueue.queueRequest(
+ "http://localhost:8080/test1", "GET", headers, null,
+ null, 0, false);
+ handle.waitUntilComplete();
+ }
+
+ public void testRequestAddHeader() throws Exception {
+ /**
+ * Test Request.addHeader with a valid header and value can be set without
+ * generating and exception
+ */
+ Log.d(LOGTAG, "testRequestAddHeader start ");
+ Map<String, String> headers = Maps.newHashMap();
+ headers.put("TestHeader", "RequestAddHeader");
+ verifySuccess(headers);
+ Log.d(LOGTAG, "testRequestAddHeader - returning");
+ }
+
+ public void testRequestAddMultiHeader() throws Exception {
+ /**
+ * Test multiple calls to Request.addHeader with valid headers and values
+ * can be set without generating and exception
+ */
+ Log.d(LOGTAG, "testRequestAddMultiHeader start ");
+ Map<String, String> headers = Maps.newHashMap();
+ headers.put("TestHeader", "RequestAddMultiHeader");
+ headers.put("TestHeader2", "RequestAddMultiHeader");
+ headers.put("TestHeader3", "RequestAddMultiHeader");
+ verifySuccess(headers);
+ Log.d(LOGTAG, "testRequestAddMultiHeader - returning");
+ }
+
+ public void testRequestAddSameHeader() throws Exception {
+ /**
+ * Test multiple calls to Request.addHeader with valid identical headers
+ * and values can be set without generating and exception
+ */
+ Log.d(LOGTAG, "testRequestAddSameHeader start ");
+ Map<String, String> headers = Maps.newHashMap();
+ headers.put("TestHeader", "RequestAddSameHeader");
+ headers.put("TestHeader", "RequestAddSameHeader");
+ headers.put("TestHeader", "RequestAddSameHeader");
+ verifySuccess(headers);
+ Log.d(LOGTAG, "testRequestAddSameHeader - returning");
+ }
+
+ public void testRequestAddNullHeaders() throws Exception {
+ /**
+ * Test Request.addHeaders with a null header map. This should not generate
+ * any exceptions but accept that there are no headers to add.
+ */
+ Log.d(LOGTAG, "testRequestAddNullHeaders start ");
+ verifySuccess(null);
+ Log.d(LOGTAG, "testRequestAddNullHeaders - returning");
+ }
+
+ public void testGet() throws Exception {
+ /**
+ * Test sending a GET request. Test will pass if the events received
+ * correspond with the expected response. This should respond with the
+ * test data requested.
+ */
+ TestEventHandler testEventHandler = new TestEventHandler();
+
+ mTestWebServer.setKeepAlive(false);
+
+ Log.d(LOGTAG, "testGet start ");
+
+ // Load up expected response
+ testEventHandler.expectStatus(200);
+ testEventHandler.expectHeaders();
+ testEventHandler.expectHeaderAdd(requestHeaders[REQ_CONNECTION], "Close");
+ testEventHandler.expectHeaderAdd(requestHeaders[REQ_CONTENT_LENGTH], "52");
+ testEventHandler.expectHeaderAdd(requestHeaders[REQ_CONTENT_TYPE], "text/html");
+ testEventHandler.expectData(52);
+
+ RequestHandle handle = mRequestQueue.queueRequest(
+ "http://localhost:8080/test1", "GET", null, testEventHandler,
+ null, 0, false);
+
+ Log.d(LOGTAG, "testGet - sent request. Waiting");
+ handle.waitUntilComplete();
+ Log.d(LOGTAG, "testGet - sent request. Notified");
+
+ if (!testEventHandler.expectPassed()) {
+ Log.d(LOGTAG, testEventHandler.getFailureMessage());
+ fail("expectPassed was false " + testEventHandler.getFailureMessage());
+ }
+ }
+
+ public void testReuse() throws Exception {
+ /**
+ * Test sending two GET requests. Test will pass if the events
+ * received correspond with the expected response.
+ */
+ final String TEST_NAME = "testReuse";
+ Log.d(LOGTAG, TEST_NAME + " start ");
+
+ TestEventHandler testEventHandler = new TestEventHandler();
+
+ // Load up expected response
+ testEventHandler.expectStatus(200);
+ testEventHandler.expectHeaders();
+
+ TestEventHandler testEventHandler2 = new TestEventHandler();
+ testEventHandler2.expectStatus(200);
+ testEventHandler2.expectHeaders();
+
+ mTestWebServer.setAcceptLimit(2);
+
+ RequestHandle handle0 = mRequestQueue.queueRequest(
+ "http://localhost:8080/test1", "GET", null, testEventHandler,
+ null, 0, false);
+ handle0.waitUntilComplete();
+ RequestHandle handle1 = mRequestQueue.queueRequest(
+ "http://localhost:8080/test1", "GET", null, testEventHandler2,
+ null, 0, false);
+ handle1.waitUntilComplete();
+
+ /* It's not correct to use same listener for multiple
+ requests. Otherwise there would be no distiction between
+ events delivered for either request. */
+
+ if (!testEventHandler.expectPassed() && !testEventHandler2.expectPassed()) {
+ Log.d(LOGTAG, testEventHandler.getFailureMessage());
+ Log.d(LOGTAG, testEventHandler2.getFailureMessage());
+ fail();
+ }
+ Log.d(LOGTAG, TEST_NAME + " - sent request. Notified");
+ }
+
+ public void testHead() throws Exception {
+ /**
+ * Test sending a HEAD request. Test will pass if the events
+ * delivered match the expected response.
+ */
+ TestEventHandler testEventHandler = new TestEventHandler();
+
+ // Load up expected response
+ testEventHandler.expectStatus(200);
+ testEventHandler.expectHeaders();
+ testEventHandler.expectNoData();
+
+ mTestWebServer.setKeepAlive(false);
+ mTestWebServer.setAcceptLimit(1);
+
+
+ Log.d(LOGTAG, "testHead start - rq = " + mRequestQueue);
+
+ RequestHandle handle = mRequestQueue.queueRequest(
+ "http://localhost:8080/test1", "HEAD", null, testEventHandler,
+ null, 0, false);
+
+ Log.d(LOGTAG, "testHead - sent request waiting");
+ handle.waitUntilComplete();
+
+ if (!testEventHandler.expectPassed()) {
+ Log.d(LOGTAG, testEventHandler.getFailureMessage());
+ fail("expectPassed was false " + testEventHandler.getFailureMessage());
+ }
+ }
+
+ public void testChunked() throws Exception {
+ TestEventHandler testEventHandler = new TestEventHandler();
+
+ // Load up expected response
+ testEventHandler.expectStatus(200);
+ testEventHandler.expectHeaders();
+
+ mTestWebServer.setKeepAlive(false);
+ mTestWebServer.setChunked(true);
+ mTestWebServer.setAcceptLimit(1);
+
+
+ Log.d(LOGTAG, "testChunked start - rq = " + mRequestQueue);
+
+ RequestHandle handle = mRequestQueue.queueRequest(
+ "http://localhost:8080/test1", "GET", null, testEventHandler,
+ null, 0, false);
+
+ Log.d(LOGTAG, "testChunked - sent request waiting");
+ handle.waitUntilComplete();
+
+ if (!testEventHandler.expectPassed()) {
+ Log.d(LOGTAG, testEventHandler.getFailureMessage());
+ fail("expectPassed was false " + testEventHandler.getFailureMessage());
+ }
+ }
+
+ public void verifyRedirect(int statusCode, String testName) throws Exception {
+ final String REDIRECT_TO = "http://localhost:8081/test1";
+
+ mTestWebServer.setKeepAlive(false);
+ TestWebServer redirectWebServer = new TestWebServer();
+ redirectWebServer.initServer(8081, true);
+ redirectWebServer.setKeepAlive(false);
+
+ try {
+ TestEventHandler testEventHandler = new TestEventHandler();
+ // Load up expected response
+ testEventHandler.expectStatus(statusCode);
+ testEventHandler.expectHeaders();
+ testEventHandler.expectHeaderAdd(requestHeaders[REQ_LOCATION], REDIRECT_TO);
+
+ mTestWebServer.setAcceptLimit(1);
+ mTestWebServer.setRedirect(REDIRECT_TO, statusCode);
+ redirectWebServer.setAcceptLimit(1);
+
+ Log.d(LOGTAG, testName + " start - rq = " + mRequestQueue);
+
+ RequestHandle requestHandle = mRequestQueue.queueRequest(
+ "http://localhost:8080/test1", "GET", null, testEventHandler, null, 0, false);
+ Log.d(LOGTAG, testName + " - sent request waiting");
+
+ requestHandle.waitUntilComplete();
+
+ if (!testEventHandler.expectPassed()) {
+ Log.d(LOGTAG, testEventHandler.getFailureMessage());
+ fail("expectPassed was false " + testEventHandler.getFailureMessage());
+ }
+
+ requestHandle.setupRedirect(REDIRECT_TO, statusCode, new HashMap<String, String>());
+
+ testEventHandler.expectStatus(HttpConstants.HTTP_OK);
+ testEventHandler.expectHeaders();
+ testEventHandler.expectHeaderAdd(requestHeaders[REQ_CONTENT_LENGTH], "52");
+ testEventHandler.expectHeaderAdd(requestHeaders[REQ_CONTENT_TYPE], "text/html");
+ // Server name should be TestWebServer+port
+ // we ignore the server tag, so don't test it
+ // testEventHandler.expectHeaderAdd(requestHeaders[REQ_SERVER], "TestWebServer8081");
+ testEventHandler.expectData(52);
+ testEventHandler.expectEndData();
+
+ requestHandle.waitUntilComplete();
+
+ if (!testEventHandler.expectPassed()) {
+ Log.d(LOGTAG, testEventHandler.getFailureMessage());
+ fail("expectPassed was false " + testEventHandler.getFailureMessage());
+ }
+ } finally {
+ Log.d(LOGTAG, testName + " - returning");
+ redirectWebServer.close();
+ }
+ }
+
+ public void testRedirect301() throws Exception {
+ verifyRedirect(HttpConstants.HTTP_MOVED_PERM, "testRedirect301");
+ }
+
+ public void testRedirect302() throws Exception {
+ verifyRedirect(HttpConstants.HTTP_MOVED_TEMP, "testRedirect302");
+ }
+
+ public void testRedirect303() throws Exception {
+ verifyRedirect(HttpConstants.HTTP_SEE_OTHER, "testRedirect303");
+ }
+
+ public void testRedirect307() throws Exception {
+ verifyRedirect(307, "testRedirect307");
+ }
+
+ public void testGetAndHead() throws Exception {
+ /**
+ * Test sending a GET and a HEAD request. Test will pass if the
+ * event received correspond with the expected response. The two
+ * requests should respond the same test data.
+ */
+ mTestWebServer.setKeepAlive(true);
+ mTestWebServer.setAcceptLimit(2);
+
+ TestEventHandler testEventHandler = new TestEventHandler();
+ testEventHandler.expectStatus(200);
+ testEventHandler.expectHeaders();
+
+ TestEventHandler leh2 = new TestEventHandler();
+ leh2.expectStatus(200);
+ leh2.expectHeaders();
+
+ RequestHandle handle0 = mRequestQueue.queueRequest(
+ "http://localhost:8080/test1", "GET", null, testEventHandler, null, 0, false);
+ handle0.waitUntilComplete();
+ RequestHandle handle1 = mRequestQueue.queueRequest(
+ "http://localhost:8080/test1", "HEAD", null, testEventHandler, null, 0, false);
+
+ Log.d(LOGTAG, "testGetAndHead - sent request. Waiting");
+ handle1.waitUntilComplete();
+
+ if (!testEventHandler.expectPassed() && !leh2.expectPassed()) {
+ Log.d(LOGTAG, testEventHandler.getFailureMessage());
+ Log.d(LOGTAG, leh2.getFailureMessage());
+ fail();
+ }
+ }
+
+ public void testPost() throws Exception {
+ /**
+ * Test sending a POST request with no body data. Test will pass if the event
+ * received correspond with the expected response. This should respond with
+ * the test data requested.
+ */
+ TestEventHandler testEventHandler = new TestEventHandler();
+
+ // Load up expected response
+ testEventHandler.expectStatus(200);
+ testEventHandler.expectHeaders();
+ testEventHandler.expectData(52);
+
+ mTestWebServer.setKeepAlive(false);
+ mTestWebServer.setAcceptLimit(1);
+
+ Log.d(LOGTAG, "testPost start - rq = " + mRequestQueue);
+
+ RequestHandle handle = mRequestQueue.queueRequest(
+ "http://localhost:8080/test1", "POST", null, testEventHandler, null, 0, false);
+
+ Log.d(LOGTAG, "testPost - sent request waiting");
+ handle.waitUntilComplete();
+
+ if (!testEventHandler.expectPassed()) {
+ Log.d(LOGTAG, testEventHandler.getFailureMessage());
+ fail("expectPassed was false " + testEventHandler.getFailureMessage());
+ }
+ }
+
+
+ public void testPostWithData() throws Exception {
+ /**
+ * Test sending a POST request with body data. Test will pass if the event
+ * received correspond with the expected response. This should respond with
+ * the test data requested.
+ */
+
+ TestEventHandler testEventHandler = new TestEventHandler();
+ // Load up expected response
+ testEventHandler.expectStatus(200);
+ testEventHandler.expectHeaders();
+ testEventHandler.expectData(52);
+
+ mTestWebServer.setKeepAlive(false);
+ mTestWebServer.setAcceptLimit(1);
+
+ Log.d(LOGTAG, "testPostWithData start - rq = " + mRequestQueue);
+
+ String mBody = TestWebData.postContent;
+ int bodyLength = mBody.length();
+ if (bodyLength > 0) {
+ Log.v(LOGTAG, "testPostWithData: body " + mBody);
+ }
+ InputStream bodyProvider = new ByteArrayInputStream(mBody.getBytes());
+
+ RequestHandle handle = mRequestQueue.queueRequest(
+ "http://localhost:8080/test1", "POST", null, testEventHandler, bodyProvider, bodyLength, false);
+
+ Log.d(LOGTAG, "testPostWithData - sent request waiting");
+ handle.waitUntilComplete();
+
+ if (!testEventHandler.expectPassed()) {
+ Log.d(LOGTAG, testEventHandler.getFailureMessage());
+ fail("expectPassed was false " + testEventHandler.getFailureMessage());
+ }
+ }
+}
diff --git a/tests/CoreTests/android/core/SQLiteJDBCDriverTest.java b/tests/CoreTests/android/core/SQLiteJDBCDriverTest.java
new file mode 100644
index 0000000..eec82aa
--- /dev/null
+++ b/tests/CoreTests/android/core/SQLiteJDBCDriverTest.java
@@ -0,0 +1,137 @@
+/*
+ * 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 android.core;
+
+import java.io.File;
+import java.sql.Connection;
+import java.sql.DriverManager;
+import java.sql.PreparedStatement;
+import java.sql.SQLException;
+import java.sql.Statement;
+import android.test.suitebuilder.annotation.MediumTest;
+
+/**
+ * Minimal test for JDBC driver
+ */
+public class SQLiteJDBCDriverTest extends AbstractJDBCDriverTest {
+
+ private File dbFile;
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ dbFile = File.createTempFile("sqliteTestDB", null);
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
+ if(dbFile != null) {
+ dbFile.delete();
+ }
+ super.tearDown();
+ }
+
+ @Override
+ protected String getConnectionURL() {
+ return "jdbc:sqlite:/" + dbFile;
+ }
+
+ @Override
+ protected File getDbFile() {
+ return dbFile;
+ }
+
+ @Override
+ protected String getJDBCDriverClassName() {
+ return "SQLite.JDBCDriver";
+ }
+
+ // Regression test for (Noser) #255: PreparedStatement.executeUpdate results
+ // in VM crashing with SIGABRT.
+ @MediumTest
+ public void test_connection3() throws Exception {
+ PreparedStatement prst = null;
+ Statement st = null;
+ Connection conn = null;
+ try {
+ Class.forName("SQLite.JDBCDriver").newInstance();
+ if (dbFile.exists()) {
+ dbFile.delete();
+ }
+ conn = DriverManager.getConnection("jdbc:sqlite:/"
+ + dbFile.getPath());
+ assertNotNull(conn);
+
+ // create table
+ st = conn.createStatement();
+ String sql = "CREATE TABLE zoo (ZID INTEGER NOT NULL, family VARCHAR (20) NOT NULL, name VARCHAR (20) NOT NULL, PRIMARY KEY(ZID) )";
+ st.executeUpdate(sql);
+
+ String update = "update zoo set family = ? where name = ?;";
+ prst = conn.prepareStatement(update);
+ prst.setString(1, "cat");
+ prst.setString(2, "Yasha");
+ // st = conn.createStatement();
+ // st.execute("select * from zoo where family = 'cat'");
+ // ResultSet rs = st.getResultSet();
+ // assertEquals(0, getCount(rs));
+ prst.executeUpdate();
+ // st.execute("select * from zoo where family = 'cat'");
+ // ResultSet rs1 = st.getResultSet();
+ // assertEquals(1, getCount(rs1));
+ try {
+ prst = conn.prepareStatement("");
+ prst.execute();
+ fail("SQLException is not thrown");
+ } catch (SQLException e) {
+ // expected
+ }
+
+ try {
+ conn.prepareStatement(null);
+ fail("NPE is not thrown");
+ } catch (Exception e) {
+ // expected
+ }
+ try {
+ st = conn.createStatement();
+ st.execute("drop table if exists zoo");
+
+ } catch (SQLException e) {
+ fail("Couldn't drop table: " + e.getMessage());
+ } finally {
+ try {
+ st.close();
+ conn.close();
+ } catch (SQLException ee) {
+ }
+ }
+ } finally {
+ try {
+ if (prst != null) {
+ prst.close();
+ }
+ if (st != null) {
+ st.close();
+ }
+ } catch (SQLException ee) {
+ }
+ }
+
+ }
+
+}
diff --git a/tests/CoreTests/android/core/SSLPerformanceTest.java b/tests/CoreTests/android/core/SSLPerformanceTest.java
new file mode 100644
index 0000000..e2bd9c5
--- /dev/null
+++ b/tests/CoreTests/android/core/SSLPerformanceTest.java
@@ -0,0 +1,432 @@
+/*
+ * 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 android.core;
+
+import android.test.AndroidTestCase;
+import android.os.Debug;
+import org.apache.harmony.xnet.provider.jsse.FileClientSessionCache;
+import org.apache.harmony.xnet.provider.jsse.SSLClientSessionCache;
+import org.apache.harmony.xnet.provider.jsse.SSLContextImpl;
+import org.apache.http.conn.scheme.SchemeRegistry;
+import org.apache.http.conn.scheme.Scheme;
+import org.apache.http.conn.ClientConnectionManager;
+import org.apache.http.conn.ssl.SSLSocketFactory;
+import org.apache.http.impl.conn.SingleClientConnManager;
+import org.apache.http.impl.client.DefaultHttpClient;
+import org.apache.http.client.methods.HttpGet;
+import org.apache.http.client.ResponseHandler;
+import org.apache.http.client.ClientProtocolException;
+import org.apache.http.HttpResponse;
+
+import javax.net.ssl.SSLSession;
+import javax.net.ssl.SSLSessionContext;
+import java.io.File;
+import java.io.IOException;
+import java.lang.reflect.Method;
+import java.lang.reflect.InvocationTargetException;
+import java.security.cert.Certificate;
+import java.security.Principal;
+import java.security.KeyManagementException;
+import java.util.Arrays;
+
+public class SSLPerformanceTest extends AndroidTestCase {
+
+ static final byte[] SESSION_DATA = new byte[6000];
+ static {
+ for (int i = 0; i < SESSION_DATA.length; i++) {
+ SESSION_DATA[i] = (byte) i;
+ }
+ }
+
+ static final File dataDir = new File("/data/data/android.core/");
+ static final File filesDir = new File(dataDir, "files");
+ static final File dbDir = new File(dataDir, "databases");
+
+ static final String CACHE_DIR
+ = SSLPerformanceTest.class.getName() + "/cache";
+
+ static final int ITERATIONS = 10;
+
+ public void testCreateNewEmptyDatabase() {
+ deleteDatabase();
+
+ Stopwatch stopwatch = new Stopwatch();
+
+ DatabaseSessionCache cache = new DatabaseSessionCache(getContext());
+ cache.getSessionData("crazybob.org", 443);
+
+ stopwatch.stop();
+ }
+
+ public void testCreateNewEmptyDirectory() throws IOException {
+ deleteDirectory();
+
+ Stopwatch stopwatch = new Stopwatch();
+
+ SSLClientSessionCache cache = FileClientSessionCache.usingDirectory(
+ getCacheDirectory());
+ cache.getSessionData("crazybob.org", 443);
+
+ stopwatch.stop();
+ }
+
+ public void testOpenDatabaseWith10Sessions() {
+ deleteDatabase();
+
+ DatabaseSessionCache cache = new DatabaseSessionCache(getContext());
+ putSessionsIn(cache);
+ closeDatabase();
+
+ System.err.println("Size of ssl_sessions.db w/ 10 sessions: "
+ + new File(dbDir, "ssl_sessions.db").length());
+
+ Stopwatch stopwatch = new Stopwatch();
+
+ cache = new DatabaseSessionCache(getContext());
+ cache.getSessionData("crazybob.org", 443);
+
+ stopwatch.stop();
+ }
+
+ public void testOpenDirectoryWith10Sessions() throws IOException {
+ deleteDirectory();
+
+ SSLClientSessionCache cache = FileClientSessionCache.usingDirectory(
+ getCacheDirectory());
+ putSessionsIn(cache);
+ closeDirectoryCache();
+
+ Stopwatch stopwatch = new Stopwatch();
+
+ cache = FileClientSessionCache.usingDirectory(
+ getCacheDirectory());
+ cache.getSessionData("crazybob.org", 443);
+
+ stopwatch.stop();
+ }
+
+ public void testGetSessionFromDatabase() {
+ deleteDatabase();
+
+ DatabaseSessionCache cache = new DatabaseSessionCache(getContext());
+ cache.putSessionData(new FakeSession("foo"), SESSION_DATA);
+ closeDatabase();
+
+ cache = new DatabaseSessionCache(getContext());
+ cache.getSessionData("crazybob.org", 443);
+
+ Stopwatch stopwatch = new Stopwatch();
+
+ byte[] sessionData = cache.getSessionData("foo", 443);
+
+ stopwatch.stop();
+
+ assertTrue(Arrays.equals(SESSION_DATA, sessionData));
+ }
+
+ public void testGetSessionFromDirectory() throws IOException {
+ deleteDirectory();
+
+ SSLClientSessionCache cache = FileClientSessionCache.usingDirectory(
+ getCacheDirectory());
+ cache.putSessionData(new FakeSession("foo"), SESSION_DATA);
+ closeDirectoryCache();
+
+ cache = FileClientSessionCache.usingDirectory(
+ getCacheDirectory());
+ cache.getSessionData("crazybob.org", 443);
+
+ Stopwatch stopwatch = new Stopwatch();
+
+ byte[] sessionData = cache.getSessionData("foo", 443);
+
+ stopwatch.stop();
+
+ assertTrue(Arrays.equals(SESSION_DATA, sessionData));
+ }
+
+ public void testPutSessionIntoDatabase() {
+ deleteDatabase();
+
+ DatabaseSessionCache cache = new DatabaseSessionCache(getContext());
+ cache.getSessionData("crazybob.org", 443);
+
+ Stopwatch stopwatch = new Stopwatch();
+
+ cache.putSessionData(new FakeSession("foo"), SESSION_DATA);
+
+ stopwatch.stop();
+ }
+
+ public void testPutSessionIntoDirectory() throws IOException {
+ deleteDirectory();
+
+ SSLClientSessionCache cache = FileClientSessionCache.usingDirectory(
+ getCacheDirectory());
+ cache.getSessionData("crazybob.org", 443);
+
+ Stopwatch stopwatch = new Stopwatch();
+
+ cache.putSessionData(new FakeSession("foo"), SESSION_DATA);
+
+ stopwatch.stop();
+ }
+
+ public void testEngineInit() throws IOException, KeyManagementException {
+ Stopwatch stopwatch = new Stopwatch();
+
+ new SSLContextImpl().engineInit(null, null, null);
+
+ stopwatch.stop();
+ }
+
+ public void testWebRequestWithoutCache() throws IOException,
+ KeyManagementException {
+ SSLContextImpl sslContext = new SSLContextImpl();
+ sslContext.engineInit(null, null, null);
+
+ Stopwatch stopwatch = new Stopwatch();
+
+ getVerisignDotCom(sslContext);
+
+ stopwatch.stop();
+ }
+
+ public void testWebRequestWithFileCache() throws IOException,
+ KeyManagementException {
+ deleteDirectory();
+
+ SSLContextImpl sslContext = new SSLContextImpl();
+ sslContext.engineInit(null, null, null,
+ FileClientSessionCache.usingDirectory(getCacheDirectory()),
+ null);
+
+ // Make sure www.google.com is in the cache.
+ getVerisignDotCom(sslContext);
+
+ // Re-initialize so we hit the file cache.
+ sslContext.engineInit(null, null, null,
+ FileClientSessionCache.usingDirectory(getCacheDirectory()),
+ null);
+
+ Stopwatch stopwatch = new Stopwatch();
+
+ getVerisignDotCom(sslContext);
+
+ stopwatch.stop();
+ }
+
+ public void testWebRequestWithInMemoryCache() throws IOException,
+ KeyManagementException {
+ deleteDirectory();
+
+ SSLContextImpl sslContext = new SSLContextImpl();
+ sslContext.engineInit(null, null, null);
+
+ // Make sure www.google.com is in the cache.
+ getVerisignDotCom(sslContext);
+
+ Stopwatch stopwatch = new Stopwatch();
+
+ getVerisignDotCom(sslContext);
+
+ stopwatch.stop();
+ }
+
+ private void getVerisignDotCom(SSLContextImpl sslContext)
+ throws IOException {
+ SchemeRegistry schemeRegistry = new SchemeRegistry();
+ schemeRegistry.register(new Scheme("https",
+ new SSLSocketFactory(sslContext.engineGetSocketFactory()),
+ 443));
+
+ ClientConnectionManager manager =
+ new SingleClientConnManager(null, schemeRegistry);
+
+ new DefaultHttpClient(manager, null).execute(
+ new HttpGet("https://www.verisign.com"),
+ new ResponseHandler<Object>() {
+ public Object handleResponse(HttpResponse response)
+ throws ClientProtocolException, IOException {
+ return null;
+ }
+ });
+ }
+
+ private void putSessionsIn(SSLClientSessionCache cache) {
+ for (int i = 0; i < 10; i++) {
+ cache.putSessionData(new FakeSession("host" + i), SESSION_DATA);
+ }
+ }
+
+ private void deleteDatabase() {
+ closeDatabase();
+ if (!new File(dbDir, "ssl_sessions.db").delete()) {
+ System.err.println("Failed to delete database.");
+ }
+ }
+
+ private void closeDatabase() {
+ if (DatabaseSessionCache.sDefaultDatabaseHelper != null) {
+ DatabaseSessionCache.sDefaultDatabaseHelper.close();
+ }
+ DatabaseSessionCache.sDefaultDatabaseHelper = null;
+ DatabaseSessionCache.sHookInitializationDone = false;
+ DatabaseSessionCache.mNeedsCacheLoad = true;
+ }
+
+ private void deleteDirectory() {
+ closeDirectoryCache();
+
+ File dir = getCacheDirectory();
+ if (!dir.exists()) {
+ return;
+ }
+ for (File file : dir.listFiles()) {
+ file.delete();
+ }
+ if (!dir.delete()) {
+ System.err.println("Failed to delete directory.");
+ }
+ }
+
+ private void closeDirectoryCache() {
+ try {
+ Method reset = FileClientSessionCache.class
+ .getDeclaredMethod("reset");
+ reset.setAccessible(true);
+ reset.invoke(null);
+ } catch (NoSuchMethodException e) {
+ throw new RuntimeException(e);
+ } catch (IllegalAccessException e) {
+ throw new RuntimeException(e);
+ } catch (InvocationTargetException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ private File getCacheDirectory() {
+ return new File(getContext().getFilesDir(), CACHE_DIR);
+ }
+
+ class Stopwatch {
+ {
+ Debug.startAllocCounting();
+ }
+ long start = System.nanoTime();
+
+ void stop() {
+ long elapsed = (System.nanoTime() - start) / 1000;
+ Debug.stopAllocCounting();
+ System.err.println(getName() + ": " + elapsed + "us, "
+ + Debug.getThreadAllocCount() + " allocations, "
+ + Debug.getThreadAllocSize() + " bytes");
+ }
+ }
+}
+
+class FakeSession implements SSLSession {
+ final String host;
+
+ FakeSession(String host) {
+ this.host = host;
+ }
+
+ public int getApplicationBufferSize() {
+ throw new UnsupportedOperationException();
+ }
+
+ public String getCipherSuite() {
+ throw new UnsupportedOperationException();
+ }
+
+ public long getCreationTime() {
+ throw new UnsupportedOperationException();
+ }
+
+ public byte[] getId() {
+ return host.getBytes();
+ }
+
+ public long getLastAccessedTime() {
+ throw new UnsupportedOperationException();
+ }
+
+ public Certificate[] getLocalCertificates() {
+ throw new UnsupportedOperationException();
+ }
+
+ public Principal getLocalPrincipal() {
+ throw new UnsupportedOperationException();
+ }
+
+ public int getPacketBufferSize() {
+ throw new UnsupportedOperationException();
+ }
+
+ public javax.security.cert.X509Certificate[] getPeerCertificateChain() {
+ throw new UnsupportedOperationException();
+ }
+
+ public Certificate[] getPeerCertificates() {
+ throw new UnsupportedOperationException();
+ }
+
+ public String getPeerHost() {
+ return host;
+ }
+
+ public int getPeerPort() {
+ return 443;
+ }
+
+ public Principal getPeerPrincipal() {
+ throw new UnsupportedOperationException();
+ }
+
+ public String getProtocol() {
+ throw new UnsupportedOperationException();
+ }
+
+ public SSLSessionContext getSessionContext() {
+ throw new UnsupportedOperationException();
+ }
+
+ public Object getValue(String name) {
+ throw new UnsupportedOperationException();
+ }
+
+ public String[] getValueNames() {
+ throw new UnsupportedOperationException();
+ }
+
+ public void invalidate() {
+ throw new UnsupportedOperationException();
+ }
+
+ public boolean isValid() {
+ throw new UnsupportedOperationException();
+ }
+
+ public void putValue(String name, Object value) {
+ throw new UnsupportedOperationException();
+ }
+
+ public void removeValue(String name) {
+ throw new UnsupportedOperationException();
+ }
+}
diff --git a/tests/CoreTests/android/core/SSLSocketTest.java b/tests/CoreTests/android/core/SSLSocketTest.java
new file mode 100644
index 0000000..088fa8c
--- /dev/null
+++ b/tests/CoreTests/android/core/SSLSocketTest.java
@@ -0,0 +1,1089 @@
+/*
+ * 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 android.core;
+
+import junit.framework.TestCase;
+
+import org.apache.commons.codec.binary.Base64;
+import org.apache.harmony.xnet.provider.jsse.SSLContextImpl;
+import org.apache.harmony.xnet.provider.jsse.SSLClientSessionCache;
+import org.apache.harmony.xnet.provider.jsse.FileClientSessionCache;
+
+import java.io.ByteArrayInputStream;
+import java.io.DataInputStream;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.PrintWriter;
+import java.net.InetSocketAddress;
+import java.net.Socket;
+import java.security.KeyStore;
+import java.security.KeyManagementException;
+import java.security.cert.X509Certificate;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Random;
+
+import javax.net.ssl.KeyManager;
+import javax.net.ssl.KeyManagerFactory;
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.SSLServerSocket;
+import javax.net.ssl.SSLSession;
+import javax.net.ssl.SSLSocket;
+import javax.net.ssl.SSLSocketFactory;
+import javax.net.ssl.TrustManager;
+import javax.net.ssl.X509TrustManager;
+
+/**
+ * SSL integration tests that hit real servers.
+ */
+public class SSLSocketTest extends TestCase {
+
+ private static SSLSocketFactory clientFactory =
+ (SSLSocketFactory) SSLSocketFactory.getDefault();
+
+ /**
+ * Does a number of HTTPS requests on some host and consumes the response.
+ * We don't use the HttpsUrlConnection class, but do this on our own
+ * with the SSLSocket class. This gives us a chance to test the basic
+ * behavior of SSL.
+ *
+ * @param host The host name the request is being sent to.
+ * @param port The port the request is being sent to.
+ * @param path The path being requested (e.g. "/index.html").
+ * @param outerLoop The number of times we reconnect and do the request.
+ * @param innerLoop The number of times we do the request for each
+ * connection (using HTTP keep-alive).
+ * @param delay The delay after each request (in seconds).
+ * @throws IOException When a problem occurs.
+ */
+ private void fetch(SSLSocketFactory socketFactory, String host, int port,
+ boolean secure, String path, int outerLoop, int innerLoop,
+ int delay, int timeout) throws IOException {
+ InetSocketAddress address = new InetSocketAddress(host, port);
+
+ for (int i = 0; i < outerLoop; i++) {
+ // Connect to the remote host
+ Socket socket = secure ? socketFactory.createSocket()
+ : new Socket();
+ if (timeout >= 0) {
+ socket.setKeepAlive(true);
+ socket.setSoTimeout(timeout * 1000);
+ }
+ socket.connect(address);
+
+ // Get the streams
+ OutputStream output = socket.getOutputStream();
+ PrintWriter writer = new PrintWriter(output);
+
+ try {
+ DataInputStream input = new DataInputStream(socket.getInputStream());
+ try {
+ for (int j = 0; j < innerLoop; j++) {
+ android.util.Log.d("SSLSocketTest",
+ "GET https://" + host + path + " HTTP/1.1");
+
+ // Send a request
+ writer.println("GET https://" + host + path + " HTTP/1.1\r");
+ writer.println("Host: " + host + "\r");
+ writer.println("Connection: " +
+ (j == innerLoop - 1 ? "Close" : "Keep-Alive")
+ + "\r");
+ writer.println("\r");
+ writer.flush();
+
+ int length = -1;
+ boolean chunked = false;
+
+ String line = input.readLine();
+
+ if (line == null) {
+ throw new IOException("No response from server");
+ // android.util.Log.d("SSLSocketTest", "No response from server");
+ }
+
+ // Consume the headers, check content length and encoding type
+ while (line != null && line.length() != 0) {
+// System.out.println(line);
+ int dot = line.indexOf(':');
+ if (dot != -1) {
+ String key = line.substring(0, dot).trim();
+ String value = line.substring(dot + 1).trim();
+
+ if ("Content-Length".equalsIgnoreCase(key)) {
+ length = Integer.valueOf(value);
+ } else if ("Transfer-Encoding".equalsIgnoreCase(key)) {
+ chunked = "Chunked".equalsIgnoreCase(value);
+ }
+
+ }
+ line = input.readLine();
+ }
+
+ assertTrue("Need either content length or chunked encoding", length != -1
+ || chunked);
+
+ // Consume the content itself
+ if (chunked) {
+ length = Integer.parseInt(input.readLine(), 16);
+ while (length != 0) {
+ byte[] buffer = new byte[length];
+ input.readFully(buffer);
+ input.readLine();
+ length = Integer.parseInt(input.readLine(), 16);
+ }
+ input.readLine();
+ } else {
+ byte[] buffer = new byte[length];
+ input.readFully(buffer);
+ }
+
+ // Sleep for the given number of seconds
+ try {
+ Thread.sleep(delay * 1000);
+ } catch (InterruptedException ex) {
+ // Shut up!
+ }
+ }
+ } finally {
+ input.close();
+ }
+ } finally {
+ writer.close();
+ }
+ // Close the connection
+ socket.close();
+ }
+ }
+
+ /**
+ * Invokes fetch() with the default socket factory.
+ */
+ private void fetch(String host, int port, boolean secure, String path,
+ int outerLoop, int innerLoop,
+ int delay, int timeout) throws IOException {
+ fetch(clientFactory, host, port, secure, path, outerLoop, innerLoop,
+ delay, timeout);
+ }
+
+ /**
+ * Does a single request for each of the hosts. Consumes the response.
+ *
+ * @throws IOException If a problem occurs.
+ */
+ public void testSimple() throws IOException {
+ fetch("www.fortify.net", 443, true, "/sslcheck.html", 1, 1, 0, 60);
+ fetch("mail.google.com", 443, true, "/mail/", 1, 1, 0, 60);
+ fetch("www.paypal.com", 443, true, "/", 1, 1, 0, 60);
+ fetch("www.yellownet.ch", 443, true, "/", 1, 1, 0, 60);
+ }
+
+ /**
+ * Does repeated requests for each of the hosts, with the connection being
+ * closed in between.
+ *
+ * @throws IOException If a problem occurs.
+ */
+ public void testRepeatedClose() throws IOException {
+ fetch("www.fortify.net", 443, true, "/sslcheck.html", 10, 1, 0, 60);
+ fetch("mail.google.com", 443, true, "/mail/", 10, 1, 0, 60);
+ fetch("www.paypal.com", 443, true, "/", 10, 1, 0, 60);
+ fetch("www.yellownet.ch", 443, true, "/", 10, 1, 0, 60);
+ }
+
+ /**
+ * Does repeated requests for each of the hosts, with the connection being
+ * kept alive in between.
+ *
+ * @throws IOException If a problem occurs.
+ */
+ public void testRepeatedKeepAlive() throws IOException {
+ fetch("www.fortify.net", 443, true, "/sslcheck.html", 1, 10, 0, 60);
+ fetch("mail.google.com", 443, true, "/mail/", 1, 10, 0, 60);
+
+ // These two don't accept keep-alive
+ // fetch("www.paypal.com", 443, "/", 1, 10);
+ // fetch("www.yellownet.ch", 443, "/", 1, 10);
+ }
+
+ /**
+ * Does repeated requests for each of the hosts, with the connection being
+ * closed in between. Waits a couple of seconds after each request, but
+ * stays within a reasonable timeout. Expectation is that the connection
+ * stays open.
+ *
+ * @throws IOException If a problem occurs.
+ */
+ public void testShortTimeout() throws IOException {
+ fetch("www.fortify.net", 443, true, "/sslcheck.html", 1, 10, 5, 60);
+ fetch("mail.google.com", 443, true, "/mail/", 1, 10, 5, 60);
+
+ // These two don't accept keep-alive
+ // fetch("www.paypal.com", 443, "/", 1, 10);
+ // fetch("www.yellownet.ch", 443, "/", 1, 10);
+ }
+
+ /**
+ * Does repeated requests for each of the hosts, with the connection being
+ * kept alive in between. Waits a longer time after each request.
+ * Expectation is that the host closes the connection.
+ */
+ public void testLongTimeout() {
+ // Seems to have a veeeery long timeout.
+ // fetch("www.fortify.net", 443, "/sslcheck.html", 1, 2, 60);
+
+ // Google has a 60s timeout, so 90s of waiting should trigger it.
+ try {
+ fetch("mail.google.com", 443, true, "/mail/", 1, 2, 90, 180);
+ fail("Oops - timeout expected.");
+ } catch (IOException ex) {
+ // Expected.
+ }
+
+ // These two don't accept keep-alive
+ // fetch("www.paypal.com", 443, "/", 1, 10);
+ // fetch("www.yellownet.ch", 443, "/", 1, 10);
+ }
+
+ /**
+ * Does repeated requests for each of the hosts, with the connection being
+ * closed in between. Waits a longer time after each request. Expectation is
+ * that the host closes the connection.
+ */
+ // These two need manual interaction to reproduce...
+ public void xxtestBrokenConnection() {
+ try {
+ fetch("www.fortify.net", 443, true, "/sslcheck.html", 1, 2, 60, 60);
+ fail("Oops - timeout expected.");
+ } catch (IOException ex) {
+ android.util.Log.d("SSLSocketTest", "Exception", ex);
+ // Expected.
+ }
+
+ // These two don't accept keep-alive
+ // fetch("www.paypal.com", 443, "/", 1, 10);
+ // fetch("www.yellownet.ch", 443, "/", 1, 10);
+ }
+
+ /**
+ * Does repeated requests for each of the hosts, with the connection being
+ * closed in between. Waits a longer time after each request. Expectation is
+ * that the host closes the connection.
+ */
+ // These two need manual interaction to reproduce...
+ public void xxtestBrokenConnection2() {
+ try {
+ fetch("www.heise.de", 80, false, "/index.html", 1, 2, 60, 60);
+ fail("Oops - timeout expected.");
+ } catch (IOException ex) {
+ android.util.Log.d("SSLSocketTest", "Exception", ex);
+ // Expected.
+ }
+
+ // These two don't accept keep-alive
+ // fetch("www.paypal.com", 443, "/", 1, 10);
+ // fetch("www.yellownet.ch", 443, "/", 1, 10);
+ }
+
+ /**
+ * Regression test for 865926: SSLContext.init() should
+ * use default values for null arguments.
+ */
+ public void testContextInitNullArgs() throws Exception {
+ SSLContext ctx = SSLContext.getInstance("TLS");
+ ctx.init(null, null, null);
+ }
+
+ /**
+ * Regression test for 963650: javax.net.ssl.KeyManager has no implemented
+ * (documented?) algorithms.
+ */
+ public void testDefaultAlgorithms() throws Exception {
+ SSLContext ctx = SSLContext.getInstance("TLS");
+ KeyManagerFactory kmf = KeyManagerFactory.getInstance("X509");
+ KeyStore ks = KeyStore.getInstance("BKS");
+
+ assertEquals("X509", kmf.getAlgorithm());
+ assertEquals("X509", KeyManagerFactory.getDefaultAlgorithm());
+
+ assertEquals("BKS", ks.getType());
+ assertEquals("BKS", KeyStore.getDefaultType());
+ }
+
+ /**
+ * Regression test for problem where close() resulted in a hand if
+ * a different thread was sitting in a blocking read or write.
+ */
+ public void testMultithreadedClose() throws Exception {
+ InetSocketAddress address = new InetSocketAddress("www.fortify.net", 443);
+ final Socket socket = clientFactory.createSocket();
+ socket.connect(address);
+
+ Thread reader = new Thread() {
+ @Override
+ public void run() {
+ try {
+ byte[] buffer = new byte[512];
+ InputStream stream = socket.getInputStream();
+ socket.getInputStream().read(buffer);
+ } catch (Exception ex) {
+ android.util.Log.d("SSLSocketTest",
+ "testMultithreadedClose() reader got " + ex.toString());
+ }
+ }
+ };
+
+ Thread closer = new Thread() {
+ @Override
+ public void run() {
+ try {
+ Thread.sleep(5000);
+ socket.close();
+ } catch (Exception ex) {
+ android.util.Log.d("SSLSocketTest",
+ "testMultithreadedClose() closer got " + ex.toString());
+ }
+ }
+ };
+
+ android.util.Log.d("SSLSocketTest", "testMultithreadedClose() starting reader...");
+ reader.start();
+ android.util.Log.d("SSLSocketTest", "testMultithreadedClose() starting closer...");
+ closer.start();
+
+ long t1 = System.currentTimeMillis();
+ android.util.Log.d("SSLSocketTest", "testMultithreadedClose() joining reader...");
+ reader.join(30000);
+ android.util.Log.d("SSLSocketTest", "testMultithreadedClose() joining closer...");
+ closer.join(30000);
+ long t2 = System.currentTimeMillis();
+
+ assertTrue("Concurrent close() hangs", t2 - t1 < 30000);
+ }
+
+ private int multithreadedFetchRuns;
+
+ private int multithreadedFetchWins;
+
+ private Random multithreadedFetchRandom = new Random();
+
+ /**
+ * Regression test for problem where multiple threads with multiple SSL
+ * connection would cause problems due to either missing native locking
+ * or the slowness of the SSL connections.
+ */
+ public void testMultithreadedFetch() {
+ Thread[] threads = new Thread[10];
+
+ for (int i = 0; i < threads.length; i++) {
+ threads[i] = new Thread() {
+ @Override
+ public void run() {
+ for (int i = 0; i < 10; i++) {
+ try {
+ multithreadedFetchRuns++;
+ switch (multithreadedFetchRandom.nextInt(4)) {
+ case 0: {
+ fetch("www.fortify.net", 443,
+ true, "/sslcheck.html", 1, 1, 0, 60);
+ break;
+ }
+
+ case 1: {
+ fetch("mail.google.com", 443, true, "/mail/", 1, 1, 0, 60);
+ break;
+ }
+
+ case 2: {
+ fetch("www.paypal.com", 443, true, "/", 1, 1, 0, 60);
+ break;
+ }
+
+ case 3: {
+ fetch("www.yellownet.ch", 443, true, "/", 1, 1, 0, 60);
+ break;
+ }
+ }
+ multithreadedFetchWins++;
+ } catch (Exception ex) {
+ android.util.Log.d("SSLSocketTest",
+ "testMultithreadedFetch() got Exception", ex);
+ }
+ }
+ }
+ };
+ threads[i].start();
+
+ android.util.Log.d("SSLSocketTest", "testMultithreadedFetch() started thread #" + i);
+ }
+
+ for (int i = 0; i < threads.length; i++) {
+ try {
+ threads[i].join();
+ android.util.Log.d("SSLSocketTest", "testMultithreadedFetch() joined thread #" + i);
+ } catch (InterruptedException ex) {
+ // Not interested.
+ }
+ }
+
+ assertTrue("At least 95% of multithreaded SSL connections must succeed",
+ multithreadedFetchWins >= (multithreadedFetchRuns * 95) / 100);
+ }
+
+ // -------------------------------------------------------------------------
+ // Regression test for #1204316: Missing client cert unit test. Passes on
+ // both Android and the RI. To use on the RI, install Apache Commons and
+ // replace the references to the base64-encoded keys by the JKS versions.
+ // -------------------------------------------------------------------------
+
+ /**
+ * Defines the keystore contents for the server, JKS version. Holds just a
+ * single self-generated key. The subject name is "Test Server".
+ */
+ private static final String SERVER_KEYS_JKS =
+ "/u3+7QAAAAIAAAABAAAAAQAFbXlrZXkAAAEaWFfBeAAAArowggK2MA4GCisGAQQBKgIRAQEFAASC" +
+ "AqI2kp5XjnF8YZkhcF92YsJNQkvsmH7zqMM87j23zSoV4DwyE3XeC/gZWq1ToScIhoqZkzlbWcu4" +
+ "T/Zfc/DrfGk/rKbBL1uWKGZ8fMtlZk8KoAhxZk1JSyJvdkyKxqmzUbxk1OFMlN2VJNu97FPVH+du" +
+ "dvjTvmpdoM81INWBW/1fZJeQeDvn4mMbbe0IxgpiLnI9WSevlaDP/sm1X3iO9yEyzHLL+M5Erspo" +
+ "Cwa558fOu5DdsICMXhvDQxjWFKFhPHnKtGe+VvwkG9/bAaDgx3kfhk0w5zvdnkKb+8Ed9ylNRzdk" +
+ "ocAa/mxlMTOsTvDKXjjsBupNPIIj7OP4GNnZaxkJjSs98pEO67op1GX2qhy6FSOPNuq8k/65HzUc" +
+ "PYn6voEeh6vm02U/sjEnzRevQ2+2wXoAdp0EwtQ/DlMe+NvcwPGWKuMgX4A4L93DZGb04N2VmAU3" +
+ "YLOtZwTO0LbuWrcCM/q99G/7LcczkxIVrO2I/rh8RXVczlf9QzcrFObFv4ATuspWJ8xG7DhsMbnk" +
+ "rT94Pq6TogYeoz8o8ZMykesAqN6mt/9+ToIemmXv+e+KU1hI5oLwWMnUG6dXM6hIvrULY6o+QCPH" +
+ "172YQJMa+68HAeS+itBTAF4Clm/bLn6reHCGGU6vNdwU0lYldpiOj9cB3t+u2UuLo6tiFWjLf5Zs" +
+ "EQJETd4g/EK9nHxJn0GAKrWnTw7pEHQJ08elzUuy04C/jEEG+4QXU1InzS4o/kR0Sqz2WTGDoSoq" +
+ "ewuPRU5bzQs/b9daq3mXrnPtRBL6HfSDAdpTK76iHqLCGdqx3avHjVSBm4zFvEuYBCev+3iKOBmg" +
+ "yh7eQRTjz4UOWfy85omMBr7lK8PtfVBDzOXpasxS0uBgdUyBDX4tO6k9jZ8a1kmQRQAAAAEABVgu" +
+ "NTA5AAACSDCCAkQwggGtAgRIR8SKMA0GCSqGSIb3DQEBBAUAMGkxCzAJBgNVBAYTAlVTMRMwEQYD" +
+ "VQQIEwpDYWxpZm9ybmlhMQwwCgYDVQQHEwNNVFYxDzANBgNVBAoTBkdvb2dsZTEQMA4GA1UECxMH" +
+ "QW5kcm9pZDEUMBIGA1UEAxMLVGVzdCBTZXJ2ZXIwHhcNMDgwNjA1MTA0ODQyWhcNMDgwOTAzMTA0" +
+ "ODQyWjBpMQswCQYDVQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTEMMAoGA1UEBxMDTVRWMQ8w" +
+ "DQYDVQQKEwZHb29nbGUxEDAOBgNVBAsTB0FuZHJvaWQxFDASBgNVBAMTC1Rlc3QgU2VydmVyMIGf" +
+ "MA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCwoC6chqCI84rj1PrXuJgbiit4EV909zR6N0jNlYfg" +
+ "itwB39bP39wH03rFm8T59b3mbSptnGmCIpLZn25KPPFsYD3JJ+wFlmiUdEP9H05flfwtFQJnw9uT" +
+ "3rRIdYVMPcQ3RoZzwAMliGr882I2thIDbA6xjGU/1nRIdvk0LtxH3QIDAQABMA0GCSqGSIb3DQEB" +
+ "BAUAA4GBAJn+6YgUlY18Ie+0+Vt8oEi81DNi/bfPrAUAh63fhhBikx/3R9dl3wh09Z6p7cIdNxjW" +
+ "n2ll+cRW9eqF7z75F0Omm0C7/KAEPjukVbszmzeU5VqzkpSt0j84YWi+TfcHRrfvhLbrlmGITVpY" +
+ "ol5pHLDyqGmDs53pgwipWqsn/nEXEBgj3EoqPeqHbDf7YaP8h/5BSt0=";
+
+ /**
+ * Defines the keystore contents for the server, BKS version. Holds just a
+ * single self-generated key. The subject name is "Test Server".
+ */
+ private static final String SERVER_KEYS_BKS =
+ "AAAAAQAAABQDkebzoP1XwqyWKRCJEpn/t8dqIQAABDkEAAVteWtleQAAARpYl20nAAAAAQAFWC41" +
+ "MDkAAAJNMIICSTCCAbKgAwIBAgIESEfU1jANBgkqhkiG9w0BAQUFADBpMQswCQYDVQQGEwJVUzET" +
+ "MBEGA1UECBMKQ2FsaWZvcm5pYTEMMAoGA1UEBxMDTVRWMQ8wDQYDVQQKEwZHb29nbGUxEDAOBgNV" +
+ "BAsTB0FuZHJvaWQxFDASBgNVBAMTC1Rlc3QgU2VydmVyMB4XDTA4MDYwNTExNTgxNFoXDTA4MDkw" +
+ "MzExNTgxNFowaTELMAkGA1UEBhMCVVMxEzARBgNVBAgTCkNhbGlmb3JuaWExDDAKBgNVBAcTA01U" +
+ "VjEPMA0GA1UEChMGR29vZ2xlMRAwDgYDVQQLEwdBbmRyb2lkMRQwEgYDVQQDEwtUZXN0IFNlcnZl" +
+ "cjCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA0LIdKaIr9/vsTq8BZlA3R+NFWRaH4lGsTAQy" +
+ "DPMF9ZqEDOaL6DJuu0colSBBBQ85hQTPa9m9nyJoN3pEi1hgamqOvQIWcXBk+SOpUGRZZFXwniJV" +
+ "zDKU5nE9MYgn2B9AoiH3CSuMz6HRqgVaqtppIe1jhukMc/kHVJvlKRNy9XMCAwEAATANBgkqhkiG" +
+ "9w0BAQUFAAOBgQC7yBmJ9O/eWDGtSH9BH0R3dh2NdST3W9hNZ8hIa8U8klhNHbUCSSktZmZkvbPU" +
+ "hse5LI3dh6RyNDuqDrbYwcqzKbFJaq/jX9kCoeb3vgbQElMRX8D2ID1vRjxwlALFISrtaN4VpWzV" +
+ "yeoHPW4xldeZmoVtjn8zXNzQhLuBqX2MmAAAAqwAAAAUvkUScfw9yCSmALruURNmtBai7kQAAAZx" +
+ "4Jmijxs/l8EBaleaUru6EOPioWkUAEVWCxjM/TxbGHOi2VMsQWqRr/DZ3wsDmtQgw3QTrUK666sR" +
+ "MBnbqdnyCyvM1J2V1xxLXPUeRBmR2CXorYGF9Dye7NkgVdfA+9g9L/0Au6Ugn+2Cj5leoIgkgApN" +
+ "vuEcZegFlNOUPVEs3SlBgUF1BY6OBM0UBHTPwGGxFBBcetcuMRbUnu65vyDG0pslT59qpaR0TMVs" +
+ "P+tcheEzhyjbfM32/vwhnL9dBEgM8qMt0sqF6itNOQU/F4WGkK2Cm2v4CYEyKYw325fEhzTXosck" +
+ "MhbqmcyLab8EPceWF3dweoUT76+jEZx8lV2dapR+CmczQI43tV9btsd1xiBbBHAKvymm9Ep9bPzM" +
+ "J0MQi+OtURL9Lxke/70/MRueqbPeUlOaGvANTmXQD2OnW7PISwJ9lpeLfTG0LcqkoqkbtLKQLYHI" +
+ "rQfV5j0j+wmvmpMxzjN3uvNajLa4zQ8l0Eok9SFaRr2RL0gN8Q2JegfOL4pUiHPsh64WWya2NB7f" +
+ "V+1s65eA5ospXYsShRjo046QhGTmymwXXzdzuxu8IlnTEont6P4+J+GsWk6cldGbl20hctuUKzyx" +
+ "OptjEPOKejV60iDCYGmHbCWAzQ8h5MILV82IclzNViZmzAapeeCnexhpXhWTs+xDEYSKEiG/camt" +
+ "bhmZc3BcyVJrW23PktSfpBQ6D8ZxoMfF0L7V2GQMaUg+3r7ucrx82kpqotjv0xHghNIm95aBr1Qw" +
+ "1gaEjsC/0wGmmBDg1dTDH+F1p9TInzr3EFuYD0YiQ7YlAHq3cPuyGoLXJ5dXYuSBfhDXJSeddUkl" +
+ "k1ufZyOOcskeInQge7jzaRfmKg3U94r+spMEvb0AzDQVOKvjjo1ivxMSgFRZaDb/4qw=";
+
+ /**
+ * Defines the keystore contents for the client, JKS version. Holds just a
+ * single self-generated key. The subject name is "Test Client".
+ */
+ private static final String CLIENT_KEYS_JKS =
+ "/u3+7QAAAAIAAAABAAAAAQAFbXlrZXkAAAEaWFhyMAAAArkwggK1MA4GCisGAQQBKgIRAQEFAASC" +
+ "AqGVSfXolBStZy4nnRNn4fAr+S7kfU2BS23wwW8uB2Ru3GvtLzlK9q08Gvq/LNqBafjyFTVL5FV5" +
+ "SED/8YomO5a98GpskSeRvytCiTBLJdgGhws5TOGekgIAcBROPGIyOtJPQ0HfOQs+BqgzGDHzHQhw" +
+ "u/8Tm6yQwiP+W/1I9B1QnaEztZA3mhTyMMJsmsFTYroGgAog885D5Cmzd8sYGfxec3R6I+xcmBAY" +
+ "eibR5kGpWwt1R+qMvRrtBqh5r6WSKhCBNax+SJVbtUNRiKyjKccdJg6fGqIWWeivwYTy0OhjA6b4" +
+ "NiZ/ZZs5pxFGWUj/Rlp0RYy8fCF6aw5/5s4Bf4MI6dPSqMG8Hf7sJR91GbcELyzPdM0h5lNavgit" +
+ "QPEzKeuDrGxhY1frJThBsNsS0gxeu+OgfJPEb/H4lpYX5IvuIGbWKcxoO9zq4/fimIZkdA8A+3eY" +
+ "mfDaowvy65NBVQPJSxaOyFhLHfeLqOeCsVENAea02vA7andZHTZehvcrqyKtm+z8ncHGRC2H9H8O" +
+ "jKwKHfxxrYY/jMAKLl00+PBb3kspO+BHI2EcQnQuMw/zr83OR9Meq4TJ0TMuNkApZELAeFckIBbS" +
+ "rBr8NNjAIfjuCTuKHhsTFWiHfk9ZIzigxXagfeDRiyVc6khOuF/bGorj23N2o7Rf3uLoU6PyXWi4" +
+ "uhctR1aL6NzxDoK2PbYCeA9hxbDv8emaVPIzlVwpPK3Ruvv9mkjcOhZ74J8bPK2fQmbplbOljcZi" +
+ "tZijOfzcO/11JrwhuJZRA6wanTqHoujgChV9EukVrmbWGGAcewFnAsSbFXIik7/+QznXaDIt5NgL" +
+ "H/Bcz4Z/fdV7Ae1eUaxKXdPbI//4J+8liVT/d8awjW2tldIaDlmGMR3aoc830+3mAAAAAQAFWC41" +
+ "MDkAAAJIMIICRDCCAa0CBEhHxLgwDQYJKoZIhvcNAQEEBQAwaTELMAkGA1UEBhMCVVMxEzARBgNV" +
+ "BAgTCkNhbGlmb3JuaWExDDAKBgNVBAcTA01UVjEPMA0GA1UEChMGR29vZ2xlMRAwDgYDVQQLEwdB" +
+ "bmRyb2lkMRQwEgYDVQQDEwtUZXN0IENsaWVudDAeFw0wODA2MDUxMDQ5MjhaFw0wODA5MDMxMDQ5" +
+ "MjhaMGkxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpDYWxpZm9ybmlhMQwwCgYDVQQHEwNNVFYxDzAN" +
+ "BgNVBAoTBkdvb2dsZTEQMA4GA1UECxMHQW5kcm9pZDEUMBIGA1UEAxMLVGVzdCBDbGllbnQwgZ8w" +
+ "DQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAIK3Q+KiFbmCGg422TAo4gggdhMH6FJhiuz8DxRyeMKR" +
+ "UAfP4MK0wtc8N42waZ6OKvxpBFUy0BRfBsX0GD4Ku99yu9/tavSigTraeJtwV3WWRRjIqk7L3wX5" +
+ "cmgS2KSD43Y0rNUKrko26lnt9N4qiYRBSj+tcAN3Lx9+ptqk1LApAgMBAAEwDQYJKoZIhvcNAQEE" +
+ "BQADgYEANb7Q1GVSuy1RPJ0FmiXoMYCCtvlRLkmJphwxovK0cAQK12Vll+yAzBhHiQHy/RA11mng" +
+ "wYudC7u3P8X/tBT8GR1Yk7QW3KgFyPafp3lQBBCraSsfrjKj+dCLig1uBLUr4f68W8VFWZWWTHqp" +
+ "NMGpCX6qmjbkJQLVK/Yfo1ePaUexPSOX0G9m8+DoV3iyNw6at01NRw==";
+
+ /**
+ * Defines the keystore contents for the client, BKS version. Holds just a
+ * single self-generated key. The subject name is "Test Client".
+ */
+ private static final String CLIENT_KEYS_BKS =
+ "AAAAAQAAABT4Rka6fxbFps98Y5k2VilmbibNkQAABfQEAAVteWtleQAAARpYl+POAAAAAQAFWC41" +
+ "MDkAAAJNMIICSTCCAbKgAwIBAgIESEfU9TANBgkqhkiG9w0BAQUFADBpMQswCQYDVQQGEwJVUzET" +
+ "MBEGA1UECBMKQ2FsaWZvcm5pYTEMMAoGA1UEBxMDTVRWMQ8wDQYDVQQKEwZHb29nbGUxEDAOBgNV" +
+ "BAsTB0FuZHJvaWQxFDASBgNVBAMTC1Rlc3QgQ2xpZW50MB4XDTA4MDYwNTExNTg0NVoXDTA4MDkw" +
+ "MzExNTg0NVowaTELMAkGA1UEBhMCVVMxEzARBgNVBAgTCkNhbGlmb3JuaWExDDAKBgNVBAcTA01U" +
+ "VjEPMA0GA1UEChMGR29vZ2xlMRAwDgYDVQQLEwdBbmRyb2lkMRQwEgYDVQQDEwtUZXN0IENsaWVu" +
+ "dDCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEApUvmWsQDHPpbDKK13Yez2/q54tTOmRml/qva" +
+ "2K6dZjkjSTW0iRuk7ztaVEvdJpfVIDv1oBsCI51ttyLHROy1epjF+GoL74mJb7fkcd0VOoSOTjtD" +
+ "+3GgZkHPAm5YmUYxiJXqxKKJJqMCTIW46eJaA2nAep9QIwZ14/NFAs4ObV8CAwEAATANBgkqhkiG" +
+ "9w0BAQUFAAOBgQCJrCr3hZQFDlLIfsSKI1/w+BLvyf4fubOid0pBxfklR8KBNPTiqjSmu7pd/C/F" +
+ "1FR8CdZUDoPflZHCOU+fj5r5KUC1HyigY/tEUvlforBpfB0uCF+tXW4DbUfOWhfMtLV4nCOJOOZg" +
+ "awfZLJWBJouLKOp427vDftxTSB+Ks8YjlgAAAqwAAAAU+NH6TtrzjyDdCXm5B6Vo7xX5G4YAAAZx" +
+ "EAUkcZtmykn7YdaYxC1jRFJ+GEJpC8nZVg83QClVuCSIS8a5f8Hl44Bk4oepOZsPzhtz3RdVzDVi" +
+ "RFfoyZFsrk9F5bDTVJ6sQbb/1nfJkLhZFXokka0vND5AXMSoD5Bj1Fqem3cK7fSUyqKvFoRKC3XD" +
+ "FQvhqoam29F1rbl8FaYdPvhhZo8TfZQYUyUKwW+RbR44M5iHPx+ykieMe/C/4bcM3z8cwIbYI1aO" +
+ "gjQKS2MK9bs17xaDzeAh4sBKrskFGrDe+2dgvrSKdoakJhLTNTBSG6m+rzqMSCeQpafLKMSjTSSz" +
+ "+KoQ9bLyax8cbvViGGju0SlVhquloZmKOfHr8TukIoV64h3uCGFOVFtQjCYDOq6NbfRvMh14UVF5" +
+ "zgDIGczoD9dMoULWxBmniGSntoNgZM+QP6Id7DBasZGKfrHIAw3lHBqcvB5smemSu7F4itRoa3D8" +
+ "N7hhUEKAc+xA+8NKmXfiCBoHfPHTwDvt4IR7gWjeP3Xv5vitcKQ/MAfO5RwfzkYCXQ3FfjfzmsE1" +
+ "1IfLRDiBj+lhQSulhRVStKI88Che3M4JUNGKllrc0nt1pWa1vgzmUhhC4LSdm6trTHgyJnB6OcS9" +
+ "t2furYjK88j1AuB4921oxMxRm8c4Crq8Pyuf+n3YKi8Pl2BzBtw++0gj0ODlgwut8SrVj66/nvIB" +
+ "jN3kLVahR8nZrEFF6vTTmyXi761pzq9yOVqI57wJGx8o3Ygox1p+pWUPl1hQR7rrhUbgK/Q5wno9" +
+ "uJk07h3IZnNxE+/IKgeMTP/H4+jmyT4mhsexJ2BFHeiKF1KT/FMcJdSi+ZK5yoNVcYuY8aZbx0Ef" +
+ "lHorCXAmLFB0W6Cz4KPP01nD9YBB4olxiK1t7m0AU9zscdivNiuUaB5OIEr+JuZ6dNw=";
+ /**
+ * Defines the password for the keystore.
+ */
+ private static final String PASSWORD = "android";
+
+ /**
+ * Implements basically a dummy TrustManager. It stores the certificate
+ * chain it sees, so it can later be queried.
+ */
+ class TestTrustManager implements X509TrustManager {
+
+ private X509Certificate[] chain;
+
+ private String authType;
+
+ public void checkClientTrusted(X509Certificate[] chain, String authType) {
+ this.chain = chain;
+ this.authType = authType;
+ }
+
+ public void checkServerTrusted(X509Certificate[] chain, String authType) {
+ this.chain = chain;
+ this.authType = authType;
+ }
+
+ public X509Certificate[] getAcceptedIssuers() {
+ return new X509Certificate[0];
+ }
+
+ public X509Certificate[] getChain() {
+ return chain;
+ }
+
+ public String getAuthType() {
+ return authType;
+ }
+
+ }
+
+ /**
+ * Implements a test SSL socket server. It wait for a connection on a given
+ * port, requests client authentication (if specified), and read 256 bytes
+ * from the socket.
+ */
+ class TestServer implements Runnable {
+
+ public static final int CLIENT_AUTH_NONE = 0;
+
+ public static final int CLIENT_AUTH_WANTED = 1;
+
+ public static final int CLIENT_AUTH_NEEDED = 2;
+
+ private TestTrustManager trustManager;
+
+ private Exception exception;
+
+ private int port;
+
+ private int clientAuth;
+
+ private boolean provideKeys;
+
+ public TestServer(int port, boolean provideKeys, int clientAuth) {
+ this.port = port;
+ this.clientAuth = clientAuth;
+ this.provideKeys = provideKeys;
+
+ trustManager = new TestTrustManager();
+ }
+
+ public void run() {
+ try {
+ KeyManager[] keyManagers = provideKeys
+ ? getKeyManagers(SERVER_KEYS_BKS) : null;
+ TrustManager[] trustManagers = new TrustManager[] {
+ trustManager };
+
+ SSLContext sslContext = SSLContext.getInstance("TLS");
+ sslContext.init(keyManagers, trustManagers, null);
+
+ SSLServerSocket serverSocket
+ = (SSLServerSocket) sslContext.getServerSocketFactory()
+ .createServerSocket();
+
+ if (clientAuth == CLIENT_AUTH_WANTED) {
+ serverSocket.setWantClientAuth(true);
+ } else if (clientAuth == CLIENT_AUTH_NEEDED) {
+ serverSocket.setNeedClientAuth(true);
+ } else {
+ serverSocket.setWantClientAuth(false);
+ }
+
+ serverSocket.bind(new InetSocketAddress(port));
+
+ SSLSocket clientSocket = (SSLSocket) serverSocket.accept();
+
+ InputStream stream = clientSocket.getInputStream();
+
+ for (int i = 0; i < 256; i++) {
+ int j = stream.read();
+ if (i != j) {
+ throw new RuntimeException("Error reading socket,"
+ + " expected " + i + ", got " + j);
+ }
+ }
+
+ stream.close();
+ clientSocket.close();
+ serverSocket.close();
+
+ } catch (Exception ex) {
+ exception = ex;
+ }
+ }
+
+ public Exception getException() {
+ return exception;
+ }
+
+ public X509Certificate[] getChain() {
+ return trustManager.getChain();
+ }
+
+ }
+
+ /**
+ * Implements a test SSL socket client. It open a connection to localhost on
+ * a given port and writes 256 bytes to the socket.
+ */
+ class TestClient implements Runnable {
+
+ private TestTrustManager trustManager;
+
+ private Exception exception;
+
+ private int port;
+
+ private boolean provideKeys;
+
+ public TestClient(int port, boolean provideKeys) {
+ this.port = port;
+ this.provideKeys = provideKeys;
+
+ trustManager = new TestTrustManager();
+ }
+
+ public void run() {
+ try {
+ KeyManager[] keyManagers = provideKeys
+ ? getKeyManagers(CLIENT_KEYS_BKS) : null;
+ TrustManager[] trustManagers = new TrustManager[] {
+ trustManager };
+
+ SSLContext sslContext = SSLContext.getInstance("TLS");
+ sslContext.init(keyManagers, trustManagers, null);
+
+ SSLSocket socket = (SSLSocket) sslContext.getSocketFactory()
+ .createSocket();
+
+ socket.connect(new InetSocketAddress(port));
+ socket.startHandshake();
+
+ OutputStream stream = socket.getOutputStream();
+
+ for (int i = 0; i < 256; i++) {
+ stream.write(i);
+ }
+
+ stream.flush();
+ stream.close();
+ socket.close();
+
+ } catch (Exception ex) {
+ exception = ex;
+ }
+ }
+
+ public Exception getException() {
+ return exception;
+ }
+
+ public X509Certificate[] getChain() {
+ return trustManager.getChain();
+ }
+
+ }
+
+ /**
+ * Loads a keystore from a base64-encoded String. Returns the KeyManager[]
+ * for the result.
+ */
+ private KeyManager[] getKeyManagers(String keys) throws Exception {
+ byte[] bytes = new Base64().decode(keys.getBytes());
+ InputStream inputStream = new ByteArrayInputStream(bytes);
+
+ KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
+ keyStore.load(inputStream, PASSWORD.toCharArray());
+ inputStream.close();
+
+ String algorithm = KeyManagerFactory.getDefaultAlgorithm();
+ KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(algorithm);
+ keyManagerFactory.init(keyStore, PASSWORD.toCharArray());
+
+ return keyManagerFactory.getKeyManagers();
+ }
+
+ /**
+ * Implements the actual test case. Launches a server and a client, requires
+ * client authentication and checks the certificates afterwards (not in the
+ * usual sense, we just make sure that we got the expected certificates,
+ * because our self-signed test certificates are not valid.)
+ */
+ public void testClientAuth() {
+ try {
+ TestServer server = new TestServer(8088, true, TestServer.CLIENT_AUTH_WANTED);
+ TestClient client = new TestClient(8088, true);
+
+ Thread serverThread = new Thread(server);
+ Thread clientThread = new Thread(client);
+
+ serverThread.start();
+ clientThread.start();
+
+ serverThread.join();
+ clientThread.join();
+
+ // The server must have completed without an exception.
+ if (server.getException() != null) {
+ throw new RuntimeException(server.getException());
+ }
+
+ // The client must have completed without an exception.
+ if (client.getException() != null) {
+ throw new RuntimeException(client.getException());
+ }
+
+ // Caution: The clientChain is the certificate chain from our
+ // client object. It contains the server certificates, of course!
+ X509Certificate[] clientChain = client.getChain();
+ assertTrue("Client cert chain must not be null", clientChain != null);
+ assertTrue("Client cert chain must not be empty", clientChain.length != 0);
+ assertEquals("CN=Test Server, OU=Android, O=Google, L=MTV, ST=California, C=US", clientChain[0].getSubjectDN().toString());
+ // Important part ------^
+
+ // Caution: The serverChain is the certificate chain from our
+ // server object. It contains the client certificates, of course!
+ X509Certificate[] serverChain = server.getChain();
+ assertTrue("Server cert chain must not be null", serverChain != null);
+ assertTrue("Server cert chain must not be empty", serverChain.length != 0);
+ assertEquals("CN=Test Client, OU=Android, O=Google, L=MTV, ST=California, C=US", serverChain[0].getSubjectDN().toString());
+ // Important part ------^
+
+ } catch (Exception ex) {
+ throw new RuntimeException(ex);
+ }
+ }
+
+ // -------------------------------------------------------------------------
+ private SSLSocket handshakeSocket;
+
+ private Exception handshakeException;
+
+
+ public void testSSLHandshakeHangTimeout() {
+
+ Thread thread = new Thread() {
+ @Override
+ public void run() {
+ try {
+ SSLSocket socket = (SSLSocket)clientFactory.createSocket(
+ "www.heise.de", 80);
+ socket.setSoTimeout(5000);
+ socket.startHandshake();
+ socket.close();
+ } catch (Exception ex) {
+ handshakeException = ex;
+ }
+ }
+ };
+
+ thread.start();
+
+ try {
+ thread.join(10000);
+ } catch (InterruptedException ex) {
+ // Ignore.
+ }
+
+ if (handshakeException == null) {
+ fail("SSL handshake should have failed.");
+ }
+ }
+
+ public void testSSLHandshakeHangClose() {
+
+ Thread thread = new Thread() {
+ @Override
+ public void run() {
+ try {
+ handshakeSocket = (SSLSocket)clientFactory.createSocket(
+ "www.heise.de", 80);
+ handshakeSocket.startHandshake();
+ } catch (Exception ex) {
+ handshakeException = ex;
+ }
+ }
+ };
+
+ thread.start();
+
+
+ try {
+ Thread.sleep(5000);
+ try {
+ handshakeSocket.close();
+ } catch (Exception ex) {
+ throw new RuntimeException(ex);
+ }
+
+ thread.join(5000);
+ } catch (InterruptedException ex) {
+ // Ignore.
+ }
+
+ if (handshakeException == null) {
+ fail("SSL handshake should have failed.");
+ }
+ }
+
+ /**
+ * Tests our in-memory and persistent caching support.
+ */
+ public void testClientSessionCaching() throws IOException,
+ KeyManagementException {
+ SSLContextImpl context = new SSLContextImpl();
+
+ // Cache size = 2.
+ FakeClientSessionCache fakeCache = new FakeClientSessionCache();
+ context.engineInit(null, null, null, fakeCache, null);
+ SSLSocketFactory socketFactory = context.engineGetSocketFactory();
+ context.engineGetClientSessionContext().setSessionCacheSize(2);
+ makeRequests(socketFactory);
+ List<String> smallCacheOps = Arrays.asList(
+ "get www.fortify.net",
+ "put www.fortify.net",
+ "get www.paypal.com",
+ "put www.paypal.com",
+ "get www.yellownet.ch",
+ "put www.yellownet.ch",
+
+ // At this point, all in-memory cache requests should miss,
+ // but the sessions will still be in the persistent cache.
+ "get www.fortify.net",
+ "get www.paypal.com",
+ "get www.yellownet.ch"
+ );
+ assertEquals(smallCacheOps, fakeCache.ops);
+
+ // Cache size = 3.
+ fakeCache = new FakeClientSessionCache();
+ context.engineInit(null, null, null, fakeCache, null);
+ socketFactory = context.engineGetSocketFactory();
+ context.engineGetClientSessionContext().setSessionCacheSize(3);
+ makeRequests(socketFactory);
+ List<String> bigCacheOps = Arrays.asList(
+ "get www.fortify.net",
+ "put www.fortify.net",
+ "get www.paypal.com",
+ "put www.paypal.com",
+ "get www.yellownet.ch",
+ "put www.yellownet.ch"
+
+ // At this point, all results should be in the in-memory
+ // cache, and the persistent cache shouldn't be hit anymore.
+ );
+ assertEquals(bigCacheOps, fakeCache.ops);
+
+ // Cache size = 4.
+ fakeCache = new FakeClientSessionCache();
+ context.engineInit(null, null, null, fakeCache, null);
+ socketFactory = context.engineGetSocketFactory();
+ context.engineGetClientSessionContext().setSessionCacheSize(4);
+ makeRequests(socketFactory);
+ assertEquals(bigCacheOps, fakeCache.ops);
+ }
+
+ /**
+ * Executes sequence of requests twice using given socket factory.
+ */
+ private void makeRequests(SSLSocketFactory socketFactory)
+ throws IOException {
+ for (int i = 0; i < 2; i++) {
+ fetch(socketFactory, "www.fortify.net", 443, true, "/sslcheck.html",
+ 1, 1, 0, 60);
+ fetch(socketFactory, "www.paypal.com", 443, true, "/",
+ 1, 1, 0, 60);
+ fetch(socketFactory, "www.yellownet.ch", 443, true, "/",
+ 1, 1, 0, 60);
+ }
+ }
+
+ /**
+ * Fake in the sense that it doesn't actually persist anything.
+ */
+ static class FakeClientSessionCache implements SSLClientSessionCache {
+
+ List<String> ops = new ArrayList<String>();
+ Map<String, byte[]> sessions = new HashMap<String, byte[]>();
+
+ public byte[] getSessionData(String host, int port) {
+ ops.add("get " + host);
+ return sessions.get(host);
+ }
+
+ public void putSessionData(SSLSession session, byte[] sessionData) {
+ String host = session.getPeerHost();
+ System.err.println("length: " + sessionData.length);
+ ops.add("put " + host);
+ sessions.put(host, sessionData);
+ }
+ }
+
+ public void testFileBasedClientSessionCache() throws IOException,
+ KeyManagementException {
+ SSLContextImpl context = new SSLContextImpl();
+ String tmpDir = System.getProperty("java.io.tmpdir");
+ if (tmpDir == null) {
+ fail("Please set 'java.io.tmpdir' system property.");
+ }
+ File cacheDir = new File(tmpDir
+ + "/" + SSLSocketTest.class.getName() + "/cache");
+ deleteDir(cacheDir);
+ SSLClientSessionCache fileCache
+ = FileClientSessionCache.usingDirectory(cacheDir);
+ try {
+ ClientSessionCacheProxy cacheProxy
+ = new ClientSessionCacheProxy(fileCache);
+ context.engineInit(null, null, null, cacheProxy, null);
+ SSLSocketFactory socketFactory = context.engineGetSocketFactory();
+ context.engineGetClientSessionContext().setSessionCacheSize(1);
+ makeRequests(socketFactory);
+ List<String> expected = Arrays.asList(
+ "unsuccessful get www.fortify.net",
+ "put www.fortify.net",
+ "unsuccessful get www.paypal.com",
+ "put www.paypal.com",
+ "unsuccessful get www.yellownet.ch",
+ "put www.yellownet.ch",
+
+ // At this point, all in-memory cache requests should miss,
+ // but the sessions will still be in the persistent cache.
+ "successful get www.fortify.net",
+ "successful get www.paypal.com",
+ "successful get www.yellownet.ch"
+ );
+ assertEquals(expected, cacheProxy.ops);
+
+ // Try again now that file-based cache is populated.
+ fileCache = FileClientSessionCache.usingDirectory(cacheDir);
+ cacheProxy = new ClientSessionCacheProxy(fileCache);
+ context.engineInit(null, null, null, cacheProxy, null);
+ socketFactory = context.engineGetSocketFactory();
+ context.engineGetClientSessionContext().setSessionCacheSize(1);
+ makeRequests(socketFactory);
+ expected = Arrays.asList(
+ "successful get www.fortify.net",
+ "successful get www.paypal.com",
+ "successful get www.yellownet.ch",
+ "successful get www.fortify.net",
+ "successful get www.paypal.com",
+ "successful get www.yellownet.ch"
+ );
+ assertEquals(expected, cacheProxy.ops);
+ } finally {
+ deleteDir(cacheDir);
+ }
+ }
+
+ private static void deleteDir(File directory) {
+ if (!directory.exists()) {
+ return;
+ }
+ for (File file : directory.listFiles()) {
+ file.delete();
+ }
+ directory.delete();
+ }
+
+ static class ClientSessionCacheProxy implements SSLClientSessionCache {
+
+ final SSLClientSessionCache delegate;
+ final List<String> ops = new ArrayList<String>();
+
+ ClientSessionCacheProxy(SSLClientSessionCache delegate) {
+ this.delegate = delegate;
+ }
+
+ public byte[] getSessionData(String host, int port) {
+ byte[] sessionData = delegate.getSessionData(host, port);
+ ops.add((sessionData == null ? "unsuccessful" : "successful")
+ + " get " + host);
+ return sessionData;
+ }
+
+ public void putSessionData(SSLSession session, byte[] sessionData) {
+ delegate.putSessionData(session, sessionData);
+ ops.add("put " + session.getPeerHost());
+ }
+ }
+
+ public static void main(String[] args) throws KeyManagementException, IOException {
+ new SSLSocketTest().testFileBasedClientSessionCache();
+ }
+}
diff --git a/tests/CoreTests/android/core/Sha1Test.java b/tests/CoreTests/android/core/Sha1Test.java
new file mode 100644
index 0000000..dcd4c04
--- /dev/null
+++ b/tests/CoreTests/android/core/Sha1Test.java
@@ -0,0 +1,69 @@
+/*
+ * 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 android.core;
+
+import android.security.MessageDigest;
+import android.test.suitebuilder.annotation.SmallTest;
+import junit.framework.TestCase;
+
+/**
+ * Tests SHA1 message digest algorithm.
+ */
+public class Sha1Test extends TestCase {
+ class TestData {
+ private String input;
+ private String result;
+
+ public TestData(String i, String r) {
+ input = i;
+ result = r;
+ }
+ }
+
+ TestData[] mTestData = new TestData[]{
+ new TestData("abc", "a9993e364706816aba3e25717850c26c9cd0d89d"),
+ new TestData("abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq",
+ "84983e441c3bd26ebaae4aa1f95129e5e54670f1")
+ };
+
+ @SmallTest
+ public void testSha1() throws Exception {
+ MessageDigest digest = MessageDigest.getInstance("SHA-1");
+
+ int numTests = mTestData.length;
+ for (int i = 0; i < numTests; i++) {
+ digest.update(mTestData[i].input.getBytes());
+ byte[] hash = digest.digest();
+ String encodedHash = encodeHex(hash);
+ assertEquals(encodedHash, mTestData[i].result);
+ }
+ }
+
+ private static String encodeHex(byte[] bytes) {
+ StringBuffer hex = new StringBuffer(bytes.length * 2);
+
+ for (int i = 0; i < bytes.length; i++) {
+ if (((int) bytes[i] & 0xff) < 0x10) {
+ hex.append("0");
+ }
+ hex.append(Integer.toString((int) bytes[i] & 0xff, 16));
+ }
+
+ return hex.toString();
+ }
+}
+
diff --git a/tests/CoreTests/android/core/SocketTest.java b/tests/CoreTests/android/core/SocketTest.java
new file mode 100644
index 0000000..b64c156
--- /dev/null
+++ b/tests/CoreTests/android/core/SocketTest.java
@@ -0,0 +1,288 @@
+/*
+ * 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 android.core;
+
+import junit.framework.Assert;
+import junit.framework.TestCase;
+
+import java.io.IOException;
+import java.net.InetAddress;
+import java.net.InetSocketAddress;
+import java.net.ServerSocket;
+import java.net.Socket;
+import java.net.SocketException;
+import java.net.SocketTimeoutException;
+import java.nio.channels.SocketChannel;
+import java.util.concurrent.Semaphore;
+
+import android.test.suitebuilder.annotation.LargeTest;
+import android.test.suitebuilder.annotation.SmallTest;
+import android.test.suitebuilder.annotation.Suppress;
+
+/**
+ * Regression tests for various socket related problems. And a few general
+ * socket tests.
+ */
+public class SocketTest extends TestCase {
+
+ private static final String NON_EXISTING_ADDRESS = "123.123.123.123";
+
+ private static final String KNOW_GOOD_ADDRESS = "209.85.129.147";
+
+ private static final String PACKAGE_DROPPING_ADDRESS = "191.167.0.1";
+
+ // Test for basic bind/connect/accept behavior.
+ @SmallTest
+ public void testSocketSimple() throws Exception {
+ ServerSocket ss;
+ Socket s, s1;
+ int port;
+
+ IOException lastEx = null;
+
+ ss = new ServerSocket();
+
+ for (port = 9900; port < 9999; port++) {
+ try {
+ ss.bind(new InetSocketAddress("127.0.0.1", port));
+ lastEx = null;
+ break;
+ } catch (IOException ex) {
+ lastEx = ex;
+ }
+ }
+
+ if (lastEx != null) {
+ throw lastEx;
+ }
+
+ s = new Socket("127.0.0.1", port);
+
+ s1 = ss.accept();
+
+ s.getOutputStream().write(0xa5);
+
+ assertEquals(0xa5, s1.getInputStream().read());
+
+ s1.getOutputStream().write(0x5a);
+ assertEquals(0x5a, s.getInputStream().read());
+ }
+
+ // Regression test for #820068: Wildcard address
+ @SmallTest
+ public void testWildcardAddress() throws Exception {
+ Socket s2 = new Socket();
+ s2.bind(new InetSocketAddress((InetAddress) null, 12345));
+ byte[] addr = s2.getLocalAddress().getAddress();
+ for (int i = 0; i < 4; i++) {
+ assertEquals("Not the wildcard address", 0, addr[i]);
+ }
+ }
+
+ // Regression test for #865753: server sockets not closing properly
+ @SmallTest
+ public void testServerSocketClose() throws Exception {
+ ServerSocket s3 = new ServerSocket(23456);
+ s3.close();
+ ServerSocket s4 = new ServerSocket(23456);
+ s4.close();
+ }
+
+ // Regression test for #876985: SO_REUSEADDR not working properly
+
+ private Exception serverError = null;
+
+ @LargeTest
+ public void testSetReuseAddress() throws IOException {
+ InetSocketAddress addr = new InetSocketAddress(8383);
+
+ final ServerSocket serverSock = new ServerSocket();
+ serverSock.setReuseAddress(true);
+ serverSock.bind(addr);
+
+ final Semaphore semThreadEnd = new Semaphore(0);
+ new Thread() {
+ @Override
+ public void run() {
+ try {
+ Socket sock = serverSock.accept();
+ sock.getInputStream().read();
+ sock.close();
+ } catch (IOException e) {
+ serverError = e;
+ }
+ semThreadEnd.release();
+ }
+ }.start();
+
+ // Give the server a bit of time for startup
+ try {
+ Thread.sleep(2000);
+ } catch (InterruptedException ex) {
+ // Ignored.
+ }
+
+ Socket client = new Socket("localhost", 8383);
+ client.getOutputStream().write(1);
+ // Just leave this connection open from the client side. It will be
+ // closed from the server side so the server stays in the TIME_WAIT
+ // state for a while. setReuseAddress() should be able to handle this.
+
+ try {
+ semThreadEnd.acquire();
+ } catch (InterruptedException e) {
+ // ignore
+ }
+ serverSock.close();
+
+ ServerSocket serverSock2 = new ServerSocket();
+ serverSock2.setReuseAddress(true);
+ serverSock2.bind(addr);
+ serverSock2.close();
+
+ if (serverError != null) {
+ throw new RuntimeException("Server must complete without error", serverError);
+ }
+ }
+
+ // Regression for 916701, a wrong exception was thrown after timeout of
+ // a ServerSocket.
+ @LargeTest
+ public void testTimeoutException() throws IOException {
+ ServerSocket s = new ServerSocket(9800);
+ s.setSoTimeout(2000);
+ try {
+ s.accept();
+ } catch (SocketTimeoutException e) {
+ // this is ok.
+ }
+ }
+
+ // Regression for issue 1001980, openening a SocketChannel threw an Exception
+ @SmallTest
+ public void testNativeSocketChannelOpen() throws IOException {
+ SocketChannel.open();
+ }
+
+ // Regression test for issue 1018016, connecting ignored a set timeout.
+ @LargeTest
+ public void testSocketSetSOTimeout() throws IOException {
+ Socket sock = new Socket();
+ int timeout = 5000;
+ long start = System.currentTimeMillis();
+ try {
+ sock.connect(new InetSocketAddress(NON_EXISTING_ADDRESS, 80), timeout);
+ } catch (SocketTimeoutException e) {
+ // expected
+ long delay = System.currentTimeMillis() - start;
+ if (Math.abs(delay - timeout) > 1000) {
+ fail("timeout was not accurate. expected: " + timeout
+ + " actual: " + delay + " miliseconds.");
+ }
+ } finally {
+ try {
+ sock.close();
+ } catch (IOException ioe) {
+ // ignore
+ }
+ }
+ }
+
+ /**
+ * Regression test for 1062928: Dotted IP addresses (e.g., 192.168.100.1)
+ * appear to be broken in the M5 SDK.
+ *
+ * Tests that a connection given a ip-addressv4 such as 192.168.100.100 does
+ * not fail - sdk m5 seems only to accept dns names instead of ip numbers.
+ * ip 209.85.129.147 (one address of www.google.com) on port 80 (http) is
+ * used to test the connection.
+ */
+
+// Commenting out this test since it is flaky, even at the best of times. See
+// #1191317 for Info.
+ @Suppress
+ public void disable_testConnectWithIP4IPAddr() {
+ // call a Google Web server
+ InetSocketAddress scktAddrss = new InetSocketAddress(KNOW_GOOD_ADDRESS,
+ 80);
+ Socket clntSckt = new Socket();
+ try {
+ clntSckt.connect(scktAddrss, 5000);
+ } catch (Throwable e) {
+ fail("connection problem:" + e.getClass().getName() + ": "
+ + e.getMessage());
+ } finally {
+ try {
+ clntSckt.close();
+ } catch (Exception e) {
+ // ignore
+ }
+ }
+ }
+
+
+ // Regression test for #1058962: Socket.close() does not cause
+ // socket.connect() to return immediately.
+ private Socket client;
+
+ private Exception error;
+
+ private boolean connected;
+
+// This test isn't working now, but really should work.
+// TODO Enable this test again.
+
+ @Suppress
+ public void disable_testSocketConnectClose() {
+ try {
+ client = new Socket();
+
+ new Thread() {
+ @Override
+ public void run() {
+ try {
+ client.connect(new InetSocketAddress(PACKAGE_DROPPING_ADDRESS, 1357));
+ } catch (Exception ex) {
+ error = ex;
+ }
+
+ connected = true;
+ }
+ }.start();
+
+ Thread.sleep(1000);
+
+ Assert.assertNull("Connect must not fail immediately. Maybe try different address.", error);
+ Assert.assertFalse("Connect must not succeed. Maybe try different address.", connected);
+
+ client.close();
+
+ Thread.sleep(1000);
+
+ if (error == null) {
+ fail("Socket connect still ongoing");
+ } else if (!(error instanceof SocketException)) {
+ fail("Socket connect interrupted with wrong error: " + error.toString());
+ }
+
+ } catch (Exception ex) {
+ throw new RuntimeException(ex);
+ }
+
+ }
+
+}
diff --git a/tests/CoreTests/android/core/StreamTokenizerTest.java b/tests/CoreTests/android/core/StreamTokenizerTest.java
new file mode 100644
index 0000000..5013860
--- /dev/null
+++ b/tests/CoreTests/android/core/StreamTokenizerTest.java
@@ -0,0 +1,96 @@
+/*
+ * 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 android.core;
+
+import junit.framework.TestCase;
+
+import java.io.ByteArrayInputStream;
+import java.io.StreamTokenizer;
+import java.io.StringReader;
+import android.test.suitebuilder.annotation.MediumTest;
+
+/**
+ * Tests for the StreamTokenizer
+ */
+public class StreamTokenizerTest extends TestCase {
+
+ @MediumTest
+ public void testStreamTokenizer() throws Exception {
+ String str = "Testing 12345 \n alpha \r\n omega";
+ String strb = "-3.8 'BLIND mice' \r sEe /* how */ they run";
+ StringReader aa = new StringReader(str);
+ StringReader ba = new StringReader(strb);
+ StreamTokenizer a = new StreamTokenizer(aa);
+ StreamTokenizer b = new StreamTokenizer(ba);
+
+ assertEquals(1, a.lineno());
+ assertEquals(StreamTokenizer.TT_WORD, a.nextToken());
+ assertEquals("Token[Testing], line 1", a.toString());
+ assertEquals(StreamTokenizer.TT_NUMBER, a.nextToken());
+ assertEquals("Token[n=12345.0], line 1", a.toString());
+ assertEquals(StreamTokenizer.TT_WORD, a.nextToken());
+ assertEquals("Token[alpha], line 2", a.toString());
+ assertEquals(StreamTokenizer.TT_WORD, a.nextToken());
+ assertEquals("Token[omega], line 3", a.toString());
+ assertEquals(StreamTokenizer.TT_EOF, a.nextToken());
+ assertEquals("Token[EOF], line 3", a.toString());
+
+ b.commentChar('u');
+ b.eolIsSignificant(true);
+ b.lowerCaseMode(true);
+ b.ordinaryChar('y');
+ b.slashStarComments(true);
+
+ assertEquals(StreamTokenizer.TT_NUMBER, b.nextToken());
+ assertEquals(-3.8, b.nval);
+ assertEquals("Token[n=-3.8], line 1", b.toString());
+ assertEquals(39, b.nextToken()); // '
+ assertEquals("Token[BLIND mice], line 1", b.toString());
+ assertEquals(10, b.nextToken()); // \n
+ assertEquals("Token[EOL], line 2", b.toString());
+ assertEquals(StreamTokenizer.TT_WORD, b.nextToken());
+ assertEquals("Token[see], line 2", b.toString());
+ assertEquals(StreamTokenizer.TT_WORD, b.nextToken());
+ assertEquals("Token[the], line 2", b.toString());
+ assertEquals(121, b.nextToken()); // y
+ assertEquals("Token['y'], line 2", b.toString());
+ assertEquals(StreamTokenizer.TT_WORD, b.nextToken());
+ assertEquals("Token[r], line 2", b.toString());
+ assertEquals(StreamTokenizer.TT_EOF, b.nextToken());
+ assertEquals("Token[EOF], line 2", b.toString());
+
+ // A harmony regression test
+ byte[] data = new byte[]{(byte) '-'};
+ StreamTokenizer tokenizer = new StreamTokenizer(new ByteArrayInputStream(data));
+ tokenizer.nextToken();
+ String result = tokenizer.toString();
+ assertEquals("Token['-'], line 1", result);
+
+ // another harmony regression test
+ byte[] data2 = new byte[]{(byte) '"',
+ (byte) 'H',
+ (byte) 'e',
+ (byte) 'l',
+ (byte) 'l',
+ (byte) 'o',
+ (byte) '"'};
+ StreamTokenizer tokenizer2 = new StreamTokenizer(new ByteArrayInputStream(data2));
+ tokenizer2.nextToken();
+ result = tokenizer2.toString();
+ assertEquals("Token[Hello], line 1", result);
+ }
+}
diff --git a/tests/CoreTests/android/core/StrictMathTest.java b/tests/CoreTests/android/core/StrictMathTest.java
new file mode 100644
index 0000000..92e6cb6
--- /dev/null
+++ b/tests/CoreTests/android/core/StrictMathTest.java
@@ -0,0 +1,855 @@
+/*
+ * 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.
+ */
+
+package android.core;
+
+import junit.framework.TestCase;
+import android.test.suitebuilder.annotation.SmallTest;
+import android.test.suitebuilder.annotation.MediumTest;
+
+public class StrictMathTest extends TestCase {
+
+ private final double HYP = StrictMath.sqrt(2.0);
+
+ private final double OPP = 1.0;
+
+ private final double ADJ = 1.0;
+
+ /* Required to make previous preprocessor flags work - do not remove */
+ int unused = 0;
+
+ /**
+ * @tests java.lang.StrictMath#abs(double)
+ */
+ @SmallTest
+ public void testAbsD() {
+ // Test for method double java.lang.StrictMath.abs(double)
+
+ assertTrue("Incorrect double abs value",
+ (StrictMath.abs(-1908.8976) == 1908.8976));
+ assertTrue("Incorrect double abs value",
+ (StrictMath.abs(1908.8976) == 1908.8976));
+ }
+
+ /**
+ * @tests java.lang.StrictMath#abs(float)
+ */
+ @SmallTest
+ public void testAbsF() {
+ // Test for method float java.lang.StrictMath.abs(float)
+ assertTrue("Incorrect float abs value",
+ (StrictMath.abs(-1908.8976f) == 1908.8976f));
+ assertTrue("Incorrect float abs value",
+ (StrictMath.abs(1908.8976f) == 1908.8976f));
+ }
+
+ /**
+ * @tests java.lang.StrictMath#abs(int)
+ */
+ @SmallTest
+ public void testAbsI() {
+ // Test for method int java.lang.StrictMath.abs(int)
+ assertTrue("Incorrect int abs value",
+ (StrictMath.abs(-1908897) == 1908897));
+ assertTrue("Incorrect int abs value",
+ (StrictMath.abs(1908897) == 1908897));
+ }
+
+ /**
+ * @tests java.lang.StrictMath#abs(long)
+ */
+ @SmallTest
+ public void testAbsJ() {
+ // Test for method long java.lang.StrictMath.abs(long)
+ assertTrue("Incorrect long abs value", (StrictMath
+ .abs(-19088976000089L) == 19088976000089L));
+ assertTrue("Incorrect long abs value",
+ (StrictMath.abs(19088976000089L) == 19088976000089L));
+ }
+
+ /**
+ * @tests java.lang.StrictMath#acos(double)
+ */
+ @SmallTest
+ public void testAcosD() {
+ // Test for method double java.lang.StrictMath.acos(double)
+ assertTrue("Returned incorrect arc cosine", StrictMath.cos(StrictMath
+ .acos(ADJ / HYP)) == ADJ / HYP);
+ }
+
+ /**
+ * @tests java.lang.StrictMath#asin(double)
+ */
+ @SmallTest
+ public void testAsinD() {
+ // Test for method double java.lang.StrictMath.asin(double)
+ assertTrue("Returned incorrect arc sine", StrictMath.sin(StrictMath
+ .asin(OPP / HYP)) == OPP / HYP);
+ }
+
+ /**
+ * @tests java.lang.StrictMath#atan(double)
+ */
+ @SmallTest
+ public void testAtanD() {
+ // Test for method double java.lang.StrictMath.atan(double)
+ double answer = StrictMath.tan(StrictMath.atan(1.0));
+ assertTrue("Returned incorrect arc tangent: " + answer, answer <= 1.0
+ && answer >= 9.9999999999999983E-1);
+ }
+
+ /**
+ * @tests java.lang.StrictMath#atan2(double,double)
+ */
+ @SmallTest
+ public void testAtan2DD() {
+ // Test for method double java.lang.StrictMath.atan2(double, double)
+ double answer = StrictMath.atan(StrictMath.tan(1.0));
+ assertTrue("Returned incorrect arc tangent: " + answer, answer <= 1.0
+ && answer >= 9.9999999999999983E-1);
+ }
+
+ /**
+ * @tests java.lang.StrictMath#cbrt(double)
+ */
+ @SuppressWarnings("boxing")
+ @SmallTest
+ public void testCbrtD() {
+ // Test for special situations
+ assertTrue("Should return Double.NaN", Double.isNaN(StrictMath
+ .cbrt(Double.NaN)));
+ assertEquals("Should return Double.POSITIVE_INFINITY",
+ Double.POSITIVE_INFINITY, StrictMath
+ .cbrt(Double.POSITIVE_INFINITY));
+ assertEquals("Should return Double.NEGATIVE_INFINITY",
+ Double.NEGATIVE_INFINITY, StrictMath
+ .cbrt(Double.NEGATIVE_INFINITY));
+ assertEquals(Double.doubleToLongBits(0.0), Double
+ .doubleToLongBits(StrictMath.cbrt(0.0)));
+ assertEquals(Double.doubleToLongBits(+0.0), Double
+ .doubleToLongBits(StrictMath.cbrt(+0.0)));
+ assertEquals(Double.doubleToLongBits(-0.0), Double
+ .doubleToLongBits(StrictMath.cbrt(-0.0)));
+
+ assertEquals("Should return 3.0", 3.0, StrictMath.cbrt(27.0));
+ assertEquals("Should return 23.111993172558684", 23.111993172558684,
+ StrictMath.cbrt(12345.6));
+ assertEquals("Should return 5.643803094122362E102",
+ 5.643803094122362E102, StrictMath.cbrt(Double.MAX_VALUE));
+ assertEquals("Should return 0.01", 0.01, StrictMath.cbrt(0.000001));
+
+ assertEquals("Should return -3.0", -3.0, StrictMath.cbrt(-27.0));
+ assertEquals("Should return -23.111993172558684", -23.111993172558684,
+ StrictMath.cbrt(-12345.6));
+ assertEquals("Should return 1.7031839360032603E-108",
+ 1.7031839360032603E-108, StrictMath.cbrt(Double.MIN_VALUE));
+ assertEquals("Should return -0.01", -0.01, StrictMath.cbrt(-0.000001));
+
+ try {
+ StrictMath.cbrt((Double) null);
+ fail("Should throw NullPointerException");
+ } catch (NullPointerException e) {
+ //expected
+ }
+ }
+
+ /**
+ * @tests java.lang.StrictMath#ceil(double)
+ */
+ @SmallTest
+ public void testCeilD() {
+ // Test for method double java.lang.StrictMath.ceil(double)
+ assertEquals("Incorrect ceiling for double",
+ 79, StrictMath.ceil(78.89), 0.0);
+ assertEquals("Incorrect ceiling for double",
+ -78, StrictMath.ceil(-78.89), 0.0);
+ }
+
+ /**
+ * @tests java.lang.StrictMath#cos(double)
+ */
+ @SmallTest
+ public void testCosD() {
+ // Test for method double java.lang.StrictMath.cos(double)
+
+ assertTrue("Returned incorrect cosine", StrictMath.cos(StrictMath
+ .acos(ADJ / HYP)) == ADJ / HYP);
+ }
+
+ /**
+ * @tests java.lang.StrictMath#cosh(double)
+ */
+ @SuppressWarnings("boxing")
+ @SmallTest
+ public void testCosh_D() {
+ // Test for special situations
+ assertTrue("Should return NaN", Double.isNaN(StrictMath
+ .cosh(Double.NaN)));
+ assertEquals("Should return POSITIVE_INFINITY",
+ Double.POSITIVE_INFINITY, StrictMath
+ .cosh(Double.POSITIVE_INFINITY));
+ assertEquals("Should return POSITIVE_INFINITY",
+ Double.POSITIVE_INFINITY, StrictMath
+ .cosh(Double.NEGATIVE_INFINITY));
+ assertEquals("Should return 1.0", 1.0, StrictMath.cosh(+0.0));
+ assertEquals("Should return 1.0", 1.0, StrictMath.cosh(-0.0));
+
+ assertEquals("Should return POSITIVE_INFINITY",
+ Double.POSITIVE_INFINITY, StrictMath.cosh(1234.56));
+ assertEquals("Should return POSITIVE_INFINITY",
+ Double.POSITIVE_INFINITY, StrictMath.cosh(-1234.56));
+ assertEquals("Should return 1.0000000000005", 1.0000000000005,
+ StrictMath.cosh(0.000001));
+ assertEquals("Should return 1.0000000000005", 1.0000000000005,
+ StrictMath.cosh(-0.000001));
+ assertEquals("Should return 5.212214351945598", 5.212214351945598,
+ StrictMath.cosh(2.33482));
+
+ assertEquals("Should return POSITIVE_INFINITY",
+ Double.POSITIVE_INFINITY, StrictMath.cosh(Double.MAX_VALUE));
+ assertEquals("Should return 1.0", 1.0, StrictMath
+ .cosh(Double.MIN_VALUE));
+ }
+
+ /**
+ * @tests java.lang.StrictMath#exp(double)
+ */
+ @SmallTest
+ public void testExpD() {
+ // Test for method double java.lang.StrictMath.exp(double)
+ assertTrue("Incorrect answer returned for simple power", StrictMath
+ .abs(StrictMath.exp(4D) - StrictMath.E * StrictMath.E
+ * StrictMath.E * StrictMath.E) < 0.1D);
+ assertTrue("Incorrect answer returned for larger power", StrictMath
+ .log(StrictMath.abs(StrictMath.exp(5.5D)) - 5.5D) < 10.0D);
+ }
+
+ /**
+ * @tests java.lang.StrictMath#expm1(double)
+ */
+ @SuppressWarnings("boxing")
+ @SmallTest
+ public void testExpm1D() {
+ //Test for special cases
+ assertTrue("Should return NaN", Double.isNaN(StrictMath.expm1(Double.NaN)));
+ assertEquals("Should return POSITIVE_INFINITY",
+ Double.POSITIVE_INFINITY, StrictMath.expm1(Double.POSITIVE_INFINITY));
+ assertEquals("Should return -1.0", -1.0, StrictMath
+ .expm1(Double.NEGATIVE_INFINITY));
+ assertEquals(Double.doubleToLongBits(0.0), Double
+ .doubleToLongBits(StrictMath.expm1(0.0)));
+ assertEquals(Double.doubleToLongBits(+0.0), Double
+ .doubleToLongBits(StrictMath.expm1(+0.0)));
+ assertEquals(Double.doubleToLongBits(-0.0), Double
+ .doubleToLongBits(StrictMath.expm1(-0.0)));
+
+ assertEquals("Should return -9.999950000166666E-6",
+ -9.999950000166666E-6, StrictMath.expm1(-0.00001));
+ assertEquals("Should return 1.0145103074469635E60",
+ 1.0145103074469635E60, StrictMath.expm1(138.16951162));
+ assertEquals("Should return POSITIVE_INFINITY",
+ Double.POSITIVE_INFINITY, StrictMath
+ .expm1(123456789123456789123456789.4521584223));
+ assertEquals("Should return POSITIVE_INFINITY",
+ Double.POSITIVE_INFINITY, StrictMath.expm1(Double.MAX_VALUE));
+ assertEquals("Should return MIN_VALUE", Double.MIN_VALUE, StrictMath
+ .expm1(Double.MIN_VALUE));
+
+ }
+
+ /**
+ * @tests java.lang.StrictMath#floor(double)
+ */
+ @SmallTest
+ public void testFloorD() {
+ // Test for method double java.lang.StrictMath.floor(double)
+ assertEquals("Incorrect floor for double",
+ 78, StrictMath.floor(78.89), 0.0);
+ assertEquals("Incorrect floor for double",
+ -79, StrictMath.floor(-78.89), 0.0);
+ }
+
+ /**
+ * @tests java.lang.StrictMath#hypot(double,double)
+ */
+ @SuppressWarnings("boxing")
+ @SmallTest
+ public void testHypotDD() {
+ // Test for special cases
+ assertEquals("Should return POSITIVE_INFINITY",
+ Double.POSITIVE_INFINITY, StrictMath.hypot(Double.POSITIVE_INFINITY,
+ 1.0));
+ assertEquals("Should return POSITIVE_INFINITY",
+ Double.POSITIVE_INFINITY, StrictMath.hypot(Double.NEGATIVE_INFINITY,
+ 123.324));
+ assertEquals("Should return POSITIVE_INFINITY",
+ Double.POSITIVE_INFINITY, StrictMath.hypot(-758.2587,
+ Double.POSITIVE_INFINITY));
+ assertEquals("Should return POSITIVE_INFINITY",
+ Double.POSITIVE_INFINITY, StrictMath.hypot(5687.21,
+ Double.NEGATIVE_INFINITY));
+ assertEquals("Should return POSITIVE_INFINITY",
+ Double.POSITIVE_INFINITY, StrictMath.hypot(Double.POSITIVE_INFINITY,
+ Double.NEGATIVE_INFINITY));
+ assertEquals("Should return POSITIVE_INFINITY",
+ Double.POSITIVE_INFINITY, StrictMath.hypot(Double.NEGATIVE_INFINITY,
+ Double.POSITIVE_INFINITY));
+ assertTrue("Should return NaN", Double.isNaN(StrictMath.hypot(Double.NaN,
+ 2342301.89843)));
+ assertTrue("Should return NaN", Double.isNaN(StrictMath.hypot(-345.2680,
+ Double.NaN)));
+
+ assertEquals("Should return 2396424.905416697", 2396424.905416697, StrictMath
+ .hypot(12322.12, -2396393.2258));
+ assertEquals("Should return 138.16958070558556", 138.16958070558556,
+ StrictMath.hypot(-138.16951162, 0.13817035864));
+ assertEquals("Should return 1.7976931348623157E308",
+ 1.7976931348623157E308, StrictMath.hypot(Double.MAX_VALUE, 211370.35));
+ assertEquals("Should return 5413.7185", 5413.7185, StrictMath.hypot(
+ -5413.7185, Double.MIN_VALUE));
+
+ }
+
+ /**
+ * @tests java.lang.StrictMath#IEEEremainder(double,double)
+ */
+ @SmallTest
+ public void testIEEEremainderDD() {
+ // Test for method double java.lang.StrictMath.IEEEremainder(double,
+ // double)
+ assertEquals("Incorrect remainder returned", 0.0, StrictMath.IEEEremainder(
+ 1.0, 1.0), 0.0);
+ assertTrue(
+ "Incorrect remainder returned",
+ StrictMath.IEEEremainder(1.32, 89.765) >= 1.4705063220631647E-2
+ || StrictMath.IEEEremainder(1.32, 89.765) >= 1.4705063220631649E-2);
+ }
+
+ /**
+ * @tests java.lang.StrictMath#log(double)
+ */
+ @SmallTest
+ public void testLogD() {
+ // Test for method double java.lang.StrictMath.log(double)
+ for (double d = 10; d >= -10; d -= 0.5) {
+ double answer = StrictMath.log(StrictMath.exp(d));
+ assertTrue("Answer does not equal expected answer for d = " + d
+ + " answer = " + answer,
+ StrictMath.abs(answer - d) <= StrictMath
+ .abs(d * 0.00000001));
+ }
+ }
+
+ /**
+ * @tests java.lang.StrictMath#log10(double)
+ */
+ @SuppressWarnings("boxing")
+ @SmallTest
+ public void testLog10D() {
+ // Test for special cases
+ assertTrue("Should return NaN", Double.isNaN(StrictMath
+ .log10(Double.NaN)));
+ assertTrue("Should return NaN", Double.isNaN(StrictMath
+ .log10(-2541.05745687234187532)));
+ assertEquals("Should return POSITIVE_INFINITY",
+ Double.POSITIVE_INFINITY, StrictMath
+ .log10(Double.POSITIVE_INFINITY));
+ assertEquals("Should return NEGATIVE_INFINITY",
+ Double.NEGATIVE_INFINITY, StrictMath.log10(0.0));
+ assertEquals("Should return NEGATIVE_INFINITY",
+ Double.NEGATIVE_INFINITY, StrictMath.log10(+0.0));
+ assertEquals("Should return NEGATIVE_INFINITY",
+ Double.NEGATIVE_INFINITY, StrictMath.log10(-0.0));
+ assertEquals("Should return 14.0", 14.0, StrictMath.log10(StrictMath
+ .pow(10, 14)));
+
+ assertEquals("Should return 3.7389561269540406", 3.7389561269540406,
+ StrictMath.log10(5482.2158));
+ assertEquals("Should return 14.661551142893833", 14.661551142893833,
+ StrictMath.log10(458723662312872.125782332587));
+ assertEquals("Should return -0.9083828622192334", -0.9083828622192334,
+ StrictMath.log10(0.12348583358871));
+ assertEquals("Should return 308.25471555991675", 308.25471555991675,
+ StrictMath.log10(Double.MAX_VALUE));
+ assertEquals("Should return -323.3062153431158", -323.3062153431158,
+ StrictMath.log10(Double.MIN_VALUE));
+ }
+
+ /**
+ * @tests java.lang.StrictMath#log1p(double)
+ */
+ @SuppressWarnings("boxing")
+ @SmallTest
+ public void testLog1pD() {
+ // Test for special cases
+ assertTrue("Should return NaN", Double.isNaN(StrictMath
+ .log1p(Double.NaN)));
+ assertTrue("Should return NaN", Double.isNaN(StrictMath
+ .log1p(-32.0482175)));
+ assertEquals("Should return POSITIVE_INFINITY",
+ Double.POSITIVE_INFINITY, StrictMath
+ .log1p(Double.POSITIVE_INFINITY));
+ assertEquals(Double.doubleToLongBits(0.0), Double
+ .doubleToLongBits(StrictMath.log1p(0.0)));
+ assertEquals(Double.doubleToLongBits(+0.0), Double
+ .doubleToLongBits(StrictMath.log1p(+0.0)));
+ assertEquals(Double.doubleToLongBits(-0.0), Double
+ .doubleToLongBits(StrictMath.log1p(-0.0)));
+
+ assertEquals("Should return -0.2941782295312541", -0.2941782295312541,
+ StrictMath.log1p(-0.254856327));
+ assertEquals("Should return 7.368050685564151", 7.368050685564151,
+ StrictMath.log1p(1583.542));
+ assertEquals("Should return 0.4633708685409921", 0.4633708685409921,
+ StrictMath.log1p(0.5894227));
+ assertEquals("Should return 709.782712893384", 709.782712893384,
+ StrictMath.log1p(Double.MAX_VALUE));
+ assertEquals("Should return Double.MIN_VALUE", Double.MIN_VALUE,
+ StrictMath.log1p(Double.MIN_VALUE));
+ }
+
+ /**
+ * @tests java.lang.StrictMath#max(double,double)
+ */
+ @SmallTest
+ public void testMaxDD() {
+ // Test for method double java.lang.StrictMath.max(double, double)
+ assertEquals("Incorrect double max value", 1908897.6000089, StrictMath.max(
+ -1908897.6000089, 1908897.6000089), 0D);
+ assertEquals("Incorrect double max value", 1908897.6000089, StrictMath.max(2.0,
+ 1908897.6000089), 0D);
+ assertEquals("Incorrect double max value", -2.0, StrictMath.max(-2.0,
+ -1908897.6000089), 0D);
+
+ }
+
+ /**
+ * @tests java.lang.StrictMath#max(float,float)
+ */
+ @SmallTest
+ public void testMaxFF() {
+ // Test for method float java.lang.StrictMath.max(float, float)
+ assertTrue("Incorrect float max value", StrictMath.max(-1908897.600f,
+ 1908897.600f) == 1908897.600f);
+ assertTrue("Incorrect float max value", StrictMath.max(2.0f,
+ 1908897.600f) == 1908897.600f);
+ assertTrue("Incorrect float max value", StrictMath.max(-2.0f,
+ -1908897.600f) == -2.0f);
+ }
+
+ /**
+ * @tests java.lang.StrictMath#max(int,int)
+ */
+ @SmallTest
+ public void testMaxII() {
+ // Test for method int java.lang.StrictMath.max(int, int)
+ assertEquals("Incorrect int max value", 19088976, StrictMath.max(-19088976,
+ 19088976));
+ assertEquals("Incorrect int max value",
+ 19088976, StrictMath.max(20, 19088976));
+ assertEquals("Incorrect int max value",
+ -20, StrictMath.max(-20, -19088976));
+ }
+
+ /**
+ * @tests java.lang.StrictMath#max(long,long)
+ */
+ @SmallTest
+ public void testMaxJJ() {
+ // Test for method long java.lang.StrictMath.max(long, long)
+ assertEquals("Incorrect long max value", 19088976000089L, StrictMath.max(-19088976000089L,
+ 19088976000089L));
+ assertEquals("Incorrect long max value", 19088976000089L, StrictMath.max(20,
+ 19088976000089L));
+ assertEquals("Incorrect long max value", -20, StrictMath.max(-20,
+ -19088976000089L));
+ }
+
+ /**
+ * @tests java.lang.StrictMath#min(double,double)
+ */
+ @SmallTest
+ public void testMinDD() {
+ // Test for method double java.lang.StrictMath.min(double, double)
+ assertEquals("Incorrect double min value", -1908897.6000089, StrictMath.min(
+ -1908897.6000089, 1908897.6000089), 0D);
+ assertEquals("Incorrect double min value", 2.0, StrictMath.min(2.0,
+ 1908897.6000089), 0D);
+ assertEquals("Incorrect double min value", -1908897.6000089, StrictMath.min(-2.0,
+ -1908897.6000089), 0D);
+ }
+
+ /**
+ * @tests java.lang.StrictMath#min(float,float)
+ */
+ @SmallTest
+ public void testMinFF() {
+ // Test for method float java.lang.StrictMath.min(float, float)
+ assertTrue("Incorrect float min value", StrictMath.min(-1908897.600f,
+ 1908897.600f) == -1908897.600f);
+ assertTrue("Incorrect float min value", StrictMath.min(2.0f,
+ 1908897.600f) == 2.0f);
+ assertTrue("Incorrect float min value", StrictMath.min(-2.0f,
+ -1908897.600f) == -1908897.600f);
+ }
+
+ /**
+ * @tests java.lang.StrictMath#min(int,int)
+ */
+ @SmallTest
+ public void testMinII() {
+ // Test for method int java.lang.StrictMath.min(int, int)
+ assertEquals("Incorrect int min value", -19088976, StrictMath.min(-19088976,
+ 19088976));
+ assertEquals("Incorrect int min value",
+ 20, StrictMath.min(20, 19088976));
+ assertEquals("Incorrect int min value",
+ -19088976, StrictMath.min(-20, -19088976));
+
+ }
+
+ /**
+ * @tests java.lang.StrictMath#min(long,long)
+ */
+ @SmallTest
+ public void testMinJJ() {
+ // Test for method long java.lang.StrictMath.min(long, long)
+ assertEquals("Incorrect long min value", -19088976000089L, StrictMath.min(-19088976000089L,
+ 19088976000089L));
+ assertEquals("Incorrect long min value", 20, StrictMath.min(20,
+ 19088976000089L));
+ assertEquals("Incorrect long min value", -19088976000089L, StrictMath.min(-20,
+ -19088976000089L));
+ }
+
+ /**
+ * @tests java.lang.StrictMath#pow(double,double)
+ */
+ @SmallTest
+ public void testPowDD() {
+ // Test for method double java.lang.StrictMath.pow(double, double)
+ assertTrue("pow returned incorrect value",
+ (long) StrictMath.pow(2, 8) == 256l);
+ assertTrue("pow returned incorrect value",
+ StrictMath.pow(2, -8) == 0.00390625d);
+ }
+
+ /**
+ * @tests java.lang.StrictMath#rint(double)
+ */
+ @SmallTest
+ public void testRintD() {
+ // Test for method double java.lang.StrictMath.rint(double)
+ assertEquals("Failed to round properly - up to odd",
+ 3.0, StrictMath.rint(2.9), 0D);
+ assertTrue("Failed to round properly - NaN", Double.isNaN(StrictMath
+ .rint(Double.NaN)));
+ assertEquals("Failed to round properly down to even", 2.0, StrictMath
+ .rint(2.1), 0D);
+ assertTrue("Failed to round properly " + 2.5 + " to even", StrictMath
+ .rint(2.5) == 2.0);
+ }
+
+ /**
+ * @tests java.lang.StrictMath#round(double)
+ */
+ @SmallTest
+ public void testRoundD() {
+ // Test for method long java.lang.StrictMath.round(double)
+ assertEquals("Incorrect rounding of a float",
+ -91, StrictMath.round(-90.89d));
+ }
+
+ /**
+ * @tests java.lang.StrictMath#round(float)
+ */
+ @SmallTest
+ public void testRoundF() {
+ // Test for method int java.lang.StrictMath.round(float)
+ assertEquals("Incorrect rounding of a float",
+ -91, StrictMath.round(-90.89f));
+ }
+
+ /**
+ * @tests java.lang.StrictMath#signum(double)
+ */
+ @SmallTest
+ public void testSignumD() {
+ assertTrue(Double.isNaN(StrictMath.signum(Double.NaN)));
+ assertEquals(Double.doubleToLongBits(0.0), Double
+ .doubleToLongBits(StrictMath.signum(0.0)));
+ assertEquals(Double.doubleToLongBits(+0.0), Double
+ .doubleToLongBits(StrictMath.signum(+0.0)));
+ assertEquals(Double.doubleToLongBits(-0.0), Double
+ .doubleToLongBits(StrictMath.signum(-0.0)));
+
+ assertEquals(1.0, StrictMath.signum(253681.2187962), 0D);
+ assertEquals(-1.0, StrictMath.signum(-125874693.56), 0D);
+ assertEquals(1.0, StrictMath.signum(1.2587E-308), 0D);
+ assertEquals(-1.0, StrictMath.signum(-1.2587E-308), 0D);
+
+ assertEquals(1.0, StrictMath.signum(Double.MAX_VALUE), 0D);
+ assertEquals(1.0, StrictMath.signum(Double.MIN_VALUE), 0D);
+ assertEquals(-1.0, StrictMath.signum(-Double.MAX_VALUE), 0D);
+ assertEquals(-1.0, StrictMath.signum(-Double.MIN_VALUE), 0D);
+ assertEquals(1.0, StrictMath.signum(Double.POSITIVE_INFINITY), 0D);
+ assertEquals(-1.0, StrictMath.signum(Double.NEGATIVE_INFINITY), 0D);
+
+ }
+
+ /**
+ * @tests java.lang.StrictMath#signum(float)
+ */
+ @SmallTest
+ public void testSignumF() {
+ assertTrue(Float.isNaN(StrictMath.signum(Float.NaN)));
+ assertEquals(Float.floatToIntBits(0.0f), Float
+ .floatToIntBits(StrictMath.signum(0.0f)));
+ assertEquals(Float.floatToIntBits(+0.0f), Float
+ .floatToIntBits(StrictMath.signum(+0.0f)));
+ assertEquals(Float.floatToIntBits(-0.0f), Float
+ .floatToIntBits(StrictMath.signum(-0.0f)));
+
+ assertEquals(1.0f, StrictMath.signum(253681.2187962f), 0f);
+ assertEquals(-1.0f, StrictMath.signum(-125874693.56f), 0f);
+ assertEquals(1.0f, StrictMath.signum(1.2587E-11f), 0f);
+ assertEquals(-1.0f, StrictMath.signum(-1.2587E-11f), 0f);
+
+ assertEquals(1.0f, StrictMath.signum(Float.MAX_VALUE), 0f);
+ assertEquals(1.0f, StrictMath.signum(Float.MIN_VALUE), 0f);
+ assertEquals(-1.0f, StrictMath.signum(-Float.MAX_VALUE), 0f);
+ assertEquals(-1.0f, StrictMath.signum(-Float.MIN_VALUE), 0f);
+ assertEquals(1.0f, StrictMath.signum(Float.POSITIVE_INFINITY), 0f);
+ assertEquals(-1.0f, StrictMath.signum(Float.NEGATIVE_INFINITY), 0f);
+ }
+
+ /**
+ * @tests java.lang.StrictMath#sin(double)
+ */
+ @SmallTest
+ public void testSinD() {
+ // Test for method double java.lang.StrictMath.sin(double)
+ assertTrue("Returned incorrect sine", StrictMath.sin(StrictMath
+ .asin(OPP / HYP)) == OPP / HYP);
+ }
+
+ /**
+ * @tests java.lang.StrictMath#sinh(double)
+ */
+ @SmallTest
+ public void testSinhD() {
+ // Test for special situations
+ assertTrue(Double.isNaN(StrictMath.sinh(Double.NaN)));
+ assertEquals("Should return POSITIVE_INFINITY",
+ Double.POSITIVE_INFINITY, StrictMath
+ .sinh(Double.POSITIVE_INFINITY), 0D);
+ assertEquals("Should return NEGATIVE_INFINITY",
+ Double.NEGATIVE_INFINITY, StrictMath
+ .sinh(Double.NEGATIVE_INFINITY), 0D);
+ assertEquals(Double.doubleToLongBits(0.0), Double
+ .doubleToLongBits(StrictMath.sinh(0.0)));
+ assertEquals(Double.doubleToLongBits(+0.0), Double
+ .doubleToLongBits(StrictMath.sinh(+0.0)));
+ assertEquals(Double.doubleToLongBits(-0.0), Double
+ .doubleToLongBits(StrictMath.sinh(-0.0)));
+
+ assertEquals("Should return POSITIVE_INFINITY",
+ Double.POSITIVE_INFINITY, StrictMath.sinh(1234.56), 0D);
+ assertEquals("Should return NEGATIVE_INFINITY",
+ Double.NEGATIVE_INFINITY, StrictMath.sinh(-1234.56), 0D);
+ assertEquals("Should return 1.0000000000001666E-6",
+ 1.0000000000001666E-6, StrictMath.sinh(0.000001), 0D);
+ assertEquals("Should return -1.0000000000001666E-6",
+ -1.0000000000001666E-6, StrictMath.sinh(-0.000001), 0D);
+ assertEquals("Should return 5.115386441963859", 5.115386441963859,
+ StrictMath.sinh(2.33482), 0D);
+ assertEquals("Should return POSITIVE_INFINITY",
+ Double.POSITIVE_INFINITY, StrictMath.sinh(Double.MAX_VALUE), 0D);
+ assertEquals("Should return 4.9E-324", 4.9E-324, StrictMath
+ .sinh(Double.MIN_VALUE), 0D);
+ }
+
+ /**
+ * @tests java.lang.StrictMath#sqrt(double)
+ */
+ @SmallTest
+ public void testSqrtD() {
+ // Test for method double java.lang.StrictMath.sqrt(double)
+ assertEquals("Incorrect root returned1",
+ 2, StrictMath.sqrt(StrictMath.pow(StrictMath.sqrt(2), 4)), 0.0);
+ assertEquals("Incorrect root returned2", 7, StrictMath.sqrt(49), 0.0);
+ }
+
+ /**
+ * @tests java.lang.StrictMath#tan(double)
+ */
+ @SmallTest
+ public void testTanD() {
+ // Test for method double java.lang.StrictMath.tan(double)
+ assertTrue(
+ "Returned incorrect tangent: ",
+ StrictMath.tan(StrictMath.atan(1.0)) <= 1.0
+ || StrictMath.tan(StrictMath.atan(1.0)) >= 9.9999999999999983E-1);
+ }
+
+ /**
+ * @tests java.lang.StrictMath#tanh(double)
+ */
+ @SmallTest
+ public void testTanhD() {
+ // Test for special situations
+ assertTrue(Double.isNaN(StrictMath.tanh(Double.NaN)));
+ assertEquals("Should return +1.0", +1.0, StrictMath
+ .tanh(Double.POSITIVE_INFINITY), 0D);
+ assertEquals("Should return -1.0", -1.0, StrictMath
+ .tanh(Double.NEGATIVE_INFINITY), 0D);
+ assertEquals(Double.doubleToLongBits(0.0), Double
+ .doubleToLongBits(StrictMath.tanh(0.0)));
+ assertEquals(Double.doubleToLongBits(+0.0), Double
+ .doubleToLongBits(StrictMath.tanh(+0.0)));
+ assertEquals(Double.doubleToLongBits(-0.0), Double
+ .doubleToLongBits(StrictMath.tanh(-0.0)));
+
+ assertEquals("Should return 1.0", 1.0, StrictMath.tanh(1234.56), 0D);
+ assertEquals("Should return -1.0", -1.0, StrictMath.tanh(-1234.56), 0D);
+ assertEquals("Should return 9.999999999996666E-7",
+ 9.999999999996666E-7, StrictMath.tanh(0.000001), 0D);
+ assertEquals("Should return 0.981422884124941", 0.981422884124941,
+ StrictMath.tanh(2.33482), 0D);
+ assertEquals("Should return 1.0", 1.0, StrictMath
+ .tanh(Double.MAX_VALUE), 0D);
+ assertEquals("Should return 4.9E-324", 4.9E-324, StrictMath
+ .tanh(Double.MIN_VALUE), 0D);
+ }
+
+ /**
+ * @tests java.lang.StrictMath#random()
+ */
+ @MediumTest
+ public void testRandom() {
+ // There isn't a place for these tests so just stick them here
+ assertEquals("Wrong value E",
+ 4613303445314885481L, Double.doubleToLongBits(StrictMath.E));
+ assertEquals("Wrong value PI",
+ 4614256656552045848L, Double.doubleToLongBits(StrictMath.PI));
+
+ for (int i = 500; i >= 0; i--) {
+ double d = StrictMath.random();
+ assertTrue("Generated number is out of range: " + d, d >= 0.0
+ && d < 1.0);
+ }
+ }
+
+ /**
+ * @tests java.lang.StrictMath#toRadians(double)
+ */
+ @MediumTest
+ public void testToRadiansD() {
+ for (double d = 500; d >= 0; d -= 1.0) {
+ double converted = StrictMath.toDegrees(StrictMath.toRadians(d));
+ assertTrue("Converted number not equal to original. d = " + d,
+ converted >= d * 0.99999999 && converted <= d * 1.00000001);
+ }
+ }
+
+ /**
+ * @tests java.lang.StrictMath#toDegrees(double)
+ */
+ @MediumTest
+ public void testToDegreesD() {
+ for (double d = 500; d >= 0; d -= 1.0) {
+ double converted = StrictMath.toRadians(StrictMath.toDegrees(d));
+ assertTrue("Converted number not equal to original. d = " + d,
+ converted >= d * 0.99999999 && converted <= d * 1.00000001);
+ }
+ }
+
+ /**
+ * @tests java.lang.StrictMath#ulp(double)
+ */
+ @SuppressWarnings("boxing")
+ @SmallTest
+ public void testUlp_D() {
+ // Test for special cases
+ assertTrue("Should return NaN", Double
+ .isNaN(StrictMath.ulp(Double.NaN)));
+ assertEquals("Returned incorrect value", Double.POSITIVE_INFINITY,
+ StrictMath.ulp(Double.POSITIVE_INFINITY), 0D);
+ assertEquals("Returned incorrect value", Double.POSITIVE_INFINITY,
+ StrictMath.ulp(Double.NEGATIVE_INFINITY), 0D);
+ assertEquals("Returned incorrect value", Double.MIN_VALUE, StrictMath
+ .ulp(0.0), 0D);
+ assertEquals("Returned incorrect value", Double.MIN_VALUE, StrictMath
+ .ulp(+0.0), 0D);
+ assertEquals("Returned incorrect value", Double.MIN_VALUE, StrictMath
+ .ulp(-0.0), 0D);
+ assertEquals("Returned incorrect value", StrictMath.pow(2, 971),
+ StrictMath.ulp(Double.MAX_VALUE), 0D);
+ assertEquals("Returned incorrect value", StrictMath.pow(2, 971),
+ StrictMath.ulp(-Double.MAX_VALUE), 0D);
+
+ assertEquals("Returned incorrect value", Double.MIN_VALUE, StrictMath
+ .ulp(Double.MIN_VALUE), 0D);
+ assertEquals("Returned incorrect value", Double.MIN_VALUE, StrictMath
+ .ulp(-Double.MIN_VALUE), 0D);
+
+ assertEquals("Returned incorrect value", 2.220446049250313E-16,
+ StrictMath.ulp(1.0), 0D);
+ assertEquals("Returned incorrect value", 2.220446049250313E-16,
+ StrictMath.ulp(-1.0), 0D);
+ assertEquals("Returned incorrect value", 2.2737367544323206E-13,
+ StrictMath.ulp(1153.0), 0D);
+ }
+
+ /**
+ * @tests java.lang.StrictMath#ulp(float)
+ */
+ @SuppressWarnings("boxing")
+ @SmallTest
+ public void testUlpF() {
+ // Test for special cases
+ assertTrue("Should return NaN", Float.isNaN(StrictMath.ulp(Float.NaN)));
+ assertEquals("Returned incorrect value", Float.POSITIVE_INFINITY,
+ StrictMath.ulp(Float.POSITIVE_INFINITY), 0f);
+ assertEquals("Returned incorrect value", Float.POSITIVE_INFINITY,
+ StrictMath.ulp(Float.NEGATIVE_INFINITY), 0f);
+ assertEquals("Returned incorrect value", Float.MIN_VALUE, StrictMath
+ .ulp(0.0f), 0f);
+ assertEquals("Returned incorrect value", Float.MIN_VALUE, StrictMath
+ .ulp(+0.0f), 0f);
+ assertEquals("Returned incorrect value", Float.MIN_VALUE, StrictMath
+ .ulp(-0.0f), 0f);
+ assertEquals("Returned incorrect value", 2.028241E31f, StrictMath
+ .ulp(Float.MAX_VALUE), 0f);
+ assertEquals("Returned incorrect value", 2.028241E31f, StrictMath
+ .ulp(-Float.MAX_VALUE), 0f);
+
+ assertEquals("Returned incorrect value", 1.4E-45f, StrictMath
+ .ulp(Float.MIN_VALUE), 0f);
+ assertEquals("Returned incorrect value", 1.4E-45f, StrictMath
+ .ulp(-Float.MIN_VALUE), 0f);
+
+ assertEquals("Returned incorrect value", 1.1920929E-7f, StrictMath
+ .ulp(1.0f), 0f);
+ assertEquals("Returned incorrect value", 1.1920929E-7f, StrictMath
+ .ulp(-1.0f), 0f);
+ assertEquals("Returned incorrect value", 1.2207031E-4f, StrictMath
+ .ulp(1153.0f), 0f);
+ assertEquals("Returned incorrect value", 5.6E-45f, Math
+ .ulp(9.403954E-38f), 0f);
+ }
+}
diff --git a/tests/CoreTests/android/core/StringReaderTest.java b/tests/CoreTests/android/core/StringReaderTest.java
new file mode 100644
index 0000000..66b3e81
--- /dev/null
+++ b/tests/CoreTests/android/core/StringReaderTest.java
@@ -0,0 +1,40 @@
+/*
+ * 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 android.core;
+
+import junit.framework.TestCase;
+
+import java.io.StringReader;
+import android.test.suitebuilder.annotation.SmallTest;
+
+public class StringReaderTest extends TestCase {
+
+ @SmallTest
+ public void testStringReader() throws Exception {
+ String str = "AbCdEfGhIjKlMnOpQrStUvWxYz";
+
+ StringReader a = new StringReader(str);
+ StringReader b = new StringReader(str);
+ StringReader c = new StringReader(str);
+ StringReader d = new StringReader(str);
+
+ assertEquals(str, IOUtil.read(a));
+ assertEquals("AbCdEfGhIj", IOUtil.read(b, 10));
+ assertEquals("bdfhjlnprtvxz", IOUtil.skipRead(c));
+ assertEquals("AbCdEfGdEfGhIjKlMnOpQrStUvWxYz", IOUtil.markRead(d, 3, 4));
+ }
+}
diff --git a/tests/CoreTests/android/core/StringTest.java b/tests/CoreTests/android/core/StringTest.java
new file mode 100644
index 0000000..957dd40
--- /dev/null
+++ b/tests/CoreTests/android/core/StringTest.java
@@ -0,0 +1,149 @@
+/*
+ * 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 android.core;
+
+import com.ibm.icu4jni.text.RuleBasedNumberFormat;
+import com.ibm.icu4jni.text.RuleBasedNumberFormat.RBNFType;
+
+import junit.framework.TestCase;
+import android.test.suitebuilder.annotation.SmallTest;
+
+/**
+ * Some String tests.
+ */
+public class StringTest extends TestCase {
+ private String germanSpelloutRule = "%alt-ones:" +
+ " -x: minus >>;" +
+ " x.x: << komma >>;" +
+ " null; eins; =%%main=;" +
+ "%%main:" +
+ " null; ein; zwei; drei; vier; f\u00fcnf; sechs; sieben; acht; neun;\n" +
+ " zehn; elf; zwu00f6lf; >>zehn;" +
+ " 20: [>>und]zwanzig;" +
+ " 30: [>>und]dreiu00dfig;" +
+ " 40: [>>und]vierzig;" +
+ " 50: [>>und]fu00fcnfzig;" +
+ " 60: [>>und]sechzig;" +
+ " 70: [>>und]siebzig;" +
+ " 80: [>>und]achtzig;" +
+ " 90: [>>und]neunzig;" +
+ " 100: hundert[>%alt-ones>];" +
+ " 200: <<hundert[>%alt-ones>];" +
+ " 1000: tausend[>%alt-ones>];" +
+ " 1100: tausendein[>%alt-ones>];" +
+ " 1200: tausend[>%alt-ones>];" +
+ " 2000: <<tausend[>%alt-ones>];";
+
+ @SmallTest
+ public void testString() throws Exception {
+ String test = "0123456789";
+ String test1 = new String("0123456789"); // different object
+ String test2 = new String("0123456780"); // different value
+ String offset = new String("xxx0123456789yyy");
+ String sub = offset.substring(3, 13);
+
+ assertEquals(test, test);
+ assertEquals(test, test1);
+ assertFalse(test.equals(test2));
+
+ assertEquals(0, test.compareTo(test1));
+ assertTrue(test1.compareTo(test2) > 0);
+ assertTrue(test2.compareTo(test1) < 0);
+
+ /* compare string with a nonzero offset, in left/right side */
+ assertEquals(0, test.compareTo(sub));
+ assertEquals(0, sub.compareTo(test));
+ assertEquals(test, sub);
+ assertEquals(sub, test);
+ /* same base, one is a substring */
+ assertFalse(offset.equals(sub));
+ assertFalse(sub.equals(offset));
+ /* wrong class */
+ assertFalse(test.equals(this));
+
+ /* null ptr - throw */
+ try {
+ test.compareTo(null);
+ fail("didn't get expected npe");
+ } catch (NullPointerException npe) {
+ // expected
+ }
+ /* null ptr - ok */
+ assertFalse(test.equals(null));
+
+ test = test.substring(1);
+ assertEquals("123456789", test);
+ assertFalse(test.equals(test1));
+
+ test = test.substring(1);
+ assertEquals("23456789", test);
+
+ test = test.substring(1);
+ assertEquals("3456789", test);
+
+ test = test.substring(1);
+ assertEquals("456789", test);
+
+ test = test.substring(3, 5);
+ assertEquals("78", test);
+
+ test = "this/is/a/path";
+ String[] strings = test.split("/");
+ assertEquals(4, strings.length);
+
+ assertEquals("this is a path", test.replaceAll("/", " "));
+ assertEquals("this is a path", test.replace("/", " "));
+
+ assertEquals(0, "abc".compareToIgnoreCase("ABC"));
+ assertTrue("abc".compareToIgnoreCase("DEF") < 0);
+ assertTrue("ABC".compareToIgnoreCase("def") < 0);
+ assertTrue("Now".compareTo("Mow") > 0);
+ assertTrue("Now".compareToIgnoreCase("Mow") > 0);
+
+ // RuleBasedNumberFormnat tests
+ RuleBasedNumberFormat format = new RuleBasedNumberFormat();
+ format.open(RBNFType.SPELLOUT);
+ String result = format.format(15);
+ assertEquals("Expected spellout format: 'fifteen' but was "
+ + result, "fifteen", result);
+ format.close();
+
+ format.open(RBNFType.DURATION);
+ result = format.format(15);
+ assertEquals("Expected spellout format: '15 sec.' but was "
+ + result, "15 sec.", result);
+ format.close();
+
+ format.open(RBNFType.ORDINAL);
+ result = format.format(15);
+ assertEquals("Expected spellout format: '15th' but was "
+ + result, "15th", result);
+ format.close();
+ format.open(germanSpelloutRule);
+
+ result = format.format(1323);
+ assertEquals("Expected spellout format: 'tausenddrei" +
+ "hundertdreiundzwanzig' but was " + result, "tausend" +
+ "dreihundertdreiundzwanzig", result);
+ int res = format.parse("tausenddreihundertdreiundzwanzig")
+ .intValue();
+ assertEquals("Expected spellout format: 'tausend" +
+ "dreihundertdreiundzwanzig' but was " + res , 1323, res);
+ format.close();
+ }
+}
+
diff --git a/tests/CoreTests/android/core/StringWriterTest.java b/tests/CoreTests/android/core/StringWriterTest.java
new file mode 100644
index 0000000..fed2221
--- /dev/null
+++ b/tests/CoreTests/android/core/StringWriterTest.java
@@ -0,0 +1,42 @@
+/*
+ * 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 android.core;
+
+import junit.framework.TestCase;
+
+import java.io.StringWriter;
+import android.test.suitebuilder.annotation.SmallTest;
+
+public class StringWriterTest extends TestCase {
+
+ @SmallTest
+ public void testStringWriter() throws Exception {
+ String str = "AbCdEfGhIjKlMnOpQrStUvWxYz";
+ StringWriter a = new StringWriter(10);
+
+ a.write(str, 0, 26);
+ a.write('X');
+
+ assertEquals("AbCdEfGhIjKlMnOpQrStUvWxYzX", a.toString());
+
+ a.write("alphabravodelta", 5, 5);
+ a.append('X');
+ assertEquals("AbCdEfGhIjKlMnOpQrStUvWxYzXbravoX", a.toString());
+ a.append("omega");
+ assertEquals("AbCdEfGhIjKlMnOpQrStUvWxYzXbravoXomega", a.toString());
+ }
+}
diff --git a/tests/CoreTests/android/core/TestEventHandler.java b/tests/CoreTests/android/core/TestEventHandler.java
new file mode 100644
index 0000000..4cfcade
--- /dev/null
+++ b/tests/CoreTests/android/core/TestEventHandler.java
@@ -0,0 +1,811 @@
+/*
+ * Copyright (C) 2007 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 android.core;
+
+import java.util.ArrayList;
+import java.util.Map;
+
+import org.apache.http.protocol.HTTP;
+import android.util.Log;
+import android.util.Config;
+import android.net.http.*;
+
+/**
+ * Implements EventHandler and provides test functionality to validate
+ * responses to requests from the test server
+ */
+public class TestEventHandler implements EventHandler {
+
+ /**
+ * Status variables
+ */
+ private int majorVersion = -1;
+ private int minorVersion = -1;
+ private int responseCode = -1;
+ private String reasonPhrase;
+
+ /* List of headers received */
+ private Map<String, String> headerMap;
+
+ /* Used to sync low level delayed requests */
+ public static final Object syncObj = new Object();
+
+ /* Indicates whether the low level request testing is in operation */
+ private boolean useLowLevel = false;
+
+ /* Indicates whether responses should be automatically generated or
+ * delayed
+ */
+ private boolean delayResponse = false;
+
+ /* Test method expectation identifiers */
+ public final static int TEST_REQUEST_SENT = 0;
+ public final static int TEST_STATUS = 1;
+ public final static int TEST_HEADERS = 2;
+ public final static int TEST_LOCATION_CHANGED = 3;
+ public final static int TEST_DATA = 4;
+ public final static int TEST_ENDDATA = 5;
+ public final static int TEST_ERROR = 6;
+ public final static int TEST_SSL_CERTIFICATE_ERROR = 7;
+
+ public final static int TEST_NUM_EXPECTS = 8;
+
+ /* Expected status codes */
+ private int expectMajor = -1;
+ private int expectMinor = -1;
+ private int expectCode = -1;
+
+ /* Array indicating which event types are expected */
+ private boolean[] expects = new boolean[TEST_NUM_EXPECTS];
+
+ /* Array indicating which event types are not expected */
+ private boolean[] notExpecting = new boolean[TEST_NUM_EXPECTS];
+
+ /* Indicates which events have been received */
+ private boolean[] eventsReceived = new boolean[TEST_NUM_EXPECTS];
+
+ /* Redirection variables */
+ private String expectLocation;
+ private int expectPermanent = -1;
+
+ /* Content data expected to be received */
+ private byte[] expectData;
+ private int expectDataLength = -1;
+
+ private int expectErrorId = -1;
+
+ private int expectSslErrors = -1;
+ private SslCertificate expectCertificate;
+
+ public class TestHeader {
+ public TestHeader(String n, String v) {
+ name = n;
+ value = v;
+ }
+ public String name;
+ public String value;
+ }
+
+ private ArrayList<TestHeader> expectHeaders = new ArrayList<TestHeader>();
+
+ /* Holds failure details */
+ private StringBuffer expectDetails = new StringBuffer();
+
+ /* If we use a request handle, we retain a reference here for redirects
+ * using setupRedirect
+ */
+ private RequestHandle mRequestHandle;
+
+ /* The low level API uses this reference also for non-delayed requests */
+ private LowLevelNetRunner netRunner;
+
+ public TestEventHandler() {
+ for (int i = 0; i < TEST_NUM_EXPECTS; i++) {
+ expects[i] = false;
+ notExpecting[i] = false;
+ eventsReceived[i] = false;
+ }
+ }
+
+ /**
+ * Implementation of EventHandler method called when a request has been
+ * sent. If the test is waiting for this call, it will be signalled,
+ * otherwise this method will trigger the response to be read
+ * automatically.
+ */
+ public void requestSent() {
+ Log.v(LOGTAG, "TestEventHandler:requestSent()");
+ expects[TEST_REQUEST_SENT] = false;
+ eventsReceived[TEST_REQUEST_SENT] = true;
+ if (notExpecting[TEST_REQUEST_SENT]) {
+ expectDetails.append("Request sent event received but not expected");
+ expectDetails.append("\r\n");
+ }
+
+ if (useLowLevel) {
+ if (delayResponse) {
+ synchronized (syncObj) {
+ syncObj.notifyAll();
+ }
+ } else {
+ // mRequest.startReadingResponse();
+ }
+ }
+ }
+
+ /**
+ * Implements the EventHandler status method called when a server status
+ * response is received.
+ * @param major_version The HTTP major version
+ * @param minor_version The HTTP minor version
+ * @param code The status code
+ * @param reason_phrase A reason phrase passed to us by the server
+ */
+ public void status(int major_version, int minor_version,
+ int code, String reason_phrase) {
+ if (Config.LOGV) {
+ Log.v(LOGTAG, "TestEventHandler:status() major: " + major_version +
+ " minor: " + minor_version +
+ " code: " + code +
+ " reason: " + reason_phrase);
+ }
+
+ eventsReceived[TEST_STATUS] = true;
+ if (notExpecting[TEST_STATUS]) {
+ expectDetails.append("Status event received but not expected");
+ expectDetails.append("\r\n");
+ }
+
+ majorVersion = major_version;
+ minorVersion = minor_version;
+ responseCode = code;
+ reasonPhrase = reason_phrase;
+
+ if (expectMajor != -1) {
+ if (expectMajor == major_version) {
+ expectMajor = -1;
+ } else {
+ expectDetails.append("Major version expected:"+expectMajor+
+ " got:"+major_version);
+ expectDetails.append("\r\n");
+ }
+ }
+
+ if (expectMinor != -1) {
+ if (expectMinor == minor_version) {
+ expectMinor = -1;
+ } else {
+ expectDetails.append("Minor version expected:"+expectMinor+
+ " got:"+minor_version);
+ expectDetails.append("\r\n");
+ }
+ }
+
+ if (expectCode != -1) {
+ if (expectCode == code) {
+ expectCode = -1;
+ } else {
+ expectDetails.append("Status code expected:"+expectCode+
+ " got:"+code);
+ expectDetails.append("\r\n");
+ }
+ }
+
+
+ if ((expectMajor == -1) && (expectMinor == -1) && (expectCode == -1)) {
+ expects[TEST_STATUS] = false;
+ } else {
+ System.out.println("MAJOR = "+expectMajor+" MINOR = "+expectMinor+
+ " CODE = "+expectCode);
+ }
+ }
+
+ /**
+ * Implements the EventHandler headers method called when a server
+ * sends header fields
+ */
+ public void headers(Headers headers) {
+ if (Config.LOGV) {
+ Log.v(LOGTAG, "TestEventHandler:headers()");
+ }
+ expects[TEST_HEADERS] = false;
+
+ if (notExpecting[TEST_HEADERS]) {
+ expectDetails.append("Header event received but not expected");
+ expectDetails.append("\r\n");
+ }
+
+ /* Check through headers received for matches with expected
+ * headers */
+ if (expectHeaders.isEmpty()) {
+ return;
+ }
+
+ for (int i = expectHeaders.size() - 1; i >= 0; i--) {
+ TestHeader h = expectHeaders.get(i);
+ System.out.println("Expected header name: " + h.name);
+ String s = null;
+ switch (h.name.hashCode()) {
+ case -1132779846:
+ s = Long.toString(headers.getContentLength());
+ break;
+ case 785670158:
+ s = headers.getContentType();
+ break;
+ case 2095084583:
+ s = headers.getContentEncoding();
+ break;
+ case 1901043637:
+ s = headers.getLocation();
+ break;
+ case -243037365:
+ s = headers.getWwwAuthenticate();
+ break;
+ case -301767724:
+ s = headers.getProxyAuthenticate();
+ break;
+ case -1267267485:
+ s = headers.getContentDisposition();
+ break;
+ case 1397189435:
+ s = headers.getAcceptRanges();
+ break;
+ case -1309235404:
+ s = headers.getExpires();
+ break;
+ case -208775662:
+ s = headers.getCacheControl();
+ break;
+ case 150043680:
+ s = headers.getLastModified();
+ break;
+ case 3123477:
+ s = headers.getEtag();
+ break;
+ case -775651618:
+ int ct = headers.getConnectionType();
+ if (ct == Headers.CONN_CLOSE) {
+ s = HTTP.CONN_CLOSE;
+ } else if (ct == Headers.CONN_KEEP_ALIVE) {
+ s = HTTP.CONN_KEEP_ALIVE;
+ }
+ break;
+ default:
+ s = null;
+
+ }
+ if (evaluateHeader(h, s)) {
+ expectHeaders.remove(i);
+ }
+ }
+
+ }
+
+ public boolean evaluateHeader(TestHeader h, String value) {
+ if (value == null) {
+ expects[TEST_HEADERS] = true;
+ System.out.print(" Missing! ");
+ expectDetails.append(" missing header " + h.name);
+ return false;
+ }
+ if (h.value == null) {
+ System.out.println("Expect value = null");
+ return true;
+ }
+ System.out.println("Expect value = " +
+ (h.value.toLowerCase()) + " got " +
+ value.toLowerCase());
+
+ if (!h.value.equalsIgnoreCase(value)) {
+ expectDetails.append("expect header value " + h.value +
+ " got " + value);
+ expects[TEST_HEADERS] = true;
+ return false;
+ }
+ return true;
+ }
+ /**
+ * Implements the EventHandler locationChanged method called when a server
+ * sends a redirect message
+ * @param newLocation The URL to the new server
+ * @param permanent Indicator of whether this is a permanent change
+ */
+ public void locationChanged(String newLocation, boolean permanent) {
+ if (Config.LOGV) {
+ Log.v(LOGTAG, "TestEventHandler: locationChanged() " +
+ newLocation + " permanent " + permanent);
+ }
+
+ eventsReceived[TEST_LOCATION_CHANGED] = true;
+ if (notExpecting[TEST_LOCATION_CHANGED]) {
+ expectDetails.append("Location changed event received but "+
+ "not expected");
+ expectDetails.append("\r\n");
+ }
+
+ if (expectLocation != null) {
+ if (expectLocation.equals(newLocation)) {
+ expectLocation = null;
+ } else {
+ expectDetails.append("Location expected:"+expectLocation+
+ " got:"+newLocation);
+ expectDetails.append("\r\n");
+ }
+ }
+
+ if (expectPermanent != -1) {
+ if (((expectPermanent == 0) && !permanent) ||
+ ((expectPermanent == 1) && permanent)){
+ expectPermanent = -1;
+ } else {
+ expectDetails.append("Location permanent expected:"+
+ expectPermanent+" got"+permanent);
+ expectDetails.append("\r\n");
+ }
+ }
+
+ if ((expectLocation == null) && (expectPermanent == -1))
+ expects[TEST_LOCATION_CHANGED] = false;
+ }
+
+ /**
+ * Implements the EventHandler data method called when a server
+ * sends content data
+ * @param data The byte array content
+ * @param len The length of the data
+ */
+ public void data(byte[] data, int len) {
+ boolean mismatch = false;
+
+ if (Config.LOGV) {
+ Log.v(LOGTAG, "TestEventHandler: data() " + len + " bytes");
+ }
+
+ eventsReceived[TEST_DATA] = true;
+ if (notExpecting[TEST_DATA]) {
+ expectDetails.append("Data event received but not expected");
+ expectDetails.append("\r\n");
+ }
+
+ Log.v(LOGTAG, new String(data, 0, len));
+
+ if (expectDataLength != -1) {
+ if (expectDataLength == len) {
+ expectDataLength = -1;
+ } else {
+ expectDetails.append("expect data length mismatch expected:"+
+ expectDataLength+" got:"+len);
+ expectDetails.append("\r\n");
+ }
+
+ /* Check data only if length is the same */
+ if ((expectDataLength == -1) && expectData != null) {
+ for (int i = 0; i < len; i++) {
+ if (expectData[i] != data[i]) {
+ mismatch = true;
+ expectDetails.append("Expect data mismatch at byte "+
+ i+" expected:"+expectData[i]+" got:"+data[i]);
+ expectDetails.append("\r\n");
+ break;
+ }
+ }
+ }
+ }
+
+ if ((expectDataLength == -1) || !mismatch)
+ expects[TEST_DATA] = false;
+ }
+
+ /**
+ * Implements the EventHandler endData method called to
+ * indicate completion or a request
+ */
+ public void endData() {
+ if (Config.LOGV) {
+ Log.v(LOGTAG, "TestEventHandler: endData() called");
+ }
+
+ eventsReceived[TEST_ENDDATA] = true;
+ if (notExpecting[TEST_ENDDATA]) {
+ expectDetails.append("End data event received but not expected");
+ expectDetails.append("\r\n");
+ }
+
+ expects[TEST_ENDDATA] = false;
+
+ if (useLowLevel) {
+ if (delayResponse) {
+ synchronized (syncObj) {
+ syncObj.notifyAll();
+ }
+ } else {
+ if (netRunner != null) {
+ System.out.println("TestEventHandler: endData() stopping "+
+ netRunner);
+ netRunner.decrementRunCount();
+ }
+ }
+ }
+ }
+
+ /**
+ * Implements the EventHandler certificate method called every
+ * time a resource is loaded via a secure connection
+ */
+ public void certificate(SslCertificate certificate) {}
+
+ /**
+ * Implements the EventHandler error method called when a server
+ * sends header fields
+ * @param id Status code of the error
+ * @param description Brief description of the error
+ */
+ public void error(int id, String description) {
+ if (Config.LOGV) {
+ Log.v(LOGTAG, "TestEventHandler: error() called Id:" + id +
+ " description " + description);
+ }
+
+ eventsReceived[TEST_ERROR] = true;
+ if (notExpecting[TEST_ERROR]) {
+ expectDetails.append("Error event received but not expected");
+ expectDetails.append("\r\n");
+ }
+ if (expectErrorId != -1) {
+ if (expectErrorId == id) {
+ expectErrorId = -1;
+ } else {
+ expectDetails.append("Error Id expected:"+expectErrorId+
+ " got:"+id);
+ expectDetails.append("\r\n");
+ }
+ }
+
+ if (expectErrorId == -1)
+ expects[TEST_ERROR] = false;
+
+ if (useLowLevel) {
+ if (delayResponse) {
+ synchronized (syncObj) {
+ syncObj.notifyAll();
+ }
+ } else {
+ if (netRunner != null) {
+ System.out.println("TestEventHandler: endData() stopping "+
+ netRunner);
+ netRunner.decrementRunCount();
+ }
+ }
+ }
+ }
+
+ /**
+ * SSL certificate error callback. Handles SSL error(s) on the way
+ * up to the user.
+ */
+ public void handleSslErrorRequest(SslError error) {
+ int primaryError = error.getPrimaryError();
+
+ if (Config.LOGV) {
+ Log.v(LOGTAG, "TestEventHandler: handleSslErrorRequest(): "+
+ " primary error:" + primaryError +
+ " certificate: " + error.getCertificate());
+ }
+
+ eventsReceived[TEST_SSL_CERTIFICATE_ERROR] = true;
+ if (notExpecting[TEST_SSL_CERTIFICATE_ERROR]) {
+ expectDetails.append("SSL Certificate error event received "+
+ "but not expected");
+ expectDetails.append("\r\n");
+ }
+
+ if (expectSslErrors != -1) {
+ if (expectSslErrors == primaryError) {
+ expectSslErrors = -1;
+ } else {
+ expectDetails.append("SslCertificateError id expected:"+
+ expectSslErrors+" got: " + primaryError);
+ expectDetails.append("\r\n");
+ }
+ }
+
+ // SslCertificate match here?
+
+ if (expectSslErrors == -1) // && expectSslCertificate == certificate?
+ expects[TEST_SSL_CERTIFICATE_ERROR] = false;
+ }
+
+ /**
+ * Use the low level net runner with no delayed response
+ * @param runner The LowLevelNetRunner object
+ */
+ public void setNetRunner(LowLevelNetRunner runner) {
+ setNetRunner(runner, false);
+ }
+
+ /**
+ * Use the low level net runner and specify if the response
+ * should be delayed
+ * @param runner The LowLevelNetRunner object
+ * @param delayedResponse Set to true is you will use the
+ * waitForRequestSent/waitForRequestResponse routines
+ */
+ public void setNetRunner(LowLevelNetRunner runner,
+ boolean delayedResponse) {
+ netRunner = runner;
+ useLowLevel = true;
+ delayResponse = delayedResponse;
+
+ if (!delayResponse)
+ netRunner.incrementRunCount();
+ }
+
+ /**
+ * Enable this listeners Request object to read server responses.
+ * This should only be used in conjunction with setDelayResponse(true)
+ */
+ public void waitForRequestResponse() {
+ if (!delayResponse || !useLowLevel) {
+ Log.d(LOGTAG, " Cant do this without delayReponse set ");
+ return;
+ }
+
+ //if (mRequest != null) {
+ // mRequest.startReadingResponse();
+ // }
+ /* Now wait for the response to be completed either through endData
+ * or an error
+ */
+ synchronized (syncObj) {
+ try {
+ syncObj.wait();
+ } catch (InterruptedException e) {
+ }
+ }
+ }
+
+ /**
+ * Enable this listeners Request object to read server responses.
+ * This should only be used in conjunction with setDelayResponse(true)
+ */
+ public void waitForRequestSent() {
+ if (!delayResponse || !useLowLevel) {
+ Log.d(LOGTAG, " Cant do this without delayReponse set ");
+ return;
+ }
+
+ /* Now wait for the response to be completed either through endData
+ * or an error
+ */
+ synchronized (syncObj) {
+ try {
+ syncObj.wait();
+ } catch (InterruptedException e) {
+ }
+ }
+ }
+
+ /* Test expected values - these routines set the tests expectations */
+
+ public void expectRequestSent() {
+ expects[TEST_REQUEST_SENT] = true;
+ }
+
+ public void expectNoRequestSent() {
+ notExpecting[TEST_REQUEST_SENT] = true;
+ }
+
+ public void expectStatus() {
+ expects[TEST_STATUS] = true;
+ }
+
+ public void expectNoStatus() {
+ notExpecting[TEST_STATUS] = true;
+ }
+
+ public void expectStatus(int major, int minor, int code) {
+ expects[TEST_STATUS] = true;
+ expectMajor = major;
+ expectMinor = minor;
+ expectCode = code;
+ }
+
+ public void expectStatus(int code) {
+ expects[TEST_STATUS] = true;
+ expectCode = code;
+ }
+
+ public void expectHeaders() {
+ expects[TEST_HEADERS] = true;
+ }
+
+ public void expectNoHeaders() {
+ notExpecting[TEST_HEADERS] = true;
+ }
+
+ public void expectHeaderAdd(String name) {
+ expects[TEST_HEADERS] = true;
+ TestHeader h = new TestHeader(name.toLowerCase(), null);
+ expectHeaders.add(h);
+ }
+
+ public void expectHeaderAdd(String name, String value) {
+ expects[TEST_HEADERS] = true;
+ TestHeader h = new TestHeader(name.toLowerCase(), value);
+ expectHeaders.add(h);
+ }
+
+ public void expectLocationChanged() {
+ expects[TEST_LOCATION_CHANGED] = true;
+ }
+
+ public void expectNoLocationChanged() {
+ notExpecting[TEST_LOCATION_CHANGED] = true;
+ }
+
+ public void expectLocationChanged(String newLocation) {
+ expects[TEST_LOCATION_CHANGED] = true;
+ expectLocation = newLocation;
+ }
+
+ public void expectLocationChanged(String newLocation, boolean permanent) {
+ expects[TEST_LOCATION_CHANGED] = true;
+ expectLocation = newLocation;
+ expectPermanent = permanent ? 1 : 0;
+ }
+
+ public void expectData() {
+ expects[TEST_DATA] = true;
+ }
+
+ public void expectNoData() {
+ notExpecting[TEST_DATA] = true;
+ }
+
+ public void expectData(int len) {
+ expects[TEST_DATA] = true;
+ expectDataLength = len;
+ }
+
+ public void expectData(byte[] data, int len) {
+ expects[TEST_DATA] = true;
+ expectData = new byte[len];
+ expectDataLength = len;
+
+ for (int i = 0; i < len; i++) {
+ expectData[i] = data[i];
+ }
+ }
+
+ public void expectEndData() {
+ expects[TEST_ENDDATA] = true;
+ }
+
+ public void expectNoEndData() {
+ notExpecting[TEST_ENDDATA] = true;
+ }
+
+ public void expectError() {
+ expects[TEST_ERROR] = true;
+ }
+
+ public void expectNoError() {
+ notExpecting[TEST_ERROR] = true;
+ }
+
+ public void expectError(int errorId) {
+ expects[TEST_ERROR] = true;
+ expectErrorId = errorId;
+ }
+
+ public void expectSSLCertificateError() {
+ expects[TEST_SSL_CERTIFICATE_ERROR] = true;
+ }
+
+ public void expectNoSSLCertificateError() {
+ notExpecting[TEST_SSL_CERTIFICATE_ERROR] = true;
+ }
+
+ public void expectSSLCertificateError(int errors) {
+ expects[TEST_SSL_CERTIFICATE_ERROR] = true;
+ expectSslErrors = errors;
+ }
+
+ public void expectSSLCertificateError(SslCertificate certificate) {
+ expects[TEST_SSL_CERTIFICATE_ERROR] = true;
+ expectCertificate = certificate;
+ }
+
+ /**
+ * Test to see if current expectations match recieved information
+ * @return True is all expected results have been matched
+ */
+ public boolean expectPassed() {
+ for (int i = 0; i < TEST_NUM_EXPECTS; i++) {
+ if (expects[i] == true) {
+ return false;
+ }
+ }
+
+ for (int i = 0; i < TEST_NUM_EXPECTS; i++) {
+ if (eventsReceived[i] && notExpecting[i]) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /**
+ * Return message indicating expectation failures
+ */
+ public String getFailureMessage() {
+ return expectDetails.toString();
+ }
+
+ /**
+ * Reset all expectation values for re-use
+ */
+ public void resetExpects() {
+ expectMajor = -1;
+ expectMinor = -1;
+ expectCode = -1;
+ expectLocation = null;
+ expectPermanent = -1;
+ expectErrorId = -1;
+ expectSslErrors = -1;
+ expectCertificate = null;
+ expectDetails.setLength(0);
+ expectHeaders.clear();
+
+ for (int i = 0; i < TEST_NUM_EXPECTS; i++) {
+ expects[i] = false;
+ notExpecting[i] = false;
+ eventsReceived[i] = false;
+ }
+
+ for (int i = 0; i < expectDataLength; i++) {
+ expectData[i] = 0;
+ }
+
+ expectDataLength = -1;
+ }
+
+ /**
+ * Attach the RequestHandle to this handler
+ * @param requestHandle The RequestHandle
+ */
+ public void attachRequestHandle(RequestHandle requestHandle) {
+ if (Config.LOGV) {
+ Log.v(LOGTAG, "TestEventHandler.attachRequestHandle(): " +
+ "requestHandle: " + requestHandle);
+ }
+ mRequestHandle = requestHandle;
+ }
+
+ /**
+ * Detach the RequestHandle
+ */
+ public void detachRequestHandle() {
+ if (Config.LOGV) {
+ Log.v(LOGTAG, "TestEventHandler.detachRequestHandle(): " +
+ "requestHandle: " + mRequestHandle);
+ }
+ mRequestHandle = null;
+ }
+
+ protected final static String LOGTAG = "http";
+}
diff --git a/tests/CoreTests/android/core/TestWebData.java b/tests/CoreTests/android/core/TestWebData.java
new file mode 100644
index 0000000..2ef19be
--- /dev/null
+++ b/tests/CoreTests/android/core/TestWebData.java
@@ -0,0 +1,132 @@
+/*
+ * Copyright (C) 2007 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 android.core;
+
+/**
+ * Represents test data used by the Request API tests
+ */
+public class TestWebData {
+
+ /*
+ * Simple Html body
+ * <html>
+ * <body>
+ * <h1>Hello World!</h1>
+ * </body>
+ * </html>
+ */
+ public final static byte[] test1 = {
+ (byte)0x3c, (byte)0x68, (byte)0x74, (byte)0x6d,
+ (byte)0x6c, (byte)0x3e, (byte)0x0a, (byte)0x3c,
+ (byte)0x62, (byte)0x6f, (byte)0x64, (byte)0x79,
+ (byte)0x3e, (byte)0x0a, (byte)0x3c, (byte)0x68,
+ (byte)0x31, (byte)0x3e, (byte)0x48, (byte)0x65,
+ (byte)0x6c, (byte)0x6c, (byte)0x6f, (byte)0x20,
+ (byte)0x57, (byte)0x6f, (byte)0x72, (byte)0x6c,
+ (byte)0x64, (byte)0x21, (byte)0x3c, (byte)0x2f,
+ (byte)0x68, (byte)0x31, (byte)0x3e, (byte)0x0a,
+ (byte)0x3c, (byte)0x2f, (byte)0x62, (byte)0x6f,
+ (byte)0x64, (byte)0x79, (byte)0x3e, (byte)0x0a,
+ (byte)0x3c, (byte)0x2f, (byte)0x68, (byte)0x74,
+ (byte)0x6d, (byte)0x6c, (byte)0x3e, (byte)0x0a
+ };
+
+ /*
+ * Simple Html body
+ * <html>
+ * <body>
+ * <h1>Hello World!</h1>
+ * </body>
+ * </html>
+ */
+ public final static byte[] test2 = {
+ (byte)0x3c, (byte)0x68, (byte)0x74, (byte)0x6d,
+ (byte)0x6c, (byte)0x3e, (byte)0x0a, (byte)0x3c,
+ (byte)0x62, (byte)0x6f, (byte)0x64, (byte)0x79,
+ (byte)0x3e, (byte)0x0a, (byte)0x3c, (byte)0x68,
+ (byte)0x31, (byte)0x3e, (byte)0x48, (byte)0x65,
+ (byte)0x6c, (byte)0x6c, (byte)0x6f, (byte)0x20,
+ (byte)0x57, (byte)0x6f, (byte)0x72, (byte)0x6c,
+ (byte)0x64, (byte)0x21, (byte)0x3c, (byte)0x2f,
+ (byte)0x68, (byte)0x31, (byte)0x3e, (byte)0x0a,
+ (byte)0x3c, (byte)0x2f, (byte)0x62, (byte)0x6f,
+ (byte)0x64, (byte)0x79, (byte)0x3e, (byte)0x0a,
+ (byte)0x3c, (byte)0x2f, (byte)0x68, (byte)0x74,
+ (byte)0x6d, (byte)0x6c, (byte)0x3e, (byte)0x0a
+ };
+
+ // string for test request post body
+ public final static String postContent = "user=111";
+
+ // Array of all test data
+ public final static byte[][] tests = {
+ test1,
+ test2
+ };
+
+ /**
+ * List of static test cases for use with test server
+ */
+ public static TestWebData[] testParams = {
+ new TestWebData(52, 14000000, "test1", "text/html", false),
+ new TestWebData(52, 14000002, "test2", "unknown/unknown", false)
+ };
+
+ /**
+ * List of response strings for use by the test server
+ */
+ public static String[] testServerResponse = {
+ "Redirecting 301",
+ "Redirecting 302",
+ "Redirecting 303",
+ "Redirecting 307"
+ };
+
+ // Redirection indices into testServerResponse
+ public final static int REDIRECT_301 = 0;
+ public final static int REDIRECT_302 = 1;
+ public final static int REDIRECT_303 = 2;
+ public final static int REDIRECT_307 = 3;
+
+ /**
+ * Creates a data package with information used by the server when responding
+ * to requests
+ */
+ TestWebData(int length, int lastModified, String name, String type, boolean isDir) {
+ testLength = length;
+ testLastModified = lastModified;
+ testName = name;
+ testType = type;
+ testDir = isDir;
+ }
+
+ // Length of test entity body
+ public int testLength;
+
+ // Last modified date value (milliseconds)
+ public int testLastModified;
+
+ // Test identification name
+ public String testName;
+
+ // The MIME type to assume for this test
+ public String testType;
+
+ // Indicates if this is a directory or not
+ public boolean testDir;
+
+}
diff --git a/tests/CoreTests/android/core/TestWebServer.java b/tests/CoreTests/android/core/TestWebServer.java
new file mode 100644
index 0000000..f73e6ff
--- /dev/null
+++ b/tests/CoreTests/android/core/TestWebServer.java
@@ -0,0 +1,871 @@
+/*
+ * Copyright (C) 2007 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 android.core;
+
+import android.util.Log;
+
+import java.io.*;
+import java.lang.Thread;
+import java.net.*;
+import java.util.*;
+
+/**
+ * TestWebServer is a simulated controllable test server that
+ * can respond to requests from HTTP clients.
+ *
+ * The server can be controlled to change how it reacts to any
+ * requests, and can be told to simulate various events (such as
+ * network failure) that would happen in a real environment.
+ */
+class TestWebServer implements HttpConstants {
+
+ /* static class data/methods */
+
+ /* The ANDROID_LOG_TAG */
+ private final static String LOGTAG = "httpsv";
+
+ /* Where worker threads stand idle */
+ Vector threads = new Vector();
+
+ /* List of all active worker threads */
+ Vector activeThreads = new Vector();
+
+ /* timeout on client connections */
+ int timeout = 0;
+
+ /* max # worker threads */
+ int workers = 5;
+
+ /* Default port for this server to listen on */
+ final static int DEFAULT_PORT = 8080;
+
+ /* Default socket timeout value */
+ final static int DEFAULT_TIMEOUT = 5000;
+
+ /* Version string (configurable) */
+ protected String HTTP_VERSION_STRING = "HTTP/1.1";
+
+ /* Indicator for whether this server is configured as a HTTP/1.1
+ * or HTTP/1.0 server
+ */
+ private boolean http11 = true;
+
+ /* The thread handling new requests from clients */
+ private AcceptThread acceptT;
+
+ /* timeout on client connections */
+ int mTimeout;
+
+ /* Server port */
+ int mPort;
+
+ /* Switch on/off logging */
+ boolean mLog = false;
+
+ /* If set, this will keep connections alive after a request has been
+ * processed.
+ */
+ boolean keepAlive = true;
+
+ /* If set, this will cause response data to be sent in 'chunked' format */
+ boolean chunked = false;
+
+ /* If set, this will indicate a new redirection host */
+ String redirectHost = null;
+
+ /* If set, this indicates the reason for redirection */
+ int redirectCode = -1;
+
+ /* Set the number of connections the server will accept before shutdown */
+ int acceptLimit = 100;
+
+ /* Count of number of accepted connections */
+ int acceptedConnections = 0;
+
+ public TestWebServer() {
+ }
+
+ /**
+ * Initialize a new server with default port and timeout.
+ * @param log Set true if you want trace output
+ */
+ public void initServer(boolean log) throws Exception {
+ initServer(DEFAULT_PORT, DEFAULT_TIMEOUT, log);
+ }
+
+ /**
+ * Initialize a new server with default timeout.
+ * @param port Sets the server to listen on this port
+ * @param log Set true if you want trace output
+ */
+ public void initServer(int port, boolean log) throws Exception {
+ initServer(port, DEFAULT_TIMEOUT, log);
+ }
+
+ /**
+ * Initialize a new server with default port and timeout.
+ * @param port Sets the server to listen on this port
+ * @param timeout Indicates the period of time to wait until a socket is
+ * closed
+ * @param log Set true if you want trace output
+ */
+ public void initServer(int port, int timeout, boolean log) throws Exception {
+ mPort = port;
+ mTimeout = timeout;
+ mLog = log;
+ keepAlive = true;
+
+ if (acceptT == null) {
+ acceptT = new AcceptThread();
+ acceptT.init();
+ acceptT.start();
+ }
+ }
+
+ /**
+ * Print to the log file (if logging enabled)
+ * @param s String to send to the log
+ */
+ protected void log(String s) {
+ if (mLog) {
+ Log.d(LOGTAG, s);
+ }
+ }
+
+ /**
+ * Set the server to be an HTTP/1.0 or HTTP/1.1 server.
+ * This should be called prior to any requests being sent
+ * to the server.
+ * @param set True for the server to be HTTP/1.1, false for HTTP/1.0
+ */
+ public void setHttpVersion11(boolean set) {
+ http11 = set;
+ if (set) {
+ HTTP_VERSION_STRING = "HTTP/1.1";
+ } else {
+ HTTP_VERSION_STRING = "HTTP/1.0";
+ }
+ }
+
+ /**
+ * Call this to determine whether server connection should remain open
+ * @param value Set true to keep connections open after a request
+ * completes
+ */
+ public void setKeepAlive(boolean value) {
+ keepAlive = value;
+ }
+
+ /**
+ * Call this to indicate whether chunked data should be used
+ * @param value Set true to make server respond with chunk encoded
+ * content data.
+ */
+ public void setChunked(boolean value) {
+ chunked = value;
+ }
+
+ /**
+ * Call this to specify the maximum number of sockets to accept
+ * @param limit The number of sockets to accept
+ */
+ public void setAcceptLimit(int limit) {
+ acceptLimit = limit;
+ }
+
+ /**
+ * Call this to indicate redirection port requirement.
+ * When this value is set, the server will respond to a request with
+ * a redirect code with the Location response header set to the value
+ * specified.
+ * @param redirect The location to be redirected to
+ * @param redirectCode The code to send when redirecting
+ */
+ public void setRedirect(String redirect, int code) {
+ redirectHost = redirect;
+ redirectCode = code;
+ log("Server will redirect output to "+redirect+" code "+code);
+ }
+
+ /**
+ * Cause the thread accepting connections on the server socket to close
+ */
+ public void close() {
+ /* Stop the Accept thread */
+ if (acceptT != null) {
+ log("Closing AcceptThread"+acceptT);
+ acceptT.close();
+ acceptT = null;
+ }
+ }
+ /**
+ * The AcceptThread is responsible for initiating worker threads
+ * to handle incoming requests from clients.
+ */
+ class AcceptThread extends Thread {
+
+ ServerSocket ss = null;
+ boolean running = false;
+
+ public void init() {
+ // Networking code doesn't support ServerSocket(port) yet
+ InetSocketAddress ia = new InetSocketAddress(mPort);
+ while (true) {
+ try {
+ ss = new ServerSocket();
+ // Socket timeout functionality is not available yet
+ //ss.setSoTimeout(5000);
+ ss.setReuseAddress(true);
+ ss.bind(ia);
+ break;
+ } catch (IOException e) {
+ log("IOException in AcceptThread.init()");
+ e.printStackTrace();
+ // wait and retry
+ try {
+ Thread.sleep(1000);
+ } catch (InterruptedException e1) {
+ // TODO Auto-generated catch block
+ e1.printStackTrace();
+ }
+ }
+ }
+ }
+
+ /**
+ * Main thread responding to new connections
+ */
+ public synchronized void run() {
+ running = true;
+ try {
+ while (running) {
+ // Log.d(LOGTAG, "TestWebServer run() calling accept()");
+ Socket s = ss.accept();
+ acceptedConnections++;
+ if (acceptedConnections >= acceptLimit) {
+ running = false;
+ }
+
+ Worker w = null;
+ synchronized (threads) {
+ if (threads.isEmpty()) {
+ Worker ws = new Worker();
+ ws.setSocket(s);
+ activeThreads.addElement(ws);
+ (new Thread(ws, "additional worker")).start();
+ } else {
+ w = (Worker) threads.elementAt(0);
+ threads.removeElementAt(0);
+ w.setSocket(s);
+ }
+ }
+ }
+ } catch (SocketException e) {
+ log("SocketException in AcceptThread: probably closed during accept");
+ running = false;
+ } catch (IOException e) {
+ log("IOException in AcceptThread");
+ e.printStackTrace();
+ running = false;
+ }
+ log("AcceptThread terminated" + this);
+ }
+
+ // Close this socket
+ public void close() {
+ try {
+ running = false;
+ /* Stop server socket from processing further. Currently
+ this does not cause the SocketException from ss.accept
+ therefore the acceptLimit functionality has been added
+ to circumvent this limitation */
+ ss.close();
+
+ // Stop worker threads from continuing
+ for (Enumeration e = activeThreads.elements(); e.hasMoreElements();) {
+ Worker w = (Worker)e.nextElement();
+ w.close();
+ }
+ activeThreads.clear();
+
+ } catch (IOException e) {
+ /* We are shutting down the server, so we expect
+ * things to die. Don't propagate.
+ */
+ log("IOException caught by server socket close");
+ }
+ }
+ }
+
+ // Size of buffer for reading from the connection
+ final static int BUF_SIZE = 2048;
+
+ /* End of line byte sequence */
+ static final byte[] EOL = {(byte)'\r', (byte)'\n' };
+
+ /**
+ * The worker thread handles all interactions with a current open
+ * connection. If pipelining is turned on, this will allow this
+ * thread to continuously operate on numerous requests before the
+ * connection is closed.
+ */
+ class Worker implements HttpConstants, Runnable {
+
+ /* buffer to use to hold request data */
+ byte[] buf;
+
+ /* Socket to client we're handling */
+ private Socket s;
+
+ /* Reference to current request method ID */
+ private int requestMethod;
+
+ /* Reference to current requests test file/data */
+ private String testID;
+
+ /* Reference to test number from testID */
+ private int testNum;
+
+ /* Reference to whether new request has been initiated yet */
+ private boolean readStarted;
+
+ /* Indicates whether current request has any data content */
+ private boolean hasContent = false;
+
+ boolean running = false;
+
+ /* Request headers are stored here */
+ private Hashtable<String, String> headers = new Hashtable<String, String>();
+
+ /* Create a new worker thread */
+ Worker() {
+ buf = new byte[BUF_SIZE];
+ s = null;
+ }
+
+ /**
+ * Called by the AcceptThread to unblock this Worker to process
+ * a request.
+ * @param s The socket on which the connection has been made
+ */
+ synchronized void setSocket(Socket s) {
+ this.s = s;
+ notify();
+ }
+
+ /**
+ * Called by the accept thread when it's closing. Potentially unblocks
+ * the worker thread to terminate properly
+ */
+ synchronized void close() {
+ running = false;
+ notify();
+ }
+
+ /**
+ * Main worker thread. This will wait until a request has
+ * been identified by the accept thread upon which it will
+ * service the thread.
+ */
+ public synchronized void run() {
+ running = true;
+ while(running) {
+ if (s == null) {
+ /* nothing to do */
+ try {
+ log(this+" Moving to wait state");
+ wait();
+ } catch (InterruptedException e) {
+ /* should not happen */
+ continue;
+ }
+ if (!running) break;
+ }
+ try {
+ handleClient();
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ /* go back in wait queue if there's fewer
+ * than numHandler connections.
+ */
+ s = null;
+ Vector pool = threads;
+ synchronized (pool) {
+ if (pool.size() >= workers) {
+ /* too many threads, exit this one */
+ activeThreads.remove(this);
+ return;
+ } else {
+ pool.addElement(this);
+ }
+ }
+ }
+ log(this+" terminated");
+ }
+
+ /**
+ * Zero out the buffer from last time
+ */
+ private void clearBuffer() {
+ for (int i = 0; i < BUF_SIZE; i++) {
+ buf[i] = 0;
+ }
+ }
+
+ /**
+ * Utility method to read a line of data from the input stream
+ * @param is Inputstream to read
+ * @return number of bytes read
+ */
+ private int readOneLine(InputStream is) {
+
+ int read = 0;
+
+ clearBuffer();
+ try {
+ log("Reading one line: started ="+readStarted+" avail="+is.available());
+ while ((!readStarted) || (is.available() > 0)) {
+ int data = is.read();
+ // We shouldn't get EOF but we need tdo check
+ if (data == -1) {
+ log("EOF returned");
+ return -1;
+ }
+
+ buf[read] = (byte)data;
+
+ System.out.print((char)data);
+
+ readStarted = true;
+ if (buf[read++]==(byte)'\n') {
+ System.out.println();
+ return read;
+ }
+ }
+ } catch (IOException e) {
+ log("IOException from readOneLine");
+ e.printStackTrace();
+ }
+ return read;
+ }
+
+ /**
+ * Read a chunk of data
+ * @param is Stream from which to read data
+ * @param length Amount of data to read
+ * @return number of bytes read
+ */
+ private int readData(InputStream is, int length) {
+ int read = 0;
+ int count;
+ // At the moment we're only expecting small data amounts
+ byte[] buf = new byte[length];
+
+ try {
+ while (is.available() > 0) {
+ count = is.read(buf, read, length-read);
+ read += count;
+ }
+ } catch (IOException e) {
+ log("IOException from readData");
+ e.printStackTrace();
+ }
+ return read;
+ }
+
+ /**
+ * Read the status line from the input stream extracting method
+ * information.
+ * @param is Inputstream to read
+ * @return number of bytes read
+ */
+ private int parseStatusLine(InputStream is) {
+ int index;
+ int nread = 0;
+
+ log("Parse status line");
+ // Check for status line first
+ nread = readOneLine(is);
+ // Bomb out if stream closes prematurely
+ if (nread == -1) {
+ requestMethod = UNKNOWN_METHOD;
+ return -1;
+ }
+
+ if (buf[0] == (byte)'G' &&
+ buf[1] == (byte)'E' &&
+ buf[2] == (byte)'T' &&
+ buf[3] == (byte)' ') {
+ requestMethod = GET_METHOD;
+ log("GET request");
+ index = 4;
+ } else if (buf[0] == (byte)'H' &&
+ buf[1] == (byte)'E' &&
+ buf[2] == (byte)'A' &&
+ buf[3] == (byte)'D' &&
+ buf[4] == (byte)' ') {
+ requestMethod = HEAD_METHOD;
+ log("HEAD request");
+ index = 5;
+ } else if (buf[0] == (byte)'P' &&
+ buf[1] == (byte)'O' &&
+ buf[2] == (byte)'S' &&
+ buf[3] == (byte)'T' &&
+ buf[4] == (byte)' ') {
+ requestMethod = POST_METHOD;
+ log("POST request");
+ index = 5;
+ } else {
+ // Unhandled request
+ requestMethod = UNKNOWN_METHOD;
+ return -1;
+ }
+
+ // A valid method we understand
+ if (requestMethod > UNKNOWN_METHOD) {
+ // Read file name
+ int i = index;
+ while (buf[i] != (byte)' ') {
+ // There should be HTTP/1.x at the end
+ if ((buf[i] == (byte)'\n') || (buf[i] == (byte)'\r')) {
+ requestMethod = UNKNOWN_METHOD;
+ return -1;
+ }
+ i++;
+ }
+
+ testID = new String(buf, 0, index, i-index);
+ if (testID.startsWith("/")) {
+ testID = testID.substring(1);
+ }
+
+ return nread;
+ }
+ return -1;
+ }
+
+ /**
+ * Read a header from the input stream
+ * @param is Inputstream to read
+ * @return number of bytes read
+ */
+ private int parseHeader(InputStream is) {
+ int index = 0;
+ int nread = 0;
+ log("Parse a header");
+ // Check for status line first
+ nread = readOneLine(is);
+ // Bomb out if stream closes prematurely
+ if (nread == -1) {
+ requestMethod = UNKNOWN_METHOD;
+ return -1;
+ }
+ // Read header entry 'Header: data'
+ int i = index;
+ while (buf[i] != (byte)':') {
+ // There should be an entry after the header
+
+ if ((buf[i] == (byte)'\n') || (buf[i] == (byte)'\r')) {
+ return UNKNOWN_METHOD;
+ }
+ i++;
+ }
+
+ String headerName = new String(buf, 0, i);
+ i++; // Over ':'
+ while (buf[i] == ' ') {
+ i++;
+ }
+ String headerValue = new String(buf, i, nread-1);
+
+ headers.put(headerName, headerValue);
+ return nread;
+ }
+
+ /**
+ * Read all headers from the input stream
+ * @param is Inputstream to read
+ * @return number of bytes read
+ */
+ private int readHeaders(InputStream is) {
+ int nread = 0;
+ log("Read headers");
+ // Headers should be terminated by empty CRLF line
+ while (true) {
+ int headerLen = 0;
+ headerLen = parseHeader(is);
+ if (headerLen == -1)
+ return -1;
+ nread += headerLen;
+ if (headerLen <= 2) {
+ return nread;
+ }
+ }
+ }
+
+ /**
+ * Read content data from the input stream
+ * @param is Inputstream to read
+ * @return number of bytes read
+ */
+ private int readContent(InputStream is) {
+ int nread = 0;
+ log("Read content");
+ String lengthString = headers.get(requestHeaders[REQ_CONTENT_LENGTH]);
+ int length = new Integer(lengthString).intValue();
+
+ // Read content
+ length = readData(is, length);
+ return length;
+ }
+
+ /**
+ * The main loop, reading requests.
+ */
+ void handleClient() throws IOException {
+ InputStream is = new BufferedInputStream(s.getInputStream());
+ PrintStream ps = new PrintStream(s.getOutputStream());
+ int nread = 0;
+
+ /* we will only block in read for this many milliseconds
+ * before we fail with java.io.InterruptedIOException,
+ * at which point we will abandon the connection.
+ */
+ s.setSoTimeout(mTimeout);
+ s.setTcpNoDelay(true);
+
+ do {
+ nread = parseStatusLine(is);
+ if (requestMethod != UNKNOWN_METHOD) {
+
+ // If status line found, read any headers
+ nread = readHeaders(is);
+
+ // Then read content (if any)
+ // TODO handle chunked encoding from the client
+ if (headers.get(requestHeaders[REQ_CONTENT_LENGTH]) != null) {
+ nread = readContent(is);
+ }
+ } else {
+ if (nread > 0) {
+ /* we don't support this method */
+ ps.print(HTTP_VERSION_STRING + " " + HTTP_BAD_METHOD +
+ " unsupported method type: ");
+ ps.write(buf, 0, 5);
+ ps.write(EOL);
+ ps.flush();
+ } else {
+ }
+ if (!keepAlive || nread <= 0) {
+ headers.clear();
+ readStarted = false;
+
+ log("SOCKET CLOSED");
+ s.close();
+ return;
+ }
+ }
+
+ // Reset test number prior to outputing data
+ testNum = -1;
+
+ // Write out the data
+ printStatus(ps);
+ printHeaders(ps);
+
+ // Write line between headers and body
+ psWriteEOL(ps);
+
+ // Write the body
+ if (redirectCode == -1) {
+ switch (requestMethod) {
+ case GET_METHOD:
+ if ((testNum < 0) || (testNum > TestWebData.tests.length - 1)) {
+ send404(ps);
+ } else {
+ sendFile(ps);
+ }
+ break;
+ case HEAD_METHOD:
+ // Nothing to do
+ break;
+ case POST_METHOD:
+ // Post method write body data
+ if ((testNum > 0) || (testNum < TestWebData.tests.length - 1)) {
+ sendFile(ps);
+ }
+
+ break;
+ default:
+ break;
+ }
+ } else { // Redirecting
+ switch (redirectCode) {
+ case 301:
+ // Seems 301 needs a body by neon (although spec
+ // says SHOULD).
+ psPrint(ps, TestWebData.testServerResponse[TestWebData.REDIRECT_301]);
+ break;
+ case 302:
+ //
+ psPrint(ps, TestWebData.testServerResponse[TestWebData.REDIRECT_302]);
+ break;
+ case 303:
+ psPrint(ps, TestWebData.testServerResponse[TestWebData.REDIRECT_303]);
+ break;
+ case 307:
+ psPrint(ps, TestWebData.testServerResponse[TestWebData.REDIRECT_307]);
+ break;
+ default:
+ break;
+ }
+ }
+
+ ps.flush();
+
+ // Reset for next request
+ readStarted = false;
+ headers.clear();
+
+ } while (keepAlive);
+
+ log("SOCKET CLOSED");
+ s.close();
+ }
+
+ // Print string to log and output stream
+ void psPrint(PrintStream ps, String s) throws IOException {
+ log(s);
+ ps.print(s);
+ }
+
+ // Print bytes to log and output stream
+ void psWrite(PrintStream ps, byte[] bytes, int len) throws IOException {
+ log(new String(bytes));
+ ps.write(bytes, 0, len);
+ }
+
+ // Print CRLF to log and output stream
+ void psWriteEOL(PrintStream ps) throws IOException {
+ log("CRLF");
+ ps.write(EOL);
+ }
+
+
+ // Print status to log and output stream
+ void printStatus(PrintStream ps) throws IOException {
+ // Handle redirects first.
+ if (redirectCode != -1) {
+ log("REDIRECTING TO "+redirectHost+" status "+redirectCode);
+ psPrint(ps, HTTP_VERSION_STRING + " " + redirectCode +" Moved permanently");
+ psWriteEOL(ps);
+ psPrint(ps, "Location: " + redirectHost);
+ psWriteEOL(ps);
+ return;
+ }
+
+
+ if (testID.startsWith("test")) {
+ testNum = Integer.valueOf(testID.substring(4))-1;
+ }
+
+ if ((testNum < 0) || (testNum > TestWebData.tests.length - 1)) {
+ psPrint(ps, HTTP_VERSION_STRING + " " + HTTP_NOT_FOUND + " not found");
+ psWriteEOL(ps);
+ } else {
+ psPrint(ps, HTTP_VERSION_STRING + " " + HTTP_OK+" OK");
+ psWriteEOL(ps);
+ }
+
+ log("Status sent");
+ }
+ /**
+ * Create the server response and output to the stream
+ * @param ps The PrintStream to output response headers and data to
+ */
+ void printHeaders(PrintStream ps) throws IOException {
+ psPrint(ps,"Server: TestWebServer"+mPort);
+ psWriteEOL(ps);
+ psPrint(ps, "Date: " + (new Date()));
+ psWriteEOL(ps);
+ psPrint(ps, "Connection: " + ((keepAlive) ? "Keep-Alive" : "Close"));
+ psWriteEOL(ps);
+
+ // Yuk, if we're not redirecting, we add the file details
+ if (redirectCode == -1) {
+
+ if (!TestWebData.testParams[testNum].testDir) {
+ if (chunked) {
+ psPrint(ps, "Transfer-Encoding: chunked");
+ } else {
+ psPrint(ps, "Content-length: "+TestWebData.testParams[testNum].testLength);
+ }
+ psWriteEOL(ps);
+
+ psPrint(ps,"Last Modified: " + (new
+ Date(TestWebData.testParams[testNum].testLastModified)));
+ psWriteEOL(ps);
+
+ psPrint(ps, "Content-type: " + TestWebData.testParams[testNum].testType);
+ psWriteEOL(ps);
+ } else {
+ psPrint(ps, "Content-type: text/html");
+ psWriteEOL(ps);
+ }
+ } else {
+ // Content-length of 301, 302, 303, 307 are the same.
+ psPrint(ps, "Content-length: "+(TestWebData.testServerResponse[TestWebData.REDIRECT_301]).length());
+ psWriteEOL(ps);
+ psWriteEOL(ps);
+ }
+ log("Headers sent");
+
+ }
+
+ /**
+ * Sends the 404 not found message
+ * @param ps The PrintStream to write to
+ */
+ void send404(PrintStream ps) throws IOException {
+ ps.println("Not Found\n\n"+
+ "The requested resource was not found.\n");
+ }
+
+ /**
+ * Sends the data associated with the headers
+ * @param ps The PrintStream to write to
+ */
+ void sendFile(PrintStream ps) throws IOException {
+ // For now just make a chunk with the whole of the test data
+ // It might be worth making this multiple chunks for large
+ // test data to test multiple chunks.
+ int dataSize = TestWebData.tests[testNum].length;
+ if (chunked) {
+ psPrint(ps, Integer.toHexString(dataSize));
+ psWriteEOL(ps);
+ psWrite(ps, TestWebData.tests[testNum], dataSize);
+ psWriteEOL(ps);
+ psPrint(ps, "0");
+ psWriteEOL(ps);
+ psWriteEOL(ps);
+ } else {
+ psWrite(ps, TestWebData.tests[testNum], dataSize);
+ }
+ }
+ }
+}
diff --git a/tests/CoreTests/android/core/TreeMapTest.java b/tests/CoreTests/android/core/TreeMapTest.java
new file mode 100644
index 0000000..229d86d
--- /dev/null
+++ b/tests/CoreTests/android/core/TreeMapTest.java
@@ -0,0 +1,105 @@
+/*
+ * 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 android.core;
+
+import junit.framework.TestCase;
+
+import java.util.HashMap;
+import java.util.Random;
+import java.util.TreeMap;
+import android.test.suitebuilder.annotation.LargeTest;
+
+/**
+ * Tests for basic functinality of TreeMaps
+ */
+public class TreeMapTest extends TestCase {
+
+ private Random mRandom = new Random(1);
+
+ private static final boolean SPEW = false;
+
+ @LargeTest
+ public void testTreeMap() {
+ for (int i = 0; i < 10; i++) {
+ if (SPEW) System.out.println("Running doTest cycle #" + (i + 1));
+ doTest();
+ }
+ }
+
+ private void doTest() {
+ TreeMap<Integer, String> tm = new TreeMap<Integer, String>();
+ HashMap<Integer, String> hm = new HashMap<Integer, String>();
+
+ int minVal = Integer.MAX_VALUE;
+ int maxVal = Integer.MIN_VALUE;
+
+ for (int i = 0; i < 100; i++) {
+ int val = mRandom.nextInt(1000);
+ if (SPEW) System.out.println("Adding val = " + val);
+ if (val < minVal) {
+ minVal = val;
+ }
+ if (val > maxVal) {
+ maxVal = val;
+ }
+ tm.put(new Integer(val), "V:" + val);
+ hm.put(new Integer(val), "V:" + val);
+
+ if (SPEW) System.out.println("tm = " + tm);
+
+ if (SPEW) System.out.println("tm.size() = " + tm.size());
+ if (SPEW) System.out.println("hm.size() = " + hm.size());
+ assertEquals(tm.size(), hm.size());
+
+ if (SPEW) System.out.println("tm.firstKey() = " + tm.firstKey());
+ if (SPEW) System.out.println("minVal = " + minVal);
+ if (SPEW) System.out.println("tm.lastKey() = " + tm.lastKey());
+ if (SPEW) System.out.println("maxVal = " + maxVal);
+ assertEquals(minVal, tm.firstKey().intValue());
+ assertEquals(maxVal, tm.lastKey().intValue());
+ }
+
+ // Check for equality
+ for (int val = 0; val < 1000; val++) {
+ Integer vv = new Integer(val);
+ String tms = tm.get(vv);
+ String hms = hm.get(vv);
+ assertEquals(tms, hms);
+ }
+
+ for (int i = 0; i < 1000; i++) {
+ int val = mRandom.nextInt(1000);
+ if (SPEW) System.out.println("Removing val = " + val);
+
+ String tms = tm.remove(new Integer(val));
+ String hms = hm.remove(new Integer(val));
+
+ if (SPEW) System.out.println("tm = " + tm);
+
+ assertEquals(tm.size(), hm.size());
+ assertEquals(tms, hms);
+ }
+
+ // Check for equality
+ for (int val = 0; val < 1000; val++) {
+ Integer vv = new Integer(val);
+ String tms = tm.get(vv);
+ String hms = hm.get(vv);
+ assertEquals(tms, hms);
+ }
+ }
+}
diff --git a/tests/CoreTests/android/core/URITest.java b/tests/CoreTests/android/core/URITest.java
new file mode 100644
index 0000000..3b821d8
--- /dev/null
+++ b/tests/CoreTests/android/core/URITest.java
@@ -0,0 +1,55 @@
+/*
+ * 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 android.core;
+
+import junit.framework.TestCase;
+
+import java.net.URI;
+import java.net.URISyntaxException;
+import android.test.suitebuilder.annotation.SmallTest;
+
+public class URITest extends TestCase {
+
+ @SmallTest
+ public void testConstruct() throws Exception {
+ construct("http://www.google.com/this/is-the/path?query#fragment",
+ "www.google.com", "/this/is-the/path", true);
+ }
+
+ private static void construct(String str, String host, String path, boolean absolute)
+ throws URISyntaxException {
+ URI uri = new URI(str);
+ assertEquals(host, uri.getHost());
+ assertEquals(path, uri.getPath());
+ assertEquals(absolute, uri.isAbsolute());
+ }
+
+ @SmallTest
+ public void testResolve() throws Exception {
+ resolve("http://www.google.com/your",
+ "mom",
+ "http://www.google.com/mom");
+ }
+
+ private static void resolve(String base, String uri, String expected) {
+ URI b = URI.create(base);
+ URI resolved = b.resolve(uri);
+// System.out.println("base=" + base + " uri=" + uri
+// + " resolved=" + resolved);
+ assertEquals(expected, resolved.toString());
+ }
+}
diff --git a/tests/CoreTests/android/core/URLTest.java b/tests/CoreTests/android/core/URLTest.java
new file mode 100644
index 0000000..56f9f7b
--- /dev/null
+++ b/tests/CoreTests/android/core/URLTest.java
@@ -0,0 +1,200 @@
+/*
+ * 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 android.core;
+
+import junit.framework.TestCase;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.OutputStream;
+import java.io.PrintWriter;
+import java.net.HttpURLConnection;
+import java.net.ServerSocket;
+import java.net.Socket;
+import java.net.URL;
+import java.net.URLConnection;
+
+import android.test.suitebuilder.annotation.Suppress;
+
+@Suppress
+public class URLTest extends TestCase {
+
+ private static void get(String u) throws IOException {
+ URL url = new URL(u);
+ URLConnection cn = url.openConnection();
+ cn.connect();
+// System.out.println("Content-Type: " + cn.getContentType());
+// System.out.println("Content-Length: " + cn.getContentLength());
+
+ InputStream stream = cn.getInputStream();
+ if (stream == null) {
+ throw new RuntimeException("stream is null");
+ }
+ byte[] data = new byte[1024];
+ stream.read(data);
+
+// if (true) {
+// System.out.print("data=");
+// System.out.write(data);
+// System.out.println();
+// }
+
+// System.out.println("Content-Type: " + cn.getContentType());
+// System.out.print("data:");
+// System.out.write(data);
+// System.out.println();
+
+ assertTrue(new String(data).indexOf("<html>") >= 0);
+ }
+
+ public void testGetHTTP() throws Exception {
+ get("http://www.google.com");
+ }
+
+ public void testGetHTTPS() throws Exception {
+ get("https://www.fortify.net/cgi/ssl_2.pl");
+ }
+
+ /**
+ * Dummy HTTP server class for testing keep-alive behavior. Listens a
+ * single time and responds to a given number of requests on the same
+ * socket. Then closes the socket.
+ */
+ private static class DummyServer implements Runnable {
+
+ private int keepAliveCount;
+
+ public DummyServer(int keepAliveCount) {
+ this.keepAliveCount = keepAliveCount;
+ }
+
+ public void run() {
+ try {
+ ServerSocket server = new ServerSocket(8182);
+ Socket socket = server.accept();
+
+ InputStream input = socket.getInputStream();
+ BufferedReader reader = new BufferedReader(new InputStreamReader(input));
+ try {
+ for (int i = 0; i < keepAliveCount; i++) {
+ String header = reader.readLine();
+ while (header != null && header.length() != 0) {
+ header = reader.readLine();
+ }
+
+ OutputStream output = socket.getOutputStream();
+ PrintWriter writer = new PrintWriter(output);
+
+ try {
+ writer.println("HTTP/1.1 200 OK");
+ String body = "Hello, Android world #" + i + "!";
+ writer.println("Content-Length: " + body.length());
+ writer.println("");
+ writer.print(body);
+ writer.flush();
+ } finally {
+ writer.close();
+ }
+ }
+ } finally {
+ reader.close();
+ }
+ socket.close();
+ server.close();
+ } catch (Exception ex) {
+ throw new RuntimeException(ex);
+ }
+ }
+ }
+
+ /**
+ * Does a request to the given URL, reads and returns the result.
+ */
+ private String request(URL url) throws Exception {
+ URLConnection connection = url.openConnection();
+ connection.connect();
+
+ InputStream input = connection.getInputStream();
+ BufferedReader reader = new BufferedReader(new InputStreamReader(input));
+ try {
+ return reader.readLine();
+ } finally {
+ reader.close();
+ }
+ }
+
+ /**
+ * Test case for HTTP keep-alive behavior.
+ */
+ public void testGetKeepAlive() throws Exception {
+ new Thread(new DummyServer(3)).start();
+ Thread.sleep(100);
+
+ // We expect the request to work three times, then it fails.
+ URL url = new URL("http://localhost:8182");
+ assertEquals("Hello, Android world #0!", request(url));
+ assertEquals("Hello, Android world #1!", request(url));
+ assertEquals("Hello, Android world #2!", request(url));
+
+ try {
+ request(url);
+ fail("ConnectException expected.");
+ } catch (Exception ex) {
+ // Ok.
+ }
+ }
+
+ /**
+ * Regression for issue 1001814.
+ */
+ public void testHttpConnectionTimeout() throws Exception {
+ int timeout = 5000;
+ HttpURLConnection cn = null;
+ long start = 0;
+ try {
+ start = System.currentTimeMillis();
+ URL url = new URL("http://123.123.123.123");
+ cn = (HttpURLConnection) url.openConnection();
+ cn.setConnectTimeout(5000);
+ cn.connect();
+ fail("should have thrown an exception");
+ } catch (IOException ioe) {
+ long delay = System.currentTimeMillis() - start;
+ if (Math.abs(timeout - delay) > 1000) {
+ fail("Timeout was not accurate. it needed " + delay +
+ " instead of " + timeout + "miliseconds");
+ }
+ } finally {
+ if (cn != null) {
+ cn.disconnect();
+ }
+ }
+ }
+
+ /**
+ * Regression test for issue 1158780 where using '{' and '}' in an URL threw
+ * an NPE. The RI accepts this URL and returns the status 404.
+ */
+ public void testMalformedUrl() throws Exception {
+ URL url = new URL("http://www.google.com/cgi-bin/myscript?g={United+States}+Borders+Mexico+{Climate+change}+Marketing+{Automotive+industry}+News+Health+Internet");
+ HttpURLConnection conn = (HttpURLConnection)url.openConnection();
+ int status = conn.getResponseCode();
+ android.util.Log.d("URLTest", "status: " + status);
+ }
+}
diff --git a/tests/CoreTests/android/core/ZipFileTest.java b/tests/CoreTests/android/core/ZipFileTest.java
new file mode 100644
index 0000000..04b476b
--- /dev/null
+++ b/tests/CoreTests/android/core/ZipFileTest.java
@@ -0,0 +1,200 @@
+/*
+ * 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 android.core;
+
+import junit.framework.TestCase;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.Enumeration;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipFile;
+import java.util.zip.ZipOutputStream;
+import android.test.suitebuilder.annotation.MediumTest;
+
+
+/**
+ * Basic tests for ZipFile.
+ */
+public class ZipFileTest extends TestCase {
+ private static final int SAMPLE_SIZE = 128 * 1024;
+
+ @MediumTest
+ public void testZipFile() throws Exception {
+
+ File file = File.createTempFile("ZipFileTest", ".zip");
+ try {
+ // create a test file; assume it's not going to collide w/anything
+ FileOutputStream outStream = new FileOutputStream(file);
+ createCompressedZip(outStream);
+// System.out.println("CREATED " + file);
+
+ scanZip(file.getPath());
+ read2(file.getPath());
+ } finally {
+ file.delete();
+ }
+ }
+
+ /*
+ * stepStep == 0 --> >99% compression
+ * stepStep == 1 --> ~30% compression
+ * stepStep == 2 --> no compression
+ */
+ static byte[] makeSampleFile(int stepStep) throws IOException {
+ byte[] sample = new byte[SAMPLE_SIZE];
+ byte val, step;
+ int i, j, offset;
+
+ val = 0;
+ step = 1;
+ offset = 0;
+ for (i = 0; i < SAMPLE_SIZE / 256; i++) {
+ for (j = 0; j < 256; j++) {
+ sample[offset++] = val;
+ val += step;
+ }
+
+ step += stepStep;
+ }
+
+ return sample;
+ }
+
+ static void createCompressedZip(OutputStream bytesOut) throws IOException {
+ ZipOutputStream out = new ZipOutputStream(bytesOut);
+ try {
+ int i;
+
+ for (i = 0; i < 3; i++) {
+ byte[] input = makeSampleFile(i);
+ ZipEntry newEntry = new ZipEntry("file-" + i);
+
+ if (i != 1) {
+ newEntry.setComment("this is file " + i);
+ }
+ out.putNextEntry(newEntry);
+ out.write(input, 0, input.length);
+ out.closeEntry();
+ }
+
+ out.setComment("This is a lovely compressed archive!");
+ } finally {
+ out.close();
+ }
+ }
+
+ static void scanZip(String fileName) throws IOException {
+ ZipFile zipFile = new ZipFile(fileName);
+ Enumeration fileList;
+ int idx = 0;
+
+// System.out.println("Contents of " + zipFile + ":");
+ for (fileList = zipFile.entries(); fileList.hasMoreElements();) {
+ ZipEntry entry = (ZipEntry) fileList.nextElement();
+// System.out.println(" " + entry.getName());
+ assertEquals(entry.getName(), "file-" + idx);
+ idx++;
+ }
+
+ zipFile.close();
+ }
+
+ /*
+ * Read compressed data from two different entries at the same time,
+ * to verify that the streams aren't getting confused. If we do
+ * something wrong, the inflater will choke and throw a ZipException.
+ *
+ * This doesn't test synchronization in multi-threaded use.
+ */
+ static void read2(String fileName) throws IOException {
+ ZipFile zipFile;
+ ZipEntry entry1, entry2;
+ byte buf[] = new byte[16384];
+ InputStream stream1, stream2;
+ int len, totalLen1, totalLen2;
+
+ /* use file-1 and file-2 because the compressed data is large */
+ zipFile = new ZipFile(fileName);
+ entry1 = zipFile.getEntry("file-1");
+ entry2 = zipFile.getEntry("file-2");
+
+ /* make sure we got the right thing */
+ assertEquals("file-1", entry1.getName());
+ assertEquals("file-2", entry2.getName());
+
+ /* create streams */
+ stream1 = zipFile.getInputStream(entry1);
+ stream2 = zipFile.getInputStream(entry2);
+
+ /*
+ * Read a piece of file #1.
+ */
+ totalLen1 = stream1.read(buf);
+ assertTrue("initial read failed on #1", totalLen1 >= 0);
+
+ /*
+ * Read a piece of file #2.
+ */
+ totalLen2 = stream2.read(buf);
+ assertTrue("initial read failed on #2", totalLen2 >= 0);
+
+ /*
+ * Read the rest of file #1, and close the stream.
+ *
+ * If our streams are crossed up, we'll fail here.
+ */
+ while ((len = stream1.read(buf)) > 0) {
+ totalLen1 += len;
+ }
+ assertEquals(SAMPLE_SIZE, totalLen1);
+ stream1.close();
+
+ /*
+ * Read the rest of file #2, and close the stream.
+ */
+ while ((len = stream2.read(buf)) > 0) {
+ totalLen2 += len;
+ }
+ assertEquals(SAMPLE_SIZE, totalLen2);
+ stream2.close();
+
+ /*
+ * Open a new one.
+ */
+ stream1 = zipFile.getInputStream(zipFile.getEntry("file-0"));
+
+ /*
+ * Close the ZipFile. According to the RI, none if its InputStreams can
+ * be read after this point.
+ */
+ zipFile.close();
+
+ Exception error = null;
+ try {
+ stream1.read(buf);
+ } catch (Exception ex) {
+ error = ex;
+ }
+
+ assertNotNull("ZipFile shouldn't allow reading of closed files.", error);
+ }
+}
+
diff --git a/tests/CoreTests/android/core/ZipStreamTest.java b/tests/CoreTests/android/core/ZipStreamTest.java
new file mode 100644
index 0000000..74cfe82
--- /dev/null
+++ b/tests/CoreTests/android/core/ZipStreamTest.java
@@ -0,0 +1,171 @@
+/*
+ * 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 android.core;
+
+import junit.framework.TestCase;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipInputStream;
+import java.util.zip.ZipOutputStream;
+import android.test.suitebuilder.annotation.LargeTest;
+
+/**
+ * Basic tests for ZipStream
+ */
+public class ZipStreamTest extends TestCase {
+
+ @LargeTest
+ public void testZipStream() throws Exception {
+ ByteArrayOutputStream bytesOut = new ByteArrayOutputStream();
+ createCompressedZip(bytesOut);
+
+ byte[] zipData = bytesOut.toByteArray();
+
+ /*
+ FileOutputStream outFile = new FileOutputStream("/tmp/foo.zip");
+ outFile.write(zipData, 0, zipData.length);
+ outFile.close();
+ */
+
+ /*
+ FileInputStream inFile = new FileInputStream("/tmp/foo.zip");
+ int inputLength = inFile.available();
+ zipData = new byte[inputLength];
+ if (inFile.read(zipData) != inputLength)
+ throw new RuntimeException();
+ inFile.close();
+ */
+
+ ByteArrayInputStream bytesIn = new ByteArrayInputStream(zipData);
+ scanZip(bytesIn);
+
+ bytesOut = new ByteArrayOutputStream();
+ createUncompressedZip(bytesOut);
+
+ zipData = bytesOut.toByteArray();
+
+ bytesIn = new ByteArrayInputStream(zipData);
+ scanZip(bytesIn);
+ }
+
+ /*
+ * stepStep == 0 --> >99% compression
+ * stepStep == 1 --> ~30% compression
+ * stepStep == 2 --> no compression
+ */
+ private static byte[] makeSampleFile(int stepStep) throws IOException {
+ byte[] sample = new byte[128 * 1024];
+ byte val, step;
+ int i, j, offset;
+
+ val = 0;
+ step = 1;
+ offset = 0;
+ for (i = 0; i < (128 * 1024) / 256; i++) {
+ for (j = 0; j < 256; j++) {
+ sample[offset++] = val;
+ val += step;
+ }
+
+ step += stepStep;
+ }
+
+ return sample;
+ }
+
+ private static void createCompressedZip(ByteArrayOutputStream bytesOut) throws IOException {
+ ZipOutputStream out = new ZipOutputStream(bytesOut);
+ try {
+ int i;
+
+ for (i = 0; i < 3; i++) {
+ byte[] input = makeSampleFile(i);
+ ZipEntry newEntry = new ZipEntry("file-" + i);
+
+ if (i != 1)
+ newEntry.setComment("this is file " + i);
+ out.putNextEntry(newEntry);
+ out.write(input, 0, input.length);
+ out.closeEntry();
+ }
+
+ out.setComment("This is a lovely compressed archive!");
+ } finally {
+ out.close();
+ }
+ }
+
+ private static void createUncompressedZip(ByteArrayOutputStream bytesOut) throws IOException {
+ ZipOutputStream out = new ZipOutputStream(bytesOut);
+ try {
+ long[] crcs = {0x205fbff3, 0x906fae57L, 0x2c235131};
+ int i;
+
+ for (i = 0; i < 3; i++) {
+ byte[] input = makeSampleFile(i);
+ ZipEntry newEntry = new ZipEntry("file-" + i);
+
+ if (i != 1)
+ newEntry.setComment("this is file " + i);
+ newEntry.setMethod(ZipEntry.STORED);
+ newEntry.setSize(128 * 1024);
+ newEntry.setCrc(crcs[i]);
+ out.putNextEntry(newEntry);
+ out.write(input, 0, input.length);
+ out.closeEntry();
+ }
+
+ out.setComment("This is a lovely, but uncompressed, archive!");
+ } finally {
+ out.close();
+ }
+ }
+
+ private static void scanZip(ByteArrayInputStream bytesIn) throws IOException {
+ ZipInputStream in = new ZipInputStream(bytesIn);
+ try {
+ int i;
+
+ for (i = 0; i < 3; i++) {
+ ZipEntry entry = in.getNextEntry();
+ ByteArrayOutputStream contents = new ByteArrayOutputStream();
+ byte[] buf = new byte[4096];
+ int len, totalLen = 0;
+
+ while ((len = in.read(buf)) > 0) {
+ contents.write(buf, 0, len);
+ totalLen += len;
+ }
+
+ assertEquals(128 * 1024, totalLen);
+
+// System.out.println("ZipStreamTest: name='" + entry.getName()
+// + "', zero=" + contents.toByteArray()[0]
+// + ", tfs=" + contents.toByteArray()[257]
+// + ", crc=" + Long.toHexString(entry.getCrc()));
+ }
+
+ assertNull("should only be three entries", in.getNextEntry());
+ } finally {
+ in.close();
+ }
+ }
+}
+
diff --git a/tests/CoreTests/android/database/MatrixCursorTest.java b/tests/CoreTests/android/database/MatrixCursorTest.java
new file mode 100644
index 0000000..fb8a12f
--- /dev/null
+++ b/tests/CoreTests/android/database/MatrixCursorTest.java
@@ -0,0 +1,146 @@
+/*
+ * Copyright (C) 2007 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 android.database;
+
+import junit.framework.TestCase;
+
+import java.util.*;
+
+public class MatrixCursorTest extends TestCase {
+
+ public void testEmptyCursor() {
+ Cursor cursor = new MatrixCursor(new String[] { "a" });
+ assertEquals(0, cursor.getCount());
+ }
+
+ public void testNullValue() {
+ MatrixCursor cursor = new MatrixCursor(new String[] { "a" });
+ cursor.newRow().add(null);
+ cursor.moveToNext();
+ assertTrue(cursor.isNull(0));
+ }
+
+ public void testMatrixCursor() {
+ MatrixCursor cursor = newMatrixCursor();
+
+ cursor.newRow()
+ .add("a")
+ .add(1)
+ .add(2)
+ .add(3)
+ .add(4)
+ .add(5);
+
+ cursor.moveToNext();
+
+ checkValues(cursor);
+
+ cursor.newRow()
+ .add("a")
+ .add("1")
+ .add("2")
+ .add("3")
+ .add("4")
+ .add("5");
+
+ cursor.moveToNext();
+ checkValues(cursor);
+
+ cursor.moveToPrevious();
+ checkValues(cursor);
+ }
+
+ public void testAddArray() {
+ MatrixCursor cursor = newMatrixCursor();
+
+ cursor.addRow(new Object[] { "a", 1, 2, 3, 4, 5 });
+ cursor.moveToNext();
+ checkValues(cursor);
+
+ try {
+ cursor.addRow(new Object[0]);
+ fail();
+ } catch (IllegalArgumentException e) { /* expected */ }
+ }
+
+ public void testAddIterable() {
+ MatrixCursor cursor = newMatrixCursor();
+
+ cursor.addRow(Arrays.asList("a", 1, 2, 3, 4, 5));
+ cursor.moveToNext();
+ checkValues(cursor);
+
+ try {
+ cursor.addRow(Collections.emptyList());
+ fail();
+ } catch (IllegalArgumentException e) { /* expected */ }
+
+ try {
+ cursor.addRow(Arrays.asList("a", 1, 2, 3, 4, 5, "Too many!"));
+ fail();
+ } catch (IllegalArgumentException e) { /* expected */ }
+ }
+
+ public void testAddArrayList() {
+ MatrixCursor cursor = newMatrixCursor();
+
+ cursor.addRow(new NonIterableArrayList<Object>(
+ Arrays.asList("a", 1, 2, 3, 4, 5)));
+ cursor.moveToNext();
+ checkValues(cursor);
+
+ try {
+ cursor.addRow(new NonIterableArrayList<Object>());
+ fail();
+ } catch (IllegalArgumentException e) { /* expected */ }
+
+ try {
+ cursor.addRow(new NonIterableArrayList<Object>(
+ Arrays.asList("a", 1, 2, 3, 4, 5, "Too many!")));
+ fail();
+ } catch (IllegalArgumentException e) { /* expected */ }
+ }
+
+ static class NonIterableArrayList<T> extends ArrayList<T> {
+
+ NonIterableArrayList() {}
+
+ NonIterableArrayList(Collection<? extends T> ts) {
+ super(ts);
+ }
+
+ @Override
+ public Iterator<T> iterator() {
+ throw new AssertionError();
+ }
+ }
+
+ private MatrixCursor newMatrixCursor() {
+ return new MatrixCursor(new String[] {
+ "string", "short", "int", "long", "float", "double" });
+ }
+
+ private void checkValues(MatrixCursor cursor) {
+ assertEquals("a", cursor.getString(0));
+ assertEquals(1, cursor.getShort(1));
+ assertEquals(2, cursor.getInt(2));
+ assertEquals(3, cursor.getLong(3));
+ assertEquals(4.0f, cursor.getFloat(4));
+ assertEquals(5.0D, cursor.getDouble(5));
+ }
+
+}
diff --git a/tests/CoreTests/android/graphics/ColorStateListTest.java b/tests/CoreTests/android/graphics/ColorStateListTest.java
new file mode 100644
index 0000000..68c2fc1
--- /dev/null
+++ b/tests/CoreTests/android/graphics/ColorStateListTest.java
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2007 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 android.graphics;
+
+import android.content.res.Resources;
+import android.content.res.ColorStateList;
+import android.test.AndroidTestCase;
+import android.core.R;
+import android.test.suitebuilder.annotation.SmallTest;
+
+/**
+ * Tests of {@link android.graphics.ColorStateList}
+ */
+
+public class ColorStateListTest extends AndroidTestCase {
+
+ private Resources mResources;
+ private int mFailureColor;
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ mResources = mContext.getResources();
+ mFailureColor = mResources.getColor(R.color.failColor);
+ }
+
+ @SmallTest
+ public void testStateIsInList() throws Exception {
+ ColorStateList colorStateList = mResources.getColorStateList(R.color.color1);
+ int[] focusedState = {android.R.attr.state_focused};
+ int focusColor = colorStateList.getColorForState(focusedState, R.color.failColor);
+ assertEquals(mResources.getColor(R.color.testcolor1), focusColor);
+ }
+
+ @SmallTest
+ public void testEmptyState() throws Exception {
+ ColorStateList colorStateList = mResources.getColorStateList(R.color.color1);
+ int[] emptyState = {};
+ int defaultColor = colorStateList.getColorForState(emptyState, mFailureColor);
+ assertEquals(mResources.getColor(R.color.testcolor2), defaultColor);
+ }
+
+ @SmallTest
+ public void testGetColor() throws Exception {
+ int defaultColor = mResources.getColor(R.color.color1);
+ assertEquals(mResources.getColor(R.color.testcolor2), defaultColor);
+ }
+
+ @SmallTest
+ public void testGetColorWhenListHasNoDefault() throws Exception {
+ int defaultColor = mResources.getColor(R.color.color_no_default);
+ assertEquals(mResources.getColor(R.color.testcolor1), defaultColor);
+ }
+}
diff --git a/tests/CoreTests/android/graphics/drawable/StateListDrawableTest.java b/tests/CoreTests/android/graphics/drawable/StateListDrawableTest.java
new file mode 100644
index 0000000..0d9f72e
--- /dev/null
+++ b/tests/CoreTests/android/graphics/drawable/StateListDrawableTest.java
@@ -0,0 +1,98 @@
+/*
+ * Copyright (C) 2007 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 android.graphics.drawable;
+
+import junit.framework.TestCase;
+
+import android.R;
+import android.graphics.Canvas;
+import android.graphics.ColorFilter;
+import android.util.StateSet;
+import android.view.MockView;
+
+/**
+ * Tests for StateListDrawable
+ *
+ */
+
+public class StateListDrawableTest extends TestCase {
+
+ private StateListDrawable slDrawable;
+ private MockDrawable mockFocusedDrawable;
+ private MockDrawable mockCheckedDrawable;
+ private MockView mockView;
+ private MockDrawable mockDefaultDrawable;
+
+
+ // Re-enable tests when we are running in the framework-test directory which allows
+ // access to package private access for MockView
+
+ public void broken_testFocusScenarioSetStringWildcardFirst() throws Exception {
+ int focusedStateSet[] = {R.attr.state_focused};
+ int checkedStateSet[] = {R.attr.state_checked};
+ slDrawable.addState(StateSet.WILD_CARD,
+ mockDefaultDrawable);
+ slDrawable.addState(checkedStateSet, mockCheckedDrawable);
+ slDrawable.addState(focusedStateSet, mockFocusedDrawable);
+ mockView.requestFocus();
+ mockView.getBackground().draw(null);
+ assertTrue(mockDefaultDrawable.wasDrawn);
+ }
+
+ public void broken_testFocusScenarioStateSetWildcardLast() throws Exception {
+ int focusedStateSet[] = {R.attr.state_focused};
+ int checkedStateSet[] = {R.attr.state_checked};
+ slDrawable.addState(checkedStateSet, mockCheckedDrawable);
+ slDrawable.addState(focusedStateSet, mockFocusedDrawable);
+ slDrawable.addState(StateSet.WILD_CARD,
+ mockDefaultDrawable);
+ mockView.requestFocus();
+ mockView.getBackground().draw(null);
+ assertTrue(mockFocusedDrawable.wasDrawn);
+ }
+
+
+ protected void setUp() throws Exception {
+ super.setUp();
+ slDrawable = new StateListDrawable();
+ mockFocusedDrawable = new MockDrawable();
+ mockCheckedDrawable = new MockDrawable();
+ mockDefaultDrawable = new MockDrawable();
+ mockView = new MockView();
+ mockView.setBackgroundDrawable(slDrawable);
+ }
+
+ static class MockDrawable extends Drawable {
+
+ public boolean wasDrawn = false;
+
+ public void draw(Canvas canvas) {
+ wasDrawn = true;
+ }
+
+ public void setAlpha(int alpha) {
+ }
+
+ public void setColorFilter(ColorFilter cf) {
+ }
+
+ public int getOpacity() {
+ return android.graphics.PixelFormat.UNKNOWN;
+ }
+ }
+
+}
diff --git a/tests/CoreTests/android/location/LocationManagerProximityTest.java b/tests/CoreTests/android/location/LocationManagerProximityTest.java
new file mode 100644
index 0000000..e1501e3
--- /dev/null
+++ b/tests/CoreTests/android/location/LocationManagerProximityTest.java
@@ -0,0 +1,282 @@
+/*
+ * Copyright (C) 2008 Google Inc.
+ *
+ * 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 android.location;
+
+import android.app.PendingIntent;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.location.Criteria;
+import android.location.Location;
+import android.location.LocationManager;
+import android.provider.Settings;
+import android.test.AndroidTestCase;
+import android.test.suitebuilder.annotation.MediumTest;
+import android.util.Log;
+
+/**
+ * Tests for LocationManager.addProximityAlert
+ *
+ * TODO: add tests for more scenarios
+ *
+ * To run:
+ * adb shell am instrument -e class android.location.LocationManagerProximityTest \
+ * -w android.core/android.test.InstrumentationTestRunner
+ *
+ * This test requires that the "Allow mock locations" setting be enabled
+ *
+ */
+@MediumTest
+public class LocationManagerProximityTest extends AndroidTestCase {
+
+ private static final int UPDATE_LOCATION_WAIT_TIME = 1000;
+ private static final int PROXIMITY_WAIT_TIME = 2000;
+
+ private LocationManager mLocationManager;
+ private PendingIntent mPendingIntent;
+ private TestIntentReceiver mIntentReceiver;
+
+ private static final String LOG_TAG = "LocationProximityTest";
+
+ // use network provider as mock location provider, because:
+ // - proximity alert is hardcoded to listen to only network or gps
+ // - 'network' provider is not installed in emulator, so can mock it
+ // using test provider APIs
+ private static final String PROVIDER_NAME = LocationManager.NETWORK_PROVIDER;
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+
+ // test that mock locations are allowed so a more descriptive error message can be logged
+ if (Settings.Secure.getInt(getContext().getContentResolver(),
+ Settings.Secure.ALLOW_MOCK_LOCATION, 0) == 0) {
+ fail("Mock locations are currently disabled in Settings - this test requires " +
+ "mock locations");
+ }
+
+ mLocationManager = (LocationManager) getContext().
+ getSystemService(Context.LOCATION_SERVICE);
+ if (mLocationManager.getProvider(PROVIDER_NAME) != null) {
+ mLocationManager.removeTestProvider(PROVIDER_NAME);
+ }
+
+ mLocationManager.addTestProvider(PROVIDER_NAME, true, //requiresNetwork,
+ false, // requiresSatellite,
+ true, // requiresCell,
+ false, // hasMonetaryCost,
+ false, // supportsAltitude,
+ false, // supportsSpeed, s
+ false, // upportsBearing,
+ Criteria.POWER_MEDIUM, // powerRequirement
+ Criteria.ACCURACY_FINE); // accuracy
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
+ mLocationManager.removeTestProvider(PROVIDER_NAME);
+
+ if (mPendingIntent != null) {
+ mLocationManager.removeProximityAlert(mPendingIntent);
+ }
+ if (mIntentReceiver != null) {
+ getContext().unregisterReceiver(mIntentReceiver);
+ }
+ }
+
+ /**
+ * Tests basic proximity alert when entering proximity
+ */
+ public void testEnterProximity() throws Exception {
+ doTestEnterProximity(10000);
+ }
+
+ /**
+ * Tests proximity alert when entering proximity, with no expiration
+ */
+ public void testEnterProximity_noexpire() throws Exception {
+ doTestEnterProximity(-1);
+ }
+
+ /**
+ * Helper variant for testing enter proximity scenario
+ * TODO: add additional parameters as more scenarios are added
+ *
+ * @param expiration - expiry of proximity alert
+ */
+ private void doTestEnterProximity(long expiration) throws Exception {
+ // update location to outside proximity range
+ synchronousSendLocation(30, 30);
+ registerProximityListener(0, 0, 1000, expiration);
+ sendLocation(0, 0);
+ waitForAlert();
+ assertProximityType(true);
+ }
+
+ /**
+ * Tests basic proximity alert when exiting proximity
+ */
+ public void testExitProximity() throws Exception {
+ // first do enter proximity scenario
+ doTestEnterProximity(-1);
+
+ // now update to trigger exit proximity proximity
+ mIntentReceiver.clearReceivedIntents();
+ sendLocation(20, 20);
+ waitForAlert();
+ assertProximityType(false);
+ }
+
+ /**
+ * Registers the proximity intent receiver
+ */
+ private void registerProximityListener(double latitude, double longitude,
+ float radius, long expiration) {
+ String intentKey = "testProximity";
+ Intent proximityIntent = new Intent(intentKey);
+ mPendingIntent = PendingIntent.getBroadcast(getContext(), 0,
+ proximityIntent, PendingIntent.FLAG_CANCEL_CURRENT);
+ mIntentReceiver = new TestIntentReceiver(intentKey);
+
+ mLocationManager.addProximityAlert(latitude, longitude, radius,
+ expiration, mPendingIntent);
+
+ getContext().registerReceiver(mIntentReceiver,
+ mIntentReceiver.getFilter());
+
+ }
+
+ /**
+ * Blocks until proximity intent notification is received
+ * @throws InterruptedException
+ */
+ private void waitForAlert() throws InterruptedException {
+ Log.d(LOG_TAG, "Waiting for proximity update");
+ synchronized (mIntentReceiver) {
+ mIntentReceiver.wait(PROXIMITY_WAIT_TIME);
+ }
+
+ assertNotNull("Did not receive proximity alert",
+ mIntentReceiver.getLastReceivedIntent());
+ }
+
+ /**
+ * Asserts that the received intent had the enter proximity property set as
+ * expected
+ * @param expectedEnterProximity - true if enter proximity expected, false if
+ * exit expected
+ */
+ private void assertProximityType(boolean expectedEnterProximity)
+ throws Exception {
+ boolean proximityTest = mIntentReceiver.getLastReceivedIntent().
+ getBooleanExtra(LocationManager.KEY_PROXIMITY_ENTERING,
+ !expectedEnterProximity);
+ assertEquals("proximity alert not set to expected enter proximity value",
+ expectedEnterProximity, proximityTest);
+ }
+
+ /**
+ * Synchronous variant of sendLocation
+ */
+ private void synchronousSendLocation(final double latitude,
+ final double longitude)
+ throws InterruptedException {
+ sendLocation(latitude, longitude, this);
+ // wait for location to be set
+ synchronized (this) {
+ wait(UPDATE_LOCATION_WAIT_TIME);
+ }
+ }
+
+ /**
+ * Asynchronously update the mock location provider without notification
+ */
+ private void sendLocation(final double latitude, final double longitude) {
+ sendLocation(latitude, longitude, null);
+ }
+
+ /**
+ * Asynchronously update the mock location provider with given latitude and
+ * longitude
+ *
+ * @param latitude - update location
+ * @param longitude - update location
+ * @param observer - optionally, object to notify when update is sent.If
+ * null, no update will be sent
+ */
+ private void sendLocation(final double latitude, final double longitude,
+ final Object observer) {
+ Thread locationUpdater = new Thread() {
+ @Override
+ public void run() {
+ Location loc = new Location(PROVIDER_NAME);
+ loc.setLatitude(latitude);
+ loc.setLongitude(longitude);
+
+ loc.setTime(java.lang.System.currentTimeMillis());
+ Log.d(LOG_TAG, "Sending update for " + PROVIDER_NAME);
+ mLocationManager.setTestProviderLocation(PROVIDER_NAME, loc);
+ if (observer != null) {
+ synchronized (observer) {
+ observer.notify();
+ }
+ }
+ }
+ };
+ locationUpdater.start();
+
+ }
+
+ /**
+ * Helper class that receives a proximity intent and notifies the main class
+ * when received
+ */
+ private static class TestIntentReceiver extends BroadcastReceiver {
+
+ private String mExpectedAction;
+ private Intent mLastReceivedIntent;
+
+ public TestIntentReceiver(String expectedAction) {
+ mExpectedAction = expectedAction;
+ mLastReceivedIntent = null;
+ }
+
+ public IntentFilter getFilter() {
+ IntentFilter filter = new IntentFilter(mExpectedAction);
+ return filter;
+ }
+
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ if (intent != null && mExpectedAction.equals(intent.getAction())) {
+ Log.d(LOG_TAG, "Intent Received: " + intent.toString());
+ mLastReceivedIntent = intent;
+ synchronized (this) {
+ notify();
+ }
+ }
+ }
+
+ public Intent getLastReceivedIntent() {
+ return mLastReceivedIntent;
+ }
+
+ public void clearReceivedIntents() {
+ mLastReceivedIntent = null;
+ }
+ }
+}
diff --git a/tests/CoreTests/android/location/LocationTest.java b/tests/CoreTests/android/location/LocationTest.java
new file mode 100644
index 0000000..847ac7a
--- /dev/null
+++ b/tests/CoreTests/android/location/LocationTest.java
@@ -0,0 +1,230 @@
+/*
+ * Copyright (C) 2007 Google Inc.
+ *
+ * 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 android.location;
+
+import android.test.suitebuilder.annotation.SmallTest;
+
+import junit.framework.TestCase;
+
+/**
+ * Unit tests for android.location.Location
+ */
+@SmallTest
+public class LocationTest extends TestCase {
+
+ // ***** Tests for Location.convert
+ public void testConvert_DegreesToDouble(){
+ String testDegreesCoord = "-80.075";
+ String message;
+ double result;
+
+ result = Location.convert(testDegreesCoord);
+ message = "degreesToDoubleTest: Double should be -80.075, actual value is " +
+ String.valueOf(result);
+ assertEquals(message, -80.075, result);
+ }
+
+ public void testConvert_MinutesToDouble(){
+ String testMinutesCoord = "-80:05.10000";
+ String message;
+ double result;
+
+ result = Location.convert(testMinutesCoord);
+ message = "minutesToDoubleTest: Double should be -80.085, actual value is " +
+ String.valueOf(result);
+ assertEquals(message, -80.085, result);
+ }
+
+ public void testConvert_SecondsToDouble(){
+ String testSecondsCoord = "-80:04:03.00000";
+ String message;
+ double result;
+
+ result = Location.convert(testSecondsCoord);
+ message = "secondsToDoubleTest: Double should be -80.0675, actual value is " +
+ String.valueOf(result);
+ assertEquals(message, -80.0675, result);
+ }
+
+ public void testConvert_SecondsToDouble2(){
+ String testSecondsCoord = "-80:4:3";
+ String message;
+ double result;
+
+ result = Location.convert(testSecondsCoord);
+ message = "secondsToDouble2Test: Double should be -80.0675, actual value is " +
+ String.valueOf(result);
+ assertEquals(message, -80.0675, result);
+ }
+
+ // Testing the Convert(Double, Int)
+ public void testConvert_CoordinateToDegrees(){
+ String message;
+ String result;
+
+ result = Location.convert(-80.075, Location.FORMAT_DEGREES);
+ message = "coordinateToDegreesTest: Should return a string -80.075, but returned " + result;
+ assertEquals(message, "-80.075", result);
+ }
+
+ public void testConvert_CoordinateToDegrees2(){
+ String message;
+ String result;
+ result = Location.convert(-80.0, Location.FORMAT_DEGREES);
+ message = "coordinateToDegrees2Test: Should return a string -80, but returned " + result;
+ assertEquals(message, "-80", result);
+ }
+
+ public void testConvert_CoordinateToMinutes(){
+ String message;
+ String result;
+ double input = -80.085;
+ result = Location.convert(input, Location.FORMAT_MINUTES);
+ message = "coordinateToMinuteTest: Should return a string -80:5.1, but returned " +
+ result;
+ assertEquals(message, "-80:5.1", result);
+ }
+
+ public void testConvert_CoordinateToMinutes2(){
+ String message;
+ String result;
+ double input = -80;
+ result = Location.convert(input, Location.FORMAT_MINUTES);
+ message = "coordinateToMinute2Test: Should return a string -80:0, but returned " +
+ result;
+ assertEquals(message, "-80:0", result);
+ }
+
+ public void testConvert_CoordinateToSeconds(){
+ String message;
+ String result;
+
+ result = Location.convert(-80.075, Location.FORMAT_SECONDS);
+ message = "coordinateToSecondsTest: Should return a string -80:4:30, but returned " +
+ result;
+ assertEquals(message, "-80:4:30", result);
+ }
+ // **** end tests for Location.convert
+
+
+ public void testBearingTo(){
+ String message;
+ float bearing;
+ Location zeroLocation = new Location("");
+ zeroLocation.setLatitude(0);
+ zeroLocation.setLongitude(0);
+
+ Location testLocation = new Location("");
+ testLocation.setLatitude(1000000);
+ testLocation.setLongitude(0);
+
+ bearing = zeroLocation.bearingTo(zeroLocation);
+ message = "bearingToTest: Bearing should be 0, actual value is " + String.valueOf(bearing);
+ assertEquals(message, 0, bearing, 0);
+
+ bearing = zeroLocation.bearingTo(testLocation);
+ message = "bearingToTest: Bearing should be 180, actual value is " +
+ String.valueOf(bearing);
+ assertEquals(message, 180, bearing, 0);
+
+ testLocation.setLatitude(0);
+ testLocation.setLongitude(1000000);
+ bearing = zeroLocation.bearingTo(testLocation);
+ message = "bearingToTest: Bearing should be -90, actual value is " +
+ String.valueOf(bearing);
+ assertEquals(message, -90, bearing, 0);
+
+ //TODO: Test a Random Middle Value
+ }
+
+ public void testDistanceTo() {
+ String message;
+ boolean result = true;
+ float distance;
+ Location zeroLocation = new Location("");
+ zeroLocation.setLatitude(0);
+ zeroLocation.setLongitude(0);
+
+ Location testLocation = new Location("");
+ testLocation.setLatitude(1000000);
+ testLocation.setLongitude(0);
+
+ distance = zeroLocation.distanceTo(zeroLocation);
+ message = "distanceToTest: Distance should be 0, actual value is " +
+ String.valueOf(distance);
+ assertEquals(message, distance, 0, 0);
+
+ distance = zeroLocation.distanceTo(testLocation);
+ message = "distanceToTest: Distance should be 8885140, actual value is " +
+ String.valueOf(distance);
+ assertEquals(message, distance, 8885140.0, 1);
+ }
+
+ public void testAltitude() {
+ String message;
+ Location loc = new Location("");
+
+ loc.setAltitude(1);
+ message = "altitudeTest: set/getAltitude to 1 didn't work.";
+ assertEquals(message, loc.getAltitude(), 1, 0);
+ message = "altitudeTest: hasAltitude (a) didn't work.";
+ assertTrue(message, loc.hasAltitude());
+
+ loc.removeAltitude();
+ message = "altitudeTest: hasAltitude (b) didn't work.";
+ assertFalse(message, loc.hasAltitude());
+ message = "altitudeTest: getAltitude didn't return 0 when there was no altitude.";
+ assertEquals(message, loc.getAltitude(), 0, 0);
+ }
+
+ public void testSpeed() {
+ String message;
+ Location loc = new Location("");
+
+ loc.setSpeed(1);
+ message = "speedTest: set/getSpeed to 1 didn't work.";
+ assertEquals(message, loc.getSpeed(), 1, 0);
+ message = "speedTest: hasSpeed (a) didn't work.";
+ assertTrue(message, loc.hasSpeed());
+
+ loc.removeSpeed();
+ message = "speedTest: hasSpeed (b) didn't work.";
+ assertFalse(message, loc.hasSpeed());
+ message = "speedTest: getSpeed didn't return 0 when there was no speed.";
+ assertEquals(message, loc.getSpeed(), 0, 0);
+ }
+
+ public void testBearing() {
+ String message;
+ Location loc = new Location("");
+
+ loc.setBearing(1);
+ message = "bearingTest: set/getBearing to 1 didn't work.";
+ assertEquals(message, loc.getBearing(), 1, 0);
+ message = "bearingTest: hasBearing (a) didn't work.";
+ assertTrue(message, loc.hasBearing());
+
+ loc.removeBearing();
+ message = "bearingTest: hasBearing (b) didn't work.";
+ assertFalse(message, loc.hasBearing());
+ message = "bearingTest: getBearing didn't return 0 when there was no bearing.";
+ assertEquals(message, loc.getBearing(), 0, 0);
+ }
+
+}
+
+
diff --git a/tests/CoreTests/android/res/color/color1.xml b/tests/CoreTests/android/res/color/color1.xml
new file mode 100644
index 0000000..87034fa
--- /dev/null
+++ b/tests/CoreTests/android/res/color/color1.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 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.
+-->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+ <item android:state_focused="true" android:color="@color/testcolor1"/>
+ <item android:color="@color/testcolor2"/>
+</selector>
diff --git a/tests/CoreTests/android/res/color/color_no_default.xml b/tests/CoreTests/android/res/color/color_no_default.xml
new file mode 100644
index 0000000..41a9b5d
--- /dev/null
+++ b/tests/CoreTests/android/res/color/color_no_default.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 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.
+-->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+ <item android:state_focused="true" android:color="@color/testcolor1"/>
+</selector>
diff --git a/tests/CoreTests/android/res/values/colors.xml b/tests/CoreTests/android/res/values/colors.xml
new file mode 100644
index 0000000..7559e65
--- /dev/null
+++ b/tests/CoreTests/android/res/values/colors.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+**
+** Copyright 2006, 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.
+*/
+-->
+<resources>
+ <color name="testcolor1">#ff00ff00</color>
+ <color name="testcolor2">#ffff0000</color>
+ <color name="failColor">#ff0000ff</color>
+</resources>
+
diff --git a/tests/CoreTests/android/test/AndroidTestRunnerTest.java b/tests/CoreTests/android/test/AndroidTestRunnerTest.java
new file mode 100644
index 0000000..0574704
--- /dev/null
+++ b/tests/CoreTests/android/test/AndroidTestRunnerTest.java
@@ -0,0 +1,294 @@
+/*
+ * 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 android.test;
+
+import android.test.mock.MockContext;
+import android.test.suitebuilder.annotation.SmallTest;
+
+import com.google.android.collect.Lists;
+
+import junit.framework.TestCase;
+import junit.framework.AssertionFailedError;
+import junit.framework.Test;
+import junit.framework.TestSuite;
+import junit.framework.TestListener;
+
+import java.util.List;
+import java.util.Arrays;
+
+/**
+ * Unit tests for {@link AndroidTestRunner}
+ */
+@SmallTest
+public class AndroidTestRunnerTest extends TestCase {
+ private AndroidTestRunner mAndroidTestRunner;
+ private StubContext mStubContext;
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ mStubContext = new StubContext(getClass().getClassLoader());
+
+ mAndroidTestRunner = new AndroidTestRunner();
+ mAndroidTestRunner.setContext(mStubContext);
+ }
+
+ public void testLoadNoTestCases() throws Exception {
+ mAndroidTestRunner.setTestClassName(TestSuite.class.getName(), null);
+
+ List<TestCase> testCases = mAndroidTestRunner.getTestCases();
+ assertNotNull(testCases);
+ assertEquals(1, testCases.size());
+ assertEquals("warning", testCases.get(0).getName());
+ assertEquals(TestSuite.class.getSimpleName(), mAndroidTestRunner.getTestClassName());
+ }
+
+ public void testSetTestSuiteWithOneTestCase() throws Exception {
+ mAndroidTestRunner.setTestClassName(OneTestTestCase.class.getName(), null);
+
+ List<TestCase> testCases = mAndroidTestRunner.getTestCases();
+ assertNotNull(testCases);
+ assertEquals(1, testCases.size());
+ assertEquals("testOne", testCases.get(0).getName());
+ assertEquals(OneTestTestCase.class.getSimpleName(), mAndroidTestRunner.getTestClassName());
+ }
+
+ public void testRunTest() throws Exception {
+ mAndroidTestRunner.setTestClassName(OneTestTestCase.class.getName(), null);
+
+ TestListenerStub testListenerStub = new TestListenerStub();
+ mAndroidTestRunner.addTestListener(testListenerStub);
+
+ mAndroidTestRunner.runTest();
+
+ assertTrue(testListenerStub.saw("testOne"));
+ }
+
+ public void testRunTestWithAndroidTestCase() throws Exception {
+ mAndroidTestRunner.setTestClassName(
+ OneAndroidTestTestCase.class.getName(), "testOneAndroid");
+
+ TestListenerStub testListenerStub = new TestListenerStub();
+ mAndroidTestRunner.addTestListener(testListenerStub);
+
+ assertNull(((AndroidTestCase) mAndroidTestRunner.getTestCases().get(0)).getContext());
+
+ mAndroidTestRunner.runTest();
+
+ assertTrue(testListenerStub.saw("testOneAndroid"));
+ assertSame(mStubContext,
+ ((AndroidTestCase) mAndroidTestRunner.getTestCases().get(0)).getContext());
+ }
+
+ public void testRunTestWithAndroidTestCaseInSuite() throws Exception {
+ mAndroidTestRunner.setTestClassName(OneAndroidTestTestCase.class.getName(), null);
+
+ TestListenerStub testListenerStub = new TestListenerStub();
+ mAndroidTestRunner.addTestListener(testListenerStub);
+
+ mAndroidTestRunner.runTest();
+
+ assertTrue(testListenerStub.saw("testOneAndroid"));
+
+ List<TestCase> testCases = mAndroidTestRunner.getTestCases();
+ for (TestCase testCase : testCases) {
+ assertSame(mStubContext, ((AndroidTestCase) testCase).getContext());
+ }
+ }
+
+ public void testRunTestWithAndroidTestCaseInNestedSuite() throws Exception {
+ mAndroidTestRunner.setTestClassName(AndroidTestCaseTestSuite.class.getName(), null);
+
+ TestListenerStub testListenerStub = new TestListenerStub();
+ mAndroidTestRunner.addTestListener(testListenerStub);
+
+ mAndroidTestRunner.runTest();
+
+ assertTrue(testListenerStub.saw("testOneAndroid"));
+
+ List<TestCase> testCases = mAndroidTestRunner.getTestCases();
+ for (TestCase testCase : testCases) {
+ assertSame(mStubContext, ((AndroidTestCase) testCase).getContext());
+ }
+ }
+
+ public void testRunTestWithNullListener() throws Exception {
+ mAndroidTestRunner.setTestClassName(OneTestTestCase.class.getName(), null);
+
+ mAndroidTestRunner.addTestListener(null);
+ try {
+ mAndroidTestRunner.runTest();
+ } catch (NullPointerException e) {
+ fail("Should not add a null TestListener");
+ }
+ }
+
+ public void testSetTestClassWithTestSuiteProvider() throws Exception {
+ mAndroidTestRunner.setTestClassName(SampleTestSuiteProvider.class.getName(), null);
+ List<TestCase> testCases = mAndroidTestRunner.getTestCases();
+ List<String> testNames = Lists.newArrayList();
+ for (TestCase testCase : testCases) {
+ testNames.add(testCase.getName());
+ }
+
+ // Use the test suite provided by the interface method rather than the static suite method.
+ assertEquals(Arrays.asList("testOne"), testNames);
+ }
+
+ public void testSetTestClassWithTestSuite() throws Exception {
+ mAndroidTestRunner.setTestClassName(SampleTestSuite.class.getName(), null);
+ List<TestCase> testCases = mAndroidTestRunner.getTestCases();
+ List<String> testNames = Lists.newArrayList();
+ for (TestCase testCase : testCases) {
+ testNames.add(testCase.getName());
+ }
+ assertEquals(Arrays.asList("testOne", "testOne", "testTwo"), testNames);
+ }
+
+ public void testRunSingleTestMethod() throws Exception {
+ String testMethodName = "testTwo";
+ mAndroidTestRunner.setTestClassName(TwoTestTestCase.class.getName(), testMethodName);
+ List<TestCase> testCases = mAndroidTestRunner.getTestCases();
+ List<String> testNames = Lists.newArrayList();
+ for (TestCase testCase : testCases) {
+ testNames.add(testCase.getName());
+ }
+ assertEquals(Arrays.asList(testMethodName), testNames);
+ }
+
+ public void testSetTestClassInvalidClass() throws Exception {
+ try {
+ mAndroidTestRunner.setTestClassName("class.that.does.not.exist", null);
+ fail("expected exception not thrown");
+ } catch (RuntimeException e) {
+ // expected
+ }
+ }
+
+ public void testRunSkipExecution() throws Exception {
+ String testMethodName = "testFail";
+ mAndroidTestRunner.setTestClassName(
+ OnePassOneErrorOneFailTestCase.class.getName(), testMethodName);
+
+ TestListenerStub testListenerStub = new TestListenerStub();
+ mAndroidTestRunner.addTestListener(testListenerStub);
+
+ // running the failing test should pass - ie as if its not run
+ mAndroidTestRunner.runTest();
+
+ assertTrue(testListenerStub.saw("testFail"));
+ }
+
+ public static class SampleTestSuiteProvider implements TestSuiteProvider {
+
+ public TestSuite getTestSuite() {
+ TestSuite testSuite = new TestSuite();
+ testSuite.addTestSuite(OneTestTestCase.class);
+ return testSuite;
+ }
+
+ public static Test suite() {
+ return SampleTestSuite.suite();
+ }
+ }
+
+ public static class SampleTestSuite {
+ public static TestSuite suite() {
+ TestSuite testSuite = new TestSuite();
+ testSuite.addTestSuite(OneTestTestCase.class);
+ testSuite.addTestSuite(TwoTestTestCase.class);
+ return testSuite;
+ }
+ }
+
+ public static class AndroidTestCaseTestSuite {
+ public static TestSuite suite() {
+ TestSuite testSuite = new TestSuite();
+ testSuite.addTestSuite(OneAndroidTestTestCase.class);
+ return testSuite;
+ }
+ }
+
+ public static class OneAndroidTestTestCase extends AndroidTestCase {
+ public void testOneAndroid() throws Exception {
+ }
+ }
+
+ public static class OneTestTestCase extends TestCase {
+ public void testOne() throws Exception {
+ }
+ }
+
+ public static class TwoTestTestCase extends TestCase {
+ public void testOne() throws Exception {
+ }
+
+ public void testTwo() throws Exception {
+ }
+ }
+
+ public static class OnePassOneErrorOneFailTestCase extends TestCase {
+ public void testPass() throws Exception {
+ }
+
+ public void testError() throws Exception {
+ throw new Exception();
+ }
+
+ public void testFail() throws Exception {
+ fail();
+ }
+ }
+
+ private static class TestListenerStub implements TestListener {
+ List<String> testNames = Lists.newArrayList();
+
+ public void addError(Test test, Throwable t) {
+ }
+
+ public void addFailure(Test test, AssertionFailedError t) {
+ }
+
+ public void endTest(Test test) {
+ }
+
+ public void startTest(Test test) {
+ if (test instanceof TestCase) {
+ testNames.add(((TestCase) test).getName());
+ } else if (test instanceof TestSuite) {
+ testNames.add(((TestSuite) test).getName());
+ }
+ }
+
+ public boolean saw(String testName) {
+ return testNames.contains(testName);
+ }
+ }
+
+ private static class StubContext extends MockContext {
+ private ClassLoader mClassLoader;
+
+ public StubContext(ClassLoader classLoader) {
+ this.mClassLoader = classLoader;
+ }
+
+ @Override
+ public ClassLoader getClassLoader() {
+ return mClassLoader;
+ }
+ }
+}
diff --git a/tests/CoreTests/android/test/InstrumentationTestRunnerTest.java b/tests/CoreTests/android/test/InstrumentationTestRunnerTest.java
new file mode 100644
index 0000000..d9afd54
--- /dev/null
+++ b/tests/CoreTests/android/test/InstrumentationTestRunnerTest.java
@@ -0,0 +1,272 @@
+/*
+ * 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 android.test;
+
+import android.content.Context;
+import android.os.Bundle;
+import android.test.mock.MockContext;
+import android.test.suitebuilder.ListTestCaseNames;
+import android.test.suitebuilder.ListTestCaseNames.TestDescriptor;
+import android.test.suitebuilder.annotation.SmallTest;
+
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+
+import java.util.List;
+
+/**
+ * Tests for {@link InstrumentationTestRunner}
+ */
+@SmallTest
+public class InstrumentationTestRunnerTest extends TestCase {
+ private StubInstrumentationTestRunner mInstrumentationTestRunner;
+ private StubAndroidTestRunner mStubAndroidTestRunner;
+ private String mTargetContextPackageName;
+
+ protected void setUp() throws Exception {
+ super.setUp();
+ mStubAndroidTestRunner = new StubAndroidTestRunner();
+ mTargetContextPackageName = "android.test.suitebuilder.examples";
+ mInstrumentationTestRunner = new StubInstrumentationTestRunner(
+ new StubContext("com.google.foo.tests"),
+ new StubContext(mTargetContextPackageName), mStubAndroidTestRunner);
+ }
+
+ public void testOverrideTestToRunWithClassArgument() throws Exception {
+ String expectedTestClassName = PlaceHolderTest.class.getName();
+ mInstrumentationTestRunner.onCreate(createBundle(
+ InstrumentationTestRunner.ARGUMENT_TEST_CLASS, expectedTestClassName));
+
+ assertTestRunnerCalledWithExpectedParameters(expectedTestClassName, "testPlaceHolder");
+ }
+
+ public void testOverrideTestToRunWithClassAndMethodArgument() throws Exception {
+ String expectedTestClassName = PlaceHolderTest.class.getName();
+ String expectedTestMethodName = "testPlaceHolder";
+ String classAndMethod = expectedTestClassName + "#" + expectedTestMethodName;
+ mInstrumentationTestRunner.onCreate(createBundle(
+ InstrumentationTestRunner.ARGUMENT_TEST_CLASS, classAndMethod));
+
+ assertTestRunnerCalledWithExpectedParameters(expectedTestClassName,
+ expectedTestMethodName);
+ }
+
+ public void testUseSelfAsTestSuiteProviderWhenNoMetaDataOrClassArgument() throws Exception {
+ TestSuite testSuite = new TestSuite();
+ testSuite.addTestSuite(PlaceHolderTest.class);
+ mInstrumentationTestRunner.setAllTestsSuite(testSuite);
+ mInstrumentationTestRunner.onCreate(null);
+ assertTestRunnerCalledWithExpectedParameters(
+ PlaceHolderTest.class.getName(), "testPlaceHolder");
+ }
+
+ public void testMultipleTestClass() throws Exception {
+ String classArg = PlaceHolderTest.class.getName() + "," +
+ PlaceHolderTest2.class.getName();
+ mInstrumentationTestRunner.onCreate(createBundle(
+ InstrumentationTestRunner.ARGUMENT_TEST_CLASS, classArg));
+
+ Test test = mStubAndroidTestRunner.getTest();
+
+ assertContentsInOrder(ListTestCaseNames.getTestNames((TestSuite) test),
+ new TestDescriptor(PlaceHolderTest.class.getName(), "testPlaceHolder"),
+ new TestDescriptor(PlaceHolderTest2.class.getName(), "testPlaceHolder2"));
+
+ }
+
+ public void testDelayParameter() throws Exception {
+ int delayMsec = 1000;
+ Bundle args = new Bundle();
+ args.putInt(InstrumentationTestRunner.ARGUMENT_DELAY_MSEC, delayMsec);
+ args.putString(InstrumentationTestRunner.ARGUMENT_TEST_CLASS,
+ PlaceHolderTest.class.getName() + "," +
+ PlaceHolderTest2.class.getName());
+ mInstrumentationTestRunner.onCreate(args);
+ Thread t = new Thread() { public void run() { mInstrumentationTestRunner.onStart(); } };
+
+ // Should delay three times: before, between, and after the two tests.
+ long beforeTest = System.currentTimeMillis();
+ t.start();
+ t.join();
+ assertTrue(System.currentTimeMillis() > beforeTest + delayMsec * 3);
+ assertTrue(mInstrumentationTestRunner.isStarted());
+ assertTrue(mInstrumentationTestRunner.isFinished());
+ assertTrue(mStubAndroidTestRunner.isRun());
+ }
+
+ private void assertContentsInOrder(List<TestDescriptor> actual, TestDescriptor... source) {
+ TestDescriptor[] clonedSource = source.clone();
+ assertEquals("Unexpected number of items.", clonedSource.length, actual.size());
+ for (int i = 0; i < actual.size(); i++) {
+ TestDescriptor actualItem = actual.get(i);
+ TestDescriptor sourceItem = clonedSource[i];
+ assertEquals("Unexpected item. Index: " + i, sourceItem, actualItem);
+ }
+ }
+
+ private void assertTestRunnerCalledWithExpectedParameters(
+ String expectedTestClassName, String expectedTestMethodName) {
+ Test test = mStubAndroidTestRunner.getTest();
+ assertContentsInOrder(ListTestCaseNames.getTestNames((TestSuite) test),
+ new TestDescriptor(expectedTestClassName, expectedTestMethodName));
+ assertTrue(mInstrumentationTestRunner.isStarted());
+ assertFalse(mInstrumentationTestRunner.isFinished());
+ }
+
+ private Bundle createBundle(String key, String value) {
+ Bundle bundle = new Bundle();
+ bundle.putString(key, value);
+ return bundle;
+ }
+
+ private static class StubInstrumentationTestRunner extends InstrumentationTestRunner {
+ private Context mContext;
+ private Context mTargetContext;
+ private boolean mStarted;
+ private boolean mFinished;
+ private AndroidTestRunner mAndroidTestRunner;
+ private TestSuite mTestSuite;
+ private TestSuite mDefaultTestSuite;
+ private String mPackageNameForDefaultTests;
+
+ public StubInstrumentationTestRunner(Context context, Context targetContext,
+ AndroidTestRunner androidTestRunner) {
+ this.mContext = context;
+ this.mTargetContext = targetContext;
+ this.mAndroidTestRunner = androidTestRunner;
+ }
+
+ public Context getContext() {
+ return mContext;
+ }
+
+ public TestSuite getAllTests() {
+ return mTestSuite;
+ }
+
+ public Context getTargetContext() {
+ return mTargetContext;
+ }
+
+ protected AndroidTestRunner getAndroidTestRunner() {
+ return mAndroidTestRunner;
+ }
+
+ public void start() {
+ mStarted = true;
+ }
+
+ public void finish(int resultCode, Bundle results) {
+ mFinished = true;
+ }
+
+ public boolean isStarted() {
+ return mStarted;
+ }
+
+ public boolean isFinished() {
+ return mFinished;
+ }
+
+ public void setAllTestsSuite(TestSuite testSuite) {
+ mTestSuite = testSuite;
+ }
+
+ public void setDefaultTestsSuite(TestSuite testSuite) {
+ mDefaultTestSuite = testSuite;
+ }
+
+ public String getPackageNameForDefaultTests() {
+ return mPackageNameForDefaultTests;
+ }
+ }
+
+ private static class StubContext extends MockContext {
+ private String mPackageName;
+
+ public StubContext(String packageName) {
+ this.mPackageName = packageName;
+ }
+
+ @Override
+ public String getPackageCodePath() {
+ return mPackageName;
+ }
+
+ @Override
+ public String getPackageName() {
+ return mPackageName;
+ }
+
+ @Override
+ public ClassLoader getClassLoader() {
+ return getClass().getClassLoader();
+ }
+ }
+
+ private static class StubAndroidTestRunner extends AndroidTestRunner {
+ private Test mTest;
+ private boolean mRun;
+
+ public boolean isRun() {
+ return mRun;
+ }
+
+ public void setTest(Test test) {
+ super.setTest(test);
+ mTest = test;
+ }
+
+ public Test getTest() {
+ return mTest;
+ }
+
+ public void runTest() {
+ super.runTest();
+ mRun = true;
+ }
+ }
+
+ /**
+ * Empty test used for validation
+ */
+ public static class PlaceHolderTest extends TestCase {
+
+ public PlaceHolderTest() {
+ super("testPlaceHolder");
+ }
+
+ public void testPlaceHolder() throws Exception {
+
+ }
+ }
+
+ /**
+ * Empty test used for validation
+ */
+ public static class PlaceHolderTest2 extends TestCase {
+
+ public PlaceHolderTest2() {
+ super("testPlaceHolder2");
+ }
+
+ public void testPlaceHolder2() throws Exception {
+
+ }
+ }
+}
diff --git a/tests/CoreTests/android/test/StubTestBrowserActivity.java b/tests/CoreTests/android/test/StubTestBrowserActivity.java
new file mode 100644
index 0000000..97ed3ce
--- /dev/null
+++ b/tests/CoreTests/android/test/StubTestBrowserActivity.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2007 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 android.test;
+
+import junit.framework.TestSuite;
+
+public class StubTestBrowserActivity extends TestBrowserActivity {
+
+ private static TestSuite mTestSuite;
+
+ static void setTopTestSuite(TestSuite testSuite) {
+ mTestSuite = testSuite;
+ }
+
+ @Override
+ public TestSuite getTopTestSuite() {
+ return mTestSuite;
+ }
+}
diff --git a/tests/CoreTests/android/test/TestBrowserActivityTest.java b/tests/CoreTests/android/test/TestBrowserActivityTest.java
new file mode 100644
index 0000000..6afbe37
--- /dev/null
+++ b/tests/CoreTests/android/test/TestBrowserActivityTest.java
@@ -0,0 +1,270 @@
+/*
+ * Copyright (C) 2007 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 android.test;
+
+import android.app.Activity;
+import android.app.Instrumentation;
+import android.content.Intent;
+import android.net.Uri;
+import android.os.RemoteException;
+import android.os.ServiceManager;
+import android.view.IWindowManager;
+import android.widget.ListView;
+
+import com.google.android.collect.Lists;
+
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+
+import java.util.List;
+
+public class TestBrowserActivityTest extends InstrumentationTestCase {
+
+ private TestBrowserActivity mTestBrowserActivity;
+ private StubTestBrowserController mTestBrowserController;
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ StubTestBrowserActivity.setTopTestSuite(null);
+ mTestBrowserController = new StubTestBrowserController();
+ ServiceLocator.setTestBrowserController(mTestBrowserController);
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
+ if (mTestBrowserActivity != null) {
+ mTestBrowserActivity.finish();
+ }
+ mTestBrowserActivity = null;
+ super.tearDown();
+ }
+
+ public void testEmptyListContent() throws Exception {
+ StubTestBrowserActivity.setTopTestSuite(new TestSuite());
+
+ mTestBrowserActivity = createActivity();
+
+ ListView listView = getListView();
+ // There is always an item on the list for running all tests.
+ assertEquals("Unexpected number of items on list view.", 1, listView.getCount());
+
+ assertEquals("Stubbed Test Browser", mTestBrowserActivity.getTitle().toString());
+ }
+
+ public void testOneListContent() throws Exception {
+ List<String> testCaseNames = Lists.newArrayList("AllTests");
+ StubTestBrowserActivity.setTopTestSuite(createTestSuite(testCaseNames));
+
+ mTestBrowserActivity = createActivity();
+
+ ListView listView = getListView();
+ assertListViewContents(testCaseNames, listView);
+ }
+
+ public void testListWithTestCases() throws Exception {
+ List<String> testCaseNames = Lists.newArrayList("AllTests", "Apples", "Bananas", "Oranges");
+ StubTestBrowserActivity.setTopTestSuite(createTestSuite(testCaseNames));
+
+ mTestBrowserActivity = createActivity();
+
+ ListView listView = getListView();
+ assertListViewContents(testCaseNames, listView);
+ }
+
+ public void testListWithTestSuite() throws Exception {
+ List<String> testCaseNames = Lists.newArrayList(OneTestTestCase.class.getSimpleName());
+ StubTestBrowserActivity.setTopTestSuite(new OneTestInTestSuite());
+
+ mTestBrowserActivity = createActivity();
+
+ ListView listView = getListView();
+ assertListViewContents(testCaseNames, listView);
+ }
+
+ public void testSelectATestCase() throws Exception {
+ List<String> testCaseNames = Lists.newArrayList("AllTests");
+ TestSuite testSuite = createTestSuite(testCaseNames);
+ StubTestBrowserActivity.setTopTestSuite(testSuite);
+
+ mTestBrowserController.setTestCase(OneTestTestCase.class);
+ mTestBrowserActivity = createActivity();
+
+ Instrumentation.ActivityMonitor activityMonitor = getInstrumentation().addMonitor(
+ TestBrowserControllerImpl.TEST_RUNNER_ACTIVITY_CLASS_NAME, null, false);
+ try {
+ assertEquals(0, activityMonitor.getHits());
+
+ ListView listView = getListView();
+ int invokedTestCaseIndex = 0;
+ listView.performItemClick(listView, invokedTestCaseIndex, 0);
+
+ Activity activity = activityMonitor.waitForActivityWithTimeout(2000);
+ assertNotNull(activity);
+ try {
+ assertEquals(1, activityMonitor.getHits());
+ assertEquals(invokedTestCaseIndex, mTestBrowserController.getLastPosition());
+ } finally {
+ activity.finish();
+ }
+ } finally {
+ getInstrumentation().removeMonitor(activityMonitor);
+ }
+ }
+
+ public void testCreateFromIntentWithOneTest() throws Exception {
+ List<String> testCaseNames = Lists.newArrayList("testOne");
+
+ mTestBrowserActivity = launchTestBrowserActivity(new TestSuite(OneTestTestCase.class));
+
+ ListView listView = getListView();
+ assertListViewContents(testCaseNames, listView);
+ }
+
+ public void testUpdateListOnStart() throws Exception {
+ StubTestBrowserActivity.setTopTestSuite(new TestSuite());
+
+ mTestBrowserActivity = createActivity();
+
+ ListView listView = getListView();
+ assertEquals("Unexpected number of items on list view.", 1, listView.getCount());
+
+ List<String> testCaseNames = Lists.newArrayList("AllTests");
+ StubTestBrowserActivity.setTopTestSuite(createTestSuite(testCaseNames));
+
+ getInstrumentation().runOnMainSync(new Runnable() {
+ public void run() {
+ ((StubTestBrowserActivity) mTestBrowserActivity).onStart();
+ }
+ });
+
+ listView = getListView();
+ assertListViewContents(testCaseNames, listView);
+ }
+
+ public void testTitleHasTestSuiteName() throws Exception {
+ final String testSuiteName = "com.android.TestSuite";
+ StubTestBrowserActivity.setTopTestSuite(new TestSuite(testSuiteName));
+
+ mTestBrowserActivity = createActivity();
+
+ assertEquals("TestSuite", mTestBrowserActivity.getTitle().toString());
+ }
+
+ private TestSuite createTestSuite(List<String> testCaseNames) {
+ return createTestSuite(testCaseNames.toArray(new String[testCaseNames.size()]));
+ }
+
+ private TestSuite createTestSuite(String... testCaseNames) {
+ TestSuite testSuite = new TestSuite();
+ for (String testCaseName : testCaseNames) {
+ testSuite.addTest(new FakeTestCase(testCaseName));
+ }
+
+ return testSuite;
+ }
+
+ public static class FakeTestCase extends TestCase {
+ public FakeTestCase(String name) {
+ super(name);
+ }
+ }
+
+ public static class OneTestTestCase extends TestCase {
+ public void testOne() throws Exception {
+ }
+ }
+
+ public static class OneTestInTestSuite extends TestSuite {
+ public static Test suite() {
+ TestSuite suite = new TestSuite(OneTestInTestSuite.class.getName());
+ suite.addTestSuite(OneTestTestCase.class);
+ return suite;
+ }
+ }
+
+ private void assertListViewContents(List<String> expectedTestCaseNames, ListView listView) {
+ assertEquals("Run All", listView.getItemAtPosition(0).toString());
+ assertEquals("Unexpected number of items on list view.",
+ expectedTestCaseNames.size() + 1, listView.getCount());
+ for (int i = 0; i < expectedTestCaseNames.size(); i++) {
+ String expectedTestCaseName = expectedTestCaseNames.get(i);
+ String actualTestCaseName = listView.getItemAtPosition(i + 1).toString();
+ assertEquals("Unexpected test case name. Index: " + i,
+ expectedTestCaseName, actualTestCaseName);
+ }
+ }
+
+ private ListView getListView() {
+ return mTestBrowserActivity.getListView();
+ }
+
+ private TestBrowserActivity createActivity() throws RemoteException {
+ return launchActivity("android.test", StubTestBrowserActivity.class, null);
+ }
+
+ private Intent createIntent(TestSuite testSuite) {
+ Intent intent = new Intent(Intent.ACTION_RUN);
+ intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ String className = StubTestBrowserActivity.class.getName();
+ String packageName = className.substring(0, className.lastIndexOf("."));
+ intent.setClassName(packageName, className);
+ intent.setData(Uri.parse(testSuite.getName()));
+ return intent;
+ }
+
+ private TestBrowserActivity launchTestBrowserActivity(TestSuite testSuite)
+ throws RemoteException {
+ getInstrumentation().setInTouchMode(false);
+
+ TestBrowserActivity activity =
+ (TestBrowserActivity) getInstrumentation().startActivitySync(
+ createIntent(testSuite));
+ getInstrumentation().waitForIdleSync();
+ return activity;
+ }
+
+ private static class StubTestBrowserController extends TestBrowserControllerImpl {
+ private int mPosition;
+ private Class<? extends TestCase> mTestCaseClass;
+
+ public Intent getIntentForTestAt(int position) {
+ mPosition = position;
+
+ Intent intent = new Intent();
+ intent.setAction(Intent.ACTION_RUN);
+
+ String className = TestBrowserControllerImpl.TEST_RUNNER_ACTIVITY_CLASS_NAME;
+ String testName = mTestCaseClass.getClass().getName();
+
+ String packageName = className.substring(0, className.lastIndexOf("."));
+ intent.setClassName(packageName, className);
+ intent.setData(Uri.parse(testName));
+
+ return intent;
+ }
+
+ public void setTestCase(Class<? extends TestCase> testCaseClass) {
+ mTestCaseClass = testCaseClass;
+ }
+
+ public int getLastPosition() {
+ return mPosition;
+ }
+ }
+}
diff --git a/tests/CoreTests/android/test/TestBrowserControllerImplTest.java b/tests/CoreTests/android/test/TestBrowserControllerImplTest.java
new file mode 100644
index 0000000..1315606
--- /dev/null
+++ b/tests/CoreTests/android/test/TestBrowserControllerImplTest.java
@@ -0,0 +1,134 @@
+/*
+ * Copyright (C) 2007 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 android.test;
+
+import android.content.Intent;
+
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+
+import java.util.Arrays;
+import java.util.List;
+
+public class TestBrowserControllerImplTest extends TestCase {
+ private TestBrowserControllerImpl mTestBrowserController;
+ private TestBrowserViewStub mTestBrowserView;
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ mTestBrowserController = new TestBrowserControllerImpl();
+ mTestBrowserView = new TestBrowserViewStub();
+ mTestBrowserController.registerView(mTestBrowserView);
+ }
+
+ public void testSetTestSuite() throws Exception {
+ TestSuite testSuite = new TestSuite();
+ testSuite.addTestSuite(DummyTestCase.class);
+
+ mTestBrowserController.setTestSuite(testSuite);
+
+ verifyTestNames(Arrays.asList("Run All", DummyTestCase.class.getSimpleName()),
+ mTestBrowserView.getTestNames());
+ }
+
+ private static void verifyTestNames(List<String> expectedTestNames,
+ List<String> actualTestNames) {
+ assertEquals(expectedTestNames.size(), actualTestNames.size());
+
+ // We use endsWith instead of equals because the return value of
+ // class.getSimpleName(), when called on an inner class, varies
+ // from one vm to another.
+ // This allows the test to pass in multiple environments.
+ for (int i = 0; i < expectedTestNames.size(); i++) {
+ assertTrue(actualTestNames.get(i).endsWith(expectedTestNames.get(i)));
+ }
+ }
+
+ public void testGetIntentForTestSuite() throws Exception {
+ TestSuite testSuite = new TestSuite();
+ testSuite.addTestSuite(DummyTestCase.class);
+
+ String targetBrowserActvityClassName = "com.android.bogus.DummyActivity";
+ String expectedTargetPackageName = "com.android.bogus";
+ mTestBrowserController.setTargetBrowserActivityClassName(targetBrowserActvityClassName);
+ mTestBrowserController.setTestSuite(testSuite);
+ mTestBrowserController.setTargetPackageName(expectedTargetPackageName);
+ Intent intent = mTestBrowserController.getIntentForTestAt(1);
+ verifyIntent(intent, DummyTestCase.class, expectedTargetPackageName);
+ assertEquals(targetBrowserActvityClassName, intent.getComponent().getClassName());
+ }
+
+ public void testGetIntentForTestCase() throws Exception {
+ TestSuite testSuite = new TestSuite();
+ testSuite.addTest(new DummyTestCase());
+
+ mTestBrowserController.setTestSuite(testSuite);
+ Intent intent = mTestBrowserController.getIntentForTestAt(1);
+ verifyIntent(intent, DummyTestCase.class, "com.android.testharness");
+ assertEquals(TestBrowserControllerImpl.TEST_RUNNER_ACTIVITY_CLASS_NAME,
+ intent.getComponent().getClassName());
+ assertEquals("testDummyTest",
+ intent.getStringExtra(TestBrowserController.BUNDLE_EXTRA_TEST_METHOD_NAME));
+ }
+
+ public void testGetIntentForRunAll() throws Exception {
+ TestSuite testSuite = new DummyTestSuite();
+ testSuite.addTestSuite(DummyTestCase.class);
+
+ mTestBrowserController.setTestSuite(testSuite);
+ Intent intent = mTestBrowserController.getIntentForTestAt(0);
+ verifyIntent(intent, DummyTestSuite.class, "com.android.testharness");
+ }
+
+ private static void verifyIntent(Intent intent, Class testClass, String expectedPackageName) {
+ assertEquals(Intent.ACTION_RUN, intent.getAction());
+ assertEquals(Intent.FLAG_ACTIVITY_NEW_TASK,
+ intent.getFlags() & Intent.FLAG_ACTIVITY_NEW_TASK);
+ assertEquals(Intent.FLAG_ACTIVITY_MULTIPLE_TASK,
+ intent.getFlags() & Intent.FLAG_ACTIVITY_MULTIPLE_TASK);
+ assertEquals(testClass.getName(), intent.getData().toString());
+ assertEquals(expectedPackageName, intent.getComponent().getPackageName());
+ }
+
+ private static class DummyTestSuite extends TestSuite {
+ private DummyTestSuite() {
+ super(DummyTestSuite.class.getName());
+ }
+ }
+
+ private static class DummyTestCase extends TestCase {
+ private DummyTestCase() {
+ super("testDummyTest");
+ }
+
+ public void testDummyTest() throws Exception {
+ }
+ }
+
+ private class TestBrowserViewStub implements TestBrowserView {
+ private List<String> mTestNames;
+
+ public void setTestNames(List<String> testNames) {
+ mTestNames = testNames;
+ }
+
+ public List<String> getTestNames() {
+ return mTestNames;
+ }
+ }
+}
diff --git a/tests/CoreTests/android/test/TestBrowserTests.java b/tests/CoreTests/android/test/TestBrowserTests.java
new file mode 100644
index 0000000..535e2f8
--- /dev/null
+++ b/tests/CoreTests/android/test/TestBrowserTests.java
@@ -0,0 +1,22 @@
+// Copyright 2007 The Android Open Source Project
+
+
+package android.test;
+
+import junit.framework.TestSuite;
+
+public class TestBrowserTests extends TestBrowserActivity {
+
+ @Override
+ public TestSuite getTopTestSuite() {
+ return suite();
+ }
+
+ public static TestSuite suite() {
+ TestSuite testSuite = new TestSuite(TestBrowserTests.class.getName());
+ testSuite.addTestSuite(TestBrowserControllerImplTest.class);
+ testSuite.addTestSuite(TestCaseUtilTest.class);
+
+ return testSuite;
+ }
+}
diff --git a/tests/CoreTests/android/test/TestCaseUtilTest.java b/tests/CoreTests/android/test/TestCaseUtilTest.java
new file mode 100644
index 0000000..bc6fa92
--- /dev/null
+++ b/tests/CoreTests/android/test/TestCaseUtilTest.java
@@ -0,0 +1,100 @@
+/*
+ * Copyright (C) 2007 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 android.test;
+
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+
+import java.util.List;
+
+public class TestCaseUtilTest extends TestCase {
+
+ public void testGetTestCaseNamesForTestSuiteWithSuiteMethod() throws Exception {
+ TestSuite testSuite = new TwoTestsInTestSuite();
+
+ List<String> testCaseNames = TestCaseUtil.getTestCaseNames(testSuite, false);
+
+ assertEquals(2, testCaseNames.size());
+ assertTrue(testCaseNames.get(0).endsWith("OneTestTestCase"));
+ assertTrue(testCaseNames.get(1).endsWith("OneTestTestSuite"));
+ }
+
+ public void testGetTestCaseNamesForTestCaseWithSuiteMethod() throws Exception {
+ TestCase testCase = new OneTestTestCaseWithSuite();
+
+ List<String> testCaseNames = TestCaseUtil.getTestCaseNames(testCase, false);
+
+ assertEquals(1, testCaseNames.size());
+ assertTrue(testCaseNames.get(0).endsWith("testOne"));
+ }
+
+ public void testCreateTestForTestCase() throws Exception {
+ Test test = TestCaseUtil.createTestSuite(OneTestTestCase.class);
+ assertEquals(1, test.countTestCases());
+ }
+
+ public void testCreateTestForTestSuiteWithSuiteMethod() throws Exception {
+ Test test = TestCaseUtil.createTestSuite(TwoTestsInTestSuite.class);
+ assertEquals(2, test.countTestCases());
+ }
+
+ public void testCreateTestForTestCaseWithSuiteMethod() throws Exception {
+ Test test = TestCaseUtil.createTestSuite(OneTestTestCaseWithSuite.class);
+ assertEquals(1, test.countTestCases());
+ }
+
+ public void testReturnEmptyStringForTestSuiteWithNoName() throws Exception {
+ assertEquals("", TestCaseUtil.getTestName(new TestSuite()));
+ }
+
+ public static class OneTestTestCase extends TestCase {
+ public void testOne() throws Exception {
+ }
+ }
+
+ public static class OneTestTestCaseWithSuite extends TestCase {
+ public static Test suite() {
+ TestCase testCase = new OneTestTestCase();
+ testCase.setName("testOne");
+ return testCase;
+ }
+
+ public void testOne() throws Exception {
+ }
+
+ public void testTwo() throws Exception {
+ }
+ }
+
+ public static class OneTestTestSuite {
+ public static Test suite() {
+ TestSuite suite = new TestSuite(OneTestTestSuite.class.getName());
+ suite.addTestSuite(OneTestTestCase.class);
+ return suite;
+ }
+ }
+
+ public static class TwoTestsInTestSuite extends TestSuite {
+ public static Test suite() {
+ TestSuite suite = new TestSuite(TwoTestsInTestSuite.class.getName());
+ suite.addTestSuite(OneTestTestCase.class);
+ suite.addTest(OneTestTestSuite.suite());
+ return suite;
+ }
+ }
+}
diff --git a/tests/CoreTests/android/test/suitebuilder/AssignableFromTest.java b/tests/CoreTests/android/test/suitebuilder/AssignableFromTest.java
new file mode 100644
index 0000000..0f73e89
--- /dev/null
+++ b/tests/CoreTests/android/test/suitebuilder/AssignableFromTest.java
@@ -0,0 +1,85 @@
+/*
+ * 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 android.test.suitebuilder;
+
+import junit.framework.TestCase;
+
+import java.lang.reflect.Method;
+
+public class AssignableFromTest extends TestCase {
+ private AssignableFrom assignableFrom;
+
+
+ protected void setUp() throws Exception {
+ super.setUp();
+ assignableFrom = new AssignableFrom(Animal.class);
+ }
+
+ public void testSelfIsAssignable() throws Exception {
+ assertTrue(assignableFrom.apply(testMethodFor(Animal.class)));
+ }
+
+ public void testSubclassesAreAssignable() throws Exception {
+ assertTrue(assignableFrom.apply(testMethodFor(Mammal.class)));
+ assertTrue(assignableFrom.apply(testMethodFor(Human.class)));
+ }
+
+ public void testNotAssignable() throws Exception {
+ assertFalse(assignableFrom.apply(testMethodFor(Pencil.class)));
+ }
+
+ public void testImplementorsAreAssignable() throws Exception {
+ assignableFrom = new AssignableFrom(WritingInstrument.class);
+
+ assertTrue(assignableFrom.apply(testMethodFor(Pencil.class)));
+ assertTrue(assignableFrom.apply(testMethodFor(Pen.class)));
+ }
+
+ private TestMethod testMethodFor(Class<? extends TestCase> aClass)
+ throws NoSuchMethodException {
+ Method method = aClass.getMethod("testX");
+ return new TestMethod(method, aClass);
+ }
+
+ private class Animal extends TestCase {
+ public void testX() {
+ }
+ }
+
+ private class Mammal extends Animal {
+ public void testX() {
+ }
+ }
+
+ private class Human extends Mammal {
+ public void testX() {
+ }
+ }
+
+ private interface WritingInstrument {
+ }
+
+ private class Pencil extends TestCase implements WritingInstrument {
+ public void testX() {
+ }
+ }
+
+ private class Pen extends TestCase implements WritingInstrument {
+ public void testX() {
+ }
+ }
+}
diff --git a/tests/CoreTests/android/test/suitebuilder/InstrumentationTestSuiteBuilderTest.java b/tests/CoreTests/android/test/suitebuilder/InstrumentationTestSuiteBuilderTest.java
new file mode 100644
index 0000000..1872803
--- /dev/null
+++ b/tests/CoreTests/android/test/suitebuilder/InstrumentationTestSuiteBuilderTest.java
@@ -0,0 +1,116 @@
+/*
+ * 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 android.test.suitebuilder;
+
+import static android.test.suitebuilder.ListTestCaseNames.getTestCaseNames;
+import android.test.suitebuilder.examples.OuterTest;
+import android.test.suitebuilder.examples.instrumentation.InstrumentationTest;
+
+import junit.framework.AssertionFailedError;
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestListener;
+import junit.framework.TestResult;
+import junit.framework.TestSuite;
+
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+public class InstrumentationTestSuiteBuilderTest extends TestCase {
+
+ private InstrumentationTestSuiteBuilder instrumentationTestSuiteBuilder;
+
+ protected void setUp() throws Exception {
+ super.setUp();
+ instrumentationTestSuiteBuilder = new InstrumentationTestSuiteBuilder(getClass());
+ }
+
+ public void testShouldIncludeIntrumentationTests() throws Exception {
+ instrumentationTestSuiteBuilder.includePackages(packageFor(InstrumentationTest.class));
+
+ SuiteExecutionRecorder recorder = runSuite(instrumentationTestSuiteBuilder);
+
+ assertEquals(1, recorder.testsSeen.size());
+ assertTrue(recorder.saw("InstrumentationTest.testInstrumentation"));
+ }
+
+ public void testShouldOnlyIncludeIntrumentationTests() throws Exception {
+ TestSuite testSuite = new OuterTest()
+ .buildTestsUnderHereWith(instrumentationTestSuiteBuilder);
+ List<String> testCaseNames = getTestCaseNames(testSuite);
+ assertEquals(1, testCaseNames.size());
+ assertEquals("testInstrumentation", testCaseNames.get(0));
+ }
+
+ private static String packageFor(Class clazz) {
+ String className = clazz.getName();
+ return className.substring(0, className.lastIndexOf('.'));
+ }
+
+ private SuiteExecutionRecorder runSuite(TestSuiteBuilder builder) {
+ TestSuite suite = builder.build();
+ SuiteExecutionRecorder recorder = new SuiteExecutionRecorder();
+ TestResult result = new TestResult();
+ result.addListener(recorder);
+ suite.run(result);
+ return recorder;
+ }
+
+ private class SuiteExecutionRecorder implements TestListener {
+
+ private Set<String> failures = new HashSet<String>();
+ private Set<String> errors = new HashSet<String>();
+ private Set<String> testsSeen = new HashSet<String>();
+
+ public void addError(Test test, Throwable t) {
+ errors.add(testName(test));
+ }
+
+ public void addFailure(Test test, AssertionFailedError t) {
+ failures.add(testName(test));
+ }
+
+ public void endTest(Test test) {
+ }
+
+ public void startTest(Test test) {
+ testsSeen.add(testName(test));
+ }
+
+ public boolean saw(String testName) {
+ return testsSeen.contains(testName);
+ }
+
+ public boolean failed(String testName) {
+ return failures.contains(testName);
+ }
+
+ public boolean errored(String testName) {
+ return errors.contains(testName);
+ }
+
+ public boolean passed(String testName) {
+ return saw(testName) && !failed(testName) && !errored(testName);
+ }
+
+ private String testName(Test test) {
+ TestCase testCase = (TestCase) test;
+ return testCase.getClass().getSimpleName() + "." + testCase.getName();
+ }
+ }
+}
diff --git a/tests/CoreTests/android/test/suitebuilder/ListTestCaseNames.java b/tests/CoreTests/android/test/suitebuilder/ListTestCaseNames.java
new file mode 100644
index 0000000..37ec328
--- /dev/null
+++ b/tests/CoreTests/android/test/suitebuilder/ListTestCaseNames.java
@@ -0,0 +1,102 @@
+/*
+ * 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 android.test.suitebuilder;
+
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+public class ListTestCaseNames {
+ public static List<String> getTestCaseNames(TestSuite suite) {
+ // TODO: deprecate this method and move all callers to use getTestNames
+ List<Test> tests = Collections.<Test>list(suite.tests());
+ ArrayList<String> testCaseNames = new ArrayList<String>();
+ for (Test test : tests) {
+ if (test instanceof TestCase) {
+ testCaseNames.add(((TestCase) test).getName());
+ } else if (test instanceof TestSuite) {
+ testCaseNames.addAll(getTestCaseNames((TestSuite) test));
+ }
+ }
+ return testCaseNames;
+ }
+
+ /**
+ * Returns a list of test class and method names for each TestCase in suite.
+ */
+ public static List<TestDescriptor> getTestNames(TestSuite suite) {
+ List<Test> tests = Collections.<Test>list(suite.tests());
+ ArrayList<TestDescriptor> testNames = new ArrayList<TestDescriptor>();
+ for (Test test : tests) {
+ if (test instanceof TestCase) {
+ String className = test.getClass().getName();
+ String testName = ((TestCase) test).getName();
+ testNames.add(new TestDescriptor(className, testName));
+ } else if (test instanceof TestSuite) {
+ testNames.addAll(getTestNames((TestSuite) test));
+ }
+ }
+ return testNames;
+ }
+
+ /**
+ * Data holder for test case info
+ */
+ public static class TestDescriptor {
+ private String mClassName;
+ private String mTestName;
+
+ public TestDescriptor(String className, String testName) {
+ mClassName = className;
+ mTestName = testName;
+ }
+
+ public String getClassName() {
+ return mClassName;
+ }
+
+ public String getTestName() {
+ return mTestName;
+ }
+
+ /**
+ * Override parent to do string-based class and test name comparison
+ */
+ @Override
+ public boolean equals(Object otherObj) {
+ if (otherObj instanceof TestDescriptor) {
+ TestDescriptor otherDesc = (TestDescriptor)otherObj;
+ return otherDesc.getClassName().equals(this.getClassName()) &&
+ otherDesc.getTestName().equals(this.getTestName());
+
+ }
+ return false;
+ }
+
+ /**
+ * Override parent to return a more user-friendly display string
+ */
+ @Override
+ public String toString() {
+ return getClassName() + "#" + getTestName();
+ }
+ }
+}
diff --git a/tests/CoreTests/android/test/suitebuilder/SmokeTestSuiteBuilderTest.java b/tests/CoreTests/android/test/suitebuilder/SmokeTestSuiteBuilderTest.java
new file mode 100644
index 0000000..f817297
--- /dev/null
+++ b/tests/CoreTests/android/test/suitebuilder/SmokeTestSuiteBuilderTest.java
@@ -0,0 +1,34 @@
+/*
+ * 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 android.test.suitebuilder;
+
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+
+import java.util.List;
+
+public class SmokeTestSuiteBuilderTest extends TestCase {
+
+ public void testShouldOnlyIncludeSmokeTests() throws Exception {
+ TestSuite testSuite = new SmokeTestSuiteBuilder(getClass())
+ .includeAllPackagesUnderHere().build();
+
+ List<String> testCaseNames = ListTestCaseNames.getTestCaseNames(testSuite);
+ assertEquals("Unexpected number of smoke tests.", 1, testCaseNames.size());
+ assertEquals("Unexpected test name", "testSmoke", testCaseNames.get(0));
+ }
+}
diff --git a/tests/CoreTests/android/test/suitebuilder/TestSuiteBuilderTest.java b/tests/CoreTests/android/test/suitebuilder/TestSuiteBuilderTest.java
new file mode 100644
index 0000000..293c813
--- /dev/null
+++ b/tests/CoreTests/android/test/suitebuilder/TestSuiteBuilderTest.java
@@ -0,0 +1,218 @@
+/*
+ * 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 android.test.suitebuilder;
+
+import com.android.internal.util.Predicate;
+import static android.test.suitebuilder.ListTestCaseNames.getTestCaseNames;
+import android.test.suitebuilder.examples.OuterTest;
+import android.test.suitebuilder.examples.suppress.SuppressedTest;
+import android.test.suitebuilder.examples.error.ErrorTest;
+import android.test.suitebuilder.examples.error.FailingTest;
+import android.test.suitebuilder.examples.nested.Level1Test;
+import android.test.suitebuilder.examples.nested.nested.Level2Test;
+import android.test.suitebuilder.examples.simple.SimpleTest;
+import android.test.suitebuilder.examples.subclass.SubclassTest;
+import junit.framework.AssertionFailedError;
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestListener;
+import junit.framework.TestResult;
+import junit.framework.TestSuite;
+
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+
+public class TestSuiteBuilderTest extends TestCase {
+
+ private TestSuiteBuilder testSuiteBuilder;
+
+ protected void setUp() throws Exception {
+ super.setUp();
+ testSuiteBuilder = new TestSuiteBuilder(getClass());
+ }
+
+ public void testShouldRunSimpleTests() throws Exception {
+ testSuiteBuilder.includePackages(packageFor(SimpleTest.class));
+
+ SuiteExecutionRecorder recorder = runSuite(testSuiteBuilder);
+
+ assertTrue(recorder.passed("SimpleTest.testSimpleOne"));
+ assertTrue(recorder.passed("SimpleTest.testSimpleTwo"));
+ assertTrue(recorder.passed("AnotherSimpleTest.testAnotherOne"));
+ }
+
+ public void testShouldOnlyIncludeTestsThatSatisfyAllPredicates() throws Exception {
+ testSuiteBuilder.includePackages(packageFor(SimpleTest.class))
+ .addRequirements(testsWhoseNameContains("test"))
+ .addRequirements(testsWhoseNameContains("Simple"))
+ .addRequirements(testsWhoseNameContains("Two"));
+
+ SuiteExecutionRecorder recorder = runSuite(testSuiteBuilder);
+
+ assertTrue(recorder.passed("SimpleTest.testSimpleTwo"));
+ }
+
+ public void testShouldAddFailingTestsToSuite() throws Exception {
+ testSuiteBuilder.includePackages(packageFor(FailingTest.class));
+
+ SuiteExecutionRecorder recorder = runSuite(testSuiteBuilder);
+
+ assertTrue(recorder.failed("FailingTest.testFailOne"));
+ assertTrue(recorder.failed("FailingTest.testFailTwo"));
+ }
+
+ public void testShouldAddTestsWithErrorsToSuite() throws Exception {
+ testSuiteBuilder.includePackages(packageFor(ErrorTest.class));
+
+ SuiteExecutionRecorder recorder = runSuite(testSuiteBuilder);
+
+ assertTrue(recorder.errored("ErrorTest.testErrorOne"));
+ assertTrue(recorder.errored("ErrorTest.testErrorTwo"));
+ }
+
+ public void testShouldRunTestsInheritedFromSuperclass() throws Exception {
+ testSuiteBuilder.includePackages(packageFor(SubclassTest.class));
+
+ SuiteExecutionRecorder recorder = runSuite(testSuiteBuilder);
+
+ assertEquals(2, getTestCaseNames(testSuiteBuilder.build()).size());
+
+ assertTrue(recorder.passed("SubclassTest.testSubclass"));
+ assertTrue(recorder.passed("SubclassTest.testSuperclass"));
+ assertFalse(recorder.saw("SuperclassTest.testSuperclass"));
+ }
+
+ public void testShouldIncludeTestsInSubPackagesRecursively() throws Exception {
+ testSuiteBuilder.includePackages(packageFor(Level1Test.class));
+
+ SuiteExecutionRecorder recorder = runSuite(testSuiteBuilder);
+
+ assertTrue(recorder.passed("Level1Test.testLevel1"));
+ assertTrue(recorder.passed("Level2Test.testLevel2"));
+ }
+
+ public void testExcludePackage() throws Exception {
+ testSuiteBuilder.includePackages(packageFor(SimpleTest.class),
+ packageFor(Level1Test.class)).excludePackages(packageFor(Level2Test.class));
+
+ TestSuite testSuite = testSuiteBuilder.build();
+ assertContentsInOrder(getTestCaseNames(testSuite),
+ "testLevel1", "testAnotherOne", "testSimpleOne", "testSimpleTwo");
+ }
+
+ public void testShouldExcludeSuppressedTests() throws Exception {
+ testSuiteBuilder.includePackages(packageFor(SuppressedTest.class));
+ testSuiteBuilder.build();
+
+ SuiteExecutionRecorder recorder = runSuite(testSuiteBuilder);
+
+ assertEquals(1, recorder.testsSeen.size());
+ assertTrue(recorder.passed("PartiallySuppressedTest.testUnSuppressedMethod"));
+ }
+
+ /**
+ * This test calls {@link OuterTest#buildTestsUnderHereRecursively()} to control
+ * the packages under test. The call to {@link TestSuiteBuilder#includeAllPackagesUnderHere()}
+ * is made from there so that only return the example tests.
+ */
+ public void testIncludeAllPackagesUnderHere() throws Exception {
+
+ TestSuite testSuite = new OuterTest().buildTestsUnderHereRecursively();
+ assertContentsInOrder(getTestCaseNames(testSuite),
+ "testOuter", "testErrorOne", "testErrorTwo", "testFailOne", "testFailTwo",
+ "testInstrumentation", "testLevel1", "testLevel2", "testAnotherOne",
+ "testSimpleOne", "testSimpleTwo", "testNonSmoke", "testSmoke", "testSubclass",
+ "testSuperclass", "testUnSuppressedMethod");
+ }
+
+ private void assertContentsInOrder(List<String> actual, String... source) {
+ String[] clonedSource = source.clone();
+ assertEquals("Unexpected number of items.", clonedSource.length, actual.size());
+ for (int i = 0; i < actual.size(); i++) {
+ String actualItem = actual.get(i);
+ String sourceItem = clonedSource[i];
+ assertEquals("Unexpected item. Index: " + i, sourceItem, actualItem);
+ }
+ }
+
+ private static String packageFor(Class clazz) {
+ String className = clazz.getName();
+ return className.substring(0, className.lastIndexOf('.'));
+ }
+
+ private Predicate<TestMethod> testsWhoseNameContains(final String string) {
+ return new Predicate<TestMethod>() {
+ public boolean apply(TestMethod testMethod) {
+ return testMethod.getName().contains(string);
+ }
+ };
+ }
+
+ private SuiteExecutionRecorder runSuite(TestSuiteBuilder builder) {
+ TestSuite suite = builder.build();
+ SuiteExecutionRecorder recorder = new SuiteExecutionRecorder();
+ TestResult result = new TestResult();
+ result.addListener(recorder);
+ suite.run(result);
+ return recorder;
+ }
+
+ private class SuiteExecutionRecorder implements TestListener {
+
+ private Set<String> failures = new HashSet<String>();
+ private Set<String> errors = new HashSet<String>();
+ private Set<String> testsSeen = new HashSet<String>();
+
+ public void addError(Test test, Throwable t) {
+ errors.add(testName(test));
+ }
+
+ public void addFailure(Test test, AssertionFailedError t) {
+ failures.add(testName(test));
+ }
+
+ public void endTest(Test test) {
+ }
+
+ public void startTest(Test test) {
+ testsSeen.add(testName(test));
+ }
+
+ public boolean saw(String testName) {
+ return testsSeen.contains(testName);
+ }
+
+ public boolean failed(String testName) {
+ return failures.contains(testName);
+ }
+
+ public boolean errored(String testName) {
+ return errors.contains(testName);
+ }
+
+ public boolean passed(String testName) {
+ return saw(testName) && !failed(testName) && !errored(testName);
+ }
+
+ private String testName(Test test) {
+ TestCase testCase = (TestCase) test;
+ return testCase.getClass().getSimpleName() + "." + testCase.getName();
+ }
+ }
+}
diff --git a/tests/CoreTests/android/test/suitebuilder/UnitTestSuiteBuilderTest.java b/tests/CoreTests/android/test/suitebuilder/UnitTestSuiteBuilderTest.java
new file mode 100644
index 0000000..469938e
--- /dev/null
+++ b/tests/CoreTests/android/test/suitebuilder/UnitTestSuiteBuilderTest.java
@@ -0,0 +1,109 @@
+/*
+ * 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 android.test.suitebuilder;
+
+import android.test.suitebuilder.examples.instrumentation.InstrumentationTest;
+
+import junit.framework.Assert;
+import junit.framework.AssertionFailedError;
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestListener;
+import junit.framework.TestResult;
+import junit.framework.TestSuite;
+
+import java.util.HashSet;
+import java.util.Set;
+
+public class UnitTestSuiteBuilderTest extends TestCase {
+
+ private UnitTestSuiteBuilder unitTestSuiteBuilder;
+
+ protected void setUp() throws Exception {
+ super.setUp();
+ unitTestSuiteBuilder = new UnitTestSuiteBuilder(getClass());
+ }
+
+ public void testShouldExcludeIntrumentationTests() throws Exception {
+ unitTestSuiteBuilder.includePackages(packageFor(InstrumentationTest.class));
+
+ TestSuite testSuite = unitTestSuiteBuilder.build();
+ Assert.assertEquals(0, ListTestCaseNames.getTestCaseNames(testSuite).size());
+
+ SuiteExecutionRecorder recorder = runSuite(unitTestSuiteBuilder);
+
+ assertFalse(recorder.saw("InstrumentationTest.testInstrumentation"));
+ assertTrue(recorder.testsSeen.isEmpty());
+ }
+
+ private static String packageFor(Class clazz) {
+ String className = clazz.getName();
+ return className.substring(0, className.lastIndexOf('.'));
+ }
+
+ private SuiteExecutionRecorder runSuite(TestSuiteBuilder builder) {
+ TestSuite suite = builder.build();
+ SuiteExecutionRecorder recorder = new SuiteExecutionRecorder();
+ TestResult result = new TestResult();
+ result.addListener(recorder);
+ suite.run(result);
+ return recorder;
+ }
+
+ private class SuiteExecutionRecorder implements TestListener {
+
+ private Set<String> failures = new HashSet<String>();
+ private Set<String> errors = new HashSet<String>();
+ private Set<String> testsSeen = new HashSet<String>();
+
+ public void addError(Test test, Throwable t) {
+ errors.add(testName(test));
+ }
+
+ public void addFailure(Test test, AssertionFailedError t) {
+ failures.add(testName(test));
+ }
+
+ public void endTest(Test test) {
+ }
+
+ public void startTest(Test test) {
+ testsSeen.add(testName(test));
+ }
+
+ public boolean saw(String testName) {
+ return testsSeen.contains(testName);
+ }
+
+ public boolean failed(String testName) {
+ return failures.contains(testName);
+ }
+
+ public boolean errored(String testName) {
+ return errors.contains(testName);
+ }
+
+ public boolean passed(String testName) {
+ return saw(testName) && !failed(testName) && !errored(testName);
+ }
+
+ private String testName(Test test) {
+ TestCase testCase = (TestCase) test;
+ return testCase.getClass().getSimpleName() + "." + testCase.getName();
+ }
+ }
+}
diff --git a/tests/CoreTests/android/test/suitebuilder/annotation/HasAnnotationTest.java b/tests/CoreTests/android/test/suitebuilder/annotation/HasAnnotationTest.java
new file mode 100644
index 0000000..edf067d
--- /dev/null
+++ b/tests/CoreTests/android/test/suitebuilder/annotation/HasAnnotationTest.java
@@ -0,0 +1,76 @@
+/*
+ * 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 android.test.suitebuilder.annotation;
+
+import android.test.suitebuilder.TestMethod;
+import junit.framework.TestCase;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+import java.lang.reflect.Method;
+
+public class HasAnnotationTest extends TestCase {
+
+ public void testThatMethodWithAnnotationIsReportedAsBeingAnnotated() throws Exception {
+ assertTrue(hasExampleAnnotation(ClassWithAnnotation.class, "testWithAnnotation"));
+ assertTrue(hasExampleAnnotation(ClassWithoutAnnotation.class, "testWithAnnotation"));
+ }
+
+ public void testThatMethodWithOutAnnotationIsNotReportedAsBeingAnnotated() throws Exception {
+ assertFalse(hasExampleAnnotation(ClassWithoutAnnotation.class, "testWithoutAnnotation"));
+ }
+
+ public void testThatClassAnnotatioCausesAllMethodsToBeReportedAsBeingAnnotated()
+ throws Exception {
+ assertTrue(hasExampleAnnotation(ClassWithAnnotation.class, "testWithoutAnnotation"));
+ }
+
+ private boolean hasExampleAnnotation(Class<? extends TestCase> aClass, String methodName)
+ throws NoSuchMethodException {
+ Method method = aClass.getMethod(methodName);
+ TestMethod testMethod = new TestMethod(method, aClass);
+ return new HasAnnotation(Example.class).apply(testMethod);
+ }
+
+ @Retention(RetentionPolicy.RUNTIME)
+ @Target({ElementType.TYPE, ElementType.METHOD})
+ public @interface Example {
+ }
+
+ @Example
+ static class ClassWithAnnotation extends TestCase {
+
+ @Example
+ public void testWithAnnotation() {
+ }
+
+ public void testWithoutAnnotation() {
+ }
+ }
+
+ static class ClassWithoutAnnotation extends TestCase {
+
+ @Example
+ public void testWithAnnotation() {
+ }
+
+ public void testWithoutAnnotation() {
+ }
+ }
+}
diff --git a/tests/CoreTests/android/test/suitebuilder/annotation/HasClassAnnotationTest.java b/tests/CoreTests/android/test/suitebuilder/annotation/HasClassAnnotationTest.java
new file mode 100644
index 0000000..051ea54
--- /dev/null
+++ b/tests/CoreTests/android/test/suitebuilder/annotation/HasClassAnnotationTest.java
@@ -0,0 +1,57 @@
+/*
+ * 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 android.test.suitebuilder.annotation;
+
+import android.test.suitebuilder.TestMethod;
+import junit.framework.TestCase;
+
+import java.lang.reflect.Method;
+
+public class HasClassAnnotationTest extends TestCase {
+
+ public void testShouldTellIfParentClassHasSpecifiedClassification()
+ throws NoSuchMethodException {
+ assertTrue(classHasAnnotation(SmokeTestExample.class, Smoke.class));
+ }
+
+ public void testShouldTellIfParentClassDoesNotHaveSpecifiedClassification()
+ throws NoSuchMethodException {
+ assertFalse(classHasAnnotation(NonSmokeTestExample.class, Smoke.class));
+ }
+
+ private boolean classHasAnnotation(
+ Class<? extends TestCase> aClass,
+ Class<Smoke> expectedClassification) throws NoSuchMethodException {
+ Method method = aClass.getMethod("testSomeTest");
+
+ TestMethod testMethod = new TestMethod(method, aClass);
+ return new HasClassAnnotation(expectedClassification).apply(testMethod);
+ }
+
+ @Smoke
+ static class SmokeTestExample extends TestCase {
+
+ public void testSomeTest() {
+ }
+ }
+
+ static class NonSmokeTestExample extends TestCase {
+
+ public void testSomeTest() {
+ }
+ }
+}
diff --git a/tests/CoreTests/android/test/suitebuilder/annotation/HasMethodAnnotationTest.java b/tests/CoreTests/android/test/suitebuilder/annotation/HasMethodAnnotationTest.java
new file mode 100644
index 0000000..c864e28
--- /dev/null
+++ b/tests/CoreTests/android/test/suitebuilder/annotation/HasMethodAnnotationTest.java
@@ -0,0 +1,56 @@
+/*
+ * 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 android.test.suitebuilder.annotation;
+
+import android.test.suitebuilder.TestMethod;
+import junit.framework.TestCase;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Method;
+
+
+public class HasMethodAnnotationTest extends TestCase {
+
+ public void testMethodWithSpecifiedAttribute() throws Exception {
+ assertTrue(methodHasAnnotation(AnnotatedMethodExample.class,
+ "testThatIsAnnotated", Smoke.class));
+ }
+
+ public void testMethodWithoutSpecifiedAttribute() throws Exception {
+ assertFalse(methodHasAnnotation(AnnotatedMethodExample.class,
+ "testThatIsNotAnnotated", Smoke.class));
+ }
+
+ private boolean methodHasAnnotation(Class<? extends TestCase> aClass,
+ String methodName,
+ Class<? extends Annotation> expectedClassification
+ ) throws NoSuchMethodException {
+ Method method = aClass.getMethod(methodName);
+ TestMethod testMethod = new TestMethod(method, aClass);
+ return new HasMethodAnnotation(expectedClassification).apply(testMethod);
+ }
+
+ static class AnnotatedMethodExample extends TestCase {
+
+ @Smoke
+ public void testThatIsAnnotated() {
+ }
+
+ public void testThatIsNotAnnotated() {
+ }
+ }
+}
diff --git a/tests/CoreTests/android/test/suitebuilder/examples/OuterTest.java b/tests/CoreTests/android/test/suitebuilder/examples/OuterTest.java
new file mode 100644
index 0000000..4659bf9
--- /dev/null
+++ b/tests/CoreTests/android/test/suitebuilder/examples/OuterTest.java
@@ -0,0 +1,37 @@
+/*
+ * 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 android.test.suitebuilder.examples;
+
+import android.test.suitebuilder.TestSuiteBuilder;
+
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+
+public class OuterTest extends TestCase {
+
+ public void testOuter() {
+ assertTrue(true);
+ }
+
+ public TestSuite buildTestsUnderHereRecursively() {
+ return buildTestsUnderHereWith(new TestSuiteBuilder(getClass()));
+ }
+
+ public TestSuite buildTestsUnderHereWith(TestSuiteBuilder testSuiteBuilder) {
+ return testSuiteBuilder.includeAllPackagesUnderHere().build();
+ }
+}
diff --git a/tests/CoreTests/android/test/suitebuilder/examples/error/ErrorTest.java b/tests/CoreTests/android/test/suitebuilder/examples/error/ErrorTest.java
new file mode 100644
index 0000000..f1f6113
--- /dev/null
+++ b/tests/CoreTests/android/test/suitebuilder/examples/error/ErrorTest.java
@@ -0,0 +1,30 @@
+/*
+ * 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 android.test.suitebuilder.examples.error;
+
+import junit.framework.TestCase;
+
+public class ErrorTest extends TestCase {
+
+ public void testErrorOne() throws Exception {
+ throw new RuntimeException("Expected");
+ }
+
+ public void testErrorTwo() throws Exception {
+ throw new RuntimeException("Expected");
+ }
+}
diff --git a/tests/CoreTests/android/test/suitebuilder/examples/error/FailingTest.java b/tests/CoreTests/android/test/suitebuilder/examples/error/FailingTest.java
new file mode 100644
index 0000000..428fd23
--- /dev/null
+++ b/tests/CoreTests/android/test/suitebuilder/examples/error/FailingTest.java
@@ -0,0 +1,30 @@
+/*
+ * 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 android.test.suitebuilder.examples.error;
+
+import junit.framework.TestCase;
+
+public class FailingTest extends TestCase {
+
+ public void testFailOne() throws Exception {
+ fail("Expected");
+ }
+
+ public void testFailTwo() throws Exception {
+ fail("Expected");
+ }
+}
diff --git a/tests/CoreTests/android/test/suitebuilder/examples/instrumentation/InstrumentationTest.java b/tests/CoreTests/android/test/suitebuilder/examples/instrumentation/InstrumentationTest.java
new file mode 100644
index 0000000..5158a90
--- /dev/null
+++ b/tests/CoreTests/android/test/suitebuilder/examples/instrumentation/InstrumentationTest.java
@@ -0,0 +1,26 @@
+/*
+ * 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 android.test.suitebuilder.examples.instrumentation;
+
+import android.test.InstrumentationTestCase;
+
+public class InstrumentationTest extends InstrumentationTestCase {
+
+ public void testInstrumentation() throws Exception {
+ assertTrue(true);
+ }
+}
diff --git a/tests/CoreTests/android/test/suitebuilder/examples/nested/Level1Test.java b/tests/CoreTests/android/test/suitebuilder/examples/nested/Level1Test.java
new file mode 100644
index 0000000..17d39d6
--- /dev/null
+++ b/tests/CoreTests/android/test/suitebuilder/examples/nested/Level1Test.java
@@ -0,0 +1,26 @@
+/*
+ * 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 android.test.suitebuilder.examples.nested;
+
+import junit.framework.TestCase;
+
+public class Level1Test extends TestCase {
+
+ public void testLevel1() throws Exception {
+ assertTrue(true);
+ }
+}
diff --git a/tests/CoreTests/android/test/suitebuilder/examples/nested/nested/Level2Test.java b/tests/CoreTests/android/test/suitebuilder/examples/nested/nested/Level2Test.java
new file mode 100644
index 0000000..6f0daca
--- /dev/null
+++ b/tests/CoreTests/android/test/suitebuilder/examples/nested/nested/Level2Test.java
@@ -0,0 +1,26 @@
+/*
+ * 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 android.test.suitebuilder.examples.nested.nested;
+
+import junit.framework.TestCase;
+
+public class Level2Test extends TestCase {
+
+ public void testLevel2() throws Exception {
+ assertTrue(true);
+ }
+}
diff --git a/tests/CoreTests/android/test/suitebuilder/examples/simple/AnotherSimpleTest.java b/tests/CoreTests/android/test/suitebuilder/examples/simple/AnotherSimpleTest.java
new file mode 100644
index 0000000..0dfeda8
--- /dev/null
+++ b/tests/CoreTests/android/test/suitebuilder/examples/simple/AnotherSimpleTest.java
@@ -0,0 +1,26 @@
+/*
+ * 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 android.test.suitebuilder.examples.simple;
+
+import junit.framework.TestCase;
+
+public class AnotherSimpleTest extends TestCase {
+
+ public void testAnotherOne() throws Exception {
+ assertTrue(true);
+ }
+}
diff --git a/tests/CoreTests/android/test/suitebuilder/examples/simple/SimpleTest.java b/tests/CoreTests/android/test/suitebuilder/examples/simple/SimpleTest.java
new file mode 100644
index 0000000..4dcac44
--- /dev/null
+++ b/tests/CoreTests/android/test/suitebuilder/examples/simple/SimpleTest.java
@@ -0,0 +1,30 @@
+/*
+ * 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 android.test.suitebuilder.examples.simple;
+
+import junit.framework.TestCase;
+
+public class SimpleTest extends TestCase {
+
+ public void testSimpleOne() throws Exception {
+ assertTrue(true);
+ }
+
+ public void testSimpleTwo() throws Exception {
+ assertTrue(true);
+ }
+}
diff --git a/tests/CoreTests/android/test/suitebuilder/examples/smoke/NonSmokeTest.java b/tests/CoreTests/android/test/suitebuilder/examples/smoke/NonSmokeTest.java
new file mode 100644
index 0000000..1512ba7
--- /dev/null
+++ b/tests/CoreTests/android/test/suitebuilder/examples/smoke/NonSmokeTest.java
@@ -0,0 +1,26 @@
+/*
+ * 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 android.test.suitebuilder.examples.smoke;
+
+import junit.framework.TestCase;
+
+public class NonSmokeTest extends TestCase {
+
+ public void testNonSmoke() throws Exception {
+ assertTrue(true);
+ }
+}
diff --git a/tests/CoreTests/android/test/suitebuilder/examples/smoke/SmokeTest.java b/tests/CoreTests/android/test/suitebuilder/examples/smoke/SmokeTest.java
new file mode 100644
index 0000000..c3515df
--- /dev/null
+++ b/tests/CoreTests/android/test/suitebuilder/examples/smoke/SmokeTest.java
@@ -0,0 +1,28 @@
+/*
+ * 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 android.test.suitebuilder.examples.smoke;
+
+import android.test.suitebuilder.annotation.Smoke;
+import junit.framework.TestCase;
+
+@Smoke
+public class SmokeTest extends TestCase {
+
+ public void testSmoke() throws Exception {
+ assertTrue(true);
+ }
+}
diff --git a/tests/CoreTests/android/test/suitebuilder/examples/subclass/SubclassTest.java b/tests/CoreTests/android/test/suitebuilder/examples/subclass/SubclassTest.java
new file mode 100644
index 0000000..0ab8c72
--- /dev/null
+++ b/tests/CoreTests/android/test/suitebuilder/examples/subclass/SubclassTest.java
@@ -0,0 +1,24 @@
+/*
+ * 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 android.test.suitebuilder.examples.subclass;
+
+public class SubclassTest extends SuperclassTest {
+
+ public void testSubclass() throws Exception {
+ assertTrue(true);
+ }
+}
diff --git a/tests/CoreTests/android/test/suitebuilder/examples/subclass/SuperclassTest.java b/tests/CoreTests/android/test/suitebuilder/examples/subclass/SuperclassTest.java
new file mode 100644
index 0000000..05513c5
--- /dev/null
+++ b/tests/CoreTests/android/test/suitebuilder/examples/subclass/SuperclassTest.java
@@ -0,0 +1,26 @@
+/*
+ * 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 android.test.suitebuilder.examples.subclass;
+
+import junit.framework.TestCase;
+
+public abstract class SuperclassTest extends TestCase {
+
+ public void testSuperclass() throws Exception {
+ assertTrue(true);
+ }
+}
diff --git a/tests/CoreTests/android/test/suitebuilder/examples/suppress/PartiallySuppressedTest.java b/tests/CoreTests/android/test/suitebuilder/examples/suppress/PartiallySuppressedTest.java
new file mode 100644
index 0000000..3ca0f70
--- /dev/null
+++ b/tests/CoreTests/android/test/suitebuilder/examples/suppress/PartiallySuppressedTest.java
@@ -0,0 +1,33 @@
+/*
+ * 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 android.test.suitebuilder.examples.suppress;
+
+import android.test.suitebuilder.annotation.Suppress;
+
+import junit.framework.TestCase;
+
+public class PartiallySuppressedTest extends TestCase {
+
+ @Suppress
+ public void testSuppressedMethod() throws Exception {
+ assertTrue(true);
+ }
+
+ public void testUnSuppressedMethod() throws Exception {
+ assertTrue(true);
+ }
+}
diff --git a/tests/CoreTests/android/test/suitebuilder/examples/suppress/SuppressedTest.java b/tests/CoreTests/android/test/suitebuilder/examples/suppress/SuppressedTest.java
new file mode 100644
index 0000000..c4e0e07
--- /dev/null
+++ b/tests/CoreTests/android/test/suitebuilder/examples/suppress/SuppressedTest.java
@@ -0,0 +1,29 @@
+/*
+ * 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 android.test.suitebuilder.examples.suppress;
+
+import android.test.suitebuilder.annotation.Suppress;
+
+import junit.framework.TestCase;
+
+@Suppress
+public class SuppressedTest extends TestCase {
+
+ public void testSuppressedClass() throws Exception {
+ assertTrue(true);
+ }
+}
diff --git a/tests/CoreTests/android/util/DayOfMonthCursorTest.java b/tests/CoreTests/android/util/DayOfMonthCursorTest.java
new file mode 100644
index 0000000..4c5ad76
--- /dev/null
+++ b/tests/CoreTests/android/util/DayOfMonthCursorTest.java
@@ -0,0 +1,157 @@
+/*
+ * Copyright (C) 2007 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 android.util;
+
+import junit.framework.TestCase;
+
+import java.util.Calendar;
+import android.test.suitebuilder.annotation.SmallTest;
+
+/**
+ * Unit tests for {@link DayOfMonthCursor}.
+ */
+public class DayOfMonthCursorTest extends TestCase {
+
+ @SmallTest
+ public void testMonthRows() {
+ DayOfMonthCursor mc = new DayOfMonthCursor(2007,
+ Calendar.SEPTEMBER, 11, Calendar.SUNDAY);
+
+ assertArraysEqual(new int[]{26, 27, 28, 29, 30, 31, 1},
+ mc.getDigitsForRow(0));
+ assertArraysEqual(new int[]{2, 3, 4, 5, 6, 7, 8},
+ mc.getDigitsForRow(1));
+ assertArraysEqual(new int[]{30, 1, 2, 3, 4, 5, 6},
+ mc.getDigitsForRow(5));
+ }
+
+ @SmallTest
+ public void testMoveLeft() {
+ DayOfMonthCursor mc = new DayOfMonthCursor(2007,
+ Calendar.SEPTEMBER, 3, Calendar.SUNDAY);
+
+ assertEquals(Calendar.SEPTEMBER, mc.getMonth());
+ assertEquals(3, mc.getSelectedDayOfMonth());
+ assertEquals(1, mc.getSelectedRow());
+ assertEquals(1, mc.getSelectedColumn());
+
+ // move left, still same row
+ assertFalse(mc.left());
+ assertEquals(2, mc.getSelectedDayOfMonth());
+ assertEquals(1, mc.getSelectedRow());
+ assertEquals(0, mc.getSelectedColumn());
+
+ // wrap over to previous column, same month
+ assertFalse(mc.left());
+ assertEquals(1, mc.getSelectedDayOfMonth());
+ assertEquals(0, mc.getSelectedRow());
+ assertEquals(6, mc.getSelectedColumn());
+
+ // wrap to previous month
+ assertTrue(mc.left());
+ assertEquals(Calendar.AUGUST, mc.getMonth());
+ assertEquals(31, mc.getSelectedDayOfMonth());
+ assertEquals(4, mc.getSelectedRow());
+ assertEquals(5, mc.getSelectedColumn());
+ }
+
+ @SmallTest
+ public void testMoveRight() {
+ DayOfMonthCursor mc = new DayOfMonthCursor(2007,
+ Calendar.SEPTEMBER, 28, Calendar.SUNDAY);
+
+ assertEquals(Calendar.SEPTEMBER, mc.getMonth());
+ assertEquals(28, mc.getSelectedDayOfMonth());
+ assertEquals(4, mc.getSelectedRow());
+ assertEquals(5, mc.getSelectedColumn());
+
+ // same row
+ assertFalse(mc.right());
+ assertEquals(29, mc.getSelectedDayOfMonth());
+ assertEquals(4, mc.getSelectedRow());
+ assertEquals(6, mc.getSelectedColumn());
+
+ // wrap to next column, same month
+ assertFalse(mc.right());
+ assertEquals(30, mc.getSelectedDayOfMonth());
+ assertEquals(5, mc.getSelectedRow());
+ assertEquals(0, mc.getSelectedColumn());
+
+ // next month
+ assertTrue(mc.right());
+ assertEquals(Calendar.OCTOBER, mc.getMonth());
+ assertEquals(1, mc.getSelectedDayOfMonth());
+ assertEquals(0, mc.getSelectedRow());
+ assertEquals(1, mc.getSelectedColumn());
+ }
+
+ @SmallTest
+ public void testMoveUp() {
+ DayOfMonthCursor mc = new DayOfMonthCursor(2007,
+ Calendar.SEPTEMBER, 13, Calendar.SUNDAY);
+
+ assertEquals(Calendar.SEPTEMBER, mc.getMonth());
+ assertEquals(13, mc.getSelectedDayOfMonth());
+ assertEquals(2, mc.getSelectedRow());
+ assertEquals(4, mc.getSelectedColumn());
+
+ // up, same month
+ assertFalse(mc.up());
+ assertEquals(6, mc.getSelectedDayOfMonth());
+ assertEquals(1, mc.getSelectedRow());
+ assertEquals(4, mc.getSelectedColumn());
+
+ // up, flips back
+ assertTrue(mc.up());
+ assertEquals(Calendar.AUGUST, mc.getMonth());
+ assertEquals(30, mc.getSelectedDayOfMonth());
+ assertEquals(4, mc.getSelectedRow());
+ assertEquals(4, mc.getSelectedColumn());
+ }
+
+ @SmallTest
+ public void testMoveDown() {
+ DayOfMonthCursor mc = new DayOfMonthCursor(2007,
+ Calendar.SEPTEMBER, 23, Calendar.SUNDAY);
+
+ assertEquals(Calendar.SEPTEMBER, mc.getMonth());
+ assertEquals(23, mc.getSelectedDayOfMonth());
+ assertEquals(4, mc.getSelectedRow());
+ assertEquals(0, mc.getSelectedColumn());
+
+ // down, same month
+ assertFalse(mc.down());
+ assertEquals(30, mc.getSelectedDayOfMonth());
+ assertEquals(5, mc.getSelectedRow());
+ assertEquals(0, mc.getSelectedColumn());
+
+ // down, next month
+ assertTrue(mc.down());
+ assertEquals(Calendar.OCTOBER, mc.getMonth());
+ assertEquals(7, mc.getSelectedDayOfMonth());
+ assertEquals(1, mc.getSelectedRow());
+ assertEquals(0, mc.getSelectedColumn());
+ }
+
+ private void assertArraysEqual(int[] expected, int[] actual) {
+ assertEquals("array length", expected.length, actual.length);
+ for (int i = 0; i < expected.length; i++) {
+ assertEquals("index " + i,
+ expected[i], actual[i]);
+ }
+ }
+}
diff --git a/tests/CoreTests/android/util/FloatMathTest.java b/tests/CoreTests/android/util/FloatMathTest.java
new file mode 100644
index 0000000..f479e2b
--- /dev/null
+++ b/tests/CoreTests/android/util/FloatMathTest.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2007 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 android.util;
+
+import junit.framework.TestCase;
+import android.test.suitebuilder.annotation.SmallTest;
+
+public class FloatMathTest extends TestCase {
+
+ @SmallTest
+ public void testSqrt() {
+ assertEquals(7, FloatMath.sqrt(49), 0);
+ assertEquals(10, FloatMath.sqrt(100), 0);
+ assertEquals(0, FloatMath.sqrt(0), 0);
+ assertEquals(1, FloatMath.sqrt(1), 0);
+ }
+
+ @SmallTest
+ public void testFloor() {
+ assertEquals(78, FloatMath.floor(78.89f), 0);
+ assertEquals(-79, FloatMath.floor(-78.89f), 0);
+ }
+
+ @SmallTest
+ public void testCeil() {
+ assertEquals(79, FloatMath.ceil(78.89f), 0);
+ assertEquals(-78, FloatMath.ceil(-78.89f), 0);
+ }
+
+ @SmallTest
+ public void testSin() {
+ assertEquals(0.0, FloatMath.sin(0), 0);
+ assertEquals(0.8414709848078965f, FloatMath.sin(1), 0);
+ }
+
+ @SmallTest
+ public void testCos() {
+ assertEquals(1.0f, FloatMath.cos(0), 0);
+ assertEquals(0.5403023058681398f, FloatMath.cos(1), 0);
+ }
+}
diff --git a/tests/CoreTests/android/util/MonthDisplayHelperTest.java b/tests/CoreTests/android/util/MonthDisplayHelperTest.java
new file mode 100644
index 0000000..5207ad9
--- /dev/null
+++ b/tests/CoreTests/android/util/MonthDisplayHelperTest.java
@@ -0,0 +1,211 @@
+/*
+ * Copyright (C) 2007 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 android.util;
+
+import junit.framework.TestCase;
+import junit.framework.Test;
+import junit.framework.TestSuite;
+
+import java.util.Calendar;
+import android.test.suitebuilder.annotation.SmallTest;
+import android.test.suitebuilder.annotation.MediumTest;
+
+/**
+ * Unit tests for {@link MonthDisplayHelper}.
+ */
+public class MonthDisplayHelperTest extends TestCase {
+
+
+ @SmallTest
+ public void testFirstDayOfMonth() {
+
+ assertEquals("august 2007",
+ Calendar.WEDNESDAY,
+ new MonthDisplayHelper(2007, Calendar.AUGUST).getFirstDayOfMonth());
+
+ assertEquals("september, 2007",
+ Calendar.SATURDAY,
+ new MonthDisplayHelper(2007, Calendar.SEPTEMBER).getFirstDayOfMonth());
+ }
+
+ @MediumTest
+ public void testNumberOfDaysInCurrentMonth() {
+ assertEquals(30,
+ new MonthDisplayHelper(2007, Calendar.SEPTEMBER).getNumberOfDaysInMonth());
+ }
+
+ @SmallTest
+ public void testMonthRows() {
+ MonthDisplayHelper helper = new MonthDisplayHelper(2007, Calendar.SEPTEMBER);
+
+ assertArraysEqual(new int[]{26, 27, 28, 29, 30, 31, 1},
+ helper.getDigitsForRow(0));
+ assertArraysEqual(new int[]{2, 3, 4, 5, 6, 7, 8},
+ helper.getDigitsForRow(1));
+ assertArraysEqual(new int[]{30, 1, 2, 3, 4, 5, 6},
+ helper.getDigitsForRow(5));
+
+ }
+
+ @SmallTest
+ public void testMonthRowsWeekStartsMonday() {
+ MonthDisplayHelper helper = new MonthDisplayHelper(2007,
+ Calendar.SEPTEMBER, Calendar.MONDAY);
+
+ assertArraysEqual(new int[]{27, 28, 29, 30, 31, 1, 2},
+ helper.getDigitsForRow(0));
+ assertArraysEqual(new int[]{3, 4, 5, 6, 7, 8, 9},
+ helper.getDigitsForRow(1));
+ assertArraysEqual(new int[]{24, 25, 26, 27, 28, 29, 30},
+ helper.getDigitsForRow(4));
+ assertArraysEqual(new int[]{1, 2, 3, 4, 5, 6, 7},
+ helper.getDigitsForRow(5));
+ }
+
+ @SmallTest
+ public void testMonthRowsWeekStartsSaturday() {
+ MonthDisplayHelper helper = new MonthDisplayHelper(2007,
+ Calendar.SEPTEMBER, Calendar.SATURDAY);
+
+ assertArraysEqual(new int[]{1, 2, 3, 4, 5, 6, 7},
+ helper.getDigitsForRow(0));
+ assertArraysEqual(new int[]{8, 9, 10, 11, 12, 13, 14},
+ helper.getDigitsForRow(1));
+ assertArraysEqual(new int[]{29, 30, 1, 2, 3, 4, 5},
+ helper.getDigitsForRow(4));
+
+
+ helper = new MonthDisplayHelper(2007,
+ Calendar.AUGUST, Calendar.SATURDAY);
+
+ assertArraysEqual(new int[]{28, 29, 30, 31, 1, 2, 3},
+ helper.getDigitsForRow(0));
+ assertArraysEqual(new int[]{4, 5, 6, 7, 8, 9, 10},
+ helper.getDigitsForRow(1));
+ assertArraysEqual(new int[]{25, 26, 27, 28, 29, 30, 31},
+ helper.getDigitsForRow(4));
+ }
+
+ @SmallTest
+ public void testGetDayAt() {
+ MonthDisplayHelper helper = new MonthDisplayHelper(2007,
+ Calendar.SEPTEMBER, Calendar.SUNDAY);
+
+ assertEquals(26, helper.getDayAt(0, 0));
+ assertEquals(1, helper.getDayAt(0, 6));
+ assertEquals(17, helper.getDayAt(3, 1));
+ assertEquals(2, helper.getDayAt(5, 2));
+ }
+
+ @SmallTest
+ public void testPrevMonth() {
+ MonthDisplayHelper helper = new MonthDisplayHelper(2007,
+ Calendar.SEPTEMBER, Calendar.SUNDAY);
+
+ assertArraysEqual(new int[]{26, 27, 28, 29, 30, 31, 1},
+ helper.getDigitsForRow(0));
+
+ helper.previousMonth();
+
+ assertEquals(Calendar.AUGUST, helper.getMonth());
+ assertArraysEqual(new int[]{29, 30, 31, 1, 2, 3, 4},
+ helper.getDigitsForRow(0));
+ }
+
+ @SmallTest
+ public void testPrevMonthRollOver() {
+ MonthDisplayHelper helper = new MonthDisplayHelper(2007,
+ Calendar.JANUARY);
+
+ helper.previousMonth();
+
+ assertEquals(2006, helper.getYear());
+ assertEquals(Calendar.DECEMBER, helper.getMonth());
+ }
+
+ @SmallTest
+ public void testNextMonth() {
+ MonthDisplayHelper helper = new MonthDisplayHelper(2007,
+ Calendar.AUGUST, Calendar.SUNDAY);
+
+ assertArraysEqual(new int[]{29, 30, 31, 1, 2, 3, 4},
+ helper.getDigitsForRow(0));
+
+ helper.nextMonth();
+
+ assertEquals(Calendar.SEPTEMBER, helper.getMonth());
+ assertArraysEqual(new int[]{26, 27, 28, 29, 30, 31, 1},
+ helper.getDigitsForRow(0));
+ }
+
+ @SmallTest
+ public void testGetRowOf() {
+ MonthDisplayHelper helper = new MonthDisplayHelper(2007,
+ Calendar.AUGUST, Calendar.SUNDAY);
+
+ assertEquals(0, helper.getRowOf(2));
+ assertEquals(0, helper.getRowOf(4));
+ assertEquals(2, helper.getRowOf(12));
+ assertEquals(2, helper.getRowOf(18));
+ assertEquals(3, helper.getRowOf(19));
+ }
+
+ @SmallTest
+ public void testGetColumnOf() {
+ MonthDisplayHelper helper = new MonthDisplayHelper(2007,
+ Calendar.AUGUST, Calendar.SUNDAY);
+
+ assertEquals(3, helper.getColumnOf(1));
+ assertEquals(4, helper.getColumnOf(9));
+ assertEquals(5, helper.getColumnOf(17));
+ assertEquals(6, helper.getColumnOf(25));
+ assertEquals(0, helper.getColumnOf(26));
+ }
+
+ @SmallTest
+ public void testWithinCurrentMonth() {
+ MonthDisplayHelper helper = new MonthDisplayHelper(2007,
+ Calendar.SEPTEMBER, Calendar.SUNDAY);
+
+ // out of bounds
+ assertFalse(helper.isWithinCurrentMonth(-1, 3));
+ assertFalse(helper.isWithinCurrentMonth(6, 3));
+ assertFalse(helper.isWithinCurrentMonth(2, -1));
+ assertFalse(helper.isWithinCurrentMonth(2, 7));
+
+ // last day of previous month
+ assertFalse(helper.isWithinCurrentMonth(0, 5));
+
+ // first day of next month
+ assertFalse(helper.isWithinCurrentMonth(5, 1));
+
+ // first day in month
+ assertTrue(helper.isWithinCurrentMonth(0, 6));
+
+ // last day in month
+ assertTrue(helper.isWithinCurrentMonth(5, 0));
+ }
+
+ private void assertArraysEqual(int[] expected, int[] actual) {
+ assertEquals("array length", expected.length, actual.length);
+ for (int i = 0; i < expected.length; i++) {
+ assertEquals("index " + i,
+ expected[i], actual[i]);
+ }
+ }
+
+}
diff --git a/tests/CoreTests/android/util/StateSetTest.java b/tests/CoreTests/android/util/StateSetTest.java
new file mode 100644
index 0000000..e481ce04
--- /dev/null
+++ b/tests/CoreTests/android/util/StateSetTest.java
@@ -0,0 +1,182 @@
+/*
+ * Copyright (C) 2007 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 android.util;
+
+import junit.framework.TestCase;
+import android.test.suitebuilder.annotation.SmallTest;
+
+/**
+ * Tests for {@link StateSet}
+ */
+
+public class StateSetTest extends TestCase {
+
+ @SmallTest
+ public void testStateSetPositiveMatches() throws Exception {
+ int[] stateSpec = new int[2];
+ int[] stateSet = new int[3];
+ // Single states in both sets - match
+ stateSpec[0] = 1;
+ stateSet[0] = 1;
+ assertTrue(StateSet.stateSetMatches(stateSpec, stateSet));
+ // Single states in both sets - non-match
+ stateSet[0] = 2;
+ assertFalse(StateSet.stateSetMatches(stateSpec, stateSet));
+ // Add another state to the spec which the stateSet doesn't match
+ stateSpec[1] = 2;
+ assertFalse(StateSet.stateSetMatches(stateSpec, stateSet));
+ // Add the missing matching element to the stateSet
+ stateSet[1] = 1;
+ assertTrue(StateSet.stateSetMatches(stateSpec, stateSet));
+ // Add an irrelevent state to the stateSpec
+ stateSet[2] = 12345;
+ assertTrue(StateSet.stateSetMatches(stateSpec, stateSet));
+ }
+
+ @SmallTest
+ public void testStatesSetMatchMixEmUp() throws Exception {
+ int[] stateSpec = new int[2];
+ int[] stateSet = new int[2];
+ // One element in stateSpec which we must match and one which we must
+ // not match. stateSet only contains the match.
+ stateSpec[0] = 1;
+ stateSpec[1] = -2;
+ stateSet[0] = 1;
+ assertTrue(StateSet.stateSetMatches(stateSpec, stateSet));
+ // stateSet now contains just the element we must not match
+ stateSet[0] = 2;
+ assertFalse(StateSet.stateSetMatches(stateSpec, stateSet));
+ // Add another matching state to the the stateSet. We still fail
+ // because stateSet contains a must-not-match element
+ stateSet[1] = 1;
+ assertFalse(StateSet.stateSetMatches(stateSpec, stateSet));
+ // Switch the must-not-match element in stateSet with a don't care
+ stateSet[0] = 12345;
+ assertTrue(StateSet.stateSetMatches(stateSpec, stateSet));
+ }
+
+ @SmallTest
+ public void testStateSetNegativeMatches() throws Exception {
+ int[] stateSpec = new int[2];
+ int[] stateSet = new int[3];
+ // Single states in both sets - match
+ stateSpec[0] = -1;
+ stateSet[0] = 2;
+ assertTrue(StateSet.stateSetMatches(stateSpec, stateSet));
+ // Add another arrelevent state to the stateSet
+ stateSet[1] = 12345;
+ assertTrue(StateSet.stateSetMatches(stateSpec, stateSet));
+ // Single states in both sets - non-match
+ stateSet[0] = 1;
+ assertFalse(StateSet.stateSetMatches(stateSpec, stateSet));
+ // Add another state to the spec which the stateSet doesn't match
+ stateSpec[1] = -2;
+ assertFalse(StateSet.stateSetMatches(stateSpec, stateSet));
+ // Add an irrelevent state to the stateSet
+ stateSet[2] = 12345;
+ assertFalse(StateSet.stateSetMatches(stateSpec, stateSet));
+ }
+
+ @SmallTest
+ public void testEmptySetMatchesNegtives() throws Exception {
+ int[] stateSpec = {-12345, -6789};
+ int[] stateSet = new int[0];
+ assertTrue(StateSet.stateSetMatches(stateSpec, stateSet));
+ int[] stateSet2 = {0};
+ assertTrue(StateSet.stateSetMatches(stateSpec, stateSet2));
+ }
+
+ @SmallTest
+ public void testEmptySetFailsPositives() throws Exception {
+ int[] stateSpec = {12345};
+ int[] stateSet = new int[0];
+ assertFalse(StateSet.stateSetMatches(stateSpec, stateSet));
+ int[] stateSet2 = {0};
+ assertFalse(StateSet.stateSetMatches(stateSpec, stateSet2));
+ }
+
+ @SmallTest
+ public void testEmptySetMatchesWildcard() throws Exception {
+ int[] stateSpec = StateSet.WILD_CARD;
+ int[] stateSet = new int[0];
+ assertTrue(StateSet.stateSetMatches(stateSpec, stateSet));
+ int[] stateSet2 = {0};
+ assertTrue(StateSet.stateSetMatches(stateSpec, stateSet2));
+ }
+
+ @SmallTest
+ public void testSingleStatePositiveMatches() throws Exception {
+ int[] stateSpec = new int[2];
+ int state;
+ // match
+ stateSpec[0] = 1;
+ state = 1;
+ assertTrue(StateSet.stateSetMatches(stateSpec, state));
+ // non-match
+ state = 2;
+ assertFalse(StateSet.stateSetMatches(stateSpec, state));
+ // add irrelevant must-not-match
+ stateSpec[1] = -12345;
+ assertFalse(StateSet.stateSetMatches(stateSpec, state));
+ }
+
+ @SmallTest
+ public void testSingleStateNegativeMatches() throws Exception {
+ int[] stateSpec = new int[2];
+ int state;
+ // match
+ stateSpec[0] = -1;
+ state = 1;
+ assertFalse(StateSet.stateSetMatches(stateSpec, state));
+ // non-match
+ state = 2;
+ assertTrue(StateSet.stateSetMatches(stateSpec, state));
+ // add irrelevant must-not-match
+ stateSpec[1] = -12345;
+ assertTrue(StateSet.stateSetMatches(stateSpec, state));
+ }
+
+ @SmallTest
+ public void testZeroStateOnlyMatchesDefault() throws Exception {
+ int[] stateSpec = new int[3];
+ int state = 0;
+ // non-match
+ stateSpec[0] = 1;
+ assertFalse(StateSet.stateSetMatches(stateSpec, state));
+ // non-match
+ stateSpec[1] = -1;
+ assertFalse(StateSet.stateSetMatches(stateSpec, state));
+ // match
+ stateSpec = StateSet.WILD_CARD;
+ assertTrue(StateSet.stateSetMatches(stateSpec, state));
+ }
+
+ @SmallTest
+ public void testNullStateOnlyMatchesDefault() throws Exception {
+ int[] stateSpec = new int[3];
+ int[] stateSet = null;
+ // non-match
+ stateSpec[0] = 1;
+ assertFalse(StateSet.stateSetMatches(stateSpec, stateSet));
+ // non-match
+ stateSpec[1] = -1;
+ assertFalse(StateSet.stateSetMatches(stateSpec, stateSet));
+ // match
+ stateSpec = StateSet.WILD_CARD;
+ assertTrue(StateSet.stateSetMatches(stateSpec, stateSet));
+ }
+}
diff --git a/tests/CoreTests/android/view/FocusFinderTest.java b/tests/CoreTests/android/view/FocusFinderTest.java
new file mode 100644
index 0000000..7ac8dfc
--- /dev/null
+++ b/tests/CoreTests/android/view/FocusFinderTest.java
@@ -0,0 +1,576 @@
+/*
+ * 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 android.view;
+
+import android.graphics.Rect;
+import android.test.AndroidTestCase;
+import android.test.suitebuilder.annotation.MediumTest;
+import android.test.suitebuilder.annotation.SmallTest;
+
+public class FocusFinderTest extends AndroidTestCase {
+
+ private FocusFinderHelper mFocusFinder;
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+
+ mFocusFinder = new FocusFinderHelper(FocusFinder.getInstance());
+ }
+
+ @SmallTest
+ public void testPreconditions() {
+ assertNotNull("focus finder instance", mFocusFinder);
+ }
+
+ @SmallTest
+ public void testBelowNotCandidateForDirectionUp() {
+ assertIsNotCandidate(View.FOCUS_UP,
+ new Rect(0, 30, 10, 40), // src (left, top, right, bottom)
+ new Rect(0, 50, 10, 60)); // dest (left, top, right, bottom)
+ }
+
+ @SmallTest
+ public void testAboveShareEdgeEdgeOkForDirectionUp() {
+ final Rect src = new Rect(0, 30, 10, 40);
+
+ final Rect dest = new Rect(src);
+ dest.offset(0, -src.height());
+ assertEquals(src.top, dest.bottom);
+
+ assertDirectionIsCandidate(View.FOCUS_UP, src, dest);
+ }
+
+ @SmallTest
+ public void testCompletelyContainedNotCandidate() {
+ assertIsNotCandidate(
+ View.FOCUS_DOWN,
+ // L T R B
+ new Rect(0, 0, 50, 50),
+ new Rect(0, 1, 50, 49));
+ }
+
+ @SmallTest
+ public void testContinaedWithCommonBottomNotCandidate() {
+ assertIsNotCandidate(
+ View.FOCUS_DOWN,
+ // L T R B
+ new Rect(0, 0, 50, 50),
+ new Rect(0, 1, 50, 50));
+ }
+
+ @SmallTest
+ public void testOverlappingIsCandidateWhenBothEdgesAreInDirection() {
+ assertDirectionIsCandidate(
+ View.FOCUS_DOWN,
+ // L T R B
+ new Rect(0, 0, 50, 50),
+ new Rect(0, 1, 50, 51));
+ }
+
+ @SmallTest
+ public void testTopEdgeOfDestAtOrAboveTopOfSrcNotCandidateForDown() {
+ assertIsNotCandidate(
+ View.FOCUS_DOWN,
+ // L T R B
+ new Rect(0, 0, 50, 50),
+ new Rect(0, 0, 50, 51));
+ assertIsNotCandidate(
+ View.FOCUS_DOWN,
+ // L T R B
+ new Rect(0, 0, 50, 50),
+ new Rect(0, -1, 50, 51));
+ }
+
+ @SmallTest
+ public void testSameRectBeamsOverlap() {
+ final Rect rect = new Rect(0, 0, 20, 20);
+
+ assertBeamsOverlap(View.FOCUS_LEFT, rect, rect);
+ assertBeamsOverlap(View.FOCUS_RIGHT, rect, rect);
+ assertBeamsOverlap(View.FOCUS_UP, rect, rect);
+ assertBeamsOverlap(View.FOCUS_DOWN, rect, rect);
+ }
+
+ @SmallTest
+ public void testOverlapBeamsRightLeftUpToEdge() {
+ final Rect rect1 = new Rect(0, 0, 20, 20);
+ final Rect rect2 = new Rect(rect1);
+
+ // just below bottom edge
+ rect2.offset(0, rect1.height() - 1);
+ assertBeamsOverlap(View.FOCUS_LEFT, rect1, rect2);
+ assertBeamsOverlap(View.FOCUS_RIGHT, rect1, rect2);
+
+ // at edge
+ rect2.offset(0, 1);
+ assertBeamsOverlap(View.FOCUS_LEFT, rect1, rect2);
+ assertBeamsOverlap(View.FOCUS_RIGHT, rect1, rect2);
+
+ // just beyond
+ rect2.offset(0, 1);
+ assertBeamsDontOverlap(View.FOCUS_LEFT, rect1, rect2);
+ assertBeamsDontOverlap(View.FOCUS_RIGHT, rect1, rect2);
+
+ // just below top edge
+ rect2.set(rect1);
+ rect2.offset(0, -(rect1.height() - 1));
+ assertBeamsOverlap(View.FOCUS_LEFT, rect1, rect2);
+ assertBeamsOverlap(View.FOCUS_RIGHT, rect1, rect2);
+
+ // at top edge
+ rect2.offset(0, -1);
+ assertBeamsOverlap(View.FOCUS_LEFT, rect1, rect2);
+ assertBeamsOverlap(View.FOCUS_RIGHT, rect1, rect2);
+
+ // just beyond top edge
+ rect2.offset(0, -1);
+ assertBeamsDontOverlap(View.FOCUS_LEFT, rect1, rect2);
+ assertBeamsDontOverlap(View.FOCUS_RIGHT, rect1, rect2);
+ }
+
+ @SmallTest
+ public void testOverlapBeamsUpDownUpToEdge() {
+ final Rect rect1 = new Rect(0, 0, 20, 20);
+ final Rect rect2 = new Rect(rect1);
+
+ // just short of right edge
+ rect2.offset(rect1.width() - 1, 0);
+ assertBeamsOverlap(View.FOCUS_UP, rect1, rect2);
+ assertBeamsOverlap(View.FOCUS_DOWN, rect1, rect2);
+
+ // at edge
+ rect2.offset(1, 0);
+ assertBeamsOverlap(View.FOCUS_UP, rect1, rect2);
+ assertBeamsOverlap(View.FOCUS_DOWN, rect1, rect2);
+
+ // just beyond
+ rect2.offset(1, 0);
+ assertBeamsDontOverlap(View.FOCUS_UP, rect1, rect2);
+ assertBeamsDontOverlap(View.FOCUS_DOWN, rect1, rect2);
+
+ // just short of left edge
+ rect2.set(rect1);
+ rect2.offset(-(rect1.width() - 1), 0);
+ assertBeamsOverlap(View.FOCUS_UP, rect1, rect2);
+ assertBeamsOverlap(View.FOCUS_DOWN, rect1, rect2);
+
+ // at edge
+ rect2.offset(-1, 0);
+ assertBeamsOverlap(View.FOCUS_UP, rect1, rect2);
+ assertBeamsOverlap(View.FOCUS_DOWN, rect1, rect2);
+
+ // just beyond edge
+ rect2.offset(-1, 0);
+ assertBeamsDontOverlap(View.FOCUS_UP, rect1, rect2);
+ assertBeamsDontOverlap(View.FOCUS_DOWN, rect1, rect2);
+ }
+
+ @SmallTest
+ public void testDirectlyAboveTrumpsAboveLeft() {
+ Rect src = new Rect(0, 50, 20, 70); // src (left, top, right, bottom)
+
+ Rect directlyAbove = new Rect(src);
+ directlyAbove.offset(0, -(1 + src.height()));
+
+ Rect aboveLeft = new Rect(src);
+ aboveLeft.offset(-(1 + src.width()), -(1 + src.height()));
+
+ assertBetterCandidate(View.FOCUS_UP, src, directlyAbove, aboveLeft);
+ }
+
+ @SmallTest
+ public void testAboveInBeamTrumpsSlightlyCloserOutOfBeam() {
+ Rect src = new Rect(0, 50, 20, 70); // src (left, top, right, bottom)
+
+ Rect directlyAbove = new Rect(src);
+ directlyAbove.offset(0, -(1 + src.height()));
+
+ Rect aboveLeft = new Rect(src);
+ aboveLeft.offset(-(1 + src.width()), -(1 + src.height()));
+
+ // offset directly above a little further up
+ directlyAbove.offset(0, -5);
+ assertBetterCandidate(View.FOCUS_UP, src, directlyAbove, aboveLeft);
+ }
+
+ @SmallTest
+ public void testOutOfBeamBeatsInBeamUp() {
+
+ Rect src = new Rect(0, 0, 50, 50); // (left, top, right, bottom)
+
+ Rect aboveLeftOfBeam = new Rect(src);
+ aboveLeftOfBeam.offset(-(src.width() + 1), -src.height());
+ assertBeamsDontOverlap(View.FOCUS_UP, src, aboveLeftOfBeam);
+
+ Rect aboveInBeam = new Rect(src);
+ aboveInBeam.offset(0, -src.height());
+ assertBeamsOverlap(View.FOCUS_UP, src, aboveInBeam);
+
+ // in beam wins
+ assertBetterCandidate(View.FOCUS_UP, src, aboveInBeam, aboveLeftOfBeam);
+
+ // still wins while aboveInBeam's bottom edge is < out of beams' top
+ aboveInBeam.offset(0, -(aboveLeftOfBeam.height() - 1));
+ assertTrue("aboveInBeam.bottom > aboveLeftOfBeam.top", aboveInBeam.bottom > aboveLeftOfBeam.top);
+ assertBetterCandidate(View.FOCUS_UP, src, aboveInBeam, aboveLeftOfBeam);
+
+ // cross the threshold: the out of beam prevails
+ aboveInBeam.offset(0, -1);
+ assertEquals(aboveInBeam.bottom, aboveLeftOfBeam.top);
+ assertBetterCandidate(View.FOCUS_UP, src, aboveLeftOfBeam, aboveInBeam);
+ }
+
+ /**
+ * A non-candidate (even a much closer one) is always a worse choice
+ * than a real candidate.
+ */
+ @MediumTest
+ public void testSomeCandidateBetterThanNonCandidate() {
+ Rect src = new Rect(0, 0, 50, 50); // (left, top, right, bottom)
+
+ Rect nonCandidate = new Rect(src);
+ nonCandidate.offset(src.width() + 1, 0);
+
+ assertIsNotCandidate(View.FOCUS_LEFT, src, nonCandidate);
+
+ Rect candidate = new Rect(src);
+ candidate.offset(-(4 * src.width()), 0);
+ assertDirectionIsCandidate(View.FOCUS_LEFT, src, candidate);
+
+ assertBetterCandidate(View.FOCUS_LEFT, src, candidate, nonCandidate);
+ }
+
+ /**
+ * Grabbed from {@link com.android.frameworktest.focus.VerticalFocusSearchTest#testSearchFromMidLeft()}
+ */
+ @SmallTest
+ public void testVerticalFocusSearchScenario() {
+ assertBetterCandidate(View.FOCUS_DOWN,
+ // L T R B
+ new Rect(0, 109, 153, 169), // src
+ new Rect(166, 169, 319, 229), // expectedbetter
+ new Rect(0, 229, 320, 289)); // expectedworse
+
+ // failing test 4/10/2008, the values were tweaked somehow in functional
+ // test...
+ assertBetterCandidate(View.FOCUS_DOWN,
+ // L T R B
+ new Rect(0, 91, 153, 133), // src
+ new Rect(166, 133, 319, 175), // expectedbetter
+ new Rect(0, 175, 320, 217)); // expectedworse
+
+ }
+
+ /**
+ * Example: going down from a thin button all the way to the left of a
+ * screen where, just below, is a very wide button, and just below that,
+ * is an equally skinny button all the way to the left. want to make
+ * sure any minor axis factor doesn't override the fact that the one below
+ * in vertical beam should be next focus
+ */
+ @SmallTest
+ public void testBeamsOverlapMajorAxisCloserMinorAxisFurther() {
+ assertBetterCandidate(View.FOCUS_DOWN,
+ // L T R B
+ new Rect(0, 0, 100, 100), // src
+ new Rect(0, 100, 480, 200), // expectedbetter
+ new Rect(0, 200, 100, 300)); // expectedworse
+ }
+
+ /**
+ * Real scenario grabbed from song playback screen.
+ */
+ @SmallTest
+ public void testMusicPlaybackScenario() {
+ assertBetterCandidate(View.FOCUS_LEFT,
+ // L T R B
+ new Rect(227, 185, 312, 231), // src
+ new Rect(195, 386, 266, 438), // expectedbetter
+ new Rect(124, 386, 195, 438)); // expectedworse
+ }
+
+ /**
+ * more generalized version of {@link #testMusicPlaybackScenario()}
+ */
+ @SmallTest
+ public void testOutOfBeamOverlapBeatsOutOfBeamFurtherOnMajorAxis() {
+ assertBetterCandidate(View.FOCUS_DOWN,
+ // L T R B
+ new Rect(0, 0, 50, 50), // src
+ new Rect(60, 40, 110, 90), // expectedbetter
+ new Rect(60, 70, 110, 120)); // expectedworse
+ }
+
+ /**
+ * Make sure that going down prefers views that are actually
+ * down (and not those next to but still a candidate because
+ * they are overlapping on the major axis)
+ */
+ @SmallTest
+ public void testInBeamTrumpsOutOfBeamOverlapping() {
+ assertBetterCandidate(View.FOCUS_DOWN,
+ // L T R B
+ new Rect(0, 0, 50, 50), // src
+ new Rect(0, 60, 50, 110), // expectedbetter
+ new Rect(51, 1, 101, 51)); // expectedworse
+ }
+
+ @SmallTest
+ public void testOverlappingBeatsNonOverlapping() {
+ assertBetterCandidate(View.FOCUS_DOWN,
+ // L T R B
+ new Rect(0, 0, 50, 50), // src
+ new Rect(0, 40, 50, 90), // expectedbetter
+ new Rect(0, 75, 50, 125)); // expectedworse
+ }
+
+ @SmallTest
+ public void testEditContactScenarioLeftFromDiscardChangesGoesToSaveContactInLandscape() {
+ assertBetterCandidate(View.FOCUS_LEFT,
+ // L T R B
+ new Rect(357, 258, 478, 318), // src
+ new Rect(2, 258, 100, 318), // better
+ new Rect(106, 120, 424, 184)); // worse
+ }
+
+ /**
+ * A dial pad with 9 squares arranged in a grid. no padding, so
+ * the edges are equal. see {@link com.android.frameworktest.focus.LinearLayoutGrid}
+ */
+ @SmallTest
+ public void testGridWithTouchingEdges() {
+ assertBetterCandidate(View.FOCUS_DOWN,
+ // L T R B
+ new Rect(106, 49, 212, 192), // src
+ new Rect(106, 192, 212, 335), // better
+ new Rect(0, 192, 106, 335)); // worse
+
+ assertBetterCandidate(View.FOCUS_DOWN,
+ // L T R B
+ new Rect(106, 49, 212, 192), // src
+ new Rect(106, 192, 212, 335), // better
+ new Rect(212, 192, 318, 335)); // worse
+ }
+
+ @SmallTest
+ public void testSearchFromEmptyRect() {
+ assertBetterCandidate(View.FOCUS_DOWN,
+ // L T R B
+ new Rect(0, 0, 0, 0), // src
+ new Rect(0, 0, 320, 45), // better
+ new Rect(0, 45, 320, 545)); // worse
+ }
+
+ /**
+ * Reproduce bug 1124559, drilling down to actual bug
+ * (majorAxisDistance was wrong for direction left)
+ */
+ @SmallTest
+ public void testGmailReplyButtonsScenario() {
+ assertBetterCandidate(View.FOCUS_LEFT,
+ // L T R B
+ new Rect(223, 380, 312, 417), // src
+ new Rect(102, 380, 210, 417), // better
+ new Rect(111, 443, 206, 480)); // worse
+
+ assertBeamBeats(View.FOCUS_LEFT,
+ // L T R B
+ new Rect(223, 380, 312, 417), // src
+ new Rect(102, 380, 210, 417), // better
+ new Rect(111, 443, 206, 480)); // worse
+
+ assertBeamsOverlap(View.FOCUS_LEFT,
+ // L T R B
+ new Rect(223, 380, 312, 417),
+ new Rect(102, 380, 210, 417));
+
+ assertBeamsDontOverlap(View.FOCUS_LEFT,
+ // L T R B
+ new Rect(223, 380, 312, 417),
+ new Rect(111, 443, 206, 480));
+
+ assertTrue(
+ "major axis distance less than major axis distance to "
+ + "far edge",
+ FocusFinderHelper.majorAxisDistance(View.FOCUS_LEFT,
+ // L T R B
+ new Rect(223, 380, 312, 417),
+ new Rect(102, 380, 210, 417)) <
+ FocusFinderHelper.majorAxisDistanceToFarEdge(View.FOCUS_LEFT,
+ // L T R B
+ new Rect(223, 380, 312, 417),
+ new Rect(111, 443, 206, 480)));
+ }
+
+ @SmallTest
+ public void testGmailScenarioBug1203288() {
+ assertBetterCandidate(View.FOCUS_DOWN,
+ // L T R B
+ new Rect(0, 2, 480, 82), // src
+ new Rect(344, 87, 475, 124), // better
+ new Rect(0, 130, 480, 203)); // worse
+ }
+
+ @SmallTest
+ public void testHomeShortcutScenarioBug1295354() {
+ assertBetterCandidate(View.FOCUS_RIGHT,
+ // L T R B
+ new Rect(3, 338, 77, 413), // src
+ new Rect(163, 338, 237, 413), // better
+ new Rect(83, 38, 157, 113)); // worse
+ }
+
+ @SmallTest
+ public void testBeamAlwaysBeatsHoriz() {
+ assertBetterCandidate(View.FOCUS_RIGHT,
+ // L T R B
+ new Rect(0, 0, 50, 50), // src
+ new Rect(150, 0, 200, 50), // better, (way further, but in beam)
+ new Rect(60, 51, 110, 101)); // worse, even though it is closer
+
+ assertBetterCandidate(View.FOCUS_LEFT,
+ // L T R B
+ new Rect(150, 0, 200, 50), // src
+ new Rect(0, 50, 50, 50), // better, (way further, but in beam)
+ new Rect(49, 99, 149, 101)); // worse, even though it is closer
+ }
+
+ @SmallTest
+ public void testIsCandidateOverlappingEdgeFromEmptyRect() {
+ assertDirectionIsCandidate(View.FOCUS_DOWN,
+ // L T R B
+ new Rect(0, 0, 0, 0), // src
+ new Rect(0, 0, 20, 1)); // candidate
+
+ assertDirectionIsCandidate(View.FOCUS_UP,
+ // L T R B
+ new Rect(0, 0, 0, 0), // src
+ new Rect(0, -1, 20, 0)); // candidate
+
+ assertDirectionIsCandidate(View.FOCUS_LEFT,
+ // L T R B
+ new Rect(0, 0, 0, 0), // src
+ new Rect(-1, 0, 0, 20)); // candidate
+
+ assertDirectionIsCandidate(View.FOCUS_RIGHT,
+ // L T R B
+ new Rect(0, 0, 0, 0), // src
+ new Rect(0, 0, 1, 20)); // candidate
+ }
+
+ private void assertBeamsOverlap(int direction, Rect rect1, Rect rect2) {
+ String directionStr = validateAndGetStringFor(direction);
+ String assertMsg = String.format("Expected beams to overlap in direction %s "
+ + "for rectangles %s and %s", directionStr, rect1, rect2);
+ assertTrue(assertMsg, mFocusFinder.beamsOverlap(direction, rect1, rect2));
+ }
+
+ private void assertBeamsDontOverlap(int direction, Rect rect1, Rect rect2) {
+ String directionStr = validateAndGetStringFor(direction);
+ String assertMsg = String.format("Expected beams not to overlap in direction %s "
+ + "for rectangles %s and %s", directionStr, rect1, rect2);
+ assertFalse(assertMsg, mFocusFinder.beamsOverlap(direction, rect1, rect2));
+ }
+
+ /**
+ * Assert that particular rect is a better focus search candidate from a
+ * source rect than another.
+ * @param direction The direction of focus search.
+ * @param srcRect The src rectangle.
+ * @param expectedBetter The candidate that should be better.
+ * @param expectedWorse The candidate that should be worse.
+ */
+ private void assertBetterCandidate(int direction, Rect srcRect,
+ Rect expectedBetter, Rect expectedWorse) {
+
+ String directionStr = validateAndGetStringFor(direction);
+ String assertMsg = String.format(
+ "expected %s to be a better focus search candidate than "
+ + "%s when searching "
+ + "from %s in direction %s",
+ expectedBetter, expectedWorse, srcRect, directionStr);
+
+ assertTrue(assertMsg,
+ mFocusFinder.isBetterCandidate(direction, srcRect,
+ expectedBetter, expectedWorse));
+
+ assertMsg = String.format(
+ "expected %s to not be a better focus search candidate than "
+ + "%s when searching "
+ + "from %s in direction %s",
+ expectedWorse, expectedBetter, srcRect, directionStr);
+
+ assertFalse(assertMsg,
+ mFocusFinder.isBetterCandidate(direction, srcRect,
+ expectedWorse, expectedBetter));
+ }
+
+ private void assertIsNotCandidate(int direction, Rect src, Rect dest) {
+ String directionStr = validateAndGetStringFor(direction);
+
+ final String assertMsg = String.format(
+ "expected going from %s to %s in direction %s to be an invalid "
+ + "focus search candidate",
+ src, dest, directionStr);
+ assertFalse(assertMsg, mFocusFinder.isCandidate(src, dest, direction));
+ }
+
+ private void assertBeamBeats(int direction, Rect srcRect,
+ Rect rect1, Rect rect2) {
+
+ String directionStr = validateAndGetStringFor(direction);
+ String assertMsg = String.format(
+ "expecting %s to beam beat %s w.r.t %s in direction %s",
+ rect1, rect2, srcRect, directionStr);
+ assertTrue(assertMsg, mFocusFinder.beamBeats(direction, srcRect, rect1, rect2));
+ }
+
+
+ private void assertDirectionIsCandidate(int direction, Rect src, Rect dest) {
+ String directionStr = validateAndGetStringFor(direction);
+
+ final String assertMsg = String.format(
+ "expected going from %s to %s in direction %s to be a valid "
+ + "focus search candidate",
+ src, dest, directionStr);
+ assertTrue(assertMsg, mFocusFinder.isCandidate(src, dest, direction));
+ }
+
+ private String validateAndGetStringFor(int direction) {
+ String directionStr = "??";
+ switch(direction) {
+ case View.FOCUS_UP:
+ directionStr = "FOCUS_UP";
+ break;
+ case View.FOCUS_DOWN:
+ directionStr = "FOCUS_DOWN";
+ break;
+ case View.FOCUS_LEFT:
+ directionStr = "FOCUS_LEFT";
+ break;
+ case View.FOCUS_RIGHT:
+ directionStr = "FOCUS_RIGHT";
+ break;
+ default:
+ fail("passed in unknown direction, ya blewit!");
+ }
+ return directionStr;
+ }
+
+
+}
diff --git a/tests/CoreTests/android/view/MockView.java b/tests/CoreTests/android/view/MockView.java
new file mode 100644
index 0000000..1d416bd
--- /dev/null
+++ b/tests/CoreTests/android/view/MockView.java
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2007 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 android.view;
+
+/**
+ * Mock View class for testing
+ */
+
+public class MockView extends View{
+
+}
diff --git a/tests/CoreTests/android/view/ViewGroupAttributesTest.java b/tests/CoreTests/android/view/ViewGroupAttributesTest.java
new file mode 100644
index 0000000..b4ef0e7
--- /dev/null
+++ b/tests/CoreTests/android/view/ViewGroupAttributesTest.java
@@ -0,0 +1,83 @@
+/*
+ * 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 android.view;
+
+import android.content.Context;
+import android.test.AndroidTestCase;
+import android.test.suitebuilder.annotation.SmallTest;
+
+public class ViewGroupAttributesTest extends AndroidTestCase {
+
+ private MyViewGroup mViewGroup;
+
+ private static final class MyViewGroup extends ViewGroup {
+
+ public MyViewGroup(Context context) {
+ super(context);
+ }
+
+ @Override
+ protected void onLayout(boolean changed, int l, int t, int r, int b) {
+ }
+
+ @Override
+ public boolean isChildrenDrawnWithCacheEnabled() {
+ return super.isChildrenDrawnWithCacheEnabled();
+ }
+ }
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ mViewGroup = new MyViewGroup(getContext());
+ }
+
+ @SmallTest
+ public void testDescendantFocusabilityEnum() {
+ assertEquals("expected ViewGroup.FOCUS_BEFORE_DESCENDANTS to be default",
+ ViewGroup.FOCUS_BEFORE_DESCENDANTS, mViewGroup.getDescendantFocusability());
+
+ // remember some state before we muck with flags
+ final boolean isAnimationCachEnabled = mViewGroup.isAnimationCacheEnabled();
+ final boolean isAlwaysDrawnWithCacheEnabled = mViewGroup.isAlwaysDrawnWithCacheEnabled();
+ final boolean isChildrenDrawnWithCacheEnabled = mViewGroup.isChildrenDrawnWithCacheEnabled();
+
+ mViewGroup.setDescendantFocusability(ViewGroup.FOCUS_AFTER_DESCENDANTS);
+ assertEquals(ViewGroup.FOCUS_AFTER_DESCENDANTS, mViewGroup.getDescendantFocusability());
+
+ mViewGroup.setDescendantFocusability(ViewGroup.FOCUS_BLOCK_DESCENDANTS);
+ assertEquals(ViewGroup.FOCUS_BLOCK_DESCENDANTS, mViewGroup.getDescendantFocusability());
+
+ mViewGroup.setDescendantFocusability(ViewGroup.FOCUS_BEFORE_DESCENDANTS);
+ assertEquals(ViewGroup.FOCUS_BEFORE_DESCENDANTS, mViewGroup.getDescendantFocusability());
+
+ // verify we didn't change something unrelated
+ final String msg = "setDescendantFocusability messed with an unrelated flag";
+ assertEquals(msg, isAnimationCachEnabled, mViewGroup.isAnimationCacheEnabled());
+ assertEquals(msg, isAlwaysDrawnWithCacheEnabled, mViewGroup.isAlwaysDrawnWithCacheEnabled());
+ assertEquals(msg, isChildrenDrawnWithCacheEnabled, mViewGroup.isChildrenDrawnWithCacheEnabled());
+ }
+
+ @SmallTest
+ public void testWrongIntSetForDescendantFocusabilityEnum() {
+ try {
+ mViewGroup.setDescendantFocusability(0);
+ fail("expected setting wrong flag to throw an exception");
+ } catch (IllegalArgumentException expected) {
+ }
+ }
+}
diff --git a/tests/CoreTests/android/webkit/CookieTest.java b/tests/CoreTests/android/webkit/CookieTest.java
new file mode 100644
index 0000000..1c3d671
--- /dev/null
+++ b/tests/CoreTests/android/webkit/CookieTest.java
@@ -0,0 +1,188 @@
+/*
+ * 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 android.webkit;
+
+import android.content.Context;
+import android.test.AndroidTestCase;
+import android.util.Log;
+import android.webkit.CookieManager;
+import android.webkit.CookieSyncManager;
+
+public class CookieTest extends AndroidTestCase {
+
+ /**
+ * To run these tests: $ mmm frameworks/base/tests/CoreTests/android && adb
+ * remount && adb sync $ adb shell am instrument -w \ -e class
+ * android.webkit.CookieTest \
+ * android.core/android.test.InstrumentationTestRunner
+ */
+
+ private CookieManager mCookieManager;
+
+ @Override
+ public void setContext(Context context) {
+ assertTrue(mContext == null);
+ super.setContext(context);
+ CookieSyncManager.createInstance(context);
+ mCookieManager = CookieManager.getInstance();
+ mCookieManager.removeAllCookie();
+ }
+
+ public void testParse() {
+ mCookieManager.removeAllCookie();
+ String url = "http://www.foo.com";
+
+ // basic
+ mCookieManager.setCookie(url, "a=b");
+ String cookie = mCookieManager.getCookie(url);
+ assertTrue(cookie.equals("a=b"));
+
+ // quoted
+ mCookieManager.setCookie(url, "c=\"d;\"");
+ cookie = mCookieManager.getCookie(url);
+ assertTrue(cookie.equals("a=b; c=\"d;\""));
+ }
+
+ public void testDomain() {
+ mCookieManager.removeAllCookie();
+ String url = "http://www.foo.com";
+
+ // basic
+ mCookieManager.setCookie(url, "a=b");
+ String cookie = mCookieManager.getCookie(url);
+ assertTrue(cookie.equals("a=b"));
+
+ // no cross domain cookie
+ cookie = mCookieManager.getCookie("http://bar.com");
+ assertTrue(cookie == null);
+
+ // more than one cookie
+ mCookieManager.setCookie(url, "c=d; domain=.foo.com");
+ cookie = mCookieManager.getCookie(url);
+ assertTrue(cookie.equals("a=b; c=d"));
+
+ // host cookie should not be accessible from a sub-domain.
+ cookie = mCookieManager.getCookie("http://bar.www.foo.com");
+ assertTrue(cookie.equals("c=d"));
+
+ // test setting a domain= that doesn't start w/ a dot, should
+ // treat it as a domain cookie, as if there was a pre-pended dot.
+ mCookieManager.setCookie(url, "e=f; domain=www.foo.com");
+ cookie = mCookieManager.getCookie(url);
+ assertTrue(cookie.equals("a=b; c=d; e=f"));
+ cookie = mCookieManager.getCookie("http://sub.www.foo.com");
+ assertTrue(cookie.equals("c=d; e=f"));
+ cookie = mCookieManager.getCookie("http://foo.com");
+ assertTrue(cookie.equals("c=d"));
+ }
+
+ public void testSubDomain() {
+ mCookieManager.removeAllCookie();
+ String url_abcd = "http://a.b.c.d.com";
+ String url_bcd = "http://b.c.d.com";
+ String url_cd = "http://c.d.com";
+ String url_d = "http://d.com";
+
+ mCookieManager.setCookie(url_abcd, "a=1; domain=.a.b.c.d.com");
+ mCookieManager.setCookie(url_abcd, "b=2; domain=.b.c.d.com");
+ mCookieManager.setCookie(url_abcd, "c=3; domain=.c.d.com");
+ mCookieManager.setCookie(url_abcd, "d=4; domain=.d.com");
+
+ String cookie = mCookieManager.getCookie(url_abcd);
+ assertTrue(cookie.equals("a=1; b=2; c=3; d=4"));
+ cookie = mCookieManager.getCookie(url_bcd);
+ assertTrue(cookie.equals("b=2; c=3; d=4"));
+ cookie = mCookieManager.getCookie(url_cd);
+ assertTrue(cookie.equals("c=3; d=4"));
+ cookie = mCookieManager.getCookie(url_d);
+ assertTrue(cookie.equals("d=4"));
+
+ // check that the same cookie can exist on different sub-domains.
+ mCookieManager.setCookie(url_bcd, "x=bcd; domain=.b.c.d.com");
+ mCookieManager.setCookie(url_bcd, "x=cd; domain=.c.d.com");
+ cookie = mCookieManager.getCookie(url_bcd);
+ assertTrue(cookie.equals("b=2; c=3; d=4; x=bcd; x=cd"));
+ cookie = mCookieManager.getCookie(url_cd);
+ assertTrue(cookie.equals("c=3; d=4; x=cd"));
+ }
+
+ public void testInvalidDomain() {
+ mCookieManager.removeAllCookie();
+ String url = "http://foo.bar.com";
+
+ mCookieManager.setCookie(url, "a=1; domain=.yo.foo.bar.com");
+ String cookie = mCookieManager.getCookie(url);
+ assertTrue(cookie == null);
+
+ mCookieManager.setCookie(url, "b=2; domain=.foo.com");
+ cookie = mCookieManager.getCookie(url);
+ assertTrue(cookie == null);
+
+ mCookieManager.setCookie(url, "c=3; domain=.bar.foo.com");
+ cookie = mCookieManager.getCookie(url);
+ assertTrue(cookie == null);
+
+ mCookieManager.setCookie(url, "d=4; domain=.foo.bar.com.net");
+ cookie = mCookieManager.getCookie(url);
+ assertTrue(cookie == null);
+
+ mCookieManager.setCookie(url, "e=5; domain=.ar.com");
+ cookie = mCookieManager.getCookie(url);
+ assertTrue(cookie == null);
+
+ mCookieManager.setCookie(url, "f=6; domain=.com");
+ cookie = mCookieManager.getCookie(url);
+ assertTrue(cookie == null);
+
+ mCookieManager.setCookie(url, "g=7; domain=.co.uk");
+ cookie = mCookieManager.getCookie(url);
+ assertTrue(cookie == null);
+
+ mCookieManager.setCookie(url, "h=8; domain=.foo.bar.com.com");
+ cookie = mCookieManager.getCookie(url);
+ assertTrue(cookie == null);
+ }
+
+ public void testPath() {
+ mCookieManager.removeAllCookie();
+ String url = "http://www.foo.com";
+
+ mCookieManager.setCookie(url, "a=b; path=/wee");
+ String cookie = mCookieManager.getCookie(url + "/wee");
+ assertTrue(cookie.equals("a=b"));
+ cookie = mCookieManager.getCookie(url + "/wee/");
+ assertTrue(cookie.equals("a=b"));
+ cookie = mCookieManager.getCookie(url + "/wee/hee");
+ assertTrue(cookie.equals("a=b"));
+ cookie = mCookieManager.getCookie(url + "/wee/hee/more");
+ assertTrue(cookie.equals("a=b"));
+ cookie = mCookieManager.getCookie(url + "/weehee");
+ assertTrue(cookie == null);
+ cookie = mCookieManager.getCookie(url);
+ assertTrue(cookie == null);
+
+ mCookieManager.setCookie(url, "a=c; path=");
+ cookie = mCookieManager.getCookie(url + "/wee");
+ assertTrue(cookie.equals("a=b; a=c"));
+ cookie = mCookieManager.getCookie(url);
+ assertTrue(cookie.equals("a=c"));
+
+ mCookieManager.setCookie(url, "a=d");
+ cookie = mCookieManager.getCookie(url + "/wee");
+ assertTrue(cookie.equals("a=b; a=c; a=d"));
+ }
+}
diff --git a/tests/CoreTests/com/android/internal/telephony/ATResponseParserTest.java b/tests/CoreTests/com/android/internal/telephony/ATResponseParserTest.java
new file mode 100644
index 0000000..81727e4
--- /dev/null
+++ b/tests/CoreTests/com/android/internal/telephony/ATResponseParserTest.java
@@ -0,0 +1,113 @@
+/*
+ * Copyright (C) 2006 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.internal.telephony;
+
+import junit.framework.TestCase;
+import android.test.suitebuilder.annotation.SmallTest;
+
+public class ATResponseParserTest extends TestCase {
+ @SmallTest
+ public void testBasic() throws Exception {
+ ATResponseParser p = new ATResponseParser("+CREG: 0");
+
+ assertEquals(0, p.nextInt());
+
+ assertFalse(p.hasMore());
+
+ try {
+ p.nextInt();
+ fail("exception expected");
+ } catch (ATParseEx ex) {
+ //test pass
+ }
+
+ p = new ATResponseParser("+CREG: 0,1");
+ assertEquals(0, p.nextInt());
+ assertEquals(1, p.nextInt());
+ assertFalse(p.hasMore());
+
+ p = new ATResponseParser("+CREG: 0, 1");
+ assertEquals(0, p.nextInt());
+ assertEquals(1, p.nextInt());
+ assertFalse(p.hasMore());
+
+ p = new ATResponseParser("+CREG: 0, 1,");
+ assertEquals(0, p.nextInt());
+ assertEquals(1, p.nextInt());
+ // this seems odd but is probably OK
+ assertFalse(p.hasMore());
+ try {
+ p.nextInt();
+ fail("exception expected");
+ } catch (ATParseEx ex) {
+ //test pass
+ }
+
+ p = new ATResponseParser("+CREG: 0, 1 ");
+ assertEquals(0, p.nextInt());
+ assertEquals(1, p.nextInt());
+ assertFalse(p.hasMore());
+
+ p = new ATResponseParser("0, 1 ");
+ // no prefix -> exception
+ try {
+ p.nextInt();
+ fail("exception expected");
+ } catch (ATParseEx ex) {
+ //test pass
+ }
+
+ p = new ATResponseParser("+CREG: 0, 1, 5");
+ assertFalse(p.nextBoolean());
+ assertTrue(p.nextBoolean());
+ try {
+ // is this over-constraining?
+ p.nextBoolean();
+ fail("exception expected");
+ } catch (ATParseEx ex) {
+ //test pass
+ }
+
+ p = new ATResponseParser("+CLCC: 1,0,2,0,0,\"+18005551212\",145");
+
+ assertEquals(1, p.nextInt());
+ assertFalse(p.nextBoolean());
+ assertEquals(2, p.nextInt());
+ assertEquals(0, p.nextInt());
+ assertEquals(0, p.nextInt());
+ assertEquals("+18005551212", p.nextString());
+ assertEquals(145, p.nextInt());
+ assertFalse(p.hasMore());
+
+ p = new ATResponseParser("+CLCC: 1,0,2,0,0,\"+18005551212,145");
+
+ assertEquals(1, p.nextInt());
+ assertFalse(p.nextBoolean());
+ assertEquals(2, p.nextInt());
+ assertEquals(0, p.nextInt());
+ assertEquals(0, p.nextInt());
+ try {
+ p.nextString();
+ fail("expected ex");
+ } catch (ATParseEx ex) {
+ //test pass
+ }
+
+ p = new ATResponseParser("+FOO: \"\"");
+ assertEquals("", p.nextString());
+ }
+}
diff --git a/tests/CoreTests/com/android/internal/telephony/PhoneNumberUtilsTest.java b/tests/CoreTests/com/android/internal/telephony/PhoneNumberUtilsTest.java
new file mode 100644
index 0000000..e8bd239
--- /dev/null
+++ b/tests/CoreTests/com/android/internal/telephony/PhoneNumberUtilsTest.java
@@ -0,0 +1,326 @@
+/*
+ * Copyright (C) 2006 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.internal.telephony;
+
+import android.test.suitebuilder.annotation.SmallTest;
+import android.text.SpannableStringBuilder;
+import android.telephony.PhoneNumberUtils;
+
+import junit.framework.TestCase;
+
+public class PhoneNumberUtilsTest extends TestCase {
+
+ @SmallTest
+ public void testA() throws Exception {
+ assertEquals(
+ "+17005554141",
+ PhoneNumberUtils.extractNetworkPortion("+17005554141")
+ );
+
+ assertEquals(
+ "+17005554141",
+ PhoneNumberUtils.extractNetworkPortion("+1 (700).555-4141")
+ );
+
+ assertEquals(
+ "17005554141",
+ PhoneNumberUtils.extractNetworkPortion("1 (700).555-4141")
+ );
+
+ // This may seem wrong, but it's probably ok
+ assertEquals(
+ "17005554141*#",
+ PhoneNumberUtils.extractNetworkPortion("1 (700).555-4141*#")
+ );
+
+ assertEquals(
+ "170055541NN",
+ PhoneNumberUtils.extractNetworkPortion("1 (700).555-41NN")
+ );
+
+ assertEquals(
+ "170055541NN",
+ PhoneNumberUtils.extractNetworkPortion("1 (700).555-41NN,1234")
+ );
+
+ assertEquals(
+ "170055541NN",
+ PhoneNumberUtils.extractNetworkPortion("1 (700).555-41NN;1234")
+ );
+
+ // An MMI string is unperterbed, even though it contains a
+ // (valid in this case) embedded +
+ assertEquals(
+ "**21**17005554141#",
+ PhoneNumberUtils.extractNetworkPortion("**21**+17005554141#")
+ //TODO this is the correct result, although the above
+ //result has been returned since change 31776
+ //"**21**+17005554141#"
+ );
+
+ assertEquals("", PhoneNumberUtils.extractNetworkPortion(""));
+
+ assertEquals("", PhoneNumberUtils.extractNetworkPortion(",1234"));
+
+ byte [] b = new byte[20];
+ b[0] = (byte) 0x81; b[1] = (byte) 0x71; b[2] = (byte) 0x00; b[3] = (byte) 0x55;
+ b[4] = (byte) 0x05; b[5] = (byte) 0x20; b[6] = (byte) 0xF0;
+ assertEquals("17005550020",
+ PhoneNumberUtils.calledPartyBCDToString(b, 0, 7));
+
+ b[0] = (byte) 0x91; b[1] = (byte) 0x71; b[2] = (byte) 0x00; b[3] = (byte) 0x55;
+ b[4] = (byte) 0x05; b[5] = (byte) 0x20; b[6] = (byte) 0xF0;
+ assertEquals("+17005550020",
+ PhoneNumberUtils.calledPartyBCDToString(b, 0, 7));
+
+ byte[] bRet = PhoneNumberUtils.networkPortionToCalledPartyBCD("+17005550020");
+ assertEquals(7, bRet.length);
+ for (int i = 0; i < 7; i++) {
+ assertEquals(b[i], bRet[i]);
+ }
+
+ bRet = PhoneNumberUtils.networkPortionToCalledPartyBCD("7005550020");
+ assertEquals("7005550020",
+ PhoneNumberUtils.calledPartyBCDToString(bRet, 0, bRet.length));
+
+ b[0] = (byte) 0x81; b[1] = (byte) 0x71; b[2] = (byte) 0x00; b[3] = (byte) 0x55;
+ b[4] = (byte) 0x05; b[5] = (byte) 0x20; b[6] = (byte) 0xB0;
+ assertEquals("17005550020#",
+ PhoneNumberUtils.calledPartyBCDToString(b, 0, 7));
+
+ b[0] = (byte) 0x91; b[1] = (byte) 0x71; b[2] = (byte) 0x00; b[3] = (byte) 0x55;
+ b[4] = (byte) 0x05; b[5] = (byte) 0x20; b[6] = (byte) 0xB0;
+ assertEquals("+17005550020#",
+ PhoneNumberUtils.calledPartyBCDToString(b, 0, 7));
+
+ b[0] = (byte) 0x81; b[1] = (byte) 0x2A; b[2] = (byte) 0xB1;
+ assertEquals("*21#",
+ PhoneNumberUtils.calledPartyBCDToString(b, 0, 3));
+
+ b[0] = (byte) 0x81; b[1] = (byte) 0x2B; b[2] = (byte) 0xB1;
+ assertEquals("#21#",
+ PhoneNumberUtils.calledPartyBCDToString(b, 0, 3));
+
+ b[0] = (byte) 0x91; b[1] = (byte) 0x2A; b[2] = (byte) 0xB1;
+ assertEquals("*21#+",
+ PhoneNumberUtils.calledPartyBCDToString(b, 0, 3));
+
+ b[0] = (byte) 0x81; b[1] = (byte) 0xAA; b[2] = (byte) 0x12; b[3] = (byte) 0xFB;
+ assertEquals("**21#",
+ PhoneNumberUtils.calledPartyBCDToString(b, 0, 4));
+
+ b[0] = (byte) 0x91; b[1] = (byte) 0xAA; b[2] = (byte) 0x12; b[3] = (byte) 0xFB;
+ assertEquals("**21#+",
+ PhoneNumberUtils.calledPartyBCDToString(b, 0, 4));
+
+ b[0] = (byte) 0x81; b[1] = (byte) 0x9A; b[2] = (byte) 0xA9; b[3] = (byte) 0x71;
+ b[4] = (byte) 0x00; b[5] = (byte) 0x55; b[6] = (byte) 0x05; b[7] = (byte) 0x20;
+ b[8] = (byte) 0xB0;
+ assertEquals("*99*17005550020#",
+ PhoneNumberUtils.calledPartyBCDToString(b, 0, 9));
+
+ b[0] = (byte) 0x91; b[1] = (byte) 0x9A; b[2] = (byte) 0xA9; b[3] = (byte) 0x71;
+ b[4] = (byte) 0x00; b[5] = (byte) 0x55; b[6] = (byte) 0x05; b[7] = (byte) 0x20;
+ b[8] = (byte) 0xB0;
+ assertEquals("*99*+17005550020#",
+ PhoneNumberUtils.calledPartyBCDToString(b, 0, 9));
+
+ b[0] = (byte) 0x81; b[1] = (byte) 0xAA; b[2] = (byte) 0x12; b[3] = (byte) 0x1A;
+ b[4] = (byte) 0x07; b[5] = (byte) 0x50; b[6] = (byte) 0x55; b[7] = (byte) 0x00;
+ b[8] = (byte) 0x02; b[9] = (byte) 0xFB;
+ assertEquals("**21*17005550020#",
+ PhoneNumberUtils.calledPartyBCDToString(b, 0, 10));
+
+ b[0] = (byte) 0x91; b[1] = (byte) 0xAA; b[2] = (byte) 0x12; b[3] = (byte) 0x1A;
+ b[4] = (byte) 0x07; b[5] = (byte) 0x50; b[6] = (byte) 0x55; b[7] = (byte) 0x00;
+ b[8] = (byte) 0x02; b[9] = (byte) 0xFB;
+ assertEquals("**21*+17005550020#",
+ PhoneNumberUtils.calledPartyBCDToString(b, 0, 10));
+
+ b[0] = (byte) 0x81; b[1] = (byte) 0x2A; b[2] = (byte) 0xA1; b[3] = (byte) 0x71;
+ b[4] = (byte) 0x00; b[5] = (byte) 0x55; b[6] = (byte) 0x05; b[7] = (byte) 0x20;
+ b[8] = (byte) 0xF0;
+ assertEquals("*21*17005550020",
+ PhoneNumberUtils.calledPartyBCDToString(b, 0, 9));
+
+ b[0] = (byte) 0x91; b[1] = (byte) 0x2A; b[2] = (byte) 0xB1; b[3] = (byte) 0x71;
+ b[4] = (byte) 0x00; b[5] = (byte) 0x55; b[6] = (byte) 0x05; b[7] = (byte) 0x20;
+ b[8] = (byte) 0xF0;
+ assertEquals("*21#+17005550020",
+ PhoneNumberUtils.calledPartyBCDToString(b, 0, 9));
+
+ assertNull(PhoneNumberUtils.extractNetworkPortion(null));
+ assertNull(PhoneNumberUtils.extractPostDialPortion(null));
+ assertTrue(PhoneNumberUtils.compare(null, null));
+ assertFalse(PhoneNumberUtils.compare(null, "123"));
+ assertFalse(PhoneNumberUtils.compare("123", null));
+ assertNull(PhoneNumberUtils.toCallerIDMinMatch(null));
+ assertNull(PhoneNumberUtils.getStrippedReversed(null));
+ assertNull(PhoneNumberUtils.stringFromStringAndTOA(null, 1));
+ }
+
+ @SmallTest
+ public void testB() throws Exception {
+ assertEquals("", PhoneNumberUtils.extractPostDialPortion("+17005554141"));
+ assertEquals("", PhoneNumberUtils.extractPostDialPortion("+1 (700).555-4141"));
+ assertEquals("", PhoneNumberUtils.extractPostDialPortion("+1 (700).555-41NN"));
+ assertEquals(",1234", PhoneNumberUtils.extractPostDialPortion("+1 (700).555-41NN,1234"));
+ assertEquals(";1234", PhoneNumberUtils.extractPostDialPortion("+1 (700).555-41NN;1234"));
+ assertEquals(";1234,;N",
+ PhoneNumberUtils.extractPostDialPortion("+1 (700).555-41NN;1-2.34 ,;N"));
+ }
+
+ @SmallTest
+ public void testCompare() throws Exception {
+ // this is odd
+ assertFalse(PhoneNumberUtils.compare("", ""));
+
+ assertTrue(PhoneNumberUtils.compare("911", "911"));
+ assertFalse(PhoneNumberUtils.compare("911", "18005550911"));
+ assertTrue(PhoneNumberUtils.compare("5555", "5555"));
+ assertFalse(PhoneNumberUtils.compare("5555", "180055555555"));
+
+ assertTrue(PhoneNumberUtils.compare("+17005554141", "+17005554141"));
+ assertTrue(PhoneNumberUtils.compare("+17005554141", "+1 (700).555-4141"));
+ assertTrue(PhoneNumberUtils.compare("+17005554141", "+1 (700).555-4141,1234"));
+ assertTrue(PhoneNumberUtils.compare("+17005554141", "17005554141"));
+ assertTrue(PhoneNumberUtils.compare("+17005554141", "7005554141"));
+ assertTrue(PhoneNumberUtils.compare("+17005554141", "5554141"));
+ assertTrue(PhoneNumberUtils.compare("17005554141", "5554141"));
+ assertTrue(PhoneNumberUtils.compare("+17005554141", "01117005554141"));
+ assertTrue(PhoneNumberUtils.compare("+17005554141", "0017005554141"));
+ assertTrue(PhoneNumberUtils.compare("17005554141", "0017005554141"));
+
+
+ assertTrue(PhoneNumberUtils.compare("+17005554141", "**31#+17005554141"));
+
+ assertFalse(PhoneNumberUtils.compare("+1 999 7005554141", "+1 7005554141"));
+ assertTrue(PhoneNumberUtils.compare("011 1 7005554141", "7005554141"));
+
+ assertFalse(PhoneNumberUtils.compare("011 11 7005554141", "+17005554141"));
+
+ assertFalse(PhoneNumberUtils.compare("+17005554141", "7085882300"));
+
+ assertTrue(PhoneNumberUtils.compare("+44 207 792 3490", "0 207 792 3490"));
+
+ assertFalse(PhoneNumberUtils.compare("+44 207 792 3490", "00 207 792 3490"));
+ assertFalse(PhoneNumberUtils.compare("+44 207 792 3490", "011 207 792 3490"));
+
+ /***** FIXME's ******/
+ //
+ // MMI header should be ignored
+ assertFalse(PhoneNumberUtils.compare("+17005554141", "**31#17005554141"));
+
+ // It's too bad this is false
+ // +44 (0) 207 792 3490 is not a dialable number
+ // but it is commonly how European phone numbers are written
+ assertFalse(PhoneNumberUtils.compare("+44 207 792 3490", "+44 (0) 207 792 3490"));
+
+ // The japanese international prefix, for example, messes us up
+ // But who uses a GSM phone in Japan?
+ assertFalse(PhoneNumberUtils.compare("+44 207 792 3490", "010 44 207 792 3490"));
+
+ // The Australian one messes us up too
+ assertFalse(PhoneNumberUtils.compare("+44 207 792 3490", "0011 44 207 792 3490"));
+
+ // The Russian trunk prefix messes us up, as does current
+ // Russian area codes (which bein with 0)
+
+ assertFalse(PhoneNumberUtils.compare("+7(095)9100766", "8(095)9100766"));
+
+ // 444 is not a valid country code, but
+ // matchIntlPrefixAndCC doesnt know this
+ assertTrue(PhoneNumberUtils.compare("+444 207 792 3490", "0 207 792 3490"));
+ }
+
+
+ @SmallTest
+ public void testToCallerIDIndexable() throws Exception {
+ assertEquals("14145", PhoneNumberUtils.toCallerIDMinMatch("17005554141"));
+ assertEquals("14145", PhoneNumberUtils.toCallerIDMinMatch("1-700-555-4141"));
+ assertEquals("14145", PhoneNumberUtils.toCallerIDMinMatch("1-700-555-4141,1234"));
+ assertEquals("14145", PhoneNumberUtils.toCallerIDMinMatch("1-700-555-4141;1234"));
+
+ //this seems wrong, or at least useless
+ assertEquals("NN145", PhoneNumberUtils.toCallerIDMinMatch("1-700-555-41NN"));
+
+ //<shrug> -- these are all not useful, but not terribly wrong
+ assertEquals("", PhoneNumberUtils.toCallerIDMinMatch(""));
+ assertEquals("0032", PhoneNumberUtils.toCallerIDMinMatch("2300"));
+ assertEquals("0032+", PhoneNumberUtils.toCallerIDMinMatch("+2300"));
+ assertEquals("#130#", PhoneNumberUtils.toCallerIDMinMatch("*#031#"));
+ }
+
+ @SmallTest
+ public void testGetIndexable() throws Exception {
+ assertEquals("14145550071", PhoneNumberUtils.getStrippedReversed("1-700-555-4141"));
+ assertEquals("14145550071", PhoneNumberUtils.getStrippedReversed("1-700-555-4141,1234"));
+ assertEquals("14145550071", PhoneNumberUtils.getStrippedReversed("1-700-555-4141;1234"));
+
+ //this seems wrong, or at least useless
+ assertEquals("NN145550071", PhoneNumberUtils.getStrippedReversed("1-700-555-41NN"));
+
+ //<shrug> -- these are all not useful, but not terribly wrong
+ assertEquals("", PhoneNumberUtils.getStrippedReversed(""));
+ assertEquals("0032", PhoneNumberUtils.getStrippedReversed("2300"));
+ assertEquals("0032+", PhoneNumberUtils.getStrippedReversed("+2300"));
+ assertEquals("#130#*", PhoneNumberUtils.getStrippedReversed("*#031#"));
+ }
+
+ @SmallTest
+ public void testNanpFormatting() {
+ SpannableStringBuilder number = new SpannableStringBuilder();
+ number.append("8005551212");
+ PhoneNumberUtils.formatNanpNumber(number);
+ assertEquals("800-555-1212", number.toString());
+
+ number.clear();
+ number.append("800555121");
+ PhoneNumberUtils.formatNanpNumber(number);
+ assertEquals("800-555-121", number.toString());
+
+ number.clear();
+ number.append("555-1212");
+ PhoneNumberUtils.formatNanpNumber(number);
+ assertEquals("555-1212", number.toString());
+
+ number.clear();
+ number.append("800-55512");
+ PhoneNumberUtils.formatNanpNumber(number);
+ assertEquals("800-555-12", number.toString());
+ }
+
+ @SmallTest
+ public void testConvertKeypadLettersToDigits() {
+ assertEquals("1-800-4664-411",
+ PhoneNumberUtils.convertKeypadLettersToDigits("1-800-GOOG-411"));
+ assertEquals("18004664411",
+ PhoneNumberUtils.convertKeypadLettersToDigits("1800GOOG411"));
+ assertEquals("1-800-466-4411",
+ PhoneNumberUtils.convertKeypadLettersToDigits("1-800-466-4411"));
+ assertEquals("18004664411",
+ PhoneNumberUtils.convertKeypadLettersToDigits("18004664411"));
+ assertEquals("222-333-444-555-666-7777-888-9999",
+ PhoneNumberUtils.convertKeypadLettersToDigits(
+ "ABC-DEF-GHI-JKL-MNO-PQRS-TUV-WXYZ"));
+ assertEquals("222-333-444-555-666-7777-888-9999",
+ PhoneNumberUtils.convertKeypadLettersToDigits(
+ "abc-def-ghi-jkl-mno-pqrs-tuv-wxyz"));
+ assertEquals("(800) 222-3334",
+ PhoneNumberUtils.convertKeypadLettersToDigits("(800) ABC-DEFG"));
+ }
+}
diff --git a/tests/CoreTests/com/android/internal/telephony/PhoneNumberWatcherTest.java b/tests/CoreTests/com/android/internal/telephony/PhoneNumberWatcherTest.java
new file mode 100644
index 0000000..88eaecd
--- /dev/null
+++ b/tests/CoreTests/com/android/internal/telephony/PhoneNumberWatcherTest.java
@@ -0,0 +1,65 @@
+/*
+ * 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.internal.telephony;
+
+import android.telephony.PhoneNumberFormattingTextWatcher;
+import android.test.suitebuilder.annotation.SmallTest;
+import android.text.Selection;
+import android.text.SpannableStringBuilder;
+import android.text.TextWatcher;
+
+import junit.framework.TestCase;
+
+public class PhoneNumberWatcherTest extends TestCase {
+ @SmallTest
+ public void testHyphenation() throws Exception {
+ SpannableStringBuilder number = new SpannableStringBuilder();
+ TextWatcher tw = new PhoneNumberFormattingTextWatcher();
+ number.append("555-1212");
+ // Move the cursor to the left edge
+ Selection.setSelection(number, 0);
+ tw.beforeTextChanged(number, 0, 0, 1);
+ // Insert an 8 at the beginning
+ number.insert(0, "8");
+ tw.afterTextChanged(number);
+ assertEquals("855-512-12", number.toString());
+ }
+
+ @SmallTest
+ public void testHyphenDeletion() throws Exception {
+ SpannableStringBuilder number = new SpannableStringBuilder();
+ TextWatcher tw = new PhoneNumberFormattingTextWatcher();
+ number.append("555-1212");
+ // Move the cursor to after the hyphen
+ Selection.setSelection(number, 4);
+ // Delete the hyphen
+ tw.beforeTextChanged(number, 3, 1, 0);
+ number.delete(3, 4);
+ tw.afterTextChanged(number);
+ // Make sure that it deleted the character before the hyphen
+ assertEquals("551-212", number.toString());
+
+ // Make sure it deals with left edge boundary case
+ number.insert(0, "-");
+ Selection.setSelection(number, 1);
+ tw.beforeTextChanged(number, 0, 1, 0);
+ number.delete(0, 1);
+ tw.afterTextChanged(number);
+ // Make sure that it deleted the character before the hyphen
+ assertEquals("551-212", number.toString());
+ }
+}
diff --git a/tests/CoreTests/com/android/internal/telephony/TelephonyTests.java b/tests/CoreTests/com/android/internal/telephony/TelephonyTests.java
new file mode 100644
index 0000000..eb2bd23
--- /dev/null
+++ b/tests/CoreTests/com/android/internal/telephony/TelephonyTests.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2006 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.internal.telephony;
+
+import com.android.internal.telephony.gsm.AdnRecordTest;
+import com.android.internal.telephony.gsm.GSMPhoneTest;
+import com.android.internal.telephony.gsm.GsmAlphabetTest;
+import com.android.internal.telephony.gsm.SMSDispatcherTest;
+import com.android.internal.telephony.gsm.SimPhoneBookTest;
+import com.android.internal.telephony.gsm.SimSmsTest;
+import com.android.internal.telephony.gsm.SimUtilsTest;
+
+import junit.framework.TestSuite;
+
+/**
+ * To run these tests:
+ * $ mmm java/tests && adb sync
+ * $ adb shell am instrument -w \
+ * -e class com.android.internal.telephony.TelephonyTests \
+ * android.core/android.test.InstrumentationTestRunner
+ */
+public class TelephonyTests {
+ public static TestSuite suite() {
+ TestSuite suite = new TestSuite(TelephonyTests.class.getName());
+
+ suite.addTestSuite(PhoneNumberWatcherTest.class);
+ suite.addTestSuite(ATResponseParserTest.class);
+ suite.addTestSuite(PhoneNumberUtilsTest.class);
+ suite.addTestSuite(SMSDispatcherTest.class);
+ //suite.addTestSuite(GSMPhoneTest.class);
+ suite.addTestSuite(AdnRecordTest.class);
+ suite.addTestSuite(GsmAlphabetTest.class);
+ suite.addTestSuite(SimUtilsTest.class);
+ suite.addTestSuite(SimPhoneBookTest.class);
+ suite.addTestSuite(SimSmsTest.class);
+
+ return suite;
+ }
+}
diff --git a/tests/CoreTests/com/android/internal/telephony/TestPhoneNotifier.java b/tests/CoreTests/com/android/internal/telephony/TestPhoneNotifier.java
new file mode 100644
index 0000000..427795b
--- /dev/null
+++ b/tests/CoreTests/com/android/internal/telephony/TestPhoneNotifier.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2006 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.internal.telephony;
+
+/**
+ * Stub class used for unit tests
+ */
+
+public class TestPhoneNotifier implements PhoneNotifier {
+ public TestPhoneNotifier() {
+ }
+
+ public void notifyPhoneState(Phone sender) {
+ }
+
+ public void notifyServiceState(Phone sender) {
+ }
+
+ public void notifyCellLocation(Phone sender) {
+ }
+
+ public void notifySignalStrength(Phone sender) {
+ }
+
+ public void notifyMessageWaitingChanged(Phone sender) {
+ }
+
+ public void notifyCallForwardingChanged(Phone sender) {
+ }
+
+ public void notifyDataConnection(Phone sender, String reason) {
+ }
+
+ public void notifyDataConnectionFailed(Phone sender, String reason) {
+ }
+
+ public void notifyDataActivity(Phone sender) {
+ }
+}
diff --git a/tests/CoreTests/com/android/internal/telephony/gsm/AdnRecordTest.java b/tests/CoreTests/com/android/internal/telephony/gsm/AdnRecordTest.java
new file mode 100644
index 0000000..6cafdf0
--- /dev/null
+++ b/tests/CoreTests/com/android/internal/telephony/gsm/AdnRecordTest.java
@@ -0,0 +1,176 @@
+/*
+ * Copyright (C) 2006 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.internal.telephony.gsm;
+
+import junit.framework.TestCase;
+import android.test.suitebuilder.annotation.SmallTest;
+
+/**
+ * {@hide}
+ */
+public class AdnRecordTest extends TestCase {
+
+ @SmallTest
+ public void testBasic() throws Exception {
+ AdnRecord adn;
+
+ //
+ // Typical record
+ //
+ adn = new AdnRecord(
+ SimUtils.hexStringToBytes("566F696365204D61696C07918150367742F3FFFFFFFFFFFF"));
+
+ assertEquals("Voice Mail", adn.getAlphaTag());
+ assertEquals("+18056377243", adn.getNumber());
+ assertFalse(adn.isEmpty());
+
+ //
+ // Empty records, empty strings
+ //
+ adn = new AdnRecord(
+ SimUtils.hexStringToBytes("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"));
+
+ assertEquals("", adn.getAlphaTag());
+ assertEquals("", adn.getNumber());
+ assertTrue(adn.isEmpty());
+
+ //
+ // Record too short
+ //
+ adn = new AdnRecord(SimUtils.hexStringToBytes( "FF"));
+
+ assertEquals("", adn.getAlphaTag());
+ assertEquals("", adn.getNumber());
+ assertTrue(adn.isEmpty());
+
+ //
+ // TOA = 0xff ("control string")
+ //
+ adn = new AdnRecord(
+ SimUtils.hexStringToBytes("566F696365204D61696C07FF8150367742F3FFFFFFFFFFFF"));
+
+ assertEquals("Voice Mail", adn.getAlphaTag());
+ assertEquals("18056377243", adn.getNumber());
+ assertFalse(adn.isEmpty());
+
+ //
+ // TOA = 0x81 (unknown)
+ //
+ adn = new AdnRecord(
+ SimUtils.hexStringToBytes("566F696365204D61696C07818150367742F3FFFFFFFFFFFF"));
+
+ assertEquals("Voice Mail", adn.getAlphaTag());
+ assertEquals("18056377243", adn.getNumber());
+ assertFalse(adn.isEmpty());
+
+ //
+ // Number Length is too long
+ //
+ adn = new AdnRecord(
+ SimUtils.hexStringToBytes("566F696365204D61696C0F918150367742F3FFFFFFFFFFFF"));
+
+ assertEquals("Voice Mail", adn.getAlphaTag());
+ assertEquals("", adn.getNumber());
+ assertFalse(adn.isEmpty());
+
+ //
+ // Number Length is zero (invalid)
+ //
+ adn = new AdnRecord(
+ SimUtils.hexStringToBytes("566F696365204D61696C00918150367742F3FFFFFFFFFFFF"));
+
+ assertEquals("Voice Mail", adn.getAlphaTag());
+ assertEquals("", adn.getNumber());
+ assertFalse(adn.isEmpty());
+
+ //
+ // Number Length is 2, first number byte is FF, TOA is international
+ //
+ adn = new AdnRecord(
+ SimUtils.hexStringToBytes("566F696365204D61696C0291FF50367742F3FFFFFFFFFFFF"));
+
+ assertEquals("Voice Mail", adn.getAlphaTag());
+ assertEquals("", adn.getNumber());
+ assertFalse(adn.isEmpty());
+
+ //
+ // Number Length is 2, first number digit is valid, TOA is international
+ //
+ adn = new AdnRecord(
+ SimUtils.hexStringToBytes("566F696365204D61696C0291F150367742F3FFFFFFFFFFFF"));
+
+ assertEquals("Voice Mail", adn.getAlphaTag());
+ assertEquals("+1", adn.getNumber());
+ assertFalse(adn.isEmpty());
+
+ //
+ // An extended record
+ //
+ adn = new AdnRecord(
+ SimUtils.hexStringToBytes(
+ "4164676A6DFFFFFFFFFFFFFFFFFFFFFF0B918188551512C221436587FF01"));
+
+ assertEquals("Adgjm", adn.getAlphaTag());
+ assertEquals("+18885551212,12345678", adn.getNumber());
+ assertFalse(adn.isEmpty());
+ assertTrue(adn.hasExtendedRecord());
+
+ adn.appendExtRecord(SimUtils.hexStringToBytes("0206092143658709ffffffffff"));
+
+ assertEquals("Adgjm", adn.getAlphaTag());
+ assertEquals("+18885551212,12345678901234567890", adn.getNumber());
+ assertFalse(adn.isEmpty());
+
+ //
+ // An extended record with an invalid extension
+ //
+ adn = new AdnRecord(
+ SimUtils.hexStringToBytes(
+ "4164676A6DFFFFFFFFFFFFFFFFFFFFFF0B918188551512C221436587FF01"));
+
+ assertEquals("Adgjm", adn.getAlphaTag());
+ assertEquals("+18885551212,12345678", adn.getNumber());
+ assertFalse(adn.isEmpty());
+ assertTrue(adn.hasExtendedRecord());
+
+ adn.appendExtRecord(SimUtils.hexStringToBytes("0106092143658709ffffffffff"));
+
+ assertEquals("Adgjm", adn.getAlphaTag());
+ assertEquals("+18885551212,12345678", adn.getNumber());
+ assertFalse(adn.isEmpty());
+
+ //
+ // An extended record with an invalid extension
+ //
+ adn = new AdnRecord(
+ SimUtils.hexStringToBytes(
+ "4164676A6DFFFFFFFFFFFFFFFFFFFFFF0B918188551512C221436587FF01"));
+
+ assertEquals("Adgjm", adn.getAlphaTag());
+ assertEquals("+18885551212,12345678", adn.getNumber());
+ assertFalse(adn.isEmpty());
+ assertTrue(adn.hasExtendedRecord());
+
+ adn.appendExtRecord(SimUtils.hexStringToBytes("020B092143658709ffffffffff"));
+
+ assertEquals("Adgjm", adn.getAlphaTag());
+ assertEquals("+18885551212,12345678", adn.getNumber());
+ assertFalse(adn.isEmpty());
+ }
+}
+
+
diff --git a/tests/CoreTests/com/android/internal/telephony/gsm/GSMPhoneTest.java b/tests/CoreTests/com/android/internal/telephony/gsm/GSMPhoneTest.java
new file mode 100644
index 0000000..7107412
--- /dev/null
+++ b/tests/CoreTests/com/android/internal/telephony/gsm/GSMPhoneTest.java
@@ -0,0 +1,1938 @@
+/*
+ * Copyright (C) 2007 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 GSMTestHandler.ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.telephony.gsm;
+
+import android.os.AsyncResult;
+import android.os.Handler;
+import android.os.HandlerThread;
+import android.os.Looper;
+import android.os.Message;
+import android.os.Process;
+import android.telephony.ServiceState;
+import android.test.AndroidTestCase;
+import android.test.PerformanceTestCase;
+import android.util.Log;
+
+import com.android.internal.telephony.Call;
+import com.android.internal.telephony.CallStateException;
+import com.android.internal.telephony.Connection;
+import com.android.internal.telephony.MmiCode;
+import com.android.internal.telephony.Phone;
+import com.android.internal.telephony.TestPhoneNotifier;
+import com.android.internal.telephony.gsm.CallFailCause;
+import com.android.internal.telephony.gsm.GSMPhone;
+import com.android.internal.telephony.gsm.GSMTestHandler;
+import com.android.internal.telephony.gsm.GsmMmiCode;
+import com.android.internal.telephony.gsm.SuppServiceNotification;
+import com.android.internal.telephony.test.SimulatedCommands;
+import com.android.internal.telephony.test.SimulatedRadioControl;
+
+import java.util.List;
+
+
+public class GSMPhoneTest extends AndroidTestCase implements PerformanceTestCase {
+ private SimulatedRadioControl mRadioControl;
+ private GSMPhone mGSMPhone;
+ private GSMTestHandler mGSMTestHandler;
+ private Handler mHandler;
+
+ private static final int EVENT_PHONE_STATE_CHANGED = 1;
+ private static final int EVENT_DISCONNECT = 2;
+ private static final int EVENT_RINGING = 3;
+ private static final int EVENT_CHANNEL_OPENED = 4;
+ private static final int EVENT_POST_DIAL = 5;
+ private static final int EVENT_DONE = 6;
+ private static final int EVENT_SSN = 7;
+ private static final int EVENT_MMI_INITIATE = 8;
+ private static final int EVENT_MMI_COMPLETE = 9;
+ private static final int EVENT_IN_SERVICE = 10;
+ private static final int SUPP_SERVICE_FAILED = 11;
+ private static final int SERVICE_STATE_CHANGED = 12;
+ private static final int EVENT_OEM_RIL_MESSAGE = 13;
+ public static final int ANY_MESSAGE = -1;
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ mGSMTestHandler = new GSMTestHandler(mContext);
+
+ mGSMTestHandler.start();
+ synchronized (mGSMTestHandler) {
+ do {
+ mGSMTestHandler.wait();
+ } while (mGSMTestHandler.getGSMPhone() == null);
+ }
+
+ mGSMPhone = mGSMTestHandler.getGSMPhone();
+ mRadioControl = mGSMTestHandler.getSimulatedCommands();
+
+ mHandler = mGSMTestHandler.getHandler();
+ mGSMPhone.registerForPhoneStateChanged(mHandler, EVENT_PHONE_STATE_CHANGED, null);
+ mGSMPhone.registerForNewRingingConnection(mHandler, EVENT_RINGING, null);
+ mGSMPhone.registerForDisconnect(mHandler, EVENT_DISCONNECT, null);
+
+ mGSMPhone.setOnPostDialCharacter(mHandler, EVENT_POST_DIAL, null);
+
+ mGSMPhone.registerForSuppServiceNotification(mHandler, EVENT_SSN, null);
+ mGSMPhone.registerForMmiInitiate(mHandler, EVENT_MMI_INITIATE, null);
+ mGSMPhone.registerForMmiComplete(mHandler, EVENT_MMI_COMPLETE, null);
+ mGSMPhone.registerForSuppServiceFailed(mHandler, SUPP_SERVICE_FAILED, null);
+
+ mGSMPhone.registerForServiceStateChanged(mHandler, SERVICE_STATE_CHANGED, null);
+
+ // wait until we get phone in both voice and data service
+ Message msg;
+ ServiceState state;
+
+ do {
+ msg = mGSMTestHandler.waitForMessage(SERVICE_STATE_CHANGED);
+ assertNotNull("Message Time Out", msg);
+ state = (ServiceState) ((AsyncResult) msg.obj).result;
+ } while (state.getState() != ServiceState.STATE_IN_SERVICE);
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
+ mRadioControl.shutdown();
+
+ mGSMPhone.unregisterForPhoneStateChanged(mHandler);
+ mGSMPhone.unregisterForNewRingingConnection(mHandler);
+ mGSMPhone.unregisterForDisconnect(mHandler);
+ mGSMPhone.setOnPostDialCharacter(mHandler, 0, null);
+ mGSMPhone.unregisterForSuppServiceNotification(mHandler);
+ mGSMPhone.unregisterForMmiInitiate(mHandler);
+ mGSMPhone.unregisterForMmiComplete(mHandler);
+
+ mGSMPhone = null;
+ mRadioControl = null;
+ mHandler = null;
+ mGSMTestHandler.cleanup();
+
+ super.tearDown();
+ }
+
+ // These test can only be run once.
+ public int startPerformance(Intermediates intermediates) {
+ return 1;
+ }
+
+ public boolean isPerformanceOnly() {
+ return false;
+ }
+
+
+ //This test is causing the emulator screen to turn off. I don't understand
+ //why, but I'm removing it until we can figure it out.
+ public void brokenTestGeneral() throws Exception {
+ Connection cn;
+ Message msg;
+ AsyncResult ar;
+
+ // IDLE state
+
+ assertEquals(Phone.State.IDLE, mGSMPhone.getState());
+ assertEquals(0, mGSMPhone.getRingingCall().getConnections().size());
+ assertEquals(0, mGSMPhone.getForegroundCall().getConnections().size());
+ assertEquals(0, mGSMPhone.getBackgroundCall().getConnections().size());
+
+ assertEquals(Call.State.IDLE, mGSMPhone.getRingingCall().getState());
+ assertEquals(Call.State.IDLE, mGSMPhone.getForegroundCall().getState());
+ assertEquals(Call.State.IDLE, mGSMPhone.getBackgroundCall().getState());
+
+ assertEquals(0, mGSMPhone.getForegroundCall().getEarliestCreateTime());
+ assertEquals(0, mGSMPhone.getForegroundCall().getEarliestConnectTime());
+ assertFalse(mGSMPhone.canConference());
+
+ // One DIALING connection
+
+ mRadioControl.setAutoProgressConnectingCall(false);
+
+ mGSMPhone.dial("+13125551212");
+
+ assertEquals(Phone.State.OFFHOOK, mGSMPhone.getState());
+
+ msg = mGSMTestHandler.waitForMessage(EVENT_PHONE_STATE_CHANGED);
+ assertNotNull("Message Time Out", msg);
+
+ assertEquals(Phone.State.OFFHOOK, mGSMPhone.getState());
+ assertEquals(Call.State.DIALING, mGSMPhone.getForegroundCall().getState());
+ assertTrue(mGSMPhone.getForegroundCall().isDialingOrAlerting());
+
+ /*do {
+ mGSMTestHandler.waitForMessage(ANY_MESSAGE);
+ } while (mGSMPhone.getForegroundCall().getConnections().size() == 0);*/
+
+ assertEquals(0, mGSMPhone.getRingingCall().getConnections().size());
+ assertEquals(1, mGSMPhone.getForegroundCall().getConnections().size());
+ assertEquals(0, mGSMPhone.getBackgroundCall().getConnections().size());
+
+ assertEquals(Call.State.IDLE, mGSMPhone.getRingingCall().getState());
+ assertEquals(Call.State.DIALING,
+ mGSMPhone.getForegroundCall().getState());
+ assertEquals(Call.State.IDLE, mGSMPhone.getBackgroundCall().getState());
+
+ assertTrue(mGSMPhone.getForegroundCall().getEarliestCreateTime() > 0);
+ assertEquals(0, mGSMPhone.getForegroundCall().getEarliestConnectTime());
+
+ cn = mGSMPhone.getForegroundCall().getConnections().get(0);
+ assertTrue(!cn.isIncoming());
+ assertEquals(Connection.PostDialState.NOT_STARTED, cn.getPostDialState());
+
+ assertEquals(Connection.DisconnectCause.NOT_DISCONNECTED, cn.getDisconnectCause());
+
+ assertFalse(mGSMPhone.canConference());
+
+ // One ALERTING connection
+
+ mRadioControl.progressConnectingCallState();
+
+ do {
+ assertNotNull("Message Time Out", mGSMTestHandler.waitForMessage(ANY_MESSAGE));
+ }
+ while (mGSMPhone.getForegroundCall().getState() != Call.State.ALERTING);
+
+ assertEquals(Phone.State.OFFHOOK, mGSMPhone.getState());
+ assertTrue(mGSMPhone.getForegroundCall().isDialingOrAlerting());
+
+ assertEquals(0, mGSMPhone.getRingingCall().getConnections().size());
+ assertEquals(1, mGSMPhone.getForegroundCall().getConnections().size());
+ assertEquals(0, mGSMPhone.getBackgroundCall().getConnections().size());
+
+ assertEquals(Call.State.IDLE, mGSMPhone.getRingingCall().getState());
+ assertEquals(Call.State.ALERTING, mGSMPhone.getForegroundCall().getState());
+ assertEquals(Call.State.IDLE, mGSMPhone.getBackgroundCall().getState());
+
+ assertTrue(mGSMPhone.getForegroundCall().getEarliestCreateTime() > 0);
+ assertEquals(0, mGSMPhone.getForegroundCall().getEarliestConnectTime());
+
+ cn = mGSMPhone.getForegroundCall().getConnections().get(0);
+ assertTrue(!cn.isIncoming());
+ assertEquals(Connection.PostDialState.NOT_STARTED, cn.getPostDialState());
+ assertFalse(mGSMPhone.canConference());
+
+ // One ACTIVE connection
+
+ mRadioControl.progressConnectingCallState();
+
+ do {
+ assertNotNull("Message Time Out", mGSMTestHandler.waitForMessage(ANY_MESSAGE));
+ } while (mGSMPhone.getForegroundCall().getState() != Call.State.ACTIVE);
+
+ assertEquals(Phone.State.OFFHOOK, mGSMPhone.getState());
+ assertFalse(mGSMPhone.getForegroundCall().isDialingOrAlerting());
+
+ assertEquals(0, mGSMPhone.getRingingCall().getConnections().size());
+ assertEquals(1, mGSMPhone.getForegroundCall().getConnections().size());
+ assertEquals(0, mGSMPhone.getBackgroundCall().getConnections().size());
+
+ assertEquals(Call.State.IDLE, mGSMPhone.getRingingCall().getState());
+ assertEquals(Call.State.ACTIVE, mGSMPhone.getForegroundCall().getState());
+ assertEquals(Call.State.IDLE, mGSMPhone.getBackgroundCall().getState());
+
+ assertTrue(mGSMPhone.getForegroundCall().getEarliestCreateTime() > 0);
+ assertTrue(mGSMPhone.getForegroundCall().getEarliestConnectTime() > 0);
+
+ cn = mGSMPhone.getForegroundCall().getConnections().get(0);
+ assertTrue(!cn.isIncoming());
+ assertEquals(Connection.PostDialState.COMPLETE, cn.getPostDialState());
+ assertFalse(mGSMPhone.canConference());
+
+ // One disconnected connection
+ mGSMPhone.getForegroundCall().hangup();
+
+ msg = mGSMTestHandler.waitForMessage(EVENT_DISCONNECT);
+ assertNotNull("Message Time Out", msg);
+
+ assertEquals(Phone.State.IDLE, mGSMPhone.getState());
+ assertFalse(mGSMPhone.getForegroundCall().isDialingOrAlerting());
+
+ assertEquals(0, mGSMPhone.getRingingCall().getConnections().size());
+ assertEquals(1, mGSMPhone.getForegroundCall().getConnections().size());
+ assertEquals(0, mGSMPhone.getBackgroundCall().getConnections().size());
+
+ assertEquals(Call.State.IDLE, mGSMPhone.getRingingCall().getState());
+ assertEquals(Call.State.DISCONNECTED, mGSMPhone.getForegroundCall().getState());
+ assertEquals(Call.State.IDLE, mGSMPhone.getBackgroundCall().getState());
+
+ assertTrue(mGSMPhone.getForegroundCall().getEarliestCreateTime() > 0);
+ assertTrue(mGSMPhone.getForegroundCall().getEarliestConnectTime() > 0);
+
+ assertFalse(mGSMPhone.canConference());
+
+ cn = mGSMPhone.getForegroundCall().getEarliestConnection();
+
+ assertEquals(Call.State.DISCONNECTED, cn.getState());
+
+ // Back to idle state
+
+ mGSMPhone.clearDisconnected();
+
+ assertEquals(Phone.State.IDLE, mGSMPhone.getState());
+ assertFalse(mGSMPhone.getForegroundCall().isDialingOrAlerting());
+
+ assertEquals(0, mGSMPhone.getRingingCall().getConnections().size());
+ assertEquals(0, mGSMPhone.getForegroundCall().getConnections().size());
+ assertEquals(0, mGSMPhone.getBackgroundCall().getConnections().size());
+
+ assertEquals(Call.State.IDLE, mGSMPhone.getRingingCall().getState());
+ assertEquals(Call.State.IDLE, mGSMPhone.getForegroundCall().getState());
+ assertEquals(Call.State.IDLE, mGSMPhone.getBackgroundCall().getState());
+
+ assertEquals(0, mGSMPhone.getForegroundCall().getEarliestCreateTime());
+ assertEquals(0, mGSMPhone.getForegroundCall().getEarliestConnectTime());
+
+ assertFalse(mGSMPhone.canConference());
+
+ // cn left over from before phone.clearDisconnected();
+
+ assertEquals(Call.State.DISCONNECTED, cn.getState());
+
+ // One ringing (INCOMING) call
+
+ mRadioControl.triggerRing("18005551212");
+
+ msg = mGSMTestHandler.waitForMessage(EVENT_RINGING);
+ assertNotNull("Message Time Out", msg);
+
+ assertEquals(Phone.State.RINGING, mGSMPhone.getState());
+ assertTrue(mGSMPhone.getRingingCall().isRinging());
+
+ ar = (AsyncResult) msg.obj;
+ cn = (Connection) ar.result;
+ assertTrue(cn.isRinging());
+ assertEquals(mGSMPhone.getRingingCall(), cn.getCall());
+
+ assertEquals(1, mGSMPhone.getRingingCall().getConnections().size());
+ assertEquals(0, mGSMPhone.getForegroundCall().getConnections().size());
+ assertEquals(0, mGSMPhone.getBackgroundCall().getConnections().size());
+
+ assertEquals(Call.State.INCOMING, mGSMPhone.getRingingCall().getState());
+ assertEquals(Call.State.IDLE, mGSMPhone.getForegroundCall().getState());
+ assertEquals(Call.State.IDLE, mGSMPhone.getBackgroundCall().getState());
+
+ assertTrue(mGSMPhone.getRingingCall().getEarliestCreateTime() > 0);
+ assertEquals(0, mGSMPhone.getRingingCall().getEarliestConnectTime());
+
+ assertEquals(0, mGSMPhone.getForegroundCall().getEarliestCreateTime());
+ assertEquals(0, mGSMPhone.getForegroundCall().getEarliestConnectTime());
+
+ cn = mGSMPhone.getRingingCall().getConnections().get(0);
+ assertTrue(cn.isIncoming());
+ assertEquals(Connection.PostDialState.NOT_STARTED, cn.getPostDialState());
+
+ assertFalse(mGSMPhone.canConference());
+
+ // One mobile terminated active call
+ mGSMPhone.acceptCall();
+
+ do {
+ assertNotNull("Message Time Out", mGSMTestHandler.waitForMessage(ANY_MESSAGE));
+ } while (mGSMPhone.getRingingCall().getConnections().size() == 1);
+
+ assertEquals(Phone.State.OFFHOOK, mGSMPhone.getState());
+ assertFalse(mGSMPhone.getRingingCall().isRinging());
+
+ assertEquals(0, mGSMPhone.getRingingCall().getConnections().size());
+ assertEquals(1, mGSMPhone.getForegroundCall().getConnections().size());
+ assertEquals(0, mGSMPhone.getBackgroundCall().getConnections().size());
+
+ assertEquals(Call.State.IDLE, mGSMPhone.getRingingCall().getState());
+ assertEquals(Call.State.ACTIVE,
+ mGSMPhone.getForegroundCall().getState());
+ assertEquals(Call.State.IDLE, mGSMPhone.getBackgroundCall().getState());
+
+ assertTrue(mGSMPhone.getForegroundCall().getEarliestCreateTime() > 0);
+ assertTrue(mGSMPhone.getForegroundCall().getEarliestConnectTime() > 0);
+
+ cn = mGSMPhone.getForegroundCall().getConnections().get(0);
+ assertTrue(cn.isIncoming());
+ assertEquals(Connection.PostDialState.NOT_STARTED, cn.getPostDialState());
+
+ assertFalse(mGSMPhone.canConference());
+
+ // One disconnected (local hangup) call
+
+ try {
+ Connection conn;
+ conn = mGSMPhone.getForegroundCall().getConnections().get(0);
+ conn.hangup();
+ } catch (CallStateException ex) {
+ ex.printStackTrace();
+ fail("unexpected ex");
+ }
+
+ msg = mGSMTestHandler.waitForMessage(EVENT_DISCONNECT);
+ assertNotNull("Message Time Out", msg);
+
+ assertEquals(Phone.State.IDLE, mGSMPhone.getState());
+ assertFalse(mGSMPhone.getForegroundCall().isDialingOrAlerting());
+ assertFalse(mGSMPhone.getRingingCall().isRinging());
+
+ assertEquals(0, mGSMPhone.getRingingCall().getConnections().size());
+ assertEquals(1, mGSMPhone.getForegroundCall().getConnections().size());
+ assertEquals(0, mGSMPhone.getBackgroundCall().getConnections().size());
+
+ assertEquals(Call.State.IDLE, mGSMPhone.getRingingCall().getState());
+ assertEquals(Call.State.DISCONNECTED,
+ mGSMPhone.getForegroundCall().getState());
+ assertEquals(Call.State.IDLE, mGSMPhone.getBackgroundCall().getState());
+
+ assertTrue(mGSMPhone.getForegroundCall().getEarliestCreateTime() > 0);
+ assertTrue(mGSMPhone.getForegroundCall().getEarliestConnectTime() > 0);
+
+ cn = mGSMPhone.getForegroundCall().getEarliestConnection();
+
+ assertEquals(Call.State.DISCONNECTED, cn.getState());
+
+ assertEquals(Connection.DisconnectCause.LOCAL, cn.getDisconnectCause());
+
+ assertFalse(mGSMPhone.canConference());
+
+ // Back to idle state
+
+ mGSMPhone.clearDisconnected();
+
+ assertFalse(mGSMPhone.getForegroundCall().isDialingOrAlerting());
+ assertFalse(mGSMPhone.getRingingCall().isRinging());
+
+ assertEquals(Connection.DisconnectCause.LOCAL, cn.getDisconnectCause());
+ assertEquals(0, mGSMPhone.getForegroundCall().getConnections().size());
+ assertEquals(Phone.State.IDLE, mGSMPhone.getState());
+
+ assertEquals(0, mGSMPhone.getRingingCall().getConnections().size());
+ assertEquals(0, mGSMPhone.getForegroundCall().getConnections().size());
+ assertEquals(0, mGSMPhone.getBackgroundCall().getConnections().size());
+
+ assertEquals(Call.State.IDLE, mGSMPhone.getRingingCall().getState());
+ assertEquals(Call.State.IDLE, mGSMPhone.getForegroundCall().getState());
+ assertEquals(Call.State.IDLE, mGSMPhone.getBackgroundCall().getState());
+
+ assertEquals(0, mGSMPhone.getForegroundCall().getEarliestCreateTime());
+ assertEquals(0, mGSMPhone.getForegroundCall().getEarliestConnectTime());
+
+ assertFalse(mGSMPhone.canConference());
+
+ // cn left over from before phone.clearDisconnected();
+
+ assertEquals(Call.State.DISCONNECTED, cn.getState());
+
+ // One ringing call
+
+ mRadioControl.triggerRing("18005551212");
+
+ do {
+ assertNotNull("Message Time Out", mGSMTestHandler.waitForMessage(ANY_MESSAGE));
+ } while (mGSMPhone.getRingingCall().getConnections().isEmpty());
+
+ assertEquals(Phone.State.RINGING, mGSMPhone.getState());
+ assertFalse(mGSMPhone.getForegroundCall().isDialingOrAlerting());
+ assertTrue(mGSMPhone.getRingingCall().isRinging());
+
+ assertEquals(1, mGSMPhone.getRingingCall().getConnections().size());
+ assertEquals(0, mGSMPhone.getForegroundCall().getConnections().size());
+ assertEquals(0, mGSMPhone.getBackgroundCall().getConnections().size());
+
+ assertEquals(Call.State.INCOMING, mGSMPhone.getRingingCall().getState());
+ assertEquals(Call.State.IDLE, mGSMPhone.getForegroundCall().getState());
+ assertEquals(Call.State.IDLE, mGSMPhone.getBackgroundCall().getState());
+
+ assertTrue(mGSMPhone.getRingingCall().getEarliestCreateTime() > 0);
+ assertEquals(0, mGSMPhone.getRingingCall().getEarliestConnectTime());
+
+ assertEquals(0, mGSMPhone.getForegroundCall().getEarliestCreateTime());
+ assertEquals(0, mGSMPhone.getForegroundCall().getEarliestConnectTime());
+
+ assertFalse(mGSMPhone.canConference());
+
+ // One rejected call
+ mGSMPhone.rejectCall();
+
+ do {
+ assertNotNull("Message Time Out", mGSMTestHandler.waitForMessage(ANY_MESSAGE));
+ } while (mGSMPhone.getState() != Phone.State.IDLE);
+
+ assertFalse(mGSMPhone.getForegroundCall().isDialingOrAlerting());
+ assertFalse(mGSMPhone.getRingingCall().isRinging());
+
+ assertEquals(1, mGSMPhone.getRingingCall().getConnections().size());
+ assertEquals(0, mGSMPhone.getForegroundCall().getConnections().size());
+ assertEquals(0, mGSMPhone.getBackgroundCall().getConnections().size());
+
+ assertEquals(Call.State.DISCONNECTED, mGSMPhone.getRingingCall().getState());
+ assertEquals(Call.State.IDLE, mGSMPhone.getForegroundCall().getState());
+ assertEquals(Call.State.IDLE, mGSMPhone.getBackgroundCall().getState());
+
+ assertTrue(mGSMPhone.getRingingCall().getEarliestCreateTime() > 0);
+ assertEquals(0, mGSMPhone.getRingingCall().getEarliestConnectTime());
+
+ assertEquals(0, mGSMPhone.getForegroundCall().getEarliestCreateTime());
+ assertEquals(0, mGSMPhone.getForegroundCall().getEarliestConnectTime());
+
+ cn = mGSMPhone.getRingingCall().getEarliestConnection();
+ assertEquals(Call.State.DISCONNECTED, cn.getState());
+
+ assertEquals(Connection.DisconnectCause.INCOMING_MISSED, cn.getDisconnectCause());
+
+ assertFalse(mGSMPhone.canConference());
+
+ // Back to idle state
+
+ mGSMPhone.clearDisconnected();
+
+ assertEquals(Connection.DisconnectCause.INCOMING_MISSED, cn.getDisconnectCause());
+ assertEquals(0, mGSMPhone.getForegroundCall().getConnections().size());
+ assertEquals(Phone.State.IDLE, mGSMPhone.getState());
+
+ assertEquals(0, mGSMPhone.getRingingCall().getConnections().size());
+ assertEquals(0, mGSMPhone.getForegroundCall().getConnections().size());
+ assertEquals(0, mGSMPhone.getBackgroundCall().getConnections().size());
+
+ assertEquals(Call.State.IDLE, mGSMPhone.getRingingCall().getState());
+ assertEquals(Call.State.IDLE, mGSMPhone.getForegroundCall().getState());
+ assertEquals(Call.State.IDLE, mGSMPhone.getBackgroundCall().getState());
+
+ assertEquals(0, mGSMPhone.getForegroundCall().getEarliestCreateTime());
+ assertEquals(0, mGSMPhone.getForegroundCall().getEarliestConnectTime());
+
+ assertFalse(mGSMPhone.canConference());
+ assertEquals(Call.State.DISCONNECTED, cn.getState());
+
+ // One ringing call
+
+ mRadioControl.triggerRing("18005551212");
+
+ do {
+ assertNotNull("Message Time Out", mGSMTestHandler.waitForMessage(ANY_MESSAGE));
+ } while (mGSMPhone.getRingingCall().getConnections().isEmpty());
+
+ assertEquals(Phone.State.RINGING, mGSMPhone.getState());
+ assertFalse(mGSMPhone.getForegroundCall().isDialingOrAlerting());
+ assertTrue(mGSMPhone.getRingingCall().isRinging());
+
+ cn = mGSMPhone.getRingingCall().getEarliestConnection();
+
+ // Ringing call disconnects
+
+ mRadioControl.triggerHangupForeground();
+
+ do {
+ assertNotNull("Message Time Out", mGSMTestHandler.waitForMessage(ANY_MESSAGE));
+ } while (mGSMPhone.getState() != Phone.State.IDLE);
+
+ assertEquals(Connection.DisconnectCause.INCOMING_MISSED, cn.getDisconnectCause());
+
+ // One Ringing Call
+
+ mRadioControl.triggerRing("18005551212");
+
+ do {
+ assertNotNull("Message Time Out", mGSMTestHandler.waitForMessage(ANY_MESSAGE));
+ } while (mGSMPhone.getState() != Phone.State.RINGING);
+
+
+ cn = mGSMPhone.getRingingCall().getEarliestConnection();
+
+ // One answered call
+ mGSMPhone.acceptCall();
+
+ do {
+ assertNotNull("Message Time Out", mGSMTestHandler.waitForMessage(ANY_MESSAGE));
+ } while (mGSMPhone.getState() != Phone.State.OFFHOOK);
+
+ assertEquals(Call.State.ACTIVE, mGSMPhone.getForegroundCall().getState());
+ assertEquals(Call.State.IDLE, mGSMPhone.getBackgroundCall().getState());
+
+ // one holding call
+ mGSMPhone.switchHoldingAndActive();
+
+ do {
+ assertNotNull("Message Time Out", mGSMTestHandler.waitForMessage(ANY_MESSAGE));
+ } while (mGSMPhone.getBackgroundCall().getState() == Call.State.IDLE);
+
+
+ assertEquals(Call.State.IDLE, mGSMPhone.getForegroundCall().getState());
+ assertEquals(Call.State.HOLDING, mGSMPhone.getBackgroundCall().getState());
+
+ // one active call
+ mGSMPhone.switchHoldingAndActive();
+
+ do {
+ assertNotNull("Message Time Out", mGSMTestHandler.waitForMessage(ANY_MESSAGE));
+ }
+ while (mGSMPhone.getBackgroundCall().getState() == Call.State.HOLDING);
+
+ assertEquals(Call.State.ACTIVE, mGSMPhone.getForegroundCall().getState());
+ assertEquals(Call.State.IDLE, mGSMPhone.getBackgroundCall().getState());
+
+ // One disconnected call in the foreground slot
+
+ mRadioControl.triggerHangupAll();
+
+ do {
+ assertNotNull("Message Time Out", mGSMTestHandler.waitForMessage(ANY_MESSAGE));
+ } while (mGSMPhone.getState() != Phone.State.IDLE);
+
+ assertEquals(Call.State.DISCONNECTED, mGSMPhone.getForegroundCall().getState());
+ assertEquals(Connection.DisconnectCause.NORMAL, cn.getDisconnectCause());
+
+ // Test missed calls
+
+ mRadioControl.triggerRing("18005551212");
+
+ do {
+ assertNotNull("Message Time Out", mGSMTestHandler.waitForMessage(ANY_MESSAGE));
+ } while (mGSMPhone.getState() != Phone.State.RINGING);
+
+ mGSMPhone.rejectCall();
+
+ do {
+ assertNotNull("Message Time Out", mGSMTestHandler.waitForMessage(ANY_MESSAGE));
+ } while (msg.what != EVENT_DISCONNECT);
+
+ ar = (AsyncResult) msg.obj;
+ cn = (Connection) ar.result;
+
+ assertEquals(Connection.DisconnectCause.INCOMING_MISSED, cn.getDisconnectCause());
+ assertEquals(Phone.State.IDLE, mGSMPhone.getState());
+ assertEquals(Call.State.DISCONNECTED, mGSMPhone.getRingingCall().getState());
+
+ // Test incoming not missed calls
+
+ mRadioControl.triggerRing("18005551212");
+
+ do {
+ assertNotNull("Message Time Out", mGSMTestHandler.waitForMessage(ANY_MESSAGE));
+ } while (mGSMPhone.getState() != Phone.State.RINGING);
+
+ cn = mGSMPhone.getRingingCall().getEarliestConnection();
+
+ mGSMPhone.acceptCall();
+
+ do {
+ assertNotNull("Message Time Out", mGSMTestHandler.waitForMessage(ANY_MESSAGE));
+ } while (mGSMPhone.getState() != Phone.State.OFFHOOK);
+
+ assertEquals(Connection.DisconnectCause.NOT_DISCONNECTED, cn.getDisconnectCause());
+ assertEquals(Call.State.IDLE, mGSMPhone.getRingingCall().getState());
+ assertEquals(Call.State.ACTIVE, mGSMPhone.getForegroundCall().getState());
+
+ try {
+ mGSMPhone.getForegroundCall().hangup();
+ } catch (CallStateException ex) {
+ ex.printStackTrace();
+ fail("unexpected ex");
+ }
+
+ do {
+ assertNotNull("Message Time Out", mGSMTestHandler.waitForMessage(ANY_MESSAGE));
+ } while (mGSMPhone.getForegroundCall().getState()
+ != Call.State.DISCONNECTED);
+
+ assertEquals(Connection.DisconnectCause.LOCAL, cn.getDisconnectCause());
+
+ //
+ // Test held and hangup held calls
+ //
+
+ // One ALERTING call
+ mGSMPhone.dial("+13125551212");
+
+ do {
+ assertNotNull("Message Time Out", mGSMTestHandler.waitForMessage(ANY_MESSAGE));
+ } while (mGSMPhone.getState() != Phone.State.OFFHOOK);
+
+ assertTrue(mGSMPhone.getForegroundCall().isDialingOrAlerting());
+
+ mRadioControl.progressConnectingCallState();
+ mRadioControl.progressConnectingCallState();
+
+ // One ACTIVE call
+
+ do {
+ assertNotNull("Message Time Out", mGSMTestHandler.waitForMessage(ANY_MESSAGE));
+ } while (mGSMPhone.getForegroundCall().getState() != Call.State.ACTIVE);
+
+ assertFalse(mGSMPhone.getForegroundCall().isDialingOrAlerting());
+
+ // One ACTIVE call, one ringing call
+
+ mRadioControl.triggerRing("18005551212");
+
+ do {
+ assertNotNull("Message Time Out", mGSMTestHandler.waitForMessage(ANY_MESSAGE));
+ } while (mGSMPhone.getState() != Phone.State.RINGING);
+
+ assertFalse(mGSMPhone.getForegroundCall().isDialingOrAlerting());
+ assertTrue(mGSMPhone.getRingingCall().isRinging());
+
+ // One HOLDING call, one ACTIVE call
+ mGSMPhone.acceptCall();
+
+ do {
+ assertNotNull("Message Time Out", mGSMTestHandler.waitForMessage(ANY_MESSAGE));
+ } while (mGSMPhone.getState() != Phone.State.OFFHOOK);
+
+ assertFalse(mGSMPhone.getForegroundCall().isDialingOrAlerting());
+
+ assertEquals(Call.State.IDLE, mGSMPhone.getRingingCall().getState());
+ assertEquals(Call.State.ACTIVE, mGSMPhone.getForegroundCall().getState());
+ assertEquals(Call.State.HOLDING, mGSMPhone.getBackgroundCall().getState());
+ assertTrue(mGSMPhone.canConference());
+
+ // Conference the two
+ mGSMPhone.conference();
+
+ do {
+ assertNotNull("Message Time Out", mGSMTestHandler.waitForMessage(ANY_MESSAGE));
+ } while (mGSMPhone.getBackgroundCall().getState() != Call.State.IDLE);
+
+ assertFalse(mGSMPhone.getForegroundCall().isDialingOrAlerting());
+
+ assertEquals(Call.State.IDLE, mGSMPhone.getRingingCall().getState());
+ assertEquals(Call.State.ACTIVE, mGSMPhone.getForegroundCall().getState());
+ assertTrue(mGSMPhone.getForegroundCall().isMultiparty());
+ assertFalse(mGSMPhone.canConference());
+
+ // Hold the multiparty call
+ mGSMPhone.switchHoldingAndActive();
+
+ do {
+ assertNotNull("Message Time Out", mGSMTestHandler.waitForMessage(ANY_MESSAGE));
+ }
+ while (mGSMPhone.getBackgroundCall().getState() != Call.State.HOLDING);
+
+ assertEquals(Call.State.IDLE, mGSMPhone.getRingingCall().getState());
+ assertEquals(Call.State.IDLE, mGSMPhone.getForegroundCall().getState());
+ assertTrue(mGSMPhone.getBackgroundCall().isMultiparty());
+ assertFalse(mGSMPhone.canConference());
+
+ // Multiparty call on hold, call waiting added
+
+ mRadioControl.triggerRing("18005558355");
+
+ do {
+ assertNotNull("Message Time Out", mGSMTestHandler.waitForMessage(ANY_MESSAGE));
+ } while (mGSMPhone.getState() != Phone.State.RINGING);
+
+ assertFalse(mGSMPhone.getForegroundCall().isDialingOrAlerting());
+ assertTrue(mGSMPhone.getRingingCall().isRinging());
+
+ assertEquals(Call.State.IDLE, mGSMPhone.getForegroundCall().getState());
+ assertEquals(Call.State.HOLDING, mGSMPhone.getBackgroundCall().getState());
+ assertTrue(mGSMPhone.getBackgroundCall().isMultiparty());
+ assertEquals(Call.State.WAITING, mGSMPhone.getRingingCall().getState());
+ assertFalse(mGSMPhone.canConference());
+
+ // Hangup conference call, ringing call still around
+ mGSMPhone.getBackgroundCall().hangup();
+
+ do {
+ assertNotNull("Message Time Out", mGSMTestHandler.waitForMessage(ANY_MESSAGE));
+ } while (mGSMPhone.getBackgroundCall().getState() != Call.State.DISCONNECTED);
+
+ assertEquals(Phone.State.RINGING, mGSMPhone.getState());
+ assertEquals(Call.State.DISCONNECTED, mGSMPhone.getBackgroundCall().getState());
+
+ assertFalse(mGSMPhone.getForegroundCall().isDialingOrAlerting());
+ assertTrue(mGSMPhone.getRingingCall().isRinging());
+
+ // Reject waiting call
+ mGSMPhone.rejectCall();
+
+ do {
+ assertNotNull("Message Time Out", mGSMTestHandler.waitForMessage(ANY_MESSAGE));
+ } while (mGSMPhone.getState() != Phone.State.IDLE);
+
+ assertFalse(mGSMPhone.getForegroundCall().isDialingOrAlerting());
+ assertFalse(mGSMPhone.getRingingCall().isRinging());
+ }
+
+ public void testOutgoingCallFailImmediately() throws Exception {
+ Message msg;
+
+ // Test outgoing call fail-immediately edge case
+ // This happens when a call terminated before ever appearing in a
+ // call list
+ // This should land the immediately-failing call in the
+ // ForegroundCall list as an IDLE call
+ mRadioControl.setNextDialFailImmediately(true);
+
+ Connection cn = mGSMPhone.dial("+13125551212");
+
+ msg = mGSMTestHandler.waitForMessage(EVENT_DISCONNECT);
+ assertNotNull("Message Time Out", msg);
+ assertEquals(Phone.State.IDLE, mGSMPhone.getState());
+
+ assertEquals(Connection.DisconnectCause.NORMAL, cn.getDisconnectCause());
+
+ assertEquals(0, mGSMPhone.getRingingCall().getConnections().size());
+ assertEquals(1, mGSMPhone.getForegroundCall().getConnections().size());
+ assertEquals(0, mGSMPhone.getBackgroundCall().getConnections().size());
+
+ assertEquals(Call.State.IDLE, mGSMPhone.getRingingCall().getState());
+ assertEquals(Call.State.DISCONNECTED, mGSMPhone.getForegroundCall().getState());
+ assertEquals(Call.State.IDLE, mGSMPhone.getBackgroundCall().getState());
+
+ assertTrue(mGSMPhone.getForegroundCall().getEarliestCreateTime() > 0);
+ assertEquals(0, mGSMPhone.getForegroundCall().getEarliestConnectTime());
+ }
+
+ public void testHangupOnOutgoing() throws Exception {
+ Connection cn;
+ Message msg;
+
+ mRadioControl.setAutoProgressConnectingCall(false);
+
+ // Test 1: local hangup in "DIALING" state
+ mGSMPhone.dial("+13125551212");
+
+ do {
+ assertNotNull("Message Time Out", mGSMTestHandler.waitForMessage(ANY_MESSAGE));
+ }
+ while (mGSMPhone.getForegroundCall().getState() != Call.State.DIALING);
+
+ cn = mGSMPhone.getForegroundCall().getEarliestConnection();
+
+ mGSMPhone.getForegroundCall().hangup();
+
+ msg = mGSMTestHandler.waitForMessage(EVENT_DISCONNECT);
+ assertNotNull("Message Time Out", msg);
+ assertEquals(Phone.State.IDLE, mGSMPhone.getState());
+
+ assertEquals(Call.State.DISCONNECTED, mGSMPhone.getForegroundCall().getState());
+ assertEquals(Connection.DisconnectCause.LOCAL, cn.getDisconnectCause());
+
+ // Test 2: local hangup in "ALERTING" state
+ mGSMPhone.dial("+13125551212");
+
+ do {
+ assertNotNull("Message Time Out", mGSMTestHandler.waitForMessage(ANY_MESSAGE));
+ } while (mGSMPhone.getState() != Phone.State.OFFHOOK);
+
+ mRadioControl.progressConnectingCallState();
+
+ do {
+ assertNotNull("Message Time Out", mGSMTestHandler.waitForMessage(ANY_MESSAGE));
+ }
+ while (mGSMPhone.getForegroundCall().getState() != Call.State.ALERTING);
+
+ cn = mGSMPhone.getForegroundCall().getEarliestConnection();
+
+ mGSMPhone.getForegroundCall().hangup();
+
+ msg = mGSMTestHandler.waitForMessage(EVENT_DISCONNECT);
+ assertNotNull("Message Time Out", msg);
+
+ assertEquals(Phone.State.IDLE, mGSMPhone.getState());
+
+ assertEquals(Call.State.DISCONNECTED, mGSMPhone.getForegroundCall().getState());
+ assertEquals(Connection.DisconnectCause.LOCAL, cn.getDisconnectCause());
+
+ // Test 3: local immediate hangup before GSM index is
+ // assigned (CallTracker.hangupPendingMO case)
+
+ mRadioControl.pauseResponses();
+
+ cn = mGSMPhone.dial("+13125551212");
+
+ cn.hangup();
+
+ mRadioControl.resumeResponses();
+
+ msg = mGSMTestHandler.waitForMessage(EVENT_DISCONNECT);
+ assertNotNull("Message Time Out", msg);
+ assertEquals(Phone.State.IDLE, mGSMPhone.getState());
+
+ assertEquals(Call.State.DISCONNECTED, mGSMPhone.getForegroundCall().getState());
+
+ assertEquals(Connection.DisconnectCause.LOCAL,
+ mGSMPhone.getForegroundCall().getEarliestConnection().getDisconnectCause());
+ }
+
+ public void testHangupOnChannelClose() throws Exception {
+ mGSMPhone.dial("+13125551212");
+
+ do {
+ assertNotNull("Message Time Out", mGSMTestHandler.waitForMessage(ANY_MESSAGE));
+ } while (mGSMPhone.getForegroundCall().getConnections().isEmpty());
+
+ mRadioControl.shutdown();
+
+ do {
+ assertNotNull("Message Time Out", mGSMTestHandler.waitForMessage(ANY_MESSAGE));
+ mGSMPhone.clearDisconnected();
+ } while (!mGSMPhone.getForegroundCall().getConnections().isEmpty());
+ }
+
+ public void testIncallMmiCallDeflection() throws Exception {
+ Message msg;
+
+ // establish an active call
+ mGSMPhone.dial("+13125551212");
+
+ do {
+ mRadioControl.progressConnectingCallState();
+ assertNotNull("Message Time Out", mGSMTestHandler.waitForMessage(ANY_MESSAGE));
+ } while (mGSMPhone.getForegroundCall().getState() != Call.State.ACTIVE);
+
+ assertEquals(Call.State.ACTIVE, mGSMPhone.getForegroundCall().getState());
+ assertEquals(Call.State.IDLE, mGSMPhone.getBackgroundCall().getState());
+
+ // establish a ringing (WAITING) call
+
+ mRadioControl.triggerRing("18005551212");
+
+ msg = mGSMTestHandler.waitForMessage(EVENT_RINGING);
+ assertNotNull("Message Time Out", msg);
+
+ assertEquals(Phone.State.RINGING, mGSMPhone.getState());
+ assertTrue(mGSMPhone.getRingingCall().isRinging());
+ assertEquals(Call.State.WAITING, mGSMPhone.getRingingCall().getState());
+ assertEquals(Call.State.ACTIVE, mGSMPhone.getForegroundCall().getState());
+ assertEquals(Call.State.IDLE, mGSMPhone.getBackgroundCall().getState());
+
+ // Simulate entering 0 followed by SEND: release all held calls
+ // or sets UDUB for a waiting call.
+ mGSMPhone.handleInCallMmiCommands("0");
+
+ do {
+ assertNotNull("Message Time Out", mGSMTestHandler.waitForMessage(ANY_MESSAGE));
+ } while (mGSMPhone.getRingingCall().getState() == Call.State.WAITING);
+
+ assertEquals(Phone.State.OFFHOOK, mGSMPhone.getState());
+ assertFalse(mGSMPhone.getRingingCall().isRinging());
+ assertEquals(Call.State.DISCONNECTED, mGSMPhone.getRingingCall().getState());
+ assertEquals(Call.State.ACTIVE, mGSMPhone.getForegroundCall().getState());
+ assertEquals(Call.State.IDLE, mGSMPhone.getBackgroundCall().getState());
+
+ // change the active call to holding call
+ mGSMPhone.switchHoldingAndActive();
+
+ do {
+ assertNotNull("Message Time Out", mGSMTestHandler.waitForMessage(ANY_MESSAGE));
+ } while (mGSMPhone.getBackgroundCall().getState() == Call.State.IDLE);
+
+
+ assertEquals(Call.State.IDLE, mGSMPhone.getForegroundCall().getState());
+ assertEquals(Call.State.HOLDING, mGSMPhone.getBackgroundCall().getState());
+
+ // Simulate entering 0 followed by SEND: release all held calls
+ // or sets UDUB for a waiting call.
+ mGSMPhone.handleInCallMmiCommands("0");
+
+ do {
+ assertNotNull("Message Time Out", mGSMTestHandler.waitForMessage(ANY_MESSAGE));
+ } while (mGSMPhone.getBackgroundCall().getState() == Call.State.HOLDING);
+
+ assertEquals(Phone.State.IDLE, mGSMPhone.getState());
+ assertEquals(Call.State.IDLE, mGSMPhone.getForegroundCall().getState());
+ assertEquals(Call.State.DISCONNECTED, mGSMPhone.getBackgroundCall().getState());
+ }
+
+ public void testIncallMmiCallWaiting() throws Exception {
+ Message msg;
+
+ // establish an active call
+ mGSMPhone.dial("+13125551212");
+
+ do {
+ mRadioControl.progressConnectingCallState();
+ assertNotNull("Message Time Out", mGSMTestHandler.waitForMessage(ANY_MESSAGE));
+ } while (mGSMPhone.getForegroundCall().getState() != Call.State.ACTIVE);
+
+ assertEquals(Call.State.ACTIVE, mGSMPhone.getForegroundCall().getState());
+ assertEquals(Call.State.IDLE, mGSMPhone.getBackgroundCall().getState());
+
+ // establish a ringing (WAITING) call
+
+ mRadioControl.triggerRing("18005551212");
+
+ do {
+ msg = mGSMTestHandler.waitForMessage(ANY_MESSAGE);
+ assertNotNull("Message Time Out", msg);
+ } while (msg.what != EVENT_RINGING);
+
+ assertEquals(Phone.State.RINGING, mGSMPhone.getState());
+ assertTrue(mGSMPhone.getRingingCall().isRinging());
+ assertEquals(Call.State.WAITING, mGSMPhone.getRingingCall().getState());
+ assertEquals(Call.State.ACTIVE, mGSMPhone.getForegroundCall().getState());
+ assertEquals(Call.State.IDLE, mGSMPhone.getBackgroundCall().getState());
+
+ // Simulate entering 1 followed by SEND: release all active calls
+ // (if any exist) and accepts the other (held or waiting) call.
+
+ mGSMPhone.handleInCallMmiCommands("1");
+
+ do {
+ assertNotNull("Message Time Out", mGSMTestHandler.waitForMessage(ANY_MESSAGE));
+ } while (mGSMPhone.getRingingCall().getState() == Call.State.WAITING);
+
+ assertEquals(Phone.State.OFFHOOK, mGSMPhone.getState());
+ assertFalse(mGSMPhone.getRingingCall().isRinging());
+ assertEquals(Call.State.IDLE, mGSMPhone.getRingingCall().getState());
+ assertEquals(Call.State.ACTIVE, mGSMPhone.getForegroundCall().getState());
+ assertEquals("18005551212",
+ mGSMPhone.getForegroundCall().getConnections().get(0).getAddress());
+
+ // change the active call to holding call
+ mGSMPhone.switchHoldingAndActive();
+
+ do {
+ assertNotNull("Message Time Out", mGSMTestHandler.waitForMessage(ANY_MESSAGE));
+ } while (mGSMPhone.getBackgroundCall().getState() == Call.State.IDLE);
+
+ assertEquals(Call.State.IDLE, mGSMPhone.getForegroundCall().getState());
+ assertEquals(Call.State.HOLDING, mGSMPhone.getBackgroundCall().getState());
+
+ // Simulate entering 1 followed by SEND: release all active calls
+ // (if any exist) and accepts the other (held or waiting) call.
+ mGSMPhone.handleInCallMmiCommands("1");
+
+ do {
+ assertNotNull("Message Time Out", mGSMTestHandler.waitForMessage(ANY_MESSAGE));
+ } while (mGSMPhone.getBackgroundCall().getState() != Call.State.IDLE);
+
+ assertEquals(Phone.State.OFFHOOK, mGSMPhone.getState());
+ assertEquals(Call.State.ACTIVE, mGSMPhone.getForegroundCall().getState());
+ assertEquals(Call.State.IDLE, mGSMPhone.getBackgroundCall().getState());
+ assertEquals("18005551212",
+ mGSMPhone.getForegroundCall().getConnections().get(0).getAddress());
+
+ // at this point, the active call with number==18005551212 should
+ // have the gsm index of 2
+
+ mRadioControl.triggerRing("16505550100");
+
+ msg = mGSMTestHandler.waitForMessage(EVENT_RINGING);
+ assertNotNull("Message Time Out", msg);
+
+ assertEquals(Phone.State.RINGING, mGSMPhone.getState());
+ assertTrue(mGSMPhone.getRingingCall().isRinging());
+ assertEquals(Call.State.WAITING, mGSMPhone.getRingingCall().getState());
+ assertEquals(Call.State.ACTIVE, mGSMPhone.getForegroundCall().getState());
+ assertEquals(Call.State.IDLE, mGSMPhone.getBackgroundCall().getState());
+
+ // Simulate entering "12" followed by SEND: release the call with
+ // gsm index equals to 2.
+ mGSMPhone.handleInCallMmiCommands("12");
+
+ do {
+ assertNotNull("Message Time Out", mGSMTestHandler.waitForMessage(ANY_MESSAGE));
+ } while (mGSMPhone.getForegroundCall().getState() == Call.State.ACTIVE);
+
+ assertEquals(Phone.State.RINGING, mGSMPhone.getState());
+ assertTrue(mGSMPhone.getRingingCall().isRinging());
+ assertEquals(Call.State.WAITING, mGSMPhone.getRingingCall().getState());
+ assertEquals(Call.State.DISCONNECTED, mGSMPhone.getForegroundCall().getState());
+ assertEquals(Call.State.IDLE, mGSMPhone.getBackgroundCall().getState());
+
+ mGSMPhone.acceptCall();
+
+ do {
+ assertNotNull("Message Time Out", mGSMTestHandler.waitForMessage(ANY_MESSAGE));
+ } while (mGSMPhone.getState() != Phone.State.OFFHOOK);
+
+ assertEquals(Phone.State.OFFHOOK, mGSMPhone.getState());
+ assertFalse(mGSMPhone.getRingingCall().isRinging());
+ assertEquals(Call.State.IDLE, mGSMPhone.getRingingCall().getState());
+ assertEquals(Call.State.ACTIVE, mGSMPhone.getForegroundCall().getState());
+ assertEquals(Call.State.IDLE, mGSMPhone.getBackgroundCall().getState());
+
+ // at this point, the call with number==16505550100 should
+ // have the gsm index of 1
+ mGSMPhone.dial("+13125551212");
+
+ do {
+ mRadioControl.progressConnectingCallState();
+ assertNotNull("Message Time Out", mGSMTestHandler.waitForMessage(ANY_MESSAGE));
+ } while (mGSMPhone.getForegroundCall().getState() != Call.State.ACTIVE ||
+ mGSMPhone.getBackgroundCall().getState() != Call.State.HOLDING);
+
+ assertEquals(Call.State.ACTIVE, mGSMPhone.getForegroundCall().getState());
+ assertEquals(Call.State.HOLDING, mGSMPhone.getBackgroundCall().getState());
+
+ // at this point, the active call with number==13125551212 should
+ // have the gsm index of 2
+
+ // Simulate entering "11" followed by SEND: release the call with
+ // gsm index equals to 1. This should not be allowed, and a
+ // Supplementary Service notification must be received.
+ mGSMPhone.handleInCallMmiCommands("11");
+
+ msg = mGSMTestHandler.waitForMessage(SUPP_SERVICE_FAILED);
+ assertNotNull("Message Time Out", msg);
+ assertFalse("IncallMmiCallWaiting: command should not work on holding call", msg == null);
+
+ // Simulate entering "12" followed by SEND: release the call with
+ // gsm index equals to 2.
+ mGSMPhone.handleInCallMmiCommands("12");
+
+ do {
+ assertNotNull("Message Time Out", mGSMTestHandler.waitForMessage(ANY_MESSAGE));
+ } while (mGSMPhone.getForegroundCall().getState() == Call.State.ACTIVE);
+
+ assertEquals(Call.State.DISCONNECTED, mGSMPhone.getForegroundCall().getState());
+ assertEquals(Call.State.HOLDING, mGSMPhone.getBackgroundCall().getState());
+
+ // Simulate entering 1 followed by SEND: release all active calls
+ // (if any exist) and accepts the other (held or waiting) call.
+ mGSMPhone.handleInCallMmiCommands("1");
+
+ do {
+ assertNotNull("Message Time Out", mGSMTestHandler.waitForMessage(ANY_MESSAGE));
+ } while (mGSMPhone.getBackgroundCall().getState() != Call.State.IDLE);
+
+ assertEquals(Phone.State.OFFHOOK, mGSMPhone.getState());
+ assertEquals(Call.State.ACTIVE, mGSMPhone.getForegroundCall().getState());
+ assertEquals(Call.State.IDLE, mGSMPhone.getBackgroundCall().getState());
+ assertEquals("16505550100",
+ mGSMPhone.getForegroundCall().getConnections().get(0).getAddress());
+
+ // Simulate entering "11" followed by SEND: release the call with
+ // gsm index equals to 1.
+ mGSMPhone.handleInCallMmiCommands("11");
+
+ do {
+ assertNotNull("Message Time Out", mGSMTestHandler.waitForMessage(ANY_MESSAGE));
+ } while (mGSMPhone.getForegroundCall().getState() == Call.State.ACTIVE);
+
+ assertEquals(Call.State.DISCONNECTED, mGSMPhone.getForegroundCall().getState());
+ assertEquals(Call.State.IDLE, mGSMPhone.getBackgroundCall().getState());
+ }
+
+ public void testIncallMmiCallHold() throws Exception {
+ Message msg;
+
+ // establish an active call
+ mGSMPhone.dial("13125551212");
+
+ do {
+ mRadioControl.progressConnectingCallState();
+ assertNotNull("Message Time Out", mGSMTestHandler.waitForMessage(ANY_MESSAGE));
+ } while (mGSMPhone.getForegroundCall().getState() != Call.State.ACTIVE);
+
+ assertEquals(Call.State.ACTIVE, mGSMPhone.getForegroundCall().getState());
+ assertEquals(Call.State.IDLE, mGSMPhone.getBackgroundCall().getState());
+
+ // establish a ringing (WAITING) call
+
+ mRadioControl.triggerRing("18005551212");
+
+ msg = mGSMTestHandler.waitForMessage(EVENT_RINGING);
+ assertNotNull("Message Time Out", msg);
+
+ assertEquals(Phone.State.RINGING, mGSMPhone.getState());
+ assertTrue(mGSMPhone.getRingingCall().isRinging());
+ assertEquals(Call.State.WAITING, mGSMPhone.getRingingCall().getState());
+ assertEquals(Call.State.ACTIVE, mGSMPhone.getForegroundCall().getState());
+ assertEquals(Call.State.IDLE, mGSMPhone.getBackgroundCall().getState());
+
+ // simulate entering 2 followed by SEND: place all active calls
+ // (if any exist) on hold and accepts the other (held or waiting)
+ // call
+
+ mGSMPhone.handleInCallMmiCommands("2");
+
+ do {
+ assertNotNull("Message Time Out", mGSMTestHandler.waitForMessage(ANY_MESSAGE));
+ } while (mGSMPhone.getRingingCall().getState() == Call.State.WAITING);
+
+
+ assertFalse(mGSMPhone.getRingingCall().isRinging());
+ assertEquals(Phone.State.OFFHOOK, mGSMPhone.getState());
+ assertEquals(Call.State.IDLE, mGSMPhone.getRingingCall().getState());
+ assertEquals(Call.State.ACTIVE,
+ mGSMPhone.getForegroundCall().getState());
+ assertEquals("18005551212",
+ mGSMPhone.getForegroundCall().getConnections().get(0).getAddress());
+ assertEquals(Call.State.HOLDING, mGSMPhone.getBackgroundCall().getState());
+ assertEquals("13125551212",
+ mGSMPhone.getBackgroundCall().getConnections().get(0).getAddress());
+
+ // swap the active and holding calls
+ mGSMPhone.handleInCallMmiCommands("2");
+
+ msg = mGSMTestHandler.waitForMessage(EVENT_PHONE_STATE_CHANGED);
+ assertNotNull("Message Time Out", msg);
+
+ assertEquals(Call.State.ACTIVE, mGSMPhone.getForegroundCall().getState());
+ assertEquals("13125551212",
+ mGSMPhone.getForegroundCall().getConnections().get(0).getAddress());
+ assertEquals(Call.State.HOLDING, mGSMPhone.getBackgroundCall().getState());
+ assertEquals("18005551212",
+ mGSMPhone.getBackgroundCall().getConnections().get(0).getAddress());
+
+ // merge the calls
+ mGSMPhone.conference();
+
+ do {
+ assertNotNull("Message Time Out", mGSMTestHandler.waitForMessage(ANY_MESSAGE));
+ } while (mGSMPhone.getBackgroundCall().getState() != Call.State.IDLE);
+
+ assertEquals(Call.State.ACTIVE, mGSMPhone.getForegroundCall().getState());
+ assertEquals(Call.State.IDLE, mGSMPhone.getBackgroundCall().getState());
+ assertEquals(2, mGSMPhone.getForegroundCall().getConnections().size());
+
+ // at this point, we have an active conference call, with
+ // call(1) = 13125551212 and call(2) = 18005551212
+
+ // Simulate entering "23" followed by SEND: places all active call
+ // on hold except call 3. This should fail and a supplementary service
+ // failed notification should be received.
+
+ mGSMPhone.handleInCallMmiCommands("23");
+
+ msg = mGSMTestHandler.waitForMessage(SUPP_SERVICE_FAILED);
+ assertNotNull("Message Time Out", msg);
+ assertFalse("IncallMmiCallHold: separate should have failed!", msg == null);
+
+ // Simulate entering "21" followed by SEND: places all active call
+ // on hold except call 1.
+ mGSMPhone.handleInCallMmiCommands("21");
+
+ do {
+ assertNotNull("Message Time Out", mGSMTestHandler.waitForMessage(ANY_MESSAGE));
+ } while (mGSMPhone.getBackgroundCall().getState() == Call.State.IDLE);
+
+ assertEquals(Call.State.ACTIVE, mGSMPhone.getForegroundCall().getState());
+ assertEquals("13125551212",
+ mGSMPhone.getForegroundCall().getConnections().get(0).getAddress());
+ assertEquals(Call.State.HOLDING, mGSMPhone.getBackgroundCall().getState());
+ assertEquals("18005551212",
+ mGSMPhone.getBackgroundCall().getConnections().get(0).getAddress());
+ }
+
+ public void testIncallMmiMultipartyServices() throws Exception {
+ // establish an active call
+ mGSMPhone.dial("13125551212");
+
+ do {
+ mRadioControl.progressConnectingCallState();
+ assertNotNull("Message Time Out", mGSMTestHandler.waitForMessage(ANY_MESSAGE));
+ } while (mGSMPhone.getForegroundCall().getState() != Call.State.ACTIVE);
+
+ assertEquals(Call.State.ACTIVE, mGSMPhone.getForegroundCall().getState());
+ assertEquals(Call.State.IDLE, mGSMPhone.getBackgroundCall().getState());
+
+ // dial another call
+ mGSMPhone.dial("18005551212");
+
+ do {
+ mRadioControl.progressConnectingCallState();
+ assertNotNull("Message Time Out", mGSMTestHandler.waitForMessage(ANY_MESSAGE));
+ } while (mGSMPhone.getForegroundCall().getState() != Call.State.ACTIVE);
+
+ assertEquals(Call.State.ACTIVE, mGSMPhone.getForegroundCall().getState());
+ assertEquals(Call.State.HOLDING, mGSMPhone.getBackgroundCall().getState());
+
+ mGSMPhone.handleInCallMmiCommands("3");
+
+ do {
+ assertNotNull("Message Time Out", mGSMTestHandler.waitForMessage(ANY_MESSAGE));
+ } while (mGSMPhone.getBackgroundCall().getState() != Call.State.IDLE);
+
+ assertEquals(Phone.State.OFFHOOK, mGSMPhone.getState());
+ assertEquals(Call.State.ACTIVE, mGSMPhone.getForegroundCall().getState());
+ assertEquals("18005551212",
+ mGSMPhone.getForegroundCall().getConnections().get(0).getAddress());
+ assertEquals("13125551212",
+ mGSMPhone.getForegroundCall().getConnections().get(1).getAddress());
+ assertEquals(Call.State.IDLE, mGSMPhone.getBackgroundCall().getState());
+ }
+
+ public void testCallIndex() throws Exception {
+ Message msg;
+
+ // establish the first call
+ mGSMPhone.dial("16505550100");
+
+ do {
+ mRadioControl.progressConnectingCallState();
+ assertNotNull("Message Time Out", mGSMTestHandler.waitForMessage(ANY_MESSAGE));
+ } while (mGSMPhone.getForegroundCall().getState() != Call.State.ACTIVE);
+
+ assertEquals(Call.State.ACTIVE, mGSMPhone.getForegroundCall().getState());
+ assertEquals(Call.State.IDLE, mGSMPhone.getBackgroundCall().getState());
+
+ String baseNumber = "1650555010";
+
+ for (int i = 1; i < 6; i++) {
+ String number = baseNumber + i;
+
+ mGSMPhone.dial(number);
+
+ do {
+ mRadioControl.progressConnectingCallState();
+ assertNotNull("Message Time Out", mGSMTestHandler.waitForMessage(ANY_MESSAGE));
+ } while (mGSMPhone.getForegroundCall().getState() != Call.State.ACTIVE);
+
+ assertEquals(Call.State.ACTIVE, mGSMPhone.getForegroundCall().getState());
+ assertEquals(Call.State.HOLDING, mGSMPhone.getBackgroundCall().getState());
+
+ if (mGSMPhone.getBackgroundCall().getConnections().size() >= 5) {
+ break;
+ }
+
+ mGSMPhone.conference();
+
+ do {
+ assertNotNull("Message Time Out", mGSMTestHandler.waitForMessage(ANY_MESSAGE));
+ } while (mGSMPhone.getBackgroundCall().getState() != Call.State.IDLE);
+
+ assertEquals(Call.State.ACTIVE, mGSMPhone.getForegroundCall().getState());
+ assertEquals(Call.State.IDLE, mGSMPhone.getBackgroundCall().getState());
+ }
+
+ assertEquals(Call.State.ACTIVE, mGSMPhone.getForegroundCall().getState());
+ assertEquals("16505550105",
+ mGSMPhone.getForegroundCall().getConnections().get(0).getAddress());
+ assertEquals(Call.State.HOLDING, mGSMPhone.getBackgroundCall().getState());
+
+ // create an incoming call, this call should have the call index
+ // of 7
+ mRadioControl.triggerRing("18005551212");
+
+ msg = mGSMTestHandler.waitForMessage(EVENT_RINGING);
+ assertNotNull("Message Time Out", msg);
+
+ assertEquals(Phone.State.RINGING, mGSMPhone.getState());
+ assertTrue(mGSMPhone.getRingingCall().isRinging());
+ assertEquals(Call.State.WAITING, mGSMPhone.getRingingCall().getState());
+ assertEquals(Call.State.ACTIVE, mGSMPhone.getForegroundCall().getState());
+ assertEquals(Call.State.HOLDING, mGSMPhone.getBackgroundCall().getState());
+
+ // hangup the background call and accept the ringing call
+ mGSMPhone.getBackgroundCall().hangup();
+ mGSMPhone.acceptCall();
+
+ do {
+ assertNotNull("Message Time Out", mGSMTestHandler.waitForMessage(ANY_MESSAGE));
+ } while (mGSMPhone.getRingingCall().getState() != Call.State.IDLE);
+
+ assertEquals(Call.State.ACTIVE, mGSMPhone.getForegroundCall().getState());
+ assertEquals("18005551212",
+ mGSMPhone.getForegroundCall().getConnections().get(0).getAddress());
+ assertEquals(Call.State.HOLDING, mGSMPhone.getBackgroundCall().getState());
+ assertEquals("16505550105",
+ mGSMPhone.getBackgroundCall().getConnections().get(0).getAddress());
+
+ mGSMPhone.handleInCallMmiCommands("17");
+
+ do {
+ assertNotNull("Message Time Out", mGSMTestHandler.waitForMessage(ANY_MESSAGE));
+ } while (mGSMPhone.getForegroundCall().getState() == Call.State.ACTIVE);
+
+ assertEquals(Call.State.DISCONNECTED, mGSMPhone.getForegroundCall().getState());
+ assertEquals(Call.State.HOLDING, mGSMPhone.getBackgroundCall().getState());
+ assertEquals("16505550105",
+ mGSMPhone.getBackgroundCall().getConnections().get(0).
+ getAddress());
+
+ mGSMPhone.handleInCallMmiCommands("1");
+
+ do {
+ assertNotNull("Message Time Out", mGSMTestHandler.waitForMessage(ANY_MESSAGE));
+ } while (mGSMPhone.getForegroundCall().getState() != Call.State.ACTIVE);
+
+ assertEquals(Call.State.ACTIVE, mGSMPhone.getForegroundCall().getState());
+ assertEquals(Call.State.IDLE, mGSMPhone.getBackgroundCall().getState());
+
+ mGSMPhone.handleInCallMmiCommands("16");
+
+ do {
+ assertNotNull("Message Time Out", mGSMTestHandler.waitForMessage(ANY_MESSAGE));
+ } while (mGSMPhone.getForegroundCall().getState() == Call.State.ACTIVE);
+
+ assertEquals(Call.State.DISCONNECTED, mGSMPhone.getForegroundCall().getState());
+ assertEquals(Call.State.IDLE, mGSMPhone.getBackgroundCall().getState());
+ }
+
+ public void testPostDialSequences() throws Exception {
+ Message msg;
+ AsyncResult ar;
+ Connection cn;
+
+ mGSMPhone.dial("+13125551212,1234;5N8xx");
+
+ msg = mGSMTestHandler.waitForMessage(EVENT_POST_DIAL);
+ assertNotNull("Message Time Out", msg);
+ ar = (AsyncResult) (msg.obj);
+ cn = (Connection) (ar.result);
+ assertEquals(',', msg.arg1);
+ assertEquals("1234;5N8", cn.getRemainingPostDialString());
+
+
+ msg = mGSMTestHandler.waitForMessage(EVENT_POST_DIAL);
+ assertNotNull("Message Time Out", msg);
+ assertEquals('1', msg.arg1);
+ ar = (AsyncResult) (msg.obj);
+ assertEquals(Connection.PostDialState.STARTED, ar.userObj);
+
+
+ msg = mGSMTestHandler.waitForMessage(EVENT_POST_DIAL);
+ assertNotNull("Message Time Out", msg);
+ assertEquals('2', msg.arg1);
+ ar = (AsyncResult) (msg.obj);
+ assertEquals(Connection.PostDialState.STARTED, ar.userObj);
+
+
+ msg = mGSMTestHandler.waitForMessage(EVENT_POST_DIAL);
+ assertNotNull("Message Time Out", msg);
+ assertEquals('3', msg.arg1);
+ ar = (AsyncResult) (msg.obj);
+ assertEquals(Connection.PostDialState.STARTED, ar.userObj);
+
+
+ msg = mGSMTestHandler.waitForMessage(EVENT_POST_DIAL);
+ assertNotNull("Message Time Out", msg);
+ assertEquals('4', msg.arg1);
+ ar = (AsyncResult) (msg.obj);
+ assertEquals(Connection.PostDialState.STARTED, ar.userObj);
+
+
+ msg = mGSMTestHandler.waitForMessage(EVENT_POST_DIAL);
+ assertNotNull("Message Time Out", msg);
+ assertEquals(';', msg.arg1);
+ ar = (AsyncResult) (msg.obj);
+ cn = (Connection) (ar.result);
+ assertEquals(Connection.PostDialState.WAIT, cn.getPostDialState());
+ assertEquals(Connection.PostDialState.WAIT, ar.userObj);
+ cn.proceedAfterWaitChar();
+
+
+ msg = mGSMTestHandler.waitForMessage(EVENT_POST_DIAL);
+ assertNotNull("Message Time Out", msg);
+ assertEquals('5', msg.arg1);
+ ar = (AsyncResult) (msg.obj);
+ assertEquals(Connection.PostDialState.STARTED, ar.userObj);
+
+
+ msg = mGSMTestHandler.waitForMessage(EVENT_POST_DIAL);
+ assertEquals('N', msg.arg1);
+ ar = (AsyncResult) (msg.obj);
+ cn = (Connection) (ar.result);
+ assertEquals(Connection.PostDialState.WILD, cn.getPostDialState());
+ assertEquals(Connection.PostDialState.WILD, ar.userObj);
+ cn.proceedAfterWildChar(",6;7");
+
+
+ msg = mGSMTestHandler.waitForMessage(EVENT_POST_DIAL);
+ assertNotNull("Message Time Out", msg);
+ ar = (AsyncResult) (msg.obj);
+ cn = (Connection) (ar.result);
+ assertEquals(',', msg.arg1);
+ assertEquals("6;78", cn.getRemainingPostDialString());
+
+ msg = mGSMTestHandler.waitForMessage(EVENT_POST_DIAL);
+ assertNotNull("Message Time Out", msg);
+ assertEquals('6', msg.arg1);
+ ar = (AsyncResult) (msg.obj);
+ assertEquals(Connection.PostDialState.STARTED, ar.userObj);
+
+ msg = mGSMTestHandler.waitForMessage(EVENT_POST_DIAL);
+ assertNotNull("Message Time Out", msg);
+ assertEquals(';', msg.arg1);
+ ar = (AsyncResult) (msg.obj);
+ cn = (Connection) (ar.result);
+ assertEquals(Connection.PostDialState.WAIT, cn.getPostDialState());
+ assertEquals(Connection.PostDialState.WAIT, ar.userObj);
+ cn.proceedAfterWaitChar();
+
+ msg = mGSMTestHandler.waitForMessage(EVENT_POST_DIAL);
+ assertNotNull("Message Time Out", msg);
+ assertEquals('7', msg.arg1);
+ ar = (AsyncResult) (msg.obj);
+ assertEquals(Connection.PostDialState.STARTED, ar.userObj);
+
+ msg = mGSMTestHandler.waitForMessage(EVENT_POST_DIAL);
+ assertNotNull("Message Time Out", msg);
+ assertEquals('8', msg.arg1);
+ ar = (AsyncResult) (msg.obj);
+ assertEquals(Connection.PostDialState.STARTED, ar.userObj);
+
+ // Bogus chars at end should be ignored
+ msg = mGSMTestHandler.waitForMessage(EVENT_POST_DIAL);
+ assertNotNull("Message Time Out", msg);
+ assertEquals(0, msg.arg1);
+ ar = (AsyncResult) (msg.obj);
+ cn = (Connection) (ar.result);
+ assertEquals(Connection.PostDialState.COMPLETE,
+ cn.getPostDialState());
+ assertEquals(Connection.PostDialState.COMPLETE, ar.userObj);
+ }
+
+ public void testPostDialCancel() throws Exception {
+ Message msg;
+ AsyncResult ar;
+ Connection cn;
+
+ mGSMPhone.dial("+13125551212,N");
+ mRadioControl.progressConnectingToActive();
+
+ mRadioControl.progressConnectingToActive();
+
+ msg = mGSMTestHandler.waitForMessage(EVENT_POST_DIAL);
+ assertNotNull("Message Time Out", msg);
+ assertEquals(',', msg.arg1);
+
+ msg = mGSMTestHandler.waitForMessage(EVENT_POST_DIAL);
+ assertEquals('N', msg.arg1);
+ ar = (AsyncResult) (msg.obj);
+ cn = (Connection) (ar.result);
+ assertEquals(Connection.PostDialState.WILD, cn.getPostDialState());
+ cn.cancelPostDial();
+
+ assertEquals(Connection.PostDialState.CANCELLED, cn.getPostDialState());
+ }
+
+ public void testOutgoingCallFail() throws Exception {
+ Message msg;
+ /*
+ * normal clearing
+ */
+
+ mRadioControl.setNextCallFailCause(CallFailCause.NORMAL_CLEARING);
+ mRadioControl.setAutoProgressConnectingCall(false);
+
+ Connection cn = mGSMPhone.dial("+13125551212");
+
+ mRadioControl.progressConnectingCallState();
+
+ // I'm just progressing the call state to
+ // ensure getCurrentCalls() gets processed...
+ // Normally these failure conditions would happen in DIALING
+ // not ALERTING
+ do {
+ assertNotNull("Message Time Out", mGSMTestHandler.waitForMessage(ANY_MESSAGE));
+ } while (cn.getState() == Call.State.DIALING);
+
+
+ mRadioControl.triggerHangupAll();
+ msg = mGSMTestHandler.waitForMessage(EVENT_DISCONNECT);
+ assertNotNull("Message Time Out", msg);
+ assertEquals(Phone.State.IDLE, mGSMPhone.getState());
+
+ assertEquals(Connection.DisconnectCause.NORMAL, cn.getDisconnectCause());
+
+ assertEquals(0, mGSMPhone.getRingingCall().getConnections().size());
+ assertEquals(1, mGSMPhone.getForegroundCall().getConnections().size());
+ assertEquals(0, mGSMPhone.getBackgroundCall().getConnections().size());
+
+ assertEquals(Call.State.IDLE, mGSMPhone.getRingingCall().getState());
+ assertEquals(Call.State.DISCONNECTED, mGSMPhone.getForegroundCall().getState());
+ assertEquals(Call.State.IDLE, mGSMPhone.getBackgroundCall().getState());
+
+ assertTrue(mGSMPhone.getForegroundCall().getEarliestCreateTime() > 0);
+ assertEquals(0, mGSMPhone.getForegroundCall().getEarliestConnectTime());
+
+ /*
+ * busy
+ */
+
+ mRadioControl.setNextCallFailCause(CallFailCause.USER_BUSY);
+ mRadioControl.setAutoProgressConnectingCall(false);
+
+ cn = mGSMPhone.dial("+13125551212");
+
+ mRadioControl.progressConnectingCallState();
+
+ // I'm just progressing the call state to
+ // ensure getCurrentCalls() gets processed...
+ // Normally these failure conditions would happen in DIALING
+ // not ALERTING
+ do {
+ assertNotNull("Message Time Out", mGSMTestHandler.waitForMessage(ANY_MESSAGE));
+ } while (cn.getState() == Call.State.DIALING);
+
+
+ mRadioControl.triggerHangupAll();
+ msg = mGSMTestHandler.waitForMessage(EVENT_DISCONNECT);
+ assertNotNull("Message Time Out", msg);
+ assertEquals(Phone.State.IDLE, mGSMPhone.getState());
+
+ assertEquals(Connection.DisconnectCause.BUSY, cn.getDisconnectCause());
+
+ assertEquals(0, mGSMPhone.getRingingCall().getConnections().size());
+ assertEquals(1, mGSMPhone.getForegroundCall().getConnections().size());
+ assertEquals(0, mGSMPhone.getBackgroundCall().getConnections().size());
+
+ assertEquals(Call.State.IDLE, mGSMPhone.getRingingCall().getState());
+ assertEquals(Call.State.DISCONNECTED,
+ mGSMPhone.getForegroundCall().getState());
+ assertEquals(Call.State.IDLE, mGSMPhone.getBackgroundCall().getState());
+
+ assertTrue(mGSMPhone.getForegroundCall().getEarliestCreateTime() > 0);
+ assertEquals(0, mGSMPhone.getForegroundCall().getEarliestConnectTime());
+
+ /*
+ * congestion
+ */
+
+ mRadioControl.setNextCallFailCause(CallFailCause.NO_CIRCUIT_AVAIL);
+ mRadioControl.setAutoProgressConnectingCall(false);
+
+ cn = mGSMPhone.dial("+13125551212");
+
+ mRadioControl.progressConnectingCallState();
+
+ // I'm just progressing the call state to
+ // ensure getCurrentCalls() gets processed...
+ // Normally these failure conditions would happen in DIALING
+ // not ALERTING
+ do {
+ msg = mGSMTestHandler.waitForMessage(ANY_MESSAGE);
+ assertNotNull("Message Time Out", msg);
+ } while (cn.getState() == Call.State.DIALING);
+
+
+ mRadioControl.triggerHangupAll();
+
+ // Unlike the while loops above, this one waits
+ // for a "phone state changed" message back to "idle"
+ do {
+ msg = mGSMTestHandler.waitForMessage(ANY_MESSAGE);
+ assertNotNull("Message Time Out", msg);
+ } while (!(msg.what == EVENT_PHONE_STATE_CHANGED
+ && mGSMPhone.getState() == Phone.State.IDLE));
+
+ assertEquals(Phone.State.IDLE, mGSMPhone.getState());
+
+ assertEquals(Connection.DisconnectCause.CONGESTION, cn.getDisconnectCause());
+
+ assertEquals(0, mGSMPhone.getRingingCall().getConnections().size());
+ assertEquals(1, mGSMPhone.getForegroundCall().getConnections().size());
+ assertEquals(0, mGSMPhone.getBackgroundCall().getConnections().size());
+
+ assertEquals(Call.State.IDLE, mGSMPhone.getRingingCall().getState());
+ assertEquals(Call.State.DISCONNECTED, mGSMPhone.getForegroundCall().getState());
+ assertEquals(Call.State.IDLE, mGSMPhone.getBackgroundCall().getState());
+
+ assertTrue(mGSMPhone.getForegroundCall().getEarliestCreateTime() > 0);
+ assertEquals(0, mGSMPhone.getForegroundCall().getEarliestConnectTime());
+ }
+
+ public void testSSNotification() throws Exception {
+ // MO
+ runTest(0, SuppServiceNotification.MO_CODE_UNCONDITIONAL_CF_ACTIVE);
+ runTest(0, SuppServiceNotification.MO_CODE_CALL_IS_WAITING);
+ runTest(0, SuppServiceNotification.MO_CODE_CALL_DEFLECTED);
+
+ // MT
+ runTest(1, SuppServiceNotification.MT_CODE_FORWARDED_CALL);
+ runTest(1, SuppServiceNotification.MT_CODE_CALL_CONNECTED_ECT);
+ runTest(1, SuppServiceNotification.MT_CODE_ADDITIONAL_CALL_FORWARDED);
+ }
+
+ private void runTest(int type, int code) {
+ Message msg;
+
+ mRadioControl.triggerSsn(type, code);
+
+ msg = mGSMTestHandler.waitForMessage(EVENT_SSN);
+ assertNotNull("Message Time Out", msg);
+ AsyncResult ar = (AsyncResult) msg.obj;
+
+ assertNull(ar.exception);
+
+ SuppServiceNotification notification =
+ (SuppServiceNotification) ar.result;
+
+ assertEquals(type, notification.notificationType);
+ assertEquals(code, notification.code);
+ }
+
+ public void testUssd() throws Exception {
+ // Quick hack to work around a race condition in this test:
+ // We may initiate a USSD MMI before GSMPhone receives its initial
+ // GSMTestHandler.EVENT_RADIO_OFF_OR_NOT_AVAILABLE event. When the phone sees this
+ // event, it will cancel the just issued USSD MMI, which we don't
+ // want. So sleep a little first.
+ try {
+ Thread.sleep(1000);
+ } catch (InterruptedException ex) {
+ // do nothing
+ }
+
+ verifyNormal();
+ verifyCancel();
+ varifyNetworkInitiated();
+ }
+
+ private void varifyNetworkInitiated() {
+ Message msg;
+ AsyncResult ar;
+ MmiCode mmi;
+
+ // Receive an incoming NOTIFY
+ mRadioControl.triggerIncomingUssd("0", "NOTIFY message");
+ msg = mGSMTestHandler.waitForMessage(EVENT_MMI_COMPLETE);
+ assertNotNull("Message Time Out", msg);
+ ar = (AsyncResult) msg.obj;
+ mmi = (MmiCode) ar.result;
+
+ assertFalse(mmi.isUssdRequest());
+
+ // Receive a REQUEST and send response
+ mRadioControl.triggerIncomingUssd("1", "REQUEST Message");
+ msg = mGSMTestHandler.waitForMessage(EVENT_MMI_COMPLETE);
+ assertNotNull("Message Time Out", msg);
+ ar = (AsyncResult) msg.obj;
+ mmi = (MmiCode) ar.result;
+
+ assertTrue(mmi.isUssdRequest());
+
+ mGSMPhone.sendUssdResponse("## TEST: TEST_GSMPhone responding...");
+ msg = mGSMTestHandler.waitForMessage(EVENT_MMI_INITIATE);
+ assertNotNull("Message Time Out", msg);
+ ar = (AsyncResult) msg.obj;
+ mmi = (MmiCode) ar.result;
+
+ GsmMmiCode gsmMmi = (GsmMmiCode) mmi;
+ assertTrue(gsmMmi.isPendingUSSD());
+ msg = mGSMTestHandler.waitForMessage(EVENT_MMI_COMPLETE);
+ assertNotNull("Message Time Out", msg);
+ ar = (AsyncResult) msg.obj;
+ mmi = (MmiCode) ar.result;
+
+ assertNull(ar.exception);
+ assertFalse(mmi.isUssdRequest());
+
+ // Receive a REQUEST and cancel
+ mRadioControl.triggerIncomingUssd("1", "REQUEST Message");
+ msg = mGSMTestHandler.waitForMessage(EVENT_MMI_COMPLETE);
+ assertNotNull("Message Time Out", msg);
+ ar = (AsyncResult) msg.obj;
+ mmi = (MmiCode) ar.result;
+
+ assertTrue(mmi.isUssdRequest());
+
+ mmi.cancel();
+ msg = mGSMTestHandler.waitForMessage(EVENT_MMI_COMPLETE);
+ assertNotNull("Message Time Out", msg);
+
+ ar = (AsyncResult) msg.obj;
+ mmi = (MmiCode) ar.result;
+
+ assertNull(ar.exception);
+ assertEquals(MmiCode.State.CANCELLED, mmi.getState());
+
+ List mmiList = mGSMPhone.getPendingMmiCodes();
+ assertEquals(0, mmiList.size());
+ }
+
+ private void verifyNormal() throws CallStateException {
+ Message msg;
+ AsyncResult ar;
+ MmiCode mmi;
+
+ mGSMPhone.dial("#646#");
+
+ msg = mGSMTestHandler.waitForMessage(EVENT_MMI_INITIATE);
+ assertNotNull("Message Time Out", msg);
+
+ msg = mGSMTestHandler.waitForMessage(EVENT_MMI_COMPLETE);
+ assertNotNull("Message Time Out", msg);
+
+ ar = (AsyncResult) msg.obj;
+ mmi = (MmiCode) ar.result;
+ assertEquals(MmiCode.State.COMPLETE, mmi.getState());
+ }
+
+
+ private void verifyCancel() throws CallStateException {
+ /**
+ * This case makes an assumption that dial() will add the USSD
+ * to the "pending MMI codes" list before it returns. This seems
+ * like reasonable semantics. It also assumes that the USSD
+ * request in question won't complete until we get back to the
+ * event loop, thus cancel() is safe.
+ */
+ Message msg;
+
+ mGSMPhone.dial("#646#");
+
+ List<? extends MmiCode> pendingMmis = mGSMPhone.getPendingMmiCodes();
+
+ assertEquals(1, pendingMmis.size());
+
+ MmiCode mmi = pendingMmis.get(0);
+ assertTrue(mmi.isCancelable());
+ mmi.cancel();
+
+ msg = mGSMTestHandler.waitForMessage(EVENT_MMI_INITIATE);
+ assertNotNull("Message Time Out", msg);
+
+ msg = mGSMTestHandler.waitForMessage(EVENT_MMI_COMPLETE);
+ assertNotNull("Message Time Out", msg);
+
+ AsyncResult ar = (AsyncResult) msg.obj;
+ mmi = (MmiCode) ar.result;
+
+ assertEquals(MmiCode.State.CANCELLED, mmi.getState());
+ }
+
+ public void testRilHooks() throws Exception {
+ //
+ // These test cases all assume the RIL OEM hooks
+ // just echo back their input
+ //
+
+ Message msg;
+ AsyncResult ar;
+
+ // null byte array
+
+ mGSMPhone.invokeOemRilRequestRaw(null, mHandler.obtainMessage(EVENT_OEM_RIL_MESSAGE));
+
+ msg = mGSMTestHandler.waitForMessage(EVENT_OEM_RIL_MESSAGE);
+ assertNotNull("Message Time Out", msg);
+
+ ar = ((AsyncResult) msg.obj);
+
+ assertNull(ar.result);
+ assertNull(ar.exception);
+
+ // empty byte array
+
+ mGSMPhone.invokeOemRilRequestRaw(new byte[0], mHandler.obtainMessage(EVENT_OEM_RIL_MESSAGE));
+
+ msg = mGSMTestHandler.waitForMessage(EVENT_OEM_RIL_MESSAGE);
+ assertNotNull("Message Time Out", msg);
+
+ ar = ((AsyncResult) msg.obj);
+
+ assertEquals(0, ((byte[]) (ar.result)).length);
+ assertNull(ar.exception);
+
+ // byte array with data
+
+ mGSMPhone.invokeOemRilRequestRaw("Hello".getBytes("utf-8"),
+ mHandler.obtainMessage(EVENT_OEM_RIL_MESSAGE));
+
+ msg = mGSMTestHandler.waitForMessage(EVENT_OEM_RIL_MESSAGE);
+ assertNotNull("Message Time Out", msg);
+
+ ar = ((AsyncResult) msg.obj);
+
+ assertEquals("Hello", new String(((byte[]) (ar.result)), "utf-8"));
+ assertNull(ar.exception);
+
+ // null strings
+
+ mGSMPhone.invokeOemRilRequestStrings(null, mHandler.obtainMessage(EVENT_OEM_RIL_MESSAGE));
+
+ msg = mGSMTestHandler.waitForMessage(EVENT_OEM_RIL_MESSAGE);
+ assertNotNull("Message Time Out", msg);
+
+ ar = ((AsyncResult) msg.obj);
+
+ assertNull(ar.result);
+ assertNull(ar.exception);
+
+ // empty byte array
+
+ mGSMPhone.invokeOemRilRequestStrings(new String[0],
+ mHandler.obtainMessage(EVENT_OEM_RIL_MESSAGE));
+
+ msg = mGSMTestHandler.waitForMessage(EVENT_OEM_RIL_MESSAGE);
+ assertNotNull("Message Time Out", msg);
+
+ ar = ((AsyncResult) msg.obj);
+
+ assertEquals(0, ((String[]) (ar.result)).length);
+ assertNull(ar.exception);
+
+ // Strings with data
+
+ String s[] = new String[1];
+
+ s[0] = "Hello";
+
+ mGSMPhone.invokeOemRilRequestStrings(s, mHandler.obtainMessage(EVENT_OEM_RIL_MESSAGE));
+
+ msg = mGSMTestHandler.waitForMessage(EVENT_OEM_RIL_MESSAGE);
+ assertNotNull("Message Time Out", msg);
+
+ ar = ((AsyncResult) msg.obj);
+
+ assertEquals("Hello", ((String[]) (ar.result))[0]);
+ assertEquals(1, ((String[]) (ar.result)).length);
+ assertNull(ar.exception);
+ }
+
+ public void testMmi() throws Exception {
+ mRadioControl.setAutoProgressConnectingCall(false);
+
+ // "valid" MMI sequences
+ runValidMmi("*#67#", false);
+ runValidMmi("##43*11#", false);
+ runValidMmi("#33*1234*11#", false);
+ runValidMmi("*21*6505551234**5#", false);
+ runValidMmi("**03**1234*4321*4321#", false);
+ // pound string
+ runValidMmi("5308234092307540923#", true);
+ // short code
+ runValidMmi("22", true);
+ // as part of call setup
+ runValidMmiWithConnect("*31#6505551234");
+
+ // invalid MMI sequences
+ runNotMmi("6505551234");
+ runNotMmi("1234#*12#34566654");
+ runNotMmi("*#*#12#*");
+ }
+
+ private void runValidMmi(String dialString, boolean cancelable) throws CallStateException {
+ Connection c = mGSMPhone.dial(dialString);
+ assertNull(c);
+ Message msg = mGSMTestHandler.waitForMessage(EVENT_MMI_INITIATE);
+ assertNotNull("Message Time Out", msg);
+ // Should not be cancelable.
+ AsyncResult ar = (AsyncResult) msg.obj;
+ MmiCode mmi = (MmiCode) ar.result;
+ assertEquals(cancelable, mmi.isCancelable());
+
+ msg = mGSMTestHandler.waitForMessage(EVENT_MMI_COMPLETE);
+ assertNotNull("Message Time Out", msg);
+ }
+
+ private void runValidMmiWithConnect(String dialString) throws CallStateException {
+ mRadioControl.pauseResponses();
+
+ Connection c = mGSMPhone.dial(dialString);
+ assertNotNull(c);
+
+ hangup(c);
+ }
+
+ private void hangup(Connection cn) throws CallStateException {
+ cn.hangup();
+
+ mRadioControl.resumeResponses();
+ assertNotNull(mGSMTestHandler.waitForMessage(EVENT_DISCONNECT));
+
+ }
+
+ private void runNotMmi(String dialString) throws CallStateException {
+ mRadioControl.pauseResponses();
+
+ Connection c = mGSMPhone.dial(dialString);
+ assertNotNull(c);
+
+ hangup(c);
+ }
+}
diff --git a/tests/CoreTests/com/android/internal/telephony/gsm/GSMTestHandler.java b/tests/CoreTests/com/android/internal/telephony/gsm/GSMTestHandler.java
new file mode 100644
index 0000000..fb8a5d9
--- /dev/null
+++ b/tests/CoreTests/com/android/internal/telephony/gsm/GSMTestHandler.java
@@ -0,0 +1,118 @@
+/*
+ * 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.android.internal.telephony.gsm;
+
+import android.content.Context;
+
+import android.os.Handler;
+import android.os.HandlerThread;
+import android.os.Looper;
+import android.os.Message;
+import android.util.Log;
+
+import com.android.internal.telephony.gsm.GSMPhone;
+import com.android.internal.telephony.test.SimulatedCommands;
+import com.android.internal.telephony.TestPhoneNotifier;
+
+/**
+ * This class creates a HandlerThread which waits for the various messages.
+ */
+public class GSMTestHandler extends HandlerThread implements Handler.Callback {
+
+ private Handler mHandler;
+ private Message mCurrentMessage;
+
+ private Boolean mMsgConsumed;
+ private SimulatedCommands sc;
+ private GSMPhone mGSMPhone;
+ private Context mContext;
+
+ private static final int FAIL_TIMEOUT_MILLIS = 5 * 1000;
+
+ public GSMTestHandler(Context context) {
+ super("GSMPhoneTest");
+ mMsgConsumed = false;
+ mContext = context;
+ }
+
+ @Override
+ protected void onLooperPrepared() {
+ sc = new SimulatedCommands();
+ mGSMPhone = new GSMPhone(mContext, sc, new TestPhoneNotifier(), true);
+ mHandler = new Handler(getLooper(), this);
+ synchronized (this) {
+ notifyAll();
+ }
+ }
+
+ public boolean handleMessage(Message msg) {
+ synchronized (this) {
+ mCurrentMessage = msg;
+ this.notifyAll();
+ while(!mMsgConsumed) {
+ try {
+ this.wait();
+ } catch (InterruptedException e) {}
+ }
+ mMsgConsumed = false;
+ }
+ return true;
+ }
+
+
+ public void cleanup() {
+ Looper looper = getLooper();
+ if (looper != null) looper.quit();
+ mHandler = null;
+ }
+
+ public Handler getHandler() {
+ return mHandler;
+ }
+
+ public SimulatedCommands getSimulatedCommands() {
+ return sc;
+ }
+
+ public GSMPhone getGSMPhone() {
+ return mGSMPhone;
+ }
+
+ public Message waitForMessage(int code) {
+ Message msg;
+ while(true) {
+ msg = null;
+ synchronized (this) {
+ try {
+ this.wait(FAIL_TIMEOUT_MILLIS);
+ } catch (InterruptedException e) {
+ }
+
+ // Check if timeout has occurred.
+ if (mCurrentMessage != null) {
+ // Consume the message
+ msg = Message.obtain();
+ msg.copyFrom(mCurrentMessage);
+ mCurrentMessage = null;
+ mMsgConsumed = true;
+ this.notifyAll();
+ }
+ }
+ if (msg == null || code == GSMPhoneTest.ANY_MESSAGE || msg.what == code) return msg;
+ }
+ }
+}
diff --git a/tests/CoreTests/com/android/internal/telephony/gsm/GsmAlphabetTest.java b/tests/CoreTests/com/android/internal/telephony/gsm/GsmAlphabetTest.java
new file mode 100644
index 0000000..f36d96b
--- /dev/null
+++ b/tests/CoreTests/com/android/internal/telephony/gsm/GsmAlphabetTest.java
@@ -0,0 +1,309 @@
+/*
+ * Copyright (C) 2006 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.internal.telephony.gsm;
+
+import junit.framework.TestCase;
+
+import android.test.suitebuilder.annotation.LargeTest;
+import android.test.suitebuilder.annotation.SmallTest;
+import android.test.suitebuilder.annotation.Suppress;
+
+public class GsmAlphabetTest extends TestCase {
+
+ private static final String sGsmExtendedChars = "{|}\\[~]\f\u20ac";
+
+ @SmallTest
+ public void test7bitWithHeader() throws Exception {
+ byte[] data = new byte[3];
+ data[0] = (byte) 1;
+ data[1] = (byte) 2;
+ data[2] = (byte) 2;
+ SmsHeader header = new SmsHeader();
+ header.add(new SmsHeader.Element(SmsHeader.CONCATENATED_8_BIT_REFERENCE, data));
+
+ String message = "aaaaaaaaaabbbbbbbbbbcccccccccc";
+ byte[] userData = GsmAlphabet.stringToGsm7BitPackedWithHeader(message, header.toByteArray());
+ int septetCount = GsmAlphabet.countGsmSeptets(message, false);
+ String parsedMessage = GsmAlphabet.gsm7BitPackedToString(
+ userData, header.toByteArray().length+1, septetCount, 1);
+ assertEquals(message, parsedMessage);
+ }
+
+ // TODO: This method should *really* be a series of individual test methods.
+ @LargeTest
+ public void testBasic() throws Exception {
+ // '@' maps to char 0
+ assertEquals(0, GsmAlphabet.charToGsm('@'));
+
+ // `a (a with grave accent) maps to last GSM charater
+ assertEquals(0x7f, GsmAlphabet.charToGsm('\u00e0'));
+
+ //
+ // These are the extended chars
+ // They should all return GsmAlphabet.GSM_EXTENDED_ESCAPE
+ //
+
+ for (int i = 0, s = sGsmExtendedChars.length(); i < s; i++) {
+ assertEquals(GsmAlphabet.GSM_EXTENDED_ESCAPE,
+ GsmAlphabet.charToGsm(sGsmExtendedChars.charAt(i)));
+
+ }
+
+ // euro symbol
+ assertEquals(GsmAlphabet.GSM_EXTENDED_ESCAPE,
+ GsmAlphabet.charToGsm('\u20ac'));
+
+ // An unmappable char (the 'cent' char) maps to a space
+ assertEquals(GsmAlphabet.charToGsm(' '),
+ GsmAlphabet.charToGsm('\u00a2'));
+
+ // unmappable = space = 1 septet
+ assertEquals(1, GsmAlphabet.countGsmSeptets('\u00a2'));
+
+ //
+ // Test extended table
+ //
+
+ for (int i = 0, s = sGsmExtendedChars.length(); i < s; i++) {
+ assertEquals(sGsmExtendedChars.charAt(i),
+ GsmAlphabet.gsmExtendedToChar(
+ GsmAlphabet.charToGsmExtended(sGsmExtendedChars.charAt(i))));
+
+ }
+
+ // Unmappable extended char
+ assertEquals(GsmAlphabet.charToGsm(' '),
+ GsmAlphabet.charToGsmExtended('@'));
+
+ //
+ // gsmToChar()
+ //
+
+ assertEquals('@', GsmAlphabet.gsmToChar(0));
+
+ // `a (a with grave accent) maps to last GSM charater
+ assertEquals('\u00e0', GsmAlphabet.gsmToChar(0x7f));
+
+ assertEquals('\uffff',
+ GsmAlphabet.gsmToChar(GsmAlphabet.GSM_EXTENDED_ESCAPE));
+
+ // Out-of-range/unmappable value
+ assertEquals(' ', GsmAlphabet.gsmToChar(0x80));
+
+ //
+ // gsmExtendedToChar()
+ //
+
+ assertEquals('{', GsmAlphabet.gsmExtendedToChar(0x28));
+
+ // No double-escapes
+ assertEquals(' ', GsmAlphabet.gsmExtendedToChar(
+ GsmAlphabet.GSM_EXTENDED_ESCAPE));
+
+ // Unmappable
+ assertEquals(' ', GsmAlphabet.gsmExtendedToChar(0));
+
+ //
+ // stringTo7BitPacked, gsm7BitPackedToString
+ //
+
+ byte[] packed;
+ StringBuilder testString = new StringBuilder(300);
+
+ // Check all alignment cases
+ for (int i = 0; i < 9; i++, testString.append('@')) {
+ packed = GsmAlphabet.stringToGsm7BitPacked(testString.toString());
+ assertEquals(testString.toString(),
+ GsmAlphabet.gsm7BitPackedToString(packed, 1, 0xff & packed[0]));
+ }
+
+ // Check full non-extended alphabet
+ for (int i = 0; i < 0x80; i++) {
+ char c;
+
+ if (i == GsmAlphabet.GSM_EXTENDED_ESCAPE) {
+ continue;
+ }
+
+ c = GsmAlphabet.gsmToChar(i);
+ testString.append(c);
+
+ // These are all non-extended chars, so it should be
+ // one septet per char
+ assertEquals(1, GsmAlphabet.countGsmSeptets(c));
+ }
+
+ packed = GsmAlphabet.stringToGsm7BitPacked(testString.toString());
+ assertEquals(testString.toString(),
+ GsmAlphabet.gsm7BitPackedToString(packed, 1, 0xff & packed[0]));
+
+ // Test extended chars too
+
+ testString.append(sGsmExtendedChars);
+
+ for (int i = 0, s = sGsmExtendedChars.length(); i < s; i++) {
+ // These are all extended chars, so it should be
+ // two septets per char
+ assertEquals(2, GsmAlphabet.countGsmSeptets(sGsmExtendedChars.charAt(i)));
+
+ }
+
+ packed = GsmAlphabet.stringToGsm7BitPacked(testString.toString());
+ assertEquals(testString.toString(),
+ GsmAlphabet.gsm7BitPackedToString(packed, 1, 0xff & packed[0]));
+
+ // stringTo7BitPacked handles up to 255 septets
+
+ testString.setLength(0);
+ for (int i = 0; i < 255; i++) {
+ testString.append('@');
+ }
+
+ packed = GsmAlphabet.stringToGsm7BitPacked(testString.toString());
+ assertEquals(testString.toString(),
+ GsmAlphabet.gsm7BitPackedToString(packed, 1, 0xff & packed[0]));
+
+ // > 255 septets throws runtime exception
+ testString.append('@');
+
+ try {
+ GsmAlphabet.stringToGsm7BitPacked(testString.toString());
+ fail("expected exception");
+ } catch (EncodeException ex) {
+ // exception expected
+ }
+
+ // Try 254 septets with 127 extended chars
+
+ testString.setLength(0);
+ for (int i = 0; i < (255 / 2); i++) {
+ testString.append('{');
+ }
+
+ packed = GsmAlphabet.stringToGsm7BitPacked(testString.toString());
+ assertEquals(testString.toString(),
+ GsmAlphabet.gsm7BitPackedToString(packed, 1, 0xff & packed[0]));
+
+ // > 255 septets throws runtime exception
+ testString.append('{');
+
+ try {
+ GsmAlphabet.stringToGsm7BitPacked(testString.toString());
+ fail("expected exception");
+ } catch (EncodeException ex) {
+ // exception expected
+ }
+
+ //
+ // 8 bit unpacked format
+ //
+ // Note: we compare hex strings here
+ // because Assert doesnt have array-comparisons
+
+ byte unpacked[];
+
+ unpacked = SimUtils.hexStringToBytes("566F696365204D61696C");
+ assertEquals("Voice Mail",
+ GsmAlphabet.gsm8BitUnpackedToString(unpacked, 0, unpacked.length));
+
+ assertEquals(SimUtils.bytesToHexString(unpacked),
+ SimUtils.bytesToHexString(
+ GsmAlphabet.stringToGsm8BitPacked("Voice Mail")));
+
+ unpacked = GsmAlphabet.stringToGsm8BitPacked(sGsmExtendedChars);
+ // two bytes for every extended char
+ assertEquals(2 * sGsmExtendedChars.length(), unpacked.length);
+ assertEquals(sGsmExtendedChars,
+ GsmAlphabet.gsm8BitUnpackedToString(unpacked, 0, unpacked.length));
+
+ // should be two bytes per extended char
+ assertEquals(2 * sGsmExtendedChars.length(), unpacked.length);
+
+ // Test truncation of unaligned extended chars
+ unpacked = new byte[3];
+ GsmAlphabet.stringToGsm8BitUnpackedField(sGsmExtendedChars, unpacked,
+ 0, unpacked.length);
+
+ // Should be one extended char and an 0xff at the end
+
+ assertEquals(0xff, 0xff & unpacked[2]);
+ assertEquals(sGsmExtendedChars.substring(0, 1),
+ GsmAlphabet.gsm8BitUnpackedToString(unpacked, 0, unpacked.length));
+
+ // Test truncation of normal chars
+ unpacked = new byte[3];
+ GsmAlphabet.stringToGsm8BitUnpackedField("abcd", unpacked,
+ 0, unpacked.length);
+
+ assertEquals("abc",
+ GsmAlphabet.gsm8BitUnpackedToString(unpacked, 0, unpacked.length));
+
+ // Test truncation of mixed normal and extended chars
+ unpacked = new byte[3];
+ GsmAlphabet.stringToGsm8BitUnpackedField("a{cd", unpacked,
+ 0, unpacked.length);
+
+ assertEquals("a{",
+ GsmAlphabet.gsm8BitUnpackedToString(unpacked, 0, unpacked.length));
+
+ // Test padding after normal char
+ unpacked = new byte[3];
+ GsmAlphabet.stringToGsm8BitUnpackedField("a", unpacked,
+ 0, unpacked.length);
+
+ assertEquals("a",
+ GsmAlphabet.gsm8BitUnpackedToString(unpacked, 0, unpacked.length));
+
+ assertEquals(0xff, 0xff & unpacked[1]);
+ assertEquals(0xff, 0xff & unpacked[2]);
+
+ // Test malformed input -- escape char followed by end of field
+ unpacked[0] = 0;
+ unpacked[1] = 0;
+ unpacked[2] = GsmAlphabet.GSM_EXTENDED_ESCAPE;
+
+ assertEquals("@@",
+ GsmAlphabet.gsm8BitUnpackedToString(unpacked, 0, unpacked.length));
+
+ // non-zero offset
+ assertEquals("@",
+ GsmAlphabet.gsm8BitUnpackedToString(unpacked, 1, unpacked.length - 1));
+
+ // test non-zero offset
+ unpacked[0] = 0;
+ GsmAlphabet.stringToGsm8BitUnpackedField("abcd", unpacked,
+ 1, unpacked.length - 1);
+
+
+ assertEquals(0, unpacked[0]);
+
+ assertEquals("ab",
+ GsmAlphabet.gsm8BitUnpackedToString(unpacked, 1, unpacked.length - 1));
+
+ // test non-zero offset with truncated extended char
+ unpacked[0] = 0;
+
+ GsmAlphabet.stringToGsm8BitUnpackedField("a{", unpacked,
+ 1, unpacked.length - 1);
+
+ assertEquals(0, unpacked[0]);
+
+ assertEquals("a",
+ GsmAlphabet.gsm8BitUnpackedToString(unpacked, 1, unpacked.length - 1));
+ }
+}
+
diff --git a/tests/CoreTests/com/android/internal/telephony/gsm/SMSDispatcherTest.java b/tests/CoreTests/com/android/internal/telephony/gsm/SMSDispatcherTest.java
new file mode 100644
index 0000000..6db230f
--- /dev/null
+++ b/tests/CoreTests/com/android/internal/telephony/gsm/SMSDispatcherTest.java
@@ -0,0 +1,97 @@
+/*
+ * Copyright (C) 2007 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.internal.telephony.gsm;
+
+import android.test.suitebuilder.annotation.MediumTest;
+import com.android.internal.telephony.TestPhoneNotifier;
+import com.android.internal.telephony.test.SimulatedCommands;
+import com.android.internal.telephony.test.SimulatedRadioControl;
+import android.test.AndroidTestCase;
+import android.test.suitebuilder.annotation.Suppress;
+import android.telephony.gsm.SmsMessage;
+
+import java.util.Iterator;
+
+/**
+ * {@hide}
+ */
+public class SMSDispatcherTest extends AndroidTestCase {
+ @MediumTest
+ public void testCMT1() throws Exception {
+ SmsMessage sms;
+ SmsHeader header;
+ Iterator<SmsHeader.Element> elements;
+
+ String[] lines = new String[2];
+
+ lines[0] = "+CMT: ,158";
+ lines[1] = "07914140279510F6440A8111110301003BF56080426101748A8C0B05040B"
+ + "8423F000035502010106276170706C69636174696F6E2F766E642E776170"
+ + "2E6D6D732D6D65737361676500AF848D0185B4848C8298524F347839776F"
+ + "7547514D4141424C3641414141536741415A4B554141414141008D908918"
+ + "802B31363530323438363137392F545950453D504C4D4E008A808E028000"
+ + "88058103093A8083687474703A2F2F36";
+
+ sms = SmsMessage.newFromCMT(lines);
+ header = sms.getUserDataHeader();
+ assertNotNull(header);
+ assertNotNull(sms.getUserData());
+
+ elements = header.getElements().iterator();
+ assertNotNull(elements);
+ }
+
+ @MediumTest
+ public void testCMT2() throws Exception {
+ SmsMessage sms;
+ SmsHeader header;
+ Iterator<SmsHeader.Element> elements;
+
+ String[] lines = new String[2];
+
+
+ lines[0] = "+CMT: ,77";
+ lines[1] = "07914140279510F6440A8111110301003BF56080426101848A3B0B05040B8423F"
+ + "00003550202362E3130322E3137312E3135302F524F347839776F7547514D4141"
+ + "424C3641414141536741415A4B55414141414100";
+
+ sms = SmsMessage.newFromCMT(lines);
+ header = sms.getUserDataHeader();
+ System.out.println("header = " + header);
+ assertNotNull(header);
+ assertNotNull(sms.getUserData());
+
+ elements = header.getElements().iterator();
+ assertNotNull(elements);
+ }
+
+ @MediumTest
+ public void testEfRecord() throws Exception {
+ SmsMessage sms;
+
+ String s = "03029111000c9194981492631000f269206190022000a053e4534a05358bd3"
+ + "69f05804259da0219418a40641536a110a0aea408080604028180e888462c1"
+ + "50341c0f484432a1542c174c46b3e1743c9f9068442a994ea8946ac56ab95e"
+ + "b0986c46abd96eb89c6ec7ebf97ec0a070482c1a8fc8a472c96c3a9fd0a874"
+ + "4aad5aafd8ac76cbed7abfe0b0784c2e9bcfe8b47acd6ebbdff0b87c4eafdb"
+ + "eff8bc7ecfeffbffffffffffffffffffffffffffff";
+ byte[] data = SimUtils.hexStringToBytes(s);
+
+ sms = SmsMessage.createFromEfRecord(1, data);
+ assertNotNull(sms.getMessageBody());
+ }
+}
diff --git a/tests/CoreTests/com/android/internal/telephony/gsm/SimPhoneBookTest.java b/tests/CoreTests/com/android/internal/telephony/gsm/SimPhoneBookTest.java
new file mode 100644
index 0000000..db55bca
--- /dev/null
+++ b/tests/CoreTests/com/android/internal/telephony/gsm/SimPhoneBookTest.java
@@ -0,0 +1,106 @@
+/*
+ * Copyright (C) 2006 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.internal.telephony.gsm;
+
+import android.os.ServiceManager;
+import android.test.suitebuilder.annotation.Suppress;
+
+import java.util.List;
+
+import junit.framework.TestCase;
+
+@Suppress
+public class SimPhoneBookTest extends TestCase {
+
+ public void testBasic() throws Exception {
+ ISimPhoneBook simPhoneBook =
+ ISimPhoneBook.Stub.asInterface(ServiceManager.getService("simphonebook"));
+ assertNotNull(simPhoneBook);
+
+ int size[] = simPhoneBook.getAdnRecordsSize(SimConstants.EF_ADN);
+ assertNotNull(size);
+ assertEquals(3, size.length);
+ assertEquals(size[0] * size[2], size[1]);
+ assertTrue(size[2] >= 100);
+
+ List<AdnRecord> adnRecordList = simPhoneBook.getAdnRecordsInEf(SimConstants.EF_ADN);
+ // do it twice cause the second time shall read from cache only
+ adnRecordList = simPhoneBook.getAdnRecordsInEf(SimConstants.EF_ADN);
+ assertNotNull(adnRecordList);
+
+ // Test for phone book update
+ int adnIndex, listIndex = 0;
+ AdnRecord originalAdn = null;
+ // We need to maintain the state of the SIM before and after the test.
+ // Since this test doesn't mock the SIM we try to get a valid ADN record,
+ // for 3 tries and if this fails, we bail out.
+ for (adnIndex = 3 ; adnIndex >= 1; adnIndex--) {
+ listIndex = adnIndex - 1; // listIndex is zero based.
+ originalAdn = adnRecordList.get(listIndex);
+ assertNotNull("Original Adn is Null.", originalAdn);
+ assertNotNull("Original Adn alpha tag is null.", originalAdn.getAlphaTag());
+ assertNotNull("Original Adn number is null.", originalAdn.getNumber());
+
+ if (originalAdn.getNumber().length() > 0 &&
+ originalAdn.getAlphaTag().length() > 0) {
+ break;
+ }
+ }
+ if (adnIndex == 0) return;
+
+ AdnRecord emptyAdn = new AdnRecord("", "");
+ AdnRecord firstAdn = new AdnRecord("John", "4085550101");
+ AdnRecord secondAdn = new AdnRecord("Andy", "6505550102");
+ String pin2 = null;
+
+ // udpate by index
+ boolean success = simPhoneBook.updateAdnRecordsInEfByIndex(SimConstants.EF_ADN,
+ firstAdn.getAlphaTag(), firstAdn.getNumber(), adnIndex, pin2);
+ adnRecordList = simPhoneBook.getAdnRecordsInEf(SimConstants.EF_ADN);
+ AdnRecord tmpAdn = adnRecordList.get(listIndex);
+ assertTrue(success);
+ assertTrue(firstAdn.isEqual(tmpAdn));
+
+ // replace by search
+ success = simPhoneBook.updateAdnRecordsInEfBySearch(SimConstants.EF_ADN,
+ firstAdn.getAlphaTag(), firstAdn.getNumber(),
+ secondAdn.getAlphaTag(), secondAdn.getNumber(), pin2);
+ adnRecordList = simPhoneBook.getAdnRecordsInEf(SimConstants.EF_ADN);
+ tmpAdn = adnRecordList.get(listIndex);
+ assertTrue(success);
+ assertFalse(firstAdn.isEqual(tmpAdn));
+ assertTrue(secondAdn.isEqual(tmpAdn));
+
+ // erase be search
+ success = simPhoneBook.updateAdnRecordsInEfBySearch(SimConstants.EF_ADN,
+ secondAdn.getAlphaTag(), secondAdn.getNumber(),
+ emptyAdn.getAlphaTag(), emptyAdn.getNumber(), pin2);
+ adnRecordList = simPhoneBook.getAdnRecordsInEf(SimConstants.EF_ADN);
+ tmpAdn = adnRecordList.get(listIndex);
+ assertTrue(success);
+ assertTrue(tmpAdn.isEmpty());
+
+ // restore the orginial adn
+ success = simPhoneBook.updateAdnRecordsInEfByIndex(SimConstants.EF_ADN,
+ originalAdn.getAlphaTag(), originalAdn.getNumber(), adnIndex,
+ pin2);
+ adnRecordList = simPhoneBook.getAdnRecordsInEf(SimConstants.EF_ADN);
+ tmpAdn = adnRecordList.get(listIndex);
+ assertTrue(success);
+ assertTrue(originalAdn.isEqual(tmpAdn));
+ }
+}
diff --git a/tests/CoreTests/com/android/internal/telephony/gsm/SimSmsTest.java b/tests/CoreTests/com/android/internal/telephony/gsm/SimSmsTest.java
new file mode 100644
index 0000000..6ced23d
--- /dev/null
+++ b/tests/CoreTests/com/android/internal/telephony/gsm/SimSmsTest.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2006 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.internal.telephony.gsm;
+
+import android.os.ServiceManager;
+import android.test.suitebuilder.annotation.MediumTest;
+import android.test.suitebuilder.annotation.Suppress;
+
+import java.util.List;
+
+import junit.framework.TestCase;
+
+public class SimSmsTest extends TestCase {
+
+ @MediumTest
+ @Suppress // TODO: suppress this test for now since it doesn't work on the emulator
+ public void testBasic() throws Exception {
+
+ ISms sms = ISms.Stub.asInterface(ServiceManager.getService("isms"));
+ assertNotNull(sms);
+
+ List<SmsRawData> records = sms.getAllMessagesFromSimEf();
+ assertNotNull(records);
+ assertTrue(records.size() >= 0);
+
+ int firstNullIndex = -1;
+ int firstValidIndex = -1;
+ byte[] pdu = null;
+ for (int i = 0; i < records.size(); i++) {
+ SmsRawData data = records.get(i);
+ if (data != null && firstValidIndex == -1) {
+ firstValidIndex = i;
+ pdu = data.getBytes();
+ }
+ if (data == null && firstNullIndex == -1) {
+ firstNullIndex = i;
+ }
+ if (firstNullIndex != -1 && firstValidIndex != -1) {
+ break;
+ }
+ }
+ if (firstNullIndex == -1 || firstValidIndex == -1)
+ return;
+ assertNotNull(pdu);
+ }
+}
diff --git a/tests/CoreTests/com/android/internal/telephony/gsm/SimUtilsTest.java b/tests/CoreTests/com/android/internal/telephony/gsm/SimUtilsTest.java
new file mode 100644
index 0000000..3fbc8f5
--- /dev/null
+++ b/tests/CoreTests/com/android/internal/telephony/gsm/SimUtilsTest.java
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2006 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.internal.telephony.gsm;
+
+import com.android.internal.telephony.gsm.SimTlv;
+import com.android.internal.telephony.gsm.SimUtils;
+import junit.framework.TestCase;
+import android.test.suitebuilder.annotation.SmallTest;
+
+
+public class SimUtilsTest extends TestCase {
+
+ @SmallTest
+ public void testBasic() throws Exception {
+ byte[] data, data2;
+
+ /*
+ * bcdToString()
+ */
+
+ // An EF[ICCID] record
+ data = SimUtils.hexStringToBytes("981062400510444868f2");
+ assertEquals("8901260450014484862", SimUtils.bcdToString(data, 0, data.length));
+
+ // skip the first and last bytes
+ assertEquals("0126045001448486", SimUtils.bcdToString(data, 1, data.length - 2));
+
+ // Stops on invalid BCD value
+ data = SimUtils.hexStringToBytes("98F062400510444868f2");
+ assertEquals("890", SimUtils.bcdToString(data, 0, data.length));
+
+ /*
+ * bcdByteToInt()
+ */
+
+ assertEquals(98, SimUtils.bcdByteToInt((byte) 0x89));
+
+ // Out of range is treated as 0
+ assertEquals(8, SimUtils.bcdByteToInt((byte) 0x8c));
+
+ /*
+ * adnStringFieldToString()
+ */
+
+
+ data = SimUtils.hexStringToBytes("00566f696365204d61696c07918150367742f3ffffffffffff");
+ // Again, skip prepended 0
+ // (this is an EF[ADN] record)
+ assertEquals("Voice Mail", SimUtils.adnStringFieldToString(data, 1, data.length - 15));
+
+ data = SimUtils.hexStringToBytes("809673539A5764002F004DFFFFFFFFFF");
+ // (this is from an EF[ADN] record)
+ assertEquals("\u9673\u539A\u5764/M", SimUtils.adnStringFieldToString(data, 0, data.length));
+
+ data = SimUtils.hexStringToBytes("810A01566fec6365204de0696cFFFFFF");
+ // (this is made up to test since I don't have a real one)
+ assertEquals("Vo\u00ECce M\u00E0il", SimUtils.adnStringFieldToString(data, 0, data.length));
+
+ data = SimUtils.hexStringToBytes("820505302D82d32d31");
+ // Example from 3GPP TS 11.11 V18.1.3.0 annex B
+ assertEquals("-\u0532\u0583-1", SimUtils.adnStringFieldToString(data, 0, data.length));
+ }
+
+}
+
diff --git a/tests/CoreTests/com/android/internal/util/PredicatesTest.java b/tests/CoreTests/com/android/internal/util/PredicatesTest.java
new file mode 100644
index 0000000..c46ff05
--- /dev/null
+++ b/tests/CoreTests/com/android/internal/util/PredicatesTest.java
@@ -0,0 +1,74 @@
+/*
+ * 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.internal.util;
+
+import junit.framework.TestCase;
+
+import java.util.ArrayList;
+import java.util.Collections;
+
+public class PredicatesTest extends TestCase {
+
+ private static final Predicate<Object> TRUE = new Predicate<Object>() {
+ public boolean apply(Object o) {
+ return true;
+ }
+ };
+
+ private static final Predicate<Object> FALSE = new Predicate<Object>() {
+ public boolean apply(Object o) {
+ return false;
+ }
+ };
+
+ public void testAndPredicate_AllConditionsTrue() throws Exception {
+ assertTrue(Predicates.and(newArrayList(TRUE)).apply(null));
+ assertTrue(Predicates.and(newArrayList(TRUE, TRUE)).apply(null));
+ }
+
+ public void testAndPredicate_AtLeastOneConditionIsFalse() throws Exception {
+ assertFalse(Predicates.and(newArrayList(FALSE, TRUE, TRUE)).apply(null));
+ assertFalse(Predicates.and(newArrayList(TRUE, FALSE, TRUE)).apply(null));
+ assertFalse(Predicates.and(newArrayList(TRUE, TRUE, FALSE)).apply(null));
+ }
+
+ public void testOrPredicate_AllConditionsTrue() throws Exception {
+ assertTrue(Predicates.or(newArrayList(TRUE, TRUE, TRUE)).apply(null));
+ }
+
+ public void testOrPredicate_AllConditionsFalse() throws Exception {
+ assertFalse(Predicates.or(newArrayList(FALSE, FALSE, FALSE)).apply(null));
+ }
+
+ public void testOrPredicate_AtLeastOneConditionIsTrue() throws Exception {
+ assertTrue(Predicates.or(newArrayList(TRUE, FALSE, FALSE)).apply(null));
+ assertTrue(Predicates.or(newArrayList(FALSE, TRUE, FALSE)).apply(null));
+ assertTrue(Predicates.or(newArrayList(FALSE, FALSE, TRUE)).apply(null));
+ }
+
+ public void testNotPredicate() throws Exception {
+ assertTrue(Predicates.not(FALSE).apply(null));
+ assertFalse(Predicates.not(TRUE).apply(null));
+ }
+
+ private static <E> ArrayList<E> newArrayList(E... elements) {
+ ArrayList<E> list = new ArrayList<E>();
+ Collections.addAll(list, elements);
+ return list;
+ }
+
+}
diff --git a/tests/CoreTests/run_core_test.sh b/tests/CoreTests/run_core_test.sh
new file mode 100755
index 0000000..ffa31ed
--- /dev/null
+++ b/tests/CoreTests/run_core_test.sh
@@ -0,0 +1,6 @@
+framework=/system/framework
+bpath=$framework/core.jar:$framework/ext.jar:$framework/framework.jar:$framework/android.test.runner.jar
+adb shell exec dalvikvm -Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=3001 \
+ -Xbootclasspath:$bpath -cp /data/app/android.core.apk \
+ -Djava.io.tmpdir=/sdcard/tmp \
+ com.android.internal.util.WithFramework junit.textui.TestRunner $*
diff --git a/tests/CoreTests/run_junit.sh b/tests/CoreTests/run_junit.sh
new file mode 100755
index 0000000..b77794d
--- /dev/null
+++ b/tests/CoreTests/run_junit.sh
@@ -0,0 +1,9 @@
+# runs unit tests over adb shell using dalvikvm. The value added is setting the classpath for you
+# and pointing to the junit textui test runner.
+#
+# the normal usage might be:
+# (make MoreJavaTests)
+# $ adb sync
+# $ java/tests/run_junit.sh android.util.MyTest
+
+adb shell exec dalvikvm -cp system/app/MoreTests.apk junit.textui.TestRunner $*