diff options
Diffstat (limited to 'tests/CoreTests')
132 files changed, 21629 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..3b80228 --- /dev/null +++ b/tests/CoreTests/android/Android.mk @@ -0,0 +1,15 @@ +LOCAL_PATH:= $(call my-dir) +include $(CLEAR_VARS) + +LOCAL_MODULE_TAGS := eng 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..8eb5ca0 --- /dev/null +++ b/tests/CoreTests/android/AndroidManifest.xml @@ -0,0 +1,53 @@ +<?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" /> + + <!-- 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"/> + + <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/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/SSLSocketTest.java b/tests/CoreTests/android/core/SSLSocketTest.java new file mode 100644 index 0000000..922090a --- /dev/null +++ b/tests/CoreTests/android/core/SSLSocketTest.java @@ -0,0 +1,872 @@ +/* + * 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 java.io.ByteArrayInputStream; +import java.io.DataInputStream; +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.cert.X509Certificate; +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.SSLSocket; +import javax.net.ssl.SSLSocketFactory; +import javax.net.ssl.TrustManager; +import javax.net.ssl.X509TrustManager; + +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(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 ? clientFactory.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(); + } + } + + /** + * 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."); + } + } + + +} 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/TestHandler.java b/tests/CoreTests/android/core/TestHandler.java new file mode 100644 index 0000000..4ff2e6e --- /dev/null +++ b/tests/CoreTests/android/core/TestHandler.java @@ -0,0 +1,174 @@ +/* //device/java/android/com/android/tests/TestHandler.java +** +** Copyright 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 com.android.internal.os.HandlerHelper; +import android.os.HandlerInterface; +import android.os.Looper; +import android.os.Message; +import android.os.SystemClock; + +/** + * Naive class that implements a getNextMessage() + * by running a Handler in a new thread. <p> + * <p/> + * This class blocks the Handler thread when the getNextMessage() thread + * is not in getNextMessage(). This allows the getNextMessage() thread to + * inspect state that is otherwise unguarded and would otherwise be prone to + * race conditions.<p> + * <p/> + * Please note that both threads are allowed to run unsynchronized until + * the first message is posted to this handler. + * <p/> + * Please call hh.looper.quit() when done to clean this up + */ +public class TestHandler implements Runnable, HandlerInterface { + //***** Instance Variables + + public HandlerHelper hh; + public Looper looper; + + Runnable setupRoutine; + Message nextMessage; + long failTimeoutMillis; + boolean waitBeforeReturning = true; + + //***** Class Methods + + public static TestHandler create() { + return create("TestHandler", null); + } + + public static TestHandler create(String name) { + return create(name, null); + } + + public static TestHandler create(String name, Runnable doSetup) { + TestHandler ret; + + ret = new TestHandler(); + + ret.setupRoutine = doSetup; + + synchronized (ret) { + new Thread(ret, name).start(); + while (ret.looper == null) { + try { + ret.wait(); + } catch (InterruptedException ex) { + } + } + } + + return ret; + } + + //***** Public Methods + + /** + * Maximum time to wait for a message before failing + * by throwing exception + */ + public void setFailTimeoutMillis(long msec) { + failTimeoutMillis = msec; + } + + /** + * Waits for the next message to be sent to this handler and returns it. + * Blocks the Handler's looper thread until another call to getNextMessage() + * is made + */ + + public Message getNextMessage() { + Message ret; + + synchronized (this) { + long time = SystemClock.uptimeMillis(); + + waitBeforeReturning = false; + this.notifyAll(); + + try { + while (nextMessage == null) { + if (failTimeoutMillis > 0 + && ((SystemClock.uptimeMillis() - time) + > failTimeoutMillis)) { + throw new RuntimeException("Timeout exceeded exceeded"); + } + + try { + this.wait(failTimeoutMillis); + } catch (InterruptedException ex) { + } + } + ret = nextMessage; + nextMessage = null; + } finally { + waitBeforeReturning = true; + } + } + + return ret; + } + + //***** Overridden from Runnable + + public void run() { + Looper.prepare(); + hh = new HandlerHelper(this); + + if (setupRoutine != null) { + setupRoutine.run(); + } + + synchronized (this) { + looper = Looper.myLooper(); + this.notify(); + } + + Looper.loop(); + } + + //***** HandlerHelper implementation + + public void handleMessage(Message msg) { + synchronized (this) { + while (nextMessage != null) { + try { + this.wait(); + } catch (InterruptedException ex) { + } + } + + // msg will be recycled when this method returns. + // so we need to make a copy of it. + nextMessage = Message.obtain(); + nextMessage.copyFrom(msg); + this.notifyAll(); + + while (waitBeforeReturning) { + try { + this.wait(); + } catch (InterruptedException ex) { + } + } + } + } +} + + 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..f2bff4d --- /dev/null +++ b/tests/CoreTests/android/location/LocationManagerProximityTest.java @@ -0,0 +1,294 @@ +/* + * 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.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 com.google.android.mapstests.api.LocationProximityTest \ + * -w com.google.android.mapstests/.MapInstrumentationTestRunner + * + */ +@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 String mOriginalAllowedProviders; + + 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(); + mOriginalAllowedProviders = + android.provider.Settings.Secure.getString( + getContext().getContentResolver(), + android.provider.Settings.Secure.LOCATION_PROVIDERS_ALLOWED); + + // ensure 'only' the mock provider is enabled + // need to do this so the proximity listener does not ignore the mock + // updates in favor of gps updates + android.provider.Settings.Secure.putString( + getContext().getContentResolver(), + android.provider.Settings.Secure.LOCATION_PROVIDERS_ALLOWED, + PROVIDER_NAME); + + 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); + } + + if (mOriginalAllowedProviders != null) { + // restore original settings + android.provider.Settings.Secure.putString( + getContext().getContentResolver(), + android.provider.Settings.Secure.LOCATION_PROVIDERS_ALLOWED, + mOriginalAllowedProviders); + mLocationManager.updateProviders(); + } + } + + /** + * 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..359c902 --- /dev/null +++ b/tests/CoreTests/android/test/InstrumentationTestRunnerTest.java @@ -0,0 +1,251 @@ +/* + * 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")); + + } + + 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() { + 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..6844de7 --- /dev/null +++ b/tests/CoreTests/android/webkit/CookieTest.java @@ -0,0 +1,184 @@ +/* + * 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")); + } +} 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..ec9b3ef --- /dev/null +++ b/tests/CoreTests/com/android/internal/telephony/gsm/GSMPhoneTest.java @@ -0,0 +1,2024 @@ +/* + * 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.core.TestHandler; +import android.os.AsyncResult; +import android.os.Message; +import android.telephony.ServiceState; +import android.test.AndroidTestCase; +import android.test.PerformanceTestCase; + +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.test.SimulatedCommands; +import com.android.internal.telephony.test.SimulatedRadioControl; + +import java.util.List; + +public class GSMPhoneTest extends AndroidTestCase implements PerformanceTestCase { + private SimulatedRadioControl mRadioControl; + private TestHandler mTestHandler; + private GSMPhone mGSMPhone; + + 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 FAIL_TIMEOUT_MILLIS = 5 * 1000; + + @Override + protected void setUp() throws Exception { + super.setUp(); + + mTestHandler = TestHandler.create("GSMPhoneTest TestHandler", + new Runnable() { + public void run() { + SimulatedCommands sc = new SimulatedCommands(); + mRadioControl = sc; + mGSMPhone = new GSMPhone( + mContext, sc, + new TestPhoneNotifier(), + true); + + } + } + ); + + mTestHandler.setFailTimeoutMillis(FAIL_TIMEOUT_MILLIS); + mGSMPhone.registerForPhoneStateChanged(mTestHandler.hh, EVENT_PHONE_STATE_CHANGED, null); + mGSMPhone.registerForNewRingingConnection(mTestHandler.hh, EVENT_RINGING, null); + mGSMPhone.registerForDisconnect(mTestHandler.hh, EVENT_DISCONNECT, null); + + mGSMPhone.setOnPostDialCharacter(mTestHandler.hh, EVENT_POST_DIAL, null); + + mGSMPhone.registerForSuppServiceNotification(mTestHandler.hh, EVENT_SSN, null); + mGSMPhone.registerForMmiInitiate(mTestHandler.hh, EVENT_MMI_INITIATE, null); + mGSMPhone.registerForMmiComplete(mTestHandler.hh, EVENT_MMI_COMPLETE, null); + mGSMPhone.registerForSuppServiceFailed(mTestHandler.hh, SUPP_SERVICE_FAILED, null); + + mGSMPhone.registerForServiceStateChanged(mTestHandler.hh, SERVICE_STATE_CHANGED, null); + + // wait until we get phone in both voice and data service + Message msg; + ServiceState state; + do { + do { + msg = mTestHandler.getNextMessage(); + } while (msg.what != SERVICE_STATE_CHANGED); + state = (ServiceState) ((AsyncResult) msg.obj).result; + } while (state.getState() != ServiceState.STATE_IN_SERVICE); + + } + + @Override + protected void tearDown() throws Exception { + mGSMPhone.unregisterForPhoneStateChanged(mTestHandler.hh); + mGSMPhone.unregisterForNewRingingConnection(mTestHandler.hh); + mGSMPhone.unregisterForDisconnect(mTestHandler.hh); + mGSMPhone.setOnPostDialCharacter(null, 0, null); + mGSMPhone.unregisterForSuppServiceNotification(mTestHandler.hh); + mGSMPhone.unregisterForMmiInitiate(mTestHandler.hh); + mGSMPhone.unregisterForMmiComplete(mTestHandler.hh); + + mRadioControl.shutdown(); + + mTestHandler.hh.sendMessage(mTestHandler.hh.obtainMessage(EVENT_DONE)); + + Message msg; + + do { + msg = mTestHandler.getNextMessage(); + } while (msg.what != EVENT_DONE); + + mTestHandler.looper.quit(); + + mGSMPhone = null; + mRadioControl = null; + mTestHandler = null; + + 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()); + + do { + msg = mTestHandler.getNextMessage(); + } while (msg.what != EVENT_PHONE_STATE_CHANGED); + + assertEquals(Phone.State.OFFHOOK, mGSMPhone.getState()); + assertEquals(Call.State.DIALING, mGSMPhone.getForegroundCall().getState()); + assertTrue(mGSMPhone.getForegroundCall().isDialingOrAlerting()); + + /* + do { + th.getNextMessage(); + } while (phone.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 { + mTestHandler.getNextMessage(); + } + 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 { + mTestHandler.getNextMessage(); + } 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(); + + do { + msg = mTestHandler.getNextMessage(); + } while (msg.what != EVENT_DISCONNECT); + + 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"); + + do { + msg = mTestHandler.getNextMessage(); + } while (msg.what != EVENT_RINGING); + + 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 { + mTestHandler.getNextMessage(); + } 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"); + } + + do { + msg = mTestHandler.getNextMessage(); + } while (msg.what != EVENT_DISCONNECT); + + + 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 { + mTestHandler.getNextMessage(); + } 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 { + mTestHandler.getNextMessage(); + } 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 { + mTestHandler.getNextMessage(); + } 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 { + mTestHandler.getNextMessage(); + } while (mGSMPhone.getState() != Phone.State.IDLE); + + assertEquals(Connection.DisconnectCause.INCOMING_MISSED, cn.getDisconnectCause()); + + // One Ringing Call + + mRadioControl.triggerRing("18005551212"); + + do { + mTestHandler.getNextMessage(); + } while (mGSMPhone.getState() != Phone.State.RINGING); + + + cn = mGSMPhone.getRingingCall().getEarliestConnection(); + + // One answered call + mGSMPhone.acceptCall(); + + do { + mTestHandler.getNextMessage(); + } 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 { + mTestHandler.getNextMessage(); + } 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 { + mTestHandler.getNextMessage(); + } + 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 { + mTestHandler.getNextMessage(); + } 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 { + mTestHandler.getNextMessage(); + } while (mGSMPhone.getState() != Phone.State.RINGING); + + mGSMPhone.rejectCall(); + + do { + msg = mTestHandler.getNextMessage(); + } 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 { + mTestHandler.getNextMessage(); + } while (mGSMPhone.getState() != Phone.State.RINGING); + + cn = mGSMPhone.getRingingCall().getEarliestConnection(); + + mGSMPhone.acceptCall(); + + do { + mTestHandler.getNextMessage(); + } 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 { + mTestHandler.getNextMessage(); + } 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 { + mTestHandler.getNextMessage(); + } while (mGSMPhone.getState() != Phone.State.OFFHOOK); + + assertTrue(mGSMPhone.getForegroundCall().isDialingOrAlerting()); + + mRadioControl.progressConnectingCallState(); + mRadioControl.progressConnectingCallState(); + + // One ACTIVE call + + do { + mTestHandler.getNextMessage(); + } while (mGSMPhone.getForegroundCall().getState() != Call.State.ACTIVE); + + assertFalse(mGSMPhone.getForegroundCall().isDialingOrAlerting()); + + // One ACTIVE call, one ringing call + + mRadioControl.triggerRing("18005551212"); + + do { + mTestHandler.getNextMessage(); + } while (mGSMPhone.getState() != Phone.State.RINGING); + + assertFalse(mGSMPhone.getForegroundCall().isDialingOrAlerting()); + assertTrue(mGSMPhone.getRingingCall().isRinging()); + + // One HOLDING call, one ACTIVE call + mGSMPhone.acceptCall(); + + do { + mTestHandler.getNextMessage(); + } 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 { + mTestHandler.getNextMessage(); + } 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 { + mTestHandler.getNextMessage(); + } + 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 { + mTestHandler.getNextMessage(); + } 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 { + mTestHandler.getNextMessage(); + } 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 { + mTestHandler.getNextMessage(); + } 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"); + + do { + msg = mTestHandler.getNextMessage(); + } while (msg.what != EVENT_DISCONNECT); + + 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 { + mTestHandler.getNextMessage(); + } + while (mGSMPhone.getForegroundCall().getState() != Call.State.DIALING); + + cn = mGSMPhone.getForegroundCall().getEarliestConnection(); + + mGSMPhone.getForegroundCall().hangup(); + + do { + msg = mTestHandler.getNextMessage(); + } while (msg.what != EVENT_DISCONNECT); + + 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 { + mTestHandler.getNextMessage(); + } while (mGSMPhone.getState() != Phone.State.OFFHOOK); + + mRadioControl.progressConnectingCallState(); + + do { + mTestHandler.getNextMessage(); + } + while (mGSMPhone.getForegroundCall().getState() != Call.State.ALERTING); + + cn = mGSMPhone.getForegroundCall().getEarliestConnection(); + + mGSMPhone.getForegroundCall().hangup(); + + do { + msg = mTestHandler.getNextMessage(); + } while (msg.what != EVENT_DISCONNECT); + + 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(); + + do { + msg = mTestHandler.getNextMessage(); + } while (msg.what != EVENT_DISCONNECT); + + 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 { + mTestHandler.getNextMessage(); + } while (mGSMPhone.getForegroundCall().getConnections().isEmpty()); + + mRadioControl.shutdown(); + + do { + mTestHandler.getNextMessage(); + mGSMPhone.clearDisconnected(); + } while (!mGSMPhone.getForegroundCall().getConnections().isEmpty()); + } + + public void testIncallMmiCallDeflection() throws Exception { + Message msg; + + // establish an active call + mGSMPhone.dial("+13125551212"); + + do { + mRadioControl.progressConnectingCallState(); + mTestHandler.getNextMessage(); + } 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 = mTestHandler.getNextMessage(); + } 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 0 followed by SEND: release all held calls + // or sets UDUB for a waiting call. + mGSMPhone.handleInCallMmiCommands("0"); + + do { + mTestHandler.getNextMessage(); + } 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 { + mTestHandler.getNextMessage(); + } 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 { + mTestHandler.getNextMessage(); + } 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(); + mTestHandler.getNextMessage(); + } 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 = mTestHandler.getNextMessage(); + } 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 { + mTestHandler.getNextMessage(); + } 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 { + mTestHandler.getNextMessage(); + } 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 { + mTestHandler.getNextMessage(); + } 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"); + + do { + msg = mTestHandler.getNextMessage(); + } 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 "12" followed by SEND: release the call with + // gsm index equals to 2. + mGSMPhone.handleInCallMmiCommands("12"); + + do { + mTestHandler.getNextMessage(); + } 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 { + mTestHandler.getNextMessage(); + } 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(); + mTestHandler.getNextMessage(); + } 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"); + do { + msg = mTestHandler.getNextMessage(); + } while (msg != null && msg.what != SUPP_SERVICE_FAILED); + 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 { + mTestHandler.getNextMessage(); + } 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 { + mTestHandler.getNextMessage(); + } 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 { + mTestHandler.getNextMessage(); + } 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(); + mTestHandler.getNextMessage(); + } 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 = mTestHandler.getNextMessage(); + } 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 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 { + mTestHandler.getNextMessage(); + } 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"); + + do { + msg = mTestHandler.getNextMessage(); + } while (msg.what != EVENT_PHONE_STATE_CHANGED); + + 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 { + mTestHandler.getNextMessage(); + } 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"); + + do { + msg = mTestHandler.getNextMessage(); + } while (msg != null && msg.what != SUPP_SERVICE_FAILED); + 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 { + mTestHandler.getNextMessage(); + } 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(); + mTestHandler.getNextMessage(); + } 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(); + mTestHandler.getNextMessage(); + } 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 { + mTestHandler.getNextMessage(); + } 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(); + mTestHandler.getNextMessage(); + } 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(); + mTestHandler.getNextMessage(); + } 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 { + mTestHandler.getNextMessage(); + } 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"); + + do { + msg = mTestHandler.getNextMessage(); + } 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.HOLDING, mGSMPhone.getBackgroundCall().getState()); + + // hangup the background call and accept the ringing call + mGSMPhone.getBackgroundCall().hangup(); + mGSMPhone.acceptCall(); + + do { + mTestHandler.getNextMessage(); + } 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 { + mTestHandler.getNextMessage(); + } 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 { + mTestHandler.getNextMessage(); + } 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 { + mTestHandler.getNextMessage(); + } 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"); + + do { + msg = mTestHandler.getNextMessage(); + mRadioControl.progressConnectingToActive(); + } while (msg.what != EVENT_POST_DIAL); + + ar = (AsyncResult) (msg.obj); + cn = (Connection) (ar.result); + assertEquals(',', msg.arg1); + assertEquals("1234;5N8", cn.getRemainingPostDialString()); + + + do { + msg = mTestHandler.getNextMessage(); + } while (msg.what != EVENT_POST_DIAL); + + assertEquals('1', msg.arg1); + ar = (AsyncResult) (msg.obj); + assertEquals(Connection.PostDialState.STARTED, ar.userObj); + + do { + msg = mTestHandler.getNextMessage(); + } while (msg.what != EVENT_POST_DIAL); + + assertEquals('2', msg.arg1); + ar = (AsyncResult) (msg.obj); + assertEquals(Connection.PostDialState.STARTED, ar.userObj); + + do { + msg = mTestHandler.getNextMessage(); + } while (msg.what != EVENT_POST_DIAL); + + assertEquals('3', msg.arg1); + ar = (AsyncResult) (msg.obj); + assertEquals(Connection.PostDialState.STARTED, ar.userObj); + + do { + msg = mTestHandler.getNextMessage(); + } while (msg.what != EVENT_POST_DIAL); + + assertEquals('4', msg.arg1); + ar = (AsyncResult) (msg.obj); + assertEquals(Connection.PostDialState.STARTED, ar.userObj); + + do { + msg = mTestHandler.getNextMessage(); + } while (msg.what != EVENT_POST_DIAL); + + 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(); + + do { + msg = mTestHandler.getNextMessage(); + } while (msg.what != EVENT_POST_DIAL); + + assertEquals('5', msg.arg1); + ar = (AsyncResult) (msg.obj); + assertEquals(Connection.PostDialState.STARTED, ar.userObj); + + do { + msg = mTestHandler.getNextMessage(); + } while (msg.what != 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"); + + do { + msg = mTestHandler.getNextMessage(); + } while (msg.what != EVENT_POST_DIAL); + + ar = (AsyncResult) (msg.obj); + cn = (Connection) (ar.result); + assertEquals(',', msg.arg1); + assertEquals("6;78", cn.getRemainingPostDialString()); + + do { + msg = mTestHandler.getNextMessage(); + } while (msg.what != EVENT_POST_DIAL); + + assertEquals('6', msg.arg1); + ar = (AsyncResult) (msg.obj); + assertEquals(Connection.PostDialState.STARTED, ar.userObj); + + do { + msg = mTestHandler.getNextMessage(); + } while (msg.what != EVENT_POST_DIAL); + + 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(); + + do { + msg = mTestHandler.getNextMessage(); + } while (msg.what != EVENT_POST_DIAL); + + assertEquals('7', msg.arg1); + ar = (AsyncResult) (msg.obj); + assertEquals(Connection.PostDialState.STARTED, ar.userObj); + + do { + msg = mTestHandler.getNextMessage(); + } while (msg.what != EVENT_POST_DIAL); + + assertEquals('8', msg.arg1); + ar = (AsyncResult) (msg.obj); + assertEquals(Connection.PostDialState.STARTED, ar.userObj); + + // Bogus chars at end should be ignored + + do { + msg = mTestHandler.getNextMessage(); + } while (msg.what != EVENT_POST_DIAL); + + 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(); + + do { + msg = mTestHandler.getNextMessage(); + } while (msg.what != EVENT_POST_DIAL); + + assertEquals(',', msg.arg1); + + do { + msg = mTestHandler.getNextMessage(); + } while (msg.what != 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 { + mTestHandler.getNextMessage(); + } while (cn.getState() == Call.State.DIALING); + + + mRadioControl.triggerHangupAll(); + + do { + msg = mTestHandler.getNextMessage(); + } while (msg.what != EVENT_DISCONNECT); + + 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 { + mTestHandler.getNextMessage(); + } while (cn.getState() == Call.State.DIALING); + + + mRadioControl.triggerHangupAll(); + + do { + msg = mTestHandler.getNextMessage(); + } while (msg.what != EVENT_DISCONNECT); + + 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 { + mTestHandler.getNextMessage(); + } 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 = mTestHandler.getNextMessage(); + } 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); + + do { + msg = mTestHandler.getNextMessage(); + } while (msg.what != EVENT_SSN); + + 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 + // 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"); + do { + msg = mTestHandler.getNextMessage(); + } while (msg.what != EVENT_MMI_COMPLETE); + + ar = (AsyncResult) msg.obj; + mmi = (MmiCode) ar.result; + + assertFalse(mmi.isUssdRequest()); + + // Receive a REQUEST and send response + mRadioControl.triggerIncomingUssd("1", "REQUEST Message"); + do { + msg = mTestHandler.getNextMessage(); + } while (msg.what != EVENT_MMI_COMPLETE); + ar = (AsyncResult) msg.obj; + mmi = (MmiCode) ar.result; + + assertTrue(mmi.isUssdRequest()); + + mGSMPhone.sendUssdResponse("## TEST: TEST_GSMPhone responding..."); + do { + msg = mTestHandler.getNextMessage(); + } while (msg.what != EVENT_MMI_INITIATE); + + ar = (AsyncResult) msg.obj; + mmi = (MmiCode) ar.result; + + GsmMmiCode gsmMmi = (GsmMmiCode) mmi; + assertTrue(gsmMmi.isPendingUSSD()); + + do { + msg = mTestHandler.getNextMessage(); + } while (msg.what != EVENT_MMI_COMPLETE); + + ar = (AsyncResult) msg.obj; + mmi = (MmiCode) ar.result; + + assertNull(ar.exception); + assertFalse(mmi.isUssdRequest()); + + // Receive a REQUEST and cancel + mRadioControl.triggerIncomingUssd("1", "REQUEST Message"); + do { + msg = mTestHandler.getNextMessage(); + } while (msg.what != EVENT_MMI_COMPLETE); + ar = (AsyncResult) msg.obj; + mmi = (MmiCode) ar.result; + + assertTrue(mmi.isUssdRequest()); + + mmi.cancel(); + + do { + msg = mTestHandler.getNextMessage(); + } while (msg.what != EVENT_MMI_COMPLETE); + + 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#"); + + do { + msg = mTestHandler.getNextMessage(); + } while (msg.what != EVENT_MMI_INITIATE); + + do { + msg = mTestHandler.getNextMessage(); + } while (msg.what != EVENT_MMI_COMPLETE); + + 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(); + + do { + msg = mTestHandler.getNextMessage(); + } while (msg.what != EVENT_MMI_INITIATE); + + do { + msg = mTestHandler.getNextMessage(); + } while (msg.what != EVENT_MMI_COMPLETE); + + 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, mTestHandler.hh.obtainMessage(999)); + + do { + msg = mTestHandler.getNextMessage(); + } while (!(msg.what == 999)); + + ar = ((AsyncResult) msg.obj); + + assertNull(ar.result); + assertNull(ar.exception); + + // empty byte array + + mGSMPhone.invokeOemRilRequestRaw(new byte[0], mTestHandler.hh.obtainMessage(999)); + + do { + msg = mTestHandler.getNextMessage(); + } while (!(msg.what == 999)); + + ar = ((AsyncResult) msg.obj); + + assertEquals(0, ((byte[]) (ar.result)).length); + assertNull(ar.exception); + + // byte array with data + + mGSMPhone.invokeOemRilRequestRaw("Hello".getBytes("utf-8"), + mTestHandler.hh.obtainMessage(999)); + + do { + msg = mTestHandler.getNextMessage(); + } while (!(msg.what == 999)); + + ar = ((AsyncResult) msg.obj); + + assertEquals("Hello", new String(((byte[]) (ar.result)), "utf-8")); + assertNull(ar.exception); + + // null strings + + mGSMPhone.invokeOemRilRequestStrings(null, mTestHandler.hh.obtainMessage(999)); + + do { + msg = mTestHandler.getNextMessage(); + } while (!(msg.what == 999)); + + ar = ((AsyncResult) msg.obj); + + assertNull(ar.result); + assertNull(ar.exception); + + // empty byte array + + mGSMPhone.invokeOemRilRequestStrings(new String[0], + mTestHandler.hh.obtainMessage(999)); + + do { + msg = mTestHandler.getNextMessage(); + } while (!(msg.what == 999)); + + 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, mTestHandler.hh.obtainMessage(999)); + + do { + msg = mTestHandler.getNextMessage(); + } while (!(msg.what == 999)); + + 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; + do { + msg = mTestHandler.getNextMessage(); + } while (msg.what != EVENT_MMI_INITIATE); + + // Should not be cancelable. + AsyncResult ar = (AsyncResult) msg.obj; + MmiCode mmi = (MmiCode) ar.result; + assertEquals(cancelable, mmi.isCancelable()); + + do { + msg = mTestHandler.getNextMessage(); + } while (msg.what != EVENT_MMI_COMPLETE); + + } + + 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(); + + Message msg; + do { + msg = mTestHandler.getNextMessage(); + } while (msg.what != 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/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..84974ef --- /dev/null +++ b/tests/CoreTests/com/android/internal/telephony/gsm/SMSDispatcherTest.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 com.android.internal.telephony.gsm; + +import android.core.TestHandler; +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..53fdd51 --- /dev/null +++ b/tests/CoreTests/com/android/internal/telephony/gsm/SimPhoneBookTest.java @@ -0,0 +1,107 @@ +/* + * 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.core.TestHandler; +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..1fc3348 --- /dev/null +++ b/tests/CoreTests/run_core_test.sh @@ -0,0 +1,4 @@ +framework=/system/framework +bpath=$framework/core.jar:$framework/ext.jar:$framework/framework.jar:$framework/android.test.runner.jar +adb shell exec dalvikvm -Xbootclasspath:$bpath -cp system/app/CoreTests.apk \ + 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 $* |