diff options
author | The Android Open Source Project <initial-contribution@android.com> | 2009-03-03 19:31:44 -0800 |
---|---|---|
committer | The Android Open Source Project <initial-contribution@android.com> | 2009-03-03 19:31:44 -0800 |
commit | 9066cfe9886ac131c34d59ed0e2d287b0e3c0087 (patch) | |
tree | d88beb88001f2482911e3d28e43833b50e4b4e97 /tests/AndroidTests | |
parent | d83a98f4ce9cfa908f5c54bbd70f03eec07e7553 (diff) | |
download | frameworks_base-9066cfe9886ac131c34d59ed0e2d287b0e3c0087.zip frameworks_base-9066cfe9886ac131c34d59ed0e2d287b0e3c0087.tar.gz frameworks_base-9066cfe9886ac131c34d59ed0e2d287b0e3c0087.tar.bz2 |
auto import from //depot/cupcake/@135843
Diffstat (limited to 'tests/AndroidTests')
214 files changed, 34096 insertions, 0 deletions
diff --git a/tests/AndroidTests/Android.mk b/tests/AndroidTests/Android.mk new file mode 100644 index 0000000..f5e49d7 --- /dev/null +++ b/tests/AndroidTests/Android.mk @@ -0,0 +1,22 @@ +LOCAL_PATH:= $(call my-dir) +include $(CLEAR_VARS) + +LOCAL_MODULE_TAGS := tests + +LOCAL_JAVA_LIBRARIES := framework-tests android.test.runner + +LOCAL_STATIC_JAVA_LIBRARIES := googlelogin-client + +# Resource unit tests use a private locale +LOCAL_AAPT_FLAGS = -c xx_YY -c cs + +LOCAL_SRC_FILES := \ + $(call all-subdir-java-files) \ + src/com/android/unit_tests/os/IAidlTest.aidl + +LOCAL_PACKAGE_NAME := AndroidTests +LOCAL_CERTIFICATE := platform + +include $(BUILD_PACKAGE) + +include $(call all-makefiles-under,$(LOCAL_PATH)) diff --git a/tests/AndroidTests/AndroidManifest.xml b/tests/AndroidTests/AndroidManifest.xml new file mode 100644 index 0000000..843d844 --- /dev/null +++ b/tests/AndroidTests/AndroidManifest.xml @@ -0,0 +1,226 @@ +<?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="com.android.unit_tests" + android:sharedUserId="com.android.uid.test"> + <permission android:name="com.android.unit_tests.permission.TEST_GRANTED" + android:protectionLevel="normal" + android:label="@string/permlab_testGranted" + android:description="@string/permdesc_testGranted"> + <meta-data android:name="com.android.unit_tests.string" android:value="foo" /> + <meta-data android:name="com.android.unit_tests.boolean" android:value="true" /> + <meta-data android:name="com.android.unit_tests.integer" android:value="100" /> + <meta-data android:name="com.android.unit_tests.color" android:value="#ff000000" /> + <meta-data android:name="com.android.unit_tests.float" android:value="100.1" /> + <meta-data android:name="com.android.unit_tests.reference" android:resource="@xml/metadata" /> + </permission> + <permission android:name="com.android.unit_tests.permission.TEST_DENIED" + android:protectionLevel="normal" + android:label="@string/permlab_testDenied" + android:description="@string/permdesc_testDenied" /> + + <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /> + <uses-permission android:name="android.permission.BROADCAST_STICKY" /> + <uses-permission android:name="android.permission.READ_CONTACTS" /> + <uses-permission android:name="android.permission.WRITE_CONTACTS" /> + <uses-permission android:name="android.permission.WRITE_SETTINGS" /> + <uses-permission android:name="android.permission.READ_SMS"/> + <uses-permission android:name="android.permission.WRITE_SMS"/> + <uses-permission android:name="android.permission.DELETE_CACHE_FILES" /> + <uses-permission android:name="android.permission.CLEAR_APP_CACHE" /> + <uses-permission android:name="android.permission.CLEAR_APP_USER_DATA" /> + <uses-permission android:name="android.permission.GET_PACKAGE_SIZE" /> + <uses-permission android:name="android.permission.READ_PHONE_STATE" /> + <uses-permission android:name="android.permission.INTERNET" /> + <uses-permission android:name="android.permission.WRITE_GSERVICES" /> + <uses-permission android:name="android.permission.WAKE_LOCK" /> + + <uses-permission android:name="com.android.unit_tests.permission.TEST_GRANTED" /> + + <uses-permission android:name="com.google.android.googleapps.permission.GOOGLE_AUTH" /> + <uses-permission android:name="com.google.android.googleapps.permission.GOOGLE_AUTH.ALL_SERVICES" /> + <uses-permission android:name="com.google.android.googleapps.permission.ACCESS_GOOGLE_PASSWORD" /> + <!-- InstrumentationTestRunner for AndroidTests --> + <instrumentation android:name="android.test.InstrumentationTestRunner" + android:targetPackage="com.android.unit_tests" + android:label="Tests for AndroidTests (unit tests collection)"/> + + <application> + <uses-library android:name="android.test.runner" /> + + <!-- Activity-level metadata --> + <meta-data android:name="com.android.unit_tests.isApp" android:value="true" /> + <meta-data android:name="com.android.unit_tests.string" android:value="foo" /> + <meta-data android:name="com.android.unit_tests.boolean" android:value="true" /> + <meta-data android:name="com.android.unit_tests.integer" android:value="100" /> + <meta-data android:name="com.android.unit_tests.color" android:value="#ff000000" /> + <meta-data android:name="com.android.unit_tests.float" android:value="100.1" /> + <meta-data android:name="com.android.unit_tests.reference" + android:resource="@xml/metadata_app" /> + + <activity android:name="AndroidPerformanceTests" android:label="Android Performance Tests"> + <intent-filter> + <action android:name="android.intent.action.MAIN" /> + <category android:name="android.intent.category.UNIT_TEST" /> + </intent-filter> + </activity> + + <!-- Application components used for activity tests --> + + <activity android:name=".activity.TestedActivity" + android:process=":remoteActivity"> + </activity> + <activity android:name=".activity.LocalActivity" android:multiprocess="true"> + <meta-data android:name="com.android.unit_tests.string" android:value="foo" /> + <meta-data android:name="com.android.unit_tests.boolean" android:value="true" /> + <meta-data android:name="com.android.unit_tests.integer" android:value="100" /> + <meta-data android:name="com.android.unit_tests.color" android:value="#ff000000" /> + <meta-data android:name="com.android.unit_tests.float" android:value="100.1" /> + <meta-data android:name="com.android.unit_tests.reference" android:resource="@xml/metadata" /> + </activity> + <activity android:name=".activity.TestedScreen" + android:process=":remoteScreen"> + </activity> + <activity android:name=".activity.LocalScreen" android:multiprocess="true"> + </activity> + <activity android:name=".activity.ClearTop" android:multiprocess="true" + android:launchMode="singleTop"> + </activity> + <activity android:name=".activity.LocalDialog" android:multiprocess="true" + android:theme="@android:style/Theme.Dialog"> + </activity> + <activity android:name=".activity.SubActivityScreen"> + </activity> + <activity android:name=".activity.RemoteSubActivityScreen" + android:process=":remoteActivity"> + </activity> + <activity android:name=".activity.LaunchpadActivity" android:multiprocess="true"> + </activity> + <activity android:name=".activity.LaunchpadTabActivity" android:multiprocess="true"> + </activity> + + <receiver android:name=".activity.AbortReceiver"> + <intent-filter android:priority="1"> + <action android:name="com.android.unit_tests.activity.BROADCAST_ABORT" /> + </intent-filter> + </receiver> + <receiver android:name=".activity.LocalReceiver"> + <intent-filter android:priority="-1"> + <action android:name="com.android.unit_tests.activity.BROADCAST_ABORT" /> + <action android:name="com.android.unit_tests.activity.BROADCAST_ALL" /> + <action android:name="com.android.unit_tests.activity.BROADCAST_REPEAT" /> + <action android:name="com.android.unit_tests.activity.BROADCAST_LOCAL" /> + <action android:name="com.android.unit_tests.activity.BROADCAST_FAIL_REGISTER" /> + <action android:name="com.android.unit_tests.activity.BROADCAST_FAIL_BIND" /> + </intent-filter> + <meta-data android:name="com.android.unit_tests.string" android:value="foo" /> + <meta-data android:name="com.android.unit_tests.boolean" android:value="true" /> + <meta-data android:name="com.android.unit_tests.integer" android:value="100" /> + <meta-data android:name="com.android.unit_tests.color" android:value="#ff000000" /> + <meta-data android:name="com.android.unit_tests.float" android:value="100.1" /> + <meta-data android:name="com.android.unit_tests.reference" android:resource="@xml/metadata" /> + </receiver> + <receiver android:name=".activity.ResultReceiver"> + <intent-filter> + <action android:name="com.android.unit_tests.activity.BROADCAST_RESULT" /> + </intent-filter> + </receiver> + <receiver android:name=".activity.LocalGrantedReceiver" + android:permission="com.android.unit_tests.permission.TEST_GRANTED"> + <intent-filter android:priority="-1"> + <action android:name="com.android.unit_tests.activity.BROADCAST_LOCAL_GRANTED" /> + </intent-filter> + </receiver> + <receiver android:name=".activity.LocalDeniedReceiver" + android:permission="com.android.unit_tests.permission.TEST_DENIED"> + <intent-filter android:priority="-1"> + <action android:name="com.android.unit_tests.activity.BROADCAST_LOCAL_DENIED" /> + </intent-filter> + </receiver> + <receiver android:name=".activity.RemoteReceiver" + android:process=":remoteReceiver"> + <intent-filter android:priority="2"> + <action android:name="com.android.unit_tests.activity.BROADCAST_ABORT" /> + <action android:name="com.android.unit_tests.activity.BROADCAST_ALL" /> + <action android:name="com.android.unit_tests.activity.BROADCAST_REPEAT" /> + <action android:name="com.android.unit_tests.activity.BROADCAST_REMOTE" /> + </intent-filter> + </receiver> + <receiver android:name=".activity.RemoteGrantedReceiver" + android:permission="com.android.unit_tests.permission.TEST_GRANTED"> + <intent-filter android:priority="2"> + <action android:name="com.android.unit_tests.activity.BROADCAST_REMOTE_GRANTED" /> + </intent-filter> + </receiver> + <receiver android:name=".activity.RemoteDeniedReceiver" + android:permission="com.android.unit_tests.permission.TEST_DENIED"> + <intent-filter android:priority="2"> + <action android:name="com.android.unit_tests.activity.BROADCAST_REMOTE_DENIED" /> + </intent-filter> + </receiver> + <service android:name=".activity.LocalService"> + <intent-filter> + <action android:name="com.android.unit_tests.activity.SERVICE_LOCAL" /> + </intent-filter> + <meta-data android:name="com.android.unit_tests.string" android:value="foo" /> + <meta-data android:name="com.android.unit_tests.boolean" android:value="true" /> + <meta-data android:name="com.android.unit_tests.integer" android:value="100" /> + <meta-data android:name="com.android.unit_tests.color" android:value="#ff000000" /> + <meta-data android:name="com.android.unit_tests.float" android:value="100.1" /> + <meta-data android:name="com.android.unit_tests.reference" android:resource="@xml/metadata" /> + </service> + <service android:name=".activity.LocalDeniedService" + android:permission="com.android.unit_tests.permission.TEST_DENIED"> + <intent-filter> + <action android:name="com.android.unit_tests.activity.SERVICE_LOCAL_DENIED" /> + </intent-filter> + </service> + <service android:name=".activity.LocalGrantedService" + android:permission="com.android.unit_tests.permission.TEST_GRANTED"> + <intent-filter> + <action android:name="com.android.unit_tests.activity.SERVICE_LOCAL_GRANTED" /> + </intent-filter> + </service> + + <provider android:name=".activity.LocalProvider" + android:authorities="com.android.unit_tests.LocalProvider"> + <meta-data android:name="com.android.unit_tests.string" android:value="foo" /> + <meta-data android:name="com.android.unit_tests.boolean" android:value="true" /> + <meta-data android:name="com.android.unit_tests.integer" android:value="100" /> + <meta-data android:name="com.android.unit_tests.color" android:value="#ff000000" /> + <meta-data android:name="com.android.unit_tests.float" android:value="100.1" /> + <meta-data android:name="com.android.unit_tests.reference" android:resource="@xml/metadata" /> + </provider> + + <!-- Application components used for os tests --> + + <service android:name=".os.MessengerService" + android:process=":messengerService"> + </service> + + <!-- Application components used for search manager tests --> + <!-- TODO: Removed temporarily - need to be replaced using mocks --> + + <!-- Used to test IPC. --> + <service android:name=".binder.BinderTestService" + android:process="binder.BinderTestService" /> + <service android:name=".binder.BinderPerformanceService" + android:process="binder.BinderPerformanceService" /> + <service android:name=".binder.BinderVsMessagingService" + android:process="binder.BinderVsMessagingService" /> + </application> +</manifest> diff --git a/tests/AndroidTests/DisabledTestApp/Android.mk b/tests/AndroidTests/DisabledTestApp/Android.mk new file mode 100644 index 0000000..a5daedf --- /dev/null +++ b/tests/AndroidTests/DisabledTestApp/Android.mk @@ -0,0 +1,12 @@ +LOCAL_PATH:= $(call my-dir) +include $(CLEAR_VARS) + +LOCAL_MODULE_TAGS := tests + +LOCAL_SRC_FILES := $(call all-subdir-java-files) + +LOCAL_PACKAGE_NAME := DisabledTestApp +LOCAL_CERTIFICATE := platform + +include $(BUILD_PACKAGE) + diff --git a/tests/AndroidTests/DisabledTestApp/AndroidManifest.xml b/tests/AndroidTests/DisabledTestApp/AndroidManifest.xml new file mode 100644 index 0000000..4d6843e --- /dev/null +++ b/tests/AndroidTests/DisabledTestApp/AndroidManifest.xml @@ -0,0 +1,13 @@ +<manifest xmlns:android="http://schemas.android.com/apk/res/android" + package="com.android.unit_tests.disabled_app" + android:sharedUserId="com.android.uid.test"> + + <application enabled="false"> + + <!-- Used to test package component enabling and disabling --> + <activity android:name=".DisabledActivity" android:enabled="false" > + </activity> + <activity android:name=".EnabledActivity" > + </activity> + </application> +</manifest> diff --git a/tests/AndroidTests/DisabledTestApp/src/com/android/unit_tests/disabled_app/EnabledActivity.java b/tests/AndroidTests/DisabledTestApp/src/com/android/unit_tests/disabled_app/EnabledActivity.java new file mode 100644 index 0000000..4e4dc85 --- /dev/null +++ b/tests/AndroidTests/DisabledTestApp/src/com/android/unit_tests/disabled_app/EnabledActivity.java @@ -0,0 +1,27 @@ +/* + * Copyright (C) 2008 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.unit_tests.disabled_app; + +import android.app.Activity; + +/** + * Empty Activity for testing + */ + +public class EnabledActivity extends Activity { + +} diff --git a/tests/AndroidTests/EnabledTestApp/Android.mk b/tests/AndroidTests/EnabledTestApp/Android.mk new file mode 100644 index 0000000..4b986d3 --- /dev/null +++ b/tests/AndroidTests/EnabledTestApp/Android.mk @@ -0,0 +1,12 @@ +LOCAL_PATH:= $(call my-dir) +include $(CLEAR_VARS) + +LOCAL_MODULE_TAGS := tests + +LOCAL_SRC_FILES := $(call all-subdir-java-files) + +LOCAL_PACKAGE_NAME := EnabledTestApp +LOCAL_CERTIFICATE := platform + +include $(BUILD_PACKAGE) + diff --git a/tests/AndroidTests/EnabledTestApp/AndroidManifest.xml b/tests/AndroidTests/EnabledTestApp/AndroidManifest.xml new file mode 100644 index 0000000..ad610f1 --- /dev/null +++ b/tests/AndroidTests/EnabledTestApp/AndroidManifest.xml @@ -0,0 +1,37 @@ +<manifest xmlns:android="http://schemas.android.com/apk/res/android" + package="com.android.unit_tests.enabled_app" + android:sharedUserId="com.android.uid.test"> + + <application> + + <!-- Used to test package component enabling and disabling --> + <activity android:name=".DisabledActivity" android:enabled="false" > + <intent-filter> + <action android:name="android.intent.action.MAIN" /> + <category android:name="com.android.unit_tests.enabled_app.TEST_CATEGORY" /> + </intent-filter> + </activity> + <service android:name=".DisabledService" android:enabled="false" > + </service> + <receiver android:name=".DisabledReceiver" android:enabled="false" > + <intent-filter> + <action android:name="android.intent.action.ENABLED_APP_DISABLED_RECEIVER" /> + </intent-filter> + </receiver> + <provider android:name=".DisabledProvider" android:enabled="false" + android:authorities="com.android.unit_tests.enabled_app.DisabledProvider" + android:process=":disabled.provider.process" /> + <activity android:name=".EnabledActivity" > + </activity> + <service android:name=".EnabledService" android:enabled="true" > + </service> + <receiver android:name=".EnabledReceiver" > + <intent-filter> + <action android:name="android.intent.action.ENABLED_APP_ENABLED_RECEIVER" /> + </intent-filter> + </receiver> + <provider android:name=".EnabledProvider" + android:authorities="com.android.unit_tests.enabled_app.EnabledProvider" + android:process=":enabled.provider.process" /> + </application> +</manifest> diff --git a/tests/AndroidTests/EnabledTestApp/src/com/android/unit_tests/enabled_app/DisabledActivity.java b/tests/AndroidTests/EnabledTestApp/src/com/android/unit_tests/enabled_app/DisabledActivity.java new file mode 100644 index 0000000..0ab0416 --- /dev/null +++ b/tests/AndroidTests/EnabledTestApp/src/com/android/unit_tests/enabled_app/DisabledActivity.java @@ -0,0 +1,27 @@ +/* + * Copyright (C) 2008 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.unit_tests.enabled_app; + +import android.app.Activity; + +/** + * Empty Activity for testing + */ + +public class DisabledActivity extends Activity { + +} diff --git a/tests/AndroidTests/EnabledTestApp/src/com/android/unit_tests/enabled_app/DisabledProvider.java b/tests/AndroidTests/EnabledTestApp/src/com/android/unit_tests/enabled_app/DisabledProvider.java new file mode 100644 index 0000000..06527f9 --- /dev/null +++ b/tests/AndroidTests/EnabledTestApp/src/com/android/unit_tests/enabled_app/DisabledProvider.java @@ -0,0 +1,54 @@ +/* + * Copyright (C) 2008 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.unit_tests.enabled_app; + +import android.content.ContentProvider; +import android.content.ContentValues; +import android.database.Cursor; +import android.net.Uri; + +/** + * Empty ContentProvider for testing + */ + +public class DisabledProvider extends ContentProvider { + + public boolean onCreate() { + return false; + } + + public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, + String sortOrder) { + return null; + } + + public String getType(Uri uri) { + return null; + } + + public Uri insert(Uri uri, ContentValues values) { + return null; + } + + public int delete(Uri uri, String selection, String[] selectionArgs) { + return 0; + } + + public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) { + return 0; + } +} diff --git a/tests/AndroidTests/EnabledTestApp/src/com/android/unit_tests/enabled_app/DisabledReceiver.java b/tests/AndroidTests/EnabledTestApp/src/com/android/unit_tests/enabled_app/DisabledReceiver.java new file mode 100644 index 0000000..c27b87e --- /dev/null +++ b/tests/AndroidTests/EnabledTestApp/src/com/android/unit_tests/enabled_app/DisabledReceiver.java @@ -0,0 +1,32 @@ +/* + * Copyright (C) 2008 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.unit_tests.enabled_app; + +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; + +/** + * Empty IntentReceiver for testing + */ + +public class DisabledReceiver extends BroadcastReceiver { + + public void onReceive(Context context, Intent intent) { + + } +} diff --git a/tests/AndroidTests/EnabledTestApp/src/com/android/unit_tests/enabled_app/DisabledService.java b/tests/AndroidTests/EnabledTestApp/src/com/android/unit_tests/enabled_app/DisabledService.java new file mode 100644 index 0000000..ed8d0b9 --- /dev/null +++ b/tests/AndroidTests/EnabledTestApp/src/com/android/unit_tests/enabled_app/DisabledService.java @@ -0,0 +1,32 @@ +/* + * Copyright (C) 2008 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.unit_tests.enabled_app; + +import android.app.Service; +import android.os.IBinder; +import android.content.Intent; + +/** + * Empty Service for testing + */ + +public class DisabledService extends Service { + + public IBinder onBind(Intent intent) { + return null; + } +} diff --git a/tests/AndroidTests/EnabledTestApp/src/com/android/unit_tests/enabled_app/EnabledActivity.java b/tests/AndroidTests/EnabledTestApp/src/com/android/unit_tests/enabled_app/EnabledActivity.java new file mode 100644 index 0000000..cfac3ec --- /dev/null +++ b/tests/AndroidTests/EnabledTestApp/src/com/android/unit_tests/enabled_app/EnabledActivity.java @@ -0,0 +1,27 @@ +/* + * Copyright (C) 2008 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.unit_tests.enabled_app; + +import android.app.Activity; + +/** + * Empty Activity for testing + */ + +public class EnabledActivity extends Activity { + +} diff --git a/tests/AndroidTests/EnabledTestApp/src/com/android/unit_tests/enabled_app/EnabledProvider.java b/tests/AndroidTests/EnabledTestApp/src/com/android/unit_tests/enabled_app/EnabledProvider.java new file mode 100644 index 0000000..764937f --- /dev/null +++ b/tests/AndroidTests/EnabledTestApp/src/com/android/unit_tests/enabled_app/EnabledProvider.java @@ -0,0 +1,54 @@ +/* + * Copyright (C) 2008 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.unit_tests.enabled_app; + +import android.content.ContentProvider; +import android.content.ContentValues; +import android.database.Cursor; +import android.net.Uri; + +/** + * Empty ContentProvider for testing + */ + +public class EnabledProvider extends ContentProvider { + + public boolean onCreate() { + return false; + } + + public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, + String sortOrder) { + return null; + } + + public String getType(Uri uri) { + return null; + } + + public Uri insert(Uri uri, ContentValues values) { + return null; + } + + public int delete(Uri uri, String selection, String[] selectionArgs) { + return 0; + } + + public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) { + return 0; + } +} diff --git a/tests/AndroidTests/EnabledTestApp/src/com/android/unit_tests/enabled_app/EnabledReceiver.java b/tests/AndroidTests/EnabledTestApp/src/com/android/unit_tests/enabled_app/EnabledReceiver.java new file mode 100644 index 0000000..707448f --- /dev/null +++ b/tests/AndroidTests/EnabledTestApp/src/com/android/unit_tests/enabled_app/EnabledReceiver.java @@ -0,0 +1,32 @@ +/* + * Copyright (C) 2008 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.unit_tests.enabled_app; + +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; + +/** + * Empty IntentReceiver for testing + */ + +public class EnabledReceiver extends BroadcastReceiver { + + public void onReceive(Context context, Intent intent) { + + } +} diff --git a/tests/AndroidTests/EnabledTestApp/src/com/android/unit_tests/enabled_app/EnabledService.java b/tests/AndroidTests/EnabledTestApp/src/com/android/unit_tests/enabled_app/EnabledService.java new file mode 100644 index 0000000..81a80b3 --- /dev/null +++ b/tests/AndroidTests/EnabledTestApp/src/com/android/unit_tests/enabled_app/EnabledService.java @@ -0,0 +1,32 @@ +/* + * Copyright (C) 2008 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.unit_tests.enabled_app; + +import android.app.Service; +import android.os.IBinder; +import android.content.Intent; + +/** + * Empty Service for testing + */ + +public class EnabledService extends Service { + + public IBinder onBind(Intent intent) { + return null; + } +} diff --git a/tests/AndroidTests/MODULE_LICENSE_APACHE2 b/tests/AndroidTests/MODULE_LICENSE_APACHE2 new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/tests/AndroidTests/MODULE_LICENSE_APACHE2 diff --git a/tests/AndroidTests/NOTICE b/tests/AndroidTests/NOTICE new file mode 100644 index 0000000..c5b1efa --- /dev/null +++ b/tests/AndroidTests/NOTICE @@ -0,0 +1,190 @@ + + Copyright (c) 2005-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. + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + diff --git a/tests/AndroidTests/assets/text.txt b/tests/AndroidTests/assets/text.txt new file mode 100644 index 0000000..3d8c519 --- /dev/null +++ b/tests/AndroidTests/assets/text.txt @@ -0,0 +1 @@ +OneTwoThreeFourFiveSixSevenEightNineTen
\ No newline at end of file diff --git a/tests/AndroidTests/res/drawable/test128x96.png b/tests/AndroidTests/res/drawable/test128x96.png Binary files differnew file mode 100644 index 0000000..28dc925 --- /dev/null +++ b/tests/AndroidTests/res/drawable/test128x96.png diff --git a/tests/AndroidTests/res/drawable/test16x12.png b/tests/AndroidTests/res/drawable/test16x12.png Binary files differnew file mode 100644 index 0000000..1a3c7e5 --- /dev/null +++ b/tests/AndroidTests/res/drawable/test16x12.png diff --git a/tests/AndroidTests/res/drawable/test256x192.png b/tests/AndroidTests/res/drawable/test256x192.png Binary files differnew file mode 100644 index 0000000..ce8ee04 --- /dev/null +++ b/tests/AndroidTests/res/drawable/test256x192.png diff --git a/tests/AndroidTests/res/drawable/test320x240.png b/tests/AndroidTests/res/drawable/test320x240.png Binary files differnew file mode 100644 index 0000000..9b5800d --- /dev/null +++ b/tests/AndroidTests/res/drawable/test320x240.png diff --git a/tests/AndroidTests/res/drawable/test32x24.png b/tests/AndroidTests/res/drawable/test32x24.png Binary files differnew file mode 100644 index 0000000..76bab75 --- /dev/null +++ b/tests/AndroidTests/res/drawable/test32x24.png diff --git a/tests/AndroidTests/res/drawable/test64x48.png b/tests/AndroidTests/res/drawable/test64x48.png Binary files differnew file mode 100644 index 0000000..9119613 --- /dev/null +++ b/tests/AndroidTests/res/drawable/test64x48.png diff --git a/tests/AndroidTests/res/layout/layout_five.xml b/tests/AndroidTests/res/layout/layout_five.xml new file mode 100644 index 0000000..fd1e0ef --- /dev/null +++ b/tests/AndroidTests/res/layout/layout_five.xml @@ -0,0 +1,22 @@ +<?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. +*/ +--> +<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/content" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent"> + <TextView android:id="@+id/text" android:text="@string/layout_five_text_text" android:layout_width="fill_parent" android:layout_height="wrap_content" /> +</LinearLayout> diff --git a/tests/AndroidTests/res/layout/layout_four.xml b/tests/AndroidTests/res/layout/layout_four.xml new file mode 100644 index 0000000..e5a78bc --- /dev/null +++ b/tests/AndroidTests/res/layout/layout_four.xml @@ -0,0 +1,20 @@ +<?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. +*/ +--> +<TextView xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/text" android:text="@string/layout_four_text_text"/> diff --git a/tests/AndroidTests/res/layout/layout_one.xml b/tests/AndroidTests/res/layout/layout_one.xml new file mode 100644 index 0000000..f5c78bd --- /dev/null +++ b/tests/AndroidTests/res/layout/layout_one.xml @@ -0,0 +1,20 @@ +<?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. +*/ +--> +<view xmlns:android="http://schemas.android.com/apk/res/android" class="com.android.unit_tests.InflateTest$ViewOne" android:id="@+id/viewOne" android:layout_width="fill_parent" android:layout_height="fill_parent"/> diff --git a/tests/AndroidTests/res/layout/layout_six.xml b/tests/AndroidTests/res/layout/layout_six.xml new file mode 100644 index 0000000..6efcdf3 --- /dev/null +++ b/tests/AndroidTests/res/layout/layout_six.xml @@ -0,0 +1,27 @@ +<?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. +*/ +--> +<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/content" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent"> + <TextView android:id="@+id/text" android:text="@string/layout_six_text_text" android:layout_width="fill_parent" android:layout_height="wrap_content" /> + <TextView android:id="@+id/text" android:text="@string/layout_six_text_text" android:layout_width="fill_parent" android:layout_height="wrap_content" /> + <TextView android:id="@+id/text" android:text="@string/layout_six_text_text" android:layout_width="fill_parent" android:layout_height="wrap_content" /> + <TextView android:id="@+id/text" android:text="@string/layout_six_text_text" android:layout_width="fill_parent" android:layout_height="wrap_content" /> + <TextView android:id="@+id/text" android:text="@string/layout_six_text_text" android:layout_width="fill_parent" android:layout_height="wrap_content" /> + <TextView android:id="@+id/text" android:text="@string/layout_six_text_text" android:layout_width="fill_parent" android:layout_height="wrap_content" /> +</LinearLayout> diff --git a/tests/AndroidTests/res/layout/layout_tag.xml b/tests/AndroidTests/res/layout/layout_tag.xml new file mode 100644 index 0000000..1f17701 --- /dev/null +++ b/tests/AndroidTests/res/layout/layout_tag.xml @@ -0,0 +1,23 @@ +<?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. +*/ +--> +<view xmlns:android="http://schemas.android.com/apk/res/android" + class="com.android.unit_tests.InflateTest$ViewOne" + android:id="@+id/viewOne" android:tag="MyTag" + android:layout_width="fill_parent" android:layout_height="fill_parent"/> diff --git a/tests/AndroidTests/res/layout/layout_three.xml b/tests/AndroidTests/res/layout/layout_three.xml new file mode 100644 index 0000000..77b2aa9 --- /dev/null +++ b/tests/AndroidTests/res/layout/layout_three.xml @@ -0,0 +1,27 @@ +<?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. +*/ +--> +<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/content" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent"> + <view class="com.android.unit_tests.InflateTest$ViewOne" android:id="@+id/view1" android:layout_width="fill_parent" android:layout_height="fill_parent"/> + <view class="com.android.unit_tests.InflateTest$ViewOne" android:id="@+id/view2" android:layout_width="fill_parent" android:layout_height="fill_parent"/> + <view class="com.android.unit_tests.InflateTest$ViewOne" android:id="@+id/view3" android:layout_width="fill_parent" android:layout_height="fill_parent"/> + <view class="com.android.unit_tests.InflateTest$ViewOne" android:id="@+id/view4" android:layout_width="fill_parent" android:layout_height="fill_parent"/> + <view class="com.android.unit_tests.InflateTest$ViewOne" android:id="@+id/view5" android:layout_width="fill_parent" android:layout_height="fill_parent"/> + <view class="com.android.unit_tests.InflateTest$ViewOne" android:id="@+id/view6" android:layout_width="fill_parent" android:layout_height="fill_parent"/> +</LinearLayout> diff --git a/tests/AndroidTests/res/layout/layout_two.xml b/tests/AndroidTests/res/layout/layout_two.xml new file mode 100644 index 0000000..9c99710 --- /dev/null +++ b/tests/AndroidTests/res/layout/layout_two.xml @@ -0,0 +1,23 @@ +<?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. +*/ +--> +<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/content" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent"> + <view class="com.android.unit_tests.InflateTest$ViewOne" android:id="@+id/viewOne" android:layout_width="fill_parent" android:layout_height="fill_parent"/> +</LinearLayout> + diff --git a/tests/AndroidTests/res/raw/calendarjs.txt b/tests/AndroidTests/res/raw/calendarjs.txt new file mode 100644 index 0000000..15f7bab --- /dev/null +++ b/tests/AndroidTests/res/raw/calendarjs.txt @@ -0,0 +1 @@ +{"version":"1.0","encoding":"UTF-8","feed":{"xmlns":"http://www.w3.org/2005/Atom","xmlns$openSearch":"http://a9.com/-/spec/opensearchrss/1.0/","xmlns$gd":"http://schemas.google.com/g/2005","xmlns$gCal":"http://schemas.google.com/gCal/2005","id":{"$t":"http://www.google.com/calendar/feeds/wg%40voiceme.net/public/basic"},"updated":{"$t":"2007-02-06T02:55:15.000Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/g/2005#event"}],"title":{"type":"text","$t":"w g"},"subtitle":{"type":"text","$t":"w g"},"link":[{"rel":"http://schemas.google.com/g/2005#feed","type":"application/atom+xml","href":"http://www.google.com/calendar/feeds/wg%40voiceme.net/public/basic"},{"rel":"self","type":"application/atom+xml","href":"http://www.google.com/calendar/feeds/wg%40voiceme.net/public/basic?alt\u003Djson\u0026max-results\u003D25"}],"author":[{"name":{"$t":"w g"},"email":{"$t":"wg@voiceme.net"}}],"generator":{"version":"1.0","uri":"http://www.google.com/calendar","$t":"Google Calendar"},"openSearch$totalResults":{"$t":"13"},"openSearch$startIndex":{"$t":"1"},"openSearch$itemsPerPage":{"$t":"25"},"gCal$timezone":{"value":"America/Los_Angeles"},"entry":[{"id":{"$t":"http://www.google.com/calendar/feeds/wg%40voiceme.net/public/basic/7iqc1ro0ihc69vhsiq3uabooig"},"published":{"$t":"2007-02-05T22:04:50.000Z"},"updated":{"$t":"2007-02-05T22:04:50.000Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/g/2005#event"}],"title":{"type":"text","$t":"skate"},"summary":{"type":"html","$t":"When: Wed Feb 7, 2007 13:30 to Wed Feb 7, 2007 16:00\u0026nbsp; PST\u003Cbr\u003E \u003Cbr\u003EEvent Status: confirmed"},"content":{"type":"text","$t":"When: Wed Feb 7, 2007 13:30 to Wed Feb 7, 2007 16:00\u0026nbsp; PST\u003Cbr\u003E \u003Cbr\u003EEvent Status: confirmed"},"link":[{"rel":"alternate","type":"text/html","href":"http://www.google.com/calendar/event?eid\u003DN2lxYzFybzBpaGM2OXZoc2lxM3VhYm9vaWcgd2dAdm9pY2VtZS5uZXQ","title":"alternate"},{"rel":"self","type":"application/atom+xml","href":"http://www.google.com/calendar/feeds/wg%40voiceme.net/public/basic/7iqc1ro0ihc69vhsiq3uabooig"}],"author":[{"name":{"$t":"w g"},"email":{"$t":"wg@voiceme.net"}}],"gCal$sendEventNotifications":{"value":"false"}},{"id":{"$t":"http://www.google.com/calendar/feeds/wg%40voiceme.net/public/basic/kp4gil76n2vcrkt9kaotj3s12c"},"published":{"$t":"2007-02-05T22:04:42.000Z"},"updated":{"$t":"2007-02-05T22:04:42.000Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/g/2005#event"}],"title":{"type":"text","$t":"skate"},"summary":{"type":"html","$t":"When: Fri Feb 9, 2007 15:30 to Fri Feb 9, 2007 18:00\u0026nbsp; PST\u003Cbr\u003E \u003Cbr\u003EEvent Status: confirmed"},"content":{"type":"text","$t":"When: Fri Feb 9, 2007 15:30 to Fri Feb 9, 2007 18:00\u0026nbsp; PST\u003Cbr\u003E \u003Cbr\u003EEvent Status: confirmed"},"link":[{"rel":"alternate","type":"text/html","href":"http://www.google.com/calendar/event?eid\u003Da3A0Z2lsNzZuMnZjcmt0OWthb3RqM3MxMmMgd2dAdm9pY2VtZS5uZXQ","title":"alternate"},{"rel":"self","type":"application/atom+xml","href":"http://www.google.com/calendar/feeds/wg%40voiceme.net/public/basic/kp4gil76n2vcrkt9kaotj3s12c"}],"author":[{"name":{"$t":"w g"},"email":{"$t":"wg@voiceme.net"}}],"gCal$sendEventNotifications":{"value":"false"}},{"id":{"$t":"http://www.google.com/calendar/feeds/wg%40voiceme.net/public/basic/gkhb48fj68lcp15fd1k03tjbj0"},"published":{"$t":"2007-02-05T22:04:35.000Z"},"updated":{"$t":"2007-02-05T22:04:35.000Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/g/2005#event"}],"title":{"type":"text","$t":"test event 6"},"summary":{"type":"html","$t":"When: Sat Feb 10, 2007 14:00 to Sat Feb 10, 2007 17:00\u0026nbsp; PST\u003Cbr\u003E \u003Cbr\u003EEvent Status: confirmed"},"content":{"type":"text","$t":"When: Sat Feb 10, 2007 14:00 to Sat Feb 10, 2007 17:00\u0026nbsp; PST\u003Cbr\u003E \u003Cbr\u003EEvent Status: confirmed"},"link":[{"rel":"alternate","type":"text/html","href":"http://www.google.com/calendar/event?eid\u003DZ2toYjQ4Zmo2OGxjcDE1ZmQxazAzdGpiajAgd2dAdm9pY2VtZS5uZXQ","title":"alternate"},{"rel":"self","type":"application/atom+xml","href":"http://www.google.com/calendar/feeds/wg%40voiceme.net/public/basic/gkhb48fj68lcp15fd1k03tjbj0"}],"author":[{"name":{"$t":"w g"},"email":{"$t":"wg@voiceme.net"}}],"gCal$sendEventNotifications":{"value":"false"}},{"id":{"$t":"http://www.google.com/calendar/feeds/wg%40voiceme.net/public/basic/32p5g68cpean3p2ol7kanj38sg"},"published":{"$t":"2007-02-05T22:04:29.000Z"},"updated":{"$t":"2007-02-05T22:04:29.000Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/g/2005#event"}],"title":{"type":"text","$t":"test event 5"},"summary":{"type":"html","$t":"When: Fri Feb 9, 2007 09:00 to 10:30\u0026nbsp; PST\u003Cbr\u003E \u003Cbr\u003EEvent Status: confirmed"},"content":{"type":"text","$t":"When: Fri Feb 9, 2007 09:00 to 10:30\u0026nbsp; PST\u003Cbr\u003E \u003Cbr\u003EEvent Status: confirmed"},"link":[{"rel":"alternate","type":"text/html","href":"http://www.google.com/calendar/event?eid\u003DMzJwNWc2OGNwZWFuM3Ayb2w3a2FuajM4c2cgd2dAdm9pY2VtZS5uZXQ","title":"alternate"},{"rel":"self","type":"application/atom+xml","href":"http://www.google.com/calendar/feeds/wg%40voiceme.net/public/basic/32p5g68cpean3p2ol7kanj38sg"}],"author":[{"name":{"$t":"w g"},"email":{"$t":"wg@voiceme.net"}}],"gCal$sendEventNotifications":{"value":"false"}},{"id":{"$t":"http://www.google.com/calendar/feeds/wg%40voiceme.net/public/basic/tfqpth26conshdmav0apje1tf4"},"published":{"$t":"2007-02-05T22:04:19.000Z"},"updated":{"$t":"2007-02-05T22:04:19.000Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/g/2005#event"}],"title":{"type":"text","$t":"skate"},"summary":{"type":"html","$t":"When: Thu Feb 8, 2007 15:00 to Thu Feb 8, 2007 17:00\u0026nbsp; PST\u003Cbr\u003E \u003Cbr\u003EEvent Status: confirmed"},"content":{"type":"text","$t":"When: Thu Feb 8, 2007 15:00 to Thu Feb 8, 2007 17:00\u0026nbsp; PST\u003Cbr\u003E \u003Cbr\u003EEvent Status: confirmed"},"link":[{"rel":"alternate","type":"text/html","href":"http://www.google.com/calendar/event?eid\u003DdGZxcHRoMjZjb25zaGRtYXYwYXBqZTF0ZjQgd2dAdm9pY2VtZS5uZXQ","title":"alternate"},{"rel":"self","type":"application/atom+xml","href":"http://www.google.com/calendar/feeds/wg%40voiceme.net/public/basic/tfqpth26conshdmav0apje1tf4"}],"author":[{"name":{"$t":"w g"},"email":{"$t":"wg@voiceme.net"}}],"gCal$sendEventNotifications":{"value":"false"}},{"id":{"$t":"http://www.google.com/calendar/feeds/wg%40voiceme.net/public/basic/onbo9mhbr5m6mo356nog7uel4s"},"published":{"$t":"2007-02-05T22:04:07.000Z"},"updated":{"$t":"2007-02-05T22:04:07.000Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/g/2005#event"}],"title":{"type":"text","$t":"Sharks at Anaheim"},"summary":{"type":"html","$t":"When: Wed Feb 7, 2007 19:00 to 22:00\u0026nbsp; PST\u003Cbr\u003E \u003Cbr\u003EEvent Status: confirmed"},"content":{"type":"text","$t":"When: Wed Feb 7, 2007 19:00 to 22:00\u0026nbsp; PST\u003Cbr\u003E \u003Cbr\u003EEvent Status: confirmed"},"link":[{"rel":"alternate","type":"text/html","href":"http://www.google.com/calendar/event?eid\u003Db25ibzltaGJyNW02bW8zNTZub2c3dWVsNHMgd2dAdm9pY2VtZS5uZXQ","title":"alternate"},{"rel":"self","type":"application/atom+xml","href":"http://www.google.com/calendar/feeds/wg%40voiceme.net/public/basic/onbo9mhbr5m6mo356nog7uel4s"}],"author":[{"name":{"$t":"w g"},"email":{"$t":"wg@voiceme.net"}}],"gCal$sendEventNotifications":{"value":"true"}},{"id":{"$t":"http://www.google.com/calendar/feeds/wg%40voiceme.net/public/basic/tjqrd9fve576hieh3sa67nql5k"},"published":{"$t":"2007-02-05T22:04:02.000Z"},"updated":{"$t":"2007-02-05T22:04:02.000Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/g/2005#event"}],"title":{"type":"text","$t":"Sharks vs. ANAHEIM"},"summary":{"type":"html","$t":"When: Tue Feb 6, 2007 19:30 to 22:30\u0026nbsp; PST\u003Cbr\u003E \u003Cbr\u003EEvent Status: confirmed"},"content":{"type":"text","$t":"When: Tue Feb 6, 2007 19:30 to 22:30\u0026nbsp; PST\u003Cbr\u003E \u003Cbr\u003EEvent Status: confirmed"},"link":[{"rel":"alternate","type":"text/html","href":"http://www.google.com/calendar/event?eid\u003DdGpxcmQ5ZnZlNTc2aGllaDNzYTY3bnFsNWsgd2dAdm9pY2VtZS5uZXQ","title":"alternate"},{"rel":"self","type":"application/atom+xml","href":"http://www.google.com/calendar/feeds/wg%40voiceme.net/public/basic/tjqrd9fve576hieh3sa67nql5k"}],"author":[{"name":{"$t":"w g"},"email":{"$t":"wg@voiceme.net"}}],"gCal$sendEventNotifications":{"value":"true"}},{"id":{"$t":"http://www.google.com/calendar/feeds/wg%40voiceme.net/public/basic/or6dtpn065f9mntond4jh2docc"},"published":{"$t":"2007-02-05T22:03:52.000Z"},"updated":{"$t":"2007-02-05T22:03:52.000Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/g/2005#event"}],"title":{"type":"text","$t":"skate"},"summary":{"type":"html","$t":"When: Tue Feb 6, 2007 14:00 to 15:00\u0026nbsp; PST\u003Cbr\u003E \u003Cbr\u003EEvent Status: confirmed"},"content":{"type":"text","$t":"When: Tue Feb 6, 2007 14:00 to 15:00\u0026nbsp; PST\u003Cbr\u003E \u003Cbr\u003EEvent Status: confirmed"},"link":[{"rel":"alternate","type":"text/html","href":"http://www.google.com/calendar/event?eid\u003Db3I2ZHRwbjA2NWY5bW50b25kNGpoMmRvY2Mgd2dAdm9pY2VtZS5uZXQ","title":"alternate"},{"rel":"self","type":"application/atom+xml","href":"http://www.google.com/calendar/feeds/wg%40voiceme.net/public/basic/or6dtpn065f9mntond4jh2docc"}],"author":[{"name":{"$t":"w g"},"email":{"$t":"wg@voiceme.net"}}],"gCal$sendEventNotifications":{"value":"false"}},{"id":{"$t":"http://www.google.com/calendar/feeds/wg%40voiceme.net/public/basic/k70v8o4jt1afi17hg2spavq1c0"},"published":{"$t":"2007-02-05T22:03:36.000Z"},"updated":{"$t":"2007-02-05T22:03:36.000Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/g/2005#event"}],"title":{"type":"text","$t":"lunch"},"summary":{"type":"html","$t":"Recurring Event\u003Cbr\u003E First start: 2007-02-06 12:00:00 PST \u003Cbr\u003E Duration: 3600 \u003Cbr\u003EEvent Status: confirmed"},"content":{"type":"text","$t":"Recurring Event\u003Cbr\u003E First start: 2007-02-06 12:00:00 PST \u003Cbr\u003E Duration: 3600 \u003Cbr\u003EEvent Status: confirmed"},"link":[{"rel":"alternate","type":"text/html","href":"http://www.google.com/calendar/event?eid\u003DazcwdjhvNGp0MWFmaTE3aGcyc3BhdnExYzBfMjAwNzAyMDZUMjAwMDAwWiB3Z0B2b2ljZW1lLm5ldA","title":"alternate"},{"rel":"self","type":"application/atom+xml","href":"http://www.google.com/calendar/feeds/wg%40voiceme.net/public/basic/k70v8o4jt1afi17hg2spavq1c0"}],"author":[{"name":{"$t":"w g"},"email":{"$t":"wg@voiceme.net"}}],"gCal$sendEventNotifications":{"value":"true"}},{"id":{"$t":"http://www.google.com/calendar/feeds/wg%40voiceme.net/public/basic/6ee7b8nohdt03tv0gknm4v7124"},"published":{"$t":"2007-02-05T22:03:19.000Z"},"updated":{"$t":"2007-02-05T22:03:19.000Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/g/2005#event"}],"title":{"type":"text","$t":"test event 4"},"summary":{"type":"html","$t":"When: Tue Feb 6, 2007 09:00 to 11:00\u0026nbsp; PST\u003Cbr\u003E \u003Cbr\u003EEvent Status: confirmed"},"content":{"type":"text","$t":"When: Tue Feb 6, 2007 09:00 to 11:00\u0026nbsp; PST\u003Cbr\u003E \u003Cbr\u003EEvent Status: confirmed"},"link":[{"rel":"alternate","type":"text/html","href":"http://www.google.com/calendar/event?eid\u003DNmVlN2I4bm9oZHQwM3R2MGdrbm00djcxMjQgd2dAdm9pY2VtZS5uZXQ","title":"alternate"},{"rel":"self","type":"application/atom+xml","href":"http://www.google.com/calendar/feeds/wg%40voiceme.net/public/basic/6ee7b8nohdt03tv0gknm4v7124"}],"author":[{"name":{"$t":"w g"},"email":{"$t":"wg@voiceme.net"}}],"gCal$sendEventNotifications":{"value":"false"}},{"id":{"$t":"http://www.google.com/calendar/feeds/wg%40voiceme.net/public/basic/of1vh1r2q5aqdplo65i8bqbn3o"},"published":{"$t":"2007-02-05T22:03:11.000Z"},"updated":{"$t":"2007-02-05T22:03:11.000Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/g/2005#event"}],"title":{"type":"text","$t":"test event 3"},"summary":{"type":"html","$t":"When: Mon Feb 5, 2007 18:00 to 19:00\u0026nbsp; PST\u003Cbr\u003E \u003Cbr\u003EEvent Status: confirmed"},"content":{"type":"text","$t":"When: Mon Feb 5, 2007 18:00 to 19:00\u0026nbsp; PST\u003Cbr\u003E \u003Cbr\u003EEvent Status: confirmed"},"link":[{"rel":"alternate","type":"text/html","href":"http://www.google.com/calendar/event?eid\u003Db2YxdmgxcjJxNWFxZHBsbzY1aThicWJuM28gd2dAdm9pY2VtZS5uZXQ","title":"alternate"},{"rel":"self","type":"application/atom+xml","href":"http://www.google.com/calendar/feeds/wg%40voiceme.net/public/basic/of1vh1r2q5aqdplo65i8bqbn3o"}],"author":[{"name":{"$t":"w g"},"email":{"$t":"wg@voiceme.net"}}],"gCal$sendEventNotifications":{"value":"false"}},{"id":{"$t":"http://www.google.com/calendar/feeds/wg%40voiceme.net/public/basic/s7ahgfomlgii9qbkgpfbinr9u8"},"published":{"$t":"2007-02-05T22:02:40.000Z"},"updated":{"$t":"2007-02-05T22:03:04.000Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/g/2005#event"}],"title":{"type":"text","$t":"test event 2"},"summary":{"type":"html","$t":"When: Mon Feb 5, 2007 16:30 to 17:30\u0026nbsp; PST\u003Cbr\u003E \u003Cbr\u003EEvent Status: confirmed"},"content":{"type":"text","$t":"When: Mon Feb 5, 2007 16:30 to 17:30\u0026nbsp; PST\u003Cbr\u003E \u003Cbr\u003EEvent Status: confirmed"},"link":[{"rel":"alternate","type":"text/html","href":"http://www.google.com/calendar/event?eid\u003DczdhaGdmb21sZ2lpOXFia2dwZmJpbnI5dTggd2dAdm9pY2VtZS5uZXQ","title":"alternate"},{"rel":"self","type":"application/atom+xml","href":"http://www.google.com/calendar/feeds/wg%40voiceme.net/public/basic/s7ahgfomlgii9qbkgpfbinr9u8"}],"author":[{"name":{"$t":"w g"},"email":{"$t":"wg@voiceme.net"}}],"gCal$sendEventNotifications":{"value":"false"}},{"id":{"$t":"http://www.google.com/calendar/feeds/wg%40voiceme.net/public/basic/rl8focglfe6jndql4u8lg73q5k"},"published":{"$t":"2007-02-05T22:02:28.000Z"},"updated":{"$t":"2007-02-05T22:02:53.000Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/g/2005#event"}],"title":{"type":"text","$t":"test event 1"},"summary":{"type":"html","$t":"When: Mon Feb 5, 2007 15:00 to Mon Feb 5, 2007 16:00\u0026nbsp; PST\u003Cbr\u003E \u003Cbr\u003EEvent Status: confirmed"},"content":{"type":"text","$t":"When: Mon Feb 5, 2007 15:00 to Mon Feb 5, 2007 16:00\u0026nbsp; PST\u003Cbr\u003E \u003Cbr\u003EEvent Status: confirmed"},"link":[{"rel":"alternate","type":"text/html","href":"http://www.google.com/calendar/event?eid\u003Dcmw4Zm9jZ2xmZTZqbmRxbDR1OGxnNzNxNWsgd2dAdm9pY2VtZS5uZXQ","title":"alternate"},{"rel":"self","type":"application/atom+xml","href":"http://www.google.com/calendar/feeds/wg%40voiceme.net/public/basic/rl8focglfe6jndql4u8lg73q5k"}],"author":[{"name":{"$t":"w g"},"email":{"$t":"wg@voiceme.net"}}],"gCal$sendEventNotifications":{"value":"false"}}]}}
\ No newline at end of file diff --git a/tests/AndroidTests/res/raw/calendarjsgz.jsgz b/tests/AndroidTests/res/raw/calendarjsgz.jsgz Binary files differnew file mode 100644 index 0000000..6f1bf54 --- /dev/null +++ b/tests/AndroidTests/res/raw/calendarjsgz.jsgz diff --git a/tests/AndroidTests/res/raw/calendarxml.xml b/tests/AndroidTests/res/raw/calendarxml.xml new file mode 100644 index 0000000..1adcd74 --- /dev/null +++ b/tests/AndroidTests/res/raw/calendarxml.xml @@ -0,0 +1,38 @@ +<?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. +--> + +<feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:gd='http://schemas.google.com/g/2005' xmlns:gCal='http://schemas.google.com/gCal/2005'><id>http://www.google.com/calendar/feeds/default/private/full</id><updated>2007-02-05T22:04:50.000Z</updated><category scheme='http://schemas.google.com/g/2005#kind' term='http://schemas.google.com/g/2005#event'></category><title type='text'>w g</title><subtitle type='text'>w g</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://www.google.com/calendar/feeds/default/private/full'></link><link rel='http://schemas.google.com/g/2005#post' type='application/atom+xml' href='http://www.google.com/calendar/feeds/default/private/full'></link><link rel='self' type='application/atom+xml' href='http://www.google.com/calendar/feeds/default/private/full?max-results=25'></link><author><name>w g</name><email>wg@voiceme.net</email></author><generator version='1.0' uri='http://www.google.com/calendar'>Google Calendar</generator><openSearch:totalResults>13</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><gCal:timezone value='America/Los_Angeles'></gCal:timezone><entry><id>http://www.google.com/calendar/feeds/default/private/full/7iqc1ro0ihc69vhsiq3uabooig</id><published>2007-02-05T22:04:50.000Z</published><updated>2007-02-05T22:04:50.000Z</updated><category scheme='http://schemas.google.com/g/2005#kind' term='http://schemas.google.com/g/2005#event'></category><title type='text'>skate</title><content type='text'></content><link rel='alternate' type='text/html' href='http://www.google.com/calendar/hosted/voiceme.net/event?eid=N2lxYzFybzBpaGM2OXZoc2lxM3VhYm9vaWcgd2dAdm9pY2VtZS5uZXQ' title='alternate'></link><link rel='self' type='application/atom+xml' href='http://www.google.com/calendar/feeds/default/private/full/7iqc1ro0ihc69vhsiq3uabooig'></link><link rel='edit' type='application/atom+xml' href='http://www.google.com/calendar/feeds/default/private/full/7iqc1ro0ihc69vhsiq3uabooig/63306396290'></link><author><name>w g</name><email>wg@voiceme.net</email></author><gd:comments><gd:feedLink href='http://www.google.com/calendar/feeds/default/private/full/7iqc1ro0ihc69vhsiq3uabooig/comments'></gd:feedLink></gd:comments><gd:eventStatus value='http://schemas.google.com/g/2005#event.confirmed'></gd:eventStatus><gd:visibility value='http://schemas.google.com/g/2005#event.default'></gd:visibility><gCal:sendEventNotifications value='false'></gCal:sendEventNotifications><gd:transparency value='http://schemas.google.com/g/2005#event.opaque'></gd:transparency><gd:where></gd:where><gd:when startTime='2007-02-07T13:30:00.000-08:00' endTime='2007-02-07T16:00:00.000-08:00'><gd:reminder minutes='10'></gd:reminder></gd:when></entry><entry><id>http://www.google.com/calendar/feeds/default/private/full/kp4gil76n2vcrkt9kaotj3s12c</id><published>2007-02-05T22:04:42.000Z</published><updated>2007-02-05T22:04:42.000Z</updated><category scheme='http://schemas.google.com/g/2005#kind' term='http://schemas.google.com/g/2005#event'></category><title type='text'>skate</title><content type='text'></content><link rel='alternate' type='text/html' href='http://www.google.com/calendar/hosted/voiceme.net/event?eid=a3A0Z2lsNzZuMnZjcmt0OWthb3RqM3MxMmMgd2dAdm9pY2VtZS5uZXQ' title='alternate'></link><link rel='self' type='application/atom+xml' href='http://www.google.com/calendar/feeds/default/private/full/kp4gil76n2vcrkt9kaotj3s12c'></link><link rel='edit' type='application/atom+xml' href='http://www.google.com/calendar/feeds/default/private/full/kp4gil76n2vcrkt9kaotj3s12c/63306396282'></link><author><name>w g</name><email>wg@voiceme.net</email></author><gd:comments><gd:feedLink href='http://www.google.com/calendar/feeds/default/private/full/kp4gil76n2vcrkt9kaotj3s12c/comments'></gd:feedLink></gd:comments><gd:eventStatus value='http://schemas.google.com/g/2005#event.confirmed'></gd:eventStatus><gd:visibility value='http://schemas.google.com/g/2005#event.default'></gd:visibility><gCal:sendEventNotifications value='false'></gCal:sendEventNotifications><gd:transparency value='http://schemas.google.com/g/2005#event.opaque'></gd:transparency><gd:where></gd:where><gd:when startTime='2007-02-09T15:30:00.000-08:00' endTime='2007-02-09T18:00:00.000-08:00'><gd:reminder minutes='10'></gd:reminder></gd:when></entry><entry><id>http://www.google.com/calendar/feeds/default/private/full/gkhb48fj68lcp15fd1k03tjbj0</id><published>2007-02-05T22:04:35.000Z</published><updated>2007-02-05T22:04:35.000Z</updated><category scheme='http://schemas.google.com/g/2005#kind' term='http://schemas.google.com/g/2005#event'></category><title type='text'>test event 6</title><content type='text'></content><link rel='alternate' type='text/html' href='http://www.google.com/calendar/hosted/voiceme.net/event?eid=Z2toYjQ4Zmo2OGxjcDE1ZmQxazAzdGpiajAgd2dAdm9pY2VtZS5uZXQ' title='alternate'></link><link rel='self' type='application/atom+xml' href='http://www.google.com/calendar/feeds/default/private/full/gkhb48fj68lcp15fd1k03tjbj0'></link><link rel='edit' type='application/atom+xml' href='http://www.google.com/calendar/feeds/default/private/full/gkhb48fj68lcp15fd1k03tjbj0/63306396275'></link><author><name>w g</name><email>wg@voiceme.net</email></author><gd:comments><gd:feedLink href='http://www.google.com/calendar/feeds/default/private/full/gkhb48fj68lcp15fd1k03tjbj0/comments'></gd:feedLink></gd:comments><gd:eventStatus value='http://schemas.google.com/g/2005#event.confirmed'></gd:eventStatus><gd:visibility value='http://schemas.google.com/g/2005#event.default'></gd:visibility><gCal:sendEventNotifications value='false'></gCal:sendEventNotifications><gd:transparency value='http://schemas.google.com/g/2005#event.opaque'></gd:transparency><gd:where></gd:where><gd:when startTime='2007-02-10T14:00:00.000-08:00' endTime='2007-02-10T17:00:00.000-08:00'><gd:reminder minutes='10'></gd:reminder></gd:when></entry><entry><id>http://www.google.com/calendar/feeds/default/private/full/32p5g68cpean3p2ol7kanj38sg</id><published>2007-02-05T22:04:29.000Z</published><updated>2007-02-05T22:04:29.000Z</updated><category scheme='http://schemas.google.com/g/2005#kind' term='http://schemas.google.com/g/2005#event'></category><title type='text'>test event 5</title><content type='text'></content><link rel='alternate' type='text/html' href='http://www.google.com/calendar/hosted/voiceme.net/event?eid=MzJwNWc2OGNwZWFuM3Ayb2w3a2FuajM4c2cgd2dAdm9pY2VtZS5uZXQ' title='alternate'></link><link rel='self' type='application/atom+xml' href='http://www.google.com/calendar/feeds/default/private/full/32p5g68cpean3p2ol7kanj38sg'></link><link rel='edit' type='application/atom+xml' href='http://www.google.com/calendar/feeds/default/private/full/32p5g68cpean3p2ol7kanj38sg/63306396269'></link><author><name>w g</name><email>wg@voiceme.net</email></author><gd:comments><gd:feedLink href='http://www.google.com/calendar/feeds/default/private/full/32p5g68cpean3p2ol7kanj38sg/comments'></gd:feedLink></gd:comments><gd:eventStatus value='http://schemas.google.com/g/2005#event.confirmed'></gd:eventStatus><gd:visibility value='http://schemas.google.com/g/2005#event.default'></gd:visibility><gCal:sendEventNotifications value='false'></gCal:sendEventNotifications><gd:transparency value='http://schemas.google.com/g/2005#event.opaque'></gd:transparency><gd:where></gd:where><gd:when startTime='2007-02-09T09:00:00.000-08:00' endTime='2007-02-09T10:30:00.000-08:00'><gd:reminder minutes='10'></gd:reminder></gd:when></entry><entry><id>http://www.google.com/calendar/feeds/default/private/full/tfqpth26conshdmav0apje1tf4</id><published>2007-02-05T22:04:19.000Z</published><updated>2007-02-05T22:04:19.000Z</updated><category scheme='http://schemas.google.com/g/2005#kind' term='http://schemas.google.com/g/2005#event'></category><title type='text'>skate</title><content type='text'></content><link rel='alternate' type='text/html' href='http://www.google.com/calendar/hosted/voiceme.net/event?eid=dGZxcHRoMjZjb25zaGRtYXYwYXBqZTF0ZjQgd2dAdm9pY2VtZS5uZXQ' title='alternate'></link><link rel='self' type='application/atom+xml' href='http://www.google.com/calendar/feeds/default/private/full/tfqpth26conshdmav0apje1tf4'></link><link rel='edit' type='application/atom+xml' href='http://www.google.com/calendar/feeds/default/private/full/tfqpth26conshdmav0apje1tf4/63306396259'></link><author><name>w g</name><email>wg@voiceme.net</email></author><gd:comments><gd:feedLink href='http://www.google.com/calendar/feeds/default/private/full/tfqpth26conshdmav0apje1tf4/comments'></gd:feedLink></gd:comments><gd:eventStatus value='http://schemas.google.com/g/2005#event.confirmed'></gd:eventStatus><gd:visibility value='http://schemas.google.com/g/2005#event.default'></gd:visibility><gCal:sendEventNotifications value='false'></gCal:sendEventNotifications><gd:transparency value='http://schemas.google.com/g/2005#event.opaque'></gd:transparency><gd:where></gd:where><gd:when startTime='2007-02-08T15:00:00.000-08:00' endTime='2007-02-08T17:00:00.000-08:00'><gd:reminder minutes='10'></gd:reminder></gd:when></entry><entry><id>http://www.google.com/calendar/feeds/default/private/full/onbo9mhbr5m6mo356nog7uel4s</id><published>2007-02-05T22:04:07.000Z</published><updated>2007-02-05T22:04:07.000Z</updated><category scheme='http://schemas.google.com/g/2005#kind' term='http://schemas.google.com/g/2005#event'></category><title type='text'>Sharks at Anaheim</title><content type='text'></content><link rel='alternate' type='text/html' href='http://www.google.com/calendar/hosted/voiceme.net/event?eid=b25ibzltaGJyNW02bW8zNTZub2c3dWVsNHMgd2dAdm9pY2VtZS5uZXQ' title='alternate'></link><link rel='self' type='application/atom+xml' href='http://www.google.com/calendar/feeds/default/private/full/onbo9mhbr5m6mo356nog7uel4s'></link><link rel='edit' type='application/atom+xml' href='http://www.google.com/calendar/feeds/default/private/full/onbo9mhbr5m6mo356nog7uel4s/63306396247'></link><author><name>w g</name><email>wg@voiceme.net</email></author><gd:comments><gd:feedLink href='http://www.google.com/calendar/feeds/default/private/full/onbo9mhbr5m6mo356nog7uel4s/comments'></gd:feedLink></gd:comments><gd:eventStatus value='http://schemas.google.com/g/2005#event.confirmed'></gd:eventStatus><gd:visibility value='http://schemas.google.com/g/2005#event.default'></gd:visibility><gCal:sendEventNotifications value='true'></gCal:sendEventNotifications><gd:transparency value='http://schemas.google.com/g/2005#event.opaque'></gd:transparency><gd:where valueString=''></gd:where><gd:when startTime='2007-02-07T19:00:00.000-08:00' endTime='2007-02-07T22:00:00.000-08:00'><gd:reminder minutes='10'></gd:reminder></gd:when></entry><entry><id>http://www.google.com/calendar/feeds/default/private/full/tjqrd9fve576hieh3sa67nql5k</id><published>2007-02-05T22:04:02.000Z</published><updated>2007-02-05T22:04:02.000Z</updated><category scheme='http://schemas.google.com/g/2005#kind' term='http://schemas.google.com/g/2005#event'></category><title type='text'>Sharks vs. ANAHEIM</title><content type='text'></content><link rel='alternate' type='text/html' href='http://www.google.com/calendar/hosted/voiceme.net/event?eid=dGpxcmQ5ZnZlNTc2aGllaDNzYTY3bnFsNWsgd2dAdm9pY2VtZS5uZXQ' title='alternate'></link><link rel='self' type='application/atom+xml' href='http://www.google.com/calendar/feeds/default/private/full/tjqrd9fve576hieh3sa67nql5k'></link><link rel='edit' type='application/atom+xml' href='http://www.google.com/calendar/feeds/default/private/full/tjqrd9fve576hieh3sa67nql5k/63306396242'></link><author><name>w g</name><email>wg@voiceme.net</email></author><gd:comments><gd:feedLink href='http://www.google.com/calendar/feeds/default/private/full/tjqrd9fve576hieh3sa67nql5k/comments'></gd:feedLink></gd:comments><gd:eventStatus value='http://schemas.google.com/g/2005#event.confirmed'></gd:eventStatus><gd:visibility value='http://schemas.google.com/g/2005#event.default'></gd:visibility><gCal:sendEventNotifications value='true'></gCal:sendEventNotifications><gd:transparency value='http://schemas.google.com/g/2005#event.opaque'></gd:transparency><gd:where valueString=''></gd:where><gd:when startTime='2007-02-06T19:30:00.000-08:00' endTime='2007-02-06T22:30:00.000-08:00'><gd:reminder minutes='10'></gd:reminder></gd:when></entry><entry><id>http://www.google.com/calendar/feeds/default/private/full/or6dtpn065f9mntond4jh2docc</id><published>2007-02-05T22:03:52.000Z</published><updated>2007-02-05T22:03:52.000Z</updated><category scheme='http://schemas.google.com/g/2005#kind' term='http://schemas.google.com/g/2005#event'></category><title type='text'>skate</title><content type='text'></content><link rel='alternate' type='text/html' href='http://www.google.com/calendar/hosted/voiceme.net/event?eid=b3I2ZHRwbjA2NWY5bW50b25kNGpoMmRvY2Mgd2dAdm9pY2VtZS5uZXQ' title='alternate'></link><link rel='self' type='application/atom+xml' href='http://www.google.com/calendar/feeds/default/private/full/or6dtpn065f9mntond4jh2docc'></link><link rel='edit' type='application/atom+xml' href='http://www.google.com/calendar/feeds/default/private/full/or6dtpn065f9mntond4jh2docc/63306396232'></link><author><name>w g</name><email>wg@voiceme.net</email></author><gd:comments><gd:feedLink href='http://www.google.com/calendar/feeds/default/private/full/or6dtpn065f9mntond4jh2docc/comments'></gd:feedLink></gd:comments><gd:eventStatus value='http://schemas.google.com/g/2005#event.confirmed'></gd:eventStatus><gd:visibility value='http://schemas.google.com/g/2005#event.default'></gd:visibility><gCal:sendEventNotifications value='false'></gCal:sendEventNotifications><gd:transparency value='http://schemas.google.com/g/2005#event.opaque'></gd:transparency><gd:where></gd:where><gd:when startTime='2007-02-06T14:00:00.000-08:00' endTime='2007-02-06T15:00:00.000-08:00'><gd:reminder minutes='10'></gd:reminder></gd:when></entry><entry><id>http://www.google.com/calendar/feeds/default/private/full/k70v8o4jt1afi17hg2spavq1c0</id><published>2007-02-05T22:03:36.000Z</published><updated>2007-02-05T22:03:36.000Z</updated><category scheme='http://schemas.google.com/g/2005#kind' term='http://schemas.google.com/g/2005#event'></category><title type='text'>lunch</title><content type='text'></content><link rel='alternate' type='text/html' href='http://www.google.com/calendar/hosted/voiceme.net/event?eid=azcwdjhvNGp0MWFmaTE3aGcyc3BhdnExYzBfMjAwNzAyMDZUMjAwMDAwWiB3Z0B2b2ljZW1lLm5ldA' title='alternate'></link><link rel='self' type='application/atom+xml' href='http://www.google.com/calendar/feeds/default/private/full/k70v8o4jt1afi17hg2spavq1c0'></link><link rel='edit' type='application/atom+xml' href='http://www.google.com/calendar/feeds/default/private/full/k70v8o4jt1afi17hg2spavq1c0/63306396216'></link><author><name>w g</name><email>wg@voiceme.net</email></author><gd:eventStatus value='http://schemas.google.com/g/2005#event.confirmed'></gd:eventStatus><gd:visibility value='http://schemas.google.com/g/2005#event.default'></gd:visibility><gCal:sendEventNotifications value='true'></gCal:sendEventNotifications><gd:transparency value='http://schemas.google.com/g/2005#event.opaque'></gd:transparency><gd:recurrence>DTSTART;TZID=America/Los_Angeles:20070206T120000 +DURATION:PT3600S +RRULE:FREQ=DAILY;WKST=SU +BEGIN:VTIMEZONE +TZID:America/Los_Angeles +X-LIC-LOCATION:America/Los_Angeles +BEGIN:STANDARD +TZOFFSETFROM:-0700 +TZOFFSETTO:-0800 +TZNAME:PST +DTSTART:19701025T020000 +RRULE:FREQ=YEARLY;BYMONTH=10;BYDAY=-1SU +END:STANDARD +BEGIN:DAYLIGHT +TZOFFSETFROM:-0800 +TZOFFSETTO:-0700 +TZNAME:PDT +DTSTART:19700405T020000 +RRULE:FREQ=YEARLY;BYMONTH=4;BYDAY=1SU +END:DAYLIGHT +END:VTIMEZONE +</gd:recurrence><gd:where valueString=''></gd:where><gd:reminder minutes='10'></gd:reminder></entry><entry><id>http://www.google.com/calendar/feeds/default/private/full/6ee7b8nohdt03tv0gknm4v7124</id><published>2007-02-05T22:03:19.000Z</published><updated>2007-02-05T22:03:19.000Z</updated><category scheme='http://schemas.google.com/g/2005#kind' term='http://schemas.google.com/g/2005#event'></category><title type='text'>test event 4</title><content type='text'></content><link rel='alternate' type='text/html' href='http://www.google.com/calendar/hosted/voiceme.net/event?eid=NmVlN2I4bm9oZHQwM3R2MGdrbm00djcxMjQgd2dAdm9pY2VtZS5uZXQ' title='alternate'></link><link rel='self' type='application/atom+xml' href='http://www.google.com/calendar/feeds/default/private/full/6ee7b8nohdt03tv0gknm4v7124'></link><link rel='edit' type='application/atom+xml' href='http://www.google.com/calendar/feeds/default/private/full/6ee7b8nohdt03tv0gknm4v7124/63306396199'></link><author><name>w g</name><email>wg@voiceme.net</email></author><gd:comments><gd:feedLink href='http://www.google.com/calendar/feeds/default/private/full/6ee7b8nohdt03tv0gknm4v7124/comments'></gd:feedLink></gd:comments><gd:eventStatus value='http://schemas.google.com/g/2005#event.confirmed'></gd:eventStatus><gd:visibility value='http://schemas.google.com/g/2005#event.default'></gd:visibility><gCal:sendEventNotifications value='false'></gCal:sendEventNotifications><gd:transparency value='http://schemas.google.com/g/2005#event.opaque'></gd:transparency><gd:where></gd:where><gd:when startTime='2007-02-06T09:00:00.000-08:00' endTime='2007-02-06T11:00:00.000-08:00'><gd:reminder minutes='10'></gd:reminder></gd:when></entry><entry><id>http://www.google.com/calendar/feeds/default/private/full/of1vh1r2q5aqdplo65i8bqbn3o</id><published>2007-02-05T22:03:11.000Z</published><updated>2007-02-05T22:03:11.000Z</updated><category scheme='http://schemas.google.com/g/2005#kind' term='http://schemas.google.com/g/2005#event'></category><title type='text'>test event 3</title><content type='text'></content><link rel='alternate' type='text/html' href='http://www.google.com/calendar/hosted/voiceme.net/event?eid=b2YxdmgxcjJxNWFxZHBsbzY1aThicWJuM28gd2dAdm9pY2VtZS5uZXQ' title='alternate'></link><link rel='self' type='application/atom+xml' href='http://www.google.com/calendar/feeds/default/private/full/of1vh1r2q5aqdplo65i8bqbn3o'></link><link rel='edit' type='application/atom+xml' href='http://www.google.com/calendar/feeds/default/private/full/of1vh1r2q5aqdplo65i8bqbn3o/63306396191'></link><author><name>w g</name><email>wg@voiceme.net</email></author><gd:comments><gd:feedLink href='http://www.google.com/calendar/feeds/default/private/full/of1vh1r2q5aqdplo65i8bqbn3o/comments'></gd:feedLink></gd:comments><gd:eventStatus value='http://schemas.google.com/g/2005#event.confirmed'></gd:eventStatus><gd:visibility value='http://schemas.google.com/g/2005#event.default'></gd:visibility><gCal:sendEventNotifications value='false'></gCal:sendEventNotifications><gd:transparency value='http://schemas.google.com/g/2005#event.opaque'></gd:transparency><gd:where></gd:where><gd:when startTime='2007-02-05T18:00:00.000-08:00' endTime='2007-02-05T19:00:00.000-08:00'><gd:reminder minutes='10'></gd:reminder></gd:when></entry><entry><id>http://www.google.com/calendar/feeds/default/private/full/s7ahgfomlgii9qbkgpfbinr9u8</id><published>2007-02-05T22:02:40.000Z</published><updated>2007-02-05T22:03:04.000Z</updated><category scheme='http://schemas.google.com/g/2005#kind' term='http://schemas.google.com/g/2005#event'></category><title type='text'>test event 2</title><content type='text'></content><link rel='alternate' type='text/html' href='http://www.google.com/calendar/hosted/voiceme.net/event?eid=czdhaGdmb21sZ2lpOXFia2dwZmJpbnI5dTggd2dAdm9pY2VtZS5uZXQ' title='alternate'></link><link rel='self' type='application/atom+xml' href='http://www.google.com/calendar/feeds/default/private/full/s7ahgfomlgii9qbkgpfbinr9u8'></link><link rel='edit' type='application/atom+xml' href='http://www.google.com/calendar/feeds/default/private/full/s7ahgfomlgii9qbkgpfbinr9u8/63306396184'></link><author><name>w g</name><email>wg@voiceme.net</email></author><gd:comments><gd:feedLink href='http://www.google.com/calendar/feeds/default/private/full/s7ahgfomlgii9qbkgpfbinr9u8/comments'></gd:feedLink></gd:comments><gd:eventStatus value='http://schemas.google.com/g/2005#event.confirmed'></gd:eventStatus><gd:visibility value='http://schemas.google.com/g/2005#event.default'></gd:visibility><gCal:sendEventNotifications value='false'></gCal:sendEventNotifications><gd:transparency value='http://schemas.google.com/g/2005#event.opaque'></gd:transparency><gd:where valueString=''></gd:where><gd:when startTime='2007-02-05T16:30:00.000-08:00' endTime='2007-02-05T17:30:00.000-08:00'><gd:reminder minutes='10'></gd:reminder></gd:when></entry><entry><id>http://www.google.com/calendar/feeds/default/private/full/rl8focglfe6jndql4u8lg73q5k</id><published>2007-02-05T22:02:28.000Z</published><updated>2007-02-05T22:02:53.000Z</updated><category scheme='http://schemas.google.com/g/2005#kind' term='http://schemas.google.com/g/2005#event'></category><title type='text'>test event 1</title><content type='text'></content><link rel='alternate' type='text/html' href='http://www.google.com/calendar/hosted/voiceme.net/event?eid=cmw4Zm9jZ2xmZTZqbmRxbDR1OGxnNzNxNWsgd2dAdm9pY2VtZS5uZXQ' title='alternate'></link><link rel='self' type='application/atom+xml' href='http://www.google.com/calendar/feeds/default/private/full/rl8focglfe6jndql4u8lg73q5k'></link><link rel='edit' type='application/atom+xml' href='http://www.google.com/calendar/feeds/default/private/full/rl8focglfe6jndql4u8lg73q5k/63306396173'></link><author><name>w g</name><email>wg@voiceme.net</email></author><gd:comments><gd:feedLink href='http://www.google.com/calendar/feeds/default/private/full/rl8focglfe6jndql4u8lg73q5k/comments'></gd:feedLink></gd:comments><gd:eventStatus value='http://schemas.google.com/g/2005#event.confirmed'></gd:eventStatus><gd:visibility value='http://schemas.google.com/g/2005#event.default'></gd:visibility><gCal:sendEventNotifications value='false'></gCal:sendEventNotifications><gd:transparency value='http://schemas.google.com/g/2005#event.opaque'></gd:transparency><gd:where></gd:where><gd:when startTime='2007-02-05T15:00:00.000-08:00' endTime='2007-02-05T16:00:00.000-08:00'><gd:reminder minutes='10'></gd:reminder></gd:when></entry></feed> diff --git a/tests/AndroidTests/res/raw/calendarxmlgz.xmlgz b/tests/AndroidTests/res/raw/calendarxmlgz.xmlgz Binary files differnew file mode 100644 index 0000000..6c86462 --- /dev/null +++ b/tests/AndroidTests/res/raw/calendarxmlgz.xmlgz diff --git a/tests/AndroidTests/res/raw/medium.xml b/tests/AndroidTests/res/raw/medium.xml new file mode 100644 index 0000000..51c952c --- /dev/null +++ b/tests/AndroidTests/res/raw/medium.xml @@ -0,0 +1,27 @@ +<?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. +*/ +--> +<LinearLayout id="@+id/content" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent"> + <TextView id="@+id/text" android:text="S" android:layout_width="fill_parent" android:layout_height="wrap_content" /> + <TextView id="@+id/text" android:text="M" android:layout_width="fill_parent" android:layout_height="wrap_content" /> + <TextView id="@+id/text" android:text="T" android:layout_width="fill_parent" android:layout_height="wrap_content" /> + <TextView id="@+id/text" android:text="W" android:layout_width="fill_parent" android:layout_height="wrap_content" /> + <TextView id="@+id/text" android:text="H" android:layout_width="fill_parent" android:layout_height="wrap_content" /> + <TextView id="@+id/text" android:text="F" android:layout_width="fill_parent" android:layout_height="wrap_content" /> +</LinearLayout> diff --git a/tests/AndroidTests/res/raw/small.xml b/tests/AndroidTests/res/raw/small.xml new file mode 100644 index 0000000..2697fb8 --- /dev/null +++ b/tests/AndroidTests/res/raw/small.xml @@ -0,0 +1,20 @@ +<?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. +*/ +--> +<view class="com.android.tests.InflateTest$ViewOne" id="@+id/viewOne" android:layout_width="fill_parent" android:layout_height="fill_parent"/> diff --git a/tests/AndroidTests/res/raw/text.txt b/tests/AndroidTests/res/raw/text.txt new file mode 100644 index 0000000..3d8c519 --- /dev/null +++ b/tests/AndroidTests/res/raw/text.txt @@ -0,0 +1 @@ +OneTwoThreeFourFiveSixSevenEightNineTen
\ No newline at end of file diff --git a/tests/AndroidTests/res/raw/youtube.xml b/tests/AndroidTests/res/raw/youtube.xml new file mode 100644 index 0000000..fedaeac --- /dev/null +++ b/tests/AndroidTests/res/raw/youtube.xml @@ -0,0 +1,1852 @@ +<?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. +--> + +<feed xmlns='http://www.w3.org/2005/Atom' + xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' + xmlns:media='http://search.yahoo.com/mrss/' + xmlns:gd='http://schemas.google.com/g/2005' + xmlns:yt='http://gdata.youtube.com/schemas/2007'> + <id>http://dm5.google.com/feeds/standardfeeds/top_rated</id> + <updated>2007-05-01T18:13:20.333Z</updated> + <title type='text'>Top Rated - Beta</title> + <logo>http://www.youtube.com/img/pic_youtubelogo_123x63.gif</logo> + <link rel='alternate' type='text/html' + href='http://www.youtube.com/browse?s=tr'></link> + <link rel='http://schemas.google.com/g/2005#feed' + type='application/atom+xml' + href='http://dm5.google.com/feeds/standardfeeds/top_rated'></link> + <link rel='self' type='application/atom+xml' + href='http://dm5.google.com/feeds/standardfeeds/top_rated?start-index=1&max-results=25'></link> + <link rel='next' type='application/atom+xml' + href='http://dm5.google.com/feeds/standardfeeds/top_rated?start-index=26&max-results=25'></link> + <author> + <name>YouTube</name> + <uri>http://www.youtube.com/</uri> + </author> + <generator version='beta' uri='http://gdata.youtube.com/'>YouTube data API + </generator> + <openSearch:totalResults>99</openSearch:totalResults> + <openSearch:startIndex>1</openSearch:startIndex> + <openSearch:itemsPerPage>25</openSearch:itemsPerPage> + <entry> + <id>http://dm5.google.com/feeds/videos/nojWJ6-XmeQ</id> + <published>2006-09-01T15:13:19.000Z</published> + <updated>2006-09-01T15:13:19.000Z</updated> + <category scheme='http://gdata.youtube.com/schemas/2007/keywords.cat' + term='comedy'></category> + <category scheme='http://gdata.youtube.com/schemas/2007/keywords.cat' + term='hilarious'></category> + <category scheme='http://gdata.youtube.com/schemas/2007/keywords.cat' + term='funny'></category> + <category scheme='http://gdata.youtube.com/schemas/2007/keywords.cat' + term='Commercial'></category> + <category scheme='http://gdata.youtube.com/schemas/2007/keywords.cat' + term='humor'></category> + <category scheme='http://gdata.youtube.com/schemas/2007/keywords.cat' + term='Condoms'></category> + <category scheme='http://gdata.youtube.com/schemas/2007/categories.cat' + term='Comedy' label='Comedy'></category> + <category scheme='http://gdata.youtube.com/schemas/2007/keywords.cat' + term='Banned'></category> + <title type='text'>Banned Commercial - Condoms</title> + <link rel='self' type='application/atom+xml' + href='http://dm5.google.com/feeds/videos/nojWJ6-XmeQ'></link> + <link rel='alternate' type='text/html' + href='http://www.youtube.com/watch?v=nojWJ6-XmeQ'></link> + <link rel='http://gdata.youtube.com/schemas/2007#video.responses' + type='application/atom+xml' + href='http://dm5.google.com/feeds/videos/nojWJ6-XmeQ/responses'></link> + <link rel='http://gdata.youtube.com/schemas/2007#video.ratings' + type='application/atom+xml' + href='http://dm5.google.com/feeds/videos/nojWJ6-XmeQ/ratings'></link> + <author> + <name>bannedcommercials</name> + <uri>http://dm5.google.com/feeds/users/bannedcommercials</uri> + </author> + <media:group> + <media:title type='plain'>Banned Commercial - Condoms</media:title> + <media:description type='plain'>Banned Commercial - Condoms + </media:description> + <media:keywords>Banned, Commercial, Condoms, funny, hilarious, + comedy, humor + </media:keywords> + <yt:duration seconds='45'></yt:duration> + <media:category label='Comedy' + scheme='http://gdata.youtube.com/schemas/2007/categories.cat'> + Comedy + </media:category> + <media:player + url='http://www.youtube.com/watch?v=nojWJ6-XmeQ'></media:player> + <media:thumbnail url='http://img.youtube.com/vi/nojWJ6-XmeQ/2.jpg' + height='97' width='130' + time='00:00:22.500'></media:thumbnail> + <media:thumbnail url='http://img.youtube.com/vi/nojWJ6-XmeQ/1.jpg' + height='97' width='130' + time='00:00:11.250'></media:thumbnail> + <media:thumbnail url='http://img.youtube.com/vi/nojWJ6-XmeQ/3.jpg' + height='97' width='130' + time='00:00:33.750'></media:thumbnail> + <media:thumbnail url='http://img.youtube.com/vi/nojWJ6-XmeQ/0.jpg' + height='240' width='320'></media:thumbnail> + </media:group> + <gd:rating min='1' max='5' numRaters='65183' average='4.92'></gd:rating> + <gd:feedLink rel='comments' + href='http://dm5.google.com/feeds/videos/nojWJ6-XmeQ/comments'></gd:feedLink> + </entry> + <entry> + <id>http://dm5.google.com/feeds/videos/JahdnOQ9XCA</id> + <published>2006-09-01T17:25:14.000Z</published> + <updated>2006-09-01T17:25:14.000Z</updated> + <category scheme='http://gdata.youtube.com/schemas/2007/keywords.cat' + term='comedy'></category> + <category scheme='http://gdata.youtube.com/schemas/2007/keywords.cat' + term='Voodoo'></category> + <category scheme='http://gdata.youtube.com/schemas/2007/keywords.cat' + term='hilarious'></category> + <category scheme='http://gdata.youtube.com/schemas/2007/keywords.cat' + term='Clinton'></category> + <category scheme='http://gdata.youtube.com/schemas/2007/keywords.cat' + term='funny'></category> + <category scheme='http://gdata.youtube.com/schemas/2007/keywords.cat' + term='Bill'></category> + <category scheme='http://gdata.youtube.com/schemas/2007/keywords.cat' + term='Commercial'></category> + <category scheme='http://gdata.youtube.com/schemas/2007/keywords.cat' + term='very'></category> + <category scheme='http://gdata.youtube.com/schemas/2007/keywords.cat' + term='doll'></category> + <category scheme='http://gdata.youtube.com/schemas/2007/keywords.cat' + term='humor'></category> + <category scheme='http://gdata.youtube.com/schemas/2007/categories.cat' + term='Entertainment' label='Entertainment'></category> + <category scheme='http://gdata.youtube.com/schemas/2007/keywords.cat' + term='Banned'></category> + <title type='text'>Banned Commercial - Bill Clinton Voodoo doll very + funny + </title> + <link rel='self' type='application/atom+xml' + href='http://dm5.google.com/feeds/videos/JahdnOQ9XCA'></link> + <link rel='alternate' type='text/html' + href='http://www.youtube.com/watch?v=JahdnOQ9XCA'></link> + <link rel='http://gdata.youtube.com/schemas/2007#video.responses' + type='application/atom+xml' + href='http://dm5.google.com/feeds/videos/JahdnOQ9XCA/responses'></link> + <link rel='http://gdata.youtube.com/schemas/2007#video.ratings' + type='application/atom+xml' + href='http://dm5.google.com/feeds/videos/JahdnOQ9XCA/ratings'></link> + <author> + <name>bannedcommercials</name> + <uri>http://dm5.google.com/feeds/users/bannedcommercials</uri> + </author> + <media:group> + <media:title type='plain'>Banned Commercial - Bill Clinton Voodoo + doll very funny + </media:title> + <media:description type='plain'>Banned Commercial - Bill Clinton + Voodoo doll very funny + </media:description> + <media:keywords>Banned, Commercial, Bill, Clinton, Voodoo, doll, + very, funny, humor, hilarious, comedy + </media:keywords> + <yt:duration seconds='69'></yt:duration> + <media:category label='Entertainment' + scheme='http://gdata.youtube.com/schemas/2007/categories.cat'> + Entertainment + </media:category> + <media:player + url='http://www.youtube.com/watch?v=JahdnOQ9XCA'></media:player> + <media:thumbnail url='http://img.youtube.com/vi/JahdnOQ9XCA/2.jpg' + height='97' width='130' + time='00:00:34.500'></media:thumbnail> + <media:thumbnail url='http://img.youtube.com/vi/JahdnOQ9XCA/1.jpg' + height='97' width='130' + time='00:00:17.250'></media:thumbnail> + <media:thumbnail url='http://img.youtube.com/vi/JahdnOQ9XCA/3.jpg' + height='97' width='130' + time='00:00:51.750'></media:thumbnail> + <media:thumbnail url='http://img.youtube.com/vi/JahdnOQ9XCA/0.jpg' + height='240' width='320'></media:thumbnail> + </media:group> + <gd:rating min='1' max='5' numRaters='60422' average='4.92'></gd:rating> + <gd:feedLink rel='comments' + href='http://dm5.google.com/feeds/videos/JahdnOQ9XCA/comments'></gd:feedLink> + </entry> + <entry> + <id>http://dm5.google.com/feeds/videos/VcQIwbvGRKU</id> + <published>2006-09-03T05:32:33.000Z</published> + <updated>2006-09-03T05:32:33.000Z</updated> + <category scheme='http://gdata.youtube.com/schemas/2007/keywords.cat' + term='hilarious'></category> + <category scheme='http://gdata.youtube.com/schemas/2007/keywords.cat' + term='funny'></category> + <category scheme='http://gdata.youtube.com/schemas/2007/keywords.cat' + term='Commercial'></category> + <category scheme='http://gdata.youtube.com/schemas/2007/keywords.cat' + term='Talk'></category> + <category scheme='http://gdata.youtube.com/schemas/2007/keywords.cat' + term='Amazing'></category> + <category scheme='http://gdata.youtube.com/schemas/2007/keywords.cat' + term='humor'></category> + <category scheme='http://gdata.youtube.com/schemas/2007/categories.cat' + term='Entertainment' label='Entertainment'></category> + <category scheme='http://gdata.youtube.com/schemas/2007/keywords.cat' + term='awesome'></category> + <category scheme='http://gdata.youtube.com/schemas/2007/keywords.cat' + term='TV'></category> + <title type='text'>Amazing funny TV Commercial - Talk Talk</title> + <link rel='self' type='application/atom+xml' + href='http://dm5.google.com/feeds/videos/VcQIwbvGRKU'></link> + <link rel='alternate' type='text/html' + href='http://www.youtube.com/watch?v=VcQIwbvGRKU'></link> + <link rel='http://gdata.youtube.com/schemas/2007#video.responses' + type='application/atom+xml' + href='http://dm5.google.com/feeds/videos/VcQIwbvGRKU/responses'></link> + <link rel='http://gdata.youtube.com/schemas/2007#video.ratings' + type='application/atom+xml' + href='http://dm5.google.com/feeds/videos/VcQIwbvGRKU/ratings'></link> + <author> + <name>bannedcommercials</name> + <uri>http://dm5.google.com/feeds/users/bannedcommercials</uri> + </author> + <media:group> + <media:title type='plain'>Amazing funny TV Commercial - Talk Talk + </media:title> + <media:description type='plain'>Amazing funny TV Commercial - Talk + Talk + </media:description> + <media:keywords>Amazing, funny, TV, Commercial, Talk, humor, + hilarious, awesome + </media:keywords> + <yt:duration seconds='39'></yt:duration> + <media:category label='Entertainment' + scheme='http://gdata.youtube.com/schemas/2007/categories.cat'> + Entertainment + </media:category> + <media:player + url='http://www.youtube.com/watch?v=VcQIwbvGRKU'></media:player> + <media:thumbnail url='http://img.youtube.com/vi/VcQIwbvGRKU/2.jpg' + height='97' width='130' + time='00:00:19.500'></media:thumbnail> + <media:thumbnail url='http://img.youtube.com/vi/VcQIwbvGRKU/1.jpg' + height='97' width='130' + time='00:00:09.750'></media:thumbnail> + <media:thumbnail url='http://img.youtube.com/vi/VcQIwbvGRKU/3.jpg' + height='97' width='130' + time='00:00:29.250'></media:thumbnail> + <media:thumbnail url='http://img.youtube.com/vi/VcQIwbvGRKU/0.jpg' + height='240' width='320'></media:thumbnail> + </media:group> + <gd:rating min='1' max='5' numRaters='47602' average='4.92'></gd:rating> + <gd:feedLink rel='comments' + href='http://dm5.google.com/feeds/videos/VcQIwbvGRKU/comments'></gd:feedLink> + </entry> + <entry> + <id>http://dm5.google.com/feeds/videos/JsD6uEZsIsU</id> + <published>2006-11-28T16:42:47.000Z</published> + <updated>2006-11-28T16:42:47.000Z</updated> + <category scheme='http://gdata.youtube.com/schemas/2007/keywords.cat' + term='Mckee'></category> + <category scheme='http://gdata.youtube.com/schemas/2007/keywords.cat' + term='Andy'></category> + <category scheme='http://gdata.youtube.com/schemas/2007/categories.cat' + term='Music' label='Music'></category> + <category scheme='http://gdata.youtube.com/schemas/2007/keywords.cat' + term='Guitar'></category> + <category scheme='http://gdata.youtube.com/schemas/2007/keywords.cat' + term='Acoustic'></category> + <title type='text'>Andy Mckee - Rylynn - Acoustic Guitar - + www.candyrat.com + </title> + <link rel='self' type='application/atom+xml' + href='http://dm5.google.com/feeds/videos/JsD6uEZsIsU'></link> + <link rel='alternate' type='text/html' + href='http://www.youtube.com/watch?v=JsD6uEZsIsU'></link> + <link rel='http://gdata.youtube.com/schemas/2007#video.responses' + type='application/atom+xml' + href='http://dm5.google.com/feeds/videos/JsD6uEZsIsU/responses'></link> + <link rel='http://gdata.youtube.com/schemas/2007#video.ratings' + type='application/atom+xml' + href='http://dm5.google.com/feeds/videos/JsD6uEZsIsU/ratings'></link> + <author> + <name>rpoland</name> + <uri>http://dm5.google.com/feeds/users/rpoland</uri> + </author> + <media:group> + <media:title type='plain'>Andy Mckee - Rylynn - Acoustic Guitar - + www.candyrat.com + </media:title> + <media:description type='plain'>Filmed Nov, 2006. + + CD - Art of Motion + + http://www.candyrat.com + + Transcriptions Available at: + + http://www.candyrat.com + </media:description> + <media:keywords>Andy, Mckee, Acoustic, Guitar</media:keywords> + <yt:duration seconds='315'></yt:duration> + <media:category label='Music' + scheme='http://gdata.youtube.com/schemas/2007/categories.cat'> + Music + </media:category> + <media:player + url='http://www.youtube.com/watch?v=JsD6uEZsIsU'></media:player> + <media:thumbnail url='http://img.youtube.com/vi/JsD6uEZsIsU/2.jpg' + height='97' width='130' + time='00:02:37.500'></media:thumbnail> + <media:thumbnail url='http://img.youtube.com/vi/JsD6uEZsIsU/1.jpg' + height='97' width='130' + time='00:01:18.750'></media:thumbnail> + <media:thumbnail url='http://img.youtube.com/vi/JsD6uEZsIsU/3.jpg' + height='97' width='130' + time='00:03:56.250'></media:thumbnail> + <media:thumbnail url='http://img.youtube.com/vi/JsD6uEZsIsU/0.jpg' + height='240' width='320'></media:thumbnail> + </media:group> + <gd:rating min='1' max='5' numRaters='5035' average='4.92'></gd:rating> + <gd:feedLink rel='comments' + href='http://dm5.google.com/feeds/videos/JsD6uEZsIsU/comments'></gd:feedLink> + </entry> + <entry> + <id>http://dm5.google.com/feeds/videos/dt1fB62cGbo</id> + <published>2006-11-19T16:02:11.000Z</published> + <updated>2006-11-19T16:02:11.000Z</updated> + <category scheme='http://gdata.youtube.com/schemas/2007/keywords.cat' + term='Toto'></category> + <category scheme='http://gdata.youtube.com/schemas/2007/keywords.cat' + term='Africa'></category> + <category scheme='http://gdata.youtube.com/schemas/2007/keywords.cat' + term='Mckee'></category> + <category scheme='http://gdata.youtube.com/schemas/2007/keywords.cat' + term='Andy'></category> + <category scheme='http://gdata.youtube.com/schemas/2007/categories.cat' + term='Music' label='Music'></category> + <category scheme='http://gdata.youtube.com/schemas/2007/keywords.cat' + term='Guitar'></category> + <category scheme='http://gdata.youtube.com/schemas/2007/keywords.cat' + term='Fingerstyle'></category> + <category scheme='http://gdata.youtube.com/schemas/2007/keywords.cat' + term='Acoustic'></category> + <title type='text'>Andy Mckee - Africa - Toto - www.candyrat.com</title> + <link rel='self' type='application/atom+xml' + href='http://dm5.google.com/feeds/videos/dt1fB62cGbo'></link> + <link rel='alternate' type='text/html' + href='http://www.youtube.com/watch?v=dt1fB62cGbo'></link> + <link rel='http://gdata.youtube.com/schemas/2007#video.responses' + type='application/atom+xml' + href='http://dm5.google.com/feeds/videos/dt1fB62cGbo/responses'></link> + <link rel='http://gdata.youtube.com/schemas/2007#video.ratings' + type='application/atom+xml' + href='http://dm5.google.com/feeds/videos/dt1fB62cGbo/ratings'></link> + <author> + <name>rpoland</name> + <uri>http://dm5.google.com/feeds/users/rpoland</uri> + </author> + <media:group> + <media:title type='plain'>Andy Mckee - Africa - Toto - + www.candyrat.com + </media:title> + <media:description type='plain'>Andy Mckee + + filmed, Nov, 2006. + + CD - Dreamcatcher + http://www.candyrat.com + + Transcriptions Available at: + http://www.candyrat.com + </media:description> + <media:keywords>Andy, Mckee, Acoustic, Guitar, Fingerstyle, Africa, + Toto + </media:keywords> + <yt:duration seconds='268'></yt:duration> + <media:category label='Music' + scheme='http://gdata.youtube.com/schemas/2007/categories.cat'> + Music + </media:category> + <media:player + url='http://www.youtube.com/watch?v=dt1fB62cGbo'></media:player> + <media:thumbnail url='http://img.youtube.com/vi/dt1fB62cGbo/2.jpg' + height='97' width='130' + time='00:02:14'></media:thumbnail> + <media:thumbnail url='http://img.youtube.com/vi/dt1fB62cGbo/1.jpg' + height='97' width='130' + time='00:01:07'></media:thumbnail> + <media:thumbnail url='http://img.youtube.com/vi/dt1fB62cGbo/3.jpg' + height='97' width='130' + time='00:03:21'></media:thumbnail> + <media:thumbnail url='http://img.youtube.com/vi/dt1fB62cGbo/0.jpg' + height='240' width='320'></media:thumbnail> + </media:group> + <gd:rating min='1' max='5' numRaters='4741' average='4.93'></gd:rating> + <gd:feedLink rel='comments' + href='http://dm5.google.com/feeds/videos/dt1fB62cGbo/comments'></gd:feedLink> + </entry> + <entry> + <id>http://dm5.google.com/feeds/videos/Ddn4MGaS3N4</id> + <published>2006-11-25T21:38:20.000Z</published> + <updated>2006-11-25T21:38:20.000Z</updated> + <category scheme='http://gdata.youtube.com/schemas/2007/keywords.cat' + term='Mckee'></category> + <category scheme='http://gdata.youtube.com/schemas/2007/keywords.cat' + term='Andy'></category> + <category scheme='http://gdata.youtube.com/schemas/2007/categories.cat' + term='Music' label='Music'></category> + <category scheme='http://gdata.youtube.com/schemas/2007/keywords.cat' + term='Guitar'></category> + <category scheme='http://gdata.youtube.com/schemas/2007/keywords.cat' + term='Acoustic'></category> + <title type='text'>Andy Mckee - Guitar - Drifting - www.candyrat.com + </title> + <link rel='self' type='application/atom+xml' + href='http://dm5.google.com/feeds/videos/Ddn4MGaS3N4'></link> + <link rel='alternate' type='text/html' + href='http://www.youtube.com/watch?v=Ddn4MGaS3N4'></link> + <link rel='http://gdata.youtube.com/schemas/2007#video.responses' + type='application/atom+xml' + href='http://dm5.google.com/feeds/videos/Ddn4MGaS3N4/responses'></link> + <link rel='http://gdata.youtube.com/schemas/2007#video.ratings' + type='application/atom+xml' + href='http://dm5.google.com/feeds/videos/Ddn4MGaS3N4/ratings'></link> + <author> + <name>rpoland</name> + <uri>http://dm5.google.com/feeds/users/rpoland</uri> + </author> + <media:group> + <media:title type='plain'>Andy Mckee - Guitar - Drifting - + www.candyrat.com + </media:title> + <media:description type='plain'>Acoustic Guitar + + Drifting - Andy Mckee's Original Song + + filmed, Nov, 2006. + + CD - Art of Motion + + http://www.candyrat.com + + Transcriptions Available at: + + http://www.candyrat.com + </media:description> + <media:keywords>Acoustic, Guitar, Andy, Mckee</media:keywords> + <yt:duration seconds='198'></yt:duration> + <media:category label='Music' + scheme='http://gdata.youtube.com/schemas/2007/categories.cat'> + Music + </media:category> + <media:player + url='http://www.youtube.com/watch?v=Ddn4MGaS3N4'></media:player> + <media:thumbnail url='http://img.youtube.com/vi/Ddn4MGaS3N4/2.jpg' + height='97' width='130' + time='00:01:39'></media:thumbnail> + <media:thumbnail url='http://img.youtube.com/vi/Ddn4MGaS3N4/1.jpg' + height='97' width='130' + time='00:00:49.500'></media:thumbnail> + <media:thumbnail url='http://img.youtube.com/vi/Ddn4MGaS3N4/3.jpg' + height='97' width='130' + time='00:02:28.500'></media:thumbnail> + <media:thumbnail url='http://img.youtube.com/vi/Ddn4MGaS3N4/0.jpg' + height='240' width='320'></media:thumbnail> + </media:group> + <gd:rating min='1' max='5' numRaters='26323' average='4.90'></gd:rating> + <gd:feedLink rel='comments' + href='http://dm5.google.com/feeds/videos/Ddn4MGaS3N4/comments'></gd:feedLink> + </entry> + <entry> + <id>http://dm5.google.com/feeds/videos/SmVAWKfJ4Go</id> + <published>2005-12-13T02:25:05.000Z</published> + <updated>2005-12-13T02:25:05.000Z</updated> + <category scheme='http://gdata.youtube.com/schemas/2007/keywords.cat' + term='Cash'></category> + <category scheme='http://gdata.youtube.com/schemas/2007/categories.cat' + term='Music' label='Music'></category> + <category scheme='http://gdata.youtube.com/schemas/2007/keywords.cat' + term='hurt'></category> + <title type='text'>Cash Hurt</title> + <link rel='self' type='application/atom+xml' + href='http://dm5.google.com/feeds/videos/SmVAWKfJ4Go'></link> + <link rel='alternate' type='text/html' + href='http://www.youtube.com/watch?v=SmVAWKfJ4Go'></link> + <link rel='http://gdata.youtube.com/schemas/2007#video.responses' + type='application/atom+xml' + href='http://dm5.google.com/feeds/videos/SmVAWKfJ4Go/responses'></link> + <link rel='http://gdata.youtube.com/schemas/2007#video.ratings' + type='application/atom+xml' + href='http://dm5.google.com/feeds/videos/SmVAWKfJ4Go/ratings'></link> + <author> + <name>beachbuggy</name> + <uri>http://dm5.google.com/feeds/users/beachbuggy</uri> + </author> + <media:group> + <media:title type='plain'>Cash Hurt</media:title> + <media:description type='plain'>cash hurt</media:description> + <media:keywords>Cash, hurt</media:keywords> + <yt:duration seconds='241'></yt:duration> + <media:category label='Music' + scheme='http://gdata.youtube.com/schemas/2007/categories.cat'> + Music + </media:category> + <media:player + url='http://www.youtube.com/watch?v=SmVAWKfJ4Go'></media:player> + <media:thumbnail url='http://img.youtube.com/vi/SmVAWKfJ4Go/2.jpg' + height='97' width='130' + time='00:02:00.500'></media:thumbnail> + <media:thumbnail url='http://img.youtube.com/vi/SmVAWKfJ4Go/1.jpg' + height='97' width='130' + time='00:01:00.250'></media:thumbnail> + <media:thumbnail url='http://img.youtube.com/vi/SmVAWKfJ4Go/3.jpg' + height='97' width='130' + time='00:03:00.750'></media:thumbnail> + <media:thumbnail url='http://img.youtube.com/vi/SmVAWKfJ4Go/0.jpg' + height='240' width='320'></media:thumbnail> + </media:group> + <gd:rating min='1' max='5' numRaters='5328' average='4.91'></gd:rating> + <gd:feedLink rel='comments' + href='http://dm5.google.com/feeds/videos/SmVAWKfJ4Go/comments'></gd:feedLink> + </entry> + <entry> + <id>http://dm5.google.com/feeds/videos/AbndgwfG22k</id> + <published>2006-06-18T18:07:46.000Z</published> + <updated>2006-06-18T18:07:46.000Z</updated> + <category scheme='http://gdata.youtube.com/schemas/2007/keywords.cat' + term='Tommy'></category> + <category scheme='http://gdata.youtube.com/schemas/2007/keywords.cat' + term='Don'></category> + <category scheme='http://gdata.youtube.com/schemas/2007/keywords.cat' + term='Preston'></category> + <category scheme='http://gdata.youtube.com/schemas/2007/keywords.cat' + term='Kottke'></category> + <category scheme='http://gdata.youtube.com/schemas/2007/keywords.cat' + term='Emmanuel'></category> + <category scheme='http://gdata.youtube.com/schemas/2007/keywords.cat' + term='Ross'></category> + <category scheme='http://gdata.youtube.com/schemas/2007/keywords.cat' + term='Mongrain'></category> + <category scheme='http://gdata.youtube.com/schemas/2007/keywords.cat' + term='Hedges'></category> + <category scheme='http://gdata.youtube.com/schemas/2007/keywords.cat' + term='Erik'></category> + <category scheme='http://gdata.youtube.com/schemas/2007/keywords.cat' + term='Michael'></category> + <category scheme='http://gdata.youtube.com/schemas/2007/keywords.cat' + term='Reed'></category> + <category scheme='http://gdata.youtube.com/schemas/2007/categories.cat' + term='Music' label='Music'></category> + <category scheme='http://gdata.youtube.com/schemas/2007/keywords.cat' + term='Guitar'></category> + <category scheme='http://gdata.youtube.com/schemas/2007/keywords.cat' + term='Leo'></category> + <category scheme='http://gdata.youtube.com/schemas/2007/keywords.cat' + term='Acoustic'></category> + <title type='text'>"AirTap!"</title> + <link rel='self' type='application/atom+xml' + href='http://dm5.google.com/feeds/videos/AbndgwfG22k'></link> + <link rel='alternate' type='text/html' + href='http://www.youtube.com/watch?v=AbndgwfG22k'></link> + <link rel='http://gdata.youtube.com/schemas/2007#video.responses' + type='application/atom+xml' + href='http://dm5.google.com/feeds/videos/AbndgwfG22k/responses'></link> + <link rel='http://gdata.youtube.com/schemas/2007#video.ratings' + type='application/atom+xml' + href='http://dm5.google.com/feeds/videos/AbndgwfG22k/ratings'></link> + <author> + <name>erikmongrain</name> + <uri>http://dm5.google.com/feeds/users/erikmongrain</uri> + </author> + <media:group> + <media:title type='plain'>"AirTap!"</media:title> + <media:description type='plain'>MY FIRST CD IS NOW AVAILABLE ON MY + WEBSITE IN MP3 FORMAT !!! IN STORE MAY 2007 ! + www.erikmongrain.com + + Myself playing a composition I made 6 years ago in the streets + of Spain when I was travelling around.That was on "Belle et Bum" + (popular music show in Quebec ). + </media:description> + <media:keywords>Acoustic, Guitar, Michael, Hedges, Preston, Reed, + Don, Ross, Erik, Mongrain, Tommy, Emmanuel, Leo, Kottke + </media:keywords> + <yt:duration seconds='180'></yt:duration> + <media:category label='Music' + scheme='http://gdata.youtube.com/schemas/2007/categories.cat'> + Music + </media:category> + <media:player + url='http://www.youtube.com/watch?v=AbndgwfG22k'></media:player> + <media:thumbnail url='http://img.youtube.com/vi/AbndgwfG22k/2.jpg' + height='97' width='130' + time='00:01:30'></media:thumbnail> + <media:thumbnail url='http://img.youtube.com/vi/AbndgwfG22k/1.jpg' + height='97' width='130' + time='00:00:45'></media:thumbnail> + <media:thumbnail url='http://img.youtube.com/vi/AbndgwfG22k/3.jpg' + height='97' width='130' + time='00:02:15'></media:thumbnail> + <media:thumbnail url='http://img.youtube.com/vi/AbndgwfG22k/0.jpg' + height='240' width='320'></media:thumbnail> + </media:group> + <gd:rating min='1' max='5' numRaters='6453' average='4.90'></gd:rating> + <gd:feedLink rel='comments' + href='http://dm5.google.com/feeds/videos/AbndgwfG22k/comments'></gd:feedLink> + </entry> + <entry> + <id>http://dm5.google.com/feeds/videos/2Neop9OVaB8</id> + <published>2006-11-21T23:03:29.000Z</published> + <updated>2006-11-21T23:03:29.000Z</updated> + <category scheme='http://gdata.youtube.com/schemas/2007/keywords.cat' + term='Reel'></category> + <category scheme='http://gdata.youtube.com/schemas/2007/keywords.cat' + term='Minor'></category> + <category scheme='http://gdata.youtube.com/schemas/2007/keywords.cat' + term='Dunks'></category> + <category scheme='http://gdata.youtube.com/schemas/2007/keywords.cat' + term='Shinoda'></category> + <category scheme='http://gdata.youtube.com/schemas/2007/keywords.cat' + term='Skate'></category> + <category scheme='http://gdata.youtube.com/schemas/2007/keywords.cat' + term='Mike'></category> + <category scheme='http://gdata.youtube.com/schemas/2007/keywords.cat' + term='Name'></category> + <category scheme='http://gdata.youtube.com/schemas/2007/keywords.cat' + term='Fuse'></category> + <category scheme='http://gdata.youtube.com/schemas/2007/keywords.cat' + term='Flips'></category> + <category scheme='http://gdata.youtube.com/schemas/2007/keywords.cat' + term='Sports'></category> + <category scheme='http://gdata.youtube.com/schemas/2007/categories.cat' + term='Entertainment' label='Entertainment'></category> + <category scheme='http://gdata.youtube.com/schemas/2007/keywords.cat' + term='Action'></category> + <category scheme='http://gdata.youtube.com/schemas/2007/keywords.cat' + term='Ties'></category> + <category scheme='http://gdata.youtube.com/schemas/2007/keywords.cat' + term='Remember'></category> + <category scheme='http://gdata.youtube.com/schemas/2007/keywords.cat' + term='Fort'></category> + <category scheme='http://gdata.youtube.com/schemas/2007/keywords.cat' + term='Highlight'></category> + <category scheme='http://gdata.youtube.com/schemas/2007/keywords.cat' + term='Scooter'></category> + <category scheme='http://gdata.youtube.com/schemas/2007/keywords.cat' + term='Tricks'></category> + <category scheme='http://gdata.youtube.com/schemas/2007/keywords.cat' + term='Rising'></category> + <category scheme='http://gdata.youtube.com/schemas/2007/keywords.cat' + term='The'></category> + <title type='text'>Remember The Name - Highlight Reel Video</title> + <link rel='self' type='application/atom+xml' + href='http://dm5.google.com/feeds/videos/2Neop9OVaB8'></link> + <link rel='alternate' type='text/html' + href='http://www.youtube.com/watch?v=2Neop9OVaB8'></link> + <link rel='http://gdata.youtube.com/schemas/2007#video.responses' + type='application/atom+xml' + href='http://dm5.google.com/feeds/videos/2Neop9OVaB8/responses'></link> + <link rel='http://gdata.youtube.com/schemas/2007#video.ratings' + type='application/atom+xml' + href='http://dm5.google.com/feeds/videos/2Neop9OVaB8/ratings'></link> + <author> + <name>fortminor</name> + <uri>http://dm5.google.com/feeds/users/fortminor</uri> + </author> + <media:group> + <media:title type='plain'>Remember The Name - Highlight Reel Video + </media:title> + <media:description type='plain'>Fort Minor Remember The Name + "Highlight Reel" video - made from the winning video clips + submitted for the Fort Minor / Fuse Remember The Name contest - + congratulations to all the winners! + </media:description> + <media:keywords>Fort, Minor, Fuse, Highlight, Reel, Action, Sports, + Remember, The, Name, Rising, Ties, Mike, Shinoda, Skate, + Scooter, Tricks, Flips, Dunks + </media:keywords> + <yt:duration seconds='246'></yt:duration> + <media:category label='Entertainment' + scheme='http://gdata.youtube.com/schemas/2007/categories.cat'> + Entertainment + </media:category> + <media:player + url='http://www.youtube.com/watch?v=2Neop9OVaB8'></media:player> + <media:thumbnail url='http://img.youtube.com/vi/2Neop9OVaB8/2.jpg' + height='97' width='130' + time='00:02:03'></media:thumbnail> + <media:thumbnail url='http://img.youtube.com/vi/2Neop9OVaB8/1.jpg' + height='97' width='130' + time='00:01:01.500'></media:thumbnail> + <media:thumbnail url='http://img.youtube.com/vi/2Neop9OVaB8/3.jpg' + height='97' width='130' + time='00:03:04.500'></media:thumbnail> + <media:thumbnail url='http://img.youtube.com/vi/2Neop9OVaB8/0.jpg' + height='240' width='320'></media:thumbnail> + </media:group> + <gd:rating min='1' max='5' numRaters='5535' average='4.90'></gd:rating> + <gd:feedLink rel='comments' + href='http://dm5.google.com/feeds/videos/2Neop9OVaB8/comments'></gd:feedLink> + </entry> + <entry> + <id>http://dm5.google.com/feeds/videos/QKXWAE8YYxY</id> + <published>2006-02-03T00:07:12.000Z</published> + <updated>2006-02-03T00:07:12.000Z</updated> + <category scheme='http://gdata.youtube.com/schemas/2007/keywords.cat' + term='MF'></category> + <category scheme='http://gdata.youtube.com/schemas/2007/keywords.cat' + term='Self'></category> + <category scheme='http://gdata.youtube.com/schemas/2007/keywords.cat' + term='Resident'></category> + <category scheme='http://gdata.youtube.com/schemas/2007/keywords.cat' + term='MSI'></category> + <category scheme='http://gdata.youtube.com/schemas/2007/keywords.cat' + term='Evil'></category> + <category scheme='http://gdata.youtube.com/schemas/2007/keywords.cat' + term='Stupid'></category> + <category scheme='http://gdata.youtube.com/schemas/2007/keywords.cat' + term='Indulgence'></category> + <category scheme='http://gdata.youtube.com/schemas/2007/keywords.cat' + term='Four'></category> + <category scheme='http://gdata.youtube.com/schemas/2007/keywords.cat' + term='Mindless'></category> + <category scheme='http://gdata.youtube.com/schemas/2007/keywords.cat' + term='RE4'></category> + <category scheme='http://gdata.youtube.com/schemas/2007/categories.cat' + term='Games' label='Gadgets & Games'></category> + <title type='text'>Resident Evil 4 -- Stupid MF</title> + <link rel='self' type='application/atom+xml' + href='http://dm5.google.com/feeds/videos/QKXWAE8YYxY'></link> + <link rel='alternate' type='text/html' + href='http://www.youtube.com/watch?v=QKXWAE8YYxY'></link> + <link rel='http://gdata.youtube.com/schemas/2007#video.responses' + type='application/atom+xml' + href='http://dm5.google.com/feeds/videos/QKXWAE8YYxY/responses'></link> + <link rel='http://gdata.youtube.com/schemas/2007#video.ratings' + type='application/atom+xml' + href='http://dm5.google.com/feeds/videos/QKXWAE8YYxY/ratings'></link> + <author> + <name>raypinot</name> + <uri>http://dm5.google.com/feeds/users/raypinot</uri> + </author> + <media:group> + <media:title type='plain'>Resident Evil 4 -- Stupid MF</media:title> + <media:description type='plain'>Video I made for Resident Evil 4 + using "Separate Ways" and footage and that didn't make it into + my first video, "Vicinity of Obscenity" This video is done to + the song "Stupid MF" by Mindless Self Indulgence. + + http://www.help-lara-and-ray.com/ + </media:description> + <media:keywords>Resident, Evil, Four, RE4, Mindless, Self, + Indulgence, MSI, Stupid, MF + </media:keywords> + <yt:duration seconds='146'></yt:duration> + <media:category label='Gadgets & Games' + scheme='http://gdata.youtube.com/schemas/2007/categories.cat'> + Games + </media:category> + <media:player + url='http://www.youtube.com/watch?v=QKXWAE8YYxY'></media:player> + <media:thumbnail url='http://img.youtube.com/vi/QKXWAE8YYxY/2.jpg' + height='97' width='130' + time='00:01:13'></media:thumbnail> + <media:thumbnail url='http://img.youtube.com/vi/QKXWAE8YYxY/1.jpg' + height='97' width='130' + time='00:00:36.500'></media:thumbnail> + <media:thumbnail url='http://img.youtube.com/vi/QKXWAE8YYxY/3.jpg' + height='97' width='130' + time='00:01:49.500'></media:thumbnail> + <media:thumbnail url='http://img.youtube.com/vi/QKXWAE8YYxY/0.jpg' + height='240' width='320'></media:thumbnail> + </media:group> + <gd:rating min='1' max='5' numRaters='12632' average='4.89'></gd:rating> + <gd:feedLink rel='comments' + href='http://dm5.google.com/feeds/videos/QKXWAE8YYxY/comments'></gd:feedLink> + </entry> + <entry> + <id>http://dm5.google.com/feeds/videos/zQoAUI84amI</id> + <published>2006-02-02T23:36:31.000Z</published> + <updated>2006-02-02T23:36:31.000Z</updated> + <category scheme='http://gdata.youtube.com/schemas/2007/keywords.cat' + term='Resident'></category> + <category scheme='http://gdata.youtube.com/schemas/2007/keywords.cat' + term='Evil'></category> + <category scheme='http://gdata.youtube.com/schemas/2007/keywords.cat' + term='of'></category> + <category scheme='http://gdata.youtube.com/schemas/2007/keywords.cat' + term='SOAD'></category> + <category scheme='http://gdata.youtube.com/schemas/2007/keywords.cat' + term='Obscenity'></category> + <category scheme='http://gdata.youtube.com/schemas/2007/keywords.cat' + term='Four'></category> + <category scheme='http://gdata.youtube.com/schemas/2007/keywords.cat' + term='Vicinity'></category> + <category scheme='http://gdata.youtube.com/schemas/2007/keywords.cat' + term='System'></category> + <category scheme='http://gdata.youtube.com/schemas/2007/keywords.cat' + term='RE4'></category> + <category scheme='http://gdata.youtube.com/schemas/2007/categories.cat' + term='Games' label='Gadgets & Games'></category> + <category scheme='http://gdata.youtube.com/schemas/2007/keywords.cat' + term='Down'></category> + <title type='text'>Resident Evil 4 -- Vicinity of Obscenity</title> + <link rel='self' type='application/atom+xml' + href='http://dm5.google.com/feeds/videos/zQoAUI84amI'></link> + <link rel='alternate' type='text/html' + href='http://www.youtube.com/watch?v=zQoAUI84amI'></link> + <link rel='http://gdata.youtube.com/schemas/2007#video.responses' + type='application/atom+xml' + href='http://dm5.google.com/feeds/videos/zQoAUI84amI/responses'></link> + <link rel='http://gdata.youtube.com/schemas/2007#video.ratings' + type='application/atom+xml' + href='http://dm5.google.com/feeds/videos/zQoAUI84amI/ratings'></link> + <author> + <name>raypinot</name> + <uri>http://dm5.google.com/feeds/users/raypinot</uri> + </author> + <media:group> + <media:title type='plain'>Resident Evil 4 -- Vicinity of Obscenity + </media:title> + <media:description type='plain'>Music video I made For Resident Evil + 4 (PS2), using the System of a Down song, "Vicinity of + Obscenity" + + + http://www.help-lara-and-ray.com/ + </media:description> + <media:keywords>Resident, Evil, Four, RE4, System, Down, SOAD, + Vicinity, of, Obscenity + </media:keywords> + <yt:duration seconds='168'></yt:duration> + <media:category label='Gadgets & Games' + scheme='http://gdata.youtube.com/schemas/2007/categories.cat'> + Games + </media:category> + <media:player + url='http://www.youtube.com/watch?v=zQoAUI84amI'></media:player> + <media:thumbnail url='http://img.youtube.com/vi/zQoAUI84amI/2.jpg' + height='97' width='130' + time='00:01:24'></media:thumbnail> + <media:thumbnail url='http://img.youtube.com/vi/zQoAUI84amI/1.jpg' + height='97' width='130' + time='00:00:42'></media:thumbnail> + <media:thumbnail url='http://img.youtube.com/vi/zQoAUI84amI/3.jpg' + height='97' width='130' + time='00:02:06'></media:thumbnail> + <media:thumbnail url='http://img.youtube.com/vi/zQoAUI84amI/0.jpg' + height='240' width='320'></media:thumbnail> + </media:group> + <gd:rating min='1' max='5' numRaters='9509' average='4.89'></gd:rating> + <gd:feedLink rel='comments' + href='http://dm5.google.com/feeds/videos/zQoAUI84amI/comments'></gd:feedLink> + </entry> + <entry> + <id>http://dm5.google.com/feeds/videos/JzqumbhfxRo</id> + <published>2006-11-07T16:59:10.000Z</published> + <updated>2006-11-07T16:59:10.000Z</updated> + <category scheme='http://gdata.youtube.com/schemas/2007/keywords.cat' + term='gjertsen'></category> + <category scheme='http://gdata.youtube.com/schemas/2007/keywords.cat' + term='drums'></category> + <category scheme='http://gdata.youtube.com/schemas/2007/keywords.cat' + term='and'></category> + <category scheme='http://gdata.youtube.com/schemas/2007/keywords.cat' + term='editing'></category> + <category scheme='http://gdata.youtube.com/schemas/2007/keywords.cat' + term='piano'></category> + <category scheme='http://gdata.youtube.com/schemas/2007/keywords.cat' + term='amateur'></category> + <category scheme='http://gdata.youtube.com/schemas/2007/keywords.cat' + term='drumkit'></category> + <category scheme='http://gdata.youtube.com/schemas/2007/keywords.cat' + term='titties'></category> + <category scheme='http://gdata.youtube.com/schemas/2007/keywords.cat' + term='norsk'></category> + <category scheme='http://gdata.youtube.com/schemas/2007/keywords.cat' + term='ass'></category> + <category scheme='http://gdata.youtube.com/schemas/2007/categories.cat' + term='Film' label='Film & Animation'></category> + <category scheme='http://gdata.youtube.com/schemas/2007/keywords.cat' + term='lasse'></category> + <category scheme='http://gdata.youtube.com/schemas/2007/keywords.cat' + term='hyperactive'></category> + <category scheme='http://gdata.youtube.com/schemas/2007/keywords.cat' + term='lassegg'></category> + <category scheme='http://gdata.youtube.com/schemas/2007/keywords.cat' + term='music'></category> + <category scheme='http://gdata.youtube.com/schemas/2007/keywords.cat' + term='norwegian'></category> + <title type='text'>Amateur - Lasse Gjertsen</title> + <link rel='self' type='application/atom+xml' + href='http://dm5.google.com/feeds/videos/JzqumbhfxRo'></link> + <link rel='alternate' type='text/html' + href='http://www.youtube.com/watch?v=JzqumbhfxRo'></link> + <link rel='http://gdata.youtube.com/schemas/2007#video.responses' + type='application/atom+xml' + href='http://dm5.google.com/feeds/videos/JzqumbhfxRo/responses'></link> + <link rel='http://gdata.youtube.com/schemas/2007#video.ratings' + type='application/atom+xml' + href='http://dm5.google.com/feeds/videos/JzqumbhfxRo/ratings'></link> + <author> + <name>lassegg</name> + <uri>http://dm5.google.com/feeds/users/lassegg</uri> + </author> + <media:group> + <media:title type='plain'>Amateur - Lasse Gjertsen</media:title> + <media:description type='plain'>I've taken my hyperactive editing + style a step further! Hope you'll enjoy it! + + If you want to download the audio from this video, go to + http://www11.nrk.no/urort/user/?id=36781 + It's a norwegian page where I uploaded some of my music. (Lytt = + Listen to, Last ned = Download) + + Oh shit, I forgot to put this in the video, and now it's too + late to change it: + Thanks to my friend Mattis for letting me borrow the drum kit. + Also thanks to the person letting me use her piano, but she + didn't want her name here :P + + And now; to you people saying I'm ripping off Michel Gondry: + I've seen his video with the drumkit called "Drumb and Drumber". + It's here on youtube somewhere. His video and my video are + different because of one very important detail: Gondy filmed + himself doing drumming sequences and LOOPED them, while I hit + each drum and piano chord seperately and edited them together. + This is a very big difference if you have any idea about video + editing. Actually, there is a short sequence of 5 sec where he + does cut the beat, but I didn't notice this until recently, + which makes me an idiot. But I still don't think it's a rip off, + only similar. SO one question to you guys: If I write a song + which includes the words "love" and "tight", am I ripping off + The Beatles?? :P I met Michel Gondry in Milan, Italy and asked + him. He didn't really give me a clear answer, but it seemed like + he thought so. Either that or he didn't like my clothes. Lol. + </media:description> + <media:keywords>amateur, lasse, gjertsen, drumkit, drums, piano, + music, norsk, norwegian, lassegg, hyperactive, editing, ass, + and, titties + </media:keywords> + <yt:duration seconds='192'></yt:duration> + <media:category label='Film & Animation' + scheme='http://gdata.youtube.com/schemas/2007/categories.cat'> + Film + </media:category> + <media:content + url='rtsp://rtsp.youtube.com/youtube/videos/JzqumbhfxRo/video.3gp' + type='video/3gpp' medium='video' isDefault='true' + expression='full' duration='192' + yt:format='1'></media:content> + <media:player + url='http://www.youtube.com/watch?v=JzqumbhfxRo'></media:player> + <media:thumbnail url='http://img.youtube.com/vi/JzqumbhfxRo/2.jpg' + height='97' width='130' + time='00:01:36'></media:thumbnail> + <media:thumbnail url='http://img.youtube.com/vi/JzqumbhfxRo/1.jpg' + height='97' width='130' + time='00:00:48'></media:thumbnail> + <media:thumbnail url='http://img.youtube.com/vi/JzqumbhfxRo/3.jpg' + height='97' width='130' + time='00:02:24'></media:thumbnail> + <media:thumbnail url='http://img.youtube.com/vi/JzqumbhfxRo/0.jpg' + height='240' width='320'></media:thumbnail> + </media:group> + <gd:rating min='1' max='5' numRaters='35620' average='4.89'></gd:rating> + <gd:feedLink rel='comments' + href='http://dm5.google.com/feeds/videos/JzqumbhfxRo/comments'></gd:feedLink> + </entry> + <entry> + <id>http://dm5.google.com/feeds/videos/YxQrPXPSVhQ</id> + <published>2006-06-17T16:04:49.000Z</published> + <updated>2006-06-17T16:04:49.000Z</updated> + <category scheme='http://gdata.youtube.com/schemas/2007/keywords.cat' + term='Evanescence'></category> + <category scheme='http://gdata.youtube.com/schemas/2007/categories.cat' + term='Music' label='Music'></category> + <title type='text'>Evanescence</title> + <link rel='self' type='application/atom+xml' + href='http://dm5.google.com/feeds/videos/YxQrPXPSVhQ'></link> + <link rel='alternate' type='text/html' + href='http://www.youtube.com/watch?v=YxQrPXPSVhQ'></link> + <link rel='http://gdata.youtube.com/schemas/2007#video.responses' + type='application/atom+xml' + href='http://dm5.google.com/feeds/videos/YxQrPXPSVhQ/responses'></link> + <link rel='http://gdata.youtube.com/schemas/2007#video.ratings' + type='application/atom+xml' + href='http://dm5.google.com/feeds/videos/YxQrPXPSVhQ/ratings'></link> + <author> + <name>luke4leanne</name> + <uri>http://dm5.google.com/feeds/users/luke4leanne</uri> + </author> + <media:group> + <media:title type='plain'>Evanescence</media:title> + <media:description type='plain'>Evanescence-My Immortal + </media:description> + <media:keywords>Evanescence</media:keywords> + <yt:duration seconds='272'></yt:duration> + <media:category label='Music' + scheme='http://gdata.youtube.com/schemas/2007/categories.cat'> + Music + </media:category> + <media:player + url='http://www.youtube.com/watch?v=YxQrPXPSVhQ'></media:player> + <media:thumbnail url='http://img.youtube.com/vi/YxQrPXPSVhQ/2.jpg' + height='97' width='130' + time='00:02:16'></media:thumbnail> + <media:thumbnail url='http://img.youtube.com/vi/YxQrPXPSVhQ/1.jpg' + height='97' width='130' + time='00:01:08'></media:thumbnail> + <media:thumbnail url='http://img.youtube.com/vi/YxQrPXPSVhQ/3.jpg' + height='97' width='130' + time='00:03:24'></media:thumbnail> + <media:thumbnail url='http://img.youtube.com/vi/YxQrPXPSVhQ/0.jpg' + height='240' width='320'></media:thumbnail> + </media:group> + <gd:rating min='1' max='5' numRaters='5226' average='4.90'></gd:rating> + <gd:feedLink rel='comments' + href='http://dm5.google.com/feeds/videos/YxQrPXPSVhQ/comments'></gd:feedLink> + </entry> + <entry> + <id>http://dm5.google.com/feeds/videos/O9mEKMz2Pvo</id> + <published>2006-02-15T12:14:08.000Z</published> + <updated>2006-02-15T12:14:08.000Z</updated> + <category scheme='http://gdata.youtube.com/schemas/2007/keywords.cat' + term='Weeps'></category> + <category scheme='http://gdata.youtube.com/schemas/2007/keywords.cat' + term='Shimabukuro'></category> + <category scheme='http://gdata.youtube.com/schemas/2007/keywords.cat' + term='ukelele'></category> + <category scheme='http://gdata.youtube.com/schemas/2007/categories.cat' + term='Music' label='Music'></category> + <category scheme='http://gdata.youtube.com/schemas/2007/keywords.cat' + term='Gently'></category> + <category scheme='http://gdata.youtube.com/schemas/2007/keywords.cat' + term='Guitar'></category> + <category scheme='http://gdata.youtube.com/schemas/2007/keywords.cat' + term='While'></category> + <category scheme='http://gdata.youtube.com/schemas/2007/keywords.cat' + term='My'></category> + <category scheme='http://gdata.youtube.com/schemas/2007/keywords.cat' + term='Jake'></category> + <title type='text'>Jake Shimabukuro plays "While My Guitar Gently Weeps" + </title> + <link rel='self' type='application/atom+xml' + href='http://dm5.google.com/feeds/videos/O9mEKMz2Pvo'></link> + <link rel='alternate' type='text/html' + href='http://www.youtube.com/watch?v=O9mEKMz2Pvo'></link> + <link rel='http://gdata.youtube.com/schemas/2007#video.responses' + type='application/atom+xml' + href='http://dm5.google.com/feeds/videos/O9mEKMz2Pvo/responses'></link> + <link rel='http://gdata.youtube.com/schemas/2007#video.ratings' + type='application/atom+xml' + href='http://dm5.google.com/feeds/videos/O9mEKMz2Pvo/ratings'></link> + <author> + <name>strewth</name> + <uri>http://dm5.google.com/feeds/users/strewth</uri> + </author> + <media:group> + <media:title type='plain'>Jake Shimabukuro plays "While My Guitar + Gently Weeps" + </media:title> + <media:description type='plain'>Jake Shimabukuro plays "While My + Guitar Gently Weeps" on the ukelele. Amazing. + </media:description> + <media:keywords>Jake, Shimabukuro, While, My, Guitar, Gently, Weeps, + ukelele + </media:keywords> + <yt:duration seconds='272'></yt:duration> + <media:category label='Music' + scheme='http://gdata.youtube.com/schemas/2007/categories.cat'> + Music + </media:category> + <media:player + url='http://www.youtube.com/watch?v=O9mEKMz2Pvo'></media:player> + <media:thumbnail url='http://img.youtube.com/vi/O9mEKMz2Pvo/2.jpg' + height='97' width='130' + time='00:02:16'></media:thumbnail> + <media:thumbnail url='http://img.youtube.com/vi/O9mEKMz2Pvo/1.jpg' + height='97' width='130' + time='00:01:08'></media:thumbnail> + <media:thumbnail url='http://img.youtube.com/vi/O9mEKMz2Pvo/3.jpg' + height='97' width='130' + time='00:03:24'></media:thumbnail> + <media:thumbnail url='http://img.youtube.com/vi/O9mEKMz2Pvo/0.jpg' + height='240' width='320'></media:thumbnail> + </media:group> + <gd:rating min='1' max='5' numRaters='6596' average='4.89'></gd:rating> + <gd:feedLink rel='comments' + href='http://dm5.google.com/feeds/videos/O9mEKMz2Pvo/comments'></gd:feedLink> + </entry> + <entry> + <id>http://dm5.google.com/feeds/videos/rP3qL4UG1TI</id> + <published>2006-10-27T20:29:34.000Z</published> + <updated>2006-10-27T20:29:34.000Z</updated> + <category scheme='http://gdata.youtube.com/schemas/2007/keywords.cat' + term='105'></category> + <category scheme='http://gdata.youtube.com/schemas/2007/keywords.cat' + term='Live'></category> + <category scheme='http://gdata.youtube.com/schemas/2007/keywords.cat' + term='Spears'></category> + <category scheme='http://gdata.youtube.com/schemas/2007/keywords.cat' + term='whitemenace'></category> + <category scheme='http://gdata.youtube.com/schemas/2007/categories.cat' + term='Entertainment' label='Entertainment'></category> + <category scheme='http://gdata.youtube.com/schemas/2007/keywords.cat' + term='Q101'></category> + <category scheme='http://gdata.youtube.com/schemas/2007/keywords.cat' + term='Woody'></category> + <category scheme='http://gdata.youtube.com/schemas/2007/keywords.cat' + term='Ravey'></category> + <category scheme='http://gdata.youtube.com/schemas/2007/keywords.cat' + term='snoop'></category> + <category scheme='http://gdata.youtube.com/schemas/2007/keywords.cat' + term='JayZ'></category> + <category scheme='http://gdata.youtube.com/schemas/2007/keywords.cat' + term='dog'></category> + <category scheme='http://gdata.youtube.com/schemas/2007/keywords.cat' + term='show'></category> + <category scheme='http://gdata.youtube.com/schemas/2007/keywords.cat' + term='morning'></category> + <category scheme='http://gdata.youtube.com/schemas/2007/keywords.cat' + term='Aries'></category> + <category scheme='http://gdata.youtube.com/schemas/2007/keywords.cat' + term='Tony'></category> + <category scheme='http://gdata.youtube.com/schemas/2007/keywords.cat' + term='radio'></category> + <title type='text'>The Woody show "Aries Spears" rap Live105.com</title> + <link rel='self' type='application/atom+xml' + href='http://dm5.google.com/feeds/videos/rP3qL4UG1TI'></link> + <link rel='alternate' type='text/html' + href='http://www.youtube.com/watch?v=rP3qL4UG1TI'></link> + <link rel='http://gdata.youtube.com/schemas/2007#video.responses' + type='application/atom+xml' + href='http://dm5.google.com/feeds/videos/rP3qL4UG1TI/responses'></link> + <link rel='http://gdata.youtube.com/schemas/2007#video.ratings' + type='application/atom+xml' + href='http://dm5.google.com/feeds/videos/rP3qL4UG1TI/ratings'></link> + <author> + <name>Livemorningshow</name> + <uri>http://dm5.google.com/feeds/users/Livemorningshow</uri> + </author> + <media:group> + <media:title type='plain'>The Woody show "Aries Spears" rap + Live105.com + </media:title> + <media:description type='plain'>Live 105 Morning show "Aries Spears" + rap with Woody,Tony and Ravey. Edited By: + myspace.com/whitemenace + </media:description> + <media:keywords>Woody, Tony, Ravey, Live, 105, radio, morning, show, + Aries, Spears, JayZ, whitemenace, snoop, dog, Q101 + </media:keywords> + <yt:duration seconds='135'></yt:duration> + <media:category label='Entertainment' + scheme='http://gdata.youtube.com/schemas/2007/categories.cat'> + Entertainment + </media:category> + <media:player + url='http://www.youtube.com/watch?v=rP3qL4UG1TI'></media:player> + <media:thumbnail url='http://img.youtube.com/vi/rP3qL4UG1TI/2.jpg' + height='97' width='130' + time='00:01:07.500'></media:thumbnail> + <media:thumbnail url='http://img.youtube.com/vi/rP3qL4UG1TI/1.jpg' + height='97' width='130' + time='00:00:33.750'></media:thumbnail> + <media:thumbnail url='http://img.youtube.com/vi/rP3qL4UG1TI/3.jpg' + height='97' width='130' + time='00:01:41.250'></media:thumbnail> + <media:thumbnail url='http://img.youtube.com/vi/rP3qL4UG1TI/0.jpg' + height='240' width='320'></media:thumbnail> + </media:group> + <gd:rating min='1' max='5' numRaters='4856' average='4.90'></gd:rating> + <gd:feedLink rel='comments' + href='http://dm5.google.com/feeds/videos/rP3qL4UG1TI/comments'></gd:feedLink> + </entry> + <entry> + <id>http://dm5.google.com/feeds/videos/4NFiu-V7StQ</id> + <published>2006-05-19T17:11:52.000Z</published> + <updated>2006-05-19T17:11:52.000Z</updated> + <category scheme='http://gdata.youtube.com/schemas/2007/keywords.cat' + term='Sims'></category> + <category scheme='http://gdata.youtube.com/schemas/2007/keywords.cat' + term='Chemical'></category> + <category scheme='http://gdata.youtube.com/schemas/2007/categories.cat' + term='Film' label='Film & Animation'></category> + <category scheme='http://gdata.youtube.com/schemas/2007/keywords.cat' + term='Helena'></category> + <category scheme='http://gdata.youtube.com/schemas/2007/keywords.cat' + term='Jaydee'></category> + <category scheme='http://gdata.youtube.com/schemas/2007/keywords.cat' + term='Romance'></category> + <category scheme='http://gdata.youtube.com/schemas/2007/keywords.cat' + term='Movie'></category> + <category scheme='http://gdata.youtube.com/schemas/2007/keywords.cat' + term='MCR'></category> + <category scheme='http://gdata.youtube.com/schemas/2007/keywords.cat' + term='machinima'></category> + <category scheme='http://gdata.youtube.com/schemas/2007/keywords.cat' + term='My'></category> + <title type='text'>Helena - My Chemical Romance - Sims 2 version</title> + <link rel='self' type='application/atom+xml' + href='http://dm5.google.com/feeds/videos/4NFiu-V7StQ'></link> + <link rel='alternate' type='text/html' + href='http://www.youtube.com/watch?v=4NFiu-V7StQ'></link> + <link rel='http://gdata.youtube.com/schemas/2007#video.responses' + type='application/atom+xml' + href='http://dm5.google.com/feeds/videos/4NFiu-V7StQ/responses'></link> + <link rel='http://gdata.youtube.com/schemas/2007#video.ratings' + type='application/atom+xml' + href='http://dm5.google.com/feeds/videos/4NFiu-V7StQ/ratings'></link> + <author> + <name>jaydee227</name> + <uri>http://dm5.google.com/feeds/users/jaydee227</uri> + </author> + <media:group> + <media:title type='plain'>Helena - My Chemical Romance - Sims 2 + version + </media:title> + <media:description type='plain'>This is the 3rd sims movie I made. + you need to watch it carefully or you won't understand the + story. But hope you enjoy :) + + USEFUL LINKS: + + Explanations to the storyline: + http://www.jd-movies.com/helenaexplained.html + + List of the custom content: + http://www.jd-movies.com/helenacc.html + + Movie FAQ: + http://www.jd-movies.com/helenafaq.html + + Download link (MUCH better quality): + http://www.archive.org/download/helenasims2/Helena.wmv + </media:description> + <media:keywords>Helena, My, Chemical, Romance, MCR, Sims, Movie, + machinima, Jaydee + </media:keywords> + <yt:duration seconds='265'></yt:duration> + <media:category label='Film & Animation' + scheme='http://gdata.youtube.com/schemas/2007/categories.cat'> + Film + </media:category> + <media:player + url='http://www.youtube.com/watch?v=4NFiu-V7StQ'></media:player> + <media:thumbnail url='http://img.youtube.com/vi/4NFiu-V7StQ/2.jpg' + height='97' width='130' + time='00:02:12.500'></media:thumbnail> + <media:thumbnail url='http://img.youtube.com/vi/4NFiu-V7StQ/1.jpg' + height='97' width='130' + time='00:01:06.250'></media:thumbnail> + <media:thumbnail url='http://img.youtube.com/vi/4NFiu-V7StQ/3.jpg' + height='97' width='130' + time='00:03:18.750'></media:thumbnail> + <media:thumbnail url='http://img.youtube.com/vi/4NFiu-V7StQ/0.jpg' + height='240' width='320'></media:thumbnail> + </media:group> + <gd:rating min='1' max='5' numRaters='8446' average='4.89'></gd:rating> + <gd:feedLink rel='comments' + href='http://dm5.google.com/feeds/videos/4NFiu-V7StQ/comments'></gd:feedLink> + </entry> + <entry> + <id>http://dm5.google.com/feeds/videos/bGFXKYvH39I</id> + <published>2006-06-21T17:23:54.000Z</published> + <updated>2006-06-21T17:23:54.000Z</updated> + <category scheme='http://gdata.youtube.com/schemas/2007/keywords.cat' + term='Three'></category> + <category scheme='http://gdata.youtube.com/schemas/2007/categories.cat' + term='Music' label='Music'></category> + <category scheme='http://gdata.youtube.com/schemas/2007/keywords.cat' + term='grace'></category> + <category scheme='http://gdata.youtube.com/schemas/2007/keywords.cat' + term='days'></category> + <title type='text'>three days grace-Animal I Have Become</title> + <link rel='self' type='application/atom+xml' + href='http://dm5.google.com/feeds/videos/bGFXKYvH39I'></link> + <link rel='alternate' type='text/html' + href='http://www.youtube.com/watch?v=bGFXKYvH39I'></link> + <link rel='http://gdata.youtube.com/schemas/2007#video.responses' + type='application/atom+xml' + href='http://dm5.google.com/feeds/videos/bGFXKYvH39I/responses'></link> + <link rel='http://gdata.youtube.com/schemas/2007#video.ratings' + type='application/atom+xml' + href='http://dm5.google.com/feeds/videos/bGFXKYvH39I/ratings'></link> + <author> + <name>jollech69</name> + <uri>http://dm5.google.com/feeds/users/jollech69</uri> + </author> + <media:group> + <media:title type='plain'>three days grace-Animal I Have Become + </media:title> + <media:description type='plain'>By 3 days grace</media:description> + <media:keywords>Three, days, grace</media:keywords> + <yt:duration seconds='233'></yt:duration> + <media:category label='Music' + scheme='http://gdata.youtube.com/schemas/2007/categories.cat'> + Music + </media:category> + <media:player + url='http://www.youtube.com/watch?v=bGFXKYvH39I'></media:player> + <media:thumbnail url='http://img.youtube.com/vi/bGFXKYvH39I/2.jpg' + height='97' width='130' + time='00:01:56.500'></media:thumbnail> + <media:thumbnail url='http://img.youtube.com/vi/bGFXKYvH39I/1.jpg' + height='97' width='130' + time='00:00:58.250'></media:thumbnail> + <media:thumbnail url='http://img.youtube.com/vi/bGFXKYvH39I/3.jpg' + height='97' width='130' + time='00:02:54.750'></media:thumbnail> + <media:thumbnail url='http://img.youtube.com/vi/bGFXKYvH39I/0.jpg' + height='240' width='320'></media:thumbnail> + </media:group> + <gd:rating min='1' max='5' numRaters='5975' average='4.89'></gd:rating> + <gd:feedLink rel='comments' + href='http://dm5.google.com/feeds/videos/bGFXKYvH39I/comments'></gd:feedLink> + </entry> + <entry> + <id>http://dm5.google.com/feeds/videos/V1_OkegYtZI</id> + <published>2007-03-17T10:45:49.000Z</published> + <updated>2007-03-17T10:45:49.000Z</updated> + <category scheme='http://gdata.youtube.com/schemas/2007/keywords.cat' + term='series'></category> + <category scheme='http://gdata.youtube.com/schemas/2007/keywords.cat' + term='spoof'></category> + <category scheme='http://gdata.youtube.com/schemas/2007/keywords.cat' + term='dub'></category> + <category scheme='http://gdata.youtube.com/schemas/2007/keywords.cat' + term='abridged'></category> + <category scheme='http://gdata.youtube.com/schemas/2007/keywords.cat' + term='yugioh'></category> + <category scheme='http://gdata.youtube.com/schemas/2007/categories.cat' + term='Comedy' label='Comedy'></category> + <title type='text'>Yu-Gi-Oh: The Abridged Series - Episode 19</title> + <link rel='self' type='application/atom+xml' + href='http://dm5.google.com/feeds/videos/V1_OkegYtZI'></link> + <link rel='alternate' type='text/html' + href='http://www.youtube.com/watch?v=V1_OkegYtZI'></link> + <link rel='http://gdata.youtube.com/schemas/2007#video.responses' + type='application/atom+xml' + href='http://dm5.google.com/feeds/videos/V1_OkegYtZI/responses'></link> + <link rel='http://gdata.youtube.com/schemas/2007#video.ratings' + type='application/atom+xml' + href='http://dm5.google.com/feeds/videos/V1_OkegYtZI/ratings'></link> + <author> + <name>LittleKuriboh</name> + <uri>http://dm5.google.com/feeds/users/LittleKuriboh</uri> + </author> + <media:group> + <media:title type='plain'>Yu-Gi-Oh: The Abridged Series - Episode 19 + </media:title> + <media:description type='plain'>Imagine Yu-Gi-Oh condensed into + about nine minutes. That's basically what this is. + + Yu-Gi-Oh is the property of Konami and Kazuki Takahasi. + </media:description> + <media:keywords>yugioh, abridged, series, dub, spoof + </media:keywords> + <yt:duration seconds='513'></yt:duration> + <media:category label='Comedy' + scheme='http://gdata.youtube.com/schemas/2007/categories.cat'> + Comedy + </media:category> + <media:player + url='http://www.youtube.com/watch?v=V1_OkegYtZI'></media:player> + <media:thumbnail url='http://img.youtube.com/vi/V1_OkegYtZI/2.jpg' + height='97' width='130' + time='00:04:16.500'></media:thumbnail> + <media:thumbnail url='http://img.youtube.com/vi/V1_OkegYtZI/1.jpg' + height='97' width='130' + time='00:02:08.250'></media:thumbnail> + <media:thumbnail url='http://img.youtube.com/vi/V1_OkegYtZI/3.jpg' + height='97' width='130' + time='00:06:24.750'></media:thumbnail> + <media:thumbnail url='http://img.youtube.com/vi/V1_OkegYtZI/0.jpg' + height='240' width='320'></media:thumbnail> + </media:group> + <gd:rating min='1' max='5' numRaters='5912' average='4.89'></gd:rating> + <gd:feedLink rel='comments' + href='http://dm5.google.com/feeds/videos/V1_OkegYtZI/comments'></gd:feedLink> + </entry> + <entry> + <id>http://dm5.google.com/feeds/videos/1A42U-pKP0U</id> + <published>2006-06-02T16:38:18.000Z</published> + <updated>2006-06-02T16:38:18.000Z</updated> + <category scheme='http://gdata.youtube.com/schemas/2007/keywords.cat' + term='Inside'></category> + <category scheme='http://gdata.youtube.com/schemas/2007/categories.cat' + term='Music' label='Music'></category> + <category scheme='http://gdata.youtube.com/schemas/2007/keywords.cat' + term='FroM'></category> + <category scheme='http://gdata.youtube.com/schemas/2007/keywords.cat' + term='LP'></category> + <category scheme='http://gdata.youtube.com/schemas/2007/keywords.cat' + term='The'></category> + <title type='text'>â„¢[LINKIN PARK-From The Inside]â„¢</title> + <link rel='self' type='application/atom+xml' + href='http://dm5.google.com/feeds/videos/1A42U-pKP0U'></link> + <link rel='alternate' type='text/html' + href='http://www.youtube.com/watch?v=1A42U-pKP0U'></link> + <link rel='http://gdata.youtube.com/schemas/2007#video.responses' + type='application/atom+xml' + href='http://dm5.google.com/feeds/videos/1A42U-pKP0U/responses'></link> + <link rel='http://gdata.youtube.com/schemas/2007#video.ratings' + type='application/atom+xml' + href='http://dm5.google.com/feeds/videos/1A42U-pKP0U/ratings'></link> + <author> + <name>linkin2789</name> + <uri>http://dm5.google.com/feeds/users/linkin2789</uri> + </author> + <media:group> + <media:title type='plain'>â„¢[LINKIN PARK-From The Inside]â„¢ + </media:title> + <media:description type='plain'>Video de la canción From The Inside + de Linkin Park. + </media:description> + <media:keywords>LP, FroM, The, Inside</media:keywords> + <yt:duration seconds='175'></yt:duration> + <media:category label='Music' + scheme='http://gdata.youtube.com/schemas/2007/categories.cat'> + Music + </media:category> + <media:player + url='http://www.youtube.com/watch?v=1A42U-pKP0U'></media:player> + <media:thumbnail url='http://img.youtube.com/vi/1A42U-pKP0U/2.jpg' + height='97' width='130' + time='00:01:27.500'></media:thumbnail> + <media:thumbnail url='http://img.youtube.com/vi/1A42U-pKP0U/1.jpg' + height='97' width='130' + time='00:00:43.750'></media:thumbnail> + <media:thumbnail url='http://img.youtube.com/vi/1A42U-pKP0U/3.jpg' + height='97' width='130' + time='00:02:11.250'></media:thumbnail> + <media:thumbnail url='http://img.youtube.com/vi/1A42U-pKP0U/0.jpg' + height='240' width='320'></media:thumbnail> + </media:group> + <gd:rating min='1' max='5' numRaters='6824' average='4.89'></gd:rating> + <gd:feedLink rel='comments' + href='http://dm5.google.com/feeds/videos/1A42U-pKP0U/comments'></gd:feedLink> + </entry> + <entry> + <id>http://dm5.google.com/feeds/videos/s-7UX1xSEfU</id> + <published>2006-07-18T17:06:52.000Z</published> + <updated>2006-07-18T17:06:52.000Z</updated> + <category scheme='http://gdata.youtube.com/schemas/2007/keywords.cat' + term='spoof'></category> + <category scheme='http://gdata.youtube.com/schemas/2007/keywords.cat' + term='dub'></category> + <category scheme='http://gdata.youtube.com/schemas/2007/keywords.cat' + term='abridged'></category> + <category scheme='http://gdata.youtube.com/schemas/2007/keywords.cat' + term='yugioh'></category> + <category scheme='http://gdata.youtube.com/schemas/2007/categories.cat' + term='Comedy' label='Comedy'></category> + <category scheme='http://gdata.youtube.com/schemas/2007/keywords.cat' + term='yu-gi-oh'></category> + <category scheme='http://gdata.youtube.com/schemas/2007/keywords.cat' + term='anime'></category> + <title type='text'>Yu-Gi-Oh: The Abridged Series (Episode 3)</title> + <link rel='self' type='application/atom+xml' + href='http://dm5.google.com/feeds/videos/s-7UX1xSEfU'></link> + <link rel='alternate' type='text/html' + href='http://www.youtube.com/watch?v=s-7UX1xSEfU'></link> + <link rel='http://gdata.youtube.com/schemas/2007#video.responses' + type='application/atom+xml' + href='http://dm5.google.com/feeds/videos/s-7UX1xSEfU/responses'></link> + <link rel='http://gdata.youtube.com/schemas/2007#video.ratings' + type='application/atom+xml' + href='http://dm5.google.com/feeds/videos/s-7UX1xSEfU/ratings'></link> + <author> + <name>LittleKuriboh</name> + <uri>http://dm5.google.com/feeds/users/LittleKuriboh</uri> + </author> + <media:group> + <media:title type='plain'>Yu-Gi-Oh: The Abridged Series (Episode 3) + </media:title> + <media:description type='plain'>Imagine "Yu-Gi-Oh" condensed into + four minutes. That's basically what this is. + </media:description> + <media:keywords>yugioh, yu-gi-oh, dub, spoof, anime, abridged + </media:keywords> + <yt:duration seconds='273'></yt:duration> + <media:category label='Comedy' + scheme='http://gdata.youtube.com/schemas/2007/categories.cat'> + Comedy + </media:category> + <media:player + url='http://www.youtube.com/watch?v=s-7UX1xSEfU'></media:player> + <media:thumbnail url='http://img.youtube.com/vi/s-7UX1xSEfU/2.jpg' + height='97' width='130' + time='00:02:16.500'></media:thumbnail> + <media:thumbnail url='http://img.youtube.com/vi/s-7UX1xSEfU/1.jpg' + height='97' width='130' + time='00:01:08.250'></media:thumbnail> + <media:thumbnail url='http://img.youtube.com/vi/s-7UX1xSEfU/3.jpg' + height='97' width='130' + time='00:03:24.750'></media:thumbnail> + <media:thumbnail url='http://img.youtube.com/vi/s-7UX1xSEfU/0.jpg' + height='240' width='320'></media:thumbnail> + </media:group> + <gd:rating min='1' max='5' numRaters='5907' average='4.89'></gd:rating> + <gd:feedLink rel='comments' + href='http://dm5.google.com/feeds/videos/s-7UX1xSEfU/comments'></gd:feedLink> + </entry> + <entry> + <id>http://dm5.google.com/feeds/videos/V6k3YlcYtS0</id> + <published>2006-08-05T22:15:41.000Z</published> + <updated>2006-08-05T22:15:41.000Z</updated> + <category scheme='http://gdata.youtube.com/schemas/2007/keywords.cat' + term='spoof'></category> + <category scheme='http://gdata.youtube.com/schemas/2007/keywords.cat' + term='dub'></category> + <category scheme='http://gdata.youtube.com/schemas/2007/keywords.cat' + term='abridged'></category> + <category scheme='http://gdata.youtube.com/schemas/2007/keywords.cat' + term='yugioh'></category> + <category scheme='http://gdata.youtube.com/schemas/2007/categories.cat' + term='Comedy' label='Comedy'></category> + <category scheme='http://gdata.youtube.com/schemas/2007/keywords.cat' + term='yu-gi-oh'></category> + <category scheme='http://gdata.youtube.com/schemas/2007/keywords.cat' + term='anime'></category> + <title type='text'>Yu-Gi-Oh: The Abridged Series (Episode 6)</title> + <link rel='self' type='application/atom+xml' + href='http://dm5.google.com/feeds/videos/V6k3YlcYtS0'></link> + <link rel='alternate' type='text/html' + href='http://www.youtube.com/watch?v=V6k3YlcYtS0'></link> + <link rel='http://gdata.youtube.com/schemas/2007#video.responses' + type='application/atom+xml' + href='http://dm5.google.com/feeds/videos/V6k3YlcYtS0/responses'></link> + <link rel='http://gdata.youtube.com/schemas/2007#video.ratings' + type='application/atom+xml' + href='http://dm5.google.com/feeds/videos/V6k3YlcYtS0/ratings'></link> + <author> + <name>LittleKuriboh</name> + <uri>http://dm5.google.com/feeds/users/LittleKuriboh</uri> + </author> + <media:group> + <media:title type='plain'>Yu-Gi-Oh: The Abridged Series (Episode 6) + </media:title> + <media:description type='plain'>Imagine "Yu-Gi-Oh" condensed into + four... uh, six minutes. That's basically what this is. + + Yu-Gi-Oh belongs to Kazuki Takahashi + </media:description> + <media:keywords>yu-gi-oh, yugioh, abridged, dub, spoof, anime + </media:keywords> + <yt:duration seconds='355'></yt:duration> + <media:category label='Comedy' + scheme='http://gdata.youtube.com/schemas/2007/categories.cat'> + Comedy + </media:category> + <media:player + url='http://www.youtube.com/watch?v=V6k3YlcYtS0'></media:player> + <media:thumbnail url='http://img.youtube.com/vi/V6k3YlcYtS0/2.jpg' + height='97' width='130' + time='00:02:57.500'></media:thumbnail> + <media:thumbnail url='http://img.youtube.com/vi/V6k3YlcYtS0/1.jpg' + height='97' width='130' + time='00:01:28.750'></media:thumbnail> + <media:thumbnail url='http://img.youtube.com/vi/V6k3YlcYtS0/3.jpg' + height='97' width='130' + time='00:04:26.250'></media:thumbnail> + <media:thumbnail url='http://img.youtube.com/vi/V6k3YlcYtS0/0.jpg' + height='240' width='320'></media:thumbnail> + </media:group> + <gd:rating min='1' max='5' numRaters='6447' average='4.89'></gd:rating> + <gd:feedLink rel='comments' + href='http://dm5.google.com/feeds/videos/V6k3YlcYtS0/comments'></gd:feedLink> + </entry> + <entry> + <id>http://dm5.google.com/feeds/videos/HTKs5ZT16PM</id> + <published>2006-10-23T18:15:56.000Z</published> + <updated>2006-10-23T18:15:56.000Z</updated> + <category scheme='http://gdata.youtube.com/schemas/2007/keywords.cat' + term='series'></category> + <category scheme='http://gdata.youtube.com/schemas/2007/keywords.cat' + term='spoof'></category> + <category scheme='http://gdata.youtube.com/schemas/2007/keywords.cat' + term='dub'></category> + <category scheme='http://gdata.youtube.com/schemas/2007/keywords.cat' + term='abridged'></category> + <category scheme='http://gdata.youtube.com/schemas/2007/keywords.cat' + term='yugioh'></category> + <category scheme='http://gdata.youtube.com/schemas/2007/categories.cat' + term='Comedy' label='Comedy'></category> + <category scheme='http://gdata.youtube.com/schemas/2007/keywords.cat' + term='anime'></category> + <title type='text'>Yu-Gi-Oh: The Abridged Series (Episode 13)</title> + <link rel='self' type='application/atom+xml' + href='http://dm5.google.com/feeds/videos/HTKs5ZT16PM'></link> + <link rel='alternate' type='text/html' + href='http://www.youtube.com/watch?v=HTKs5ZT16PM'></link> + <link rel='http://gdata.youtube.com/schemas/2007#video.responses' + type='application/atom+xml' + href='http://dm5.google.com/feeds/videos/HTKs5ZT16PM/responses'></link> + <link rel='http://gdata.youtube.com/schemas/2007#video.ratings' + type='application/atom+xml' + href='http://dm5.google.com/feeds/videos/HTKs5ZT16PM/ratings'></link> + <author> + <name>LittleKuriboh</name> + <uri>http://dm5.google.com/feeds/users/LittleKuriboh</uri> + </author> + <media:group> + <media:title type='plain'>Yu-Gi-Oh: The Abridged Series (Episode 13) + </media:title> + <media:description type='plain'>Please ignore the imposter videos. + + Imagine "Yu-Gi-Oh" condensed into five/six minutes. That's + basically what this is. + + Yu-Gi-Oh belongs to Kazuki Takahashi + </media:description> + <media:keywords>yugioh, abridged, series, anime, spoof, dub + </media:keywords> + <yt:duration seconds='349'></yt:duration> + <media:category label='Comedy' + scheme='http://gdata.youtube.com/schemas/2007/categories.cat'> + Comedy + </media:category> + <media:player + url='http://www.youtube.com/watch?v=HTKs5ZT16PM'></media:player> + <media:thumbnail url='http://img.youtube.com/vi/HTKs5ZT16PM/2.jpg' + height='97' width='130' + time='00:02:54.500'></media:thumbnail> + <media:thumbnail url='http://img.youtube.com/vi/HTKs5ZT16PM/1.jpg' + height='97' width='130' + time='00:01:27.250'></media:thumbnail> + <media:thumbnail url='http://img.youtube.com/vi/HTKs5ZT16PM/3.jpg' + height='97' width='130' + time='00:04:21.750'></media:thumbnail> + <media:thumbnail url='http://img.youtube.com/vi/HTKs5ZT16PM/0.jpg' + height='240' width='320'></media:thumbnail> + </media:group> + <gd:rating min='1' max='5' numRaters='7255' average='4.89'></gd:rating> + <gd:feedLink rel='comments' + href='http://dm5.google.com/feeds/videos/HTKs5ZT16PM/comments'></gd:feedLink> + </entry> + <entry> + <id>http://dm5.google.com/feeds/videos/MePzWtHqrso</id> + <published>2006-06-28T00:21:59.000Z</published> + <updated>2006-06-28T00:21:59.000Z</updated> + <category scheme='http://gdata.youtube.com/schemas/2007/keywords.cat' + term='Benjamin'></category> + <category scheme='http://gdata.youtube.com/schemas/2007/keywords.cat' + term='Breaking'></category> + <category scheme='http://gdata.youtube.com/schemas/2007/categories.cat' + term='Music' label='Music'></category> + <category scheme='http://gdata.youtube.com/schemas/2007/keywords.cat' + term='Diary'></category> + <category scheme='http://gdata.youtube.com/schemas/2007/keywords.cat' + term='Jane'></category> + <title type='text'>Breaking Benjamin - "The Diary of Jane"</title> + <link rel='self' type='application/atom+xml' + href='http://dm5.google.com/feeds/videos/MePzWtHqrso'></link> + <link rel='alternate' type='text/html' + href='http://www.youtube.com/watch?v=MePzWtHqrso'></link> + <link rel='http://gdata.youtube.com/schemas/2007#video.responses' + type='application/atom+xml' + href='http://dm5.google.com/feeds/videos/MePzWtHqrso/responses'></link> + <link rel='http://gdata.youtube.com/schemas/2007#video.ratings' + type='application/atom+xml' + href='http://dm5.google.com/feeds/videos/MePzWtHqrso/ratings'></link> + <author> + <name>BrienTA</name> + <uri>http://dm5.google.com/feeds/users/BrienTA</uri> + </author> + <media:group> + <media:title type='plain'>Breaking Benjamin - "The Diary of Jane" + </media:title> + <media:description type='plain'>Breaking Benjamin - "The Diary of + Jane" + </media:description> + <media:keywords>Breaking, Benjamin, Diary, Jane</media:keywords> + <yt:duration seconds='207'></yt:duration> + <media:category label='Music' + scheme='http://gdata.youtube.com/schemas/2007/categories.cat'> + Music + </media:category> + <media:player + url='http://www.youtube.com/watch?v=MePzWtHqrso'></media:player> + <media:thumbnail url='http://img.youtube.com/vi/MePzWtHqrso/2.jpg' + height='97' width='130' + time='00:01:43.500'></media:thumbnail> + <media:thumbnail url='http://img.youtube.com/vi/MePzWtHqrso/1.jpg' + height='97' width='130' + time='00:00:51.750'></media:thumbnail> + <media:thumbnail url='http://img.youtube.com/vi/MePzWtHqrso/3.jpg' + height='97' width='130' + time='00:02:35.250'></media:thumbnail> + <media:thumbnail url='http://img.youtube.com/vi/MePzWtHqrso/0.jpg' + height='240' width='320'></media:thumbnail> + </media:group> + <gd:rating min='1' max='5' numRaters='6298' average='4.89'></gd:rating> + <gd:feedLink rel='comments' + href='http://dm5.google.com/feeds/videos/MePzWtHqrso/comments'></gd:feedLink> + </entry> + <entry> + <id>http://dm5.google.com/feeds/videos/ElrldD02if0</id> + <published>2006-11-20T19:41:52.000Z</published> + <updated>2006-11-20T19:41:52.000Z</updated> + <category scheme='http://gdata.youtube.com/schemas/2007/keywords.cat' + term='ms.paint'></category> + <category scheme='http://gdata.youtube.com/schemas/2007/keywords.cat' + term='paint'></category> + <category scheme='http://gdata.youtube.com/schemas/2007/keywords.cat' + term='how'></category> + <category scheme='http://gdata.youtube.com/schemas/2007/keywords.cat' + term='good'></category> + <category scheme='http://gdata.youtube.com/schemas/2007/keywords.cat' + term='automobile'></category> + <category scheme='http://gdata.youtube.com/schemas/2007/keywords.cat' + term='custom'></category> + <category scheme='http://gdata.youtube.com/schemas/2007/keywords.cat' + term='art'></category> + <category scheme='http://gdata.youtube.com/schemas/2007/keywords.cat' + term='comaro'></category> + <category scheme='http://gdata.youtube.com/schemas/2007/keywords.cat' + term='foose'></category> + <category scheme='http://gdata.youtube.com/schemas/2007/keywords.cat' + term='chip'></category> + <category scheme='http://gdata.youtube.com/schemas/2007/keywords.cat' + term='artistic'></category> + <category scheme='http://gdata.youtube.com/schemas/2007/keywords.cat' + term='concept'></category> + <category scheme='http://gdata.youtube.com/schemas/2007/keywords.cat' + term='great'></category> + <category scheme='http://gdata.youtube.com/schemas/2007/keywords.cat' + term='awsome'></category> + <category scheme='http://gdata.youtube.com/schemas/2007/categories.cat' + term='Film' label='Film & Animation'></category> + <category scheme='http://gdata.youtube.com/schemas/2007/keywords.cat' + term='design'></category> + <category scheme='http://gdata.youtube.com/schemas/2007/keywords.cat' + term='draw'></category> + <category scheme='http://gdata.youtube.com/schemas/2007/keywords.cat' + term='car'></category> + <title type='text'>Re: How to draw a car in MS. Paint</title> + <link rel='self' type='application/atom+xml' + href='http://dm5.google.com/feeds/videos/ElrldD02if0'></link> + <link rel='alternate' type='text/html' + href='http://www.youtube.com/watch?v=ElrldD02if0'></link> + <link rel='http://gdata.youtube.com/schemas/2007#video.responses' + type='application/atom+xml' + href='http://dm5.google.com/feeds/videos/ElrldD02if0/responses'></link> + <link rel='http://gdata.youtube.com/schemas/2007#video.ratings' + type='application/atom+xml' + href='http://dm5.google.com/feeds/videos/ElrldD02if0/ratings'></link> + <author> + <name>picster</name> + <uri>http://dm5.google.com/feeds/users/picster</uri> + </author> + <media:group> + <media:title type='plain'>Re: How to draw a car in MS. Paint + </media:title> + <media:description type='plain'>WATCH MY NEW VIDEO!!!! + http://www.youtube.com/watch?v=vUWqRhReaZk + + ---- + Wow! So many nice comments and views :) + I'm very happy you all like it. + + And thank you very much for all the nice emails! + </media:description> + <media:keywords>car, art, paint, draw, automobile, comaro, custom, + concept, how, ms.paint, great, good, awsome, design, artistic, + chip, foose + </media:keywords> + <yt:duration seconds='318'></yt:duration> + <media:category label='Film & Animation' + scheme='http://gdata.youtube.com/schemas/2007/categories.cat'> + Film + </media:category> + <media:player + url='http://www.youtube.com/watch?v=ElrldD02if0'></media:player> + <media:thumbnail url='http://img.youtube.com/vi/ElrldD02if0/2.jpg' + height='97' width='130' + time='00:02:39'></media:thumbnail> + <media:thumbnail url='http://img.youtube.com/vi/ElrldD02if0/1.jpg' + height='97' width='130' + time='00:01:19.500'></media:thumbnail> + <media:thumbnail url='http://img.youtube.com/vi/ElrldD02if0/3.jpg' + height='97' width='130' + time='00:03:58.500'></media:thumbnail> + <media:thumbnail url='http://img.youtube.com/vi/ElrldD02if0/0.jpg' + height='240' width='320'></media:thumbnail> + </media:group> + <gd:rating min='1' max='5' numRaters='9986' average='4.88'></gd:rating> + <gd:feedLink rel='comments' + href='http://dm5.google.com/feeds/videos/ElrldD02if0/comments'></gd:feedLink> + </entry> + <entry> + <id>http://dm5.google.com/feeds/videos/Ox0c_1l9al4</id> + <published>2006-07-04T01:56:27.000Z</published> + <updated>2006-07-04T01:56:27.000Z</updated> + <category scheme='http://gdata.youtube.com/schemas/2007/keywords.cat' + term='Cook'></category> + <category scheme='http://gdata.youtube.com/schemas/2007/keywords.cat' + term='Naruto'></category> + <category scheme='http://gdata.youtube.com/schemas/2007/keywords.cat' + term='Dane'></category> + <category scheme='http://gdata.youtube.com/schemas/2007/categories.cat' + term='Comedy' label='Comedy'></category> + <title type='text'>AMV Comedians 2 (Dane Cook)</title> + <link rel='self' type='application/atom+xml' + href='http://dm5.google.com/feeds/videos/Ox0c_1l9al4'></link> + <link rel='alternate' type='text/html' + href='http://www.youtube.com/watch?v=Ox0c_1l9al4'></link> + <link rel='http://gdata.youtube.com/schemas/2007#video.responses' + type='application/atom+xml' + href='http://dm5.google.com/feeds/videos/Ox0c_1l9al4/responses'></link> + <link rel='http://gdata.youtube.com/schemas/2007#video.ratings' + type='application/atom+xml' + href='http://dm5.google.com/feeds/videos/Ox0c_1l9al4/ratings'></link> + <author> + <name>Rubix89</name> + <uri>http://dm5.google.com/feeds/users/Rubix89</uri> + </author> + <media:group> + <media:title type='plain'>AMV Comedians 2 (Dane Cook)</media:title> + <media:description type='plain'>Anime: Naruto + Comedian: Dane Cook + I know I already did Dane Cook, but I couldnt pass up this joke. + http://www.animemusicvideos.org/members/members_videoinfo.php?v=130820 + </media:description> + <media:keywords>Naruto, Dane, Cook</media:keywords> + <yt:duration seconds='126'></yt:duration> + <media:category label='Comedy' + scheme='http://gdata.youtube.com/schemas/2007/categories.cat'> + Comedy + </media:category> + <media:player + url='http://www.youtube.com/watch?v=Ox0c_1l9al4'></media:player> + <media:thumbnail url='http://img.youtube.com/vi/Ox0c_1l9al4/2.jpg' + height='97' width='130' + time='00:01:03'></media:thumbnail> + <media:thumbnail url='http://img.youtube.com/vi/Ox0c_1l9al4/1.jpg' + height='97' width='130' + time='00:00:31.500'></media:thumbnail> + <media:thumbnail url='http://img.youtube.com/vi/Ox0c_1l9al4/3.jpg' + height='97' width='130' + time='00:01:34.500'></media:thumbnail> + <media:thumbnail url='http://img.youtube.com/vi/Ox0c_1l9al4/0.jpg' + height='240' width='320'></media:thumbnail> + </media:group> + <gd:rating min='1' max='5' numRaters='6727' average='4.89'></gd:rating> + <gd:feedLink rel='comments' + href='http://dm5.google.com/feeds/videos/Ox0c_1l9al4/comments'></gd:feedLink> + </entry> +</feed> diff --git a/tests/AndroidTests/res/values-12key/configVarying.xml b/tests/AndroidTests/res/values-12key/configVarying.xml new file mode 100644 index 0000000..14ce1a7 --- /dev/null +++ b/tests/AndroidTests/res/values-12key/configVarying.xml @@ -0,0 +1,26 @@ +<?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. +--> + +<resources> + <item type="configVarying" name="simple">simple 12key</item> + <bag type="configVarying" name="bag"> + <item name="testString">bag 12key</item> + </bag> + <item type="configVarying" name="simple_12key">only simple 12key</item> + <bag type="configVarying" name="bag_12key"> + <item name="testString">only bag 12key</item> + </bag> +</resources> diff --git a/tests/AndroidTests/res/values-320x200/configVarying.xml b/tests/AndroidTests/res/values-320x200/configVarying.xml new file mode 100644 index 0000000..035e55e --- /dev/null +++ b/tests/AndroidTests/res/values-320x200/configVarying.xml @@ -0,0 +1,26 @@ +<?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. +--> + +<resources> + <item type="configVarying" name="simple">simple 320x200</item> + <bag type="configVarying" name="bag"> + <item name="testString">bag 320x200</item> + </bag> + <item type="configVarying" name="simple_320x200">only simple 320x200</item> + <bag type="configVarying" name="bag_320x200"> + <item name="testString">only bag 320x200</item> + </bag> +</resources> diff --git a/tests/AndroidTests/res/values-480x320/configVarying.xml b/tests/AndroidTests/res/values-480x320/configVarying.xml new file mode 100644 index 0000000..8b28d89 --- /dev/null +++ b/tests/AndroidTests/res/values-480x320/configVarying.xml @@ -0,0 +1,26 @@ +<?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. +--> + +<resources> + <item type="configVarying" name="simple">simple 480x320</item> + <bag type="configVarying" name="bag"> + <item name="testString">bag 480x320</item> + </bag> + <item type="configVarying" name="simple_480x320">only simple 480x320</item> + <bag type="configVarying" name="bag_480x320"> + <item name="testString">only bag 480x320</item> + </bag> +</resources> diff --git a/tests/AndroidTests/res/values-cs/strings.xml b/tests/AndroidTests/res/values-cs/strings.xml new file mode 100644 index 0000000..bd402c7 --- /dev/null +++ b/tests/AndroidTests/res/values-cs/strings.xml @@ -0,0 +1,25 @@ +<?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. +--> + +<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + + <plurals name="plurals_test"> + <item quantity="one">A Czech dog</item> + <item quantity="few">Few Czech dogs</item> + <item quantity="other">Some Czech dogs</item> + </plurals> +</resources> + diff --git a/tests/AndroidTests/res/values-dpad/configVarying.xml b/tests/AndroidTests/res/values-dpad/configVarying.xml new file mode 100644 index 0000000..c8d5767 --- /dev/null +++ b/tests/AndroidTests/res/values-dpad/configVarying.xml @@ -0,0 +1,22 @@ +<?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. +--> + +<resources> + <item type="configVarying" name="simple">simple dpad</item> + <bag type="configVarying" name="bag"> + <item name="testString">bag dpad</item> + </bag> +</resources> diff --git a/tests/AndroidTests/res/values-finger/configVarying.xml b/tests/AndroidTests/res/values-finger/configVarying.xml new file mode 100644 index 0000000..efe4758 --- /dev/null +++ b/tests/AndroidTests/res/values-finger/configVarying.xml @@ -0,0 +1,26 @@ +<?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. +--> + +<resources> + <item type="configVarying" name="simple">simple finger</item> + <bag type="configVarying" name="bag"> + <item name="testString">bag finger</item> + </bag> + <item type="configVarying" name="simple_finger">only simple finger</item> + <bag type="configVarying" name="bag_finger"> + <item name="testString">only bag finger</item> + </bag> +</resources> diff --git a/tests/AndroidTests/res/values-keysexposed/configVarying.xml b/tests/AndroidTests/res/values-keysexposed/configVarying.xml new file mode 100644 index 0000000..2380e7e --- /dev/null +++ b/tests/AndroidTests/res/values-keysexposed/configVarying.xml @@ -0,0 +1,22 @@ +<?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. +--> + +<resources> + <item type="configVarying" name="simple">simple keysexposed</item> + <bag type="configVarying" name="bag"> + <item name="testString">bag keysexposed</item> + </bag> +</resources> diff --git a/tests/AndroidTests/res/values-keyshidden/configVarying.xml b/tests/AndroidTests/res/values-keyshidden/configVarying.xml new file mode 100644 index 0000000..fdffc4d --- /dev/null +++ b/tests/AndroidTests/res/values-keyshidden/configVarying.xml @@ -0,0 +1,22 @@ +<?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. +--> + +<resources> + <item type="configVarying" name="simple">simple keyshidden</item> + <bag type="configVarying" name="bag"> + <item name="testString">bag keyshidden</item> + </bag> +</resources> diff --git a/tests/AndroidTests/res/values-mcc111/configVarying.xml b/tests/AndroidTests/res/values-mcc111/configVarying.xml new file mode 100644 index 0000000..16b13a5 --- /dev/null +++ b/tests/AndroidTests/res/values-mcc111/configVarying.xml @@ -0,0 +1,26 @@ +<?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. +--> + +<resources> + <item type="configVarying" name="simple">simple mcc111</item> + <bag type="configVarying" name="bag"> + <item name="testString">bag mcc111</item> + </bag> + <item type="configVarying" name="simple_mcc111">only simple mcc111</item> + <bag type="configVarying" name="bag_mcc111"> + <item name="testString">only bag mcc111</item> + </bag> +</resources> diff --git a/tests/AndroidTests/res/values-mnc222/configVarying.xml b/tests/AndroidTests/res/values-mnc222/configVarying.xml new file mode 100644 index 0000000..7f68729 --- /dev/null +++ b/tests/AndroidTests/res/values-mnc222/configVarying.xml @@ -0,0 +1,26 @@ +<?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. +--> + +<resources> + <item type="configVarying" name="simple">simple mnc222</item> + <bag type="configVarying" name="bag"> + <item name="testString">bag mnc222</item> + </bag> + <item type="configVarying" name="simple_mnc222">only simple mnc222</item> + <bag type="configVarying" name="bag_mnc222"> + <item name="testString">only bag mnc222</item> + </bag> +</resources> diff --git a/tests/AndroidTests/res/values-nokeys/configVarying.xml b/tests/AndroidTests/res/values-nokeys/configVarying.xml new file mode 100644 index 0000000..71f7e0b --- /dev/null +++ b/tests/AndroidTests/res/values-nokeys/configVarying.xml @@ -0,0 +1,22 @@ +<?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. +--> + +<resources> + <item type="configVarying" name="simple">simple nokeys</item> + <bag type="configVarying" name="bag"> + <item name="testString">bag nokeys</item> + </bag> +</resources> diff --git a/tests/AndroidTests/res/values-nonav/configVarying.xml b/tests/AndroidTests/res/values-nonav/configVarying.xml new file mode 100644 index 0000000..1254920 --- /dev/null +++ b/tests/AndroidTests/res/values-nonav/configVarying.xml @@ -0,0 +1,22 @@ +<?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. +--> + +<resources> + <item type="configVarying" name="simple">simple nonav</item> + <bag type="configVarying" name="bag"> + <item name="testString">bag nonav</item> + </bag> +</resources> diff --git a/tests/AndroidTests/res/values-notouch/configVarying.xml b/tests/AndroidTests/res/values-notouch/configVarying.xml new file mode 100644 index 0000000..8a71de4 --- /dev/null +++ b/tests/AndroidTests/res/values-notouch/configVarying.xml @@ -0,0 +1,26 @@ +<?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. +--> + +<resources> + <item type="configVarying" name="simple">simple notouch</item> + <bag type="configVarying" name="bag"> + <item name="testString">bag notouch</item> + </bag> + <item type="configVarying" name="simple_notouch">only simple notouch</item> + <bag type="configVarying" name="bag_notouch"> + <item name="testString">only bag notouch</item> + </bag> +</resources> diff --git a/tests/AndroidTests/res/values-qwerty/configVarying.xml b/tests/AndroidTests/res/values-qwerty/configVarying.xml new file mode 100644 index 0000000..939f682 --- /dev/null +++ b/tests/AndroidTests/res/values-qwerty/configVarying.xml @@ -0,0 +1,22 @@ +<?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. +--> + +<resources> + <item type="configVarying" name="simple">simple qwerty</item> + <bag type="configVarying" name="bag"> + <item name="testString">bag qwerty</item> + </bag> +</resources> diff --git a/tests/AndroidTests/res/values-stylus/configVarying.xml b/tests/AndroidTests/res/values-stylus/configVarying.xml new file mode 100644 index 0000000..87df119 --- /dev/null +++ b/tests/AndroidTests/res/values-stylus/configVarying.xml @@ -0,0 +1,26 @@ +<?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. +--> + +<resources> + <item type="configVarying" name="simple">simple stylus</item> + <bag type="configVarying" name="bag"> + <item name="testString">bag stylus</item> + </bag> + <item type="configVarying" name="simple_stylus">only simple stylus</item> + <bag type="configVarying" name="bag_stylus"> + <item name="testString">only bag stylus</item> + </bag> +</resources> diff --git a/tests/AndroidTests/res/values-trackball/configVarying.xml b/tests/AndroidTests/res/values-trackball/configVarying.xml new file mode 100644 index 0000000..0dec300 --- /dev/null +++ b/tests/AndroidTests/res/values-trackball/configVarying.xml @@ -0,0 +1,22 @@ +<?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. +--> + +<resources> + <item type="configVarying" name="simple">simple trackball</item> + <bag type="configVarying" name="bag"> + <item name="testString">bag trackball</item> + </bag> +</resources> diff --git a/tests/AndroidTests/res/values-wheel/configVarying.xml b/tests/AndroidTests/res/values-wheel/configVarying.xml new file mode 100644 index 0000000..6164855 --- /dev/null +++ b/tests/AndroidTests/res/values-wheel/configVarying.xml @@ -0,0 +1,22 @@ +<?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. +--> + +<resources> + <item type="configVarying" name="simple">simple wheel</item> + <bag type="configVarying" name="bag"> + <item name="testString">bag wheel</item> + </bag> +</resources> diff --git a/tests/AndroidTests/res/values-xx-rYY/configVarying.xml b/tests/AndroidTests/res/values-xx-rYY/configVarying.xml new file mode 100644 index 0000000..4e52db9 --- /dev/null +++ b/tests/AndroidTests/res/values-xx-rYY/configVarying.xml @@ -0,0 +1,26 @@ +<?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. +--> + +<resources> + <item type="configVarying" name="simple">simple xx-rYY</item> + <bag type="configVarying" name="bag"> + <item name="testString">bag xx-rYY</item> + </bag> + <item type="configVarying" name="simple_xx_rYY">only simple xx_rYY</item> + <bag type="configVarying" name="bag_xx_rYY"> + <item name="testString">only bag xx_rYY</item> + </bag> +</resources> diff --git a/tests/AndroidTests/res/values-xx/configVarying.xml b/tests/AndroidTests/res/values-xx/configVarying.xml new file mode 100644 index 0000000..e50649d --- /dev/null +++ b/tests/AndroidTests/res/values-xx/configVarying.xml @@ -0,0 +1,26 @@ +<?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. +--> + +<resources> + <item type="configVarying" name="simple">simple xx</item> + <bag type="configVarying" name="bag"> + <item name="testString">bag xx</item> + </bag> + <item type="configVarying" name="simple_xx">only simple xx</item> + <bag type="configVarying" name="bag_xx"> + <item name="testString">only bag xx</item> + </bag> +</resources> diff --git a/tests/AndroidTests/res/values/arrays.xml b/tests/AndroidTests/res/values/arrays.xml new file mode 100644 index 0000000..20ab407 --- /dev/null +++ b/tests/AndroidTests/res/values/arrays.xml @@ -0,0 +1,42 @@ +<?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. +--> + +<resources> + <item type="integer" name="reference" format="integer">101</item> + + <!-- + <array name="generic"> + <item>zero</item> + <item>1</item> + <item>@string/reference</item> + </array> + <array name="genericStrings" format="string"> + <item>zero</item> + <item>1</item> + <item>@string/reference</item> + </array> + --> + <string-array name="strings"> + <item>zero</item> + <item>1</item> + <item>@string/reference</item> + </string-array> + <integer-array name="integers"> + <item>0</item> + <item>1</item> + <item>@integer/reference</item> + </integer-array> +</resources> diff --git a/tests/AndroidTests/res/values/attrs.xml b/tests/AndroidTests/res/values/attrs.xml new file mode 100644 index 0000000..d3a31ca --- /dev/null +++ b/tests/AndroidTests/res/values/attrs.xml @@ -0,0 +1,44 @@ +<?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. +--> + +<resources> + <attr name="testEnum"> + <enum name="val1" value="1" /> + <enum name="val2" value="2" /> + <enum name="val10" value="10" /> + </attr> + + <attr name="testFlags"> + <flag name="bit1" value="0x1" /> + <flag name="bit2" value="0x2" /> + <flag name="bit31" value="0x40000000" /> + </attr> + + <attr name="testString" format="string" /> + + <declare-styleable name="EnumStyle"> + <attr name="testEnum" /> + </declare-styleable> + + <declare-styleable name="FlagStyle"> + <attr name="testFlags" /> + </declare-styleable> + + <declare-styleable name="TestConfig"> + <attr name="testString" /> + </declare-styleable> +</resources> + diff --git a/tests/AndroidTests/res/values/bools.xml b/tests/AndroidTests/res/values/bools.xml new file mode 100644 index 0000000..ffa8955 --- /dev/null +++ b/tests/AndroidTests/res/values/bools.xml @@ -0,0 +1,20 @@ +<?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. +--> + +<resources> + <bool name="trueRes">true</bool> + <bool name="falseRes">false</bool> +</resources> diff --git a/tests/AndroidTests/res/values/configVarying.xml b/tests/AndroidTests/res/values/configVarying.xml new file mode 100644 index 0000000..c4a20ad --- /dev/null +++ b/tests/AndroidTests/res/values/configVarying.xml @@ -0,0 +1,27 @@ +<?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. +--> + +<resources> + <item type="configVarying" name="simple">simple default</item> + <bag type="configVarying" name="bag"> + <item name="testString">bag default</item> + </bag> + + <item type="configVarying" name="simple_default">only simple default</item> + <bag type="configVarying" name="bag_default"> + <item name="testString">only bag default</item> + </bag> +</resources> diff --git a/tests/AndroidTests/res/values/dimens.xml b/tests/AndroidTests/res/values/dimens.xml new file mode 100644 index 0000000..72d1010 --- /dev/null +++ b/tests/AndroidTests/res/values/dimens.xml @@ -0,0 +1,42 @@ +<?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. +--> + +<resources> + <item name="frac100perc" type="dimen" format="fraction">100%</item> + <item name="frac1perc" type="dimen" format="fraction">1%</item> + <item name="fracp1perc" type="dimen" format="fraction">.1%</item> + <item name="fracp01perc" type="dimen" format="fraction">.01%</item> + <item name="frac0perc" type="dimen" format="fraction">0%</item> + <item name="frac1p1perc" type="dimen" format="fraction">1.1%</item> + <item name="frac100p1perc" type="dimen" format="fraction">100.1%</item> + <item name="frac25510perc" type="dimen" format="fraction">25510%</item> + <item name="frac25610perc" type="dimen" format="fraction">25610%</item> + <item name="frac6553510perc" type="dimen" format="fraction">6553510%</item> + <item name="frac6553610perc" type="dimen" format="fraction">6553610%</item> + + <item name="frac100pperc" type="dimen" format="fraction">100%p</item> + <item name="frac1pperc" type="dimen" format="fraction">1%p</item> + <item name="fracp1pperc" type="dimen" format="fraction">.1%p</item> + <item name="fracp01pperc" type="dimen" format="fraction">.01%p</item> + <item name="frac0pperc" type="dimen" format="fraction">0%p</item> + <item name="frac1p1pperc" type="dimen" format="fraction">1.1%p</item> + <item name="frac100p1pperc" type="dimen" format="fraction">100.1%p</item> + <item name="frac25510pperc" type="dimen" format="fraction">25510%p</item> + <item name="frac25610pperc" type="dimen" format="fraction">25610%p</item> + <item name="frac6553510pperc" type="dimen" format="fraction">6553510%p</item> + <item name="frac6553610pperc" type="dimen" format="fraction">6553610%p</item> +</resources> + diff --git a/tests/AndroidTests/res/values/strings.xml b/tests/AndroidTests/res/values/strings.xml new file mode 100644 index 0000000..21c72cf --- /dev/null +++ b/tests/AndroidTests/res/values/strings.xml @@ -0,0 +1,54 @@ +<?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. +--> + +<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="permlab_testGranted">Test Granted</string> + <string name="permdesc_testGranted">Used for running unit tests, for + testing operations where we have the permission.</string> + <string name="permlab_testDenied">Test Denied</string> + <string name="permdesc_testDenied">Used for running unit tests, for + testing operations where we do not have the permission.</string> + + <string name="layout_five_text_text">S</string> + + <string name="layout_four_text_text">S</string> + + <string name="layout_six_text_text">S</string> + + <string name="coerceIntegerToString">100</string> + <string name="coerceBooleanToString">true</string> + <string name="coerceColorToString">#fff</string> + <string name="coerceFloatToString">100.0</string> + <string name="coerceDimensionToString">100px</string> + <string name="coerceFractionToString">100<xliff:g id="percent">%</xliff:g></string> + + <string name="formattedStringNone">Format[]</string> + <string name="formattedStringOne">Format[<xliff:g id="format">%d</xliff:g>]</string> + <string name="formattedStringTwo">Format[<xliff:g id="format">%3$d,%2$s</xliff:g>]</string> + + <string name="reference">here</string> + + <string name="metadata_text">text</string> + + <string name="menu_test">test</string> + + <plurals name="plurals_test"> + <item quantity="one">A dog</item> + <item quantity="other">Some dogs</item> + </plurals> + +<!-- <string name="layout_six_text_text">F</string> --> +</resources> diff --git a/tests/AndroidTests/res/values/styles.xml b/tests/AndroidTests/res/values/styles.xml new file mode 100644 index 0000000..6c60e21 --- /dev/null +++ b/tests/AndroidTests/res/values/styles.xml @@ -0,0 +1,46 @@ +<?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. +--> + +<resources> + <style name="TestEnum1"> + <item name="testEnum">val1</item> + </style> + <style name="TestEnum2"> + <item name="testEnum">val2</item> + </style> + <style name="TestEnum10"> + <item name="testEnum">val10</item> + </style> + + <style name="TestFlag1"> + <item name="testFlags">bit1</item> + </style> + <style name="TestFlag2"> + <item name="testFlags">bit2</item> + </style> + <style name="TestFlag31"> + <item name="testFlags">bit31</item> + </style> + <style name="TestFlag1And2"> + <item name="testFlags">bit1|bit2</item> + </style> + <style name="TestFlag1And2And31"> + <item name="testFlags">bit1|bit2|bit31</item> + </style> + + <style name="TestEnum1.EmptyInherit"> + </style> +</resources> diff --git a/tests/AndroidTests/res/xml/calendar.xml b/tests/AndroidTests/res/xml/calendar.xml new file mode 100644 index 0000000..1adcd74 --- /dev/null +++ b/tests/AndroidTests/res/xml/calendar.xml @@ -0,0 +1,38 @@ +<?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. +--> + +<feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:gd='http://schemas.google.com/g/2005' xmlns:gCal='http://schemas.google.com/gCal/2005'><id>http://www.google.com/calendar/feeds/default/private/full</id><updated>2007-02-05T22:04:50.000Z</updated><category scheme='http://schemas.google.com/g/2005#kind' term='http://schemas.google.com/g/2005#event'></category><title type='text'>w g</title><subtitle type='text'>w g</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://www.google.com/calendar/feeds/default/private/full'></link><link rel='http://schemas.google.com/g/2005#post' type='application/atom+xml' href='http://www.google.com/calendar/feeds/default/private/full'></link><link rel='self' type='application/atom+xml' href='http://www.google.com/calendar/feeds/default/private/full?max-results=25'></link><author><name>w g</name><email>wg@voiceme.net</email></author><generator version='1.0' uri='http://www.google.com/calendar'>Google Calendar</generator><openSearch:totalResults>13</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><gCal:timezone value='America/Los_Angeles'></gCal:timezone><entry><id>http://www.google.com/calendar/feeds/default/private/full/7iqc1ro0ihc69vhsiq3uabooig</id><published>2007-02-05T22:04:50.000Z</published><updated>2007-02-05T22:04:50.000Z</updated><category scheme='http://schemas.google.com/g/2005#kind' term='http://schemas.google.com/g/2005#event'></category><title type='text'>skate</title><content type='text'></content><link rel='alternate' type='text/html' href='http://www.google.com/calendar/hosted/voiceme.net/event?eid=N2lxYzFybzBpaGM2OXZoc2lxM3VhYm9vaWcgd2dAdm9pY2VtZS5uZXQ' title='alternate'></link><link rel='self' type='application/atom+xml' href='http://www.google.com/calendar/feeds/default/private/full/7iqc1ro0ihc69vhsiq3uabooig'></link><link rel='edit' type='application/atom+xml' href='http://www.google.com/calendar/feeds/default/private/full/7iqc1ro0ihc69vhsiq3uabooig/63306396290'></link><author><name>w g</name><email>wg@voiceme.net</email></author><gd:comments><gd:feedLink href='http://www.google.com/calendar/feeds/default/private/full/7iqc1ro0ihc69vhsiq3uabooig/comments'></gd:feedLink></gd:comments><gd:eventStatus value='http://schemas.google.com/g/2005#event.confirmed'></gd:eventStatus><gd:visibility value='http://schemas.google.com/g/2005#event.default'></gd:visibility><gCal:sendEventNotifications value='false'></gCal:sendEventNotifications><gd:transparency value='http://schemas.google.com/g/2005#event.opaque'></gd:transparency><gd:where></gd:where><gd:when startTime='2007-02-07T13:30:00.000-08:00' endTime='2007-02-07T16:00:00.000-08:00'><gd:reminder minutes='10'></gd:reminder></gd:when></entry><entry><id>http://www.google.com/calendar/feeds/default/private/full/kp4gil76n2vcrkt9kaotj3s12c</id><published>2007-02-05T22:04:42.000Z</published><updated>2007-02-05T22:04:42.000Z</updated><category scheme='http://schemas.google.com/g/2005#kind' term='http://schemas.google.com/g/2005#event'></category><title type='text'>skate</title><content type='text'></content><link rel='alternate' type='text/html' href='http://www.google.com/calendar/hosted/voiceme.net/event?eid=a3A0Z2lsNzZuMnZjcmt0OWthb3RqM3MxMmMgd2dAdm9pY2VtZS5uZXQ' title='alternate'></link><link rel='self' type='application/atom+xml' href='http://www.google.com/calendar/feeds/default/private/full/kp4gil76n2vcrkt9kaotj3s12c'></link><link rel='edit' type='application/atom+xml' href='http://www.google.com/calendar/feeds/default/private/full/kp4gil76n2vcrkt9kaotj3s12c/63306396282'></link><author><name>w g</name><email>wg@voiceme.net</email></author><gd:comments><gd:feedLink href='http://www.google.com/calendar/feeds/default/private/full/kp4gil76n2vcrkt9kaotj3s12c/comments'></gd:feedLink></gd:comments><gd:eventStatus value='http://schemas.google.com/g/2005#event.confirmed'></gd:eventStatus><gd:visibility value='http://schemas.google.com/g/2005#event.default'></gd:visibility><gCal:sendEventNotifications value='false'></gCal:sendEventNotifications><gd:transparency value='http://schemas.google.com/g/2005#event.opaque'></gd:transparency><gd:where></gd:where><gd:when startTime='2007-02-09T15:30:00.000-08:00' endTime='2007-02-09T18:00:00.000-08:00'><gd:reminder minutes='10'></gd:reminder></gd:when></entry><entry><id>http://www.google.com/calendar/feeds/default/private/full/gkhb48fj68lcp15fd1k03tjbj0</id><published>2007-02-05T22:04:35.000Z</published><updated>2007-02-05T22:04:35.000Z</updated><category scheme='http://schemas.google.com/g/2005#kind' term='http://schemas.google.com/g/2005#event'></category><title type='text'>test event 6</title><content type='text'></content><link rel='alternate' type='text/html' href='http://www.google.com/calendar/hosted/voiceme.net/event?eid=Z2toYjQ4Zmo2OGxjcDE1ZmQxazAzdGpiajAgd2dAdm9pY2VtZS5uZXQ' title='alternate'></link><link rel='self' type='application/atom+xml' href='http://www.google.com/calendar/feeds/default/private/full/gkhb48fj68lcp15fd1k03tjbj0'></link><link rel='edit' type='application/atom+xml' href='http://www.google.com/calendar/feeds/default/private/full/gkhb48fj68lcp15fd1k03tjbj0/63306396275'></link><author><name>w g</name><email>wg@voiceme.net</email></author><gd:comments><gd:feedLink href='http://www.google.com/calendar/feeds/default/private/full/gkhb48fj68lcp15fd1k03tjbj0/comments'></gd:feedLink></gd:comments><gd:eventStatus value='http://schemas.google.com/g/2005#event.confirmed'></gd:eventStatus><gd:visibility value='http://schemas.google.com/g/2005#event.default'></gd:visibility><gCal:sendEventNotifications value='false'></gCal:sendEventNotifications><gd:transparency value='http://schemas.google.com/g/2005#event.opaque'></gd:transparency><gd:where></gd:where><gd:when startTime='2007-02-10T14:00:00.000-08:00' endTime='2007-02-10T17:00:00.000-08:00'><gd:reminder minutes='10'></gd:reminder></gd:when></entry><entry><id>http://www.google.com/calendar/feeds/default/private/full/32p5g68cpean3p2ol7kanj38sg</id><published>2007-02-05T22:04:29.000Z</published><updated>2007-02-05T22:04:29.000Z</updated><category scheme='http://schemas.google.com/g/2005#kind' term='http://schemas.google.com/g/2005#event'></category><title type='text'>test event 5</title><content type='text'></content><link rel='alternate' type='text/html' href='http://www.google.com/calendar/hosted/voiceme.net/event?eid=MzJwNWc2OGNwZWFuM3Ayb2w3a2FuajM4c2cgd2dAdm9pY2VtZS5uZXQ' title='alternate'></link><link rel='self' type='application/atom+xml' href='http://www.google.com/calendar/feeds/default/private/full/32p5g68cpean3p2ol7kanj38sg'></link><link rel='edit' type='application/atom+xml' href='http://www.google.com/calendar/feeds/default/private/full/32p5g68cpean3p2ol7kanj38sg/63306396269'></link><author><name>w g</name><email>wg@voiceme.net</email></author><gd:comments><gd:feedLink href='http://www.google.com/calendar/feeds/default/private/full/32p5g68cpean3p2ol7kanj38sg/comments'></gd:feedLink></gd:comments><gd:eventStatus value='http://schemas.google.com/g/2005#event.confirmed'></gd:eventStatus><gd:visibility value='http://schemas.google.com/g/2005#event.default'></gd:visibility><gCal:sendEventNotifications value='false'></gCal:sendEventNotifications><gd:transparency value='http://schemas.google.com/g/2005#event.opaque'></gd:transparency><gd:where></gd:where><gd:when startTime='2007-02-09T09:00:00.000-08:00' endTime='2007-02-09T10:30:00.000-08:00'><gd:reminder minutes='10'></gd:reminder></gd:when></entry><entry><id>http://www.google.com/calendar/feeds/default/private/full/tfqpth26conshdmav0apje1tf4</id><published>2007-02-05T22:04:19.000Z</published><updated>2007-02-05T22:04:19.000Z</updated><category scheme='http://schemas.google.com/g/2005#kind' term='http://schemas.google.com/g/2005#event'></category><title type='text'>skate</title><content type='text'></content><link rel='alternate' type='text/html' href='http://www.google.com/calendar/hosted/voiceme.net/event?eid=dGZxcHRoMjZjb25zaGRtYXYwYXBqZTF0ZjQgd2dAdm9pY2VtZS5uZXQ' title='alternate'></link><link rel='self' type='application/atom+xml' href='http://www.google.com/calendar/feeds/default/private/full/tfqpth26conshdmav0apje1tf4'></link><link rel='edit' type='application/atom+xml' href='http://www.google.com/calendar/feeds/default/private/full/tfqpth26conshdmav0apje1tf4/63306396259'></link><author><name>w g</name><email>wg@voiceme.net</email></author><gd:comments><gd:feedLink href='http://www.google.com/calendar/feeds/default/private/full/tfqpth26conshdmav0apje1tf4/comments'></gd:feedLink></gd:comments><gd:eventStatus value='http://schemas.google.com/g/2005#event.confirmed'></gd:eventStatus><gd:visibility value='http://schemas.google.com/g/2005#event.default'></gd:visibility><gCal:sendEventNotifications value='false'></gCal:sendEventNotifications><gd:transparency value='http://schemas.google.com/g/2005#event.opaque'></gd:transparency><gd:where></gd:where><gd:when startTime='2007-02-08T15:00:00.000-08:00' endTime='2007-02-08T17:00:00.000-08:00'><gd:reminder minutes='10'></gd:reminder></gd:when></entry><entry><id>http://www.google.com/calendar/feeds/default/private/full/onbo9mhbr5m6mo356nog7uel4s</id><published>2007-02-05T22:04:07.000Z</published><updated>2007-02-05T22:04:07.000Z</updated><category scheme='http://schemas.google.com/g/2005#kind' term='http://schemas.google.com/g/2005#event'></category><title type='text'>Sharks at Anaheim</title><content type='text'></content><link rel='alternate' type='text/html' href='http://www.google.com/calendar/hosted/voiceme.net/event?eid=b25ibzltaGJyNW02bW8zNTZub2c3dWVsNHMgd2dAdm9pY2VtZS5uZXQ' title='alternate'></link><link rel='self' type='application/atom+xml' href='http://www.google.com/calendar/feeds/default/private/full/onbo9mhbr5m6mo356nog7uel4s'></link><link rel='edit' type='application/atom+xml' href='http://www.google.com/calendar/feeds/default/private/full/onbo9mhbr5m6mo356nog7uel4s/63306396247'></link><author><name>w g</name><email>wg@voiceme.net</email></author><gd:comments><gd:feedLink href='http://www.google.com/calendar/feeds/default/private/full/onbo9mhbr5m6mo356nog7uel4s/comments'></gd:feedLink></gd:comments><gd:eventStatus value='http://schemas.google.com/g/2005#event.confirmed'></gd:eventStatus><gd:visibility value='http://schemas.google.com/g/2005#event.default'></gd:visibility><gCal:sendEventNotifications value='true'></gCal:sendEventNotifications><gd:transparency value='http://schemas.google.com/g/2005#event.opaque'></gd:transparency><gd:where valueString=''></gd:where><gd:when startTime='2007-02-07T19:00:00.000-08:00' endTime='2007-02-07T22:00:00.000-08:00'><gd:reminder minutes='10'></gd:reminder></gd:when></entry><entry><id>http://www.google.com/calendar/feeds/default/private/full/tjqrd9fve576hieh3sa67nql5k</id><published>2007-02-05T22:04:02.000Z</published><updated>2007-02-05T22:04:02.000Z</updated><category scheme='http://schemas.google.com/g/2005#kind' term='http://schemas.google.com/g/2005#event'></category><title type='text'>Sharks vs. ANAHEIM</title><content type='text'></content><link rel='alternate' type='text/html' href='http://www.google.com/calendar/hosted/voiceme.net/event?eid=dGpxcmQ5ZnZlNTc2aGllaDNzYTY3bnFsNWsgd2dAdm9pY2VtZS5uZXQ' title='alternate'></link><link rel='self' type='application/atom+xml' href='http://www.google.com/calendar/feeds/default/private/full/tjqrd9fve576hieh3sa67nql5k'></link><link rel='edit' type='application/atom+xml' href='http://www.google.com/calendar/feeds/default/private/full/tjqrd9fve576hieh3sa67nql5k/63306396242'></link><author><name>w g</name><email>wg@voiceme.net</email></author><gd:comments><gd:feedLink href='http://www.google.com/calendar/feeds/default/private/full/tjqrd9fve576hieh3sa67nql5k/comments'></gd:feedLink></gd:comments><gd:eventStatus value='http://schemas.google.com/g/2005#event.confirmed'></gd:eventStatus><gd:visibility value='http://schemas.google.com/g/2005#event.default'></gd:visibility><gCal:sendEventNotifications value='true'></gCal:sendEventNotifications><gd:transparency value='http://schemas.google.com/g/2005#event.opaque'></gd:transparency><gd:where valueString=''></gd:where><gd:when startTime='2007-02-06T19:30:00.000-08:00' endTime='2007-02-06T22:30:00.000-08:00'><gd:reminder minutes='10'></gd:reminder></gd:when></entry><entry><id>http://www.google.com/calendar/feeds/default/private/full/or6dtpn065f9mntond4jh2docc</id><published>2007-02-05T22:03:52.000Z</published><updated>2007-02-05T22:03:52.000Z</updated><category scheme='http://schemas.google.com/g/2005#kind' term='http://schemas.google.com/g/2005#event'></category><title type='text'>skate</title><content type='text'></content><link rel='alternate' type='text/html' href='http://www.google.com/calendar/hosted/voiceme.net/event?eid=b3I2ZHRwbjA2NWY5bW50b25kNGpoMmRvY2Mgd2dAdm9pY2VtZS5uZXQ' title='alternate'></link><link rel='self' type='application/atom+xml' href='http://www.google.com/calendar/feeds/default/private/full/or6dtpn065f9mntond4jh2docc'></link><link rel='edit' type='application/atom+xml' href='http://www.google.com/calendar/feeds/default/private/full/or6dtpn065f9mntond4jh2docc/63306396232'></link><author><name>w g</name><email>wg@voiceme.net</email></author><gd:comments><gd:feedLink href='http://www.google.com/calendar/feeds/default/private/full/or6dtpn065f9mntond4jh2docc/comments'></gd:feedLink></gd:comments><gd:eventStatus value='http://schemas.google.com/g/2005#event.confirmed'></gd:eventStatus><gd:visibility value='http://schemas.google.com/g/2005#event.default'></gd:visibility><gCal:sendEventNotifications value='false'></gCal:sendEventNotifications><gd:transparency value='http://schemas.google.com/g/2005#event.opaque'></gd:transparency><gd:where></gd:where><gd:when startTime='2007-02-06T14:00:00.000-08:00' endTime='2007-02-06T15:00:00.000-08:00'><gd:reminder minutes='10'></gd:reminder></gd:when></entry><entry><id>http://www.google.com/calendar/feeds/default/private/full/k70v8o4jt1afi17hg2spavq1c0</id><published>2007-02-05T22:03:36.000Z</published><updated>2007-02-05T22:03:36.000Z</updated><category scheme='http://schemas.google.com/g/2005#kind' term='http://schemas.google.com/g/2005#event'></category><title type='text'>lunch</title><content type='text'></content><link rel='alternate' type='text/html' href='http://www.google.com/calendar/hosted/voiceme.net/event?eid=azcwdjhvNGp0MWFmaTE3aGcyc3BhdnExYzBfMjAwNzAyMDZUMjAwMDAwWiB3Z0B2b2ljZW1lLm5ldA' title='alternate'></link><link rel='self' type='application/atom+xml' href='http://www.google.com/calendar/feeds/default/private/full/k70v8o4jt1afi17hg2spavq1c0'></link><link rel='edit' type='application/atom+xml' href='http://www.google.com/calendar/feeds/default/private/full/k70v8o4jt1afi17hg2spavq1c0/63306396216'></link><author><name>w g</name><email>wg@voiceme.net</email></author><gd:eventStatus value='http://schemas.google.com/g/2005#event.confirmed'></gd:eventStatus><gd:visibility value='http://schemas.google.com/g/2005#event.default'></gd:visibility><gCal:sendEventNotifications value='true'></gCal:sendEventNotifications><gd:transparency value='http://schemas.google.com/g/2005#event.opaque'></gd:transparency><gd:recurrence>DTSTART;TZID=America/Los_Angeles:20070206T120000 +DURATION:PT3600S +RRULE:FREQ=DAILY;WKST=SU +BEGIN:VTIMEZONE +TZID:America/Los_Angeles +X-LIC-LOCATION:America/Los_Angeles +BEGIN:STANDARD +TZOFFSETFROM:-0700 +TZOFFSETTO:-0800 +TZNAME:PST +DTSTART:19701025T020000 +RRULE:FREQ=YEARLY;BYMONTH=10;BYDAY=-1SU +END:STANDARD +BEGIN:DAYLIGHT +TZOFFSETFROM:-0800 +TZOFFSETTO:-0700 +TZNAME:PDT +DTSTART:19700405T020000 +RRULE:FREQ=YEARLY;BYMONTH=4;BYDAY=1SU +END:DAYLIGHT +END:VTIMEZONE +</gd:recurrence><gd:where valueString=''></gd:where><gd:reminder minutes='10'></gd:reminder></entry><entry><id>http://www.google.com/calendar/feeds/default/private/full/6ee7b8nohdt03tv0gknm4v7124</id><published>2007-02-05T22:03:19.000Z</published><updated>2007-02-05T22:03:19.000Z</updated><category scheme='http://schemas.google.com/g/2005#kind' term='http://schemas.google.com/g/2005#event'></category><title type='text'>test event 4</title><content type='text'></content><link rel='alternate' type='text/html' href='http://www.google.com/calendar/hosted/voiceme.net/event?eid=NmVlN2I4bm9oZHQwM3R2MGdrbm00djcxMjQgd2dAdm9pY2VtZS5uZXQ' title='alternate'></link><link rel='self' type='application/atom+xml' href='http://www.google.com/calendar/feeds/default/private/full/6ee7b8nohdt03tv0gknm4v7124'></link><link rel='edit' type='application/atom+xml' href='http://www.google.com/calendar/feeds/default/private/full/6ee7b8nohdt03tv0gknm4v7124/63306396199'></link><author><name>w g</name><email>wg@voiceme.net</email></author><gd:comments><gd:feedLink href='http://www.google.com/calendar/feeds/default/private/full/6ee7b8nohdt03tv0gknm4v7124/comments'></gd:feedLink></gd:comments><gd:eventStatus value='http://schemas.google.com/g/2005#event.confirmed'></gd:eventStatus><gd:visibility value='http://schemas.google.com/g/2005#event.default'></gd:visibility><gCal:sendEventNotifications value='false'></gCal:sendEventNotifications><gd:transparency value='http://schemas.google.com/g/2005#event.opaque'></gd:transparency><gd:where></gd:where><gd:when startTime='2007-02-06T09:00:00.000-08:00' endTime='2007-02-06T11:00:00.000-08:00'><gd:reminder minutes='10'></gd:reminder></gd:when></entry><entry><id>http://www.google.com/calendar/feeds/default/private/full/of1vh1r2q5aqdplo65i8bqbn3o</id><published>2007-02-05T22:03:11.000Z</published><updated>2007-02-05T22:03:11.000Z</updated><category scheme='http://schemas.google.com/g/2005#kind' term='http://schemas.google.com/g/2005#event'></category><title type='text'>test event 3</title><content type='text'></content><link rel='alternate' type='text/html' href='http://www.google.com/calendar/hosted/voiceme.net/event?eid=b2YxdmgxcjJxNWFxZHBsbzY1aThicWJuM28gd2dAdm9pY2VtZS5uZXQ' title='alternate'></link><link rel='self' type='application/atom+xml' href='http://www.google.com/calendar/feeds/default/private/full/of1vh1r2q5aqdplo65i8bqbn3o'></link><link rel='edit' type='application/atom+xml' href='http://www.google.com/calendar/feeds/default/private/full/of1vh1r2q5aqdplo65i8bqbn3o/63306396191'></link><author><name>w g</name><email>wg@voiceme.net</email></author><gd:comments><gd:feedLink href='http://www.google.com/calendar/feeds/default/private/full/of1vh1r2q5aqdplo65i8bqbn3o/comments'></gd:feedLink></gd:comments><gd:eventStatus value='http://schemas.google.com/g/2005#event.confirmed'></gd:eventStatus><gd:visibility value='http://schemas.google.com/g/2005#event.default'></gd:visibility><gCal:sendEventNotifications value='false'></gCal:sendEventNotifications><gd:transparency value='http://schemas.google.com/g/2005#event.opaque'></gd:transparency><gd:where></gd:where><gd:when startTime='2007-02-05T18:00:00.000-08:00' endTime='2007-02-05T19:00:00.000-08:00'><gd:reminder minutes='10'></gd:reminder></gd:when></entry><entry><id>http://www.google.com/calendar/feeds/default/private/full/s7ahgfomlgii9qbkgpfbinr9u8</id><published>2007-02-05T22:02:40.000Z</published><updated>2007-02-05T22:03:04.000Z</updated><category scheme='http://schemas.google.com/g/2005#kind' term='http://schemas.google.com/g/2005#event'></category><title type='text'>test event 2</title><content type='text'></content><link rel='alternate' type='text/html' href='http://www.google.com/calendar/hosted/voiceme.net/event?eid=czdhaGdmb21sZ2lpOXFia2dwZmJpbnI5dTggd2dAdm9pY2VtZS5uZXQ' title='alternate'></link><link rel='self' type='application/atom+xml' href='http://www.google.com/calendar/feeds/default/private/full/s7ahgfomlgii9qbkgpfbinr9u8'></link><link rel='edit' type='application/atom+xml' href='http://www.google.com/calendar/feeds/default/private/full/s7ahgfomlgii9qbkgpfbinr9u8/63306396184'></link><author><name>w g</name><email>wg@voiceme.net</email></author><gd:comments><gd:feedLink href='http://www.google.com/calendar/feeds/default/private/full/s7ahgfomlgii9qbkgpfbinr9u8/comments'></gd:feedLink></gd:comments><gd:eventStatus value='http://schemas.google.com/g/2005#event.confirmed'></gd:eventStatus><gd:visibility value='http://schemas.google.com/g/2005#event.default'></gd:visibility><gCal:sendEventNotifications value='false'></gCal:sendEventNotifications><gd:transparency value='http://schemas.google.com/g/2005#event.opaque'></gd:transparency><gd:where valueString=''></gd:where><gd:when startTime='2007-02-05T16:30:00.000-08:00' endTime='2007-02-05T17:30:00.000-08:00'><gd:reminder minutes='10'></gd:reminder></gd:when></entry><entry><id>http://www.google.com/calendar/feeds/default/private/full/rl8focglfe6jndql4u8lg73q5k</id><published>2007-02-05T22:02:28.000Z</published><updated>2007-02-05T22:02:53.000Z</updated><category scheme='http://schemas.google.com/g/2005#kind' term='http://schemas.google.com/g/2005#event'></category><title type='text'>test event 1</title><content type='text'></content><link rel='alternate' type='text/html' href='http://www.google.com/calendar/hosted/voiceme.net/event?eid=cmw4Zm9jZ2xmZTZqbmRxbDR1OGxnNzNxNWsgd2dAdm9pY2VtZS5uZXQ' title='alternate'></link><link rel='self' type='application/atom+xml' href='http://www.google.com/calendar/feeds/default/private/full/rl8focglfe6jndql4u8lg73q5k'></link><link rel='edit' type='application/atom+xml' href='http://www.google.com/calendar/feeds/default/private/full/rl8focglfe6jndql4u8lg73q5k/63306396173'></link><author><name>w g</name><email>wg@voiceme.net</email></author><gd:comments><gd:feedLink href='http://www.google.com/calendar/feeds/default/private/full/rl8focglfe6jndql4u8lg73q5k/comments'></gd:feedLink></gd:comments><gd:eventStatus value='http://schemas.google.com/g/2005#event.confirmed'></gd:eventStatus><gd:visibility value='http://schemas.google.com/g/2005#event.default'></gd:visibility><gCal:sendEventNotifications value='false'></gCal:sendEventNotifications><gd:transparency value='http://schemas.google.com/g/2005#event.opaque'></gd:transparency><gd:where></gd:where><gd:when startTime='2007-02-05T15:00:00.000-08:00' endTime='2007-02-05T16:00:00.000-08:00'><gd:reminder minutes='10'></gd:reminder></gd:when></entry></feed> diff --git a/tests/AndroidTests/res/xml/metadata.xml b/tests/AndroidTests/res/xml/metadata.xml new file mode 100644 index 0000000..e352f27 --- /dev/null +++ b/tests/AndroidTests/res/xml/metadata.xml @@ -0,0 +1,23 @@ +<?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. +--> + +<thedata xmlns:android="http://schemas.android.com/apk/res/android" + rawText="some raw text" + rawColor="#ffffff00" + android:color="#f00" + android:text="@string/metadata_text" + +/> diff --git a/tests/AndroidTests/res/xml/metadata_app.xml b/tests/AndroidTests/res/xml/metadata_app.xml new file mode 100644 index 0000000..c37e6ba --- /dev/null +++ b/tests/AndroidTests/res/xml/metadata_app.xml @@ -0,0 +1,24 @@ +<?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. +--> + +<thedata xmlns:android="http://schemas.android.com/apk/res/android" + rawText="some raw text" + rawColor="#ffffff00" + android:color="#f00" + android:text="@string/metadata_text" + appInfo="true" + +/> diff --git a/tests/AndroidTests/res/xml/searchable.xml b/tests/AndroidTests/res/xml/searchable.xml new file mode 100644 index 0000000..a40d53d --- /dev/null +++ b/tests/AndroidTests/res/xml/searchable.xml @@ -0,0 +1,21 @@ +<?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. +--> + +<searchable xmlns:android="http://schemas.android.com/apk/res/android" + android:label="SearchManagerTest" + android:hint="SearchManagerTest Hint" +/> + diff --git a/tests/AndroidTests/run_test.sh b/tests/AndroidTests/run_test.sh new file mode 100755 index 0000000..0cdf63f --- /dev/null +++ b/tests/AndroidTests/run_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/AndroidTests.apk \ + com.android.internal.util.WithFramework junit.textui.TestRunner $* diff --git a/tests/AndroidTests/src/com/android/unit_tests/AndroidPerformanceTests.java b/tests/AndroidTests/src/com/android/unit_tests/AndroidPerformanceTests.java new file mode 100644 index 0000000..b6a8594 --- /dev/null +++ b/tests/AndroidTests/src/com/android/unit_tests/AndroidPerformanceTests.java @@ -0,0 +1,39 @@ +/* + * 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.unit_tests; + +import android.test.TestListActivity; + +public class AndroidPerformanceTests extends TestListActivity { + @Override + public String getTestSuite() { + return "com.android.unit_tests.AndroidPerformanceTests$Suite"; + } + + public static class Suite { + public static String[] children() { + return new String[] { + DatabasePerformanceTests.class.getName(), + GraphicsPerformanceTests.class.getName(), + JavaPerformanceTests.class.getName(), + LogTest.PerformanceTest.class.getName(), + PerformanceTests.class.getName(), + TextViewPerformanceTest.class.getName(), + }; + } + } +} diff --git a/tests/AndroidTests/src/com/android/unit_tests/AndroidTests.java b/tests/AndroidTests/src/com/android/unit_tests/AndroidTests.java new file mode 100644 index 0000000..4b86add --- /dev/null +++ b/tests/AndroidTests/src/com/android/unit_tests/AndroidTests.java @@ -0,0 +1,32 @@ +/* + * Copyright (C) 2005 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.unit_tests; + +import android.test.FrameworkTests; +import android.test.suitebuilder.TestSuiteBuilder; + +import junit.framework.TestSuite; + +public class AndroidTests extends TestSuite { + + public static TestSuite suite() { + TestSuiteBuilder suiteBuilder = new TestSuiteBuilder(AndroidTests.class); + TestSuite suite = suiteBuilder.includeAllPackagesUnderHere().build(); + + return suite; + } +} diff --git a/tests/AndroidTests/src/com/android/unit_tests/ApacheHttpTests.java b/tests/AndroidTests/src/com/android/unit_tests/ApacheHttpTests.java new file mode 100644 index 0000000..cf759e0 --- /dev/null +++ b/tests/AndroidTests/src/com/android/unit_tests/ApacheHttpTests.java @@ -0,0 +1,13 @@ +package com.android.unit_tests; + +import junit.framework.TestSuite; + +public class ApacheHttpTests { + public static TestSuite suite() { + TestSuite suite = new TestSuite(ApacheHttpTests.class.getName()); + + suite.addTestSuite(TestHttpService.class); + + return suite; + } +} diff --git a/tests/AndroidTests/src/com/android/unit_tests/AppCacheTest.java b/tests/AndroidTests/src/com/android/unit_tests/AppCacheTest.java new file mode 100755 index 0000000..3daa8ab --- /dev/null +++ b/tests/AndroidTests/src/com/android/unit_tests/AppCacheTest.java @@ -0,0 +1,746 @@ +/* + * 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.unit_tests; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; + +import android.app.PendingIntent; +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; +import android.content.IntentFilter; +import android.content.pm.ApplicationInfo; +import android.content.pm.IPackageDataObserver; +import android.content.pm.IPackageStatsObserver; +import android.content.pm.PackageStats; +import android.content.pm.IPackageManager; +import android.test.AndroidTestCase; +import android.test.suitebuilder.annotation.LargeTest; +import android.test.suitebuilder.annotation.MediumTest; +import android.test.suitebuilder.annotation.SmallTest; +import android.test.suitebuilder.annotation.Suppress; +import android.util.Log; +import android.os.Handler; +import android.os.RemoteException; +import android.os.ServiceManager; +import android.os.StatFs; + +public class AppCacheTest extends AndroidTestCase { + private static final boolean localLOGV = false; + public static final String TAG="AppCacheTest"; + public final long MAX_WAIT_TIME=60*1000; + public final long WAIT_TIME_INCR=10*1000; + private static final int THRESHOLD=5; + private static final int ACTUAL_THRESHOLD=10; + + @Override + protected void setUp() throws Exception { + super.setUp(); + if(localLOGV) Log.i(TAG, "Cleaning up cache directory first"); + cleanUpCacheDirectory(); + } + + void cleanUpDirectory(File pDir, String dirName) { + File testDir = new File(pDir, dirName); + if(!testDir.exists()) { + return; + } + String fList[] = testDir.list(); + for(int i = 0; i < fList.length; i++) { + File file = new File(testDir, fList[i]); + if(file.isDirectory()) { + cleanUpDirectory(testDir, fList[i]); + } else { + file.delete(); + } + } + testDir.delete(); + } + + void cleanUpCacheDirectory() { + File testDir = mContext.getCacheDir(); + if(!testDir.exists()) { + return; + } + + String fList[] = testDir.list(); + if(fList == null) { + testDir.delete(); + return; + } + for(int i = 0; i < fList.length; i++) { + File file = new File(testDir, fList[i]); + if(file.isDirectory()) { + cleanUpDirectory(testDir, fList[i]); + } else { + file.delete(); + } + } + } + + @SmallTest + public void testDeleteAllCacheFiles() { + String testName="testDeleteAllCacheFiles"; + cleanUpCacheDirectory(); + } + + void failStr(String errMsg) { + Log.w(TAG, "errMsg="+errMsg); + fail(errMsg); + } + void failStr(Exception e) { + Log.w(TAG, "e.getMessage="+e.getMessage()); + Log.w(TAG, "e="+e); + } + long getFreeStorageBlks(StatFs st) { + st.restat("/data"); + return st.getFreeBlocks(); + } + + long getFreeStorageSize(StatFs st) { + st.restat("/data"); + return (st.getFreeBlocks()*st.getBlockSize()); + } + @LargeTest + public void testFreeApplicationCacheAllFiles() throws Exception { + boolean TRACKING = true; + StatFs st = new StatFs("/data"); + long blks1 = getFreeStorageBlks(st); + long availableMem = getFreeStorageSize(st); + File cacheDir = mContext.getCacheDir(); + assertNotNull(cacheDir); + createTestFiles1(cacheDir, "testtmpdir", 5); + long blks2 = getFreeStorageBlks(st); + if(localLOGV || TRACKING) Log.i(TAG, "blk1="+blks1+", blks2="+blks2); + //this should free up the test files that were created earlier + invokePMFreeApplicationCache(availableMem); + long blks3 = getFreeStorageBlks(st); + if(localLOGV || TRACKING) Log.i(TAG, "blks3="+blks3); + verifyTestFiles1(cacheDir, "testtmpdir", 5); + } + + @LargeTest + public void testFreeApplicationCacheSomeFiles() throws Exception { + StatFs st = new StatFs("/data"); + long blks1 = getFreeStorageBlks(st); + File cacheDir = mContext.getCacheDir(); + assertNotNull(cacheDir); + createTestFiles1(cacheDir, "testtmpdir", 5); + long blks2 = getFreeStorageBlks(st); + Log.i(TAG, "blk1="+blks1+", blks2="+blks2); + long diff = (blks1-blks2-2); + assertTrue(invokePMFreeApplicationCache(diff*st.getBlockSize())); + long blks3 = getFreeStorageBlks(st); + //blks3 should be greater than blks2 and less than blks1 + if(!((blks3 <= blks1) && (blks3 >= blks2))) { + failStr("Expected "+(blks1-blks2)+" number of blocks to be freed but freed only " + +(blks1-blks3)); + } + } + + /** + * This method opens an output file writes to it, opens the same file as an input + * stream, reads the contents and verifies the data that was written earlier can be read + */ + public void openOutFileInAppFilesDir(File pFile, String pFileOut) { + FileOutputStream fos = null; + try { + fos = new FileOutputStream(pFile); + } catch (FileNotFoundException e1) { + failStr("Error when opening file "+e1); + return; + } + try { + fos.write(pFileOut.getBytes()); + fos.close(); + } catch (FileNotFoundException e) { + failStr(e.getMessage()); + } catch (IOException e) { + failStr(e.getMessage()); + } + int count = pFileOut.getBytes().length; + byte[] buffer = new byte[count]; + try { + FileInputStream fis = new FileInputStream(pFile); + fis.read(buffer, 0, count); + fis.close(); + } catch (FileNotFoundException e) { + failStr("Failed when verifing output opening file "+e.getMessage()); + } catch (IOException e) { + failStr("Failed when verifying output, reading from written file "+e); + } + String str = new String(buffer); + assertEquals(str, pFileOut); + } + + /* + * This test case verifies that output written to a file + * using Context.openFileOutput has executed successfully. + * The operation is verified by invoking Context.openFileInput + */ + @MediumTest + public void testAppFilesCreateFile() { + String fileName = "testFile1.txt"; + String fileOut = "abcdefghijklmnopqrstuvwxyz"; + Context con = super.getContext(); + try { + FileOutputStream fos = con.openFileOutput(fileName, Context.MODE_PRIVATE); + fos.close(); + } catch (FileNotFoundException e) { + failStr(e); + } catch (IOException e) { + failStr(e); + } + } + + @SmallTest + public void testAppCacheCreateFile() { + String fileName = "testFile1.txt"; + String fileOut = "abcdefghijklmnopqrstuvwxyz"; + Context con = super.getContext(); + File file = new File(con.getCacheDir(), fileName); + openOutFileInAppFilesDir(file, fileOut); + cleanUpCacheDirectory(); + } + + @MediumTest + public void testAppCreateCacheFiles() { + File cacheDir = mContext.getCacheDir(); + String testDirName = "testtmp"; + File testTmpDir = new File(cacheDir, testDirName); + testTmpDir.mkdir(); + int numDirs = 3; + File fileArr[] = new File[numDirs]; + for(int i = 0; i < numDirs; i++) { + fileArr[i] = new File(testTmpDir, "dir"+(i+1)); + fileArr[i].mkdir(); + } + byte buffer[] = getBuffer(); + Log.i(TAG, "Size of bufer="+buffer.length); + for(int i = 0; i < numDirs; i++) { + for(int j = 1; j <= (i); j++) { + File file1 = new File(fileArr[i], "testFile"+j+".txt"); + FileOutputStream fos = null; + try { + fos = new FileOutputStream(file1); + for(int k = 1; k < 10; k++) { + fos.write(buffer); + } + Log.i(TAG, "wrote 10K bytes to "+file1); + fos.close(); + } catch (FileNotFoundException e) { + Log.i(TAG, "Excetion ="+e); + fail("Error when creating outputstream "+e); + } catch(IOException e) { + Log.i(TAG, "Excetion ="+e); + fail("Error when writing output "+e); + } + } + } + } + + byte[] getBuffer() { + String sbuffer = "a"; + for(int i = 0; i < 10; i++) { + sbuffer += sbuffer; + } + return sbuffer.getBytes(); + } + + long getFileNumBlocks(long fileSize, int blkSize) { + long ret = fileSize/blkSize; + if(ret*blkSize < fileSize) { + ret++; + } + return ret; + } + + //@LargeTest + public void testAppCacheClear() { + String dataDir="/data/data"; + StatFs st = new StatFs(dataDir); + int blkSize = st.getBlockSize(); + int totBlks = st.getBlockCount(); + long availableBlks = st.getFreeBlocks(); + long thresholdBlks = (totBlks*THRESHOLD)/100; + String testDirName = "testdir"; + //create directory in cache + File testDir = new File(mContext.getCacheDir(), testDirName); + testDir.mkdirs(); + byte[] buffer = getBuffer(); + int i = 1; + if(localLOGV) Log.i(TAG, "availableBlks="+availableBlks+", thresholdBlks="+thresholdBlks); + long createdFileBlks = 0; + int imax = 300; + while((availableBlks > thresholdBlks) &&(i < imax)) { + File testFile = new File(testDir, "testFile"+i+".txt"); + if(localLOGV) Log.i(TAG, "Creating "+i+"th test file "+testFile); + int jmax = i; + i++; + FileOutputStream fos; + try { + fos = new FileOutputStream(testFile); + } catch (FileNotFoundException e) { + Log.i(TAG, "Failed creating test file:"+testFile); + continue; + } + boolean err = false; + for(int j = 1; j <= jmax;j++) { + try { + fos.write(buffer); + } catch (IOException e) { + Log.i(TAG, "Failed to write to file:"+testFile); + err = true; + } + } + try { + fos.close(); + } catch (IOException e) { + Log.i(TAG, "Failed closing file:"+testFile); + } + if(err) { + continue; + } + createdFileBlks += getFileNumBlocks(testFile.length(), blkSize); + st.restat(dataDir); + availableBlks = st.getFreeBlocks(); + } + st.restat(dataDir); + long availableBytes = st.getFreeBlocks()*blkSize; + long shouldFree = (ACTUAL_THRESHOLD-THRESHOLD)*totBlks; + //would have run out of memory + //wait for some time and confirm cache is deleted + try { + Log.i(TAG, "Sleeping for 2 minutes..."); + Thread.sleep(2*60*1000); + } catch (InterruptedException e) { + fail("Exception when sleeping "+e); + } + boolean removedFlag = false; + long existingFileBlks = 0; + for(int k = 1; k <i; k++) { + File testFile = new File(testDir, "testFile"+k+".txt"); + if(!testFile.exists()) { + removedFlag = true; + if(localLOGV) Log.i(TAG, testFile+" removed"); + } else { + existingFileBlks += getFileNumBlocks(testFile.length(), blkSize); + } + } + if(localLOGV) Log.i(TAG, "createdFileBlks="+createdFileBlks+ + ", existingFileBlks="+existingFileBlks); + long fileSize = createdFileBlks-existingFileBlks; + //verify fileSize number of bytes have been cleared from cache + if(localLOGV) Log.i(TAG, "deletedFileBlks="+fileSize+" shouldFreeBlks="+shouldFree); + if((fileSize > (shouldFree-blkSize) && (fileSize < (shouldFree+blkSize)))) { + Log.i(TAG, "passed"); + } + assertTrue(removedFlag); + } + + //createTestFiles(new File(super.getContext().getCacheDir(), "testtmp", "dir", 3) + void createTestFiles1(File cacheDir, String testFilePrefix, int numTestFiles) { + byte buffer[] = getBuffer(); + for(int i = 0; i < numTestFiles; i++) { + File file1 = new File(cacheDir, testFilePrefix+i+".txt"); + FileOutputStream fos = null; + try { + fos = new FileOutputStream(file1); + for(int k = 1; k < 10; k++) { + fos.write(buffer); + } + fos.close(); + } catch (FileNotFoundException e) { + Log.i(TAG, "Exception ="+e); + fail("Error when creating outputstream "+e); + } catch(IOException e) { + Log.i(TAG, "Exception ="+e); + fail("Error when writing output "+e); + } + try { + //introduce sleep for 1 s to avoid common time stamps for files being created + Thread.sleep(1000); + } catch (InterruptedException e) { + fail("Exception when sleeping "+e); + } + } + } + + void verifyTestFiles1(File cacheDir, String testFilePrefix, int numTestFiles) { + for(int i = 0; i < numTestFiles; i++) { + File file1 = new File(cacheDir, testFilePrefix+i+".txt"); + if(file1.exists()) { + fail("file:"+file1+" should not exist"); + } + } + } + + void createTestFiles2(File cacheDir, String rootTestDirName, String subDirPrefix, int numDirs, String testFilePrefix) { + Context con = super.getContext(); + File testTmpDir = new File(cacheDir, rootTestDirName); + testTmpDir.mkdir(); + File fileArr[] = new File[numDirs]; + for(int i = 0; i < numDirs; i++) { + fileArr[i] = new File(testTmpDir, subDirPrefix+(i+1)); + fileArr[i].mkdir(); + } + byte buffer[] = getBuffer(); + for(int i = 0; i < numDirs; i++) { + for(int j = 1; j <= (i); j++) { + File file1 = new File(fileArr[i], testFilePrefix+j+".txt"); + FileOutputStream fos = null; + try { + fos = new FileOutputStream(file1); + for(int k = 1; k < 10; k++) { + fos.write(buffer); + } + fos.close(); + } catch (FileNotFoundException e) { + Log.i(TAG, "Exception ="+e); + fail("Error when creating outputstream "+e); + } catch(IOException e) { + Log.i(TAG, "Exception ="+e); + fail("Error when writing output "+e); + } + try { + //introduce sleep for 10 ms to avoid common time stamps for files being created + Thread.sleep(10); + } catch (InterruptedException e) { + fail("Exception when sleeping "+e); + } + } + } + } + + class PackageDataObserver extends IPackageDataObserver.Stub { + public boolean retValue = false; + private boolean doneFlag = false; + public void onRemoveCompleted(String packageName, boolean succeeded) + throws RemoteException { + synchronized(this) { + retValue = succeeded; + doneFlag = true; + notifyAll(); + } + } + public boolean isDone() { + return doneFlag; + } + } + + IPackageManager getPm() { + return IPackageManager.Stub.asInterface(ServiceManager.getService("package")); + } + + boolean invokePMDeleteAppCacheFiles() throws Exception { + try { + String packageName = mContext.getPackageName(); + PackageDataObserver observer = new PackageDataObserver(); + //wait on observer + synchronized(observer) { + getPm().deleteApplicationCacheFiles(packageName, observer); + long waitTime = 0; + while(!observer.isDone() || (waitTime > MAX_WAIT_TIME)) { + observer.wait(WAIT_TIME_INCR); + waitTime += WAIT_TIME_INCR; + } + if(!observer.isDone()) { + throw new Exception("timed out waiting for PackageDataObserver.onRemoveCompleted"); + } + } + return observer.retValue; + } catch (RemoteException e) { + Log.w(TAG, "Failed to get handle for PackageManger Exception: "+e); + return false; + } catch (InterruptedException e) { + Log.w(TAG, "InterruptedException :"+e); + return false; + } + } + + boolean invokePMFreeApplicationCache(long idealStorageSize) throws Exception { + try { + String packageName = mContext.getPackageName(); + PackageDataObserver observer = new PackageDataObserver(); + //wait on observer + synchronized(observer) { + getPm().freeStorageAndNotify(idealStorageSize, observer); + long waitTime = 0; + while(!observer.isDone() || (waitTime > MAX_WAIT_TIME)) { + observer.wait(WAIT_TIME_INCR); + waitTime += WAIT_TIME_INCR; + } + if(!observer.isDone()) { + throw new Exception("timed out waiting for PackageDataObserver.onRemoveCompleted"); + } + } + return observer.retValue; + } catch (RemoteException e) { + Log.w(TAG, "Failed to get handle for PackageManger Exception: "+e); + return false; + } catch (InterruptedException e) { + Log.w(TAG, "InterruptedException :"+e); + return false; + } + } + + boolean invokePMFreeStorage(long idealStorageSize, FreeStorageReceiver r, + PendingIntent pi) throws Exception { + try { + // Spin lock waiting for call back + synchronized(r) { + getPm().freeStorage(idealStorageSize, pi); + long waitTime = 0; + while(!r.isDone() && (waitTime < MAX_WAIT_TIME)) { + r.wait(WAIT_TIME_INCR); + waitTime += WAIT_TIME_INCR; + } + if(!r.isDone()) { + throw new Exception("timed out waiting for call back from PendingIntent"); + } + } + return r.getResultCode() == 1; + } catch (RemoteException e) { + Log.w(TAG, "Failed to get handle for PackageManger Exception: "+e); + return false; + } catch (InterruptedException e) { + Log.w(TAG, "InterruptedException :"+e); + return false; + } + } + + @LargeTest + public void testDeleteAppCacheFiles() throws Exception { + String testName="testDeleteAppCacheFiles"; + File cacheDir = mContext.getCacheDir(); + createTestFiles1(cacheDir, "testtmpdir", 5); + assertTrue(invokePMDeleteAppCacheFiles()); + //confirm files dont exist + verifyTestFiles1(cacheDir, "testtmpdir", 5); + } + + class PackageStatsObserver extends IPackageStatsObserver.Stub { + public boolean retValue = false; + public PackageStats stats; + private boolean doneFlag = false; + + public void onGetStatsCompleted(PackageStats pStats, boolean succeeded) + throws RemoteException { + synchronized(this) { + retValue = succeeded; + stats = pStats; + doneFlag = true; + notifyAll(); + } + } + public boolean isDone() { + return doneFlag; + } + } + + public PackageStats invokePMGetPackageSizeInfo() throws Exception { + try { + String packageName = mContext.getPackageName(); + PackageStatsObserver observer = new PackageStatsObserver(); + //wait on observer + synchronized(observer) { + getPm().getPackageSizeInfo(packageName, observer); + long waitTime = 0; + while((!observer.isDone()) || (waitTime > MAX_WAIT_TIME) ) { + observer.wait(WAIT_TIME_INCR); + waitTime += WAIT_TIME_INCR; + } + if(!observer.isDone()) { + throw new Exception("Timed out waiting for PackageStatsObserver.onGetStatsCompleted"); + } + } + if(localLOGV) Log.i(TAG, "OBSERVER RET VALUES code="+observer.stats.codeSize+ + ", data="+observer.stats.dataSize+", cache="+observer.stats.cacheSize); + return observer.stats; + } catch (RemoteException e) { + Log.w(TAG, "Failed to get handle for PackageManger Exception: "+e); + return null; + } catch (InterruptedException e) { + Log.w(TAG, "InterruptedException :"+e); + return null; + } + } + + @SmallTest + public void testGetPackageSizeInfo() throws Exception { + String testName="testGetPackageSizeInfo"; + PackageStats stats = invokePMGetPackageSizeInfo(); + assertTrue(stats!=null); + //confirm result + if(localLOGV) Log.i(TAG, "code="+stats.codeSize+", data="+stats.dataSize+ + ", cache="+stats.cacheSize); + } + + @SmallTest + public void testGetSystemSharedLibraryNames() throws Exception { + try { + String[] sharedLibs = getPm().getSystemSharedLibraryNames(); + if (localLOGV) { + for (String str : sharedLibs) { + Log.i(TAG, str); + } + } + } catch (RemoteException e) { + fail("Failed invoking getSystemSharedLibraryNames with exception:" + e); + } + } + + class FreeStorageReceiver extends BroadcastReceiver { + public static final String ACTION_FREE = "com.android.unit_tests.testcallback"; + private boolean doneFlag = false; + + public boolean isDone() { + return doneFlag; + } + + @Override + public void onReceive(Context context, Intent intent) { + if(intent.getAction().equalsIgnoreCase(ACTION_FREE)) { + if (localLOGV) Log.i(TAG, "Got notification: clear cache succeeded "+getResultCode()); + synchronized (this) { + doneFlag = true; + notifyAll(); + } + } + } + } + + @SmallTest + public void testFreeStorage() throws Exception { + boolean TRACKING = true; + StatFs st = new StatFs("/data"); + long blks1 = getFreeStorageBlks(st); + if(localLOGV || TRACKING) Log.i(TAG, "Available free blocks="+blks1); + long availableMem = getFreeStorageSize(st); + File cacheDir = mContext.getCacheDir(); + assertNotNull(cacheDir); + createTestFiles1(cacheDir, "testtmpdir", 5); + long blks2 = getFreeStorageBlks(st); + if(localLOGV || TRACKING) Log.i(TAG, "Available blocks after writing test files in application cache="+blks2); + // Create receiver and register it + FreeStorageReceiver receiver = new FreeStorageReceiver(); + mContext.registerReceiver(receiver, new IntentFilter(FreeStorageReceiver.ACTION_FREE)); + PendingIntent pi = PendingIntent.getBroadcast(mContext, + 0, new Intent(FreeStorageReceiver.ACTION_FREE), 0); + // Invoke PackageManager api + invokePMFreeStorage(availableMem, receiver, pi); + long blks3 = getFreeStorageBlks(st); + if(localLOGV || TRACKING) Log.i(TAG, "Available blocks after freeing cache"+blks3); + assertEquals(receiver.getResultCode(), 1); + mContext.unregisterReceiver(receiver); + // Verify result + verifyTestFiles1(cacheDir, "testtmpdir", 5); + } + + /* utility method used to create observer and check async call back from PackageManager. + * ClearApplicationUserData + */ + boolean invokePMClearApplicationUserData() throws Exception { + try { + String packageName = mContext.getPackageName(); + PackageDataObserver observer = new PackageDataObserver(); + //wait on observer + synchronized(observer) { + getPm().clearApplicationUserData(packageName, observer); + long waitTime = 0; + while(!observer.isDone() || (waitTime > MAX_WAIT_TIME)) { + observer.wait(WAIT_TIME_INCR); + waitTime += WAIT_TIME_INCR; + } + if(!observer.isDone()) { + throw new Exception("timed out waiting for PackageDataObserver.onRemoveCompleted"); + } + } + return observer.retValue; + } catch (RemoteException e) { + Log.w(TAG, "Failed to get handle for PackageManger Exception: "+e); + return false; + } catch (InterruptedException e) { + Log.w(TAG, "InterruptedException :"+e); + return false; + } + } + + void verifyUserDataCleared(File pDir) { + if(localLOGV) Log.i(TAG, "Verifying "+pDir); + if(pDir == null) { + return; + } + String fileList[] = pDir.list(); + if(fileList == null) { + return; + } + int imax = fileList.length; + //look recursively in user data dir + for(int i = 0; i < imax; i++) { + if(localLOGV) Log.i(TAG, "Found entry "+fileList[i]+ "in "+pDir); + if("lib".equalsIgnoreCase(fileList[i])) { + if(localLOGV) Log.i(TAG, "Ignoring lib directory"); + continue; + } + fail(pDir+" should be empty or contain only lib subdirectory. Found "+fileList[i]); + } + } + + File getDataDir() { + try { + ApplicationInfo appInfo = getPm().getApplicationInfo(mContext.getPackageName(), 0); + return new File(appInfo.dataDir); + } catch (RemoteException e) { + throw new RuntimeException("Pacakge manager dead", e); + } + } + + @LargeTest + public void testClearApplicationUserDataWithTestData() throws Exception { + File cacheDir = mContext.getCacheDir(); + createTestFiles1(cacheDir, "testtmpdir", 5); + if(localLOGV) { + Log.i(TAG, "Created test data Waiting for 60seconds before continuing"); + Thread.sleep(60*1000); + } + assertTrue(invokePMClearApplicationUserData()); + //confirm files dont exist + verifyUserDataCleared(getDataDir()); + } + + @SmallTest + public void testClearApplicationUserDataWithNoTestData() throws Exception { + assertTrue(invokePMClearApplicationUserData()); + //confirm files dont exist + verifyUserDataCleared(getDataDir()); + } + + @LargeTest + public void testClearApplicationUserDataNoObserver() throws Exception { + getPm().clearApplicationUserData(mContext.getPackageName(), null); + //sleep for 1 minute + Thread.sleep(60*1000); + //confirm files dont exist + verifyUserDataCleared(getDataDir()); + } + +} diff --git a/tests/AndroidTests/src/com/android/unit_tests/ArrayListTest.java b/tests/AndroidTests/src/com/android/unit_tests/ArrayListTest.java new file mode 100644 index 0000000..81e6efd --- /dev/null +++ b/tests/AndroidTests/src/com/android/unit_tests/ArrayListTest.java @@ -0,0 +1,327 @@ +/* + * 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.unit_tests; + +import java.util.ArrayList; +import android.test.PerformanceTestBase; + +public class ArrayListTest extends PerformanceTestBase { + + private ArrayList<Integer> mList; + + @Override + @SuppressWarnings("unchecked") + protected void setUp() throws Exception { + super.setUp(); + + mList = new ArrayList(); + mList.add(0); + mList.add(1); + mList.add(2); + mList.add(3); + mList.add(4); + mList.add(5); + mList.add(6); + mList.add(7); + mList.add(8); + mList.add(9); + } + + public void testArrayListAdd() { + int i = 0; + for (; i < 10; i++) { + mList.add(i); + mList.add(i); + mList.add(i); + mList.add(i); + mList.add(i); + mList.add(i); + mList.add(i); + mList.add(i); + mList.add(i); + mList.add(i); + } + } + + public void testArrayListAdd1() { + int i = 0; + for (; i < 10; i++) { + mList.add(7, i); + mList.add(7, i); + mList.add(7, i); + mList.add(7, i); + mList.add(7, i); + mList.add(7, i); + mList.add(7, i); + mList.add(7, i); + mList.add(7, i); + mList.add(7, i); + } + } + + public void testArrayListToArray() { + Object rArray; + int i = 0; + for (; i < 100; i++) { + rArray = mList.toArray(); + rArray = mList.toArray(); + rArray = mList.toArray(); + rArray = mList.toArray(); + rArray = mList.toArray(); + rArray = mList.toArray(); + rArray = mList.toArray(); + rArray = mList.toArray(); + rArray = mList.toArray(); + rArray = mList.toArray(); + } + } + + public void testArrayListSize() { + int i = 0, len; + for (; i < 100; i++) { + len = mList.size(); + len = mList.size(); + len = mList.size(); + len = mList.size(); + len = mList.size(); + len = mList.size(); + len = mList.size(); + len = mList.size(); + len = mList.size(); + len = mList.size(); + } + } + + public void testArrayListGet() { + int i = 0, value; + int len = mList.size(); + for (; i < len; i++) { + value = mList.get(i); + value = mList.get(i); + value = mList.get(i); + value = mList.get(i); + value = mList.get(i); + value = mList.get(i); + value = mList.get(i); + value = mList.get(i); + value = mList.get(i); + value = mList.get(i); + } + } + + public void testArrayListContains() { + boolean flag; + int i = 0; + + for (; i < 100; i++) { + flag = mList.contains(i); + flag = mList.contains(i); + flag = mList.contains(i); + flag = mList.contains(i); + flag = mList.contains(i); + flag = mList.contains(i); + flag = mList.contains(i); + flag = mList.contains(i); + flag = mList.contains(i); + flag = mList.contains(i); + + } + } + + public void testArrayListToArray1() { + Integer[] rArray = new Integer[10]; + + Integer[] mArray; + int i = 0; + for (; i < 100; i++) { + mArray = mList.toArray(rArray); + mArray = mList.toArray(rArray); + mArray = mList.toArray(rArray); + mArray = mList.toArray(rArray); + mArray = mList.toArray(rArray); + mArray = mList.toArray(rArray); + mArray = mList.toArray(rArray); + mArray = mList.toArray(rArray); + mArray = mList.toArray(rArray); + mArray = mList.toArray(rArray); + } + } + + public void testArrayListSet() { + int i = 0; + for (; i < 10; i++) { + mList.set(5, 0); + mList.set(5, 0); + mList.set(5, 0); + mList.set(5, 0); + mList.set(5, 0); + mList.set(5, 0); + mList.set(5, 0); + mList.set(5, 0); + mList.set(5, 0); + mList.set(5, 0); + } + } + + public void testArrayListIndexOf() { + int i = 0, index; + + for (; i < 100; i++) { + index = mList.indexOf(0); + index = mList.indexOf(0); + index = mList.indexOf(0); + index = mList.indexOf(0); + index = mList.indexOf(0); + index = mList.indexOf(0); + index = mList.indexOf(0); + index = mList.indexOf(0); + index = mList.indexOf(0); + index = mList.indexOf(0); + } + } + + public void testArrayListLastIndexOf() { + int i = 0, index; + + for (; i < 100; i++) { + index = mList.lastIndexOf(0); + index = mList.lastIndexOf(0); + index = mList.lastIndexOf(0); + index = mList.lastIndexOf(0); + index = mList.lastIndexOf(0); + index = mList.lastIndexOf(0); + index = mList.lastIndexOf(0); + index = mList.lastIndexOf(0); + index = mList.lastIndexOf(0); + index = mList.lastIndexOf(0); + } + } + + @SuppressWarnings("unchecked") + public void testArrayListRemove() { + ArrayList<Integer> aList; + aList = new ArrayList(); + for (int j = 0; j < 10000; j++) { + aList.add(0); + } + + int i = 0, index; + + for (; i < 10; i++) { + index = aList.remove(0); + index = aList.remove(0); + index = aList.remove(0); + index = aList.remove(0); + index = aList.remove(0); + index = aList.remove(0); + index = aList.remove(0); + index = aList.remove(0); + index = aList.remove(0); + index = aList.remove(0); + + + } + } + + @SuppressWarnings("unchecked") + public void testArrayListAddAll() { + ArrayList<Integer> aList = new ArrayList(); + + int i = 0; + boolean b; + for (; i < 10; i++) { + b = aList.addAll(mList); + b = aList.addAll(mList); + b = aList.addAll(mList); + b = aList.addAll(mList); + b = aList.addAll(mList); + b = aList.addAll(mList); + b = aList.addAll(mList); + b = aList.addAll(mList); + b = aList.addAll(mList); + b = aList.addAll(mList); + + } + } + + @SuppressWarnings("unchecked") + public void testArrayListRemove1() { + ArrayList<String> aList; + String s; + + aList = new ArrayList(); + for (int j = 0; j < 100; j++) { + aList.add("a"); + aList.add("b"); + } + s = new String("a"); + + int i = 0; + boolean b; + for (; i < 10; i++) { + b = aList.remove(s); + b = aList.remove(s); + b = aList.remove(s); + b = aList.remove(s); + b = aList.remove(s); + b = aList.remove(s); + b = aList.remove(s); + b = aList.remove(s); + b = aList.remove(s); + b = aList.remove(s); + } + } + + @SuppressWarnings("unchecked") + public void testArrayListAddAll1() { + ArrayList<Integer> aList = new ArrayList(); + + int i = 0; + boolean b; + + for (; i < 10; i++) { + b = aList.addAll(0, mList); + b = aList.addAll(0, mList); + b = aList.addAll(0, mList); + b = aList.addAll(0, mList); + b = aList.addAll(0, mList); + b = aList.addAll(0, mList); + b = aList.addAll(0, mList); + b = aList.addAll(0, mList); + b = aList.addAll(0, mList); + b = aList.addAll(0, mList); + } + } + + public void testArrayListClone() { + Object rObj; + int i = 0; + + for (; i < 100; i++) { + rObj = mList.clone(); + rObj = mList.clone(); + rObj = mList.clone(); + rObj = mList.clone(); + rObj = mList.clone(); + rObj = mList.clone(); + rObj = mList.clone(); + rObj = mList.clone(); + rObj = mList.clone(); + rObj = mList.clone(); + } + } +} diff --git a/tests/AndroidTests/src/com/android/unit_tests/BrickDeniedTest.java b/tests/AndroidTests/src/com/android/unit_tests/BrickDeniedTest.java new file mode 100644 index 0000000..0f2b23b --- /dev/null +++ b/tests/AndroidTests/src/com/android/unit_tests/BrickDeniedTest.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 com.android.unit_tests; + +import android.content.Intent; +import android.test.AndroidTestCase; +import android.test.suitebuilder.annotation.MediumTest; + +/** Test to make sure brick intents <b>don't</b> work without permission. */ +public class BrickDeniedTest extends AndroidTestCase { + @MediumTest + public void testBrick() { + // Try both the old and new brick intent names. Neither should work, + // since this test application doesn't have the required permission. + // If it does work, well, the test certainly won't pass. + getContext().sendBroadcast(new Intent("SHES_A_BRICK_HOUSE")); + getContext().sendBroadcast(new Intent("android.intent.action.BRICK")); + } +} diff --git a/tests/AndroidTests/src/com/android/unit_tests/BuildTest.java b/tests/AndroidTests/src/com/android/unit_tests/BuildTest.java new file mode 100644 index 0000000..dbfd0e7 --- /dev/null +++ b/tests/AndroidTests/src/com/android/unit_tests/BuildTest.java @@ -0,0 +1,131 @@ +/* + * Copyright (C) 2008 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.unit_tests; + +import android.os.Build; +import android.server.data.BuildData; +import android.test.suitebuilder.annotation.SmallTest; +import android.util.Log; +import junit.framework.Assert; +import junit.framework.TestCase; + +/** + * Provides test cases for android.os.Build and android.server.data.BuildData, + * and, in turn, many of the system properties set by the build system. + */ +public class BuildTest extends TestCase { + + private static final String TAG = "BuildTest"; + + /** + * Asserts that a String is non-null and non-empty. If it is not, + * an AssertionFailedError is thrown with the given message. + */ + private static void assertNotEmpty(String message, String string) { + //Log.i(TAG, "" + message + ": " + string); + assertNotNull(message, string); + assertFalse(message, string.equals("")); + } + + /** + * Asserts that a String is non-null and non-empty. If it is not, + * an AssertionFailedError is thrown. + */ + private static void assertNotEmpty(String string) { + assertNotEmpty(null, string); + } + + /** + * Asserts that all android.os.Build fields are non-empty and/or in a valid range. + */ + @SmallTest + public void testBuildFields() throws Exception { + assertNotEmpty("ID", Build.ID); + assertNotEmpty("DISPLAY", Build.DISPLAY); + assertNotEmpty("PRODUCT", Build.PRODUCT); + assertNotEmpty("DEVICE", Build.DEVICE); + assertNotEmpty("BOARD", Build.BOARD); + assertNotEmpty("BRAND", Build.BRAND); + assertNotEmpty("MODEL", Build.MODEL); + assertNotEmpty("VERSION.INCREMENTAL", Build.VERSION.INCREMENTAL); + assertNotEmpty("VERSION.RELEASE", Build.VERSION.RELEASE); + assertNotEmpty("TYPE", Build.TYPE); + Assert.assertNotNull("TAGS", Build.TAGS); // TAGS is allowed to be empty. + assertNotEmpty("FINGERPRINT", Build.FINGERPRINT); + Assert.assertTrue("TIME", Build.TIME > 0); + assertNotEmpty("USER", Build.USER); + assertNotEmpty("HOST", Build.HOST); + + // TODO: if any of the android.os.Build fields have additional constraints + // (e.g., must be a C identifier, must be a valid filename, must not contain any spaces) + // add tests for them. + } + + /** + * Asserts that android.server.data.BuildData behaves as expected. + */ + @SmallTest + public void testBuildData() throws Exception { + BuildData bd; + + /* + * Default constructor + */ + bd = new BuildData(); + assertNotEmpty(bd.getFingerprint()); + assertNotEmpty(bd.getIncrementalVersion()); + Assert.assertTrue(bd.getTime() > 0); + + /* + * Explicit constructor + */ + final String FINGERPRINT = "fingerprint"; + final String INCREMENTAL_VERSION = "74321"; // a valid long, for the serialization test + final long TIME = 12345; + bd = new BuildData(FINGERPRINT, INCREMENTAL_VERSION, TIME); + Assert.assertEquals(FINGERPRINT, bd.getFingerprint()); + Assert.assertEquals(INCREMENTAL_VERSION, bd.getIncrementalVersion()); + Assert.assertTrue(bd.getTime() == TIME); + +// The serialization methods are package-private. +// +// import java.io.ByteArrayInputStream; +// import java.io.ByteArrayOutputStream; +// import java.io.DataInputStream; +// import java.io.DataOutputStream; +// +// /* +// * Serialization +// */ +// ByteArrayOutputStream out = new ByteArrayOutputStream(); +// bd.write(new DataOutputStream(out)); +// Assert.assertTrue(out.size() > 0); +// +// /* +// * Deserialization +// * +// * The current version of BuildData converts the incremental version to +// * and from a long when serializing/deserializing. Future versions should +// * treat it as a string. +// */ +// BuildData bd2 = +// new BuildData(new DataInputStream(new ByteArrayInputStream(out.toByteArray()))); +// Assert.assertEquals(bd.getFingerprint(), bd2.getFingerprint()); +// Assert.assertEquals(bd.getIncrementalVersion(), bd2.getIncrementalVersion()); +// Assert.assertTrue(bd.getTime() == bd2.getTime()); + } +} diff --git a/tests/AndroidTests/src/com/android/unit_tests/CharSequencesTest.java b/tests/AndroidTests/src/com/android/unit_tests/CharSequencesTest.java new file mode 100644 index 0000000..092f309 --- /dev/null +++ b/tests/AndroidTests/src/com/android/unit_tests/CharSequencesTest.java @@ -0,0 +1,58 @@ +/* + * 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.unit_tests; + +import com.android.internal.util.CharSequences; +import static com.android.internal.util.CharSequences.forAsciiBytes; +import junit.framework.TestCase; +import android.test.suitebuilder.annotation.SmallTest; + +public class CharSequencesTest extends TestCase { + + @SmallTest + public void testCharSequences() { + String s = "Crazy Bob"; + byte[] bytes = s.getBytes(); + + String copy = toString(forAsciiBytes(bytes)); + assertTrue(s.equals(copy)); + + copy = toString(forAsciiBytes(bytes, 0, s.length())); + assertTrue(s.equals(copy)); + + String crazy = toString(forAsciiBytes(bytes, 0, 5)); + assertTrue("Crazy".equals(crazy)); + + String a = toString(forAsciiBytes(bytes, 0, 3).subSequence(2, 3)); + assertTrue("a".equals(a)); + + String empty = toString(forAsciiBytes(bytes, 0, 3).subSequence(3, 3)); + assertTrue("".equals(empty)); + + assertTrue(CharSequences.equals("bob", "bob")); + assertFalse(CharSequences.equals("b", "bob")); + assertFalse(CharSequences.equals("", "bob")); + } + + /** + * Converts a CharSequence to a string the slow way. Useful for testing + * a CharSequence implementation. + */ + static String toString(CharSequence charSequence) { + return new StringBuilder().append(charSequence).toString(); + } +} diff --git a/tests/AndroidTests/src/com/android/unit_tests/ComponentTest.java b/tests/AndroidTests/src/com/android/unit_tests/ComponentTest.java new file mode 100644 index 0000000..08fe742 --- /dev/null +++ b/tests/AndroidTests/src/com/android/unit_tests/ComponentTest.java @@ -0,0 +1,738 @@ +/* + * Copyright (C) 2008 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.unit_tests; + +import com.android.unit_tests.enabled_app.DisabledActivity; +import com.android.unit_tests.enabled_app.DisabledProvider; +import com.android.unit_tests.enabled_app.DisabledReceiver; +import com.android.unit_tests.enabled_app.DisabledService; +import com.android.unit_tests.enabled_app.EnabledActivity; +import com.android.unit_tests.enabled_app.EnabledProvider; +import com.android.unit_tests.enabled_app.EnabledReceiver; +import com.android.unit_tests.enabled_app.EnabledService; + +import android.content.ComponentName; +import android.content.Intent; +import android.content.pm.ActivityInfo; +import android.content.pm.ComponentInfo; +import android.content.pm.PackageInfo; +import android.content.pm.PackageManager; +import android.test.suitebuilder.annotation.LargeTest; +import android.test.suitebuilder.annotation.MediumTest; +import android.test.suitebuilder.annotation.SmallTest; +import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DEFAULT; +import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DISABLED; +import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_ENABLED; +import static android.content.pm.PackageManager.GET_DISABLED_COMPONENTS; +import android.content.pm.ProviderInfo; +import android.content.pm.ResolveInfo; +import android.content.pm.ServiceInfo; +import android.test.AndroidTestCase; + +import java.util.List; + +/** + * Tests for disabling and enabling application components. + * + * Note: These tests are on the slow side. This is probably because most of the tests trigger the + * package settings file to get written out by the PackageManagerService. Better, more unit-y test + * would fix this. + */ + +public class ComponentTest extends AndroidTestCase { + + private PackageManager mPackageManager; + private Intent mDisabledActivityIntent; + private Intent mEnabledActivityIntent; + private Intent mDisabledServiceIntent; + private Intent mEnabledServiceIntent; + private Intent mDisabledReceiverIntent; + private Intent mEnabledReceiverIntent; + private Intent mDisabledAppEnabledActivityIntent; + + private static final String ENABLED_PACKAGENAME = + "com.android.unit_tests.enabled_app"; + private static final String DISABLED_PACKAGENAME = + "com.android.unit_tests.disabled_app"; + private static final String DISABLED_ACTIVITY_CLASSNAME = + DisabledActivity.class.getName(); + private static final ComponentName DISABLED_ACTIVITY_COMPONENTNAME = + new ComponentName(ENABLED_PACKAGENAME, DISABLED_ACTIVITY_CLASSNAME); + private static final String ENABLED_ACTIVITY_CLASSNAME = + EnabledActivity.class.getName(); + private static final ComponentName ENABLED_ACTIVITY_COMPONENTNAME = + new ComponentName(ENABLED_PACKAGENAME, ENABLED_ACTIVITY_CLASSNAME); + private static final String DISABLED_SERVICE_CLASSNAME = + DisabledService.class.getName(); + private static final ComponentName DISABLED_SERVICE_COMPONENTNAME = + new ComponentName(ENABLED_PACKAGENAME, DISABLED_SERVICE_CLASSNAME); + private static final String DISABLED_PROVIDER_CLASSNAME = + DisabledProvider.class.getName(); + private static final ComponentName DISABLED_PROVIDER_COMPONENTNAME = + new ComponentName(ENABLED_PACKAGENAME, DISABLED_PROVIDER_CLASSNAME); + private static final String DISABLED_PROVIDER_NAME = DisabledProvider.class.getName(); + private static final String ENABLED_SERVICE_CLASSNAME = + EnabledService.class.getName(); + private static final ComponentName ENABLED_SERVICE_COMPONENTNAME = + new ComponentName(ENABLED_PACKAGENAME, ENABLED_SERVICE_CLASSNAME); + private static final String DISABLED_RECEIVER_CLASSNAME = + DisabledReceiver.class.getName(); + private static final ComponentName DISABLED_RECEIVER_COMPONENTNAME = + new ComponentName(ENABLED_PACKAGENAME, DISABLED_RECEIVER_CLASSNAME); + private static final String ENABLED_RECEIVER_CLASSNAME = + EnabledReceiver.class.getName(); + private static final ComponentName ENABLED_RECEIVER_COMPONENTNAME = + new ComponentName(ENABLED_PACKAGENAME, ENABLED_RECEIVER_CLASSNAME); + private static final String ENABLED_PROVIDER_CLASSNAME = + EnabledProvider.class.getName(); + private static final ComponentName ENABLED_PROVIDER_COMPONENTNAME = + new ComponentName(ENABLED_PACKAGENAME, ENABLED_PROVIDER_CLASSNAME); + private static final String ENABLED_PROVIDER_NAME = EnabledProvider.class.getName(); + private static final String DISABLED_APP_ENABLED_ACTIVITY_CLASSNAME = + com.android.unit_tests.disabled_app.EnabledActivity.class.getName(); + private static final ComponentName DISABLED_APP_ENABLED_ACTIVITY_COMPONENTNAME = + new ComponentName(DISABLED_PACKAGENAME, DISABLED_APP_ENABLED_ACTIVITY_CLASSNAME); + private static final String TEST_CATEGORY = + "com.android.unit_tests.enabled_app.TEST_CATEGORY"; + + @Override + protected void setUp() throws Exception { + super.setUp(); + mPackageManager = mContext.getPackageManager(); + mDisabledActivityIntent = new Intent(); + mDisabledActivityIntent.setComponent(DISABLED_ACTIVITY_COMPONENTNAME); + mEnabledActivityIntent = new Intent(); + mEnabledActivityIntent.setComponent(ENABLED_ACTIVITY_COMPONENTNAME); + mDisabledServiceIntent = new Intent(); + mDisabledServiceIntent.setComponent(DISABLED_SERVICE_COMPONENTNAME); + mEnabledServiceIntent = new Intent(); + mEnabledServiceIntent.setComponent(ENABLED_SERVICE_COMPONENTNAME); + mDisabledReceiverIntent = new Intent("android.intent.action.ENABLED_APP_DISABLED_RECEIVER"); + mDisabledReceiverIntent.setComponent(DISABLED_RECEIVER_COMPONENTNAME); + mEnabledReceiverIntent = new Intent("android.intent.action.ENABLED_APP_ENABLED_RECEIVER"); + mEnabledReceiverIntent.setComponent(ENABLED_RECEIVER_COMPONENTNAME); + mDisabledAppEnabledActivityIntent = new Intent(); + mDisabledAppEnabledActivityIntent.setComponent(DISABLED_APP_ENABLED_ACTIVITY_COMPONENTNAME); + } + + @SmallTest + public void testContextNotNull() throws Exception { + assertNotNull(mContext); + } + + @MediumTest + public void testResolveDisabledActivity() throws Exception { + mPackageManager.setComponentEnabledSetting(DISABLED_ACTIVITY_COMPONENTNAME, + COMPONENT_ENABLED_STATE_DEFAULT, + PackageManager.DONT_KILL_APP); + + final ResolveInfo info = mPackageManager.resolveActivity(mDisabledActivityIntent, 0); + assertNull(info); + + final ResolveInfo info2 = mPackageManager.resolveActivity( + mDisabledActivityIntent, GET_DISABLED_COMPONENTS); + assertNotNull(info2); + assertNotNull(info2.activityInfo); + assertFalse(info2.activityInfo.enabled); + } + + @MediumTest + public void testResolveEnabledActivity() throws Exception { + mPackageManager.setComponentEnabledSetting(ENABLED_ACTIVITY_COMPONENTNAME, + COMPONENT_ENABLED_STATE_DEFAULT, + PackageManager.DONT_KILL_APP); + + final ResolveInfo info = mPackageManager.resolveActivity(mEnabledActivityIntent, 0); + assertNotNull(info); + assertNotNull(info); + assertNotNull(info.activityInfo); + assertTrue(info.activityInfo.enabled); + } + + @MediumTest + public void testQueryDisabledActivity() throws Exception { + mPackageManager.setComponentEnabledSetting(DISABLED_ACTIVITY_COMPONENTNAME, + COMPONENT_ENABLED_STATE_DEFAULT, + PackageManager.DONT_KILL_APP); + + final List<ResolveInfo> infoList = + mPackageManager.queryIntentActivities(mDisabledActivityIntent, 0); + assertEquals(0, infoList.size()); + + final List<ResolveInfo> infoList2 = + mPackageManager.queryIntentActivities(mDisabledActivityIntent, + GET_DISABLED_COMPONENTS); + assertEquals(1, infoList2.size()); + final ResolveInfo info = infoList2.get(0); + assertNotNull(info); + assertNotNull(info.activityInfo); + assertFalse(info.activityInfo.enabled); + } + + @MediumTest + public void testQueryEnabledActivity() throws Exception { + mPackageManager.setComponentEnabledSetting(ENABLED_ACTIVITY_COMPONENTNAME, + COMPONENT_ENABLED_STATE_DEFAULT, + PackageManager.DONT_KILL_APP); + + final List<ResolveInfo> infoList = + mPackageManager.queryIntentActivities(mEnabledActivityIntent, 0); + assertEquals(1, infoList.size()); + final ResolveInfo info = infoList.get(0); + assertNotNull(info); + assertNotNull(info.activityInfo); + assertTrue(info.activityInfo.enabled); + } + + @MediumTest + public void testGetDisabledActivityInfo() throws Exception { + mPackageManager.setComponentEnabledSetting(DISABLED_ACTIVITY_COMPONENTNAME, + COMPONENT_ENABLED_STATE_DEFAULT, + PackageManager.DONT_KILL_APP); + + try { + mPackageManager.getActivityInfo(DISABLED_ACTIVITY_COMPONENTNAME, 0); + fail("Attempt to get info on disabled component should fail."); + } catch (PackageManager.NameNotFoundException e) { + // expected + } + + final ActivityInfo activityInfo = + mPackageManager.getActivityInfo(DISABLED_ACTIVITY_COMPONENTNAME, + GET_DISABLED_COMPONENTS); + assertNotNull(activityInfo); + assertFalse(activityInfo.enabled); + } + + @MediumTest + public void testGetEnabledActivityInfo() throws Exception { + mPackageManager.setComponentEnabledSetting(ENABLED_ACTIVITY_COMPONENTNAME, + COMPONENT_ENABLED_STATE_DEFAULT, + PackageManager.DONT_KILL_APP); + + ActivityInfo activityInfo = + mPackageManager.getActivityInfo(ENABLED_ACTIVITY_COMPONENTNAME, 0); + assertNotNull(activityInfo); + assertTrue(activityInfo.enabled); + } + + @MediumTest + public void testEnableActivity() throws Exception { + mPackageManager.setComponentEnabledSetting(DISABLED_ACTIVITY_COMPONENTNAME, + COMPONENT_ENABLED_STATE_DEFAULT, + PackageManager.DONT_KILL_APP); + + final ResolveInfo info = mPackageManager.resolveActivity(mDisabledActivityIntent, 0); + assertNull(info); + mPackageManager.setComponentEnabledSetting(DISABLED_ACTIVITY_COMPONENTNAME, + COMPONENT_ENABLED_STATE_ENABLED, + PackageManager.DONT_KILL_APP); + final ResolveInfo info2 = + mPackageManager.resolveActivity(mDisabledActivityIntent, + 0); + assertNotNull(info2); + assertNotNull(info2.activityInfo); + assertFalse(info2.activityInfo.enabled); + + final List<ResolveInfo> infoList = + mPackageManager.queryIntentActivities(mDisabledActivityIntent, 0); + assertEquals(1, infoList.size()); + } + + @LargeTest + public void testDisableActivity() throws Exception { + mPackageManager.setComponentEnabledSetting(ENABLED_ACTIVITY_COMPONENTNAME, + COMPONENT_ENABLED_STATE_DEFAULT, + PackageManager.DONT_KILL_APP); + + final ResolveInfo info = mPackageManager.resolveActivity(mEnabledActivityIntent, 0); + assertNotNull(info); + assertNotNull(info.activityInfo); + mPackageManager.setComponentEnabledSetting(ENABLED_ACTIVITY_COMPONENTNAME, + COMPONENT_ENABLED_STATE_DISABLED, + PackageManager.DONT_KILL_APP); + final ResolveInfo info2 = + mPackageManager.resolveActivity(mEnabledActivityIntent, + 0); + assertNull(info2); + + final ResolveInfo info3 = mPackageManager.resolveActivity(mEnabledActivityIntent, + GET_DISABLED_COMPONENTS); + assertNotNull(info3); + assertNotNull(info3.activityInfo); + assertTrue(info3.activityInfo.enabled); + + final List<ResolveInfo> infoList = + mPackageManager.queryIntentActivities(mEnabledActivityIntent, 0); + assertEquals(0, infoList.size()); + } + + @MediumTest + public void testResolveDisabledService() throws Exception { + mPackageManager.setComponentEnabledSetting(DISABLED_SERVICE_COMPONENTNAME, + COMPONENT_ENABLED_STATE_DEFAULT, + PackageManager.DONT_KILL_APP); + + final ResolveInfo info = mPackageManager.resolveService(mDisabledServiceIntent, 0); + assertNull(info); + + final ResolveInfo info2 = mPackageManager.resolveService( + mDisabledServiceIntent, GET_DISABLED_COMPONENTS); + assertNotNull(info2); + assertNotNull(info2.serviceInfo); + assertFalse(info2.serviceInfo.enabled); + } + + @MediumTest + public void testResolveEnabledService() throws Exception { + mPackageManager.setComponentEnabledSetting(ENABLED_SERVICE_COMPONENTNAME, + COMPONENT_ENABLED_STATE_DEFAULT, + PackageManager.DONT_KILL_APP); + + final ResolveInfo info = mPackageManager.resolveService(mEnabledServiceIntent, 0); + assertNotNull(info); + assertNotNull(info); + assertNotNull(info.serviceInfo); + assertTrue(info.serviceInfo.enabled); + } + + @MediumTest + public void testQueryDisabledService() throws Exception { + mPackageManager.setComponentEnabledSetting(DISABLED_SERVICE_COMPONENTNAME, + COMPONENT_ENABLED_STATE_DEFAULT, + PackageManager.DONT_KILL_APP); + + final List<ResolveInfo> infoList = + mPackageManager.queryIntentServices(mDisabledServiceIntent, 0); + assertEquals(0, infoList.size()); + + final List<ResolveInfo> infoList2 = + mPackageManager.queryIntentServices(mDisabledServiceIntent, + GET_DISABLED_COMPONENTS); + assertEquals(1, infoList2.size()); + final ResolveInfo info = infoList2.get(0); + assertNotNull(info); + assertNotNull(info.serviceInfo); + assertFalse(info.serviceInfo.enabled); + } + + @MediumTest + public void testQueryEnabledService() throws Exception { + mPackageManager.setComponentEnabledSetting(ENABLED_SERVICE_COMPONENTNAME, + COMPONENT_ENABLED_STATE_DEFAULT, + PackageManager.DONT_KILL_APP); + + final List<ResolveInfo> infoList = + mPackageManager.queryIntentServices(mEnabledServiceIntent, 0); + assertEquals(1, infoList.size()); + final ResolveInfo info = infoList.get(0); + assertNotNull(info); + assertNotNull(info.serviceInfo); + assertTrue(info.serviceInfo.enabled); + } + + @MediumTest + public void testGetDisabledServiceInfo() throws Exception { + mPackageManager.setComponentEnabledSetting(DISABLED_SERVICE_COMPONENTNAME, + COMPONENT_ENABLED_STATE_DEFAULT, + PackageManager.DONT_KILL_APP); + + try { + mPackageManager.getServiceInfo(DISABLED_SERVICE_COMPONENTNAME, 0); + fail("Attempt to get info on disabled component should fail."); + } catch (PackageManager.NameNotFoundException e) { + // expected + } + + final ServiceInfo serviceInfo = + mPackageManager.getServiceInfo(DISABLED_SERVICE_COMPONENTNAME, + GET_DISABLED_COMPONENTS); + assertNotNull(serviceInfo); + assertFalse(serviceInfo.enabled); + } + + @MediumTest + public void testGetEnabledServiceInfo() throws Exception { + mPackageManager.setComponentEnabledSetting(ENABLED_SERVICE_COMPONENTNAME, + COMPONENT_ENABLED_STATE_DEFAULT, + PackageManager.DONT_KILL_APP); + + ServiceInfo serviceInfo = + mPackageManager.getServiceInfo(ENABLED_SERVICE_COMPONENTNAME, 0); + assertNotNull(serviceInfo); + assertTrue(serviceInfo.enabled); + } + + @MediumTest + public void testEnableService() throws Exception { + mPackageManager.setComponentEnabledSetting(DISABLED_SERVICE_COMPONENTNAME, + COMPONENT_ENABLED_STATE_DEFAULT, + PackageManager.DONT_KILL_APP); + + final ResolveInfo info = mPackageManager.resolveService(mDisabledServiceIntent, 0); + assertNull(info); + mPackageManager.setComponentEnabledSetting(DISABLED_SERVICE_COMPONENTNAME, + COMPONENT_ENABLED_STATE_ENABLED, + PackageManager.DONT_KILL_APP); + final ResolveInfo info2 = + mPackageManager.resolveService(mDisabledServiceIntent, + 0); + assertNotNull(info2); + assertNotNull(info2.serviceInfo); + assertFalse(info2.serviceInfo.enabled); + } + + @LargeTest + public void testDisableService() throws Exception { + mPackageManager.setComponentEnabledSetting(ENABLED_SERVICE_COMPONENTNAME, + COMPONENT_ENABLED_STATE_DEFAULT, + PackageManager.DONT_KILL_APP); + + final ResolveInfo info = mPackageManager.resolveService(mEnabledServiceIntent, 0); + assertNotNull(info); + assertNotNull(info.serviceInfo); + mPackageManager.setComponentEnabledSetting(ENABLED_SERVICE_COMPONENTNAME, + COMPONENT_ENABLED_STATE_DISABLED, + PackageManager.DONT_KILL_APP); + final ResolveInfo info2 = + mPackageManager.resolveService(mEnabledServiceIntent, + 0); + assertNull(info2); + + final ResolveInfo info3 = mPackageManager.resolveService(mEnabledServiceIntent, + GET_DISABLED_COMPONENTS); + assertNotNull(info3); + assertNotNull(info3.serviceInfo); + assertTrue(info3.serviceInfo.enabled); + } + + @MediumTest + public void testQueryDisabledReceiver() throws Exception { + mPackageManager.setComponentEnabledSetting(DISABLED_RECEIVER_COMPONENTNAME, + COMPONENT_ENABLED_STATE_DEFAULT, + PackageManager.DONT_KILL_APP); + + final List<ResolveInfo> infoList = + mPackageManager.queryBroadcastReceivers(mDisabledReceiverIntent, 0); + assertEquals(0, infoList.size()); + + final List<ResolveInfo> infoList2 = + mPackageManager.queryBroadcastReceivers(mDisabledReceiverIntent, + GET_DISABLED_COMPONENTS); + assertEquals(1, infoList2.size()); + final ResolveInfo info = infoList2.get(0); + assertNotNull(info); + assertNotNull(info.activityInfo); + assertFalse(info.activityInfo.enabled); + } + + @MediumTest + public void testQueryEnabledReceiver() throws Exception { + mPackageManager.setComponentEnabledSetting(ENABLED_RECEIVER_COMPONENTNAME, + COMPONENT_ENABLED_STATE_DEFAULT, + PackageManager.DONT_KILL_APP); + + final List<ResolveInfo> infoList = + mPackageManager.queryBroadcastReceivers(mEnabledReceiverIntent, 0); + assertEquals(1, infoList.size()); + final ResolveInfo info = infoList.get(0); + assertNotNull(info); + assertNotNull(info.activityInfo); + assertTrue(info.activityInfo.enabled); + } + + @MediumTest + public void testGetDisabledReceiverInfo() throws Exception { + mPackageManager.setComponentEnabledSetting(DISABLED_RECEIVER_COMPONENTNAME, + COMPONENT_ENABLED_STATE_DEFAULT, + PackageManager.DONT_KILL_APP); + + try { + mPackageManager.getReceiverInfo(DISABLED_RECEIVER_COMPONENTNAME, 0); + fail("Attempt to get info on disabled component should fail."); + } catch (PackageManager.NameNotFoundException e) { + // expected + } + + final ActivityInfo activityInfo = + mPackageManager.getReceiverInfo(DISABLED_RECEIVER_COMPONENTNAME, + GET_DISABLED_COMPONENTS); + assertNotNull(activityInfo); + assertFalse(activityInfo.enabled); + } + + @MediumTest + public void testGetEnabledReceiverInfo() throws Exception { + mPackageManager.setComponentEnabledSetting(ENABLED_RECEIVER_COMPONENTNAME, + COMPONENT_ENABLED_STATE_DEFAULT, + PackageManager.DONT_KILL_APP); + + ActivityInfo activityInfo = + mPackageManager.getReceiverInfo(ENABLED_RECEIVER_COMPONENTNAME, 0); + assertNotNull(activityInfo); + assertTrue(activityInfo.enabled); + } + + @MediumTest + public void testEnableReceiver() throws Exception { + mPackageManager.setComponentEnabledSetting(DISABLED_RECEIVER_COMPONENTNAME, + COMPONENT_ENABLED_STATE_DEFAULT, + PackageManager.DONT_KILL_APP); + + try { + mPackageManager.getReceiverInfo(DISABLED_RECEIVER_COMPONENTNAME, 0); + fail("Attempt to get info on disabled component should fail."); + } catch (PackageManager.NameNotFoundException e) { + // expected + } + + mPackageManager.setComponentEnabledSetting(DISABLED_RECEIVER_COMPONENTNAME, + COMPONENT_ENABLED_STATE_ENABLED, + PackageManager.DONT_KILL_APP); + ActivityInfo activityInfo = + mPackageManager.getReceiverInfo(DISABLED_RECEIVER_COMPONENTNAME, 0); + assertNotNull(activityInfo); + assertFalse(activityInfo.enabled); + } + + @MediumTest + public void testDisableReceiver() throws Exception { + mPackageManager.setComponentEnabledSetting(ENABLED_RECEIVER_COMPONENTNAME, + COMPONENT_ENABLED_STATE_DEFAULT, + PackageManager.DONT_KILL_APP); + + ActivityInfo activityInfo = + mPackageManager.getReceiverInfo(ENABLED_RECEIVER_COMPONENTNAME, 0); + assertNotNull(activityInfo); + assertTrue(activityInfo.enabled); + mPackageManager.setComponentEnabledSetting(DISABLED_RECEIVER_COMPONENTNAME, + COMPONENT_ENABLED_STATE_DISABLED, + PackageManager.DONT_KILL_APP); + try { + mPackageManager.getReceiverInfo(DISABLED_RECEIVER_COMPONENTNAME, 0); + fail("Attempt to get info on disabled component should fail."); + } catch (PackageManager.NameNotFoundException e) { + // expected + } + } + + @MediumTest + public void testResolveEnabledProvider() throws Exception { + mPackageManager.setComponentEnabledSetting(ENABLED_PROVIDER_COMPONENTNAME, + COMPONENT_ENABLED_STATE_DEFAULT, + PackageManager.DONT_KILL_APP); + + ProviderInfo providerInfo = + mPackageManager.resolveContentProvider(ENABLED_PROVIDER_NAME, 0); + assertNotNull(providerInfo); + assertTrue(providerInfo.enabled); + } + + @MediumTest + public void testResolveDisabledProvider() throws Exception { + mPackageManager.setComponentEnabledSetting(DISABLED_PROVIDER_COMPONENTNAME, + COMPONENT_ENABLED_STATE_DEFAULT, + PackageManager.DONT_KILL_APP); + + ProviderInfo providerInfo = + mPackageManager.resolveContentProvider(DISABLED_PROVIDER_NAME, 0); + assertNull(providerInfo); + ProviderInfo providerInfo2 = + mPackageManager.resolveContentProvider(DISABLED_PROVIDER_NAME, + GET_DISABLED_COMPONENTS); + assertNotNull(providerInfo2); + assertFalse(providerInfo2.enabled); + } + + @MediumTest + public void testEnableProvider() throws Exception { + mPackageManager.setComponentEnabledSetting(DISABLED_PROVIDER_COMPONENTNAME, + COMPONENT_ENABLED_STATE_DEFAULT, + PackageManager.DONT_KILL_APP); + ProviderInfo providerInfo = + mPackageManager.resolveContentProvider(DISABLED_PROVIDER_NAME, 0); + assertNull(providerInfo); + + mPackageManager.setComponentEnabledSetting(DISABLED_PROVIDER_COMPONENTNAME, + COMPONENT_ENABLED_STATE_ENABLED, + PackageManager.DONT_KILL_APP); + ProviderInfo providerInfo2 = + mPackageManager.resolveContentProvider(DISABLED_PROVIDER_NAME, 0); + assertNotNull(providerInfo2); + assertFalse(providerInfo2.enabled); + } + + @MediumTest + public void testDisableProvider() throws Exception { + mPackageManager.setComponentEnabledSetting(ENABLED_PROVIDER_COMPONENTNAME, + COMPONENT_ENABLED_STATE_DEFAULT, + PackageManager.DONT_KILL_APP); + ProviderInfo providerInfo = + mPackageManager.resolveContentProvider(ENABLED_PROVIDER_NAME, 0); + assertNotNull(providerInfo); + assertTrue(providerInfo.enabled); + + mPackageManager.setComponentEnabledSetting(ENABLED_PROVIDER_COMPONENTNAME, + COMPONENT_ENABLED_STATE_DISABLED, + PackageManager.DONT_KILL_APP); + ProviderInfo providerInfo2 = + mPackageManager.resolveContentProvider(ENABLED_PROVIDER_NAME, 0); + assertNull(providerInfo2); + } + + @MediumTest + public void testQueryEnabledProvider() throws Exception { + mPackageManager.setComponentEnabledSetting(ENABLED_PROVIDER_COMPONENTNAME, + COMPONENT_ENABLED_STATE_DEFAULT, + PackageManager.DONT_KILL_APP); + + String enabledProviderProcessName = getComponentProcessName(ENABLED_PROVIDER_NAME); + PackageInfo pi = mPackageManager.getPackageInfo(ENABLED_PACKAGENAME, 0); + List<ProviderInfo> providerInfoList = + mPackageManager.queryContentProviders(enabledProviderProcessName, + pi.applicationInfo.uid, 0); + assertNotNull(providerInfoList); + assertEquals(1, providerInfoList.size()); + assertEquals(ENABLED_PROVIDER_CLASSNAME, + providerInfoList.get(0).name); + } + + @MediumTest + public void testQueryDisabledProvider() throws Exception { + mPackageManager.setComponentEnabledSetting(DISABLED_PROVIDER_COMPONENTNAME, + COMPONENT_ENABLED_STATE_DEFAULT, + PackageManager.DONT_KILL_APP); + + PackageInfo pi = mPackageManager.getPackageInfo(ENABLED_PACKAGENAME, 0); + + String disabledProviderProcessName = getComponentProcessName(DISABLED_PROVIDER_NAME); + List<ProviderInfo> providerInfoList = + mPackageManager.queryContentProviders(disabledProviderProcessName, + pi.applicationInfo.uid, 0); + assertNull(providerInfoList); + + + List<ProviderInfo> providerInfoList2 = + mPackageManager.queryContentProviders(disabledProviderProcessName, + pi.applicationInfo.uid, GET_DISABLED_COMPONENTS); + assertNotNull(providerInfoList2); + assertEquals(1, providerInfoList2.size()); + assertEquals(DISABLED_PROVIDER_CLASSNAME, + providerInfoList2.get(0).name); + } + + private String getComponentProcessName(String componentNameStr) { + ComponentInfo providerInfo = + mPackageManager.resolveContentProvider(componentNameStr, + GET_DISABLED_COMPONENTS); + return providerInfo.processName; + } + + public void DISABLED_testResolveEnabledActivityInDisabledApp() throws Exception { + mPackageManager.setApplicationEnabledSetting(DISABLED_PACKAGENAME, + COMPONENT_ENABLED_STATE_DEFAULT, + 0); + mPackageManager.setComponentEnabledSetting(DISABLED_APP_ENABLED_ACTIVITY_COMPONENTNAME, + COMPONENT_ENABLED_STATE_DEFAULT, + PackageManager.DONT_KILL_APP); + + final ResolveInfo info = + mPackageManager.resolveActivity(mDisabledAppEnabledActivityIntent, 0); + assertNull(info); + + final ResolveInfo info2 = mPackageManager.resolveActivity( + mDisabledAppEnabledActivityIntent, GET_DISABLED_COMPONENTS); + assertNotNull(info2); + assertNotNull(info2.activityInfo); + assertTrue(info2.activityInfo.enabled); + } + + public void DISABLED_testEnableApplication() throws Exception { + mPackageManager.setApplicationEnabledSetting(DISABLED_PACKAGENAME, + COMPONENT_ENABLED_STATE_DEFAULT, + 0); + mPackageManager.setComponentEnabledSetting(DISABLED_APP_ENABLED_ACTIVITY_COMPONENTNAME, + COMPONENT_ENABLED_STATE_DEFAULT, + PackageManager.DONT_KILL_APP); + + final ResolveInfo info = + mPackageManager.resolveActivity(mDisabledAppEnabledActivityIntent, 0); + assertNull(info); + + mPackageManager.setApplicationEnabledSetting(DISABLED_PACKAGENAME, + COMPONENT_ENABLED_STATE_ENABLED, + 0); + final ResolveInfo info2 = mPackageManager.resolveActivity( + mDisabledAppEnabledActivityIntent, 0); + assertNotNull(info2); + assertNotNull(info2.activityInfo); + assertTrue(info2.activityInfo.enabled); + + } + + public void DISABLED_testDisableApplication() throws Exception { + mPackageManager.setApplicationEnabledSetting(ENABLED_PACKAGENAME, + COMPONENT_ENABLED_STATE_DEFAULT, + 0); + mPackageManager.setComponentEnabledSetting(ENABLED_ACTIVITY_COMPONENTNAME, + COMPONENT_ENABLED_STATE_DEFAULT, + PackageManager.DONT_KILL_APP); + + final ResolveInfo info = mPackageManager.resolveActivity(mEnabledActivityIntent, 0); + assertNotNull(info); + assertNotNull(info.activityInfo); + assertTrue(info.activityInfo.enabled); + + mPackageManager.setApplicationEnabledSetting(ENABLED_PACKAGENAME, + COMPONENT_ENABLED_STATE_DISABLED, + 0); + final ResolveInfo info2 = mPackageManager.resolveActivity(mEnabledActivityIntent, 0); + assertNull(info2); + + // Clean up + mPackageManager.setApplicationEnabledSetting(ENABLED_PACKAGENAME, + COMPONENT_ENABLED_STATE_DEFAULT, + 0); + + } + + @MediumTest + public void testNonExplicitResolveAfterEnabling() throws Exception { + mPackageManager.setComponentEnabledSetting(DISABLED_ACTIVITY_COMPONENTNAME, + COMPONENT_ENABLED_STATE_DEFAULT, + PackageManager.DONT_KILL_APP); + + Intent intent = new Intent(Intent.ACTION_MAIN, null); + intent.addCategory(TEST_CATEGORY); + + final List<ResolveInfo> launchables = + mPackageManager.queryIntentActivities(intent, 0); + + int numItems = launchables.size(); + assertEquals(0, numItems); + + mPackageManager.setComponentEnabledSetting(DISABLED_ACTIVITY_COMPONENTNAME, + COMPONENT_ENABLED_STATE_ENABLED, + PackageManager.DONT_KILL_APP); + + final List<ResolveInfo> launchables2 = + mPackageManager.queryIntentActivities(intent, 0); + + int numItems2 = launchables2.size(); + assertEquals(1, numItems2); + } +} diff --git a/tests/AndroidTests/src/com/android/unit_tests/ContentQueryMapTest.java b/tests/AndroidTests/src/com/android/unit_tests/ContentQueryMapTest.java new file mode 100644 index 0000000..241a1bf --- /dev/null +++ b/tests/AndroidTests/src/com/android/unit_tests/ContentQueryMapTest.java @@ -0,0 +1,104 @@ +/* + * Copyright (C) 2008 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.unit_tests; + +import android.content.ContentQueryMap; +import android.content.ContentResolver; +import android.content.ContentValues; +import android.database.Cursor; +import android.os.Handler; +import android.os.Looper; +import android.provider.Settings; +import android.test.AndroidTestCase; +import android.test.suitebuilder.annotation.MediumTest; + +import java.util.Observable; +import java.util.Observer; + +/** Test of {@link ContentQueryMap} */ +public class ContentQueryMapTest extends AndroidTestCase { + /** Helper class to run test code in a new thread with a Looper. */ + private abstract class LooperThread extends Thread { + public Throwable mError = null; + public boolean mSuccess = false; + + abstract void go(); + + public void run() { + try { + Looper.prepare(); + go(); + Looper.loop(); + } catch (Throwable e) { + mError = e; + } + } + } + + @MediumTest + public void testContentQueryMap() throws Throwable { + LooperThread thread = new LooperThread() { + void go() { + ContentResolver r = getContext().getContentResolver(); + Settings.System.putString(r, "test", "Value"); + Cursor cursor = r.query( + Settings.System.CONTENT_URI, + new String[] { + Settings.System.NAME, + Settings.System.VALUE, + }, null, null, null); + + final ContentQueryMap cqm = new ContentQueryMap( + cursor, Settings.System.NAME, true, null); + // Get the current state of the CQM. This forces a requery and means that the + // call to getValues() below won't do a requery(). + cqm.getRows(); + + // The cache won't notice changes until the loop runs. + Settings.System.putString(r, "test", "New Value"); + ContentValues v = cqm.getValues("test"); + String value = v.getAsString(Settings.System.VALUE); + assertEquals("Value", value); + + // Use an Observer to find out when the cache does update. + cqm.addObserver(new Observer() { + public void update(Observable o, Object arg) { + // Should have the new values by now. + ContentValues v = cqm.getValues("test"); + String value = v.getAsString(Settings.System.VALUE); + assertEquals("New Value", value); + Looper.myLooper().quit(); + cqm.close(); + mSuccess = true; + } + }); + + // Give up after a few seconds, if it doesn't. + new Handler().postDelayed(new Runnable() { + public void run() { + fail("Timed out"); + } + }, 5000); + } + }; + + thread.start(); + thread.join(); + if (thread.mError != null) throw thread.mError; + assertTrue(thread.mSuccess); + } +} diff --git a/tests/AndroidTests/src/com/android/unit_tests/CreateViewTest.java b/tests/AndroidTests/src/com/android/unit_tests/CreateViewTest.java new file mode 100644 index 0000000..342094d --- /dev/null +++ b/tests/AndroidTests/src/com/android/unit_tests/CreateViewTest.java @@ -0,0 +1,123 @@ +/* + * 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.unit_tests; + +import android.content.Context; +import android.test.AndroidTestCase; +import android.test.PerformanceTestCase; +import android.test.suitebuilder.annotation.SmallTest; +import android.view.View; +import static android.view.ViewGroup.LayoutParams.FILL_PARENT; +import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT; +import android.widget.LinearLayout; +import android.widget.TextView; + +public class CreateViewTest extends AndroidTestCase implements PerformanceTestCase { + + public boolean isPerformanceOnly() { + return false; + } + + public int startPerformance(PerformanceTestCase.Intermediates intermediates) { + return 0; + } + + @SmallTest + public void testLayout1() throws Exception { + new CreateViewTest.ViewOne(mContext); + } + + @SmallTest + public void testLayout2() throws Exception { + LinearLayout vert = new LinearLayout(mContext); + vert.addView(new CreateViewTest.ViewOne(mContext), + new LinearLayout.LayoutParams(FILL_PARENT, FILL_PARENT, 0)); + } + + @SmallTest + public void testLayout3() throws Exception { + LinearLayout vert = new LinearLayout(mContext); + + ViewOne one = new ViewOne(mContext); + vert.addView(one, new LinearLayout.LayoutParams(FILL_PARENT, FILL_PARENT, 0)); + + ViewOne two = new ViewOne(mContext); + vert.addView(two, new LinearLayout.LayoutParams(FILL_PARENT, FILL_PARENT, 0)); + + ViewOne three = new ViewOne(mContext); + vert.addView(three, new LinearLayout.LayoutParams(FILL_PARENT, FILL_PARENT, 0)); + + ViewOne four = new ViewOne(mContext); + vert.addView(four, new LinearLayout.LayoutParams(FILL_PARENT, FILL_PARENT, 0)); + + ViewOne five = new ViewOne(mContext); + vert.addView(five, new LinearLayout.LayoutParams(FILL_PARENT, FILL_PARENT, 0)); + + ViewOne six = new ViewOne(mContext); + vert.addView(six, new LinearLayout.LayoutParams(FILL_PARENT, FILL_PARENT, 0)); + } + + @SmallTest + public void testLayout4() throws Exception { + TextView text = new TextView(mContext); + text.setText("S"); + } + + @SmallTest + public void testLayout5() throws Exception { + TextView text = new TextView(mContext); + text.setText("S"); + + LinearLayout vert = new LinearLayout(mContext); + vert.addView(text, new LinearLayout.LayoutParams(FILL_PARENT, WRAP_CONTENT, 0)); + } + + @SmallTest + public void testLayout6() throws Exception { + LinearLayout vert = new LinearLayout(mContext); + + TextView one = new TextView(mContext); + one.setText("S"); + vert.addView(one, new LinearLayout.LayoutParams(FILL_PARENT, WRAP_CONTENT, 0)); + + TextView two = new TextView(mContext); + two.setText("M"); + vert.addView(two, new LinearLayout.LayoutParams(FILL_PARENT, WRAP_CONTENT, 0)); + + TextView three = new TextView(mContext); + three.setText("T"); + vert.addView(three, new LinearLayout.LayoutParams(FILL_PARENT, WRAP_CONTENT, 0)); + + TextView four = new TextView(mContext); + four.setText("W"); + vert.addView(four, new LinearLayout.LayoutParams(FILL_PARENT, WRAP_CONTENT, 0)); + + TextView five = new TextView(mContext); + five.setText("H"); + vert.addView(five, new LinearLayout.LayoutParams(FILL_PARENT, WRAP_CONTENT, 0)); + + TextView six = new TextView(mContext); + six.setText("F"); + vert.addView(six, new LinearLayout.LayoutParams(FILL_PARENT, WRAP_CONTENT, 0)); + } + + public static class ViewOne extends View { + public ViewOne(Context context) { + super(context); + } + } +} diff --git a/tests/AndroidTests/src/com/android/unit_tests/CursorWindowTest.java b/tests/AndroidTests/src/com/android/unit_tests/CursorWindowTest.java new file mode 100644 index 0000000..d9068c8 --- /dev/null +++ b/tests/AndroidTests/src/com/android/unit_tests/CursorWindowTest.java @@ -0,0 +1,173 @@ +/* + * Copyright (C) 2008 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.unit_tests; + +import android.database.AbstractCursor; +import android.test.suitebuilder.annotation.SmallTest; +import com.android.internal.database.ArrayListCursor; +import android.database.CursorWindow; +import android.test.PerformanceTestCase; + +import com.google.android.collect.Lists; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Random; + +import junit.framework.TestCase; + +public class CursorWindowTest extends TestCase implements PerformanceTestCase { + public boolean isPerformanceOnly() { + return false; + } + + // These test can only be run once. + public int startPerformance(Intermediates intermediates) { + return 1; + } + + @SmallTest + public void testWriteCursorToWindow() throws Exception { + // create cursor + String[] colNames = new String[]{"name", "number", "profit"}; + int colsize = colNames.length; + ArrayList<ArrayList> list = createTestList(10, colsize); + AbstractCursor cursor = new ArrayListCursor(colNames, (ArrayList<ArrayList>) list); + + // fill window + CursorWindow window = new CursorWindow(false); + cursor.fillWindow(0, window); + + // read from cursor window + for (int i = 0; i < list.size(); i++) { + ArrayList<Integer> col = list.get(i); + for (int j = 0; j < colsize; j++) { + String s = window.getString(i, j); + int r2 = col.get(j); + int r1 = Integer.parseInt(s); + assertEquals(r2, r1); + } + } + + // test cursor window handle startpos != 0 + window.clear(); + cursor.fillWindow(1, window); + // read from cursor from window + for (int i = 1; i < list.size(); i++) { + ArrayList<Integer> col = list.get(i); + for (int j = 0; j < colsize; j++) { + String s = window.getString(i, j); + int r2 = col.get(j); + int r1 = Integer.parseInt(s); + assertEquals(r2, r1); + } + } + + // Clear the window and make sure it's empty + window.clear(); + assertEquals(0, window.getNumRows()); + } + + @SmallTest + public void testValuesLocalWindow() { + doTestValues(new CursorWindow(true)); + } + + @SmallTest + public void testValuesRemoteWindow() { + doTestValues(new CursorWindow(false)); + } + + private void doTestValues(CursorWindow window) { + assertTrue(window.setNumColumns(7)); + assertTrue(window.allocRow()); + double db1 = 1.26; + assertTrue(window.putDouble(db1, 0, 0)); + double db2 = window.getDouble(0, 0); + assertEquals(db1, db2); + + long int1 = Long.MAX_VALUE; + assertTrue(window.putLong(int1, 0, 1)); + long int2 = window.getLong(0, 1); + assertEquals(int1, int2); + + assertTrue(window.putString("1198032740000", 0, 3)); + assertEquals("1198032740000", window.getString(0, 3)); + assertEquals(1198032740000L, window.getLong(0, 3)); + + assertTrue(window.putString(Long.toString(1198032740000L), 0, 3)); + assertEquals(Long.toString(1198032740000L), window.getString(0, 3)); + assertEquals(1198032740000L, window.getLong(0, 3)); + + assertTrue(window.putString(Double.toString(42.0), 0, 4)); + assertEquals(Double.toString(42.0), window.getString(0, 4)); + assertEquals(42.0, window.getDouble(0, 4)); + + // put blob + byte[] blob = new byte[1000]; + byte value = 99; + Arrays.fill(blob, value); + assertTrue(window.putBlob(blob, 0, 6)); + assertTrue(Arrays.equals(blob, window.getBlob(0, 6))); + } + + @SmallTest + public void testNull() { + CursorWindow window = getOneByOneWindow(); + + // Put in a null value and read it back as various types + assertTrue(window.putNull(0, 0)); + assertNull(window.getString(0, 0)); + assertEquals(0, window.getLong(0, 0)); + assertEquals(0.0, window.getDouble(0, 0)); + assertNull(window.getBlob(0, 0)); + } + + @SmallTest + public void testEmptyString() { + CursorWindow window = getOneByOneWindow(); + + // put size 0 string and read it back as various types + assertTrue(window.putString("", 0, 0)); + assertEquals("", window.getString(0, 0)); + assertEquals(0, window.getLong(0, 0)); + assertEquals(0.0, window.getDouble(0, 0)); + } + + private CursorWindow getOneByOneWindow() { + CursorWindow window = new CursorWindow(false); + assertTrue(window.setNumColumns(1)); + assertTrue(window.allocRow()); + return window; + } + + private static ArrayList<ArrayList> createTestList(int rows, int cols) { + ArrayList<ArrayList> list = Lists.newArrayList(); + Random generator = new Random(); + + for (int i = 0; i < rows; i++) { + ArrayList<Integer> col = Lists.newArrayList(); + list.add(col); + for (int j = 0; j < cols; j++) { + // generate random number + Integer r = generator.nextInt(); + col.add(r); + } + } + return list; + } +} diff --git a/tests/AndroidTests/src/com/android/unit_tests/DatabaseCursorTest.java b/tests/AndroidTests/src/com/android/unit_tests/DatabaseCursorTest.java new file mode 100644 index 0000000..5df499d --- /dev/null +++ b/tests/AndroidTests/src/com/android/unit_tests/DatabaseCursorTest.java @@ -0,0 +1,626 @@ +/* + * 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.unit_tests; + +import android.content.ContentValues; +import android.database.Cursor; +import android.database.CursorIndexOutOfBoundsException; +import android.database.DataSetObserver; +import android.database.DatabaseUtils; +import android.database.sqlite.SQLiteCursor; +import android.database.sqlite.SQLiteCursorDriver; +import android.database.sqlite.SQLiteDatabase; +import android.database.sqlite.SQLiteQuery; +import android.database.sqlite.SQLiteStatement; +import android.os.Looper; +import android.test.PerformanceTestCase; +import android.test.suitebuilder.annotation.LargeTest; +import android.test.suitebuilder.annotation.MediumTest; +import android.test.suitebuilder.annotation.SmallTest; +import android.test.suitebuilder.annotation.Suppress; +import android.util.Log; + +import java.io.File; +import java.util.Arrays; +import java.util.Random; + +import junit.framework.TestCase; + +public class DatabaseCursorTest extends TestCase implements PerformanceTestCase { + + private static final String sString1 = "this is a test"; + private static final String sString2 = "and yet another test"; + private static final String sString3 = "this string is a little longer, but still a test"; + + private static final int CURRENT_DATABASE_VERSION = 42; + private SQLiteDatabase mDatabase; + private File mDatabaseFile; + + @Override + protected void setUp() throws Exception { + super.setUp(); + mDatabaseFile = new File("/sqlite_stmt_journals", "database_test.db"); + if (mDatabaseFile.exists()) { + mDatabaseFile.delete(); + } + mDatabase = SQLiteDatabase.openOrCreateDatabase(mDatabaseFile.getPath(), null); + assertNotNull(mDatabase); + mDatabase.setVersion(CURRENT_DATABASE_VERSION); + } + + @Override + protected void tearDown() throws Exception { + mDatabase.close(); + mDatabaseFile.delete(); + super.tearDown(); + } + + public boolean isPerformanceOnly() { + return false; + } + + // These test can only be run once. + public int startPerformance(Intermediates intermediates) { + return 1; + } + + private void populateDefaultTable() { + mDatabase.execSQL("CREATE TABLE test (_id INTEGER PRIMARY KEY, data TEXT);"); + + mDatabase.execSQL("INSERT INTO test (data) VALUES ('" + sString1 + "');"); + mDatabase.execSQL("INSERT INTO test (data) VALUES ('" + sString2 + "');"); + mDatabase.execSQL("INSERT INTO test (data) VALUES ('" + sString3 + "');"); + } + + @MediumTest + public void testCursorUpdate() { + mDatabase.execSQL( + "CREATE TABLE test (_id INTEGER PRIMARY KEY, d INTEGER, s INTEGER);"); + for(int i = 0; i < 20; i++) { + mDatabase.execSQL("INSERT INTO test (d, s) VALUES (" + i + + "," + i%2 + ");"); + } + + Cursor c = mDatabase.query("test", null, "s = 0", null, null, null, null); + int dCol = c.getColumnIndexOrThrow("d"); + int sCol = c.getColumnIndexOrThrow("s"); + + int count = 0; + while (c.moveToNext()) { + assertTrue(c.updateInt(dCol, 3)); + count++; + } + assertEquals(10, count); + + assertTrue(c.commitUpdates()); + + assertTrue(c.requery()); + + count = 0; + while (c.moveToNext()) { + assertEquals(3, c.getInt(dCol)); + count++; + } + + assertEquals(10, count); + assertTrue(c.moveToFirst()); + assertTrue(c.deleteRow()); + assertEquals(9, c.getCount()); + c.close(); + } + + @MediumTest + public void testBlob() throws Exception { + // create table + mDatabase.execSQL( + "CREATE TABLE test (_id INTEGER PRIMARY KEY, s TEXT, d REAL, l INTEGER, b BLOB);"); + // insert blob + Object[] args = new Object[4]; + + byte[] blob = new byte[1000]; + byte value = 99; + Arrays.fill(blob, value); + args[3] = blob; + + String s = new String("text"); + args[0] = s; + Double d = 99.9; + args[1] = d; + Long l = (long)1000; + args[2] = l; + + String sql = "INSERT INTO test (s, d, l, b) VALUES (?,?,?,?)"; + mDatabase.execSQL(sql, args); + // use cursor to access blob + Cursor c = mDatabase.query("test", null, null, null, null, null, null); + c.moveToNext(); + ContentValues cv = new ContentValues(); + DatabaseUtils.cursorRowToContentValues(c, cv); + + int bCol = c.getColumnIndexOrThrow("b"); + int sCol = c.getColumnIndexOrThrow("s"); + int dCol = c.getColumnIndexOrThrow("d"); + int lCol = c.getColumnIndexOrThrow("l"); + byte[] cBlob = c.getBlob(bCol); + assertTrue(Arrays.equals(blob, cBlob)); + assertEquals(s, c.getString(sCol)); + assertEquals((double)d, c.getDouble(dCol)); + assertEquals((long)l, c.getLong(lCol)); + + // new byte[] + byte[] newblob = new byte[1000]; + value = 98; + Arrays.fill(blob, value); + + c.updateBlob(bCol, newblob); + cBlob = c.getBlob(bCol); + assertTrue(Arrays.equals(newblob, cBlob)); + + // commit + assertTrue(c.commitUpdates()); + assertTrue(c.requery()); + c.moveToNext(); + cBlob = c.getBlob(bCol); + assertTrue(Arrays.equals(newblob, cBlob)); + c.close(); + } + + @MediumTest + public void testRealColumns() throws Exception { + mDatabase.execSQL("CREATE TABLE test (_id INTEGER PRIMARY KEY, data REAL);"); + ContentValues values = new ContentValues(); + values.put("data", 42.11); + long id = mDatabase.insert("test", "data", values); + assertTrue(id > 0); + Cursor c = mDatabase.rawQuery("SELECT data FROM test", null); + assertNotNull(c); + assertTrue(c.moveToFirst()); + assertEquals(42.11, c.getDouble(0)); + c.close(); + } + + @MediumTest + public void testCursor1() throws Exception { + populateDefaultTable(); + + Cursor c = mDatabase.query("test", null, null, null, null, null, null); + + int dataColumn = c.getColumnIndexOrThrow("data"); + + // The cursor should ignore text before the last period when looking for a column. (This + // is a temporary hack in all implementations of getColumnIndex.) + int dataColumn2 = c.getColumnIndexOrThrow("junk.data"); + assertEquals(dataColumn, dataColumn2); + + assertSame(3, c.getCount()); + + assertTrue(c.isBeforeFirst()); + + try { + c.getInt(0); + fail("CursorIndexOutOfBoundsException expected"); + } catch (CursorIndexOutOfBoundsException ex) { + // expected + } + + c.moveToNext(); + assertEquals(1, c.getInt(0)); + + String s = c.getString(dataColumn); + assertEquals(sString1, s); + + c.moveToNext(); + s = c.getString(dataColumn); + assertEquals(sString2, s); + + c.moveToNext(); + s = c.getString(dataColumn); + assertEquals(sString3, s); + + c.moveToPosition(-1); + c.moveToNext(); + s = c.getString(dataColumn); + assertEquals(sString1, s); + + c.moveToPosition(2); + s = c.getString(dataColumn); + assertEquals(sString3, s); + + int i; + + for (c.moveToFirst(), i = 0; !c.isAfterLast(); c.moveToNext(), i++) { + c.getInt(0); + } + + assertEquals(3, i); + + try { + c.getInt(0); + fail("CursorIndexOutOfBoundsException expected"); + } catch (CursorIndexOutOfBoundsException ex) { + // expected + } + c.close(); + } + + @MediumTest + public void testCursor2() throws Exception { + populateDefaultTable(); + + Cursor c = mDatabase.query("test", null, "_id > 1000", null, null, null, null); + assertEquals(0, c.getCount()); + assertTrue(c.isBeforeFirst()); + + try { + c.getInt(0); + fail("CursorIndexOutOfBoundsException expected"); + } catch (CursorIndexOutOfBoundsException ex) { + // expected + } + + int i; + for (c.moveToFirst(), i = 0; !c.isAfterLast(); c.moveToNext(), i++) { + c.getInt(0); + } + assertEquals(0, i); + try { + c.getInt(0); + fail("CursorIndexOutOfBoundsException expected"); + } catch (CursorIndexOutOfBoundsException ex) { + // expected + } + c.close(); + } + + @MediumTest + public void testLargeField() throws Exception { + mDatabase.execSQL("CREATE TABLE test (_id INTEGER PRIMARY KEY, data TEXT);"); + + StringBuilder sql = new StringBuilder(2100); + sql.append("INSERT INTO test (data) VALUES ('"); + Random random = new Random(System.currentTimeMillis()); + StringBuilder randomString = new StringBuilder(1979); + for (int i = 0; i < 1979; i++) { + randomString.append((random.nextInt() & 0xf) % 10); + } + sql.append(randomString); + sql.append("');"); + mDatabase.execSQL(sql.toString()); + + Cursor c = mDatabase.query("test", null, null, null, null, null, null); + assertNotNull(c); + assertEquals(1, c.getCount()); + + assertTrue(c.moveToFirst()); + assertEquals(0, c.getPosition()); + String largeString = c.getString(c.getColumnIndexOrThrow("data")); + assertNotNull(largeString); + assertEquals(randomString.toString(), largeString); + c.close(); + } + + class TestObserver extends DataSetObserver { + int total; + SQLiteCursor c; + boolean quit = false; + public TestObserver(int total_, SQLiteCursor cursor) { + c = cursor; + total = total_; + } + + @Override + public void onChanged() { + int count = c.getCount(); + if (total == count) { + int i = 0; + while (c.moveToNext()) { + assertEquals(i, c.getInt(1)); + i++; + } + assertEquals(count, i); + quit = true; + Looper.myLooper().quit(); + } + } + + @Override + public void onInvalidated() { + } + } + + //@Large + @Suppress + public void testLoadingThreadDelayRegisterData() throws Exception { + mDatabase.execSQL("CREATE TABLE test (_id INTEGER PRIMARY KEY, data INT);"); + + final int count = 505; + String sql = "INSERT INTO test (data) VALUES (?);"; + SQLiteStatement s = mDatabase.compileStatement(sql); + for (int i = 0; i < count; i++) { + s.bindLong(1, i); + s.execute(); + } + + int maxRead = 500; + int initialRead = 5; + SQLiteCursor c = (SQLiteCursor)mDatabase.rawQuery("select * from test;", + null, initialRead, maxRead); + + TestObserver observer = new TestObserver(count, c); + c.getCount(); + c.registerDataSetObserver(observer); + if (!observer.quit) { + Looper.loop(); + } + c.close(); + } + + @LargeTest + public void testLoadingThread() throws Exception { + mDatabase.execSQL("CREATE TABLE test (_id INTEGER PRIMARY KEY, data INT);"); + + final int count = 50000; + String sql = "INSERT INTO test (data) VALUES (?);"; + SQLiteStatement s = mDatabase.compileStatement(sql); + for (int i = 0; i < count; i++) { + s.bindLong(1, i); + s.execute(); + } + + int maxRead = 1000; + int initialRead = 5; + SQLiteCursor c = (SQLiteCursor)mDatabase.rawQuery("select * from test;", + null, initialRead, maxRead); + + TestObserver observer = new TestObserver(count, c); + c.registerDataSetObserver(observer); + c.getCount(); + + Looper.loop(); + c.close(); + } + + @LargeTest + public void testLoadingThreadClose() throws Exception { + mDatabase.execSQL("CREATE TABLE test (_id INTEGER PRIMARY KEY, data INT);"); + + final int count = 1000; + String sql = "INSERT INTO test (data) VALUES (?);"; + SQLiteStatement s = mDatabase.compileStatement(sql); + for (int i = 0; i < count; i++) { + s.bindLong(1, i); + s.execute(); + } + + int maxRead = 11; + int initialRead = 5; + SQLiteCursor c = (SQLiteCursor)mDatabase.rawQuery("select * from test;", + null, initialRead, maxRead); + + TestObserver observer = new TestObserver(count, c); + c.registerDataSetObserver(observer); + c.getCount(); + c.close(); + } + + @LargeTest + public void testLoadingThreadDeactivate() throws Exception { + mDatabase.execSQL("CREATE TABLE test (_id INTEGER PRIMARY KEY, data INT);"); + + final int count = 1000; + String sql = "INSERT INTO test (data) VALUES (?);"; + SQLiteStatement s = mDatabase.compileStatement(sql); + for (int i = 0; i < count; i++) { + s.bindLong(1, i); + s.execute(); + } + + int maxRead = 11; + int initialRead = 5; + SQLiteCursor c = (SQLiteCursor)mDatabase.rawQuery("select * from test;", + null, initialRead, maxRead); + + TestObserver observer = new TestObserver(count, c); + c.registerDataSetObserver(observer); + c.getCount(); + c.deactivate(); + c.close(); + } + + @LargeTest + public void testManyRowsLong() throws Exception { + mDatabase.execSQL("CREATE TABLE test (_id INTEGER PRIMARY KEY, data INT);"); + + final int count = 36799; + for (int i = 0; i < count; i++) { + mDatabase.execSQL("INSERT INTO test (data) VALUES (" + i + ");"); + } + + Cursor c = mDatabase.query("test", new String[]{"data"}, null, null, null, null, null); + assertNotNull(c); + + int i = 0; + while (c.moveToNext()) { + assertEquals(i, c.getInt(0)); + i++; + } + assertEquals(count, i); + assertEquals(count, c.getCount()); + + Log.d("testManyRows", "count " + Integer.toString(i)); + c.close(); + } + + @LargeTest + public void testManyRowsTxt() throws Exception { + mDatabase.execSQL("CREATE TABLE test (_id INTEGER PRIMARY KEY, data TEXT);"); + StringBuilder sql = new StringBuilder(2100); + sql.append("INSERT INTO test (data) VALUES ('"); + Random random = new Random(System.currentTimeMillis()); + StringBuilder randomString = new StringBuilder(1979); + for (int i = 0; i < 1979; i++) { + randomString.append((random.nextInt() & 0xf) % 10); + } + sql.append(randomString); + sql.append("');"); + + // if cursor window size changed, adjust this value too + final int count = 600; // more than two fillWindow needed + for (int i = 0; i < count; i++) { + mDatabase.execSQL(sql.toString()); + } + + Cursor c = mDatabase.query("test", new String[]{"data"}, null, null, null, null, null); + assertNotNull(c); + + int i = 0; + while (c.moveToNext()) { + assertEquals(randomString.toString(), c.getString(0)); + i++; + } + assertEquals(count, i); + assertEquals(count, c.getCount()); + c.close(); + } + + @LargeTest + public void testManyRowsTxtLong() throws Exception { + mDatabase.execSQL("CREATE TABLE test (_id INTEGER PRIMARY KEY, txt TEXT, data INT);"); + + Random random = new Random(System.currentTimeMillis()); + StringBuilder randomString = new StringBuilder(1979); + for (int i = 0; i < 1979; i++) { + randomString.append((random.nextInt() & 0xf) % 10); + } + + // if cursor window size changed, adjust this value too + final int count = 600; + for (int i = 0; i < count; i++) { + StringBuilder sql = new StringBuilder(2100); + sql.append("INSERT INTO test (txt, data) VALUES ('"); + sql.append(randomString); + sql.append("','"); + sql.append(i); + sql.append("');"); + mDatabase.execSQL(sql.toString()); + } + + Cursor c = mDatabase.query("test", new String[]{"txt", "data"}, null, null, null, null, null); + assertNotNull(c); + + int i = 0; + while (c.moveToNext()) { + assertEquals(randomString.toString(), c.getString(0)); + assertEquals(i, c.getInt(1)); + i++; + } + assertEquals(count, i); + assertEquals(count, c.getCount()); + c.close(); + } + + @MediumTest + public void testRequery() throws Exception { + populateDefaultTable(); + + Cursor c = mDatabase.rawQuery("SELECT * FROM test", null); + assertNotNull(c); + assertEquals(3, c.getCount()); + c.deactivate(); + c.requery(); + assertEquals(3, c.getCount()); + c.close(); + } + + @MediumTest + public void testRequeryWithSelection() throws Exception { + populateDefaultTable(); + + Cursor c = mDatabase.rawQuery("SELECT data FROM test WHERE data = '" + sString1 + "'", + null); + assertNotNull(c); + assertEquals(1, c.getCount()); + assertTrue(c.moveToFirst()); + assertEquals(sString1, c.getString(0)); + c.deactivate(); + c.requery(); + assertEquals(1, c.getCount()); + assertTrue(c.moveToFirst()); + assertEquals(sString1, c.getString(0)); + c.close(); + } + + @MediumTest + public void testRequeryWithSelectionArgs() throws Exception { + populateDefaultTable(); + + Cursor c = mDatabase.rawQuery("SELECT data FROM test WHERE data = ?", + new String[]{sString1}); + assertNotNull(c); + assertEquals(1, c.getCount()); + assertTrue(c.moveToFirst()); + assertEquals(sString1, c.getString(0)); + c.deactivate(); + c.requery(); + assertEquals(1, c.getCount()); + assertTrue(c.moveToFirst()); + assertEquals(sString1, c.getString(0)); + c.close(); + } + + @MediumTest + public void testRequeryWithAlteredSelectionArgs() throws Exception { + /** + * Test the ability of a subclass of SQLiteCursor to change its query arguments. + */ + populateDefaultTable(); + + SQLiteDatabase.CursorFactory factory = new SQLiteDatabase.CursorFactory() { + public Cursor newCursor( + SQLiteDatabase db, SQLiteCursorDriver masterQuery, String editTable, + SQLiteQuery query) { + return new SQLiteCursor(db, masterQuery, editTable, query) { + @Override + public boolean requery() { + setSelectionArguments(new String[]{"2"}); + return super.requery(); + } + }; + } + }; + Cursor c = mDatabase.rawQueryWithFactory( + factory, "SELECT data FROM test WHERE _id <= ?", new String[]{"1"}, + null); + assertNotNull(c); + assertEquals(1, c.getCount()); + assertTrue(c.moveToFirst()); + assertEquals(sString1, c.getString(0)); + + // Our hacked requery() changes the query arguments in the cursor. + c.requery(); + + assertEquals(2, c.getCount()); + assertTrue(c.moveToFirst()); + assertEquals(sString1, c.getString(0)); + assertTrue(c.moveToNext()); + assertEquals(sString2, c.getString(0)); + + // Test that setting query args on a deactivated cursor also works. + c.deactivate(); + c.requery(); + } +} diff --git a/tests/AndroidTests/src/com/android/unit_tests/DatabaseGeneralTest.java b/tests/AndroidTests/src/com/android/unit_tests/DatabaseGeneralTest.java new file mode 100644 index 0000000..b004c93 --- /dev/null +++ b/tests/AndroidTests/src/com/android/unit_tests/DatabaseGeneralTest.java @@ -0,0 +1,871 @@ +/* + * 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.unit_tests; + +import android.content.ContentValues; +import android.database.ContentObserver; +import android.database.Cursor; +import android.database.DatabaseUtils; +import android.database.CharArrayBuffer; +import android.database.sqlite.SQLiteDatabase; +import android.database.sqlite.SQLiteStatement; +import android.os.Handler; +import android.os.Parcel; +import android.test.PerformanceTestCase; +import android.test.suitebuilder.annotation.MediumTest; +import android.test.suitebuilder.annotation.SmallTest; +import android.util.Log; + +import java.io.File; +import java.io.UnsupportedEncodingException; +import java.text.Collator; +import java.util.Arrays; + +import junit.framework.Assert; +import junit.framework.TestCase; + +import static android.database.DatabaseUtils.InsertHelper.TABLE_INFO_PRAGMA_COLUMNNAME_INDEX; +import static android.database.DatabaseUtils.InsertHelper.TABLE_INFO_PRAGMA_DEFAULT_INDEX; + +public class DatabaseGeneralTest extends TestCase implements PerformanceTestCase { + + private static final String sString1 = "this is a test"; + private static final String sString2 = "and yet another test"; + private static final String sString3 = "this string is a little longer, but still a test"; + private static final String PHONE_NUMBER = "16175551212"; + + private static final int CURRENT_DATABASE_VERSION = 42; + private SQLiteDatabase mDatabase; + private File mDatabaseFile; + + @Override + protected void setUp() throws Exception { + super.setUp(); + mDatabaseFile = new File("/sqlite_stmt_journals", "database_test.db"); + if (mDatabaseFile.exists()) { + mDatabaseFile.delete(); + } + mDatabase = SQLiteDatabase.openOrCreateDatabase(mDatabaseFile.getPath(), null); + assertNotNull(mDatabase); + mDatabase.setVersion(CURRENT_DATABASE_VERSION); + } + + @Override + protected void tearDown() throws Exception { + mDatabase.close(); + mDatabaseFile.delete(); + super.tearDown(); + } + + public boolean isPerformanceOnly() { + return false; + } + + // These test can only be run once. + public int startPerformance(Intermediates intermediates) { + return 1; + } + + private void populateDefaultTable() { + mDatabase.execSQL("CREATE TABLE test (_id INTEGER PRIMARY KEY, data TEXT);"); + + mDatabase.execSQL("INSERT INTO test (data) VALUES ('" + sString1 + "');"); + mDatabase.execSQL("INSERT INTO test (data) VALUES ('" + sString2 + "');"); + mDatabase.execSQL("INSERT INTO test (data) VALUES ('" + sString3 + "');"); + } + + @MediumTest + public void testVersion() throws Exception { + assertEquals(CURRENT_DATABASE_VERSION, mDatabase.getVersion()); + mDatabase.setVersion(11); + assertEquals(11, mDatabase.getVersion()); + } + + @MediumTest + public void testUpdate() throws Exception { + populateDefaultTable(); + + ContentValues values = new ContentValues(1); + values.put("data", "this is an updated test"); + assertEquals(1, mDatabase.update("test", values, "_id=1", null)); + Cursor c = mDatabase.query("test", null, "_id=1", null, null, null, null); + assertNotNull(c); + assertEquals(1, c.getCount()); + c.moveToFirst(); + String value = c.getString(c.getColumnIndexOrThrow("data")); + assertEquals("this is an updated test", value); + } + + @MediumTest + public void testPhoneNumbersEqual() throws Exception { + mDatabase.execSQL("CREATE TABLE phones (num TEXT);"); + mDatabase.execSQL("INSERT INTO phones (num) VALUES ('911');"); + mDatabase.execSQL("INSERT INTO phones (num) VALUES ('5555');"); + mDatabase.execSQL("INSERT INTO phones (num) VALUES ('+" + PHONE_NUMBER + "');"); + + String number; + Cursor c; + + c = mDatabase.query("phones", null, + "PHONE_NUMBERS_EQUAL(num, '504-555-7683')", null, null, null, null); + assertTrue(c == null || c.getCount() == 0); + c.close(); + + c = mDatabase.query("phones", null, + "PHONE_NUMBERS_EQUAL(num, '911')", null, null, null, null); + assertNotNull(c); + assertEquals(1, c.getCount()); + c.moveToFirst(); + number = c.getString(c.getColumnIndexOrThrow("num")); + assertEquals("911", number); + c.close(); + + c = mDatabase.query("phones", null, + "PHONE_NUMBERS_EQUAL(num, '5555')", null, null, null, null); + assertNotNull(c); + assertEquals(1, c.getCount()); + c.moveToFirst(); + number = c.getString(c.getColumnIndexOrThrow("num")); + assertEquals("5555", number); + c.close(); + + c = mDatabase.query("phones", null, + "PHONE_NUMBERS_EQUAL(num, '180055555555')", null, null, null, null); + assertTrue(c == null || c.getCount() == 0); + c.close(); + + c = mDatabase.query("phones", null, + "PHONE_NUMBERS_EQUAL(num, '+" + PHONE_NUMBER + "')", null, null, null, null); + assertNotNull(c); + assertEquals(1, c.getCount()); + c.moveToFirst(); + number = c.getString(c.getColumnIndexOrThrow("num")); + assertEquals("+" + PHONE_NUMBER, number); + c.close(); + + c = mDatabase.query("phones", null, + "PHONE_NUMBERS_EQUAL(num, '+1 (617).555-1212')", null, null, null, null); + assertNotNull(c); + assertEquals(1, c.getCount()); + c.moveToFirst(); + number = c.getString(c.getColumnIndexOrThrow("num")); + assertEquals("+" + PHONE_NUMBER, number); + c.close(); + + c = mDatabase.query("phones", null, + "PHONE_NUMBERS_EQUAL(num, '+1 (617).555-1212p1234')", null, null, null, null); + assertNotNull(c); + assertEquals(1, c.getCount()); + c.moveToFirst(); + number = c.getString(c.getColumnIndexOrThrow("num")); + assertEquals("+" + PHONE_NUMBER, number); + c.close(); + + c = mDatabase.query("phones", null, + "PHONE_NUMBERS_EQUAL(num, '" + PHONE_NUMBER + "')", null, null, null, null); + assertNotNull(c); + assertEquals(1, c.getCount()); + c.moveToFirst(); + number = c.getString(c.getColumnIndexOrThrow("num")); + assertEquals("+" + PHONE_NUMBER, number); + c.close(); + + c = mDatabase.query("phones", null, + "PHONE_NUMBERS_EQUAL(num, '5551212')", null, null, null, null); + assertNotNull(c); + assertEquals(1, c.getCount()); + c.moveToFirst(); + number = c.getString(c.getColumnIndexOrThrow("num")); + assertEquals("+" + PHONE_NUMBER, number); + c.close(); + + c = mDatabase.query("phones", null, + "PHONE_NUMBERS_EQUAL(num, '011" + PHONE_NUMBER + "')", null, null, null, null); + assertNotNull(c); + assertEquals(1, c.getCount()); + c.moveToFirst(); + number = c.getString(c.getColumnIndexOrThrow("num")); + assertEquals("+" + PHONE_NUMBER, number); + c.close(); + + c = mDatabase.query("phones", null, + "PHONE_NUMBERS_EQUAL(num, '00" + PHONE_NUMBER + "')", null, null, null, null); + assertNotNull(c); + assertEquals(1, c.getCount()); + c.moveToFirst(); + number = c.getString(c.getColumnIndexOrThrow("num")); + assertEquals("+" + PHONE_NUMBER, number); + c.close(); + } + + /** + * Tests international matching issues for the PHONE_NUMBERS_EQUAL function. + * + * @throws Exception + */ + public void testPhoneNumbersEqualInternationl() throws Exception { + Cursor c; + String[] phoneNumbers = new String[2]; + + // Russian trunk digit + phoneNumbers[0] = "+79161234567"; // globablly dialable number + phoneNumbers[1] = "89161234567"; // in-country dialable number + c = mDatabase.rawQuery( + "SELECT CASE WHEN PHONE_NUMBERS_EQUAL(?, ?) THEN 'equal' ELSE 'not equal' END", + phoneNumbers); + assertTrue(c.moveToFirst()); + assertEquals("equal", c.getString(0)); + c.close(); + + // French trunk digit + phoneNumbers[0] = "+33123456789"; // globablly dialable number + phoneNumbers[1] = "0123456789"; // in-country dialable number + c = mDatabase.rawQuery( + "SELECT CASE WHEN PHONE_NUMBERS_EQUAL(?, ?) THEN 'equal' ELSE 'not equal' END", + phoneNumbers); + assertTrue(c.moveToFirst()); + assertEquals("equal", c.getString(0)); + c.close(); + + + // Trunk digit for city codes in the Netherlands + phoneNumbers[0] = "+31771234567"; // globablly dialable number + phoneNumbers[1] = "0771234567"; // in-country dialable number + c = mDatabase.rawQuery( + "SELECT CASE WHEN PHONE_NUMBERS_EQUAL(?, ?) THEN 'equal' ELSE 'not equal' END", + phoneNumbers); + assertTrue(c.moveToFirst()); + assertEquals("equal", c.getString(0)); + c.close(); + + // Test broken caller ID seen on call from Thailand to the US + phoneNumbers[0] = "+66811234567"; // in address book + phoneNumbers[1] = "166811234567"; // came in from the network + c = mDatabase.rawQuery( + "SELECT CASE WHEN PHONE_NUMBERS_EQUAL(?, ?) THEN 'equal' ELSE 'not equal' END", + phoneNumbers); + assertTrue(c.moveToFirst()); + assertEquals("equal", c.getString(0)); + c.close(); + + // Test the same in-country number with different country codes + phoneNumbers[0] = "+33123456789"; + phoneNumbers[1] = "+1123456789"; + c = mDatabase.rawQuery( + "SELECT CASE WHEN PHONE_NUMBERS_EQUAL(?, ?) THEN 'equal' ELSE 'not equal' END", + phoneNumbers); + assertTrue(c.moveToFirst()); + assertEquals("not equal", c.getString(0)); + c.close(); + + // Test one number with country code and the other without + phoneNumbers[0] = "5125551212"; + phoneNumbers[1] = "+15125551212"; + c = mDatabase.rawQuery( + "SELECT CASE WHEN PHONE_NUMBERS_EQUAL(?, ?) THEN 'equal' ELSE 'not equal' END", + phoneNumbers); + assertTrue(c.moveToFirst()); + assertEquals("equal", c.getString(0)); + c.close(); + + // Test two NANP numbers that only differ in the area code + phoneNumbers[0] = "5125551212"; + phoneNumbers[1] = "6505551212"; + c = mDatabase.rawQuery( + "SELECT CASE WHEN PHONE_NUMBERS_EQUAL(?, ?) THEN 'equal' ELSE 'not equal' END", + phoneNumbers); + assertTrue(c.moveToFirst()); + assertEquals("not equal", c.getString(0)); + c.close(); + } + + @MediumTest + public void testCopyString() throws Exception { + mDatabase.execSQL("CREATE TABLE guess (numi INTEGER, numf FLOAT, str TEXT);"); + mDatabase.execSQL( + "INSERT INTO guess (numi,numf,str) VALUES (0,0.0,'ZoomZoomZoomZoom');"); + mDatabase.execSQL("INSERT INTO guess (numi,numf,str) VALUES (2000000000,3.1415926535,'');"); + String chinese = "\u4eac\u4ec5 \u5c3d\u5f84\u60ca"; + String[] arr = new String[1]; + arr[0] = chinese; + mDatabase.execSQL("INSERT INTO guess (numi,numf,str) VALUES (-32768,-1.0,?)", arr); + + Cursor c; + + c = mDatabase.rawQuery("SELECT * FROM guess", null); + + c.moveToFirst(); + + CharArrayBuffer buf = new CharArrayBuffer(14); + + String compareTo = c.getString(c.getColumnIndexOrThrow("numi")); + int numiIdx = c.getColumnIndexOrThrow("numi"); + int numfIdx = c.getColumnIndexOrThrow("numf"); + int strIdx = c.getColumnIndexOrThrow("str"); + + c.copyStringToBuffer(numiIdx, buf); + assertEquals(1, buf.sizeCopied); + assertEquals(compareTo, new String(buf.data, 0, buf.sizeCopied)); + + c.copyStringToBuffer(strIdx, buf); + assertEquals("ZoomZoomZoomZoom", new String(buf.data, 0, buf.sizeCopied)); + + c.moveToNext(); + compareTo = c.getString(numfIdx); + + c.copyStringToBuffer(numfIdx, buf); + assertEquals(compareTo, new String(buf.data, 0, buf.sizeCopied)); + c.copyStringToBuffer(strIdx, buf); + assertEquals(0, buf.sizeCopied); + + c.moveToNext(); + c.copyStringToBuffer(numfIdx, buf); + assertEquals(-1.0, Double.valueOf( + new String(buf.data, 0, buf.sizeCopied)).doubleValue()); + + c.copyStringToBuffer(strIdx, buf); + compareTo = c.getString(strIdx); + assertEquals(chinese, compareTo); + + assertEquals(chinese, new String(buf.data, 0, buf.sizeCopied)); + c.close(); + } + + @MediumTest + public void testSchemaChange1() throws Exception { + SQLiteDatabase db1 = mDatabase; + Cursor cursor; + + db1.execSQL("CREATE TABLE db1 (_id INTEGER PRIMARY KEY, data TEXT);"); + + cursor = db1.query("db1", null, null, null, null, null, null); + assertNotNull("Cursor is null", cursor); + + db1.execSQL("CREATE TABLE db2 (_id INTEGER PRIMARY KEY, data TEXT);"); + + assertEquals(0, cursor.getCount()); + cursor.deactivate(); + } + + @MediumTest + public void testSchemaChange2() throws Exception { + SQLiteDatabase db1 = mDatabase; + SQLiteDatabase db2 = SQLiteDatabase.openOrCreateDatabase(mDatabaseFile, null); + Cursor cursor; + + db1.execSQL("CREATE TABLE db1 (_id INTEGER PRIMARY KEY, data TEXT);"); + + cursor = db1.query("db1", null, null, null, null, null, null); + assertNotNull("Cursor is null", cursor); + assertEquals(0, cursor.getCount()); + cursor.deactivate(); + // this cause exception because we're still using sqlite_prepate16 and not + // sqlite_prepare16_v2. The v2 variant added the ability to check the + // schema version and handle the case when the schema has changed + // Marco Nelissen claim it was 2x slower to compile SQL statements so + // I reverted back to the v1 variant. + /* db2.execSQL("CREATE TABLE db2 (_id INTEGER PRIMARY KEY, data TEXT);"); + + cursor = db1.query("db1", null, null, null, null, null, null); + assertNotNull("Cursor is null", cursor); + assertEquals(0, cursor.count()); + cursor.deactivate(); + */ + } + + @MediumTest + public void testSchemaChange3() throws Exception { + SQLiteDatabase db1 = mDatabase; + SQLiteDatabase db2 = SQLiteDatabase.openOrCreateDatabase(mDatabaseFile, null); + Cursor cursor; + + + db1.execSQL("CREATE TABLE db1 (_id INTEGER PRIMARY KEY, data TEXT);"); + db1.execSQL("INSERT INTO db1 (data) VALUES ('test');"); + + cursor = db1.query("db1", null, null, null, null, null, null); + // this cause exception because we're still using sqlite_prepate16 and not + // sqlite_prepare16_v2. The v2 variant added the ability to check the + // schema version and handle the case when the schema has changed + // Marco Nelissen claim it was 2x slower to compile SQL statements so + // I reverted back to the v1 variant. + /* db2.execSQL("CREATE TABLE db2 (_id INTEGER PRIMARY KEY, data TEXT);"); + + assertNotNull("Cursor is null", cursor); + assertEquals(1, cursor.count()); + assertTrue(cursor.first()); + assertEquals("test", cursor.getString(cursor.getColumnIndexOrThrow("data"))); + cursor.deactivate(); + */ + } + + private class ChangeObserver extends ContentObserver { + private int mCursorNotificationCount = 0; + private int mNotificationCount = 0; + + public int getCursorNotificationCount() { + return mCursorNotificationCount; + } + + public int getNotificationCount() { + return mNotificationCount; + } + + public ChangeObserver(boolean cursor) { + super(new Handler()); + mCursor = cursor; + } + + @Override + public boolean deliverSelfNotifications() { + return true; + } + + @Override + public void onChange(boolean selfChange) { + if (mCursor) { + mCursorNotificationCount++; + } else { + mNotificationCount++; + } + } + + boolean mCursor; + } + + @MediumTest + public void testNotificationTest1() throws Exception { + /* + Cursor c = mContentResolver.query(Notes.CONTENT_URI, + new String[] {Notes._ID, Notes.NOTE}, + null, null); + c.registerContentObserver(new MyContentObserver(true)); + int count = c.count(); + + MyContentObserver observer = new MyContentObserver(false); + mContentResolver.registerContentObserver(Notes.CONTENT_URI, true, observer); + + Uri uri; + + HashMap<String, String> values = new HashMap<String, String>(); + values.put(Notes.NOTE, "test note1"); + uri = mContentResolver.insert(Notes.CONTENT_URI, values); + assertEquals(1, mCursorNotificationCount); + assertEquals(1, mNotificationCount); + + c.requery(); + assertEquals(count + 1, c.count()); + c.first(); + assertEquals("test note1", c.getString(c.getColumnIndex(Notes.NOTE))); + c.updateString(c.getColumnIndex(Notes.NOTE), "test note2"); + c.commitUpdates(); + + assertEquals(2, mCursorNotificationCount); + assertEquals(2, mNotificationCount); + + mContentResolver.delete(uri, null); + + assertEquals(3, mCursorNotificationCount); + assertEquals(3, mNotificationCount); + + mContentResolver.unregisterContentObserver(observer); + */ + } + + @MediumTest + public void testSelectionArgs() throws Exception { + mDatabase.execSQL("CREATE TABLE test (_id INTEGER PRIMARY KEY, data TEXT);"); + ContentValues values = new ContentValues(1); + values.put("data", "don't forget to handled 's"); + mDatabase.insert("test", "data", values); + values.clear(); + values.put("data", "no apostrophes here"); + mDatabase.insert("test", "data", values); + Cursor c = mDatabase.query( + "test", null, "data GLOB ?", new String[]{"*'*"}, null, null, null); + assertEquals(1, c.getCount()); + assertTrue(c.moveToFirst()); + assertEquals("don't forget to handled 's", c.getString(1)); + c.deactivate(); + + // make sure code should checking null string properly so that + // it won't crash + try { + mDatabase.query("test", new String[]{"_id"}, + "_id=?", new String[]{null}, null, null, null); + fail("expected exception not thrown"); + } catch (IllegalArgumentException e) { + // expected + } + } + + @MediumTest + public void testTokenize() throws Exception { + Cursor c; + mDatabase.execSQL("CREATE TABLE tokens (" + + "token TEXT COLLATE unicode," + + "source INTEGER " + + ");"); + String[] cols = new String[]{"token", "source"}; + + Assert.assertEquals(0, DatabaseUtils.longForQuery(mDatabase, + "SELECT _TOKENIZE(NULL, NULL, NULL, NULL)", null)); + Assert.assertEquals(0, DatabaseUtils.longForQuery(mDatabase, + "SELECT _TOKENIZE('tokens', NULL, NULL, NULL)", null)); + Assert.assertEquals(0, DatabaseUtils.longForQuery(mDatabase, + "SELECT _TOKENIZE('tokens', 10, NULL, NULL)", null)); + Assert.assertEquals(0, DatabaseUtils.longForQuery(mDatabase, + "SELECT _TOKENIZE('tokens', 10, 'some string', NULL)", null)); + + Assert.assertEquals(3, DatabaseUtils.longForQuery(mDatabase, + "SELECT _TOKENIZE('tokens', 1, 'some string ok', ' ')", null)); + + // test Chinese + String chinese = new String("\u4eac\u4ec5 \u5c3d\u5f84\u60ca"); + Assert.assertEquals(2, DatabaseUtils.longForQuery(mDatabase, + "SELECT _TOKENIZE('tokens', 1,'" + chinese + "', ' ')", null)); + + String icustr = new String("Fr\u00e9d\u00e9ric Hj\u00f8nnev\u00e5g"); + + Assert.assertEquals(2, DatabaseUtils.longForQuery(mDatabase, + "SELECT _TOKENIZE('tokens', 1, '" + icustr + "', ' ')", null)); + + Assert.assertEquals(7, DatabaseUtils.longForQuery(mDatabase, + "SELECT count(*) from tokens;", null)); + + String key = DatabaseUtils.getHexCollationKey("Frederic Hjonneva"); + Assert.assertEquals(1, DatabaseUtils.longForQuery(mDatabase, + "SELECT count(*) from tokens where token GLOB '" + key + "*'", null)); + key = DatabaseUtils.getHexCollationKey("Hjonneva"); + Assert.assertEquals(1, DatabaseUtils.longForQuery(mDatabase, + "SELECT count(*) from tokens where token GLOB '" + key + "*'", null)); + + key = DatabaseUtils.getHexCollationKey("some string ok"); + Assert.assertEquals(1, DatabaseUtils.longForQuery(mDatabase, + "SELECT count(*) from tokens where token GLOB '" + key + "*'", null)); + key = DatabaseUtils.getHexCollationKey("string"); + Assert.assertEquals(1, DatabaseUtils.longForQuery(mDatabase, + "SELECT count(*) from tokens where token GLOB '" + key + "*'", null)); + key = DatabaseUtils.getHexCollationKey("ok"); + Assert.assertEquals(1, DatabaseUtils.longForQuery(mDatabase, + "SELECT count(*) from tokens where token GLOB '" + key + "*'", null)); + + key = DatabaseUtils.getHexCollationKey(chinese); + String[] a = new String[1]; + a[0] = key; + Assert.assertEquals(1, DatabaseUtils.longForQuery(mDatabase, + "SELECT count(*) from tokens where token= ?", a)); + a[0] += "*"; + Assert.assertEquals(1, DatabaseUtils.longForQuery(mDatabase, + "SELECT count(*) from tokens where token GLOB ?", a)); + + Assert.assertEquals(1, DatabaseUtils.longForQuery(mDatabase, + "SELECT count(*) from tokens where token= '" + key + "'", null)); + + Assert.assertEquals(1, DatabaseUtils.longForQuery(mDatabase, + "SELECT count(*) from tokens where token GLOB '" + key + "*'", null)); + + key = DatabaseUtils.getHexCollationKey("\u4eac\u4ec5"); + Assert.assertEquals(1, DatabaseUtils.longForQuery(mDatabase, + "SELECT count(*) from tokens where token GLOB '" + key + "*'", null)); + + + Assert.assertEquals(0, DatabaseUtils.longForQuery(mDatabase, + "SELECT count(*) from tokens where token GLOB 'ab*'", null)); + } + + @MediumTest + public void testTransactions() throws Exception { + mDatabase.execSQL("CREATE TABLE test (num INTEGER);"); + mDatabase.execSQL("INSERT INTO test (num) VALUES (0)"); + + // Make sure that things work outside an explicit transaction. + setNum(1); + checkNum(1); + + // Test a single-level transaction. + setNum(0); + mDatabase.beginTransaction(); + setNum(1); + mDatabase.setTransactionSuccessful(); + mDatabase.endTransaction(); + checkNum(1); + Assert.assertFalse(mDatabase.isDbLockedByCurrentThread()); + + // Test a rolled-back transaction. + setNum(0); + mDatabase.beginTransaction(); + setNum(1); + mDatabase.endTransaction(); + checkNum(0); + Assert.assertFalse(mDatabase.isDbLockedByCurrentThread()); + + // We should get an error if we end a non-existent transaction. + assertThrowsIllegalState(new Runnable() { public void run() { + mDatabase.endTransaction(); + }}); + + // We should get an error if a set a non-existent transaction as clean. + assertThrowsIllegalState(new Runnable() { public void run() { + mDatabase.setTransactionSuccessful(); + }}); + + mDatabase.beginTransaction(); + mDatabase.setTransactionSuccessful(); + // We should get an error if we mark a transaction as clean twice. + assertThrowsIllegalState(new Runnable() { public void run() { + mDatabase.setTransactionSuccessful(); + }}); + // We should get an error if we begin a transaction after marking the parent as clean. + assertThrowsIllegalState(new Runnable() { public void run() { + mDatabase.beginTransaction(); + }}); + mDatabase.endTransaction(); + Assert.assertFalse(mDatabase.isDbLockedByCurrentThread()); + + // Test a two-level transaction. + setNum(0); + mDatabase.beginTransaction(); + mDatabase.beginTransaction(); + setNum(1); + mDatabase.setTransactionSuccessful(); + mDatabase.endTransaction(); + mDatabase.setTransactionSuccessful(); + mDatabase.endTransaction(); + checkNum(1); + Assert.assertFalse(mDatabase.isDbLockedByCurrentThread()); + + // Test rolling back an inner transaction. + setNum(0); + mDatabase.beginTransaction(); + mDatabase.beginTransaction(); + setNum(1); + mDatabase.endTransaction(); + mDatabase.setTransactionSuccessful(); + mDatabase.endTransaction(); + checkNum(0); + Assert.assertFalse(mDatabase.isDbLockedByCurrentThread()); + + // Test rolling back an outer transaction. + setNum(0); + mDatabase.beginTransaction(); + mDatabase.beginTransaction(); + setNum(1); + mDatabase.setTransactionSuccessful(); + mDatabase.endTransaction(); + mDatabase.endTransaction(); + checkNum(0); + Assert.assertFalse(mDatabase.isDbLockedByCurrentThread()); + } + + private void setNum(int num) { + mDatabase.execSQL("UPDATE test SET num = " + num); + } + + private void checkNum(int num) { + Assert.assertEquals( + num, DatabaseUtils.longForQuery(mDatabase, "SELECT num FROM test", null)); + } + + private void assertThrowsIllegalState(Runnable r) { + boolean ok = false; + try { + r.run(); + } catch (IllegalStateException e) { + ok = true; + } + Assert.assertTrue(ok); + } + + // Disable these until we can explicitly mark them as stress tests + public void xxtestMem1() throws Exception { + populateDefaultTable(); + + for (int i = 0; i < 50000; i++) { + Cursor cursor = mDatabase.query("test", null, null, null, null, null, null); + cursor.moveToFirst(); + cursor.close(); +// Log.i("~~~~", "Finished round " + i); + } + } + + // Disable these until we can explicitly mark them as stress tests + public void xxtestMem2() throws Exception { + populateDefaultTable(); + + for (int i = 0; i < 50000; i++) { + Cursor cursor = mDatabase.query("test", null, null, null, null, null, null); + cursor.close(); +// Log.i("~~~~", "Finished round " + i); + } + } + + // Disable these until we can explicitly mark them as stress tests + public void xxtestMem3() throws Exception { + populateDefaultTable(); + + for (int i = 0; i < 50000; i++) { + Cursor cursor = mDatabase.query("test", null, null, null, null, null, null); + cursor.deactivate(); +// Log.i("~~~~", "Finished round " + i); + } + } + + @MediumTest + public void testContentValues() throws Exception { + ContentValues values = new ContentValues(); + values.put("string", "value"); + assertEquals("value", values.getAsString("string")); + byte[] bytes = new byte[42]; + Arrays.fill(bytes, (byte) 0x28); + values.put("byteArray", bytes); + assertTrue(Arrays.equals(bytes, values.getAsByteArray("byteArray"))); + + // Write the ContentValues to a Parcel and then read them out + Parcel p = Parcel.obtain(); + values.writeToParcel(p, 0); + p.setDataPosition(0); + values = ContentValues.CREATOR.createFromParcel(p); + + // Read the values out again and make sure they're the same + assertTrue(Arrays.equals(bytes, values.getAsByteArray("byteArray"))); + assertEquals("value", values.get("string")); + } + + @MediumTest + public void testTableInfoPragma() throws Exception { + mDatabase.execSQL("CREATE TABLE pragma_test (" + + "i INTEGER DEFAULT 1234, " + + "j INTEGER, " + + "s TEXT DEFAULT 'hello', " + + "t TEXT, " + + "'select' TEXT DEFAULT \"hello\")"); + try { + Cursor cur = mDatabase.rawQuery("PRAGMA table_info(pragma_test)", null); + Assert.assertEquals(5, cur.getCount()); + + Assert.assertTrue(cur.moveToNext()); + Assert.assertEquals("i", + cur.getString(TABLE_INFO_PRAGMA_COLUMNNAME_INDEX)); + Assert.assertEquals("1234", + cur.getString(TABLE_INFO_PRAGMA_DEFAULT_INDEX)); + + Assert.assertTrue(cur.moveToNext()); + Assert.assertEquals("j", + cur.getString(TABLE_INFO_PRAGMA_COLUMNNAME_INDEX)); + Assert.assertNull(cur.getString(TABLE_INFO_PRAGMA_DEFAULT_INDEX)); + + Assert.assertTrue(cur.moveToNext()); + Assert.assertEquals("s", + cur.getString(TABLE_INFO_PRAGMA_COLUMNNAME_INDEX)); + Assert.assertEquals("'hello'", + cur.getString(TABLE_INFO_PRAGMA_DEFAULT_INDEX)); + + Assert.assertTrue(cur.moveToNext()); + Assert.assertEquals("t", + cur.getString(TABLE_INFO_PRAGMA_COLUMNNAME_INDEX)); + Assert.assertNull(cur.getString(TABLE_INFO_PRAGMA_DEFAULT_INDEX)); + + Assert.assertTrue(cur.moveToNext()); + Assert.assertEquals("select", + cur.getString(TABLE_INFO_PRAGMA_COLUMNNAME_INDEX)); + Assert.assertEquals("\"hello\"", + cur.getString(TABLE_INFO_PRAGMA_DEFAULT_INDEX)); + + cur.close(); + } catch (Throwable t) { + throw new RuntimeException( + "If you see this test fail, it's likely that something about " + + "sqlite's PRAGMA table_info(...) command has changed.", t); + } + } + + @MediumTest + public void testInsertHelper() throws Exception { + Cursor cur; + ContentValues cv; + long row; + + mDatabase.execSQL("CREATE TABLE insert_test (" + + "_id INTEGER PRIMARY KEY, " + + "s TEXT NOT NULL UNIQUE, " + + "t TEXT NOT NULL DEFAULT 'hello world', " + + "i INTEGER, " + + "j INTEGER NOT NULL DEFAULT 1234, " + + "'select' TEXT)"); + + DatabaseUtils.InsertHelper ih = + new DatabaseUtils.InsertHelper(mDatabase, "insert_test"); + + cv = new ContentValues(); + cv.put("s", "one"); + row = ih.insert(cv); + cur = mDatabase.rawQuery("SELECT * FROM insert_test WHERE _id == " + row, null); + Assert.assertTrue(cur.moveToFirst()); + Assert.assertEquals("one", cur.getString(1)); + Assert.assertEquals("hello world", cur.getString(2)); + Assert.assertNull(cur.getString(3)); + Assert.assertEquals(1234, cur.getLong(4)); + Assert.assertNull(cur.getString(5)); + + cv = new ContentValues(); + cv.put("s", "two"); + cv.put("t", "goodbye world"); + row = ih.insert(cv); + cur = mDatabase.rawQuery("SELECT * FROM insert_test WHERE _id == " + row, null); + Assert.assertTrue(cur.moveToFirst()); + Assert.assertEquals("two", cur.getString(1)); + Assert.assertEquals("goodbye world", cur.getString(2)); + Assert.assertNull(cur.getString(3)); + Assert.assertEquals(1234, cur.getLong(4)); + Assert.assertNull(cur.getString(5)); + + cv = new ContentValues(); + cv.put("t", "goodbye world"); + row = ih.insert(cv); + Assert.assertEquals(-1, row); + + cv = new ContentValues(); + cv.put("s", "three"); + cv.put("i", 2345); + cv.put("j", 3456); + cv.put("select", "tricky"); + row = ih.insert(cv); + cur = mDatabase.rawQuery("SELECT * FROM insert_test WHERE _id == " + row, null); + Assert.assertTrue(cur.moveToFirst()); + Assert.assertEquals("three", cur.getString(1)); + Assert.assertEquals("hello world", cur.getString(2)); + Assert.assertEquals(2345, cur.getLong(3)); + Assert.assertEquals(3456, cur.getLong(4)); + Assert.assertEquals("tricky", cur.getString(5)); + + cv = new ContentValues(); + cv.put("s", "three"); + cv.put("i", 6789); + row = ih.insert(cv); + Assert.assertEquals(-1, row); + row = ih.replace(cv); + cur = mDatabase.rawQuery("SELECT * FROM insert_test WHERE _id == " + row, null); + Assert.assertTrue(cur.moveToFirst()); + Assert.assertEquals("three", cur.getString(1)); + Assert.assertEquals("hello world", cur.getString(2)); + Assert.assertEquals(6789, cur.getLong(3)); + + ih.close(); + } + +} diff --git a/tests/AndroidTests/src/com/android/unit_tests/DatabaseLocaleTest.java b/tests/AndroidTests/src/com/android/unit_tests/DatabaseLocaleTest.java new file mode 100644 index 0000000..0560c21 --- /dev/null +++ b/tests/AndroidTests/src/com/android/unit_tests/DatabaseLocaleTest.java @@ -0,0 +1,102 @@ +/* + * 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.unit_tests; + +import android.database.sqlite.SQLiteDatabase; +import android.database.Cursor; +import android.test.suitebuilder.annotation.MediumTest; +import android.test.suitebuilder.annotation.SmallTest; +import android.util.Log; +import android.test.MoreAsserts; + +import java.util.ArrayList; +import java.util.Locale; + +import junit.framework.TestCase; + +public class DatabaseLocaleTest extends TestCase { + + private SQLiteDatabase mDatabase; + + private static final String[] STRINGS = { + "c\u00f4t\u00e9", + "cote", + "c\u00f4te", + "cot\u00e9", + "boy", + "dog", + "COTE", + }; + + @Override + protected void setUp() throws Exception { + super.setUp(); + mDatabase = SQLiteDatabase.create(null); + mDatabase.execSQL("CREATE TABLE test (data TEXT COLLATE LOCALIZED);"); + for (String s : STRINGS) { + mDatabase.execSQL("INSERT INTO test VALUES('" + s + "');"); + } + } + + @Override + protected void tearDown() throws Exception { + mDatabase.close(); + super.tearDown(); + } + + private String[] query(String sql) { + Log.i("LocaleTest", "Querying: " + sql); + Cursor c = mDatabase.rawQuery(sql, null); + assertNotNull(c); + ArrayList<String> items = new ArrayList<String>(); + while (c.moveToNext()) { + items.add(c.getString(0)); + Log.i("LocaleTest", "...." + c.getString(0)); + } + String[] result = items.toArray(new String[items.size()]); + assertEquals(STRINGS.length, result.length); + c.close(); + return result; + } + + @MediumTest + public void testLocaleInsertOrder() throws Exception { + String[] results = query("SELECT data FROM test"); + MoreAsserts.assertEquals(STRINGS, results); + } + + @MediumTest + public void testLocaleenUS() throws Exception { + Log.i("LocaleTest", "about to call setLocale en_US"); + mDatabase.setLocale(new Locale("en", "US")); + String[] results; + results = query("SELECT data FROM test ORDER BY data COLLATE LOCALIZED ASC"); + + // The database code currently uses PRIMARY collation strength, + // meaning that all versions of a character compare equal (regardless + // of case or accents), leaving the "cote" flavors in database order. + MoreAsserts.assertEquals(results, new String[] { + STRINGS[4], // "boy" + STRINGS[0], // sundry forms of "cote" + STRINGS[1], + STRINGS[2], + STRINGS[3], + STRINGS[6], // "COTE" + STRINGS[5], // "dog" + }); + } +} diff --git a/tests/AndroidTests/src/com/android/unit_tests/DatabaseLockTest.java b/tests/AndroidTests/src/com/android/unit_tests/DatabaseLockTest.java new file mode 100644 index 0000000..bb821e3 --- /dev/null +++ b/tests/AndroidTests/src/com/android/unit_tests/DatabaseLockTest.java @@ -0,0 +1,170 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.unit_tests; + +import android.app.Activity; +import android.content.Context; +import android.database.sqlite.SQLiteDatabase; +import android.test.suitebuilder.annotation.LargeTest; +import android.util.Log; +import java.io.File; +import java.util.concurrent.atomic.AtomicInteger; +import android.test.AndroidTestCase; + +import junit.framework.TestCase; + +/* + * This is a series of unit tests for database locks. + */ +public class DatabaseLockTest extends AndroidTestCase { + + private static final int NUM_ITERATIONS = 100; + private static final int SLEEP_TIME = 30; + private static final int MAX_ALLOWED_LATENCY_TIME = 30; + private SQLiteDatabase mDatabase; + private File mDatabaseFile; + private AtomicInteger mCounter = new AtomicInteger(); + + @Override + protected void setUp() throws Exception { + super.setUp(); + File parentDir = getContext().getFilesDir(); + mDatabaseFile = new File(parentDir, "database_test.db"); + + if (mDatabaseFile.exists()) { + mDatabaseFile.delete(); + } + mDatabase = SQLiteDatabase.openOrCreateDatabase(mDatabaseFile.getPath(), null); + assertNotNull(mDatabase); + } + + @Override + protected void tearDown() throws Exception { + mDatabase.close(); + mDatabaseFile.delete(); + super.tearDown(); + } + + /* + * testLockFairness() tests the fairness of prioritizing multiple threads + * attempting to access a database concurrently. + * This test is intended to verify that, when two threads are accessing the + * same database at the same time with the same prioritization, neither thread + * is locked out and prevented from accessing the database. + */ + @LargeTest + public void testLockFairness() { + startDatabaseFairnessThread(); + int previous = 0; + for (int i = 0; i < NUM_ITERATIONS; i++) { + mDatabase.beginTransaction(); + int val = mCounter.get(); + if (i == 0) { + previous = val - i; + } + assertTrue(previous == (val - i)); + try { + Thread.currentThread().sleep(SLEEP_TIME); + } catch (InterruptedException e) { + // ignore + } + mDatabase.endTransaction(); + } + } + + /* + * This function is to create the second thread for testLockFairness() test. + */ + private void startDatabaseFairnessThread() { + Thread thread = new DatabaseFairnessThread(); + thread.start(); + } + + private class DatabaseFairnessThread extends Thread { + @Override + public void run() { + for (int i = 0; i < NUM_ITERATIONS; i++) { + mDatabase.beginTransaction(); + int val = mCounter.incrementAndGet(); + try { + Thread.currentThread().sleep(SLEEP_TIME); + } catch (InterruptedException e) { + // ignore + } + mDatabase.endTransaction(); + } + } + } + + /* + * testLockLatency() tests the latency of database locks. + * This test is intended to verify that, even when two threads are accessing + * the same database, the locking/unlocking of the database is done within an + * appropriate amount of time (MAX_ALLOWED_LATENCY_TIME). + */ + @LargeTest + public void testLockLatency() { + startDatabaseLatencyThread(); + int previous = 0; + long sumTime = 0; + long maxTime = 0; + for (int i = 0; i < NUM_ITERATIONS; i++) { + long startTime = System.currentTimeMillis(); + mDatabase.beginTransaction(); + long endTime = System.currentTimeMillis(); + long elapsedTime = endTime - startTime; + if (maxTime < elapsedTime) { + maxTime = elapsedTime; + } + sumTime += elapsedTime; + try { + Thread.currentThread().sleep(SLEEP_TIME); + } catch (InterruptedException e) { + // ignore + } + mDatabase.endTransaction(); + } + long averageTime = sumTime/NUM_ITERATIONS; + Log.i("DatabaseLockLatency", "AverageTime: " + averageTime); + Log.i("DatabaseLockLatency", "MaxTime: " + maxTime); + assertTrue( (averageTime - SLEEP_TIME) <= MAX_ALLOWED_LATENCY_TIME); + } + + /* + * This function is to create the second thread for testLockLatency() test. + */ + private void startDatabaseLatencyThread() { + Thread thread = new DatabaseLatencyThread(); + thread.start(); + } + + private class DatabaseLatencyThread extends Thread { + @Override + public void run() { + for (int i = 0; i < NUM_ITERATIONS; i++) + { + mDatabase.beginTransaction(); + try { + Thread.currentThread().sleep(SLEEP_TIME); + } catch (InterruptedException e) { + // ignore + } + mDatabase.endTransaction(); + } + } + } +} diff --git a/tests/AndroidTests/src/com/android/unit_tests/DatabasePerformanceTests.java b/tests/AndroidTests/src/com/android/unit_tests/DatabasePerformanceTests.java new file mode 100644 index 0000000..68ce5e1 --- /dev/null +++ b/tests/AndroidTests/src/com/android/unit_tests/DatabasePerformanceTests.java @@ -0,0 +1,1353 @@ +/* + * 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.unit_tests; + +import junit.framework.Assert; + +import android.content.ContentValues; +import android.content.Context; +import android.database.Cursor; +import android.database.sqlite.SQLiteDatabase; +import android.provider.Contacts; +import android.provider.Contacts.People; +import android.test.PerformanceTestCase; +import android.test.TestCase; + +import java.io.File; +import java.util.Random; + +/** + * Database Performance Tests + * + */ + +public class DatabasePerformanceTests { + + public static String[] children() { + return new String[] { + ContactReadingTest1.class.getName(), + Perf1Test.class.getName(), + Perf2Test.class.getName(), + Perf3Test.class.getName(), + Perf4Test.class.getName(), + Perf5Test.class.getName(), + Perf6Test.class.getName(), + Perf7Test.class.getName(), + Perf8Test.class.getName(), + Perf9Test.class.getName(), + Perf10Test.class.getName(), + Perf11Test.class.getName(), + Perf12Test.class.getName(), + Perf13Test.class.getName(), + Perf14Test.class.getName(), + Perf15Test.class.getName(), + Perf16Test.class.getName(), + Perf17Test.class.getName(), + Perf18Test.class.getName(), + Perf19Test.class.getName(), + Perf20Test.class.getName(), + Perf21Test.class.getName(), + Perf22Test.class.getName(), + Perf23Test.class.getName(), + Perf24Test.class.getName(), + Perf25Test.class.getName(), + Perf26Test.class.getName(), + Perf27Test.class.getName(), + Perf28Test.class.getName(), + Perf29Test.class.getName(), + Perf30Test.class.getName(), + Perf31Test.class.getName(), + }; + } + + public static abstract class PerformanceBase implements TestCase, + PerformanceTestCase { + protected static final int CURRENT_DATABASE_VERSION = 42; + protected SQLiteDatabase mDatabase; + protected File mDatabaseFile; + protected Context mContext; + + public void setUp(Context c) { + mContext = c; + mDatabaseFile = new File("/tmp", "perf_database_test.db"); + if (mDatabaseFile.exists()) { + mDatabaseFile.delete(); + } + mDatabase = SQLiteDatabase.openOrCreateDatabase(mDatabaseFile.getPath(), null); + Assert.assertTrue(mDatabase != null); + mDatabase.setVersion(CURRENT_DATABASE_VERSION); + } + + public void tearDown() { + mDatabase.close(); + mDatabaseFile.delete(); + } + + public boolean isPerformanceOnly() { + return true; + } + + // These test can only be run once. + public int startPerformance(Intermediates intermediates) { + return 0; + } + + public void run() { + } + + public String numberName(int number) { + String result = ""; + + if (number >= 1000) { + result += numberName((number / 1000)) + " thousand"; + number = (number % 1000); + + if (number > 0) result += " "; + } + + if (number >= 100) { + result += ONES[(number / 100)] + " hundred"; + number = (number % 100); + + if (number > 0) result += " "; + } + + if (number >= 20) { + result += TENS[(number / 10)]; + number = (number % 10); + + if (number > 0) result += " "; + } + + if (number > 0) { + result += ONES[number]; + } + + return result; + } + } + + /** + * Test reading all contact data. + */ + public static class ContactReadingTest1 implements TestCase, PerformanceTestCase { + private static final String[] PEOPLE_PROJECTION = new String[] { + Contacts.People._ID, // 0 + Contacts.People.PRIMARY_PHONE_ID, // 1 + Contacts.People.TYPE, // 2 + Contacts.People.NUMBER, // 3 + Contacts.People.LABEL, // 4 + Contacts.People.NAME, // 5 + Contacts.People.PRESENCE_STATUS, // 6 + }; + + private Cursor mCursor; + + public void setUp(Context c) { + mCursor = c.getContentResolver().query(People.CONTENT_URI, PEOPLE_PROJECTION, null, + null, People.DEFAULT_SORT_ORDER); + } + + public void tearDown() { + mCursor.close(); + } + + public boolean isPerformanceOnly() { + return true; + } + + public int startPerformance(Intermediates intermediates) { + // This test can only be run once. + return 0; + } + + public void run() { + while (mCursor.moveToNext()) { + // Read out all of the data + mCursor.getLong(0); + mCursor.getLong(1); + mCursor.getLong(2); + mCursor.getString(3); + mCursor.getString(4); + mCursor.getString(5); + mCursor.getLong(6); + } + } + } + + /** + * Test 1000 inserts + */ + + public static class Perf1Test extends PerformanceBase { + private static final int SIZE = 1000; + + private String[] statements = new String[SIZE]; + + @Override + public void setUp(Context c) { + super.setUp(c); + Random random = new Random(42); + + for (int i = 0; i < SIZE; i++) { + int r = random.nextInt(100000); + statements[i] = + "INSERT INTO t1 VALUES(" + i + "," + r + ",'" + + numberName(r) + "')"; + } + + mDatabase + .execSQL("CREATE TABLE t1(a INTEGER, b INTEGER, c VARCHAR(100))"); + } + + @Override + public void run() { + for (int i = 0; i < SIZE; i++) { + mDatabase.execSQL(statements[i]); + } + } + } + + /** + * Test 1000 inserts into and indexed table + */ + + public static class Perf2Test extends PerformanceBase { + private static final int SIZE = 1000; + + private String[] statements = new String[SIZE]; + + @Override + public void setUp(Context c) { + super.setUp(c); + Random random = new Random(42); + + for (int i = 0; i < SIZE; i++) { + int r = random.nextInt(100000); + statements[i] = + "INSERT INTO t1 VALUES(" + i + "," + r + ",'" + + numberName(r) + "')"; + } + + mDatabase + .execSQL("CREATE TABLE t1(a INTEGER, b INTEGER, c VARCHAR(100))"); + mDatabase.execSQL("CREATE INDEX i1c ON t1(c)"); + } + + @Override + public void run() { + for (int i = 0; i < SIZE; i++) { + mDatabase.execSQL(statements[i]); + } + } + } + + /** + * 100 SELECTs without an index + */ + + public static class Perf3Test extends PerformanceBase { + private static final int SIZE = 100; + private static final String[] COLUMNS = {"count(*)", "avg(b)"}; + + private String[] where = new String[SIZE]; + + @Override + public void setUp(Context c) { + super.setUp(c); + Random random = new Random(42); + + mDatabase + .execSQL("CREATE TABLE t1(a INTEGER, b INTEGER, c VARCHAR(100))"); + + for (int i = 0; i < SIZE; i++) { + int r = random.nextInt(100000); + mDatabase.execSQL("INSERT INTO t1 VALUES(" + i + "," + r + ",'" + + numberName(r) + "')"); + } + + for (int i = 0; i < SIZE; i++) { + int lower = i * 100; + int upper = (i + 10) * 100; + where[i] = "b >= " + lower + " AND b < " + upper; + } + } + + @Override + public void run() { + for (int i = 0; i < SIZE; i++) { + mDatabase + .query("t1", COLUMNS, where[i], null, null, null, null); + } + } + } + + /** + * 100 SELECTs on a string comparison + */ + + public static class Perf4Test extends PerformanceBase { + private static final int SIZE = 100; + private static final String[] COLUMNS = {"count(*)", "avg(b)"}; + + private String[] where = new String[SIZE]; + + @Override + public void setUp(Context c) { + super.setUp(c); + Random random = new Random(42); + + mDatabase + .execSQL("CREATE TABLE t1(a INTEGER, b INTEGER, c VARCHAR(100))"); + + for (int i = 0; i < SIZE; i++) { + int r = random.nextInt(100000); + mDatabase.execSQL("INSERT INTO t1 VALUES(" + i + "," + r + ",'" + + numberName(r) + "')"); + } + + for (int i = 0; i < SIZE; i++) { + where[i] = "c LIKE '" + numberName(i) + "'"; + } + } + + @Override + public void run() { + for (int i = 0; i < SIZE; i++) { + mDatabase + .query("t1", COLUMNS, where[i], null, null, null, null); + } + } + } + + /** + * 100 SELECTs with an index + */ + + public static class Perf5Test extends PerformanceBase { + private static final int SIZE = 100; + private static final String[] COLUMNS = {"count(*)", "avg(b)"}; + + private String[] where = new String[SIZE]; + + @Override + public void setUp(Context c) { + super.setUp(c); + Random random = new Random(42); + + mDatabase + .execSQL("CREATE TABLE t1(a INTEGER, b INTEGER, c VARCHAR(100))"); + mDatabase.execSQL("CREATE INDEX i1b ON t1(b)"); + + for (int i = 0; i < SIZE; i++) { + int r = random.nextInt(100000); + mDatabase.execSQL("INSERT INTO t1 VALUES(" + i + "," + r + ",'" + + numberName(r) + "')"); + } + + for (int i = 0; i < SIZE; i++) { + int lower = i * 100; + int upper = (i + 10) * 100; + where[i] = "b >= " + lower + " AND b < " + upper; + } + } + + @Override + public void run() { + for (int i = 0; i < SIZE; i++) { + mDatabase + .query("t1", COLUMNS, where[i], null, null, null, null); + } + } + } + + /** + * INNER JOIN without an index + */ + + public static class Perf6Test extends PerformanceBase { + private static final int SIZE = 100; + private static final String[] COLUMNS = {"t1.a"}; + + @Override + public void setUp(Context c) { + super.setUp(c); + Random random = new Random(42); + + mDatabase + .execSQL("CREATE TABLE t1(a INTEGER, b INTEGER, c VARCHAR(100))"); + mDatabase + .execSQL("CREATE TABLE t2(a INTEGER, b INTEGER, c VARCHAR(100))"); + + for (int i = 0; i < SIZE; i++) { + int r = random.nextInt(100000); + mDatabase.execSQL("INSERT INTO t1 VALUES(" + i + "," + r + ",'" + + numberName(r) + "')"); + } + + for (int i = 0; i < SIZE; i++) { + int r = random.nextInt(100000); + mDatabase.execSQL("INSERT INTO t2 VALUES(" + i + "," + r + ",'" + + numberName(r) + "')"); + } + } + + @Override + public void run() { + mDatabase.query("t1 INNER JOIN t2 ON t1.b = t2.b", COLUMNS, null, + null, null, null, null); + } + } + + /** + * INNER JOIN without an index on one side + */ + + public static class Perf7Test extends PerformanceBase { + private static final int SIZE = 100; + private static final String[] COLUMNS = {"t1.a"}; + + @Override + public void setUp(Context c) { + super.setUp(c); + Random random = new Random(42); + + mDatabase + .execSQL("CREATE TABLE t1(a INTEGER, b INTEGER, c VARCHAR(100))"); + mDatabase + .execSQL("CREATE TABLE t2(a INTEGER, b INTEGER, c VARCHAR(100))"); + + mDatabase.execSQL("CREATE INDEX i1b ON t1(b)"); + + for (int i = 0; i < SIZE; i++) { + int r = random.nextInt(100000); + mDatabase.execSQL("INSERT INTO t1 VALUES(" + i + "," + r + ",'" + + numberName(r) + "')"); + } + + for (int i = 0; i < SIZE; i++) { + int r = random.nextInt(100000); + mDatabase.execSQL("INSERT INTO t2 VALUES(" + i + "," + r + ",'" + + numberName(r) + "')"); + } + } + + @Override + public void run() { + mDatabase.query("t1 INNER JOIN t2 ON t1.b = t2.b", COLUMNS, null, + null, null, null, null); + } + } + + /** + * INNER JOIN without an index on one side + */ + + public static class Perf8Test extends PerformanceBase { + private static final int SIZE = 100; + private static final String[] COLUMNS = {"t1.a"}; + + @Override + public void setUp(Context c) { + super.setUp(c); + Random random = new Random(42); + + mDatabase + .execSQL("CREATE TABLE t1(a INTEGER, b INTEGER, c VARCHAR(100))"); + mDatabase + .execSQL("CREATE TABLE t2(a INTEGER, b INTEGER, c VARCHAR(100))"); + + mDatabase.execSQL("CREATE INDEX i1b ON t1(b)"); + + for (int i = 0; i < SIZE; i++) { + int r = random.nextInt(100000); + mDatabase.execSQL("INSERT INTO t1 VALUES(" + i + "," + r + ",'" + + numberName(r) + "')"); + } + + for (int i = 0; i < SIZE; i++) { + int r = random.nextInt(100000); + mDatabase.execSQL("INSERT INTO t2 VALUES(" + i + "," + r + ",'" + + numberName(r) + "')"); + } + } + + @Override + public void run() { + mDatabase.query("t1 INNER JOIN t2 ON t1.c = t2.c", COLUMNS, null, + null, null, null, null); + } + } + + /** + * 100 SELECTs with subqueries. Subquery is using an index + */ + + public static class Perf9Test extends PerformanceBase { + private static final int SIZE = 100; + private static final String[] COLUMNS = {"t1.a"}; + + private String[] where = new String[SIZE]; + + @Override + public void setUp(Context c) { + super.setUp(c); + Random random = new Random(42); + + mDatabase + .execSQL("CREATE TABLE t1(a INTEGER, b INTEGER, c VARCHAR(100))"); + mDatabase + .execSQL("CREATE TABLE t2(a INTEGER, b INTEGER, c VARCHAR(100))"); + + mDatabase.execSQL("CREATE INDEX i2b ON t2(b)"); + + for (int i = 0; i < SIZE; i++) { + int r = random.nextInt(100000); + mDatabase.execSQL("INSERT INTO t1 VALUES(" + i + "," + r + ",'" + + numberName(r) + "')"); + } + + for (int i = 0; i < SIZE; i++) { + int r = random.nextInt(100000); + mDatabase.execSQL("INSERT INTO t2 VALUES(" + i + "," + r + ",'" + + numberName(r) + "')"); + } + + for (int i = 0; i < SIZE; i++) { + int lower = i * 100; + int upper = (i + 10) * 100; + where[i] = + "t1.b IN (SELECT t2.b FROM t2 WHERE t2.b >= " + lower + + " AND t2.b < " + upper + ")"; + } + } + + @Override + public void run() { + for (int i = 0; i < SIZE; i++) { + mDatabase + .query("t1", COLUMNS, where[i], null, null, null, null); + } + } + } + + /** + * 100 SELECTs on string comparison with Index + */ + + public static class Perf10Test extends PerformanceBase { + private static final int SIZE = 100; + private static final String[] COLUMNS = {"count(*)", "avg(b)"}; + + private String[] where = new String[SIZE]; + + @Override + public void setUp(Context c) { + super.setUp(c); + Random random = new Random(42); + + mDatabase + .execSQL("CREATE TABLE t1(a INTEGER, b INTEGER, c VARCHAR(100))"); + mDatabase.execSQL("CREATE INDEX i3c ON t1(c)"); + + for (int i = 0; i < SIZE; i++) { + int r = random.nextInt(100000); + mDatabase.execSQL("INSERT INTO t1 VALUES(" + i + "," + r + ",'" + + numberName(r) + "')"); + } + + for (int i = 0; i < SIZE; i++) { + where[i] = "c LIKE '" + numberName(i) + "'"; + } + } + + @Override + public void run() { + for (int i = 0; i < SIZE; i++) { + mDatabase + .query("t1", COLUMNS, where[i], null, null, null, null); + } + } + } + + /** + * 100 SELECTs on integer + */ + + public static class Perf11Test extends PerformanceBase { + private static final int SIZE = 100; + private static final String[] COLUMNS = {"b"}; + + private String[] where = new String[SIZE]; + + @Override + public void setUp(Context c) { + super.setUp(c); + Random random = new Random(42); + + mDatabase + .execSQL("CREATE TABLE t1(a INTEGER, b INTEGER, c VARCHAR(100))"); + + for (int i = 0; i < SIZE; i++) { + int r = random.nextInt(100000); + mDatabase.execSQL("INSERT INTO t1 VALUES(" + i + "," + r + ",'" + + numberName(r) + "')"); + } + + } + + @Override + public void run() { + for (int i = 0; i < SIZE; i++) { + mDatabase.query("t1", COLUMNS, null, null, null, null, null); + } + } + } + + /** + * 100 SELECTs on String + */ + + public static class Perf12Test extends PerformanceBase { + private static final int SIZE = 100; + private static final String[] COLUMNS = {"c"}; + + private String[] where = new String[SIZE]; + + @Override + public void setUp(Context c) { + super.setUp(c); + Random random = new Random(42); + + mDatabase + .execSQL("CREATE TABLE t1(a INTEGER, b INTEGER, c VARCHAR(100))"); + + for (int i = 0; i < SIZE; i++) { + int r = random.nextInt(100000); + mDatabase.execSQL("INSERT INTO t1 VALUES(" + i + "," + r + ",'" + + numberName(r) + "')"); + } + + } + + @Override + public void run() { + for (int i = 0; i < SIZE; i++) { + mDatabase.query("t1", COLUMNS, null, null, null, null, null); + } + } + } + + /** + * 100 SELECTs on integer with index + */ + + public static class Perf13Test extends PerformanceBase { + private static final int SIZE = 100; + private static final String[] COLUMNS = {"b"}; + + @Override + public void setUp(Context c) { + super.setUp(c); + Random random = new Random(42); + + mDatabase + .execSQL("CREATE TABLE t1(a INTEGER, b INTEGER, c VARCHAR(100))"); + mDatabase.execSQL("CREATE INDEX i1b on t1(b)"); + + for (int i = 0; i < SIZE; i++) { + int r = random.nextInt(100000); + mDatabase.execSQL("INSERT INTO t1 VALUES(" + i + "," + r + ",'" + + numberName(r) + "')"); + } + + } + + @Override + public void run() { + for (int i = 0; i < SIZE; i++) { + mDatabase.query("t1", COLUMNS, null, null, null, null, null); + } + } + } + + /** + * 100 SELECTs on String with index + */ + + public static class Perf14Test extends PerformanceBase { + private static final int SIZE = 100; + private static final String[] COLUMNS = {"c"}; + + @Override + public void setUp(Context c) { + super.setUp(c); + Random random = new Random(42); + + mDatabase + .execSQL("CREATE TABLE t1(a INTEGER, b INTEGER, c VARCHAR(100))"); + mDatabase.execSQL("CREATE INDEX i1c ON t1(c)"); + + for (int i = 0; i < SIZE; i++) { + int r = random.nextInt(100000); + mDatabase.execSQL("INSERT INTO t1 VALUES(" + i + "," + r + ",'" + + numberName(r) + "')"); + } + + } + + @Override + public void run() { + for (int i = 0; i < SIZE; i++) { + mDatabase.query("t1", COLUMNS, null, null, null, null, null); + } + } + } + + /** + * 100 SELECTs on String with starts with + */ + + public static class Perf15Test extends PerformanceBase { + private static final int SIZE = 100; + private static final String[] COLUMNS = {"c"}; + private String[] where = new String[SIZE]; + + @Override + public void setUp(Context c) { + super.setUp(c); + Random random = new Random(42); + + mDatabase + .execSQL("CREATE TABLE t1(a INTEGER, b INTEGER, c VARCHAR(100))"); + mDatabase.execSQL("CREATE INDEX i1c ON t1(c)"); + + for (int i = 0; i < SIZE; i++) { + int r = random.nextInt(100000); + mDatabase.execSQL("INSERT INTO t1 VALUES(" + i + "," + r + ",'" + + numberName(r) + "')"); + } + + for (int i = 0; i < SIZE; i++) { + int r = random.nextInt(100000); + where[i] = "c LIKE '" + numberName(r).substring(0, 1) + "*'"; + + } + + } + + @Override + public void run() { + for (int i = 0; i < SIZE; i++) { + mDatabase + .query("t1", COLUMNS, where[i], null, null, null, null); + } + } + } + + /** + * 1000 Deletes on an indexed table + */ + + public static class Perf16Test extends PerformanceBase { + private static final int SIZE = 1000; + private static final String[] COLUMNS = {"c"}; + + @Override + public void setUp(Context c) { + super.setUp(c); + Random random = new Random(42); + + mDatabase + .execSQL("CREATE TABLE t1(a INTEGER, b INTEGER, c VARCHAR(100))"); + mDatabase.execSQL("CREATE INDEX i3c ON t1(c)"); + + for (int i = 0; i < SIZE; i++) { + int r = random.nextInt(100000); + mDatabase.execSQL("INSERT INTO t1 VALUES(" + i + "," + r + ",'" + + numberName(r) + "')"); + } + + } + + @Override + public void run() { + for (int i = 0; i < SIZE; i++) { + mDatabase.delete("t1", null, null); + } + } + } + + /** + * 1000 Deletes + */ + + public static class Perf17Test extends PerformanceBase { + private static final int SIZE = 1000; + private static final String[] COLUMNS = {"c"}; + + @Override + public void setUp(Context c) { + super.setUp(c); + Random random = new Random(42); + + mDatabase + .execSQL("CREATE TABLE t1(a INTEGER, b INTEGER, c VARCHAR(100))"); + + for (int i = 0; i < SIZE; i++) { + int r = random.nextInt(100000); + mDatabase.execSQL("INSERT INTO t1 VALUES(" + i + "," + r + ",'" + + numberName(r) + "')"); + } + + } + + @Override + public void run() { + for (int i = 0; i < SIZE; i++) { + mDatabase.delete("t1", null, null); + } + } + } + + /** + * 1000 DELETE's without an index with where clause + */ + + public static class Perf18Test extends PerformanceBase { + private static final int SIZE = 1000; + private String[] where = new String[SIZE]; + + @Override + public void setUp(Context c) { + super.setUp(c); + Random random = new Random(42); + + mDatabase + .execSQL("CREATE TABLE t1(a INTEGER, b INTEGER, c VARCHAR(100))"); + + for (int i = 0; i < SIZE; i++) { + int r = random.nextInt(100000); + mDatabase.execSQL("INSERT INTO t1 VALUES(" + i + "," + r + ",'" + + numberName(r) + "')"); + } + + for (int i = 0; i < SIZE; i++) { + int lower = i * 100; + int upper = (i + 10) * 100; + where[i] = "b >= " + lower + " AND b < " + upper; + } + } + + @Override + public void run() { + for (int i = 0; i < SIZE; i++) { + mDatabase.delete("t1", where[i], null); + } + } + } + + /** + * 1000 DELETE's with an index with where clause + */ + + public static class Perf19Test extends PerformanceBase { + private static final int SIZE = 1000; + private String[] where = new String[SIZE]; + + @Override + public void setUp(Context c) { + super.setUp(c); + Random random = new Random(42); + + mDatabase + .execSQL("CREATE TABLE t1(a INTEGER, b INTEGER, c VARCHAR(100))"); + mDatabase.execSQL("CREATE INDEX i1b ON t1(b)"); + + for (int i = 0; i < SIZE; i++) { + int r = random.nextInt(100000); + mDatabase.execSQL("INSERT INTO t1 VALUES(" + i + "," + r + ",'" + + numberName(r) + "')"); + } + + for (int i = 0; i < SIZE; i++) { + int lower = i * 100; + int upper = (i + 10) * 100; + where[i] = "b >= " + lower + " AND b < " + upper; + } + } + + @Override + public void run() { + for (int i = 0; i < SIZE; i++) { + mDatabase.delete("t1", where[i], null); + } + } + } + + /** + * 1000 update's with an index with where clause + */ + + public static class Perf20Test extends PerformanceBase { + private static final int SIZE = 1000; + private String[] where = new String[SIZE]; + ContentValues[] mValues = new ContentValues[SIZE]; + + @Override + public void setUp(Context c) { + super.setUp(c); + Random random = new Random(42); + + mDatabase + .execSQL("CREATE TABLE t1(a INTEGER, b INTEGER, c VARCHAR(100))"); + mDatabase.execSQL("CREATE INDEX i1b ON t1(b)"); + + for (int i = 0; i < SIZE; i++) { + int r = random.nextInt(100000); + mDatabase.execSQL("INSERT INTO t1 VALUES(" + i + "," + r + ",'" + + numberName(r) + "')"); + } + + for (int i = 0; i < SIZE; i++) { + + int lower = i * 100; + int upper = (i + 10) * 100; + where[i] = "b >= " + lower + " AND b < " + upper; + ContentValues b = new ContentValues(1); + b.put("b", upper); + mValues[i] = b; + + } + } + + @Override + public void run() { + for (int i = 0; i < SIZE; i++) { + mDatabase.update("t1", mValues[i], where[i], null); + } + } + } + + /** + * 1000 update's without an index with where clause + */ + + public static class Perf21Test extends PerformanceBase { + private static final int SIZE = 1000; + private String[] where = new String[SIZE]; + ContentValues[] mValues = new ContentValues[SIZE]; + + @Override + public void setUp(Context c) { + super.setUp(c); + Random random = new Random(42); + + mDatabase + .execSQL("CREATE TABLE t1(a INTEGER, b INTEGER, c VARCHAR(100))"); + + for (int i = 0; i < SIZE; i++) { + int r = random.nextInt(100000); + mDatabase.execSQL("INSERT INTO t1 VALUES(" + i + "," + r + ",'" + + numberName(r) + "')"); + } + + for (int i = 0; i < SIZE; i++) { + + int lower = i * 100; + int upper = (i + 10) * 100; + where[i] = "b >= " + lower + " AND b < " + upper; + ContentValues b = new ContentValues(1); + b.put("b", upper); + mValues[i] = b; + } + } + + @Override + public void run() { + for (int i = 0; i < SIZE; i++) { + mDatabase.update("t1", mValues[i], where[i], null); + } + } + } + + /** + * 10000 inserts for an integer + */ + + public static class Perf22Test extends PerformanceBase { + private static final int SIZE = 10000; + ContentValues[] mValues = new ContentValues[SIZE]; + + @Override + public void setUp(Context c) { + super.setUp(c); + Random random = new Random(42); + + mDatabase + .execSQL("CREATE TABLE t1(a INTEGER)"); + + for (int i = 0; i < SIZE; i++) { + int r = random.nextInt(100000); + ContentValues b = new ContentValues(1); + b.put("a", r); + mValues[i] = b; + } + } + + @Override + public void run() { + for (int i = 0; i < SIZE; i++) { + mDatabase.insert("t1", null, mValues[i]); + } + } + } + + /** + * 10000 inserts for an integer -indexed table + */ + + public static class Perf23Test extends PerformanceBase { + private static final int SIZE = 10000; + ContentValues[] mValues = new ContentValues[SIZE]; + + @Override + public void setUp(Context c) { + super.setUp(c); + Random random = new Random(42); + + mDatabase + .execSQL("CREATE TABLE t1(a INTEGER)"); + mDatabase.execSQL("CREATE INDEX i1a ON t1(a)"); + + for (int i = 0; i < SIZE; i++) { + int r = random.nextInt(100000); + ContentValues b = new ContentValues(1); + b.put("a", r); + mValues[i] = b; + } + } + + @Override + public void run() { + for (int i = 0; i < SIZE; i++) { + mDatabase.insert("t1", null, mValues[i]); + } + } + } + + /** + * 10000 inserts for a String + */ + + public static class Perf24Test extends PerformanceBase { + private static final int SIZE = 10000; + ContentValues[] mValues = new ContentValues[SIZE]; + + @Override + public void setUp(Context c) { + super.setUp(c); + Random random = new Random(42); + + mDatabase + .execSQL("CREATE TABLE t1(a VARCHAR(100))"); + + for (int i = 0; i < SIZE; i++) { + int r = random.nextInt(100000); + ContentValues b = new ContentValues(1); + b.put("a", numberName(r)); + mValues[i] = b; + } + } + + @Override + public void run() { + for (int i = 0; i < SIZE; i++) { + mDatabase.insert("t1", null, mValues[i]); + } + } + } + + /** + * 10000 inserts for a String - indexed table + */ + + public static class Perf25Test extends PerformanceBase { + private static final int SIZE = 10000; + ContentValues[] mValues = new ContentValues[SIZE]; + + @Override + public void setUp(Context c) { + super.setUp(c); + Random random = new Random(42); + + mDatabase + .execSQL("CREATE TABLE t1(a VARCHAR(100))"); + mDatabase.execSQL("CREATE INDEX i1a ON t1(a)"); + + for (int i = 0; i < SIZE; i++) { + int r = random.nextInt(100000); + ContentValues b = new ContentValues(1); + b.put("a", numberName(r)); + mValues[i] = b; + } + } + + @Override + public void run() { + for (int i = 0; i < SIZE; i++) { + mDatabase.insert("t1", null, mValues[i]); + } + } + } + + + /** + * 10000 selects for a String -starts with + */ + + public static class Perf26Test extends PerformanceBase { + private static final int SIZE = 10000; + private static final String[] COLUMNS = {"t3.a"}; + private String[] where = new String[SIZE]; + + @Override + public void setUp(Context c) { + super.setUp(c); + Random random = new Random(42); + + mDatabase + .execSQL("CREATE TABLE t3(a VARCHAR(100))"); + + for (int i = 0; i < SIZE; i++) { + int r = random.nextInt(100000); + mDatabase.execSQL("INSERT INTO t3 VALUES('" + + numberName(r) + "')"); + } + + for (int i = 0; i < SIZE; i++) { + int r = random.nextInt(100000); + where[i] = "a LIKE '" + numberName(r).substring(0, 1) + "*'"; + + } + } + + @Override + public void run() { + for (int i = 0; i < SIZE; i++) { + mDatabase.query("t3", COLUMNS, where[i], null, null, null, null); + } + } + } + + /** + * 10000 selects for a String - indexed table -starts with + */ + + public static class Perf27Test extends PerformanceBase { + private static final int SIZE = 10000; + private static final String[] COLUMNS = {"t3.a"}; + private String[] where = new String[SIZE]; + + @Override + public void setUp(Context c) { + super.setUp(c); + Random random = new Random(42); + + mDatabase + .execSQL("CREATE TABLE t3(a VARCHAR(100))"); + mDatabase.execSQL("CREATE INDEX i3a ON t3(a)"); + + for (int i = 0; i < SIZE; i++) { + int r = random.nextInt(100000); + mDatabase.execSQL("INSERT INTO t3 VALUES('" + + numberName(r) + "')"); + } + + for (int i = 0; i < SIZE; i++) { + int r = random.nextInt(100000); + where[i] = "a LIKE '" + numberName(r).substring(0, 1) + "*'"; + + } + } + + @Override + public void run() { + for (int i = 0; i < SIZE; i++) { + mDatabase.query("t3", COLUMNS, where[i], null, null, null, null); + } + } + } + + /** + * 10000 selects for an integer - + */ + + public static class Perf28Test extends PerformanceBase { + private static final int SIZE = 10000; + private static final String[] COLUMNS = {"t4.a"}; + private String[] where = new String[SIZE]; + + @Override + public void setUp(Context c) { + super.setUp(c); + Random random = new Random(42); + + mDatabase + .execSQL("CREATE TABLE t4(a INTEGER)"); + + for (int i = 0; i < SIZE; i++) { + int r = random.nextInt(100000); + mDatabase.execSQL("INSERT INTO t4 VALUES(" + r + ")"); + int lower = i * 100; + int upper = (i + 10) * 100; + where[i] = "a >= " + lower + " AND a < " + upper; + } + } + + @Override + public void run() { + for (int i = 0; i < SIZE; i++) { + mDatabase.query("t4", COLUMNS, where[i], null, null, null, null); + } + } + } + + /** + * 10000 selects for an integer -indexed table + */ + + public static class Perf29Test extends PerformanceBase { + private static final int SIZE = 10000; + private static final String[] COLUMNS = {"t4.a"}; + private String[] where = new String[SIZE]; + + @Override + public void setUp(Context c) { + super.setUp(c); + Random random = new Random(42); + + mDatabase + .execSQL("CREATE TABLE t4(a INTEGER)"); + mDatabase.execSQL("CREATE INDEX i4a ON t4(a)"); + + for (int i = 0; i < SIZE; i++) { + int r = random.nextInt(100000); + mDatabase.execSQL("INSERT INTO t4 VALUES(" + r + ")"); + + int lower = i * 100; + int upper = (i + 10) * 100; + where[i] = "a >= " + lower + " AND a < " + upper; + } + + } + + @Override + public void run() { + for (int i = 0; i < SIZE; i++) { + mDatabase.query("t4", COLUMNS, where[i], null, null, null, null); + } + } + } + + + /** + * 10000 selects for a String - contains 'e' + */ + + public static class Perf30Test extends PerformanceBase { + private static final int SIZE = 10000; + private static final String[] COLUMNS = {"t3.a"}; + private String[] where = new String[SIZE]; + + @Override + public void setUp(Context c) { + super.setUp(c); + Random random = new Random(42); + + mDatabase + .execSQL("CREATE TABLE t3(a VARCHAR(100))"); + + for (int i = 0; i < SIZE; i++) { + int r = random.nextInt(100000); + mDatabase.execSQL("INSERT INTO t3 VALUES('" + + numberName(r) + "')"); + } + + for (int i = 0; i < SIZE; i++) { + where[i] = "a LIKE '*e*'"; + + } + } + + @Override + public void run() { + for (int i = 0; i < SIZE; i++) { + mDatabase.query("t3", COLUMNS, where[i], null, null, null, null); + } + } + } + + /** + * 10000 selects for a String - contains 'e'-indexed table + */ + + public static class Perf31Test extends PerformanceBase { + private static final int SIZE = 10000; + private static final String[] COLUMNS = {"t3.a"}; + private String[] where = new String[SIZE]; + + @Override + public void setUp(Context c) { + super.setUp(c); + Random random = new Random(42); + + mDatabase + .execSQL("CREATE TABLE t3(a VARCHAR(100))"); + mDatabase.execSQL("CREATE INDEX i3a ON t3(a)"); + + for (int i = 0; i < SIZE; i++) { + int r = random.nextInt(100000); + mDatabase.execSQL("INSERT INTO t3 VALUES('" + + numberName(r) + "')"); + } + + for (int i = 0; i < SIZE; i++) { + where[i] = "a LIKE '*e*'"; + + } + + } + + @Override + public void run() { + for (int i = 0; i < SIZE; i++) { + mDatabase.query("t3", COLUMNS, where[i], null, null, null, null); + } + } + } + + public static final String[] ONES = + {"zero", "one", "two", "three", "four", "five", "six", "seven", + "eight", "nine", "ten", "eleven", "twelve", "thirteen", + "fourteen", "fifteen", "sixteen", "seventeen", "eighteen", + "nineteen"}; + + public static final String[] TENS = + {"", "ten", "twenty", "thirty", "forty", "fifty", "sixty", + "seventy", "eighty", "ninety"}; +} diff --git a/tests/AndroidTests/src/com/android/unit_tests/DatabaseStatementTest.java b/tests/AndroidTests/src/com/android/unit_tests/DatabaseStatementTest.java new file mode 100644 index 0000000..16ca59f --- /dev/null +++ b/tests/AndroidTests/src/com/android/unit_tests/DatabaseStatementTest.java @@ -0,0 +1,320 @@ +/* + * 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.unit_tests; + +import android.database.Cursor; +import android.database.sqlite.SQLiteConstraintException; +import android.database.sqlite.SQLiteDatabase; +import android.database.sqlite.SQLiteDoneException; +import android.database.sqlite.SQLiteStatement; +import android.test.PerformanceTestCase; +import android.test.suitebuilder.annotation.MediumTest; +import android.test.suitebuilder.annotation.SmallTest; +import junit.framework.TestCase; + +import java.io.File; + +public class DatabaseStatementTest extends TestCase implements PerformanceTestCase { + + private static final String sString1 = "this is a test"; + private static final String sString2 = "and yet another test"; + private static final String sString3 = "this string is a little longer, but still a test"; + + private static final int CURRENT_DATABASE_VERSION = 42; + private SQLiteDatabase mDatabase; + private File mDatabaseFile; + + @Override + protected void setUp() throws Exception { + super.setUp(); + mDatabaseFile = new File("/sqlite_stmt_journals", "database_test.db"); + if (mDatabaseFile.exists()) { + mDatabaseFile.delete(); + } + mDatabase = SQLiteDatabase.openOrCreateDatabase(mDatabaseFile.getPath(), null); + assertNotNull(mDatabase); + mDatabase.setVersion(CURRENT_DATABASE_VERSION); + } + + @Override + protected void tearDown() throws Exception { + mDatabase.close(); + mDatabaseFile.delete(); + super.tearDown(); + } + + public boolean isPerformanceOnly() { + return false; + } + + // These test can only be run once. + public int startPerformance(Intermediates intermediates) { + return 1; + } + + private void populateDefaultTable() { + mDatabase.execSQL("CREATE TABLE test (_id INTEGER PRIMARY KEY, data TEXT);"); + + mDatabase.execSQL("INSERT INTO test (data) VALUES ('" + sString1 + "');"); + mDatabase.execSQL("INSERT INTO test (data) VALUES ('" + sString2 + "');"); + mDatabase.execSQL("INSERT INTO test (data) VALUES ('" + sString3 + "');"); + } + + @MediumTest + public void testExecuteStatement() throws Exception { + populateDefaultTable(); + SQLiteStatement statement = mDatabase.compileStatement("DELETE FROM test"); + statement.execute(); + + Cursor c = mDatabase.query("test", null, null, null, null, null, null); + assertEquals(0, c.getCount()); + c.deactivate(); + statement.close(); + } + + @MediumTest + public void testSimpleQuery() throws Exception { + mDatabase.execSQL("CREATE TABLE test (num INTEGER NOT NULL, str TEXT NOT NULL);"); + mDatabase.execSQL("INSERT INTO test VALUES (1234, 'hello');"); + SQLiteStatement statement1 = + mDatabase.compileStatement("SELECT num FROM test WHERE str = ?"); + SQLiteStatement statement2 = + mDatabase.compileStatement("SELECT str FROM test WHERE num = ?"); + + try { + statement1.bindString(1, "hello"); + long value = statement1.simpleQueryForLong(); + assertEquals(1234, value); + + statement1.bindString(1, "world"); + statement1.simpleQueryForLong(); + fail("shouldn't get here"); + } catch (SQLiteDoneException e) { + // expected + } + + try { + statement2.bindLong(1, 1234); + String value = statement1.simpleQueryForString(); + assertEquals("hello", value); + + statement2.bindLong(1, 5678); + statement1.simpleQueryForString(); + fail("shouldn't get here"); + } catch (SQLiteDoneException e) { + // expected + } + + statement1.close(); + statement2.close(); + } + + @MediumTest + public void testStatementLongBinding() throws Exception { + mDatabase.execSQL("CREATE TABLE test (num INTEGER);"); + SQLiteStatement statement = mDatabase.compileStatement("INSERT INTO test (num) VALUES (?)"); + + for (int i = 0; i < 10; i++) { + statement.bindLong(1, i); + statement.execute(); + } + statement.close(); + + Cursor c = mDatabase.query("test", null, null, null, null, null, null); + int numCol = c.getColumnIndexOrThrow("num"); + c.moveToFirst(); + for (long i = 0; i < 10; i++) { + long num = c.getLong(numCol); + assertEquals(i, num); + c.moveToNext(); + } + c.close(); + } + + @MediumTest + public void testStatementStringBinding() throws Exception { + mDatabase.execSQL("CREATE TABLE test (num TEXT);"); + SQLiteStatement statement = mDatabase.compileStatement("INSERT INTO test (num) VALUES (?)"); + + for (long i = 0; i < 10; i++) { + statement.bindString(1, Long.toHexString(i)); + statement.execute(); + } + statement.close(); + + Cursor c = mDatabase.query("test", null, null, null, null, null, null); + int numCol = c.getColumnIndexOrThrow("num"); + c.moveToFirst(); + for (long i = 0; i < 10; i++) { + String num = c.getString(numCol); + assertEquals(Long.toHexString(i), num); + c.moveToNext(); + } + c.close(); + } + + @MediumTest + public void testStatementClearBindings() throws Exception { + mDatabase.execSQL("CREATE TABLE test (num INTEGER);"); + SQLiteStatement statement = mDatabase.compileStatement("INSERT INTO test (num) VALUES (?)"); + + for (long i = 0; i < 10; i++) { + statement.bindLong(1, i); + statement.clearBindings(); + statement.execute(); + } + statement.close(); + + Cursor c = mDatabase.query("test", null, null, null, null, null, "ROWID"); + int numCol = c.getColumnIndexOrThrow("num"); + assertTrue(c.moveToFirst()); + for (long i = 0; i < 10; i++) { + assertTrue(c.isNull(numCol)); + c.moveToNext(); + } + c.close(); + } + + @MediumTest + public void testSimpleStringBinding() throws Exception { + mDatabase.execSQL("CREATE TABLE test (num TEXT, value TEXT);"); + String statement = "INSERT INTO test (num, value) VALUES (?,?)"; + + String[] args = new String[2]; + for (int i = 0; i < 2; i++) { + args[i] = Integer.toHexString(i); + } + + mDatabase.execSQL(statement, args); + + Cursor c = mDatabase.query("test", null, null, null, null, null, null); + int numCol = c.getColumnIndexOrThrow("num"); + int valCol = c.getColumnIndexOrThrow("value"); + c.moveToFirst(); + String num = c.getString(numCol); + assertEquals(Integer.toHexString(0), num); + + String val = c.getString(valCol); + assertEquals(Integer.toHexString(1), val); + c.close(); + } + + @MediumTest + public void testStatementMultipleBindings() throws Exception { + mDatabase.execSQL("CREATE TABLE test (num INTEGER, str TEXT);"); + SQLiteStatement statement = + mDatabase.compileStatement("INSERT INTO test (num, str) VALUES (?, ?)"); + + for (long i = 0; i < 10; i++) { + statement.bindLong(1, i); + statement.bindString(2, Long.toHexString(i)); + statement.execute(); + } + statement.close(); + + Cursor c = mDatabase.query("test", null, null, null, null, null, "ROWID"); + int numCol = c.getColumnIndexOrThrow("num"); + int strCol = c.getColumnIndexOrThrow("str"); + assertTrue(c.moveToFirst()); + for (long i = 0; i < 10; i++) { + long num = c.getLong(numCol); + String str = c.getString(strCol); + assertEquals(i, num); + assertEquals(Long.toHexString(i), str); + c.moveToNext(); + } + c.close(); + } + + private static class StatementTestThread extends Thread { + private SQLiteDatabase mDatabase; + private SQLiteStatement mStatement; + + public StatementTestThread(SQLiteDatabase db, SQLiteStatement statement) { + super(); + mDatabase = db; + mStatement = statement; + } + + @Override + public void run() { + mDatabase.beginTransaction(); + for (long i = 0; i < 10; i++) { + mStatement.bindLong(1, i); + mStatement.bindString(2, Long.toHexString(i)); + mStatement.execute(); + } + mDatabase.setTransactionSuccessful(); + mDatabase.endTransaction(); + + Cursor c = mDatabase.query("test", null, null, null, null, null, "ROWID"); + int numCol = c.getColumnIndexOrThrow("num"); + int strCol = c.getColumnIndexOrThrow("str"); + assertTrue(c.moveToFirst()); + for (long i = 0; i < 10; i++) { + long num = c.getLong(numCol); + String str = c.getString(strCol); + assertEquals(i, num); + assertEquals(Long.toHexString(i), str); + c.moveToNext(); + } + c.close(); + } + } + + @MediumTest + public void testStatementMultiThreaded() throws Exception { + mDatabase.execSQL("CREATE TABLE test (num INTEGER, str TEXT);"); + SQLiteStatement statement = + mDatabase.compileStatement("INSERT INTO test (num, str) VALUES (?, ?)"); + + StatementTestThread thread = new StatementTestThread(mDatabase, statement); + thread.start(); + try { + thread.join(); + } finally { + statement.close(); + } + } + + @MediumTest + public void testStatementConstraint() throws Exception { + mDatabase.execSQL("CREATE TABLE test (num INTEGER NOT NULL);"); + SQLiteStatement statement = mDatabase.compileStatement("INSERT INTO test (num) VALUES (?)"); + + // Try to insert NULL, which violates the constraint + try { + statement.clearBindings(); + statement.execute(); + fail("expected exception not thrown"); + } catch (SQLiteConstraintException e) { + // expected + } + + // Make sure the statement can still be used + statement.bindLong(1, 1); + statement.execute(); + statement.close(); + + Cursor c = mDatabase.query("test", null, null, null, null, null, null); + int numCol = c.getColumnIndexOrThrow("num"); + c.moveToFirst(); + long num = c.getLong(numCol); + assertEquals(1, num); + c.close(); + } +} diff --git a/tests/AndroidTests/src/com/android/unit_tests/DatabaseStressTest.java b/tests/AndroidTests/src/com/android/unit_tests/DatabaseStressTest.java new file mode 100644 index 0000000..b110125 --- /dev/null +++ b/tests/AndroidTests/src/com/android/unit_tests/DatabaseStressTest.java @@ -0,0 +1,99 @@ +/* + * Copyright (C) 2008 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.unit_tests; + +import android.content.Context; +import android.database.sqlite.*; +import android.util.Log; + +import android.test.AndroidTestCase; +import android.test.suitebuilder.annotation.Suppress; + +import java.io.File; + +// This test suite is too desctructive and takes too long to be included in the +// automated suite. +@Suppress +public class DatabaseStressTest extends AndroidTestCase { + private static final String TAG = "DatabaseStressTest"; + private static final int CURRENT_DATABASE_VERSION = 1; + private SQLiteDatabase mDatabase; + private File mDatabaseFile; + + @Override + protected void setUp() throws Exception { + super.setUp(); + Context c = getContext(); + + mDatabaseFile = c.getDatabasePath("database_test.db"); + if (mDatabaseFile.exists()) { + mDatabaseFile.delete(); + } + + mDatabase = c.openOrCreateDatabase("database_test.db", 0, null); + + assertNotNull(mDatabase); + mDatabase.setVersion(CURRENT_DATABASE_VERSION); + + mDatabase.execSQL("CREATE TABLE IF NOT EXISTS test (_id INTEGER PRIMARY KEY, data TEXT);"); + + } + + @Override + protected void tearDown() throws Exception { + mDatabase.close(); + mDatabaseFile.delete(); + super.tearDown(); + } + + public void testSingleThreadInsertDelete() { + int i = 0; + char[] ch = new char[100000]; + String str = new String(ch); + String[] strArr = new String[1]; + strArr[0] = str; + for (; i < 10000; ++i) { + try { + mDatabase.execSQL("INSERT INTO test (data) VALUES (?)", strArr); + mDatabase.execSQL("delete from test;"); + } catch (Exception e) { + Log.e(TAG, "exception " + e.getMessage()); + } + } + } + + /** + * use fillup -p 90 before run the test + * and when disk run out + * start delete some fillup files + * and see if db recover + */ + public void testOutOfSpace() { + int i = 0; + char[] ch = new char[100000]; + String str = new String(ch); + String[] strArr = new String[1]; + strArr[0] = str; + for (; i < 10000; ++i) { + try { + mDatabase.execSQL("INSERT INTO test (data) VALUES (?)", strArr); + } catch (Exception e) { + Log.e(TAG, "exception " + e.getMessage()); + } + } + } +} diff --git a/tests/AndroidTests/src/com/android/unit_tests/DatabaseTests.java b/tests/AndroidTests/src/com/android/unit_tests/DatabaseTests.java new file mode 100644 index 0000000..a7a1400 --- /dev/null +++ b/tests/AndroidTests/src/com/android/unit_tests/DatabaseTests.java @@ -0,0 +1,34 @@ +/* + * 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.unit_tests; + +import junit.framework.TestSuite; + +public class DatabaseTests { + public static TestSuite suite() { + TestSuite suite = new TestSuite(DatabaseTests.class.getName()); + + suite.addTestSuite(DatabaseGeneralTest.class); + suite.addTestSuite(DatabaseCursorTest.class); + suite.addTestSuite(DatabaseStatementTest.class); + suite.addTestSuite(DatabaseLocaleTest.class); + suite.addTestSuite(CursorWindowTest.class); + suite.addTestSuite(DatabaseLockTest.class); + + return suite; + } +} diff --git a/tests/AndroidTests/src/com/android/unit_tests/DbSSLSessionCacheTest.java b/tests/AndroidTests/src/com/android/unit_tests/DbSSLSessionCacheTest.java new file mode 100644 index 0000000..8d7d797 --- /dev/null +++ b/tests/AndroidTests/src/com/android/unit_tests/DbSSLSessionCacheTest.java @@ -0,0 +1,259 @@ +/* + * Copyright (C) 2008 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.unit_tests; + +import android.content.ContentResolver; +import android.database.Cursor; +import android.database.sqlite.SQLiteOpenHelper; +import android.provider.Settings; +import android.test.AndroidTestCase; +import android.test.suitebuilder.annotation.LargeTest; +import android.test.suitebuilder.annotation.Suppress; + +import com.google.android.net.GoogleHttpClient; + +import com.android.internal.net.DbSSLSessionCache; +import com.android.internal.net.DbSSLSessionCache.DatabaseHelper; + +import org.apache.http.HttpResponse; +import org.apache.http.client.methods.HttpGet; + +import java.io.IOException; +import java.security.Principal; +import java.security.cert.Certificate; + +import javax.net.ssl.SSLPeerUnverifiedException; +import javax.net.ssl.SSLSession; +import javax.net.ssl.SSLSessionContext; +import javax.security.cert.X509Certificate; + +/** Unit test for SSL session caching with {@link GoogleHttpClient}. + * Uses network resources. + */ +@Suppress +public class DbSSLSessionCacheTest extends AndroidTestCase { + + protected void setUp() throws Exception { + } + + protected void tearDown() throws Exception { + } + + /** + * We want to test the actual database write - the actual hooking into + * low-level SSL is tested. + */ + @LargeTest + public void testSslCacheAdd() throws Exception { + // Let's verify the database has the rows. + // Use internal details of the implementation - could make the field + // visible for testing, but it's same. + + // Use default database + DbSSLSessionCache cache = DbSSLSessionCache.getInstanceForPackage(getContext()); + cache.clear(); + + + makeRequestInNewContext("https://www.google.com"); + + // Verify the key was inserted + SQLiteOpenHelper helper = new DatabaseHelper(getContext()); + Cursor query = null; + try { + query = helper.getReadableDatabase().query(DbSSLSessionCache.SSL_CACHE_TABLE, + new String[] {"hostport"}, null, + null, null, null, null); + + assertTrue(query.moveToFirst()); // one row inserted + String hostPort = query.getString(0); + assertEquals(hostPort, "www.google.com:443"); + } finally { + query.close(); + } + } + + @LargeTest + public void testExpire() throws Exception { + DatabaseHelper helper = new DatabaseHelper(getContext()); + // clean up + DbSSLSessionCache cache = new DbSSLSessionCache(helper); + cache.clear(); + + long t0 = System.currentTimeMillis(); + for (int i = 0; i < DbSSLSessionCache.MAX_CACHE_SIZE + 2; i++) { + final int port = i; + cache.putSessionData(new MockSession() { + + public String getPeerHost() { + return "test.host.com"; + } + + public int getPeerPort() { + return port; + } + }, new byte[256]); + } + long t1 = System.currentTimeMillis(); + + System.err.println("Time to insert " + + (DbSSLSessionCache.MAX_CACHE_SIZE + 2) + " " + (t1 - t0)); + + // first entry should have port 1. + Cursor query = helper.getReadableDatabase().query(DbSSLSessionCache.SSL_CACHE_TABLE, + new String[] {"hostport", "session"}, null, + null, null, null, null); + + int cnt = query.getCount(); + + assertTrue(query.moveToFirst()); // one row inserted + String hostPort = query.getString(0); + assertEquals("test.host.com:2", hostPort); + while (query.moveToNext()) { + hostPort = query.getString(0); + String session = query.getString(1); + } + long t2 = System.currentTimeMillis(); + System.err.println("Time to load " + cnt + " " + (t2 - t1)); + + query.close(); + } + + private void makeRequestInNewContext(String url) throws IOException { + GoogleHttpClient client = new GoogleHttpClient(getContext(), "Test", + false /* no gzip */); + + try { + // Note: we must test against a real server, because the connection + // gets established before the interceptor can crash the request. + HttpGet method = new HttpGet(url); + HttpResponse response = client.execute(method); + } finally { + client.close(); + } + } + + private static class MockSession implements SSLSession { + + public String getPeerHost() { + throw new UnsupportedOperationException(); + } + + + public int getPeerPort() { + throw new UnsupportedOperationException(); + } + + + + public int getApplicationBufferSize() { + throw new UnsupportedOperationException(); + } + + + public String getCipherSuite() { + throw new UnsupportedOperationException(); + } + + + public long getCreationTime() { + throw new UnsupportedOperationException(); + } + + + public byte[] getId() { + throw new UnsupportedOperationException(); + } + + + public long getLastAccessedTime() { + throw new UnsupportedOperationException(); + } + + + public Certificate[] getLocalCertificates() { + throw new UnsupportedOperationException(); + } + + + public Principal getLocalPrincipal() { + throw new UnsupportedOperationException(); + } + + + public int getPacketBufferSize() { + throw new UnsupportedOperationException(); + } + + + public X509Certificate[] getPeerCertificateChain() + throws SSLPeerUnverifiedException { + throw new UnsupportedOperationException(); + } + + + public Certificate[] getPeerCertificates() throws SSLPeerUnverifiedException { + throw new UnsupportedOperationException(); + } + + + public Principal getPeerPrincipal() throws SSLPeerUnverifiedException { + throw new UnsupportedOperationException(); + } + + + public String getProtocol() { + throw new UnsupportedOperationException(); + } + + + public SSLSessionContext getSessionContext() { + throw new UnsupportedOperationException(); + } + + + public Object getValue(String name) { + throw new UnsupportedOperationException(); + } + + + public String[] getValueNames() { + throw new UnsupportedOperationException(); + } + + + public void invalidate() { + throw new UnsupportedOperationException(); + } + + + public boolean isValid() { + throw new UnsupportedOperationException(); + } + + + public void putValue(String name, Object value) { + throw new UnsupportedOperationException(); + } + + + public void removeValue(String name) { + throw new UnsupportedOperationException(); + } + } + + +} diff --git a/tests/AndroidTests/src/com/android/unit_tests/ExpatPerformanceTest.java b/tests/AndroidTests/src/com/android/unit_tests/ExpatPerformanceTest.java new file mode 100644 index 0000000..0d51047 --- /dev/null +++ b/tests/AndroidTests/src/com/android/unit_tests/ExpatPerformanceTest.java @@ -0,0 +1,123 @@ +/* + * 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.unit_tests; + +import android.test.AndroidTestCase; +import android.test.suitebuilder.annotation.LargeTest; +import android.util.Log; +import android.util.Xml; +import org.kxml2.io.KXmlParser; +import org.xml.sax.SAXException; +import org.xml.sax.helpers.DefaultHandler; +import org.xmlpull.v1.XmlPullParser; +import org.xmlpull.v1.XmlPullParserException; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; + +public class ExpatPerformanceTest extends AndroidTestCase { + + private static final String TAG = ExpatPerformanceTest.class.getSimpleName(); + + private byte[] mXmlBytes; + + @Override + public void setUp() throws Exception { + super.setUp(); + InputStream in = mContext.getResources().openRawResource(R.raw.youtube); + ByteArrayOutputStream out = new ByteArrayOutputStream(); + byte[] buffer = new byte[1024]; + int length; + while ((length = in.read(buffer)) != -1) { + out.write(buffer, 0, length); + } + mXmlBytes = out.toByteArray(); + + Log.i("***", "File size: " + (mXmlBytes.length / 1024) + "k"); + } + + @LargeTest + public void testPerformance() throws Exception { +// try { +// Debug.startMethodTracing("expat3"); +// for (int i = 0; i < 1; i++) { + runJavaPullParser(); + runSax(); + runExpatPullParser(); +// } +// } finally { +// Debug.stopMethodTracing(); +// } + } + + private InputStream newInputStream() { + return new ByteArrayInputStream(mXmlBytes); + } + + private void runSax() throws IOException, SAXException { + long start = System.currentTimeMillis(); + Xml.parse(newInputStream(), Xml.Encoding.UTF_8, new DefaultHandler()); + long elapsed = System.currentTimeMillis() - start; + Log.i(TAG, "expat SAX: " + elapsed + "ms"); + } + + private void runExpatPullParser() throws XmlPullParserException, IOException { + long start = System.currentTimeMillis(); + XmlPullParser pullParser = Xml.newPullParser(); + pullParser.setInput(newInputStream(), "UTF-8"); + withPullParser(pullParser); + long elapsed = System.currentTimeMillis() - start; + Log.i(TAG, "expat pull: " + elapsed + "ms"); + } + + private void runJavaPullParser() throws XmlPullParserException, IOException { + XmlPullParser pullParser; + long start = System.currentTimeMillis(); + pullParser = new KXmlParser(); + pullParser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, true); + pullParser.setInput(newInputStream(), "UTF-8"); + withPullParser(pullParser); + long elapsed = System.currentTimeMillis() - start; + Log.i(TAG, "java pull parser: " + elapsed + "ms"); + } + + private static void withPullParser(XmlPullParser pullParser) + throws IOException, XmlPullParserException { + int eventType = pullParser.next(); + while (eventType != XmlPullParser.END_DOCUMENT) { + switch (eventType) { + case XmlPullParser.START_TAG: + pullParser.getName(); +// int nattrs = pullParser.getAttributeCount(); +// for (int i = 0; i < nattrs; ++i) { +// pullParser.getAttributeName(i); +// pullParser.getAttributeValue(i); +// } + break; + case XmlPullParser.END_TAG: + pullParser.getName(); + break; + case XmlPullParser.TEXT: + pullParser.getText(); + break; + } + eventType = pullParser.next(); + } + } +} diff --git a/tests/AndroidTests/src/com/android/unit_tests/GDataParseTest.java b/tests/AndroidTests/src/com/android/unit_tests/GDataParseTest.java new file mode 100644 index 0000000..af85483 --- /dev/null +++ b/tests/AndroidTests/src/com/android/unit_tests/GDataParseTest.java @@ -0,0 +1,162 @@ +/* + * 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.unit_tests; + +import android.content.res.XmlResourceParser; +import android.test.AndroidTestCase; +import android.test.PerformanceTestCase; +import android.test.suitebuilder.annotation.MediumTest; +import android.test.suitebuilder.annotation.SmallTest; +import android.util.Xml; +import com.google.wireless.gdata.data.Entry; +import com.google.wireless.gdata.data.Feed; +import com.google.wireless.gdata.parser.ParseException; +import com.google.wireless.gdata.parser.xml.XmlGDataParser; +import org.json.JSONObject; +import org.json.JSONTokener; +import org.xmlpull.v1.XmlPullParser; +import org.xmlpull.v1.XmlPullParserException; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.util.zip.GZIPInputStream; + +/** + * Tests timing on parsing various formats of GData. + */ +public class GDataParseTest extends AndroidTestCase implements PerformanceTestCase { + + private static void parseXml(InputStream is) throws ParseException, IOException { + XmlPullParser xmlParser = Xml.newPullParser(); + XmlGDataParser parser = new XmlGDataParser(is, xmlParser); + Feed feed = parser.init(); + Entry entry = null; + while (parser.hasMoreData()) { + entry = parser.readNextEntry(entry); + } + } + + private static void parseXml(XmlPullParser xmlP) throws ParseException, IOException { + XmlGDataParser parser = new XmlGDataParser(null /* in */, xmlP); + Feed feed = parser.init(); + Entry entry = null; + while (parser.hasMoreData()) { + entry = parser.readNextEntry(entry); + } + } + + private static void dumpXml(XmlPullParser parser) throws + XmlPullParserException, IOException { + int eventType = parser.nextTag(); + while (eventType != XmlPullParser.END_DOCUMENT) { + switch (eventType) { + case XmlPullParser.START_TAG: + parser.getName(); + // System.out.print("<" + parser.getName()); + int nattrs = parser.getAttributeCount(); + for (int i = 0; i < nattrs; ++i) { + parser.getAttributeName(i); + parser.getAttributeValue(i); + // System.out.print(" " + parser.getAttributeName(i) + "=\"" + // + parser.getAttributeValue(i) + "\""); + } + // System.out.print(">"); + break; + case XmlPullParser.END_TAG: + parser.getName(); + // System.out.print("</" + parser.getName() + ">"); + break; + case XmlPullParser.TEXT: + parser.getText(); + // System.out.print(parser.getText()); + break; + default: + // do nothing + } + eventType = parser.next(); + } + } + + private byte[] getBytesForResource(int resid) throws Exception { + // all resources are written into a zip file, so the InputStream we + // get for a resource is on top of zipped + // data. in order to compare performance of parsing unzipped vs. + // zipped content, we first read the data into an in-memory buffer. + InputStream zipIs = null; + try { + zipIs = mContext.getResources().openRawResource(resid); + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + byte buf[] = new byte[1024]; + int bytesRead = zipIs.read(buf); + while (bytesRead > 0) { + baos.write(buf, 0, bytesRead); + bytesRead = zipIs.read(buf); + } + return baos.toByteArray(); + } finally { + if (zipIs != null) { + zipIs.close(); + } + } + } + + public boolean isPerformanceOnly() { + return true; + } + + public int startPerformance(PerformanceTestCase.Intermediates intermediates) { + return 0; + } + + @MediumTest + public void testXml() throws Exception { + InputStream is = new ByteArrayInputStream(getBytesForResource(R.raw.calendarxml)); + try { + is.reset(); + parseXml(is); + } finally { + is.close(); + } + } + + @MediumTest + public void testXmlGzip() throws Exception { + InputStream gzIs = new GZIPInputStream( + new ByteArrayInputStream(getBytesForResource(R.raw.calendarxmlgz))); + try { + parseXml(gzIs); + } finally { + gzIs.close(); + } + } + + @MediumTest + public void testJson() throws Exception { + String jsonString = new String(getBytesForResource(R.raw.calendarjs), "UTF-8"); + JSONTokener tokens = new JSONTokener(jsonString); + assertNotNull(new JSONObject(tokens)); + } + + @SmallTest + public void testBinaryXml() throws Exception { + XmlResourceParser parser = mContext.getResources().getXml(R.xml.calendar); + parseXml(parser); + parser.close(); + } +} diff --git a/tests/AndroidTests/src/com/android/unit_tests/GeocoderTest.java b/tests/AndroidTests/src/com/android/unit_tests/GeocoderTest.java new file mode 100644 index 0000000..e28a7dc --- /dev/null +++ b/tests/AndroidTests/src/com/android/unit_tests/GeocoderTest.java @@ -0,0 +1,64 @@ +package com.android.unit_tests; + +/* + * 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. + */ + +import android.location.Address; +import android.location.Geocoder; +import android.test.AndroidTestCase; +import android.test.suitebuilder.annotation.Suppress; +import android.util.Log; + +import java.io.IOException; +import java.util.HashSet; +import java.util.Locale; +import java.util.Set; +import java.util.List; + +@Suppress +public class GeocoderTest extends AndroidTestCase { + + public void testGeocoder() throws Exception { + Locale locale = new Locale("en", "us"); + Geocoder g = new Geocoder(mContext, locale); + + List<Address> addresses1 = g.getFromLocation(37.435067, -122.166767, 2); + assertNotNull(addresses1); + assertEquals(1, addresses1.size()); + + Address addr = addresses1.get(0); + assertEquals("94305", addr.getFeatureName()); + assertEquals("Palo Alto, CA 94305", addr.getAddressLine(0)); + assertEquals("USA", addr.getAddressLine(1)); + assertEquals("94305", addr.getPostalCode()); + assertFalse(Math.abs(addr.getLatitude() - 37.4240385) > 0.1); + + List<Address> addresses2 = g.getFromLocationName("San Francisco, CA", 1); + assertNotNull(addresses2); + assertEquals(1, addresses2.size()); + + addr = addresses2.get(0); + assertEquals("San Francisco", addr.getFeatureName()); + assertEquals("San Francisco, CA", addr.getAddressLine(0)); + assertEquals("United States", addr.getAddressLine(1)); + assertEquals("San Francisco", addr.getLocality()); + assertEquals("CA", addr.getAdminArea()); + assertEquals(null, addr.getPostalCode()); + + assertFalse(Math.abs(addr.getLatitude() - 37.77916) > 0.1); + + } +} diff --git a/tests/AndroidTests/src/com/android/unit_tests/GoogleHttpClientTest.java b/tests/AndroidTests/src/com/android/unit_tests/GoogleHttpClientTest.java new file mode 100644 index 0000000..d970de3 --- /dev/null +++ b/tests/AndroidTests/src/com/android/unit_tests/GoogleHttpClientTest.java @@ -0,0 +1,122 @@ +/* + * Copyright (C) 2008 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.unit_tests; + +import android.content.ContentResolver; +import android.net.http.AndroidHttpClient; +import android.provider.Checkin; +import android.provider.Settings; +import android.test.AndroidTestCase; +import android.test.suitebuilder.annotation.LargeTest; +import android.test.suitebuilder.annotation.MediumTest; + +import com.google.android.collect.Lists; +import com.google.android.net.GoogleHttpClient; + +import org.apache.http.HttpException; +import org.apache.http.HttpRequest; +import org.apache.http.HttpResponse; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.entity.StringEntity; +import org.apache.http.protocol.HttpContext; +import org.apache.http.protocol.HttpRequestHandler; +import org.apache.http.util.EntityUtils; + +import java.io.IOException; + +/** Unit test for {@link GoogleHttpClient}. */ +public class GoogleHttpClientTest extends AndroidTestCase { + private TestHttpServer mServer; + private String mServerUrl; + + protected void setUp() throws Exception { + // Run a test server that echoes the URI back to the caller. + mServer = new TestHttpServer(); + mServer.registerHandler("*", new HttpRequestHandler() { + public void handle( + HttpRequest request, + HttpResponse response, + HttpContext context) throws HttpException, IOException { + String uri = request.getRequestLine().getUri(); + response.setEntity(new StringEntity(uri)); + } + }); + + mServer.start(); + mServerUrl = "http://localhost:" + mServer.getPort() + "/"; + } + + protected void tearDown() throws Exception { + if (mServer != null) mServer.shutdown(); + } + + @LargeTest + public void testThreadCheck() throws Exception { + ContentResolver resolver = getContext().getContentResolver(); + GoogleHttpClient client = new GoogleHttpClient(resolver, "Test", + false /* no gzip */); + + try { + // Note: we must test against a real server, because the connection + // gets established before the interceptor can crash the request. + HttpGet method = new HttpGet(mServerUrl); + + // This is actually an AndroidHttpClient feature... + // TODO: somehow test that Activity threads have the flag set? + AndroidHttpClient.setThreadBlocked(true); + + try { + client.execute(method); + fail("\"thread forbids HTTP requests\" exception expected"); + } catch (RuntimeException e) { + if (!e.toString().contains("forbids HTTP requests")) throw e; + } finally { + AndroidHttpClient.setThreadBlocked(false); + } + + HttpResponse response = client.execute(method); + assertEquals("/", EntityUtils.toString(response.getEntity())); + } finally { + client.close(); + } + } + + @MediumTest + public void testUrlRewriteRules() throws Exception { + // Don't do anything exotic; UrlRulesTest checks the actual rewriter. + // Just make sure that URLs are, in fact, rewritten. + + // TODO: Use a MockContentProvider/MockContentResolver instead. + ContentResolver resolver = getContext().getContentResolver(); + GoogleHttpClient client = new GoogleHttpClient(resolver, "Test", + false /* not gzip capable */); + Settings.Gservices.putString(resolver, + "url:test", "http://foo.bar/ rewrite " + mServerUrl + "new/"); + + // Update the digest, so the UrlRules cache is reloaded. + Settings.Gservices.putString(resolver, "digest", mServerUrl); + + try { + HttpGet method = new HttpGet("http://foo.bar/path"); + HttpResponse response = client.execute(method); + String body = EntityUtils.toString(response.getEntity()); + assertEquals("/new/path", body); + } finally { + client.close(); + } + } +} diff --git a/tests/AndroidTests/src/com/android/unit_tests/GoogleLoginServiceTest.java b/tests/AndroidTests/src/com/android/unit_tests/GoogleLoginServiceTest.java new file mode 100644 index 0000000..59f14bf --- /dev/null +++ b/tests/AndroidTests/src/com/android/unit_tests/GoogleLoginServiceTest.java @@ -0,0 +1,145 @@ +// Copyright 2008 The Android Open Source Project +// All rights reserved. + +package com.android.unit_tests; + +import java.util.Arrays; +import java.util.concurrent.locks.ReentrantLock; +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.Condition; + +import android.content.ComponentName; +import android.content.Context; +import android.content.Intent; +import android.content.ServiceConnection; +import android.os.IBinder; +import android.test.AndroidTestCase; +import android.test.suitebuilder.annotation.Suppress; +import android.util.Log; + +import com.google.android.googleapps.GoogleLoginCredentialsResult; +import com.google.android.googleapps.IGoogleLoginService; +import com.google.android.googlelogin.GoogleLoginServiceConstants; + +import junit.framework.Assert; + +// Suppress until bug http://b/issue?id=1416570 is fixed +@Suppress +/** Unit test for the Google login service. */ +public class GoogleLoginServiceTest extends AndroidTestCase { + private static final String TAG = "GoogleLoginServiceTest"; + + private IGoogleLoginService mGls = null; + private Lock mGlsLock = new ReentrantLock(); + private Condition mGlsCv = mGlsLock.newCondition(); + + private ServiceConnection mConnection = new ServiceConnection() { + public void onServiceConnected(ComponentName className, IBinder service) { + mGlsLock.lock(); + try { + mGls = IGoogleLoginService.Stub.asInterface(service); + mGlsCv.signalAll(); + } finally { + mGlsLock.unlock(); + } + Log.v(TAG, "service is connected"); + } + public void onServiceDisconnected(ComponentName className) { + mGlsLock.lock(); + try { + mGls = null; + mGlsCv.signalAll(); + } finally { + mGlsLock.unlock(); + } + Log.v(TAG, "service is disconnected"); + } + }; + + @Override + protected void setUp() throws Exception { + super.setUp(); + getContext().bindService((new Intent()) + .setClassName("com.google.android.googleapps", + "com.google.android.googleapps.GoogleLoginService"), + mConnection, Context.BIND_AUTO_CREATE); + + // wait for the service to cnnnect + mGlsLock.lock(); + try { + while (mGls == null) { + try { + mGlsCv.await(); + } catch (InterruptedException ignore) { + } + } + } finally { + mGlsLock.unlock(); + } + } + + @Override + protected void tearDown() throws Exception { + getContext().unbindService(mConnection); + super.tearDown(); + } + + public void testSingleAccountScheme() throws Exception { + Assert.assertNotNull(mGls); + mGls.deleteAllAccounts(); + + Assert.assertNull(mGls.getAccount(false)); + Assert.assertNull(mGls.getAccount(true)); + + mGls.saveUsernameAndPassword("vespa@gmail.com", "meow", + GoogleLoginServiceConstants.FLAG_GOOGLE_ACCOUNT); + Assert.assertEquals("vespa@gmail.com", mGls.getAccount(false)); + Assert.assertEquals("vespa@gmail.com", mGls.getAccount(true)); + + mGls.saveUsernameAndPassword("mackerel@hosted.com", "purr", + GoogleLoginServiceConstants.FLAG_HOSTED_ACCOUNT); + Assert.assertEquals("mackerel@hosted.com", mGls.getAccount(false)); + Assert.assertEquals("vespa@gmail.com", mGls.getAccount(true)); + } + + public void listsEqual(String[] a, String[] b) { + Assert.assertEquals(a.length, b.length); + Arrays.sort(a); + Arrays.sort(b); + Assert.assertTrue(Arrays.equals(a, b)); + } + + public void testAuthTokens() throws Exception { + Assert.assertNotNull(mGls); + mGls.deleteAllAccounts(); + + Assert.assertNull(mGls.peekCredentials("vespa@example.com", "mail")); + + mGls.saveUsernameAndPassword("vespa@example.com", "meow", + GoogleLoginServiceConstants.FLAG_HOSTED_ACCOUNT); + Assert.assertNull(mGls.peekCredentials("vespa@example.com", "mail")); + Assert.assertNull(mGls.peekCredentials(null, "mail")); + + mGls.saveAuthToken("vespa@example.com", "mail", "1234"); + Assert.assertEquals("1234", mGls.peekCredentials("vespa@example.com", "mail")); + Assert.assertEquals("1234", mGls.peekCredentials(null, "mail")); + + mGls.saveUsernameAndPassword("mackerel@example.com", "purr", + GoogleLoginServiceConstants.FLAG_GOOGLE_ACCOUNT); + mGls.saveAuthToken("mackerel@example.com", "mail", "5678"); + Assert.assertEquals("1234", mGls.peekCredentials(null, "mail")); + + mGls.saveAuthToken("mackerel@example.com", "mail", "8765"); + Assert.assertEquals("8765", mGls.peekCredentials("mackerel@example.com", "mail")); + + GoogleLoginCredentialsResult r = mGls.blockingGetCredentials( + "vespa@example.com", "mail", false); + Assert.assertEquals("vespa@example.com", r.getAccount()); + Assert.assertEquals("1234", r.getCredentialsString()); + Assert.assertNull(r.getCredentialsIntent()); + + mGls.saveAuthToken("vespa@example.com", "cl", "abcd"); + Assert.assertEquals("1234", mGls.peekCredentials("vespa@example.com", "mail")); + Assert.assertEquals("abcd", mGls.peekCredentials("vespa@example.com", "cl")); + } +} diff --git a/tests/AndroidTests/src/com/android/unit_tests/GraphicsPerformanceTests.java b/tests/AndroidTests/src/com/android/unit_tests/GraphicsPerformanceTests.java new file mode 100644 index 0000000..a6c5869 --- /dev/null +++ b/tests/AndroidTests/src/com/android/unit_tests/GraphicsPerformanceTests.java @@ -0,0 +1,448 @@ +/* + * 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.unit_tests; + +import junit.framework.Assert; +import android.content.Context; +import android.content.res.Resources; +import android.graphics.Bitmap; +import android.graphics.BitmapFactory; +import android.graphics.Canvas; +import android.graphics.Paint; +import android.test.AndroidTestCase; +import android.test.PerformanceTestCase; +import android.test.suitebuilder.annotation.Suppress; +import android.util.Log; + +/** + * Graphics Performance Tests + * + */ +//We don't want to run these perf tests in the continuous build. +@Suppress +public class GraphicsPerformanceTests { + private static final String TAG = "GfxPerf"; + public static String[] children() { + return new String[] { + // test decoding bitmaps of various sizes + DecodeBitmapTest.class.getName(), + + // odd-sized bitmap drawing tests + DrawBitmap7x7.class.getName(), + DrawBitmap15x15.class.getName(), + DrawBitmap31x31.class.getName(), + DrawBitmap63x63.class.getName(), + DrawBitmap127x127.class.getName(), + DrawBitmap319x239.class.getName(), + DrawBitmap319x479.class.getName(), + + // even-sized bitmap drawing tests + DrawBitmap8x8.class.getName(), + DrawBitmap16x16.class.getName(), + DrawBitmap32x32.class.getName(), + DrawBitmap64x64.class.getName(), + DrawBitmap128x128.class.getName(), + DrawBitmap320x240.class.getName(), + DrawBitmap320x480.class.getName()}; + } + + /** + * Base class for all graphics tests + * + */ + public static abstract class GraphicsTestBase extends AndroidTestCase + implements PerformanceTestCase { + /** Target "screen" (bitmap) width and height */ + private static final int DEFAULT_ITERATIONS = 1; + private static final int SCREEN_WIDTH = 320; + private static final int SCREEN_HEIGHT = 480; + + /** Number of iterations to pass back to harness. Subclass should override */ + protected int mIterations = 1; + + /** Bitmap we allocate and draw to */ + protected Bitmap mDestBitmap; + + /** Canvas of drawing routines */ + protected Canvas mCanvas; + + /** Style and color information (uses defaults) */ + protected Paint mPaint; + + @Override + public void setUp() throws Exception { + super.setUp(); + // Create drawable bitmap for rendering into + mDestBitmap = Bitmap.createBitmap(SCREEN_WIDTH, SCREEN_HEIGHT, + Bitmap.Config.RGB_565); + // Set of drawing routines + mCanvas = new Canvas(mDestBitmap); + // Styles + mPaint = new Paint(); + // Ask subclass for number of iterations + mIterations = getIterations(); + } + + // A reasonable default + public int getIterations() { + return DEFAULT_ITERATIONS; + } + + public boolean isPerformanceOnly() { + return true; + } + + public int startPerformance(Intermediates intermediates) { + intermediates.setInternalIterations(mIterations * 10); + return 0; + } + } + + /** + * Tests time to decode a number of sizes of images. + */ + public static class DecodeBitmapTest extends GraphicsTestBase { + /** Number of times to run this test */ + private static final int DECODE_ITERATIONS = 10; + + /** Used to access package bitmap images */ + private Resources mResources; + + @Override + public void setUp() throws Exception { + super.setUp(); + + // For bitmap resources + Context context = getContext(); + Assert.assertNotNull(context); + mResources = context.getResources(); + Assert.assertNotNull(mResources); + } + + @Override + public int getIterations() { + return DECODE_ITERATIONS; + } + + public void testDecodeBitmap() { + for (int i = 0; i < DECODE_ITERATIONS; i++) { + BitmapFactory.decodeResource(mResources, R.drawable.test16x12); + BitmapFactory.decodeResource(mResources, R.drawable.test32x24); + BitmapFactory.decodeResource(mResources, R.drawable.test64x48); + BitmapFactory.decodeResource(mResources, R.drawable.test128x96); + BitmapFactory.decodeResource(mResources, R.drawable.test256x192); + BitmapFactory.decodeResource(mResources, R.drawable.test320x240); + } + } + } + + /** + * Base class for bitmap drawing tests + * + */ + public static abstract class DrawBitmapTest extends GraphicsTestBase { + /** Number of times to run each draw test */ + private static final int ITERATIONS = 1000; + + /** Bitmap to draw. Allocated by subclass's createBitmap() function. */ + private Bitmap mBitmap; + + @Override + public void setUp() throws Exception { + super.setUp(); + + // Invoke subclass's method to create the bitmap + mBitmap = createBitmap(); + } + + public int getIterations() { + return ITERATIONS; + } + + // Generic abstract function to create bitmap for any given subclass + public abstract Bitmap createBitmap(); + + // Provide convenience test code for all subsequent classes. + // Note: Though it would be convenient to declare all of the test*() methods here + // and just inherit them, our test harness doesn't support it. So we replicate + // a bit of code in each derived test case. + public void drawBitmapEven() { + for (int i = 0; i < ITERATIONS; i++) { + mCanvas.drawBitmap(mBitmap, 0.0f, 0.0f, mPaint); + } + } + + public void drawBitmapOdd() { + for (int i = 0; i < ITERATIONS; i++) { + mCanvas.drawBitmap(mBitmap, 1.0f, 0.0f, mPaint); + } + } + } + + + /** + * Test drawing of 7x7 image + */ + public static class DrawBitmap7x7 extends DrawBitmapTest { + + public Bitmap createBitmap() { + return Bitmap.createBitmap(7, 7, Bitmap.Config.RGB_565); + } + + public void testDrawBitmapEven() { + drawBitmapEven(); + } + + public void testDrawBitmapOdd() { + drawBitmapOdd(); + } + } + + /** + * Test drawing of 15x15 image + */ + public static class DrawBitmap15x15 extends DrawBitmapTest { + + public Bitmap createBitmap() { + return Bitmap.createBitmap(15, 15, Bitmap.Config.RGB_565); + } + + public void testDrawBitmapEven() { + drawBitmapEven(); + } + + public void testDrawBitmapOdd() { + drawBitmapOdd(); + } + } + + /** + * Test drawing of 31x31 image + */ + public static class DrawBitmap31x31 extends DrawBitmapTest { + + public Bitmap createBitmap() { + return Bitmap.createBitmap(31, 31, Bitmap.Config.RGB_565); + } + + public void testDrawBitmapEven() { + drawBitmapEven(); + } + + public void testDrawBitmapOdd() { + drawBitmapOdd(); + } + } + + /** + * Test drawing of 63x63 image + */ + public static class DrawBitmap63x63 extends DrawBitmapTest { + + public Bitmap createBitmap() { + return Bitmap.createBitmap(63, 63, Bitmap.Config.RGB_565); + } + + public void testDrawBitmapEven() { + drawBitmapEven(); + } + + public void testDrawBitmapOdd() { + drawBitmapOdd(); + } + } + + /** + * Test drawing of 127x127 image + */ + public static class DrawBitmap127x127 extends DrawBitmapTest { + + public Bitmap createBitmap() { + return Bitmap.createBitmap(127, 127, Bitmap.Config.RGB_565); + } + + public void testDrawBitmapEven() { + drawBitmapEven(); + } + + public void testDrawBitmapOdd() { + drawBitmapOdd(); + } + } + + /** + * Test drawing of 319x239 image + */ + public static class DrawBitmap319x239 extends DrawBitmapTest { + + public Bitmap createBitmap() { + return Bitmap.createBitmap(319, 239, Bitmap.Config.RGB_565); + } + + public void testDrawBitmapEven() { + drawBitmapEven(); + } + + public void testDrawBitmapOdd() { + drawBitmapOdd(); + } + } + + /** + * Test drawing of 319x479 image + */ + public static class DrawBitmap319x479 extends DrawBitmapTest { + + public Bitmap createBitmap() { + return Bitmap.createBitmap(319, 479, Bitmap.Config.RGB_565); + } + + public void testDrawBitmapEven() { + drawBitmapEven(); + } + + public void testDrawBitmapOdd() { + drawBitmapOdd(); + } + } + + /** + * Test drawing of 8x8 image + */ + public static class DrawBitmap8x8 extends DrawBitmapTest { + + public Bitmap createBitmap() { + return Bitmap.createBitmap(8, 8, Bitmap.Config.RGB_565); + } + + public void testDrawBitmapEven() { + drawBitmapEven(); + } + + public void testDrawBitmapOdd() { + drawBitmapOdd(); + } + } + + /** + * Test drawing of 16x16 image + */ + public static class DrawBitmap16x16 extends DrawBitmapTest { + + public Bitmap createBitmap() { + return Bitmap.createBitmap(16, 16, Bitmap.Config.RGB_565); + } + + public void testDrawBitmapEven() { + drawBitmapEven(); + } + + public void testDrawBitmapOdd() { + drawBitmapOdd(); + } + } + + /** + * Test drawing of 32x32 image + */ + public static class DrawBitmap32x32 extends DrawBitmapTest { + + public Bitmap createBitmap() { + return Bitmap.createBitmap(32, 32, Bitmap.Config.RGB_565); + } + + public void testDrawBitmapEven() { + drawBitmapEven(); + } + + public void testDrawBitmapOdd() { + drawBitmapOdd(); + } + } + + /** + * Test drawing of 64x64 image + */ + public static class DrawBitmap64x64 extends DrawBitmapTest { + + public Bitmap createBitmap() { + return Bitmap.createBitmap(64, 64, Bitmap.Config.RGB_565); + } + + public void testDrawBitmapEven() { + drawBitmapEven(); + } + + public void testDrawBitmapOdd() { + drawBitmapOdd(); + } + } + + /** + * Test drawing of 128x128 image + */ + public static class DrawBitmap128x128 extends DrawBitmapTest { + + public Bitmap createBitmap() { + return Bitmap.createBitmap(128, 128, Bitmap.Config.RGB_565); + } + + public void testDrawBitmapEven() { + drawBitmapEven(); + } + + public void testDrawBitmapOdd() { + drawBitmapOdd(); + } + } + + /** + * Test drawing of 320x240 image + */ + public static class DrawBitmap320x240 extends DrawBitmapTest { + + public Bitmap createBitmap() { + return Bitmap.createBitmap(320, 240, Bitmap.Config.RGB_565); + } + + public void testDrawBitmapEven() { + drawBitmapEven(); + } + + public void testDrawBitmapOdd() { + drawBitmapOdd(); + } + } + + /** + * Test drawing of 320x480 image + */ + public static class DrawBitmap320x480 extends DrawBitmapTest { + + public Bitmap createBitmap() { + return Bitmap.createBitmap(320, 480, Bitmap.Config.RGB_565); + } + + public void testDrawBitmapEven() { + drawBitmapEven(); + } + + public void testDrawBitmapOdd() { + drawBitmapOdd(); + } + } +} diff --git a/tests/AndroidTests/src/com/android/unit_tests/HashMapTest.java b/tests/AndroidTests/src/com/android/unit_tests/HashMapTest.java new file mode 100644 index 0000000..b4d15c9 --- /dev/null +++ b/tests/AndroidTests/src/com/android/unit_tests/HashMapTest.java @@ -0,0 +1,185 @@ +/* + * 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.unit_tests; + +import java.util.Collection; +import java.util.HashMap; +import java.util.Set; + +import android.test.PerformanceTestBase; +import android.test.PerformanceTestCase; + +public class HashMapTest extends PerformanceTestBase { + public static final int ITERATIONS = 1000; + public HashMap mMap; + public String[] mKeys; + + @Override + @SuppressWarnings("unchecked") + protected void setUp() throws Exception { + super.setUp(); + mMap = new HashMap(); + mKeys = new String[ITERATIONS]; + + for (int i = ITERATIONS - 1; i >= 0; i--) { + mKeys[i] = Integer.toString(i, 16); + mMap.put(mKeys[i], i); + } + } + + @Override + public int startPerformance(PerformanceTestCase.Intermediates intermediates) { + intermediates.setInternalIterations(ITERATIONS); + return 0; + } + + public void testHashMapGet() { + int num; + for (int i = ITERATIONS - 1; i >= 0; i--) { + num = (Integer) mMap.get(mKeys[i]); + num = (Integer) mMap.get(mKeys[i]); + num = (Integer) mMap.get(mKeys[i]); + num = (Integer) mMap.get(mKeys[i]); + num = (Integer) mMap.get(mKeys[i]); + num = (Integer) mMap.get(mKeys[i]); + num = (Integer) mMap.get(mKeys[i]); + num = (Integer) mMap.get(mKeys[i]); + num = (Integer) mMap.get(mKeys[i]); + num = (Integer) mMap.get(mKeys[i]); + } + } + + public void testHashMapKeySet() { + Set keyset; + for (int i = ITERATIONS - 1; i >= 0; i--) { + keyset = mMap.keySet(); + keyset = mMap.keySet(); + keyset = mMap.keySet(); + keyset = mMap.keySet(); + keyset = mMap.keySet(); + keyset = mMap.keySet(); + keyset = mMap.keySet(); + keyset = mMap.keySet(); + keyset = mMap.keySet(); + keyset = mMap.keySet(); + } + } + + public void testHashMapEntrySet() { + Set keyset; + for (int i = ITERATIONS - 1; i >= 0; i--) { + keyset = mMap.entrySet(); + keyset = mMap.entrySet(); + keyset = mMap.entrySet(); + keyset = mMap.entrySet(); + keyset = mMap.entrySet(); + keyset = mMap.entrySet(); + keyset = mMap.entrySet(); + keyset = mMap.entrySet(); + keyset = mMap.entrySet(); + keyset = mMap.entrySet(); + + + } + } + + public void testHashMapValues() { + Collection c; + for (int i = ITERATIONS - 1; i >= 0; i--) { + c = mMap.values(); + c = mMap.values(); + c = mMap.values(); + c = mMap.values(); + c = mMap.values(); + c = mMap.values(); + c = mMap.values(); + c = mMap.values(); + c = mMap.values(); + c = mMap.values(); + + + } + } + + public void testHashMapSize() { + int len; + for (int i = ITERATIONS - 1; i >= 0; i--) { + len = mMap.size(); + len = mMap.size(); + len = mMap.size(); + len = mMap.size(); + len = mMap.size(); + len = mMap.size(); + len = mMap.size(); + len = mMap.size(); + len = mMap.size(); + len = mMap.size(); + + + } + } + + public void testHashMapContainsValue() { + boolean flag; + for (int i = ITERATIONS - 1; i >= 0; i--) { + flag = mMap.containsValue(i); + flag = mMap.containsValue(i); + flag = mMap.containsValue(i); + flag = mMap.containsValue(i); + flag = mMap.containsValue(i); + flag = mMap.containsValue(i); + flag = mMap.containsValue(i); + flag = mMap.containsValue(i); + flag = mMap.containsValue(i); + flag = mMap.containsValue(i); + + + } + } + + public void testHashMapRemove() { + for (int i = ITERATIONS - 1; i >= 0; i--) { + mMap.remove(mKeys[i]); + mMap.remove(mKeys[i]); + mMap.remove(mKeys[i]); + mMap.remove(mKeys[i]); + mMap.remove(mKeys[i]); + mMap.remove(mKeys[i]); + mMap.remove(mKeys[i]); + mMap.remove(mKeys[i]); + mMap.remove(mKeys[i]); + mMap.remove(mKeys[i]); + } + } + + + public void testHashMapClone() { + HashMap cMap; + for (int i = ITERATIONS - 1; i >= 0; i--) { + cMap = (HashMap) mMap.clone(); + cMap = (HashMap) mMap.clone(); + cMap = (HashMap) mMap.clone(); + cMap = (HashMap) mMap.clone(); + cMap = (HashMap) mMap.clone(); + cMap = (HashMap) mMap.clone(); + cMap = (HashMap) mMap.clone(); + cMap = (HashMap) mMap.clone(); + cMap = (HashMap) mMap.clone(); + cMap = (HashMap) mMap.clone(); + } + } +} diff --git a/tests/AndroidTests/src/com/android/unit_tests/HashSetTest.java b/tests/AndroidTests/src/com/android/unit_tests/HashSetTest.java new file mode 100644 index 0000000..80d3d8d --- /dev/null +++ b/tests/AndroidTests/src/com/android/unit_tests/HashSetTest.java @@ -0,0 +1,207 @@ +/* + * 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.unit_tests; + +import android.test.PerformanceTestBase; +import android.test.PerformanceTestCase; + +import java.util.HashSet; +import java.util.Iterator; + +/** + * Implements basic performance test functionality for HashSets + */ + +public class HashSetTest extends PerformanceTestBase { + public static final int ITERATIONS = 1000; + public static HashSet<Integer> sSet; + + @Override + protected void setUp() throws Exception { + super.setUp(); + sSet = new HashSet<Integer>(); + for (int i = ITERATIONS - 1; i >= 0; i--) { + sSet.add(i); + } + } + + @Override + public int startPerformance(PerformanceTestCase.Intermediates intermediates) { + intermediates.setInternalIterations(ITERATIONS); + return 0; + } + + /** + * + * Tests performance for the HashSet method Add(Object arg 0) + * + */ + + @SuppressWarnings("unchecked") + public void testHashSetAdd() { + HashSet set = new HashSet(); + for (int i = ITERATIONS - 1; i >= 0; i--) { + set.add(i); + set.add(i); + set.add(i); + set.add(i); + set.add(i); + set.add(i); + set.add(i); + set.add(i); + set.add(i); + set.add(i); + } + + } + + /** + * + * Tests performance of HashSet method contains(Object arg 0) + * + */ + + public void testHashSetContains() { + Integer index = new Integer(500); + boolean flag; + HashSet set = sSet; + for (int i = ITERATIONS - 1; i >= 0; i--) { + flag = set.contains(index); + flag = set.contains(index); + flag = set.contains(index); + flag = set.contains(index); + flag = set.contains(index); + flag = set.contains(index); + flag = set.contains(index); + flag = set.contains(index); + flag = set.contains(index); + } + } + + /** + * + * Tests performance of HashSet method size() + * + */ + + public void testHashSetSize() { + int num; + HashSet set = sSet; + for (int i = ITERATIONS - 1; i >= 0; i--) { + num = set.size(); + num = set.size(); + num = set.size(); + num = set.size(); + num = set.size(); + num = set.size(); + num = set.size(); + num = set.size(); + num = set.size(); + } + } + + /** + * + * Tests performance of the HashSet method -iterator() + * + */ + + public void testHashSetIterator() { + Iterator iterator; + HashSet set = sSet; + for (int i = ITERATIONS - 1; i >= 0; i--) { + iterator = set.iterator(); + iterator = set.iterator(); + iterator = set.iterator(); + iterator = set.iterator(); + iterator = set.iterator(); + iterator = set.iterator(); + iterator = set.iterator(); + iterator = set.iterator(); + iterator = set.iterator(); + } + } + + /** + * + * Tests performance for the HashSet method Remove(Object arg 0) + * + */ + + @SuppressWarnings("unchecked") + public void testHashSetRemove() { + HashSet set = new HashSet(sSet); + for (int i = ITERATIONS - 1; i >= 0; i--) { + set.remove(i); + set.remove(i); + set.remove(i); + set.remove(i); + set.remove(i); + set.remove(i); + set.remove(i); + set.remove(i); + set.remove(i); + set.remove(i); + } + } + + /** + * + * Tests performance for the HashSet method isEmpty(Object arg 0) + * + */ + + public void testHashSetIsEmpty() { + HashSet set = sSet; + boolean flag; + for (int i = ITERATIONS - 1; i >= 0; i--) { + flag = set.isEmpty(); + flag = set.isEmpty(); + flag = set.isEmpty(); + flag = set.isEmpty(); + flag = set.isEmpty(); + flag = set.isEmpty(); + flag = set.isEmpty(); + flag = set.isEmpty(); + flag = set.isEmpty(); + flag = set.isEmpty(); + } + } + + /** + * + * Tests performance for the HashSet method clone() + * + */ + + public void testHashSetClone() { + HashSet hSet = sSet; + Object set; + for (int i = ITERATIONS - 1; i > 0; i--) { + set = hSet.clone(); + set = hSet.clone(); + set = hSet.clone(); + set = hSet.clone(); + set = hSet.clone(); + set = hSet.clone(); + set = hSet.clone(); + set = hSet.clone(); + set = hSet.clone(); + set = hSet.clone(); + } + } +} diff --git a/tests/AndroidTests/src/com/android/unit_tests/HashtableTest.java b/tests/AndroidTests/src/com/android/unit_tests/HashtableTest.java new file mode 100644 index 0000000..42bec11 --- /dev/null +++ b/tests/AndroidTests/src/com/android/unit_tests/HashtableTest.java @@ -0,0 +1,357 @@ +/* + * 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.unit_tests; + +import android.test.PerformanceTestBase; +import android.test.PerformanceTestCase; + +import java.util.Hashtable; +import java.util.Set; +import java.util.Enumeration; + +/** + * Implements basic performance test functionality for java.util.Hashtable + */ + +public class HashtableTest extends PerformanceTestBase { + public static final int ITERATIONS = 1000; + public Hashtable<String, Integer> sTable; + public String[] sKeys; + + @Override + @SuppressWarnings("unchecked") + protected void setUp() throws Exception { + super.setUp(); + sTable = new Hashtable(); + sKeys = new String[ITERATIONS]; + for (int i = ITERATIONS - 1; i >= 0; i--) { + sKeys[i] = Integer.toString(i, 16); + sTable.put(sKeys[i], i); + } + } + + @Override + public int startPerformance(PerformanceTestCase.Intermediates intermediates) { + intermediates.setInternalIterations(ITERATIONS); + return 0; + } + + @SuppressWarnings("unchecked") + public void testHashtablePut() { + Hashtable hTable = new Hashtable(); + for (int i = ITERATIONS - 1; i >= 0; i--) { + hTable.put(i, i); + hTable.put(i, i); + hTable.put(i, i); + hTable.put(i, i); + hTable.put(i, i); + hTable.put(i, i); + hTable.put(i, i); + hTable.put(i, i); + hTable.put(i, i); + hTable.put(i, i); + } + } + + public void testHashtableGet() { + int value; + String[] keys = sKeys; + Hashtable<String, Integer> hTable = sTable; + for (int i = ITERATIONS - 1; i >= 0; i--) { + value = hTable.get(keys[i]); + value = hTable.get(keys[i]); + value = hTable.get(keys[i]); + value = hTable.get(keys[i]); + value = hTable.get(keys[i]); + value = hTable.get(keys[i]); + value = hTable.get(keys[i]); + value = hTable.get(keys[i]); + value = hTable.get(keys[i]); + value = hTable.get(keys[i]); + } + } + + public void testHashtablekeyset() { + Set keyset; + Hashtable<String, Integer> hTable = sTable; + for (int i = ITERATIONS - 1; i >= 0; i--) { + keyset = hTable.keySet(); + keyset = hTable.keySet(); + keyset = hTable.keySet(); + keyset = hTable.keySet(); + keyset = hTable.keySet(); + keyset = hTable.keySet(); + keyset = hTable.keySet(); + keyset = hTable.keySet(); + keyset = hTable.keySet(); + keyset = hTable.keySet(); + } + } + + /** + * + */ + + public void testHashtableEntrySet() { + Set keyset; + Hashtable<String, Integer> hTable = sTable; + for (int i = ITERATIONS - 1; i >= 0; i--) { + keyset = hTable.entrySet(); + keyset = hTable.entrySet(); + keyset = hTable.entrySet(); + keyset = hTable.entrySet(); + keyset = hTable.entrySet(); + keyset = hTable.entrySet(); + keyset = hTable.entrySet(); + keyset = hTable.entrySet(); + keyset = hTable.entrySet(); + keyset = hTable.entrySet(); + } + } + + public void testHashtableSize() { + int len; + Hashtable<String, Integer> hTable = sTable; + for (int i = ITERATIONS - 1; i >= 0; i--) { + len = hTable.size(); + len = hTable.size(); + len = hTable.size(); + len = hTable.size(); + len = hTable.size(); + len = hTable.size(); + len = hTable.size(); + len = hTable.size(); + len = hTable.size(); + len = hTable.size(); + } + } + + public void testHashtableContainsValue() { + boolean flag; + Hashtable<String, Integer> hTable = sTable; + for (int i = ITERATIONS - 1; i >= 0; i--) { + flag = hTable.containsValue(i); + flag = hTable.containsValue(i); + flag = hTable.containsValue(i); + flag = hTable.containsValue(i); + flag = hTable.containsValue(i); + flag = hTable.containsValue(i); + flag = hTable.containsValue(i); + flag = hTable.containsValue(i); + flag = hTable.containsValue(i); + flag = hTable.containsValue(i); + } + } + + @SuppressWarnings("unchecked") + public void testHashtableRemove() { + Hashtable<String, Integer> hTable = new Hashtable(sTable); + String[] keys = sKeys; + for (int i = ITERATIONS - 1; i >= 0; i--) { + hTable.remove(keys[i]); + hTable.remove(keys[i]); + hTable.remove(keys[i]); + hTable.remove(keys[i]); + hTable.remove(keys[i]); + hTable.remove(keys[i]); + hTable.remove(keys[i]); + hTable.remove(keys[i]); + hTable.remove(keys[i]); + hTable.remove(keys[i]); + } + } + + public void testHashtableContains() { + Hashtable<String, Integer> hTable = sTable; + boolean flag; + + for (int i = ITERATIONS - 1; i >= 0; i--) { + flag = hTable.contains(i); + flag = hTable.contains(i); + flag = hTable.contains(i); + flag = hTable.contains(i); + flag = hTable.contains(i); + flag = hTable.contains(i); + flag = hTable.contains(i); + flag = hTable.contains(i); + flag = hTable.contains(i); + flag = hTable.contains(i); + } + } + + public void testHashtableContainsKey() { + Hashtable<String, Integer> hTable = sTable; + boolean flag; + + for (int i = ITERATIONS - 1; i >= 0; i--) { + flag = hTable.containsKey(i); + flag = hTable.containsKey(i); + flag = hTable.containsKey(i); + flag = hTable.containsKey(i); + flag = hTable.containsKey(i); + flag = hTable.containsKey(i); + flag = hTable.containsKey(i); + flag = hTable.containsKey(i); + flag = hTable.containsKey(i); + flag = hTable.containsKey(i); + } + } + + public void testHashtableIsEmpty() { + Hashtable<String, Integer> hTable = sTable; + boolean flag; + for (int i = ITERATIONS - 1; i >= 0; i--) { + flag = hTable.isEmpty(); + flag = hTable.isEmpty(); + flag = hTable.isEmpty(); + flag = hTable.isEmpty(); + flag = hTable.isEmpty(); + flag = hTable.isEmpty(); + flag = hTable.isEmpty(); + flag = hTable.isEmpty(); + flag = hTable.isEmpty(); + flag = hTable.isEmpty(); + } + } + + public void testHashtableKeys() { + Hashtable<String, Integer> hTable = sTable; + Enumeration<String> keys; + for (int i = ITERATIONS - 1; i >= 0; i--) { + keys = hTable.keys(); + keys = hTable.keys(); + keys = hTable.keys(); + keys = hTable.keys(); + keys = hTable.keys(); + keys = hTable.keys(); + keys = hTable.keys(); + keys = hTable.keys(); + keys = hTable.keys(); + keys = hTable.keys(); + } + } + + public void testHashtableElements() { + Hashtable<String, Integer> hTable = sTable; + Enumeration<Integer> elements; + for (int i = ITERATIONS - 1; i >= 0; i--) { + elements = hTable.elements(); + elements = hTable.elements(); + elements = hTable.elements(); + elements = hTable.elements(); + elements = hTable.elements(); + elements = hTable.elements(); + elements = hTable.elements(); + elements = hTable.elements(); + elements = hTable.elements(); + elements = hTable.elements(); + } + } + + public void testHashtableHashCode() { + int index; + Hashtable<String, Integer> hTable = sTable; + for (int i = ITERATIONS - 1; i >= 0; i--) { + index = hTable.hashCode(); + index = hTable.hashCode(); + index = hTable.hashCode(); + index = hTable.hashCode(); + index = hTable.hashCode(); + index = hTable.hashCode(); + index = hTable.hashCode(); + index = hTable.hashCode(); + index = hTable.hashCode(); + index = hTable.hashCode(); + } + } + + public void testHashtableEquals() { + boolean flag; + Hashtable<String, Integer> hTable = sTable; + for (int i = ITERATIONS - 1; i >= 0; i--) { + flag = hTable.equals(hTable); + flag = hTable.equals(hTable); + flag = hTable.equals(hTable); + flag = hTable.equals(hTable); + flag = hTable.equals(hTable); + flag = hTable.equals(hTable); + flag = hTable.equals(hTable); + flag = hTable.equals(hTable); + flag = hTable.equals(hTable); + flag = hTable.equals(hTable); + } + } + + public void testHashtableToString() { + String str; + Hashtable<String, Integer> hTable = sTable; + for (int i = ITERATIONS - 1; i >= 0; i--) { + str = hTable.toString(); + str = hTable.toString(); + str = hTable.toString(); + str = hTable.toString(); + str = hTable.toString(); + str = hTable.toString(); + str = hTable.toString(); + str = hTable.toString(); + str = hTable.toString(); + str = hTable.toString(); + } + } + + @SuppressWarnings("unchecked") + public void testHashtablePutAll() { + Hashtable<String, Integer> hTable = new Hashtable(); + Hashtable<String, Integer> hTable1 = sTable; + for (int i = ITERATIONS - 1; i >= 0; i--) { + hTable.putAll(hTable1); + hTable.putAll(hTable1); + hTable.putAll(hTable1); + hTable.putAll(hTable1); + hTable.putAll(hTable1); + hTable.putAll(hTable1); + hTable.putAll(hTable1); + hTable.putAll(hTable1); + hTable.putAll(hTable1); + hTable.putAll(hTable1); + } + } + + /** + * + * clone() returns a Hashtable .. It should return Object as per the + * specification. + * + */ + + public void testHashtableClone() { + Hashtable hashTable; + Hashtable<String, Integer> hTable = sTable; + for (int i = ITERATIONS - 1; i >= 0; i--) { + hashTable = (Hashtable) hTable.clone(); + hashTable = (Hashtable) hTable.clone(); + hashTable = (Hashtable) hTable.clone(); + hashTable = (Hashtable) hTable.clone(); + hashTable = (Hashtable) hTable.clone(); + hashTable = (Hashtable) hTable.clone(); + hashTable = (Hashtable) hTable.clone(); + hashTable = (Hashtable) hTable.clone(); + hashTable = (Hashtable) hTable.clone(); + hashTable = (Hashtable) hTable.clone(); + } + } +} diff --git a/tests/AndroidTests/src/com/android/unit_tests/HeapTest.java b/tests/AndroidTests/src/com/android/unit_tests/HeapTest.java new file mode 100644 index 0000000..d21e6a3 --- /dev/null +++ b/tests/AndroidTests/src/com/android/unit_tests/HeapTest.java @@ -0,0 +1,631 @@ +/* + * 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.unit_tests; + +import android.test.suitebuilder.annotation.LargeTest; +import android.test.suitebuilder.annotation.MediumTest; +import android.test.suitebuilder.annotation.SmallTest; +import android.util.Log; +import android.test.suitebuilder.annotation.Suppress; +import dalvik.system.VMRuntime; +import junit.framework.TestCase; + +import java.lang.ref.PhantomReference; +import java.lang.ref.ReferenceQueue; +import java.lang.ref.SoftReference; +import java.lang.ref.WeakReference; +import java.util.LinkedList; +import java.util.Random; + + +public class HeapTest extends TestCase { + + private static final String TAG = "HeapTest"; + + /** + * Returns a WeakReference to an object that has no + * other references. This is done in a separate method + * to ensure that the Object's address isn't sitting in + * a stale local register. + */ + private WeakReference<Object> newRef() { + return new WeakReference<Object>(new Object()); + } + + /** + * Allocates the specified number of bytes. This is done in a separate method + * to ensure that the Object's address isn't sitting in a stale local register. + */ + private void allocateMemory(int size) { + byte[] b = new byte[size]; + } + + @MediumTest + public void testMinimumHeapSize() throws Exception { + VMRuntime r = VMRuntime.getRuntime(); + final boolean RUN_FLAKY = false; + + long origSize = r.getMinimumHeapSize(); + if (RUN_FLAKY) { + /* Check that the default value is zero. This will break if anyone + * in this process sets the minimum heap size to a positive value + * before calling this test. + */ + assertTrue(origSize == 0); + } + + long size = 4 * 1024 * 1024; + long oldSize = r.setMinimumHeapSize(size); + assertTrue(oldSize == origSize); + + long newSize = r.getMinimumHeapSize(); + /* This will fail if the maximum heap size (-Xmx) is smaller than 4MB. + */ + assertTrue(newSize == size); + + /* Make sure that getting the size doesn't change anything. + */ + newSize = r.getMinimumHeapSize(); + assertTrue(newSize == size); + + /* This test is flaky; if the heap is already large and fragmented, + * it can fail. It can also fail if another thread causes a GC + * at the wrong time. + */ + if (RUN_FLAKY) { + /* Increase the minimum size, allocate a big object, and make sure that + * a GC didn't happen. + */ + WeakReference ref = newRef(); + assertNotNull(ref.get()); + + r.setMinimumHeapSize(8 * 1024 * 1024); + allocateMemory(4 * 1024 * 1024); + + /* If a GC happened, this reference will be null. + */ + assertNotNull(ref.get()); + } + + /* Restore the original setting. + */ + r.setMinimumHeapSize(origSize); + newSize = r.getMinimumHeapSize(); + assertTrue(newSize == origSize); + + /* Clean up any large stuff we've allocated, + * and re-establish the normal utilization ratio. + */ + Runtime.getRuntime().gc(); + } + + private static void makeRefs(Object objects[], SoftReference<Object> refs[]) { + for (int i = 0; i < objects.length; i++) { + objects[i] = (Object) new byte[8 * 1024]; + refs[i] = new SoftReference<Object>(objects[i]); + } + } + + private static <T> int checkRefs(SoftReference<T> refs[], int last) { + int i; + int numCleared = 0; + for (i = 0; i < refs.length; i++) { + Object o = refs[i].get(); + if (o == null) { + numCleared++; + } + } + if (numCleared != last) { + Log.i(TAG, "****** " + numCleared + "/" + i + " cleared ******"); + } + return numCleared; + } + + private static void clearRefs(Object objects[], int skip) { + for (int i = 0; i < objects.length; i += skip) { + objects[i] = null; + } + } + + private static void clearRefs(Object objects[]) { + clearRefs(objects, 1); + } + + private static <T> void checkRefs(T objects[], SoftReference<T> refs[]) { + boolean ok = true; + + for (int i = 0; i < objects.length; i++) { + if (refs[i].get() != objects[i]) { + ok = false; + } + } + if (!ok) { + throw new RuntimeException("Test failed: soft refs not cleared"); + } + } + + @MediumTest + public void testGcSoftRefs() throws Exception { + final int NUM_REFS = 128; + + Object objects[] = new Object[NUM_REFS]; + SoftReference<Object> refs[] = new SoftReference[objects.length]; + + /* Create a bunch of objects and a parallel array + * of SoftReferences. + */ + makeRefs(objects, refs); + Runtime.getRuntime().gc(); + + /* Let go of some of the hard references to the objects so that + * the references can be cleared. + */ + clearRefs(objects, 3); + + /* Collect all softly-reachable objects. + */ + VMRuntime.getRuntime().gcSoftReferences(); + Runtime.getRuntime().runFinalization(); + + /* Make sure that the objects were collected. + */ + checkRefs(objects, refs); + + /* Remove more hard references and re-check. + */ + clearRefs(objects, 2); + VMRuntime.getRuntime().gcSoftReferences(); + Runtime.getRuntime().runFinalization(); + checkRefs(objects, refs); + + /* Remove the rest of the references and re-check. + */ + /* Remove more hard references and re-check. + */ + clearRefs(objects); + VMRuntime.getRuntime().gcSoftReferences(); + Runtime.getRuntime().runFinalization(); + checkRefs(objects, refs); + } + + public void xxtestSoftRefPartialClean() throws Exception { + final int NUM_REFS = 128; + + Object objects[] = new Object[NUM_REFS]; + SoftReference<Object> refs[] = new SoftReference[objects.length]; + + /* Create a bunch of objects and a parallel array + * of SoftReferences. + */ + makeRefs(objects, refs); + Runtime.getRuntime().gc(); + + /* Let go of the hard references to the objects so that + * the references can be cleared. + */ + clearRefs(objects); + + /* Start creating a bunch of temporary and permanent objects + * to drive GC. + */ + final int NUM_OBJECTS = 64 * 1024; + Object junk[] = new Object[NUM_OBJECTS]; + Random random = new Random(); + + int i = 0; + int mod = 0; + int totalSize = 0; + int cleared = -1; + while (i < junk.length && totalSize < 8 * 1024 * 1024) { + int r = random.nextInt(64 * 1024) + 128; + Object o = (Object) new byte[r]; + if (++mod % 16 == 0) { + junk[i++] = o; + totalSize += r * 4; + } + cleared = checkRefs(refs, cleared); + } + } + + private static void makeRefs(Object objects[], WeakReference<Object> refs[]) { + for (int i = 0; i < objects.length; i++) { + objects[i] = new Object(); + refs[i] = new WeakReference<Object>(objects[i]); + } + } + + private static <T> void checkRefs(T objects[], WeakReference<T> refs[]) { + boolean ok = true; + + for (int i = 0; i < objects.length; i++) { + if (refs[i].get() != objects[i]) { + ok = false; + } + } + if (!ok) { + throw new RuntimeException("Test failed: " + + "weak refs not cleared"); + } + } + + @MediumTest + public void testWeakRefs() throws Exception { + final int NUM_REFS = 16; + + Object objects[] = new Object[NUM_REFS]; + WeakReference<Object> refs[] = new WeakReference[objects.length]; + + /* Create a bunch of objects and a parallel array + * of WeakReferences. + */ + makeRefs(objects, refs); + Runtime.getRuntime().gc(); + checkRefs(objects, refs); + + /* Clear out every other strong reference. + */ + for (int i = 0; i < objects.length; i += 2) { + objects[i] = null; + } + Runtime.getRuntime().gc(); + checkRefs(objects, refs); + + /* Clear out the rest of them. + */ + for (int i = 0; i < objects.length; i++) { + objects[i] = null; + } + Runtime.getRuntime().gc(); + checkRefs(objects, refs); + } + + private static void makeRefs(Object objects[], PhantomReference<Object> refs[], + ReferenceQueue<Object> queue) { + for (int i = 0; i < objects.length; i++) { + objects[i] = new Object(); + refs[i] = new PhantomReference<Object>(objects[i], queue); + } + } + + static <T> void checkRefs(T objects[], PhantomReference<T> refs[], + ReferenceQueue<T> queue) { + boolean ok = true; + + /* Make sure that the reference that should be on + * the queue are marked as enqueued. Once we + * pull them off the queue, they will no longer + * be marked as enqueued. + */ + for (int i = 0; i < objects.length; i++) { + if (objects[i] == null && refs[i] != null) { + if (!refs[i].isEnqueued()) { + ok = false; + } + } + } + if (!ok) { + throw new RuntimeException("Test failed: " + + "phantom refs not marked as enqueued"); + } + + /* Make sure that all of the references on the queue + * are supposed to be there. + */ + PhantomReference<T> ref; + while ((ref = (PhantomReference<T>) queue.poll()) != null) { + /* Find the list index that corresponds to this reference. + */ + int i; + for (i = 0; i < objects.length; i++) { + if (refs[i] == ref) { + break; + } + } + if (i == objects.length) { + throw new RuntimeException("Test failed: " + + "unexpected ref on queue"); + } + if (objects[i] != null) { + throw new RuntimeException("Test failed: " + + "reference enqueued for strongly-reachable " + + "object"); + } + refs[i] = null; + + /* TODO: clear doesn't do much, since we're losing the + * strong ref to the ref object anyway. move the ref + * into another list. + */ + ref.clear(); + } + + /* We've visited all of the enqueued references. + * Make sure that there aren't any other references + * that should have been enqueued. + * + * NOTE: there is a race condition here; this assumes + * that the VM has serviced all outstanding reference + * enqueue() calls. + */ + for (int i = 0; i < objects.length; i++) { + if (objects[i] == null && refs[i] != null) { +// System.out.println("HeapTest/PhantomRefs: refs[" + i + +// "] should be enqueued"); + ok = false; + } + } + if (!ok) { + throw new RuntimeException("Test failed: " + + "phantom refs not enqueued"); + } + } + + @MediumTest + public void testPhantomRefs() throws Exception { + final int NUM_REFS = 16; + + Object objects[] = new Object[NUM_REFS]; + PhantomReference<Object> refs[] = new PhantomReference[objects.length]; + ReferenceQueue<Object> queue = new ReferenceQueue<Object>(); + + /* Create a bunch of objects and a parallel array + * of PhantomReferences. + */ + makeRefs(objects, refs, queue); + Runtime.getRuntime().gc(); + checkRefs(objects, refs, queue); + + /* Clear out every other strong reference. + */ + for (int i = 0; i < objects.length; i += 2) { + objects[i] = null; + } + // System.out.println("HeapTest/PhantomRefs: cleared evens"); + Runtime.getRuntime().gc(); + Runtime.getRuntime().runFinalization(); + checkRefs(objects, refs, queue); + + /* Clear out the rest of them. + */ + for (int i = 0; i < objects.length; i++) { + objects[i] = null; + } + // System.out.println("HeapTest/PhantomRefs: cleared all"); + Runtime.getRuntime().gc(); + Runtime.getRuntime().runFinalization(); + checkRefs(objects, refs, queue); + } + + private static int sNumFinalized = 0; + private static final Object sLock = new Object(); + + private static class FinalizableObject { + protected void finalize() { + // System.out.println("gc from finalize()"); + Runtime.getRuntime().gc(); + synchronized (sLock) { + sNumFinalized++; + } + } + } + + private static void makeRefs(FinalizableObject objects[], + WeakReference<FinalizableObject> refs[]) { + for (int i = 0; i < objects.length; i++) { + objects[i] = new FinalizableObject(); + refs[i] = new WeakReference<FinalizableObject>(objects[i]); + } + } + + @LargeTest + public void testWeakRefsAndFinalizers() throws Exception { + final int NUM_REFS = 16; + + FinalizableObject objects[] = new FinalizableObject[NUM_REFS]; + WeakReference<FinalizableObject> refs[] = new WeakReference[objects.length]; + int numCleared; + + /* Create a bunch of objects and a parallel array + * of WeakReferences. + */ + makeRefs(objects, refs); + Runtime.getRuntime().gc(); + checkRefs(objects, refs); + + /* Clear out every other strong reference. + */ + sNumFinalized = 0; + numCleared = 0; + for (int i = 0; i < objects.length; i += 2) { + objects[i] = null; + numCleared++; + } + // System.out.println("HeapTest/WeakRefsAndFinalizers: cleared evens"); + Runtime.getRuntime().gc(); + Runtime.getRuntime().runFinalization(); + checkRefs(objects, refs); + if (sNumFinalized != numCleared) { + throw new RuntimeException("Test failed: " + + "expected " + numCleared + " finalizations, saw " + + sNumFinalized); + } + + /* Clear out the rest of them. + */ + sNumFinalized = 0; + numCleared = 0; + for (int i = 0; i < objects.length; i++) { + if (objects[i] != null) { + objects[i] = null; + numCleared++; + } + } + // System.out.println("HeapTest/WeakRefsAndFinalizers: cleared all"); + Runtime.getRuntime().gc(); + Runtime.getRuntime().runFinalization(); + checkRefs(objects, refs); + if (sNumFinalized != numCleared) { + throw new RuntimeException("Test failed: " + + "expected " + numCleared + " finalizations, saw " + + sNumFinalized); + } + } + + @MediumTest + public void testOomeLarge() throws Exception { + /* Just shy of the typical max heap size so that it will actually + * try to allocate it instead of short-circuiting. + */ + final int SIXTEEN_MB = (16 * 1024 * 1024 - 32); + + Boolean sawEx = false; + byte a[]; + + try { + a = new byte[SIXTEEN_MB]; + } catch (OutOfMemoryError oom) { + //Log.i(TAG, "HeapTest/OomeLarge caught " + oom); + sawEx = true; + } + + if (!sawEx) { + throw new RuntimeException("Test failed: " + + "OutOfMemoryError not thrown"); + } + } + + //See bug 1308253 for reasons. + @Suppress + public void disableTestOomeSmall() throws Exception { + final int SIXTEEN_MB = (16 * 1024 * 1024); + final int LINK_SIZE = 6 * 4; // estimated size of a LinkedList's node + + Boolean sawEx = false; + + LinkedList<Object> list = new LinkedList<Object>(); + + /* Allocate progressively smaller objects to fill up the entire heap. + */ + int objSize = 1 * 1024 * 1024; + while (objSize >= LINK_SIZE) { + try { + for (int i = 0; i < SIXTEEN_MB / objSize; i++) { + list.add((Object)new byte[objSize]); + } + } catch (OutOfMemoryError oom) { + sawEx = true; + } + + if (!sawEx) { + throw new RuntimeException("Test failed: " + + "OutOfMemoryError not thrown while filling heap"); + } + sawEx = false; + + objSize = (objSize * 4) / 5; + } + } + + @SmallTest + public void testExternalOomeLarge() { + /* Just shy of the typical max heap size so that it will actually + * try to allocate it instead of short-circuiting. + */ + final int HUGE_SIZE = (16 * 1024 * 1024 - 32); + + assertFalse(VMRuntime.getRuntime().trackExternalAllocation(HUGE_SIZE)); + } + + /** + * "Allocates" external memory in progressively smaller chunks until there's + * only roughly 16 bytes left. + * + * @return the number of bytes allocated + */ + private long allocateMaxExternal() { + final VMRuntime runtime = VMRuntime.getRuntime(); + final int SIXTEEN_MB = (16 * 1024 * 1024); + final int MIN_SIZE = 16; + long totalAllocated = 0; + boolean success; + + success = false; + try { + /* "Allocate" progressively smaller chunks to "fill up" the entire heap. + */ + int objSize = 1 * 1024 * 1024; + while (objSize >= MIN_SIZE) { + boolean sawFailure = false; + for (int i = 0; i < SIXTEEN_MB / objSize; i++) { + if (runtime.trackExternalAllocation(objSize)) { + totalAllocated += objSize; + } else { + sawFailure = true; + break; + } + } + + if (!sawFailure) { + throw new RuntimeException("Test failed: " + + "no failure while filling heap"); + } + + objSize = (objSize * 4) / 5; + } + success = true; + } finally { + if (!success) { + runtime.trackExternalFree(totalAllocated); + totalAllocated = 0; + } + } + return totalAllocated; + } + + public void xxtest00ExternalOomeSmall() { + VMRuntime.getRuntime().trackExternalFree(allocateMaxExternal()); + } + + /** + * Allocates as much external memory as possible, then allocates from the heap + * until an OOME is caught. + * + * It's nice to run this test while the real heap is small, hence the '00' in its + * name to force it to run before testOomeSmall(). + */ + public void xxtest00CombinedOomeSmall() { + long totalAllocated = 0; + boolean sawEx = false; + try { + totalAllocated = allocateMaxExternal(); + LinkedList<Object> list = new LinkedList<Object>(); + try { + while (true) { + list.add((Object)new byte[8192]); + } + /*NOTREACHED*/ + } catch (OutOfMemoryError oom) { + sawEx = true; + } + } finally { + VMRuntime.getRuntime().trackExternalFree(totalAllocated); + } + assertTrue(sawEx); + } + + //TODO: test external alloc debugging/inspection +} diff --git a/tests/AndroidTests/src/com/android/unit_tests/HtmlTest.java b/tests/AndroidTests/src/com/android/unit_tests/HtmlTest.java new file mode 100644 index 0000000..27da4f1 --- /dev/null +++ b/tests/AndroidTests/src/com/android/unit_tests/HtmlTest.java @@ -0,0 +1,160 @@ +/* + * 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.unit_tests; + +import android.graphics.Typeface; +import android.test.suitebuilder.annotation.MediumTest; +import android.test.suitebuilder.annotation.SmallTest; +import android.text.*; +import android.text.style.*; + +import junit.framework.TestCase; + +/** + * HtmlTest tests the Spanned-to-HTML converter + */ +public class HtmlTest extends TestCase { + @MediumTest + public void testColor() throws Exception { + Spanned s; + ForegroundColorSpan[] colors; + + s = Html.fromHtml("<font color=\"#00FF00\">something</font>"); + colors = s.getSpans(0, s.length(), ForegroundColorSpan.class); + assertEquals(colors[0].getForegroundColor(), 0xFF00FF00); + + s = Html.fromHtml("<font color=\"navy\">something</font>"); + colors = s.getSpans(0, s.length(), ForegroundColorSpan.class); + assertEquals(colors[0].getForegroundColor(), 0xFF000080); + + s = Html.fromHtml("<font color=\"gibberish\">something</font>"); + colors = s.getSpans(0, s.length(), ForegroundColorSpan.class); + assertEquals(colors.length, 0); + } + + @SmallTest + public void testParagraphs() throws Exception { + SpannableString s; + + s = new SpannableString("Hello world"); + assertEquals(Html.toHtml(s), "<p>Hello world</p>\n"); + + s = new SpannableString("Hello world\nor something"); + assertEquals(Html.toHtml(s), "<p>Hello world<br>\nor something</p>\n"); + + s = new SpannableString("Hello world\n\nor something"); + assertEquals(Html.toHtml(s), "<p>Hello world</p>\n<p>or something</p>\n"); + + s = new SpannableString("Hello world\n\n\nor something"); + assertEquals(Html.toHtml(s), "<p>Hello world<br></p>\n<p>or something</p>\n"); + + assertEquals("foo\nbar", Html.fromHtml("foo<br>bar").toString()); + assertEquals("foo\nbar", Html.fromHtml("foo<br>\nbar").toString()); + assertEquals("foo\nbar", Html.fromHtml("foo<br>\n \nbar").toString()); + } + + @SmallTest + public void testBlockquote() throws Exception { + SpannableString s; + + s = new SpannableString("Hello world"); + s.setSpan(new QuoteSpan(), 0, s.length(), Spannable.SPAN_PARAGRAPH); + assertEquals(Html.toHtml(s), "<blockquote><p>Hello world</p>\n</blockquote>\n"); + + s = new SpannableString("Hello\n\nworld"); + s.setSpan(new QuoteSpan(), 0, 7, Spannable.SPAN_PARAGRAPH); + assertEquals(Html.toHtml(s), "<blockquote><p>Hello</p>\n</blockquote>\n<p>world</p>\n"); + } + + @SmallTest + public void testEntities() throws Exception { + SpannableString s; + + s = new SpannableString("Hello <&> world"); + assertEquals(Html.toHtml(s), "<p>Hello <&> world</p>\n"); + + s = new SpannableString("Hello \u03D5 world"); + assertEquals(Html.toHtml(s), "<p>Hello ϕ world</p>\n"); + + s = new SpannableString("Hello world"); + assertEquals(Html.toHtml(s), "<p>Hello world</p>\n"); + } + + @SmallTest + public void testMarkup() throws Exception { + SpannableString s; + + s = new SpannableString("Hello bold world"); + s.setSpan(new StyleSpan(Typeface.BOLD), 6, s.length() - 6, + Spannable.SPAN_EXCLUSIVE_INCLUSIVE); + assertEquals(Html.toHtml(s), "<p>Hello <b>bold</b> world</p>\n"); + + s = new SpannableString("Hello italic world"); + s.setSpan(new StyleSpan(Typeface.ITALIC), 6, s.length() - 6, + Spannable.SPAN_EXCLUSIVE_INCLUSIVE); + assertEquals(Html.toHtml(s), "<p>Hello <i>italic</i> world</p>\n"); + + s = new SpannableString("Hello monospace world"); + s.setSpan(new TypefaceSpan("monospace"), 6, s.length() - 6, + Spannable.SPAN_EXCLUSIVE_INCLUSIVE); + assertEquals(Html.toHtml(s), "<p>Hello <tt>monospace</tt> world</p>\n"); + + s = new SpannableString("Hello superscript world"); + s.setSpan(new SuperscriptSpan(), 6, s.length() - 6, + Spannable.SPAN_EXCLUSIVE_INCLUSIVE); + assertEquals(Html.toHtml(s), "<p>Hello <sup>superscript</sup> world</p>\n"); + + s = new SpannableString("Hello subscript world"); + s.setSpan(new SubscriptSpan(), 6, s.length() - 6, + Spannable.SPAN_EXCLUSIVE_INCLUSIVE); + assertEquals(Html.toHtml(s), "<p>Hello <sub>subscript</sub> world</p>\n"); + + s = new SpannableString("Hello underline world"); + s.setSpan(new UnderlineSpan(), 6, s.length() - 6, + Spannable.SPAN_EXCLUSIVE_INCLUSIVE); + assertEquals(Html.toHtml(s), "<p>Hello <u>underline</u> world</p>\n"); + + s = new SpannableString("Hello struck world"); + s.setSpan(new StrikethroughSpan(), 6, s.length() - 6, + Spannable.SPAN_EXCLUSIVE_INCLUSIVE); + assertEquals(Html.toHtml(s), "<p>Hello <strike>struck</strike> world</p>\n"); + + s = new SpannableString("Hello linky world"); + s.setSpan(new URLSpan("http://www.google.com"), 6, s.length() - 6, + Spannable.SPAN_EXCLUSIVE_INCLUSIVE); + assertEquals(Html.toHtml(s), + "<p>Hello <a href=\"http://www.google.com\">linky</a> world</p>\n"); + } + + @SmallTest + public void testImg() throws Exception { + Spanned s; + + s = Html.fromHtml("yes<img src=\"http://example.com/foo.gif\">no"); + + assertEquals("<p>yes<img src=\"http://example.com/foo.gif\">no</p>\n", + Html.toHtml(s)); + } + + @SmallTest + public void testUtf8() throws Exception { + Spanned s; + + s = Html.fromHtml("<p>\u0124\u00eb\u0142\u0142o, world!</p>"); + assertEquals("<p>Ĥëłło, world!</p>\n", Html.toHtml(s)); + } +} diff --git a/tests/AndroidTests/src/com/android/unit_tests/InflateTest.java b/tests/AndroidTests/src/com/android/unit_tests/InflateTest.java new file mode 100644 index 0000000..d7c9d60 --- /dev/null +++ b/tests/AndroidTests/src/com/android/unit_tests/InflateTest.java @@ -0,0 +1,154 @@ +/* + * 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.unit_tests; + +import android.content.Context; +import android.content.res.Resources; +import android.test.AndroidTestCase; +import android.test.PerformanceTestCase; +import android.test.suitebuilder.annotation.SmallTest; +import android.util.AttributeSet; +import android.view.LayoutInflater; +import android.view.View; + +import java.util.Map; + +public class InflateTest extends AndroidTestCase implements PerformanceTestCase { + private LayoutInflater mInflater; + private Resources mResources; + private View mView; + + @Override + protected void setUp() throws Exception { + super.setUp(); + + mInflater = LayoutInflater.from(mContext); + mResources = mContext.getResources(); + + // to try to make things consistent, before doing timing + // do an initial instantiation of the layout and then clear + // out the layout cache. +// mInflater.inflate(mResId, null, null); +// mResources.flushLayoutCache(); + } + + public int startPerformance(PerformanceTestCase.Intermediates intermediates) { + return 0; + } + + public boolean isPerformanceOnly() { + return false; + } + + public void inflateTest(int resourceId) { + mView = mInflater.inflate(resourceId, null); + mResources.flushLayoutCache(); + } + + public void inflateCachedTest(int resourceId) { + // Make sure this layout is in the cache. + mInflater.inflate(resourceId, null); + + mInflater.inflate(resourceId, null); + } + + @SmallTest + public void testLayout1() throws Exception { + inflateTest(R.layout.layout_one); + } + + @SmallTest + public void testLayout2() throws Exception { + inflateTest(R.layout.layout_two); + } + + @SmallTest + public void testLayout3() throws Exception { + inflateTest(R.layout.layout_three); + } + + @SmallTest + public void testLayout4() throws Exception { + inflateTest(R.layout.layout_four); + } + + @SmallTest + public void testLayout5() throws Exception { + inflateTest(R.layout.layout_five); + } + + @SmallTest + public void testLayout6() throws Exception { + inflateTest(R.layout.layout_six); + } + + @SmallTest + public void testCachedLayout1() throws Exception { + inflateCachedTest(R.layout.layout_one); + } + + @SmallTest + public void testCachedLayout2() throws Exception { + inflateCachedTest(R.layout.layout_two); + } + + @SmallTest + public void testCachedLayout3() throws Exception { + inflateCachedTest(R.layout.layout_three); + } + + @SmallTest + public void testCachedLayout4() throws Exception { + inflateCachedTest(R.layout.layout_four); + } + + @SmallTest + public void testCachedLayout5() throws Exception { + inflateCachedTest(R.layout.layout_five); + } + + @SmallTest + public void testCachedLayout6() throws Exception { + inflateCachedTest(R.layout.layout_six); + } + +// public void testLayoutTag() throws Exception { +// public void setUp +// (Context +// context){ +// setUp(context, R.layout.layout_tag); +// } +// public void run +// () +// { +// super.run(); +// if (!"MyTag".equals(mView.getTag())) { +// throw new RuntimeException("Incorrect tag: " + mView.getTag()); +// } +// } +// } + + public static class ViewOne extends View { + public ViewOne(Context context) { + super(context); + } + + public ViewOne(Context context, AttributeSet attrs) { + super(context, attrs); + } + } +} diff --git a/tests/AndroidTests/src/com/android/unit_tests/InstanceofTest.java b/tests/AndroidTests/src/com/android/unit_tests/InstanceofTest.java new file mode 100644 index 0000000..1f82df8 --- /dev/null +++ b/tests/AndroidTests/src/com/android/unit_tests/InstanceofTest.java @@ -0,0 +1,141 @@ +/* + * 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.unit_tests; + +import junit.framework.TestCase; +import android.test.suitebuilder.annotation.MediumTest; + + +public class InstanceofTest extends TestCase { + + protected A mA; + protected ChildOfAOne mOne; + protected ChildOfAOne mTwo; + protected ChildOfAOne mThree; + protected ChildOfAOne mFour; + protected ChildOfAFive mFive; + + @Override + protected void setUp() throws Exception { + super.setUp(); + + mA = new A(); + mOne = new ChildOfAOne(); + mTwo = new ChildOfATwo(); + mThree = new ChildOfAThree(); + mFour = new ChildOfAFour(); + mFive = new ChildOfAFive(); + } + + + @MediumTest + public void testNoInterface() throws Exception { + A a = mA; + for (int i = 0; i < 100000; i++) { + assertFalse("m_a should not be a ChildOfAFive", a instanceof ChildOfAFive); + } + } + + @MediumTest + public void testDerivedOne() throws Exception { + InterfaceOne one = mOne; + for (int i = 0; i < 100000; i++) { + assertFalse("m_one should not be a ChildOfAFive", one instanceof ChildOfAFive); + } + } + + @MediumTest + public void testDerivedTwo() throws Exception { + InterfaceTwo two = mTwo; + for (int i = 0; i < 100000; i++) { + assertFalse("m_two should not be a ChildOfAFive", two instanceof ChildOfAFive); + } + } + + @MediumTest + public void testDerivedThree() throws Exception { + InterfaceThree three = mThree; + for (int i = 0; i < 100000; i++) { + assertFalse("m_three should not be a ChildOfAFive", three instanceof ChildOfAFive); + } + } + + @MediumTest + public void testDerivedFour() throws Exception { + InterfaceFour four = mFour; + for (int i = 0; i < 100000; i++) { + assertFalse("m_four should not be a ChildOfAFive", four instanceof ChildOfAFive); + } + } + + @MediumTest + public void testSuccessClass() throws Exception { + ChildOfAOne five = mFive; + for (int i = 0; i < 100000; i++) { + assertTrue("m_five is suppose to be a ChildOfAFive", five instanceof ChildOfAFive); + } + } + + @MediumTest + public void testSuccessInterface() throws Exception { + ChildOfAFive five = mFive; + for (int i = 0; i < 100000; i++) { + assertTrue("m_five is suppose to be a InterfaceFour", five instanceof InterfaceFour); + } + } + + @MediumTest + public void testFailInterface() throws Exception { + InterfaceOne one = mFive; + for (int i = 0; i < 100000; i++) { + assertFalse("m_five does not implement InterfaceFive", one instanceof InterfaceFive); + } + } + + private interface InterfaceOne { + } + + private interface InterfaceTwo { + } + + private interface InterfaceThree { + } + + private interface InterfaceFour { + } + + private interface InterfaceFive { + } + + private static class A { + } + + private static class ChildOfAOne extends A implements InterfaceOne, InterfaceTwo, InterfaceThree, InterfaceFour { + } + + private static class ChildOfATwo extends ChildOfAOne { + } + + private static class ChildOfAThree extends ChildOfATwo { + } + + private static class ChildOfAFour extends ChildOfAThree { + } + + private static class ChildOfAFive extends ChildOfAFour { + } +} diff --git a/tests/AndroidTests/src/com/android/unit_tests/JavaPerformanceTests.java b/tests/AndroidTests/src/com/android/unit_tests/JavaPerformanceTests.java new file mode 100644 index 0000000..e778d53 --- /dev/null +++ b/tests/AndroidTests/src/com/android/unit_tests/JavaPerformanceTests.java @@ -0,0 +1,38 @@ +/* + * 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.unit_tests; + +/** + * + */ +public class JavaPerformanceTests { + + public static String[] children() { + return new String[] { + StringTest.class.getName(), + HashMapTest.class.getName(), + ArrayListTest.class.getName(), + TreeMapTest.class.getName(), + TreeSetTest.class.getName(), + HashSetTest.class.getName(), + HashtableTest.class.getName(), + VectorTest.class.getName(), + LinkedListTest.class.getName(), + MathTest.class.getName(), + }; + } +} diff --git a/tests/AndroidTests/src/com/android/unit_tests/JniLibTest.java b/tests/AndroidTests/src/com/android/unit_tests/JniLibTest.java new file mode 100644 index 0000000..6b740ba --- /dev/null +++ b/tests/AndroidTests/src/com/android/unit_tests/JniLibTest.java @@ -0,0 +1,59 @@ +/* + * 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.unit_tests; + +import android.test.suitebuilder.annotation.Suppress; +import android.util.Log; +import junit.framework.TestCase; + + +@Suppress +public class JniLibTest extends TestCase { + + @Override + protected void setUp() throws Exception { + super.setUp(); + /* + * This causes the native shared library to be loaded when the + * class is first used. The library is only loaded once, even if + * multiple classes include this line. + * + * The library must be in java.library.path, which is derived from + * LD_LIBRARY_PATH. The actual library name searched for will be + * "libjni_lib_test.so" under Linux, but may be different on other + * platforms. + */ + try { + System.loadLibrary("jni_lib_test"); + } catch (UnsatisfiedLinkError ule) { + Log.e("JniLibTest", "WARNING: Could not load jni_lib_test natives"); + } + } + + private static native int nativeStaticThing(float f); + private native void nativeThing(int val); + + public void testNativeCall() { + Log.i("JniLibTest", "JNI search path is " + + System.getProperty("java.library.path")); + Log.i("JniLibTest", "'jni_lib_test' becomes '" + + System.mapLibraryName("jni_lib_test") + "'"); + + int result = nativeStaticThing(1234.5f); + nativeThing(result); + } +} diff --git a/tests/AndroidTests/src/com/android/unit_tests/LabelView.java b/tests/AndroidTests/src/com/android/unit_tests/LabelView.java new file mode 100644 index 0000000..ac29776 --- /dev/null +++ b/tests/AndroidTests/src/com/android/unit_tests/LabelView.java @@ -0,0 +1,191 @@ +/* + * 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.unit_tests; + +import android.content.Context; +import android.graphics.Canvas; +import android.graphics.Paint; +import android.view.View; + +/** + * Example of how to write a custom subclass of View. LabelView + * is used to draw simple text views. Note that it does not handle + * styled text or right-to-left writing systems. + * + */ +public class LabelView extends View { + /** + * Constructor. This version is only needed if you will be instantiating + * the object manually (not from a layout XML file). + * @param context the application environment + */ + public LabelView(Context context) { + super(context); + initLabelView(); + } + + /** + * Construct object, initializing with any attributes we understand from a + * layout file. These attributes are defined in + * SDK/assets/res/any/classes.xml. + * + * @see android.view.View#View(android.content.Context, android.util.AttributeSet) + public LabelView(Context context, AttributeSet attrs) { + super(context, attrs); + initLabelView(); + + Resources.StyledAttributes a = context.obtainStyledAttributes(attrs, + R.styleable.LabelView); + + CharSequence s = a.getString(R.styleable.LabelView_text); + if (s != null) { + setText(s.toString()); + } + + ColorStateList textColor = a.getColorList(R.styleable. + LabelView_textColor); + if (textColor != null) { + setTextColor(textColor.getDefaultColor(0)); + } + + int textSize = a.getInt(R.styleable.LabelView_textSize, 0); + if (textSize > 0) { + setTextSize(textSize); + } + + a.recycle(); + } + + */ + private void initLabelView() { + mTextPaint = new Paint(); + mTextPaint.setAntiAlias(true); + mTextPaint.setTextSize(16); + mTextPaint.setColor(0xFF000000); + + mPaddingLeft = 3; + mPaddingTop = 3; + mPaddingRight = 3; + mPaddingBottom = 3; + } + + /** + * Sets the text to display in this label + * @param text The text to display. This will be drawn as one line. + */ + public void setText(String text) { + mText = text; + requestLayout(); + invalidate(); + } + + /** + * Sets the text size for this label + * @param size Font size + */ + public void setTextSize(int size) { + mTextPaint.setTextSize(size); + requestLayout(); + invalidate(); + } + + /** + * Sets the text color for this label + * @param color ARGB value for the text + */ + public void setTextColor(int color) { + mTextPaint.setColor(color); + invalidate(); + } + + + /** + * @see android.view.View#measure(int, int) + */ + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + setMeasuredDimension(measureWidth(widthMeasureSpec), + measureHeight(heightMeasureSpec)); + } + + /** + * Determines the width of this view + * @param measureSpec A measureSpec packed into an int + * @return The width of the view, honoring constraints from measureSpec + */ + private int measureWidth(int measureSpec) { + int result; + int specMode = MeasureSpec.getMode(measureSpec); + int specSize = MeasureSpec.getSize(measureSpec); + + if (specMode == MeasureSpec.EXACTLY) { + // We were told how big to be + result = specSize; + } else { + // Measure the text + result = (int) mTextPaint.measureText(mText) + mPaddingLeft + + mPaddingRight; + if (specMode == MeasureSpec.AT_MOST) { + // Respect AT_MOST value if that was what is called for by measureSpec + result = Math.min(result, specSize); + } + } + + return result; + } + + /** + * Determines the height of this view + * @param measureSpec A measureSpec packed into an int + * @return The height of the view, honoring constraints from measureSpec + */ + private int measureHeight(int measureSpec) { + int result; + int specMode = MeasureSpec.getMode(measureSpec); + int specSize = MeasureSpec.getSize(measureSpec); + + mAscent = (int) mTextPaint.ascent(); + if (specMode == MeasureSpec.EXACTLY) { + // We were told how big to be + result = specSize; + } else { + // Measure the text (beware: ascent is a negative number) + result = (int) (-mAscent + mTextPaint.descent()) + mPaddingTop + + mPaddingBottom; + if (specMode == MeasureSpec.AT_MOST) { + // Respect AT_MOST value if that was what is called for by measureSpec + result = Math.min(result, specSize); + } + } + return result; + } + + /** + * Render the text + * + * @see android.view.View#onDraw(android.graphics.Canvas) + */ + @Override + protected void onDraw(Canvas canvas) { + super.onDraw(canvas); + canvas.drawText(mText, mPaddingLeft, mPaddingTop - mAscent, mTextPaint); + } + + private Paint mTextPaint; + private String mText; + private int mAscent; +} diff --git a/tests/AndroidTests/src/com/android/unit_tests/LinkedListTest.java b/tests/AndroidTests/src/com/android/unit_tests/LinkedListTest.java new file mode 100644 index 0000000..ca470cd --- /dev/null +++ b/tests/AndroidTests/src/com/android/unit_tests/LinkedListTest.java @@ -0,0 +1,529 @@ +/* + * 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.unit_tests; + +import android.test.PerformanceTestBase; +import android.test.PerformanceTestCase; +import java.util.LinkedList; +import java.util.ListIterator; + +/** + * This class contains performance tests for methods in java.util.LinkedList + * + */ +@SuppressWarnings("unchecked") +public class LinkedListTest extends PerformanceTestBase { + public static final int ITERATIONS = 1000; + LinkedList<Integer> mLinkedList; + + @Override + protected void setUp() throws Exception { + super.setUp(); + mLinkedList = new LinkedList(); + for (int i = ITERATIONS - 1; i >= 0; i--) { + mLinkedList.add(i); + } + } + + @Override + public int startPerformance(PerformanceTestCase.Intermediates intermediates) { + intermediates.setInternalIterations(ITERATIONS); + return 0; + } + + public void testLinkedListAdd() { + LinkedList<Integer> list = new LinkedList(); + for (int i = ITERATIONS - 1; i >= 0; i--) { + list.add(i); + list.add(i); + list.add(i); + list.add(i); + list.add(i); + list.add(i); + list.add(i); + list.add(i); + list.add(i); + list.add(i); + } + } + + public void testLinkedListAdd1() { + LinkedList<Integer> list = new LinkedList(); + for (int i = ITERATIONS - 1; i >= 0; i--) { + list.add(0, i); + list.add(0, i); + list.add(0, i); + list.add(0, i); + list.add(0, i); + list.add(0, i); + list.add(0, i); + list.add(0, i); + list.add(0, i); + list.add(0, i); + } + } + + public void testLinkedListToArray() { + Object array; + LinkedList<Integer> list = mLinkedList; + for (int i = ITERATIONS - 1; i >= 0; i--) { + array = list.toArray(); + array = list.toArray(); + array = list.toArray(); + array = list.toArray(); + array = list.toArray(); + array = list.toArray(); + array = list.toArray(); + array = list.toArray(); + array = list.toArray(); + array = list.toArray(); + } + } + + public void testLinkedListSize() { + LinkedList<Integer> list = mLinkedList; + int len; + for (int i = ITERATIONS - 1; i >= 0; i--) { + len = list.size(); + len = list.size(); + len = list.size(); + len = list.size(); + len = list.size(); + len = list.size(); + len = list.size(); + len = list.size(); + len = list.size(); + len = list.size(); + } + } + + public void testLinkedListGet() { + int element; + LinkedList<Integer> list = mLinkedList; + for (int i = ITERATIONS - 1; i >= 0; i--) { + element = list.get(i); + element = list.get(i); + element = list.get(i); + element = list.get(i); + element = list.get(i); + element = list.get(i); + element = list.get(i); + element = list.get(i); + element = list.get(i); + element = list.get(i); + } + } + + public void testLinkedListContains() { + boolean flag; + LinkedList<Integer> list = mLinkedList; + for (int i = ITERATIONS - 1; i >= 0; i--) { + flag = list.contains(i); + flag = list.contains(i); + flag = list.contains(i); + flag = list.contains(i); + flag = list.contains(i); + flag = list.contains(i); + flag = list.contains(i); + flag = list.contains(i); + flag = list.contains(i); + flag = list.contains(i); + } + } + + public void testLinkedListToArray1() { + Integer[] rArray = new Integer[100]; + Integer[] array; + LinkedList<Integer> list = mLinkedList; + for (int i = ITERATIONS - 1; i >= 0; i--) { + array = list.toArray(rArray); + array = list.toArray(rArray); + array = list.toArray(rArray); + array = list.toArray(rArray); + array = list.toArray(rArray); + array = list.toArray(rArray); + array = list.toArray(rArray); + array = list.toArray(rArray); + array = list.toArray(rArray); + array = list.toArray(rArray); + } + } + + public void testLinkedListSet() { + LinkedList<Integer> list = mLinkedList; + int value1 = 500, value2 = 0; + for (int i = ITERATIONS - 1; i >= 0; i--) { + list.set(value1, value2); + list.set(value1, value2); + list.set(value1, value2); + list.set(value1, value2); + list.set(value1, value2); + list.set(value1, value2); + list.set(value1, value2); + list.set(value1, value2); + list.set(value1, value2); + list.set(value1, value2); + } + } + + public void testLinkedListIndexOf() { + int index; + LinkedList<Integer> list = mLinkedList; + for (int i = ITERATIONS - 1; i >= 0; i--) { + index = list.indexOf(0); + index = list.indexOf(0); + index = list.indexOf(0); + index = list.indexOf(0); + index = list.indexOf(0); + index = list.indexOf(0); + index = list.indexOf(0); + index = list.indexOf(0); + index = list.indexOf(0); + index = list.indexOf(0); + + } + } + + public void testLinkedListLastIndexOf() { + int index; + LinkedList<Integer> list = mLinkedList; + for (int i = ITERATIONS - 1; i >= 0; i--) { + index = list.lastIndexOf(0); + index = list.lastIndexOf(0); + index = list.lastIndexOf(0); + index = list.lastIndexOf(0); + index = list.lastIndexOf(0); + index = list.lastIndexOf(0); + index = list.lastIndexOf(0); + index = list.lastIndexOf(0); + index = list.lastIndexOf(0); + index = list.lastIndexOf(0); + } + } + + public void testLinkedListRemove() { + int index; + LinkedList<Integer> list = new LinkedList(mLinkedList); + for (int i = 10; i > 0; i--) { + index = list.remove(); + index = list.remove(); + index = list.remove(); + index = list.remove(); + index = list.remove(); + index = list.remove(); + index = list.remove(); + index = list.remove(); + index = list.remove(); + index = list.remove(); + } + } + + public void testLinkedListRemove1() { + int index; + LinkedList<Integer> list = new LinkedList(mLinkedList); + for (int i = 10; i > 0; i--) { + index = list.remove(0); + index = list.remove(0); + index = list.remove(0); + index = list.remove(0); + index = list.remove(0); + index = list.remove(0); + index = list.remove(0); + index = list.remove(0); + index = list.remove(0); + index = list.remove(0); + } + } + + public void testLinkedListRemoveFirst() { + int index; + LinkedList<Integer> list = new LinkedList(mLinkedList); + for (int i = 10; i > 0; i--) { + index = list.removeFirst(); + index = list.removeFirst(); + index = list.removeFirst(); + index = list.removeFirst(); + index = list.removeFirst(); + index = list.removeFirst(); + index = list.removeFirst(); + index = list.removeFirst(); + index = list.removeFirst(); + index = list.removeFirst(); + } + } + + public void testLinkedListRemoveLast() { + int index; + LinkedList<Integer> list = new LinkedList(mLinkedList); + for (int i = 10; i > 0; i--) { + index = list.removeLast(); + index = list.removeLast(); + index = list.removeLast(); + index = list.removeLast(); + index = list.removeLast(); + index = list.removeLast(); + index = list.removeLast(); + index = list.removeLast(); + index = list.removeLast(); + index = list.removeLast(); + } + } + + public void testLinkedListAddAll() { + LinkedList<Integer> mList = mLinkedList; + boolean flag; + LinkedList<Integer> list = new LinkedList(); + for (int i = 10; i > 0; i--) { + flag = list.addAll(mList); + flag = list.addAll(mList); + flag = list.addAll(mList); + flag = list.addAll(mList); + flag = list.addAll(mList); + flag = list.addAll(mList); + flag = list.addAll(mList); + flag = list.addAll(mList); + flag = list.addAll(mList); + flag = list.addAll(mList); + } + } + + public void testLinkedListRemove2() { + LinkedList<String> list; + String s = new String("a"); + list = new LinkedList(); + for (int j = 1000; j > 0; j--) { + list.add("a"); + list.add("b"); + } + boolean flag; + for (int i = 10; i > 0; i--) { + flag = list.remove(s); + flag = list.remove(s); + flag = list.remove(s); + flag = list.remove(s); + flag = list.remove(s); + flag = list.remove(s); + flag = list.remove(s); + flag = list.remove(s); + flag = list.remove(s); + flag = list.remove(s); + } + } + + public void testLinkedListAddAll1() { + LinkedList<Integer> mList = new LinkedList(); + int pos = 0; + boolean flag; + LinkedList<Integer> list = mLinkedList; + for (int i = 0; i < 10; i++) { + flag = mList.addAll(pos, list); + flag = mList.addAll(pos, list); + flag = mList.addAll(pos, list); + flag = mList.addAll(pos, list); + flag = mList.addAll(pos, list); + flag = mList.addAll(pos, list); + flag = mList.addAll(pos, list); + flag = mList.addAll(pos, list); + flag = mList.addAll(pos, list); + flag = mList.addAll(pos, list); + } + } + + public void testLinkedListClone() { + Object rObj; + LinkedList<Integer> list = mLinkedList; + for (int i = 100; i > 0; i--) { + rObj = list.clone(); + rObj = list.clone(); + rObj = list.clone(); + rObj = list.clone(); + rObj = list.clone(); + rObj = list.clone(); + rObj = list.clone(); + rObj = list.clone(); + rObj = list.clone(); + rObj = list.clone(); + } + } + + public void testLinkedListHashcode() { + int element; + LinkedList<Integer> list = mLinkedList; + for (int i = ITERATIONS - 1; i >= 0; i--) { + element = list.hashCode(); + element = list.hashCode(); + element = list.hashCode(); + element = list.hashCode(); + element = list.hashCode(); + element = list.hashCode(); + element = list.hashCode(); + element = list.hashCode(); + element = list.hashCode(); + element = list.hashCode(); + } + } + + public void testLinkedListElement() { + int element; + LinkedList<Integer> list = mLinkedList; + for (int i = ITERATIONS - 1; i >= 0; i--) { + element = list.element(); + element = list.element(); + element = list.element(); + element = list.element(); + element = list.element(); + element = list.element(); + element = list.element(); + element = list.element(); + element = list.element(); + element = list.element(); + } + } + + public void testLinkedListToString() { + String str; + LinkedList<Integer> list = mLinkedList; + for (int i = ITERATIONS - 1; i >= 0; i--) { + str = list.toString(); + str = list.toString(); + str = list.toString(); + str = list.toString(); + str = list.toString(); + str = list.toString(); + str = list.toString(); + str = list.toString(); + str = list.toString(); + str = list.toString(); + } + } + + public void testLinkedListIsEmpty() { + boolean flag; + LinkedList<Integer> list = mLinkedList; + for (int i = ITERATIONS - 1; i >= 0; i--) { + flag = list.isEmpty(); + flag = list.isEmpty(); + flag = list.isEmpty(); + flag = list.isEmpty(); + flag = list.isEmpty(); + flag = list.isEmpty(); + flag = list.isEmpty(); + flag = list.isEmpty(); + flag = list.isEmpty(); + flag = list.isEmpty(); + } + } + + public void testLinkedListOffer() { + LinkedList<Integer> list = new LinkedList(); + for (int i = ITERATIONS - 1; i >= 0; i--) { + list.offer(i); + list.offer(i); + list.offer(i); + list.offer(i); + list.offer(i); + list.offer(i); + list.offer(i); + list.offer(i); + list.offer(i); + list.offer(i); + } + } + + public void testLinkedListPeek() { + int element; + LinkedList<Integer> list = mLinkedList; + for (int i = ITERATIONS - 1; i >= 0; i--) { + element = list.peek(); + element = list.peek(); + element = list.peek(); + element = list.peek(); + element = list.peek(); + element = list.peek(); + element = list.peek(); + element = list.peek(); + element = list.peek(); + element = list.peek(); + } + } + + public void testLinkedListPoll() { + int element; + LinkedList<Integer> list = new LinkedList(mLinkedList); + for (int i = 10; i > 0; i--) { + element = list.poll(); + element = list.poll(); + element = list.poll(); + element = list.poll(); + element = list.poll(); + element = list.poll(); + element = list.poll(); + element = list.poll(); + element = list.poll(); + element = list.poll(); + } + } + + public void testLinkedListAddLast() { + LinkedList<Integer> list = new LinkedList(); + for (int i = ITERATIONS - 1; i >= 0; i--) { + list.addLast(i); + list.addLast(i); + list.addLast(i); + list.addLast(i); + list.addLast(i); + list.addLast(i); + list.addLast(i); + list.addLast(i); + list.addLast(i); + list.addLast(i); + } + } + + public void testLinkedListAddFirst() { + LinkedList<Integer> list = new LinkedList(); + for (int i = ITERATIONS - 1; i >= 0; i--) { + list.addFirst(i); + list.addFirst(i); + list.addFirst(i); + list.addFirst(i); + list.addFirst(i); + list.addFirst(i); + list.addFirst(i); + list.addFirst(i); + list.addFirst(i); + list.addFirst(i); + } + } + + public void testLinkedListIterator() { + ListIterator iterator; + LinkedList<Integer> list = mLinkedList; + for (int i = ITERATIONS - 1; i >= 0; i--) { + iterator = list.listIterator(); + iterator = list.listIterator(); + iterator = list.listIterator(); + iterator = list.listIterator(); + iterator = list.listIterator(); + iterator = list.listIterator(); + iterator = list.listIterator(); + iterator = list.listIterator(); + iterator = list.listIterator(); + iterator = list.listIterator(); + } + } +} diff --git a/tests/AndroidTests/src/com/android/unit_tests/LinkifyTest.java b/tests/AndroidTests/src/com/android/unit_tests/LinkifyTest.java new file mode 100644 index 0000000..83e0758 --- /dev/null +++ b/tests/AndroidTests/src/com/android/unit_tests/LinkifyTest.java @@ -0,0 +1,68 @@ +/* + * Copyright (C) 2008 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.unit_tests; + +import android.test.AndroidTestCase; +import android.test.suitebuilder.annotation.MediumTest; +import android.test.suitebuilder.annotation.SmallTest; +import android.text.*; +import android.text.method.*; +import android.text.style.*; +import android.text.util.*; +import android.widget.*; + +/** + * LinkifyTest tests {@link Linkify}. + */ +public class LinkifyTest extends AndroidTestCase { + + @SmallTest + public void testNothing() throws Exception { + TextView tv; + + tv = new TextView(getContext()); + tv.setText("Hey, foo@google.com, call 415-555-1212."); + + assertFalse(tv.getMovementMethod() instanceof LinkMovementMethod); + assertTrue(tv.getUrls().length == 0); + } + + @MediumTest + public void testNormal() throws Exception { + TextView tv; + + tv = new TextView(getContext()); + tv.setAutoLinkMask(Linkify.ALL); + tv.setText("Hey, foo@google.com, call 415-555-1212."); + + assertTrue(tv.getMovementMethod() instanceof LinkMovementMethod); + assertTrue(tv.getUrls().length == 2); + } + + @SmallTest + public void testUnclickable() throws Exception { + TextView tv; + + tv = new TextView(getContext()); + tv.setAutoLinkMask(Linkify.ALL); + tv.setLinksClickable(false); + tv.setText("Hey, foo@google.com, call 415-555-1212."); + + assertFalse(tv.getMovementMethod() instanceof LinkMovementMethod); + assertTrue(tv.getUrls().length == 2); + } +} diff --git a/tests/AndroidTests/src/com/android/unit_tests/LocalSocketTest.java b/tests/AndroidTests/src/com/android/unit_tests/LocalSocketTest.java new file mode 100644 index 0000000..0b8ec74 --- /dev/null +++ b/tests/AndroidTests/src/com/android/unit_tests/LocalSocketTest.java @@ -0,0 +1,171 @@ +/* + * 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.unit_tests; + +import android.net.Credentials; +import android.net.LocalServerSocket; +import android.net.LocalSocket; +import android.net.LocalSocketAddress; +import android.test.MoreAsserts; +import android.test.suitebuilder.annotation.SmallTest; +import junit.framework.TestCase; + +import java.io.FileDescriptor; +import java.io.IOException; + +public class LocalSocketTest extends TestCase { + + @SmallTest + public void testBasic() throws Exception { + LocalServerSocket ss; + LocalSocket ls; + LocalSocket ls1; + + ss = new LocalServerSocket("com.android.unit_tests.LocalSocketTest"); + + ls = new LocalSocket(); + + ls.connect(new LocalSocketAddress("com.android.unit_tests.LocalSocketTest")); + + ls1 = ss.accept(); + + // Test trivial read and write + ls.getOutputStream().write(42); + + assertEquals(42, ls1.getInputStream().read()); + + // Test getting credentials + Credentials c = ls1.getPeerCredentials(); + + MoreAsserts.assertNotEqual(0, c.getPid()); + + // Test sending and receiving file descriptors + ls.setFileDescriptorsForSend( + new FileDescriptor[]{FileDescriptor.in}); + + ls.getOutputStream().write(42); + + assertEquals(42, ls1.getInputStream().read()); + + FileDescriptor[] out = ls1.getAncillaryFileDescriptors(); + + assertEquals(1, out.length); + + // Test multible byte write and available() + ls1.getOutputStream().write(new byte[]{0, 1, 2, 3, 4, 5}, 1, 5); + + assertEquals(1, ls.getInputStream().read()); + assertEquals(4, ls.getInputStream().available()); + + byte[] buffer = new byte[16]; + int countRead; + + countRead = ls.getInputStream().read(buffer, 1, 15); + + assertEquals(4, countRead); + assertEquals(2, buffer[1]); + assertEquals(3, buffer[2]); + assertEquals(4, buffer[3]); + assertEquals(5, buffer[4]); + + // Try various array-out-of-bound cases + try { + ls.getInputStream().read(buffer, 1, 16); + fail("expected exception"); + } catch (ArrayIndexOutOfBoundsException ex) { + // excpected + } + + try { + ls.getOutputStream().write(buffer, 1, 16); + fail("expected exception"); + } catch (ArrayIndexOutOfBoundsException ex) { + // excpected + } + + try { + ls.getOutputStream().write(buffer, -1, 15); + fail("expected exception"); + } catch (ArrayIndexOutOfBoundsException ex) { + // excpected + } + + try { + ls.getOutputStream().write(buffer, 0, -1); + fail("expected exception"); + } catch (ArrayIndexOutOfBoundsException ex) { + // excpected + } + + try { + ls.getInputStream().read(buffer, -1, 15); + fail("expected exception"); + } catch (ArrayIndexOutOfBoundsException ex) { + // excpected + } + + try { + ls.getInputStream().read(buffer, 0, -1); + fail("expected exception"); + } catch (ArrayIndexOutOfBoundsException ex) { + // excpected + } + + // Try read of length 0 + ls.getOutputStream().write(42); + countRead = ls1.getInputStream().read(buffer, 0, 0); + assertEquals(0, countRead); + assertEquals(42, ls1.getInputStream().read()); + + ss.close(); + + ls.close(); + + // Try write on closed socket + + try { + ls.getOutputStream().write(42); + fail("expected exception"); + } catch (IOException ex) { + // Expected + } + + // Try read on closed socket + + try { + ls.getInputStream().read(); + fail("expected exception"); + } catch (IOException ex) { + // Expected + } + + // Try write on socket whose peer has closed + + try { + ls1.getOutputStream().write(42); + fail("expected exception"); + } catch (IOException ex) { + // Expected + } + + // Try read on socket whose peer has closed + + assertEquals(-1, ls1.getInputStream().read()); + + ls1.close(); + } +} diff --git a/tests/AndroidTests/src/com/android/unit_tests/LocationManagerTest.java b/tests/AndroidTests/src/com/android/unit_tests/LocationManagerTest.java new file mode 100644 index 0000000..47c7522 --- /dev/null +++ b/tests/AndroidTests/src/com/android/unit_tests/LocationManagerTest.java @@ -0,0 +1,132 @@ +/* + * 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.unit_tests; + +import android.content.Context; +import android.location.Criteria; +import android.location.Location; +import android.location.LocationManager; +import android.location.LocationProvider; +import android.test.AndroidTestCase; +import android.test.suitebuilder.annotation.Suppress; +import android.util.Log; + +@Suppress +public class LocationManagerTest extends AndroidTestCase { + private static final String LOG_TAG = "LocationManagerTest"; + + private LocationManager manager; + + @Override + public void setUp() throws Exception { + super.setUp(); + manager = (LocationManager) mContext.getSystemService(Context.LOCATION_SERVICE); + assertNotNull(manager); + } + + public void testGetBogusProvider() { + LocationProvider p = manager.getProvider("bogus"); + assertNull(p); + } + + public void testGetNetworkProvider() { + LocationProvider p = manager.getProvider("network"); + assertNotNull(p); + } + + public void testGetGpsProvider() { + LocationProvider p = manager.getProvider("gps"); + assertNotNull(p); + } + + public void testGetBestProviderEmptyCriteria() { + String p = manager.getBestProvider(new Criteria(), true); + assertNotNull(p); + } + + public void testGetBestProviderPowerCriteria() { + Criteria c = new Criteria(); + c.setPowerRequirement(Criteria.POWER_HIGH); + String p = manager.getBestProvider(c, true); + assertNotNull(p); + + c.setPowerRequirement(Criteria.POWER_MEDIUM); + p = manager.getBestProvider(c, true); + assertNotNull(p); + + c.setPowerRequirement(Criteria.POWER_LOW); + p = manager.getBestProvider(c, true); + assertNotNull(p); + + c.setPowerRequirement(Criteria.NO_REQUIREMENT); + p = manager.getBestProvider(c, true); + assertNotNull(p); + } + + public void testGpsTracklog() { + LocationProvider p = manager.getProvider("gps"); + assertNotNull(p); + + // TODO: test requestUpdates method + } + + public void testLocationConversions() { + String loc1 = Location.convert(-80.075, Location.FORMAT_DEGREES); + Log.i(LOG_TAG, "Input = " + (-80.075) + ", output = " + loc1); + assertEquals("-80.075", loc1); + + String loc1b = Location.convert(-80.0, Location.FORMAT_DEGREES); + Log.i(LOG_TAG, "Input = " + (-80.0) + ", output = " + loc1b); + assertEquals("-80", loc1b); + + String loc2 = Location.convert(-80.085, Location.FORMAT_DEGREES); + Log.i(LOG_TAG, "Input = " + (-80.085) + ", output = " + loc2); + assertEquals("-80.085", loc2); + + String loc3 = Location.convert(-80.085, Location.FORMAT_MINUTES); + Log.i(LOG_TAG, "Input = " + (-80.085) + ", output = " + loc3); + assertEquals("-80:5.1", loc3); + + String loc4 = Location.convert(-80.085, Location.FORMAT_SECONDS); + Log.i(LOG_TAG, "Input = " + (-80.085) + ", output = " + loc4); + assertEquals("-80:5:6", loc4); + + String loc5 = Location.convert(5 + 0.5f / 60.0f, Location.FORMAT_MINUTES); + Log.i(LOG_TAG, "Input = 5:0.5, output = " + loc5); + int index = loc5.indexOf(':'); + String loc5a = loc5.substring(0, index); + Log.i(LOG_TAG, "loc5a = " + loc5a); + assertTrue(loc5a.equals("5")); + String loc5b = loc5.substring(index + 1); + Log.i(LOG_TAG, "loc5b = " + loc5b); + double minutes = Double.parseDouble(loc5b); + Log.i(LOG_TAG, "minutes = " + minutes); + assertTrue(Math.abs(minutes - 0.5) < 0.0001); + + String loc6 = Location.convert(0.1, Location.FORMAT_DEGREES); + Log.i(LOG_TAG, "loc6 = " + loc6); + assertEquals(loc6, "0.1"); + + String loc7 = Location.convert(0.1, Location.FORMAT_MINUTES); + Log.i(LOG_TAG, "loc7 = " + loc7); + assertEquals(loc7, "0:6"); + + String loc8 = Location.convert(0.1, Location.FORMAT_SECONDS); + Log.i(LOG_TAG, "loc8 = " + loc8); + assertEquals(loc8, "0:6:0"); + } +} diff --git a/tests/AndroidTests/src/com/android/unit_tests/LogTest.java b/tests/AndroidTests/src/com/android/unit_tests/LogTest.java new file mode 100644 index 0000000..786c4b9 --- /dev/null +++ b/tests/AndroidTests/src/com/android/unit_tests/LogTest.java @@ -0,0 +1,152 @@ +package com.android.unit_tests; + +import junit.framework.Assert; +import junit.framework.TestCase; + +import android.os.SystemProperties; +import android.test.PerformanceTestCase; +import android.test.suitebuilder.annotation.Suppress; +import android.util.Log; + +//This is an empty TestCase. +@Suppress +public class LogTest extends TestCase { + private static final String PROPERTY_TAG = "log.tag.LogTest"; + private static final String LOG_TAG = "LogTest"; + + + // TODO: remove this test once we uncomment out the following test. + public void testLogTestDummy() { + return; + } + + + /* TODO: This test is commented out because we will not be able to set properities. Fix the test. + public void testIsLoggable() { + // First clear any SystemProperty setting for our test key. + SystemProperties.set(PROPERTY_TAG, null); + + String value = SystemProperties.get(PROPERTY_TAG); + Assert.assertTrue(value == null || value.length() == 0); + + // Check to make sure that all levels expect for INFO, WARN, ERROR, and ASSERT are loggable. + Assert.assertFalse(Log.isLoggable(LOG_TAG, Log.VERBOSE)); + Assert.assertFalse(Log.isLoggable(LOG_TAG, Log.DEBUG)); + Assert.assertTrue(Log.isLoggable(LOG_TAG, Log.INFO)); + Assert.assertTrue(Log.isLoggable(LOG_TAG, Log.WARN)); + Assert.assertTrue(Log.isLoggable(LOG_TAG, Log.ERROR)); + Assert.assertTrue(Log.isLoggable(LOG_TAG, Log.ASSERT)); + + // Set the log level to be VERBOSE for this tag. + SystemProperties.set(PROPERTY_TAG, "VERBOSE"); + + // Test to make sure all log levels >= VERBOSE are loggable. + Assert.assertTrue(Log.isLoggable(LOG_TAG, Log.VERBOSE)); + Assert.assertTrue(Log.isLoggable(LOG_TAG, Log.DEBUG)); + Assert.assertTrue(Log.isLoggable(LOG_TAG, Log.INFO)); + Assert.assertTrue(Log.isLoggable(LOG_TAG, Log.WARN)); + Assert.assertTrue(Log.isLoggable(LOG_TAG, Log.ERROR)); + Assert.assertTrue(Log.isLoggable(LOG_TAG, Log.ASSERT)); + + // Set the log level to be DEBUG for this tag. + SystemProperties.set(PROPERTY_TAG, "DEBUG"); + + // Test to make sure all log levels >= DEBUG are loggable. + Assert.assertFalse(Log.isLoggable(LOG_TAG, Log.VERBOSE)); + Assert.assertTrue(Log.isLoggable(LOG_TAG, Log.DEBUG)); + Assert.assertTrue(Log.isLoggable(LOG_TAG, Log.INFO)); + Assert.assertTrue(Log.isLoggable(LOG_TAG, Log.WARN)); + Assert.assertTrue(Log.isLoggable(LOG_TAG, Log.ERROR)); + Assert.assertTrue(Log.isLoggable(LOG_TAG, Log.ASSERT)); + + // Set the log level to be INFO for this tag. + SystemProperties.set(PROPERTY_TAG, "INFO"); + + // Test to make sure all log levels >= INFO are loggable. + Assert.assertFalse(Log.isLoggable(LOG_TAG, Log.VERBOSE)); + Assert.assertFalse(Log.isLoggable(LOG_TAG, Log.DEBUG)); + Assert.assertTrue(Log.isLoggable(LOG_TAG, Log.INFO)); + Assert.assertTrue(Log.isLoggable(LOG_TAG, Log.WARN)); + Assert.assertTrue(Log.isLoggable(LOG_TAG, Log.ERROR)); + Assert.assertTrue(Log.isLoggable(LOG_TAG, Log.ASSERT)); + + // Set the log level to be WARN for this tag. + SystemProperties.set(PROPERTY_TAG, "WARN"); + + // Test to make sure all log levels >= WARN are loggable. + Assert.assertFalse(Log.isLoggable(LOG_TAG, Log.VERBOSE)); + Assert.assertFalse(Log.isLoggable(LOG_TAG, Log.DEBUG)); + Assert.assertFalse(Log.isLoggable(LOG_TAG, Log.INFO)); + Assert.assertTrue(Log.isLoggable(LOG_TAG, Log.WARN)); + Assert.assertTrue(Log.isLoggable(LOG_TAG, Log.ERROR)); + Assert.assertTrue(Log.isLoggable(LOG_TAG, Log.ASSERT)); + + // Set the log level to be ERROR for this tag. + SystemProperties.set(PROPERTY_TAG, "ERROR"); + + // Test to make sure all log levels >= ERROR are loggable. + Assert.assertFalse(Log.isLoggable(LOG_TAG, Log.VERBOSE)); + Assert.assertFalse(Log.isLoggable(LOG_TAG, Log.DEBUG)); + Assert.assertFalse(Log.isLoggable(LOG_TAG, Log.INFO)); + Assert.assertFalse(Log.isLoggable(LOG_TAG, Log.WARN)); + Assert.assertTrue(Log.isLoggable(LOG_TAG, Log.ERROR)); + Assert.assertTrue(Log.isLoggable(LOG_TAG, Log.ASSERT)); + + // Set the log level to be ASSERT for this tag. + SystemProperties.set(PROPERTY_TAG, "ASSERT"); + + // Test to make sure all log levels >= ASSERT are loggable. + Assert.assertFalse(Log.isLoggable(LOG_TAG, Log.VERBOSE)); + Assert.assertFalse(Log.isLoggable(LOG_TAG, Log.DEBUG)); + Assert.assertFalse(Log.isLoggable(LOG_TAG, Log.INFO)); + Assert.assertFalse(Log.isLoggable(LOG_TAG, Log.WARN)); + Assert.assertFalse(Log.isLoggable(LOG_TAG, Log.ERROR)); + Assert.assertTrue(Log.isLoggable(LOG_TAG, Log.ASSERT)); + + // Set the log level to be SUPPRESS for this tag. + SystemProperties.set(PROPERTY_TAG, "SUPPRESS"); + + // Test to make sure all log levels >= ASSERT are loggable. + Assert.assertFalse(Log.isLoggable(LOG_TAG, Log.VERBOSE)); + Assert.assertFalse(Log.isLoggable(LOG_TAG, Log.DEBUG)); + Assert.assertFalse(Log.isLoggable(LOG_TAG, Log.INFO)); + Assert.assertFalse(Log.isLoggable(LOG_TAG, Log.WARN)); + Assert.assertFalse(Log.isLoggable(LOG_TAG, Log.ERROR)); + Assert.assertFalse(Log.isLoggable(LOG_TAG, Log.ASSERT)); + } + */ + + public static class PerformanceTest extends TestCase implements PerformanceTestCase { + private static final int ITERATIONS = 1000; + + @Override + public void setUp() { + SystemProperties.set(LOG_TAG, "VERBOSE"); + } + + public boolean isPerformanceOnly() { + return true; + } + + public int startPerformance(PerformanceTestCase.Intermediates intermediates) { + intermediates.setInternalIterations(ITERATIONS * 10); + return 0; + } + + public void testIsLoggable() { + boolean canLog = false; + for (int i = ITERATIONS - 1; i >= 0; i--) { + canLog = Log.isLoggable(LOG_TAG, Log.VERBOSE); + canLog = Log.isLoggable(LOG_TAG, Log.VERBOSE); + canLog = Log.isLoggable(LOG_TAG, Log.VERBOSE); + canLog = Log.isLoggable(LOG_TAG, Log.VERBOSE); + canLog = Log.isLoggable(LOG_TAG, Log.VERBOSE); + canLog = Log.isLoggable(LOG_TAG, Log.VERBOSE); + canLog = Log.isLoggable(LOG_TAG, Log.VERBOSE); + canLog = Log.isLoggable(LOG_TAG, Log.VERBOSE); + canLog = Log.isLoggable(LOG_TAG, Log.VERBOSE); + canLog = Log.isLoggable(LOG_TAG, Log.VERBOSE); + } + } + } +} diff --git a/tests/AndroidTests/src/com/android/unit_tests/MathTest.java b/tests/AndroidTests/src/com/android/unit_tests/MathTest.java new file mode 100644 index 0000000..caf2d20 --- /dev/null +++ b/tests/AndroidTests/src/com/android/unit_tests/MathTest.java @@ -0,0 +1,380 @@ +/* + * 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.unit_tests; + +import android.test.PerformanceTestBase; +import android.test.PerformanceTestCase; + +/** + * + * Implements basic performance test functionality for java.lang.Math + * + */ + +public class MathTest extends PerformanceTestBase { + public static final int ITERATIONS = 1000; + public static final double sDouble1 = -2450.50; + public static final double sDouble2 = -500; + public static final float sFloat = 300.50f; + public static final int sInt = 90; + + @Override + public int startPerformance(PerformanceTestCase.Intermediates intermediates) { + intermediates.setInternalIterations(ITERATIONS); + return 0; + } + + public void testDoubleAbs() { + double result; + for (int i = ITERATIONS - 1; i >= 0; i--) { + result = Math.abs(sDouble1); + result = Math.abs(sDouble1); + result = Math.abs(sDouble1); + result = Math.abs(sDouble1); + result = Math.abs(sDouble1); + result = Math.abs(sDouble1); + result = Math.abs(sDouble1); + result = Math.abs(sDouble1); + result = Math.abs(sDouble1); + result = Math.abs(sDouble1); + } + } + + public void testFloatAbs() { + float result; + for (int i = ITERATIONS - 1; i >= 0; i--) { + result = Math.abs(sFloat); + result = Math.abs(sFloat); + result = Math.abs(sFloat); + result = Math.abs(sFloat); + result = Math.abs(sFloat); + result = Math.abs(sFloat); + result = Math.abs(sFloat); + result = Math.abs(sFloat); + result = Math.abs(sFloat); + result = Math.abs(sFloat); + } + } + + public void testMathSin() { + double result; + for (int i = ITERATIONS - 1; i >= 0; i--) { + result = Math.sin(sDouble1); + result = Math.sin(sDouble1); + result = Math.sin(sDouble1); + result = Math.sin(sDouble1); + result = Math.sin(sDouble1); + result = Math.sin(sDouble1); + result = Math.sin(sDouble1); + result = Math.sin(sDouble1); + result = Math.sin(sDouble1); + result = Math.sin(sDouble1); + } + } + + public void testMathCos() { + double result; + for (int i = ITERATIONS - 1; i >= 0; i--) { + result = Math.cos(sDouble1); + result = Math.cos(sDouble1); + result = Math.cos(sDouble1); + result = Math.cos(sDouble1); + result = Math.cos(sDouble1); + result = Math.cos(sDouble1); + result = Math.cos(sDouble1); + result = Math.cos(sDouble1); + result = Math.cos(sDouble1); + result = Math.cos(sDouble1); + } + } + + public void testMathTan() { + double result; + for (int i = ITERATIONS - 1; i >= 0; i--) { + result = Math.tan(sDouble1); + result = Math.tan(sDouble1); + result = Math.tan(sDouble1); + result = Math.tan(sDouble1); + result = Math.tan(sDouble1); + result = Math.tan(sDouble1); + result = Math.tan(sDouble1); + result = Math.tan(sDouble1); + result = Math.tan(sDouble1); + result = Math.tan(sDouble1); + } + } + + public void testMathASin() { + double result; + for (int i = ITERATIONS - 1; i >= 0; i--) { + result = Math.asin(sDouble1); + result = Math.asin(sDouble1); + result = Math.asin(sDouble1); + result = Math.asin(sDouble1); + result = Math.asin(sDouble1); + result = Math.asin(sDouble1); + result = Math.asin(sDouble1); + result = Math.asin(sDouble1); + result = Math.asin(sDouble1); + result = Math.asin(sDouble1); + } + } + + public void testMathACos() { + double result; + for (int i = ITERATIONS - 1; i >= 0; i--) { + result = Math.acos(sDouble1); + result = Math.acos(sDouble1); + result = Math.acos(sDouble1); + result = Math.acos(sDouble1); + result = Math.acos(sDouble1); + result = Math.acos(sDouble1); + result = Math.acos(sDouble1); + result = Math.acos(sDouble1); + result = Math.acos(sDouble1); + result = Math.acos(sDouble1); + } + } + + public void testMathATan() { + double result; + for (int i = ITERATIONS - 1; i >= 0; i--) { + result = Math.atan(sDouble1); + result = Math.atan(sDouble1); + result = Math.atan(sDouble1); + result = Math.atan(sDouble1); + result = Math.atan(sDouble1); + result = Math.atan(sDouble1); + result = Math.atan(sDouble1); + result = Math.atan(sDouble1); + result = Math.atan(sDouble1); + result = Math.atan(sDouble1); + } + } + + public void testMathLog() { + double result; + for (int i = ITERATIONS - 1; i >= 0; i--) { + result = Math.log(sDouble1); + result = Math.log(sDouble1); + result = Math.log(sDouble1); + result = Math.log(sDouble1); + result = Math.log(sDouble1); + result = Math.log(sDouble1); + result = Math.log(sDouble1); + result = Math.log(sDouble1); + result = Math.log(sDouble1); + result = Math.log(sDouble1); + } + } + + public void testMathSqrt() { + double result; + for (int i = ITERATIONS - 1; i >= 0; i--) { + result = Math.sqrt(sDouble1); + result = Math.sqrt(sDouble1); + result = Math.sqrt(sDouble1); + result = Math.sqrt(sDouble1); + result = Math.sqrt(sDouble1); + result = Math.sqrt(sDouble1); + result = Math.sqrt(sDouble1); + result = Math.sqrt(sDouble1); + result = Math.sqrt(sDouble1); + result = Math.sqrt(sDouble1); + } + } + + public void testMathCeil() { + double result; + for (int i = ITERATIONS - 1; i >= 0; i--) { + result = Math.ceil(sDouble1); + result = Math.ceil(sDouble1); + result = Math.ceil(sDouble1); + result = Math.ceil(sDouble1); + result = Math.ceil(sDouble1); + result = Math.ceil(sDouble1); + result = Math.ceil(sDouble1); + result = Math.ceil(sDouble1); + result = Math.ceil(sDouble1); + result = Math.ceil(sDouble1); + } + } + + public void testMathRound() { + double result; + for (int i = ITERATIONS - 1; i >= 0; i--) { + result = Math.round(sDouble1); + result = Math.round(sDouble1); + result = Math.round(sDouble1); + result = Math.round(sDouble1); + result = Math.round(sDouble1); + result = Math.round(sDouble1); + result = Math.round(sDouble1); + result = Math.round(sDouble1); + result = Math.round(sDouble1); + result = Math.round(sDouble1); + } + } + + public void testMathFloor() { + double result; + for (int i = ITERATIONS - 1; i >= 0; i--) { + result = Math.floor(sDouble1); + result = Math.floor(sDouble1); + result = Math.floor(sDouble1); + result = Math.floor(sDouble1); + result = Math.floor(sDouble1); + result = Math.floor(sDouble1); + result = Math.floor(sDouble1); + result = Math.floor(sDouble1); + result = Math.floor(sDouble1); + result = Math.floor(sDouble1); + } + } + + public void testMathExp() { + double result; + for (int i = ITERATIONS - 1; i >= 0; i--) { + result = Math.exp(sDouble1); + result = Math.exp(sDouble1); + result = Math.exp(sDouble1); + result = Math.exp(sDouble1); + result = Math.exp(sDouble1); + result = Math.exp(sDouble1); + result = Math.exp(sDouble1); + result = Math.exp(sDouble1); + result = Math.exp(sDouble1); + result = Math.exp(sDouble1); + } + } + + /** + * + */ + + public void testMathPow() { + double result; + for (int i = ITERATIONS - 1; i >= 0; i--) { + result = Math.pow(sDouble1, sDouble2); + result = Math.pow(sDouble1, sDouble2); + result = Math.pow(sDouble1, sDouble2); + result = Math.pow(sDouble1, sDouble2); + result = Math.pow(sDouble1, sDouble2); + result = Math.pow(sDouble1, sDouble2); + result = Math.pow(sDouble1, sDouble2); + result = Math.pow(sDouble1, sDouble2); + result = Math.pow(sDouble1, sDouble2); + result = Math.pow(sDouble1, sDouble2); + } + } + + public void testMathMax() { + double result; + for (int i = ITERATIONS - 1; i >= 0; i--) { + result = Math.max(sDouble1, sDouble2); + result = Math.max(sDouble1, sDouble2); + result = Math.max(sDouble1, sDouble2); + result = Math.max(sDouble1, sDouble2); + result = Math.max(sDouble1, sDouble2); + result = Math.max(sDouble1, sDouble2); + result = Math.max(sDouble1, sDouble2); + result = Math.max(sDouble1, sDouble2); + result = Math.max(sDouble1, sDouble2); + result = Math.max(sDouble1, sDouble2); + } + } + + public void testMathMin() { + double result; + for (int i = ITERATIONS - 1; i >= 0; i--) { + result = Math.min(sDouble1, sDouble2); + result = Math.min(sDouble1, sDouble2); + result = Math.min(sDouble1, sDouble2); + result = Math.min(sDouble1, sDouble2); + result = Math.min(sDouble1, sDouble2); + result = Math.min(sDouble1, sDouble2); + result = Math.min(sDouble1, sDouble2); + result = Math.min(sDouble1, sDouble2); + result = Math.min(sDouble1, sDouble2); + result = Math.min(sDouble1, sDouble2); + } + } + + public void testMathRandom() { + double result; + for (int i = ITERATIONS - 1; i >= 0; i--) { + result = Math.random(); + result = Math.random(); + result = Math.random(); + result = Math.random(); + result = Math.random(); + result = Math.random(); + result = Math.random(); + result = Math.random(); + result = Math.random(); + result = Math.random(); + } + } + + public void testMathIEEERemainder() { + double result; + for (int i = ITERATIONS - 1; i >= 0; i--) { + result = Math.IEEEremainder(sDouble1, sDouble2); + result = Math.IEEEremainder(sDouble1, sDouble2); + result = Math.IEEEremainder(sDouble1, sDouble2); + result = Math.IEEEremainder(sDouble1, sDouble2); + result = Math.IEEEremainder(sDouble1, sDouble2); + result = Math.IEEEremainder(sDouble1, sDouble2); + result = Math.IEEEremainder(sDouble1, sDouble2); + result = Math.IEEEremainder(sDouble1, sDouble2); + result = Math.IEEEremainder(sDouble1, sDouble2); + result = Math.IEEEremainder(sDouble1, sDouble2); + } + } + + public void testMathToDegrees() { + double result; + for (int i = ITERATIONS - 1; i >= 0; i--) { + result = Math.toDegrees(sDouble1); + result = Math.toDegrees(sDouble1); + result = Math.toDegrees(sDouble1); + result = Math.toDegrees(sDouble1); + result = Math.toDegrees(sDouble1); + result = Math.toDegrees(sDouble1); + result = Math.toDegrees(sDouble1); + result = Math.toDegrees(sDouble1); + result = Math.toDegrees(sDouble1); + result = Math.toDegrees(sDouble1); + } + } + + public void testMathToRadians() { + double result; + for (int i = ITERATIONS - 1; i >= 0; i--) { + result = Math.toRadians(sDouble1); + result = Math.toRadians(sDouble1); + result = Math.toRadians(sDouble1); + result = Math.toRadians(sDouble1); + result = Math.toRadians(sDouble1); + result = Math.toRadians(sDouble1); + result = Math.toRadians(sDouble1); + result = Math.toRadians(sDouble1); + result = Math.toRadians(sDouble1); + result = Math.toRadians(sDouble1); + } + } +} diff --git a/tests/AndroidTests/src/com/android/unit_tests/MenuTest.java b/tests/AndroidTests/src/com/android/unit_tests/MenuTest.java new file mode 100644 index 0000000..c436726 --- /dev/null +++ b/tests/AndroidTests/src/com/android/unit_tests/MenuTest.java @@ -0,0 +1,277 @@ +/* + * 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.unit_tests; + +import com.android.internal.view.menu.MenuBuilder; + +import junit.framework.Assert; + +import android.test.AndroidTestCase; +import android.test.MoreAsserts; +import android.test.suitebuilder.annotation.LargeTest; +import android.test.suitebuilder.annotation.SmallTest; +import android.view.KeyEvent; +import android.view.Menu; +import android.view.MenuItem; +import android.view.SubMenu; + +public class MenuTest extends AndroidTestCase { + + private MenuBuilder mMenu; + + public void setUp() throws Exception { + super.setUp(); + mMenu = new MenuBuilder(super.getContext()); + } + + @SmallTest + public void testItemId() { + final int id = 512; + final MenuItem item = mMenu.add(0, id, 0, "test"); + + Assert.assertEquals(id, item.getItemId()); + Assert.assertEquals(item, mMenu.findItem(id)); + Assert.assertEquals(0, mMenu.findItemIndex(id)); + } + + @SmallTest + public void testGroupId() { + final int groupId = 541; + final int item1Index = 1; + final int item2Index = 3; + + mMenu.add(0, 0, item1Index - 1, "ignore"); + final MenuItem item = mMenu.add(groupId, 0, item1Index, "test"); + mMenu.add(0, 0, item2Index - 1, "ignore"); + final MenuItem item2 = mMenu.add(groupId, 0, item2Index, "test2"); + + Assert.assertEquals(groupId, item.getGroupId()); + Assert.assertEquals(groupId, item2.getGroupId()); + Assert.assertEquals(item1Index, mMenu.findGroupIndex(groupId)); + Assert.assertEquals(item2Index, mMenu.findGroupIndex(groupId, item1Index + 1)); + } + + @SmallTest + public void testGroup() { + // This test does the following + // 1. Create a grouped item in the menu + // 2. Check that findGroupIndex() finds the grouped item. + // 3. Check that findGroupIndex() doesn't find a non-existent group. + + final int GROUP_ONE = Menu.FIRST; + final int GROUP_TWO = Menu.FIRST + 1; + + mMenu.add(GROUP_ONE, 0, 0, "Menu text"); + Assert.assertEquals(mMenu.findGroupIndex(GROUP_ONE), 0); + Assert.assertEquals(mMenu.findGroupIndex(GROUP_TWO), -1); + //TODO: expand this test case to do multiple groups, + //adding and removing, hiding and showing, etc. + } + + @SmallTest + public void testIsShortcutWithAlpha() throws Exception { + mMenu.setQwertyMode(true); + mMenu.add(0, 0, 0, "test").setShortcut('2', 'a'); + Assert.assertTrue(mMenu.isShortcutKey(KeyEvent.KEYCODE_A, + makeKeyEvent(KeyEvent.KEYCODE_A, 0))); + Assert.assertFalse(mMenu.isShortcutKey(KeyEvent.KEYCODE_B, + makeKeyEvent(KeyEvent.KEYCODE_B, 0))); + } + + @SmallTest + public void testIsShortcutWithNumeric() throws Exception { + mMenu.setQwertyMode(false); + mMenu.add(0, 0, 0, "test").setShortcut('2', 'a'); + Assert.assertTrue(mMenu.isShortcutKey(KeyEvent.KEYCODE_2, + makeKeyEvent(KeyEvent.KEYCODE_2, 0))); + Assert.assertFalse(mMenu.isShortcutKey(KeyEvent.KEYCODE_A, + makeKeyEvent(KeyEvent.KEYCODE_A, 0))); + } + + @SmallTest + public void testIsShortcutWithAlt() throws Exception { + mMenu.setQwertyMode(true); + mMenu.add(0, 0, 0, "test").setShortcut('2', 'a'); + Assert.assertTrue(mMenu.isShortcutKey(KeyEvent.KEYCODE_A, + makeKeyEvent(KeyEvent.KEYCODE_A, + KeyEvent.META_ALT_ON))); + Assert.assertFalse(mMenu.isShortcutKey(KeyEvent.KEYCODE_A, + makeKeyEvent(KeyEvent.KEYCODE_A, + KeyEvent.META_SYM_ON))); + } + + @SmallTest + public void testIsNotShortcutWithShift() throws Exception { + mMenu.setQwertyMode(true); + mMenu.add(0, 0, 0, "test").setShortcut('2', 'a'); + Assert.assertFalse(mMenu.isShortcutKey(KeyEvent.KEYCODE_A, + makeKeyEvent(KeyEvent.KEYCODE_A, + KeyEvent.META_SHIFT_ON))); + } + + @SmallTest + public void testIsNotShortcutWithSym() throws Exception { + mMenu.setQwertyMode(true); + mMenu.add(0, 0, 0, "test").setShortcut('2', 'a'); + Assert.assertFalse(mMenu.isShortcutKey(KeyEvent.KEYCODE_A, + makeKeyEvent(KeyEvent.KEYCODE_A, + KeyEvent.META_SYM_ON))); + } + + @SmallTest + public void testIsShortcutWithUpperCaseAlpha() throws Exception { + mMenu.setQwertyMode(true); + mMenu.add(0, 0, 0, "test").setShortcut('2', 'A'); + Assert.assertTrue(mMenu.isShortcutKey(KeyEvent.KEYCODE_A, + makeKeyEvent(KeyEvent.KEYCODE_A, 0))); + } + + @SmallTest + public void testIsShortcutWithBackspace() throws Exception { + mMenu.setQwertyMode(true); + mMenu.add(0, 0, 0, "test").setShortcut('2', '\b'); + Assert.assertTrue(mMenu.isShortcutKey(KeyEvent.KEYCODE_DEL, + makeKeyEvent(KeyEvent.KEYCODE_DEL, 0))); + } + + @SmallTest + public void testIsShortcutWithNewline() throws Exception { + mMenu.setQwertyMode(true); + mMenu.add(0, 0, 0, "test").setShortcut('2', '\n'); + Assert.assertTrue(mMenu.isShortcutKey(KeyEvent.KEYCODE_ENTER, + makeKeyEvent(KeyEvent.KEYCODE_ENTER, 0))); + } + + @SmallTest + public void testOrder() { + final String a = "a", b = "b", c = "c"; + final int firstOrder = 7, midOrder = 8, lastOrder = 9; + + mMenu.add(0, 0, lastOrder, c); + mMenu.add(0, 0, firstOrder, a); + mMenu.add(0, 0, midOrder, b); + + Assert.assertEquals(firstOrder, mMenu.getItem(0).getOrder()); + Assert.assertEquals(a, mMenu.getItem(0).getTitle()); + Assert.assertEquals(midOrder, mMenu.getItem(1).getOrder()); + Assert.assertEquals(b, mMenu.getItem(1).getTitle()); + Assert.assertEquals(lastOrder, mMenu.getItem(2).getOrder()); + Assert.assertEquals(c, mMenu.getItem(2).getTitle()); + } + + @SmallTest + public void testTitle() { + final String title = "test"; + final MenuItem stringItem = mMenu.add(title); + final MenuItem resItem = mMenu.add(R.string.menu_test); + + Assert.assertEquals(title, stringItem.getTitle()); + Assert.assertEquals(getContext().getResources().getString(R.string.menu_test), resItem + .getTitle()); + } + + @SmallTest + public void testCheckable() { + final int groupId = 1; + final MenuItem item1 = mMenu.add(groupId, 1, 0, "item1"); + final MenuItem item2 = mMenu.add(groupId, 2, 0, "item2"); + + // Set to exclusive + mMenu.setGroupCheckable(groupId, true, true); + Assert.assertTrue("Item was not set to checkable", item1.isCheckable()); + item1.setChecked(true); + Assert.assertTrue("Item did not get checked", item1.isChecked()); + Assert.assertFalse("Item was not unchecked due to exclusive checkable", item2.isChecked()); + mMenu.findItem(2).setChecked(true); + Assert.assertTrue("Item did not get checked", item2.isChecked()); + Assert.assertFalse("Item was not unchecked due to exclusive checkable", item1.isChecked()); + + // Multiple non-exlusive checkable items + mMenu.setGroupCheckable(groupId, true, false); + Assert.assertTrue("Item was not set to checkable", item1.isCheckable()); + item1.setChecked(false); + Assert.assertFalse("Item did not get unchecked", item1.isChecked()); + item1.setChecked(true); + Assert.assertTrue("Item did not get checked", item1.isChecked()); + mMenu.findItem(2).setChecked(true); + Assert.assertTrue("Item did not get checked", item2.isChecked()); + Assert.assertTrue("Item was unchecked when it shouldnt have been", item1.isChecked()); + } + + @SmallTest + public void testVisibility() { + final MenuItem item1 = mMenu.add(0, 1, 0, "item1"); + final MenuItem item2 = mMenu.add(0, 2, 0, "item2"); + + // Should start as visible + Assert.assertTrue("Item did not start as visible", item1.isVisible()); + Assert.assertTrue("Item did not start as visible", item2.isVisible()); + + // Hide + item1.setVisible(false); + Assert.assertFalse("Item did not become invisible", item1.isVisible()); + mMenu.findItem(2).setVisible(false); + Assert.assertFalse("Item did not become invisible", item2.isVisible()); + } + + @SmallTest + public void testSubMenu() { + final SubMenu subMenu = mMenu.addSubMenu(0, 0, 0, "submenu"); + final MenuItem subMenuItem = subMenu.getItem(); + final MenuItem item1 = subMenu.add(0, 1, 0, "item1"); + final MenuItem item2 = subMenu.add(0, 2, 0, "item2"); + + // findItem should recurse into submenus + Assert.assertEquals(item1, mMenu.findItem(1)); + Assert.assertEquals(item2, mMenu.findItem(2)); + } + + @SmallTest + public void testRemove() { + final int groupId = 1; + final MenuItem item1 = mMenu.add(groupId, 1, 0, "item1"); + final MenuItem item2 = mMenu.add(groupId, 2, 0, "item2"); + final MenuItem item3 = mMenu.add(groupId, 3, 0, "item3"); + final MenuItem item4 = mMenu.add(groupId, 4, 0, "item4"); + final MenuItem item5 = mMenu.add(groupId, 5, 0, "item5"); + final MenuItem item6 = mMenu.add(0, 6, 0, "item6"); + + Assert.assertEquals(item1, mMenu.findItem(1)); + mMenu.removeItemAt(0); + Assert.assertNull(mMenu.findItem(1)); + + Assert.assertEquals(item2, mMenu.findItem(2)); + mMenu.removeItem(2); + Assert.assertNull(mMenu.findItem(2)); + + Assert.assertEquals(item3, mMenu.findItem(3)); + Assert.assertEquals(item4, mMenu.findItem(4)); + Assert.assertEquals(item5, mMenu.findItem(5)); + mMenu.removeGroup(groupId); + Assert.assertNull(mMenu.findItem(3)); + Assert.assertNull(mMenu.findItem(4)); + Assert.assertNull(mMenu.findItem(5)); + + Assert.assertEquals(item6, mMenu.findItem(6)); + mMenu.clear(); + Assert.assertNull(mMenu.findItem(6)); + } + + private KeyEvent makeKeyEvent(int keyCode, int metaState) { + return new KeyEvent(0L, 0L, KeyEvent.ACTION_DOWN, keyCode, 0, metaState); + } +} diff --git a/tests/AndroidTests/src/com/android/unit_tests/MonitorTest.java b/tests/AndroidTests/src/com/android/unit_tests/MonitorTest.java new file mode 100644 index 0000000..2f3df10 --- /dev/null +++ b/tests/AndroidTests/src/com/android/unit_tests/MonitorTest.java @@ -0,0 +1,469 @@ +/* + * 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.unit_tests; + +import junit.framework.TestCase; +import android.test.suitebuilder.annotation.MediumTest; +import android.test.suitebuilder.annotation.LargeTest; +import android.test.suitebuilder.annotation.SmallTest; + +public class MonitorTest extends TestCase { + + @MediumTest + public void testWaitArgumentsTest() throws Exception { + /* Try some valid arguments. These should all + * return very quickly. + */ + try { + synchronized (this) { + /* millisecond version */ + wait(1); + wait(10); + + /* millisecond + nanosecond version */ + wait(0, 1); + wait(0, 999999); + wait(1, 1); + wait(1, 999999); + } + } catch (InterruptedException ex) { + throw new RuntimeException("good Object.wait() interrupted", + ex); + } catch (Exception ex) { + throw new RuntimeException("Unexpected exception when calling" + + "Object.wait() with good arguments", ex); + } + + /* Try some invalid arguments. + */ + boolean sawException = false; + try { + synchronized (this) { + wait(-1); + } + } catch (InterruptedException ex) { + throw new RuntimeException("bad Object.wait() interrupted", ex); + } catch (IllegalArgumentException ex) { + sawException = true; + } catch (Exception ex) { + throw new RuntimeException("Unexpected exception when calling" + + "Object.wait() with bad arguments", ex); + } + if (!sawException) { + throw new RuntimeException("bad call to Object.wait() should " + + "have thrown IllegalArgumentException"); + } + + sawException = false; + try { + synchronized (this) { + wait(0, -1); + } + } catch (InterruptedException ex) { + throw new RuntimeException("bad Object.wait() interrupted", ex); + } catch (IllegalArgumentException ex) { + sawException = true; + } catch (Exception ex) { + throw new RuntimeException("Unexpected exception when calling" + + "Object.wait() with bad arguments", ex); + } + if (!sawException) { + throw new RuntimeException("bad call to Object.wait() should " + + "have thrown IllegalArgumentException"); + } + + sawException = false; + try { + synchronized (this) { + /* The legal range of nanos is 0-999999. */ + wait(0, 1000000); + } + } catch (InterruptedException ex) { + throw new RuntimeException("bad Object.wait() interrupted", ex); + } catch (IllegalArgumentException ex) { + sawException = true; + } catch (Exception ex) { + throw new RuntimeException("Unexpected exception when calling" + + "Object.wait() with bad arguments", ex); + } + if (!sawException) { + throw new RuntimeException("bad call to Object.wait() should " + + "have thrown IllegalArgumentException"); + } + } + + private class Interrupter extends Thread { + Waiter waiter; + + Interrupter(String name, Waiter waiter) { + super(name); + this.waiter = waiter; + } + + public void run() { + try { + run_inner(); + } catch (Throwable t) { + MonitorTest.errorException = t; + MonitorTest.testThread.interrupt(); + } + } + + void run_inner() { + waiter.spin = true; + // System.out.println("InterruptTest: starting waiter"); + waiter.start(); + + try { + Thread.currentThread().sleep(500); + } catch (InterruptedException ex) { + throw new RuntimeException("Test sleep interrupted.", ex); + } + + /* Waiter is spinning, and its monitor should still be thin. + */ + // System.out.println("Test interrupting waiter"); + waiter.interrupt(); + waiter.spin = false; + + for (int i = 0; i < 3; i++) { + /* Wait for the waiter to start waiting. + */ + synchronized (waiter.interrupterLock) { + try { + waiter.interrupterLock.wait(); + } catch (InterruptedException ex) { + throw new RuntimeException("Test wait interrupted.", ex); + } + } + + /* Before interrupting, grab the waiter lock, which + * guarantees that the waiter is already sitting in wait(). + */ + synchronized (waiter) { + //System.out.println("Test interrupting waiter (" + i + ")"); + waiter.interrupt(); + } + } + + // System.out.println("Test waiting for waiter to die."); + try { + waiter.join(); + } catch (InterruptedException ex) { + throw new RuntimeException("Test join interrupted.", ex); + } + // System.out.println("InterruptTest done."); + } + } + + private class Waiter extends Thread { + Object interrupterLock = new Object(); + Boolean spin = false; + + Waiter(String name) { + super(name); + } + + public void run() { + try { + run_inner(); + } catch (Throwable t) { + MonitorTest.errorException = t; + MonitorTest.testThread.interrupt(); + } + } + + void run_inner() { + // System.out.println("Waiter spinning"); + while (spin) { + // We're going to get interrupted while we spin. + } + if (interrupted()) { + // System.out.println("Waiter done spinning; interrupted."); + } else { + throw new RuntimeException("Thread not interrupted " + + "during spin"); + } + + synchronized (this) { + Boolean sawEx = false; + + try { + synchronized (interrupterLock) { + interrupterLock.notify(); + } + // System.out.println("Waiter calling wait()"); + this.wait(); + } catch (InterruptedException ex) { + sawEx = true; + // System.out.println("wait(): Waiter caught " + ex); + } + // System.out.println("wait() finished"); + + if (!sawEx) { + throw new RuntimeException("Thread not interrupted " + + "during wait()"); + } + } + synchronized (this) { + Boolean sawEx = false; + + try { + synchronized (interrupterLock) { + interrupterLock.notify(); + } + // System.out.println("Waiter calling wait(1000)"); + this.wait(1000); + } catch (InterruptedException ex) { + sawEx = true; + // System.out.println("wait(1000): Waiter caught " + ex); + } + // System.out.println("wait(1000) finished"); + + if (!sawEx) { + throw new RuntimeException("Thread not interrupted " + + "during wait(1000)"); + } + } + synchronized (this) { + Boolean sawEx = false; + + try { + synchronized (interrupterLock) { + interrupterLock.notify(); + } + // System.out.println("Waiter calling wait(1000, 5000)"); + this.wait(1000, 5000); + } catch (InterruptedException ex) { + sawEx = true; + // System.out.println("wait(1000, 5000): Waiter caught " + ex); + } + // System.out.println("wait(1000, 5000) finished"); + + if (!sawEx) { + throw new RuntimeException("Thread not interrupted " + + "during wait(1000, 5000)"); + } + } + + // System.out.println("Waiter returning"); + } + } + + private static Throwable errorException; + private static Thread testThread; + + @MediumTest + public void testInterruptTest() throws Exception { + + + testThread = Thread.currentThread(); + errorException = null; + + Waiter waiter = new Waiter("InterruptTest Waiter"); + Interrupter interrupter = + new Interrupter("InterruptTest Interrupter", waiter); + interrupter.start(); + + try { + interrupter.join(); + waiter.join(); + } catch (InterruptedException ex) { + throw new RuntimeException("Test join interrupted.", ex); + } + + if (errorException != null) { + throw new RuntimeException("InterruptTest failed", + errorException); + } + + + + + } + + private static void deepWait(int depth, Object lock) { + synchronized (lock) { + if (depth > 0) { + deepWait(depth - 1, lock); + } else { + String threadName = Thread.currentThread().getName(); + try { + // System.out.println(threadName + " waiting"); + lock.wait(); + // System.out.println(threadName + " done waiting"); + } catch (InterruptedException ex) { + // System.out.println(threadName + " interrupted."); + } + } + } + } + + private class Worker extends Thread { + Object lock; + int id; + + Worker(int id, Object lock) { + super("Worker(" + id + ")"); + this.id = id; + this.lock = lock; + } + + public void run() { + int iterations = 0; + + while (MonitorTest.running) { + MonitorTest.deepWait(id, lock); + iterations++; + } + // System.out.println(getName() + " done after " + iterations + " iterations."); + } + } + + private static Object commonLock = new Object(); + private static Boolean running = false; + + + @LargeTest + public void testNestedMonitors() throws Exception { + final int NUM_WORKERS = 5; + + Worker w[] = new Worker[NUM_WORKERS]; + int i; + + for (i = 0; i < NUM_WORKERS; i++) { + w[i] = new Worker(i * 2 - 1, new Object()); + } + + running = true; + + // System.out.println("NestedMonitors: starting workers"); + for (i = 0; i < NUM_WORKERS; i++) { + w[i].start(); + } + + try { + Thread.currentThread().sleep(1000); + } catch (InterruptedException ex) { + // System.out.println("Test sleep interrupted."); + } + + for (i = 0; i < 100; i++) { + for (int j = 0; j < NUM_WORKERS; j++) { + synchronized (w[j].lock) { + w[j].lock.notify(); + } + } + } + + // System.out.println("NesterMonitors: stopping workers"); + running = false; + for (i = 0; i < NUM_WORKERS; i++) { + synchronized (w[i].lock) { + w[i].lock.notifyAll(); + } + } + } + + private static class CompareAndExchange extends Thread { + static Object toggleLock = null; + static int toggle = -1; + static Boolean running = false; + + public void run() { + toggleLock = new Object(); + toggle = -1; + + Worker w1 = new Worker(0, 1); + Worker w2 = new Worker(2, 3); + Worker w3 = new Worker(4, 5); + Worker w4 = new Worker(6, 7); + + running = true; + + // System.out.println("CompareAndExchange: starting workers"); + + w1.start(); + w2.start(); + w3.start(); + w4.start(); + + try { + this.sleep(10000); + } catch (InterruptedException ex) { + // System.out.println(getName() + " interrupted."); + } + + // System.out.println("MonitorTest: stopping workers"); + running = false; + + toggleLock = null; + } + + class Worker extends Thread { + int i1; + int i2; + + Worker(int i1, int i2) { + super("Worker(" + i1 + ", " + i2 + ")"); + this.i1 = i1; + this.i2 = i2; + } + + public void run() { + int iterations = 0; + + /* Latch this because run() may set the static field to + * null at some point. + */ + Object toggleLock = CompareAndExchange.toggleLock; + + // System.out.println(getName() + " running"); + try { + while (CompareAndExchange.running) { + synchronized (toggleLock) { + int test; + int check; + + if (CompareAndExchange.toggle == i1) { + this.sleep(5 + i2); + CompareAndExchange.toggle = test = i2; + } else { + this.sleep(5 + i1); + CompareAndExchange.toggle = test = i1; + } + if ((check = CompareAndExchange.toggle) != test) { +// System.out.println("Worker(" + i1 + ", " + +// i2 + ") " + "test " + test + +// " != toggle " + check); + throw new RuntimeException( + "locked value changed"); + } + } + + iterations++; + } + } catch (InterruptedException ex) { + // System.out.println(getName() + " interrupted."); + } + +// System.out.println(getName() + " done after " + +// iterations + " iterations."); + } + } + } +} diff --git a/tests/AndroidTests/src/com/android/unit_tests/NewDatabasePerformanceTestSuite.java b/tests/AndroidTests/src/com/android/unit_tests/NewDatabasePerformanceTestSuite.java new file mode 100644 index 0000000..3462f97 --- /dev/null +++ b/tests/AndroidTests/src/com/android/unit_tests/NewDatabasePerformanceTestSuite.java @@ -0,0 +1,94 @@ +/* + * Copyright (C) 2005 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.unit_tests; +import android.test.FrameworkTests; +import android.test.suitebuilder.TestSuiteBuilder; + +import junit.framework.TestSuite; +import junit.framework.TestCase; + +public class NewDatabasePerformanceTestSuite extends TestSuite { + public static TestSuite suite() { + TestSuite suite = + new TestSuite(NewDatabasePerformanceTestSuite.class.getName()); + + suite.addTestSuite(NewDatabasePerformanceTests. + Insert1000.class); + suite.addTestSuite(NewDatabasePerformanceTests. + InsertIndexed1000.class); + suite.addTestSuite(NewDatabasePerformanceTests. + Select100.class); + suite.addTestSuite(NewDatabasePerformanceTests. + SelectStringComparison100.class); + suite.addTestSuite(NewDatabasePerformanceTests. + SelectIndex100.class); + suite.addTestSuite(NewDatabasePerformanceTests. + InnerJoin100.class); + suite.addTestSuite(NewDatabasePerformanceTests. + InnerJoinOneSide100.class); + suite.addTestSuite(NewDatabasePerformanceTests. + InnerJoinNoIndex100.class); + suite.addTestSuite(NewDatabasePerformanceTests. + SelectSubQIndex100.class); + suite.addTestSuite(NewDatabasePerformanceTests. + SelectIndexStringComparison100.class); + suite.addTestSuite(NewDatabasePerformanceTests. + SelectInteger100.class); + suite.addTestSuite(NewDatabasePerformanceTests. + SelectString100.class); + suite.addTestSuite(NewDatabasePerformanceTests. + SelectIntegerIndex100.class); + suite.addTestSuite(NewDatabasePerformanceTests. + SelectIndexString100.class); + suite.addTestSuite(NewDatabasePerformanceTests. + SelectStringStartsWith100.class); + suite.addTestSuite(NewDatabasePerformanceTests. + DeleteIndexed1000.class); + suite.addTestSuite(NewDatabasePerformanceTests. + Delete1000.class); + suite.addTestSuite(NewDatabasePerformanceTests. + DeleteWhere1000.class); + suite.addTestSuite(NewDatabasePerformanceTests. + DeleteIndexWhere1000.class); + suite.addTestSuite(NewDatabasePerformanceTests. + UpdateIndexWhere1000.class); + suite.addTestSuite(NewDatabasePerformanceTests. + UpdateWhere1000.class); + suite.addTestSuite(NewDatabasePerformanceTests. + InsertInteger10000.class); + suite.addTestSuite(NewDatabasePerformanceTests. + InsertIntegerIndex10000.class); + suite.addTestSuite(NewDatabasePerformanceTests. + InsertString10000.class); + suite.addTestSuite(NewDatabasePerformanceTests. + InsertStringIndexed10000.class); + suite.addTestSuite(NewDatabasePerformanceTests. + SelectStringStartsWith10000.class); + suite.addTestSuite(NewDatabasePerformanceTests. + SelectStringIndexedStartsWith10000.class); + suite.addTestSuite(NewDatabasePerformanceTests. + SelectInteger10000.class); + suite.addTestSuite(NewDatabasePerformanceTests. + SelectIntegerIndexed10000.class); + suite.addTestSuite(NewDatabasePerformanceTests. + SelectStringContains10000.class); + suite.addTestSuite(NewDatabasePerformanceTests. + SelectStringIndexedContains10000.class); + + return suite; + } +} diff --git a/tests/AndroidTests/src/com/android/unit_tests/NewDatabasePerformanceTests.java b/tests/AndroidTests/src/com/android/unit_tests/NewDatabasePerformanceTests.java new file mode 100644 index 0000000..8644fbb --- /dev/null +++ b/tests/AndroidTests/src/com/android/unit_tests/NewDatabasePerformanceTests.java @@ -0,0 +1,1234 @@ +/* + * 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.unit_tests; + +import android.content.ContentValues; +import android.database.sqlite.SQLiteDatabase; +import android.test.PerformanceTestCase; + +import junit.framework.Assert; +import junit.framework.TestCase; + +import java.io.File; +import java.util.Random; + +/** + * Database Performance Tests + * + */ + +public class NewDatabasePerformanceTests { + + // Edit this to change the test run times. The original is 100. + final static int kMultiplier = 1; + + public static class PerformanceBase extends TestCase + implements PerformanceTestCase { + protected static final int CURRENT_DATABASE_VERSION = 42; + protected SQLiteDatabase mDatabase; + protected File mDatabaseFile; + + public void setUp() { + mDatabaseFile = new File("/sdcard", "perf_database_test.db"); + if (mDatabaseFile.exists()) { + mDatabaseFile.delete(); + } + mDatabase = + SQLiteDatabase.openOrCreateDatabase(mDatabaseFile.getPath(), + null); + assertTrue(mDatabase != null); + mDatabase.setVersion(CURRENT_DATABASE_VERSION); + } + + public void tearDown() { + mDatabase.close(); + mDatabaseFile.delete(); + } + + public boolean isPerformanceOnly() { + return true; + } + + // These tests can only be run once. + public int startPerformance(Intermediates intermediates) { + return 0; + } + + public String numberName(int number) { + String result = ""; + + if (number >= 1000) { + result += numberName((number / 1000)) + " thousand"; + number = (number % 1000); + + if (number > 0) result += " "; + } + + if (number >= 100) { + result += ONES[(number / 100)] + " hundred"; + number = (number % 100); + + if (number > 0) result += " "; + } + + if (number >= 20) { + result += TENS[(number / 10)]; + number = (number % 10); + + if (number > 0) result += " "; + } + + if (number > 0) { + result += ONES[number]; + } + + return result; + } + } + + /** + * Test 1000 inserts. + */ + + public static class Insert1000 extends PerformanceBase { + private static final int SIZE = 10 * kMultiplier; + + private String[] statements = new String[SIZE]; + + @Override + public void setUp() { + super.setUp(); + Random random = new Random(42); + + for (int i = 0; i < SIZE; i++) { + int r = random.nextInt(100000); + statements[i] = + "INSERT INTO t1 VALUES(" + i + "," + r + ",'" + + numberName(r) + "')"; + } + + mDatabase + .execSQL("CREATE TABLE t1(a INTEGER, b INTEGER, c VARCHAR(100))"); + } + + public void testRun() { + for (int i = 0; i < SIZE; i++) { + mDatabase.execSQL(statements[i]); + } + } + } + + /** + * Test 1000 inserts into an indexed table. + */ + + public static class InsertIndexed1000 extends PerformanceBase { + private static final int SIZE = 10 * kMultiplier; + + private String[] statements = new String[SIZE]; + + @Override + public void setUp() { + super.setUp(); + Random random = new Random(42); + + for (int i = 0; i < SIZE; i++) { + int r = random.nextInt(100000); + statements[i] = + "INSERT INTO t1 VALUES(" + i + "," + r + ",'" + + numberName(r) + "')"; + } + + mDatabase + .execSQL("CREATE TABLE t1(a INTEGER, b INTEGER, c VARCHAR(100))"); + mDatabase.execSQL("CREATE INDEX i1c ON t1(c)"); + } + + public void testRun() { + for (int i = 0; i < SIZE; i++) { + mDatabase.execSQL(statements[i]); + } + } + } + + /** + * 100 SELECTs without an index + */ + + public static class Select100 extends PerformanceBase { + private static final int SIZE = 1 * kMultiplier; + private static final String[] COLUMNS = {"count(*)", "avg(b)"}; + + private String[] where = new String[SIZE]; + + @Override + public void setUp() { + super.setUp(); + Random random = new Random(42); + + mDatabase + .execSQL("CREATE TABLE t1(a INTEGER, b INTEGER, c VARCHAR(100))"); + + for (int i = 0; i < SIZE; i++) { + int r = random.nextInt(100000); + mDatabase.execSQL("INSERT INTO t1 VALUES(" + i + "," + r + ",'" + + numberName(r) + "')"); + } + + for (int i = 0; i < SIZE; i++) { + int lower = i * 100; + int upper = (i + 10) * 100; + where[i] = "b >= " + lower + " AND b < " + upper; + } + } + + public void testRun() { + for (int i = 0; i < SIZE; i++) { + mDatabase + .query("t1", COLUMNS, where[i], null, null, null, null); + } + } + } + + /** + * 100 SELECTs on a string comparison + */ + + public static class SelectStringComparison100 extends PerformanceBase { + private static final int SIZE = 1 * kMultiplier; + private static final String[] COLUMNS = {"count(*)", "avg(b)"}; + + private String[] where = new String[SIZE]; + + @Override + public void setUp() { + super.setUp(); + Random random = new Random(42); + + mDatabase + .execSQL("CREATE TABLE t1(a INTEGER, b INTEGER, c VARCHAR(100))"); + + for (int i = 0; i < SIZE; i++) { + int r = random.nextInt(100000); + mDatabase.execSQL("INSERT INTO t1 VALUES(" + i + "," + r + ",'" + + numberName(r) + "')"); + } + + for (int i = 0; i < SIZE; i++) { + where[i] = "c LIKE '" + numberName(i) + "'"; + } + } + + public void testRun() { + for (int i = 0; i < SIZE; i++) { + mDatabase + .query("t1", COLUMNS, where[i], null, null, null, null); + } + } + } + + /** + * 100 SELECTs with an index + */ + + public static class SelectIndex100 extends PerformanceBase { + private static final int SIZE = 1 * kMultiplier; + private static final String[] COLUMNS = {"count(*)", "avg(b)"}; + + private String[] where = new String[SIZE]; + + @Override + public void setUp() { + super.setUp(); + Random random = new Random(42); + + mDatabase + .execSQL("CREATE TABLE t1(a INTEGER, b INTEGER, c VARCHAR(100))"); + mDatabase.execSQL("CREATE INDEX i1b ON t1(b)"); + + for (int i = 0; i < SIZE; i++) { + int r = random.nextInt(100000); + mDatabase.execSQL("INSERT INTO t1 VALUES(" + i + "," + r + ",'" + + numberName(r) + "')"); + } + + for (int i = 0; i < SIZE; i++) { + int lower = i * 100; + int upper = (i + 10) * 100; + where[i] = "b >= " + lower + " AND b < " + upper; + } + } + + public void testRun() { + for (int i = 0; i < SIZE; i++) { + mDatabase + .query("t1", COLUMNS, where[i], null, null, null, null); + } + } + } + + /** + * INNER JOIN without an index + */ + + public static class InnerJoin100 extends PerformanceBase { + private static final int SIZE = 1 * kMultiplier; + private static final String[] COLUMNS = {"t1.a"}; + + @Override + public void setUp() { + super.setUp(); + Random random = new Random(42); + + mDatabase + .execSQL("CREATE TABLE t1(a INTEGER, b INTEGER, c VARCHAR(100))"); + mDatabase + .execSQL("CREATE TABLE t2(a INTEGER, b INTEGER, c VARCHAR(100))"); + + for (int i = 0; i < SIZE; i++) { + int r = random.nextInt(100000); + mDatabase.execSQL("INSERT INTO t1 VALUES(" + i + "," + r + ",'" + + numberName(r) + "')"); + } + + for (int i = 0; i < SIZE; i++) { + int r = random.nextInt(100000); + mDatabase.execSQL("INSERT INTO t2 VALUES(" + i + "," + r + ",'" + + numberName(r) + "')"); + } + } + + public void testRun() { + mDatabase.query("t1 INNER JOIN t2 ON t1.b = t2.b", COLUMNS, null, + null, null, null, null); + } + } + + /** + * INNER JOIN without an index on one side + */ + + public static class InnerJoinOneSide100 extends PerformanceBase { + private static final int SIZE = 1 * kMultiplier; + private static final String[] COLUMNS = {"t1.a"}; + + @Override + public void setUp() { + super.setUp(); + Random random = new Random(42); + + mDatabase + .execSQL("CREATE TABLE t1(a INTEGER, b INTEGER, c VARCHAR(100))"); + mDatabase + .execSQL("CREATE TABLE t2(a INTEGER, b INTEGER, c VARCHAR(100))"); + + mDatabase.execSQL("CREATE INDEX i1b ON t1(b)"); + + for (int i = 0; i < SIZE; i++) { + int r = random.nextInt(100000); + mDatabase.execSQL("INSERT INTO t1 VALUES(" + i + "," + r + ",'" + + numberName(r) + "')"); + } + + for (int i = 0; i < SIZE; i++) { + int r = random.nextInt(100000); + mDatabase.execSQL("INSERT INTO t2 VALUES(" + i + "," + r + ",'" + + numberName(r) + "')"); + } + } + + public void testRun() { + mDatabase.query("t1 INNER JOIN t2 ON t1.b = t2.b", COLUMNS, null, + null, null, null, null); + } + } + + /** + * INNER JOIN without an index on one side + */ + + public static class InnerJoinNoIndex100 extends PerformanceBase { + private static final int SIZE = 1 * kMultiplier; + private static final String[] COLUMNS = {"t1.a"}; + + @Override + public void setUp() { + super.setUp(); + Random random = new Random(42); + + mDatabase + .execSQL("CREATE TABLE t1(a INTEGER, b INTEGER, c VARCHAR(100))"); + mDatabase + .execSQL("CREATE TABLE t2(a INTEGER, b INTEGER, c VARCHAR(100))"); + + mDatabase.execSQL("CREATE INDEX i1b ON t1(b)"); + + for (int i = 0; i < SIZE; i++) { + int r = random.nextInt(100000); + mDatabase.execSQL("INSERT INTO t1 VALUES(" + i + "," + r + ",'" + + numberName(r) + "')"); + } + + for (int i = 0; i < SIZE; i++) { + int r = random.nextInt(100000); + mDatabase.execSQL("INSERT INTO t2 VALUES(" + i + "," + r + ",'" + + numberName(r) + "')"); + } + } + + public void testRun() { + mDatabase.query("t1 INNER JOIN t2 ON t1.c = t2.c", COLUMNS, null, + null, null, null, null); + } + } + + /** + * 100 SELECTs with subqueries. Subquery is using an index + */ + + public static class SelectSubQIndex100 extends PerformanceBase { + private static final int SIZE = 1 * kMultiplier; + private static final String[] COLUMNS = {"t1.a"}; + + private String[] where = new String[SIZE]; + + @Override + public void setUp() { + super.setUp(); + Random random = new Random(42); + + mDatabase + .execSQL("CREATE TABLE t1(a INTEGER, b INTEGER, c VARCHAR(100))"); + mDatabase + .execSQL("CREATE TABLE t2(a INTEGER, b INTEGER, c VARCHAR(100))"); + + mDatabase.execSQL("CREATE INDEX i2b ON t2(b)"); + + for (int i = 0; i < SIZE; i++) { + int r = random.nextInt(100000); + mDatabase.execSQL("INSERT INTO t1 VALUES(" + i + "," + r + ",'" + + numberName(r) + "')"); + } + + for (int i = 0; i < SIZE; i++) { + int r = random.nextInt(100000); + mDatabase.execSQL("INSERT INTO t2 VALUES(" + i + "," + r + ",'" + + numberName(r) + "')"); + } + + for (int i = 0; i < SIZE; i++) { + int lower = i * 100; + int upper = (i + 10) * 100; + where[i] = + "t1.b IN (SELECT t2.b FROM t2 WHERE t2.b >= " + lower + + " AND t2.b < " + upper + ")"; + } + } + + public void testRun() { + for (int i = 0; i < SIZE; i++) { + mDatabase + .query("t1", COLUMNS, where[i], null, null, null, null); + } + } + } + + /** + * 100 SELECTs on string comparison with Index + */ + + public static class SelectIndexStringComparison100 extends PerformanceBase { + private static final int SIZE = 1 * kMultiplier; + private static final String[] COLUMNS = {"count(*)", "avg(b)"}; + + private String[] where = new String[SIZE]; + + @Override + public void setUp() { + super.setUp(); + Random random = new Random(42); + + mDatabase + .execSQL("CREATE TABLE t1(a INTEGER, b INTEGER, c VARCHAR(100))"); + mDatabase.execSQL("CREATE INDEX i3c ON t1(c)"); + + for (int i = 0; i < SIZE; i++) { + int r = random.nextInt(100000); + mDatabase.execSQL("INSERT INTO t1 VALUES(" + i + "," + r + ",'" + + numberName(r) + "')"); + } + + for (int i = 0; i < SIZE; i++) { + where[i] = "c LIKE '" + numberName(i) + "'"; + } + } + + public void testRun() { + for (int i = 0; i < SIZE; i++) { + mDatabase + .query("t1", COLUMNS, where[i], null, null, null, null); + } + } + } + + /** + * 100 SELECTs on integer + */ + + public static class SelectInteger100 extends PerformanceBase { + private static final int SIZE = 1 * kMultiplier; + private static final String[] COLUMNS = {"b"}; + + private String[] where = new String[SIZE]; + + @Override + public void setUp() { + super.setUp(); + Random random = new Random(42); + + mDatabase + .execSQL("CREATE TABLE t1(a INTEGER, b INTEGER, c VARCHAR(100))"); + + for (int i = 0; i < SIZE; i++) { + int r = random.nextInt(100000); + mDatabase.execSQL("INSERT INTO t1 VALUES(" + i + "," + r + ",'" + + numberName(r) + "')"); + } + + } + + public void testRun() { + for (int i = 0; i < SIZE; i++) { + mDatabase.query("t1", COLUMNS, null, null, null, null, null); + } + } + } + + /** + * 100 SELECTs on String + */ + + public static class SelectString100 extends PerformanceBase { + private static final int SIZE = 1 * kMultiplier; + private static final String[] COLUMNS = {"c"}; + + private String[] where = new String[SIZE]; + + @Override + public void setUp() { + super.setUp(); + Random random = new Random(42); + + mDatabase + .execSQL("CREATE TABLE t1(a INTEGER, b INTEGER, c VARCHAR(100))"); + + for (int i = 0; i < SIZE; i++) { + int r = random.nextInt(100000); + mDatabase.execSQL("INSERT INTO t1 VALUES(" + i + "," + r + ",'" + + numberName(r) + "')"); + } + + } + + public void testRun() { + for (int i = 0; i < SIZE; i++) { + mDatabase.query("t1", COLUMNS, null, null, null, null, null); + } + } + } + + /** + * 100 SELECTs on integer with index + */ + + public static class SelectIntegerIndex100 extends PerformanceBase { + private static final int SIZE = 1 * kMultiplier; + private static final String[] COLUMNS = {"b"}; + + @Override + public void setUp() { + super.setUp(); + Random random = new Random(42); + + mDatabase + .execSQL("CREATE TABLE t1(a INTEGER, b INTEGER, c VARCHAR(100))"); + mDatabase.execSQL("CREATE INDEX i1b on t1(b)"); + + for (int i = 0; i < SIZE; i++) { + int r = random.nextInt(100000); + mDatabase.execSQL("INSERT INTO t1 VALUES(" + i + "," + r + ",'" + + numberName(r) + "')"); + } + + } + + public void testRun() { + for (int i = 0; i < SIZE; i++) { + mDatabase.query("t1", COLUMNS, null, null, null, null, null); + } + } + } + + /** + * 100 SELECTs on String with index + */ + + public static class SelectIndexString100 extends PerformanceBase { + private static final int SIZE = 1 * kMultiplier; + private static final String[] COLUMNS = {"c"}; + + @Override + public void setUp() { + super.setUp(); + Random random = new Random(42); + + mDatabase + .execSQL("CREATE TABLE t1(a INTEGER, b INTEGER, c VARCHAR(100))"); + mDatabase.execSQL("CREATE INDEX i1c ON t1(c)"); + + for (int i = 0; i < SIZE; i++) { + int r = random.nextInt(100000); + mDatabase.execSQL("INSERT INTO t1 VALUES(" + i + "," + r + ",'" + + numberName(r) + "')"); + } + + } + + public void testRun() { + for (int i = 0; i < SIZE; i++) { + mDatabase.query("t1", COLUMNS, null, null, null, null, null); + } + } + } + + /** + * 100 SELECTs on String with starts with + */ + + public static class SelectStringStartsWith100 extends PerformanceBase { + private static final int SIZE = 1 * kMultiplier; + private static final String[] COLUMNS = {"c"}; + private String[] where = new String[SIZE]; + + @Override + public void setUp() { + super.setUp(); + Random random = new Random(42); + + mDatabase + .execSQL("CREATE TABLE t1(a INTEGER, b INTEGER, c VARCHAR(100))"); + mDatabase.execSQL("CREATE INDEX i1c ON t1(c)"); + + for (int i = 0; i < SIZE; i++) { + int r = random.nextInt(100000); + mDatabase.execSQL("INSERT INTO t1 VALUES(" + i + "," + r + ",'" + + numberName(r) + "')"); + } + + for (int i = 0; i < SIZE; i++) { + int r = random.nextInt(100000); + where[i] = "c LIKE '" + numberName(r).substring(0, 1) + "*'"; + + } + + } + + public void testRun() { + for (int i = 0; i < SIZE; i++) { + mDatabase + .query("t1", COLUMNS, where[i], null, null, null, null); + } + } + } + + /** + * 1000 Deletes on an indexed table + */ + + public static class DeleteIndexed1000 extends PerformanceBase { + private static final int SIZE = 10 * kMultiplier; + private static final String[] COLUMNS = {"c"}; + + @Override + public void setUp() { + super.setUp(); + Random random = new Random(42); + + mDatabase + .execSQL("CREATE TABLE t1(a INTEGER, b INTEGER, c VARCHAR(100))"); + mDatabase.execSQL("CREATE INDEX i3c ON t1(c)"); + + for (int i = 0; i < SIZE; i++) { + int r = random.nextInt(100000); + mDatabase.execSQL("INSERT INTO t1 VALUES(" + i + "," + r + ",'" + + numberName(r) + "')"); + } + + } + + public void testRun() { + for (int i = 0; i < SIZE; i++) { + mDatabase.delete("t1", null, null); + } + } + } + + /** + * 1000 Deletes + */ + + public static class Delete1000 extends PerformanceBase { + private static final int SIZE = 10 * kMultiplier; + private static final String[] COLUMNS = {"c"}; + + @Override + public void setUp() { + super.setUp(); + Random random = new Random(42); + + mDatabase + .execSQL("CREATE TABLE t1(a INTEGER, b INTEGER, c VARCHAR(100))"); + + for (int i = 0; i < SIZE; i++) { + int r = random.nextInt(100000); + mDatabase.execSQL("INSERT INTO t1 VALUES(" + i + "," + r + ",'" + + numberName(r) + "')"); + } + + } + + public void testRun() { + for (int i = 0; i < SIZE; i++) { + mDatabase.delete("t1", null, null); + } + } + } + + /** + * 1000 DELETE's without an index with where clause + */ + + public static class DeleteWhere1000 extends PerformanceBase { + private static final int SIZE = 10 * kMultiplier; + private String[] where = new String[SIZE]; + + @Override + public void setUp() { + super.setUp(); + Random random = new Random(42); + + mDatabase + .execSQL("CREATE TABLE t1(a INTEGER, b INTEGER, c VARCHAR(100))"); + + for (int i = 0; i < SIZE; i++) { + int r = random.nextInt(100000); + mDatabase.execSQL("INSERT INTO t1 VALUES(" + i + "," + r + ",'" + + numberName(r) + "')"); + } + + for (int i = 0; i < SIZE; i++) { + int lower = i * 100; + int upper = (i + 10) * 100; + where[i] = "b >= " + lower + " AND b < " + upper; + } + } + + public void testRun() { + for (int i = 0; i < SIZE; i++) { + mDatabase.delete("t1", where[i], null); + } + } + } + + /** + * 1000 DELETE's with an index with where clause + */ + + public static class DeleteIndexWhere1000 extends PerformanceBase { + private static final int SIZE = 10 * kMultiplier; + private String[] where = new String[SIZE]; + + @Override + public void setUp() { + super.setUp(); + Random random = new Random(42); + + mDatabase + .execSQL("CREATE TABLE t1(a INTEGER, b INTEGER, c VARCHAR(100))"); + mDatabase.execSQL("CREATE INDEX i1b ON t1(b)"); + + for (int i = 0; i < SIZE; i++) { + int r = random.nextInt(100000); + mDatabase.execSQL("INSERT INTO t1 VALUES(" + i + "," + r + ",'" + + numberName(r) + "')"); + } + + for (int i = 0; i < SIZE; i++) { + int lower = i * 100; + int upper = (i + 10) * 100; + where[i] = "b >= " + lower + " AND b < " + upper; + } + } + + public void testRun() { + for (int i = 0; i < SIZE; i++) { + mDatabase.delete("t1", where[i], null); + } + } + } + + /** + * 1000 update's with an index with where clause + */ + + public static class UpdateIndexWhere1000 extends PerformanceBase { + private static final int SIZE = 10 * kMultiplier; + private String[] where = new String[SIZE]; + ContentValues[] mValues = new ContentValues[SIZE]; + + @Override + public void setUp() { + super.setUp(); + Random random = new Random(42); + + mDatabase + .execSQL("CREATE TABLE t1(a INTEGER, b INTEGER, c VARCHAR(100))"); + mDatabase.execSQL("CREATE INDEX i1b ON t1(b)"); + + for (int i = 0; i < SIZE; i++) { + int r = random.nextInt(100000); + mDatabase.execSQL("INSERT INTO t1 VALUES(" + i + "," + r + ",'" + + numberName(r) + "')"); + } + + for (int i = 0; i < SIZE; i++) { + + int lower = i * 100; + int upper = (i + 10) * 100; + where[i] = "b >= " + lower + " AND b < " + upper; + ContentValues b = new ContentValues(1); + b.put("b", upper); + mValues[i] = b; + + } + } + + public void testRun() { + for (int i = 0; i < SIZE; i++) { + mDatabase.update("t1", mValues[i], where[i], null); + } + } + } + + /** + * 1000 update's without an index with where clause + */ + + public static class UpdateWhere1000 extends PerformanceBase { + private static final int SIZE = 10 * kMultiplier; + private String[] where = new String[SIZE]; + ContentValues[] mValues = new ContentValues[SIZE]; + + @Override + public void setUp() { + super.setUp(); + Random random = new Random(42); + + mDatabase + .execSQL("CREATE TABLE t1(a INTEGER, b INTEGER, c VARCHAR(100))"); + + for (int i = 0; i < SIZE; i++) { + int r = random.nextInt(100000); + mDatabase.execSQL("INSERT INTO t1 VALUES(" + i + "," + r + ",'" + + numberName(r) + "')"); + } + + for (int i = 0; i < SIZE; i++) { + + int lower = i * 100; + int upper = (i + 10) * 100; + where[i] = "b >= " + lower + " AND b < " + upper; + ContentValues b = new ContentValues(1); + b.put("b", upper); + mValues[i] = b; + } + } + + public void testRun() { + for (int i = 0; i < SIZE; i++) { + mDatabase.update("t1", mValues[i], where[i], null); + } + } + } + + /** + * 10000 inserts for an integer + */ + + public static class InsertInteger10000 extends PerformanceBase { + private static final int SIZE = 100 * kMultiplier; + ContentValues[] mValues = new ContentValues[SIZE]; + + @Override + public void setUp() { + super.setUp(); + Random random = new Random(42); + + mDatabase + .execSQL("CREATE TABLE t1(a INTEGER)"); + + for (int i = 0; i < SIZE; i++) { + int r = random.nextInt(100000); + ContentValues b = new ContentValues(1); + b.put("a", r); + mValues[i] = b; + } + } + + public void testRun() { + for (int i = 0; i < SIZE; i++) { + mDatabase.insert("t1", null, mValues[i]); + } + } + } + + /** + * 10000 inserts for an integer -indexed table + */ + + public static class InsertIntegerIndex10000 extends PerformanceBase { + private static final int SIZE = 100 * kMultiplier; + ContentValues[] mValues = new ContentValues[SIZE]; + + @Override + public void setUp() { + super.setUp(); + Random random = new Random(42); + + mDatabase + .execSQL("CREATE TABLE t1(a INTEGER)"); + mDatabase.execSQL("CREATE INDEX i1a ON t1(a)"); + + for (int i = 0; i < SIZE; i++) { + int r = random.nextInt(100000); + ContentValues b = new ContentValues(1); + b.put("a", r); + mValues[i] = b; + } + } + + public void testRun() { + for (int i = 0; i < SIZE; i++) { + mDatabase.insert("t1", null, mValues[i]); + } + } + } + + /** + * 10000 inserts for a String + */ + + public static class InsertString10000 extends PerformanceBase { + private static final int SIZE = 100 * kMultiplier; + ContentValues[] mValues = new ContentValues[SIZE]; + + @Override + public void setUp() { + super.setUp(); + Random random = new Random(42); + + mDatabase + .execSQL("CREATE TABLE t1(a VARCHAR(100))"); + + for (int i = 0; i < SIZE; i++) { + int r = random.nextInt(100000); + ContentValues b = new ContentValues(1); + b.put("a", numberName(r)); + mValues[i] = b; + } + } + + public void testRun() { + for (int i = 0; i < SIZE; i++) { + mDatabase.insert("t1", null, mValues[i]); + } + } + } + + /** + * 10000 inserts for a String - indexed table + */ + + public static class InsertStringIndexed10000 extends PerformanceBase { + private static final int SIZE = 100 * kMultiplier; + ContentValues[] mValues = new ContentValues[SIZE]; + + @Override + public void setUp() { + super.setUp(); + Random random = new Random(42); + + mDatabase + .execSQL("CREATE TABLE t1(a VARCHAR(100))"); + mDatabase.execSQL("CREATE INDEX i1a ON t1(a)"); + + for (int i = 0; i < SIZE; i++) { + int r = random.nextInt(100000); + ContentValues b = new ContentValues(1); + b.put("a", numberName(r)); + mValues[i] = b; + } + } + + public void testRun() { + for (int i = 0; i < SIZE; i++) { + mDatabase.insert("t1", null, mValues[i]); + } + } + } + + + /** + * 10000 selects for a String -starts with + */ + + public static class SelectStringStartsWith10000 extends PerformanceBase { + private static final int SIZE = 100 * kMultiplier; + private static final String[] COLUMNS = {"t3.a"}; + private String[] where = new String[SIZE]; + + @Override + public void setUp() { + super.setUp(); + Random random = new Random(42); + + mDatabase + .execSQL("CREATE TABLE t3(a VARCHAR(100))"); + + for (int i = 0; i < SIZE; i++) { + int r = random.nextInt(100000); + mDatabase.execSQL("INSERT INTO t3 VALUES('" + + numberName(r) + "')"); + } + + for (int i = 0; i < SIZE; i++) { + int r = random.nextInt(100000); + where[i] = "a LIKE '" + numberName(r).substring(0, 1) + "*'"; + + } + } + + public void testRun() { + for (int i = 0; i < SIZE; i++) { + mDatabase.query("t3", COLUMNS, where[i], null, null, null, null); + } + } + } + + /** + * 10000 selects for a String - indexed table -starts with + */ + + public static class SelectStringIndexedStartsWith10000 extends + PerformanceBase { + private static final int SIZE = 100 * kMultiplier; + private static final String[] COLUMNS = {"t3.a"}; + private String[] where = new String[SIZE]; + + @Override + public void setUp() { + super.setUp(); + Random random = new Random(42); + + mDatabase + .execSQL("CREATE TABLE t3(a VARCHAR(100))"); + mDatabase.execSQL("CREATE INDEX i3a ON t3(a)"); + + for (int i = 0; i < SIZE; i++) { + int r = random.nextInt(100000); + mDatabase.execSQL("INSERT INTO t3 VALUES('" + + numberName(r) + "')"); + } + + for (int i = 0; i < SIZE; i++) { + int r = random.nextInt(100000); + where[i] = "a LIKE '" + numberName(r).substring(0, 1) + "*'"; + + } + } + + public void testRun() { + for (int i = 0; i < SIZE; i++) { + mDatabase.query("t3", COLUMNS, where[i], null, null, null, null); + } + } + } + + /** + * 10000 selects for an integer - + */ + + public static class SelectInteger10000 extends PerformanceBase { + private static final int SIZE = 100 * kMultiplier; + private static final String[] COLUMNS = {"t4.a"}; + private String[] where = new String[SIZE]; + + @Override + public void setUp() { + super.setUp(); + Random random = new Random(42); + + mDatabase + .execSQL("CREATE TABLE t4(a INTEGER)"); + + for (int i = 0; i < SIZE; i++) { + int r = random.nextInt(100000); + mDatabase.execSQL("INSERT INTO t4 VALUES(" + r + ")"); + int lower = i * 100; + int upper = (i + 10) * 100; + where[i] = "a >= " + lower + " AND a < " + upper; + } + } + + public void testRun() { + for (int i = 0; i < SIZE; i++) { + mDatabase.query("t4", COLUMNS, where[i], null, null, null, null); + } + } + } + + /** + * 10000 selects for an integer -indexed table + */ + + public static class SelectIntegerIndexed10000 extends PerformanceBase { + private static final int SIZE = 100 * kMultiplier; + private static final String[] COLUMNS = {"t4.a"}; + private String[] where = new String[SIZE]; + + @Override + public void setUp() { + super.setUp(); + Random random = new Random(42); + + mDatabase + .execSQL("CREATE TABLE t4(a INTEGER)"); + mDatabase.execSQL("CREATE INDEX i4a ON t4(a)"); + + for (int i = 0; i < SIZE; i++) { + int r = random.nextInt(100000); + mDatabase.execSQL("INSERT INTO t4 VALUES(" + r + ")"); + + int lower = i * 100; + int upper = (i + 10) * 100; + where[i] = "a >= " + lower + " AND a < " + upper; + } + + } + + public void testRun() { + for (int i = 0; i < SIZE; i++) { + mDatabase.query("t4", COLUMNS, where[i], null, null, null, null); + } + } + } + + + /** + * 10000 selects for a String - contains 'e' + */ + + public static class SelectStringContains10000 extends PerformanceBase { + private static final int SIZE = 100 * kMultiplier; + private static final String[] COLUMNS = {"t3.a"}; + private String[] where = new String[SIZE]; + + @Override + public void setUp() { + super.setUp(); + Random random = new Random(42); + + mDatabase + .execSQL("CREATE TABLE t3(a VARCHAR(100))"); + + for (int i = 0; i < SIZE; i++) { + int r = random.nextInt(100000); + mDatabase.execSQL("INSERT INTO t3 VALUES('" + + numberName(r) + "')"); + } + + for (int i = 0; i < SIZE; i++) { + where[i] = "a LIKE '*e*'"; + + } + } + + public void testRun() { + for (int i = 0; i < SIZE; i++) { + mDatabase.query("t3", COLUMNS, where[i], null, null, null, null); + } + } + } + + /** + * 10000 selects for a String - contains 'e'-indexed table + */ + + public static class SelectStringIndexedContains10000 extends + PerformanceBase { + private static final int SIZE = 100 * kMultiplier; + private static final String[] COLUMNS = {"t3.a"}; + private String[] where = new String[SIZE]; + + @Override + public void setUp() { + super.setUp(); + Random random = new Random(42); + + mDatabase + .execSQL("CREATE TABLE t3(a VARCHAR(100))"); + mDatabase.execSQL("CREATE INDEX i3a ON t3(a)"); + + for (int i = 0; i < SIZE; i++) { + int r = random.nextInt(100000); + mDatabase.execSQL("INSERT INTO t3 VALUES('" + + numberName(r) + "')"); + } + + for (int i = 0; i < SIZE; i++) { + where[i] = "a LIKE '*e*'"; + + } + } + + public void testRun() { + for (int i = 0; i < SIZE; i++) { + mDatabase.query("t3", COLUMNS, where[i], null, null, null, null); + } + } + } + + public static final String[] ONES = + {"zero", "one", "two", "three", "four", "five", "six", "seven", + "eight", "nine", "ten", "eleven", "twelve", "thirteen", + "fourteen", "fifteen", "sixteen", "seventeen", "eighteen", + "nineteen"}; + + public static final String[] TENS = + {"", "ten", "twenty", "thirty", "forty", "fifty", "sixty", + "seventy", "eighty", "ninety"}; +} diff --git a/tests/AndroidTests/src/com/android/unit_tests/ParentalControlTest.java b/tests/AndroidTests/src/com/android/unit_tests/ParentalControlTest.java new file mode 100644 index 0000000..d4d2a82 --- /dev/null +++ b/tests/AndroidTests/src/com/android/unit_tests/ParentalControlTest.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 com.android.unit_tests; + +import com.google.android.net.ParentalControl; +import com.google.android.net.ParentalControlState; + +import android.os.SystemClock; +import android.test.AndroidTestCase; +import android.test.suitebuilder.annotation.SmallTest; +import android.util.Log; + +import junit.framework.Assert; + +public class ParentalControlTest extends AndroidTestCase { + + private boolean mOnResultCalled = false; + + public class Callback implements ParentalControl.Callback { + public void onResult(ParentalControlState state) { + synchronized (ParentalControlTest.class) { + mOnResultCalled = true; + ParentalControlTest.class.notifyAll(); + } + } + } + + @SmallTest + public void testParentalControlCallback() { + synchronized (ParentalControlTest.class) { + ParentalControl.getParentalControlState(new Callback(), null); + try { + long start = SystemClock.uptimeMillis(); + ParentalControlTest.class.wait(20 * 1000); + long end = SystemClock.uptimeMillis(); + Log.d("AndroidTests", "ParentalControlTest callback took " + (end-start) + " ms."); + } catch (InterruptedException ex) { + } + } + + Assert.assertTrue(mOnResultCalled); + } +} diff --git a/tests/AndroidTests/src/com/android/unit_tests/PerformanceTests.java b/tests/AndroidTests/src/com/android/unit_tests/PerformanceTests.java new file mode 100644 index 0000000..9e54540 --- /dev/null +++ b/tests/AndroidTests/src/com/android/unit_tests/PerformanceTests.java @@ -0,0 +1,1223 @@ +/* + * 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.unit_tests; + +import android.os.Debug; +import junit.framework.Assert; +import android.test.PerformanceTestBase; +import android.test.PerformanceTestCase; +import org.apache.harmony.dalvik.NativeTestTarget; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.concurrent.atomic.AtomicInteger; + +public class PerformanceTests { + public static String[] children() { + return new String[] { + //StringEquals2.class.getName(), + //StringEquals10.class.getName(), + //StringEquals20.class.getName(), + //StringEquals200.class.getName(), + //StringEquals200U.class.getName(), + //StringCompareTo10.class.getName(), + //StringCompareTo200.class.getName(), + StringLength.class.getName(), + StringCrawl.class.getName(), + Ackermann.class.getName(), + AddTest.class.getName(), +// AddMemberVariableTest.class.getName(), + ArrayListIterator.class.getName(), + BoundsCheckTest.class.getName(), +// EmptyClassBaseTest.class.getName(), + EmptyJniStaticMethod0.class.getName(), + EmptyJniStaticMethod6.class.getName(), + EmptyJniStaticMethod6L.class.getName(), + FibonacciFast.class.getName(), + FibonacciSlow.class.getName(), +// LoopTests.class.getName(), +// HashMapTest.class.getName(), +// InterfaceTests.class.getName(), + LocalVariableAccess.class.getName(), + MemeberVariableAccess.class.getName(), + NestedLoop.class.getName(), +// StringConcatenationTests.class.getName(), +// ArrayListBase.class.getName(), + SynchronizedGetAndSetInt.class.getName(), + + /* this will not work on JamVM -- lacks atomic ops */ + AtomicGetAndSetInt.class.getName(), + }; + } + + public static class SizeTest { + private int mSize; + + public SizeTest(int size) { + mSize = size; + } + + public int size() { + return mSize; + } + } + + public static class LocalVariableAccess extends PerformanceTestBase { + private static final int ITERATIONS = 100000; + + public int startPerformance(PerformanceTestCase.Intermediates intermediates) { + intermediates.setInternalIterations(ITERATIONS * 20); + return 0; + } + + public void testRun() { + boolean variable = false; + boolean local = true; + for (int i = ITERATIONS - 1; i >= 0; i--) { + local = variable; + local = variable; + local = variable; + local = variable; + local = variable; // 5 + local = variable; + local = variable; + local = variable; + local = variable; + local = variable; // 10 + local = variable; + local = variable; + local = variable; + local = variable; + local = variable; // 15 + local = variable; + local = variable; + local = variable; + local = variable; + local = variable; // 20 + } + } + } + + /* This test is intentionally misspelled. Please do not rename it. Thanks! */ + public static class MemeberVariableAccess extends PerformanceTestBase { + private static final int ITERATIONS = 100000; + + public volatile boolean mMember = false; + + public int startPerformance(PerformanceTestCase.Intermediates intermediates) { + intermediates.setInternalIterations(ITERATIONS * 20); + return 0; + } + + public void testRun() { + boolean local = true; + for (int i = ITERATIONS - 1; i >= 0; i--) { + local = mMember; + local = mMember; + local = mMember; + local = mMember; + local = mMember; // 5 + local = mMember; + local = mMember; + local = mMember; + local = mMember; + local = mMember; // 10 + local = mMember; + local = mMember; + local = mMember; + local = mMember; + local = mMember; // 15 + local = mMember; + local = mMember; + local = mMember; + local = mMember; + local = mMember; // 20 + } + } + } + + public static class ArrayListIterator extends PerformanceTestBase { + private static final int ITERATIONS = 10000; + private ArrayList mList; + private String[] mKeys; + private Iterator mIterator; + + public void setUp() throws Exception { + super.setUp(); + mList = new ArrayList(); + mKeys = new String[ITERATIONS]; + + for (int i = ITERATIONS - 1; i >= 0; i--) { + mKeys[i] = Integer.toString(i, 16); + mList.add(mKeys[i]); + } + } + + public int startPerformance(PerformanceTestCase.Intermediates intermediates) { + intermediates.setInternalIterations(ITERATIONS); + return 0; + } + + public void testRun() { + mIterator = mList.iterator(); + while (mIterator.hasNext()) { + mIterator.next(); + } + } + } + + public static class Ackermann extends PerformanceTestBase { + public static final int ITERATIONS = 100; + public int startPerformance(PerformanceTestCase.Intermediates intermediates) { + intermediates.setInternalIterations(ITERATIONS); + return 0; + } + + public void testRun() { + for (int i = ITERATIONS - 1; i >= 0; i--) { + ackermann(3, 13); + } + } + + private int ackermann(int m, int n) { + if (m == 0) + return n + 1; + if (n == 0) + return ackermann(m - 1, 1); + return ackermann(m, n - 1); + } + } + + public static class FibonacciSlow extends PerformanceTestBase { + public void setUp() throws Exception { + super.setUp(); + Assert.assertEquals(0, fibonacci(0)); + Assert.assertEquals(1, fibonacci(1)); + Assert.assertEquals(1, fibonacci(2)); + Assert.assertEquals(2, fibonacci(3)); + Assert.assertEquals(6765, fibonacci(20)); + } + + public void tearDown() { + } + + public int startPerformance(PerformanceTestCase.Intermediates intermediates) { + return 0; + } + + public void testRun() { + fibonacci(20); + } + + private long fibonacci(long n) { + if (n == 0) + return 0; + if (n == 1) + return 1; + return fibonacci(n - 2) + fibonacci(n - 1); + } + } + + public static class FibonacciFast extends PerformanceTestBase { + public void setUp() throws Exception { + super.setUp(); + Assert.assertEquals(0, fibonacci(0)); + Assert.assertEquals(1, fibonacci(1)); + Assert.assertEquals(1, fibonacci(2)); + Assert.assertEquals(2, fibonacci(3)); + Assert.assertEquals(6765, fibonacci(20)); + } + + public void tearDown() { + } + + public int startPerformance(PerformanceTestCase.Intermediates intermediates) { + return 0; + } + + public void testRun() { + fibonacci(5000); + } + + private long fibonacci(long n) { + if (n == 0) + return 0; + if (n == 1) + return 1; + + int x = 0; + int y = 1; + for (int i = 0; i < n - 1; i++) { + y = y + x; + x = y - x; + } + + return y; + } + } + + public static class HashMapTest extends PerformanceTestBase { + private static final int ITERATIONS = 10000; + private HashMap mMap; + private String[] mKeys; + + public void setUp() throws Exception { + super.setUp(); + mMap = new HashMap(); + mKeys = new String[ITERATIONS]; + + for (int i = ITERATIONS - 1; i >= 0; i--) { + mKeys[i] = Integer.toString(i, 16); + mMap.put(mKeys[i], i); + } + } + + public void tearDown() { + } + + public int startPerformance(PerformanceTestCase.Intermediates intermediates) { + intermediates.setInternalIterations(ITERATIONS); + return 0; + } + + public void testHashMapContainsKey() { + for (int i = ITERATIONS - 1; i >= 0; i--) { + mMap.containsKey(mKeys[i]); + } + } + + public void testHashMapIterator() { + Iterator iterator; + + iterator = mMap.entrySet().iterator(); + while (iterator.hasNext()) { + iterator.next(); + } + } + + public void testHashMapPut() { + HashMap map = new HashMap(); + String[] keys = mKeys; + for (int i = ITERATIONS - 1; i >= 0; i--) { + map.put(keys[i], i); + } + } + } + + interface IA { + void funcA0(); + void funcA1(); + void funcA2(); + void funcA3(); + } + interface IAB extends IA { + void funcAB0(); + void funcAB1(); + void funcAB2(); + void funcAB3(); + } + interface IABC extends IAB { + void funcABC0(); + void funcABC1(); + void funcABC2(); + void funcABC3(); + } + interface IB { + void funcB0(); + void funcB1(); + void funcB2(); + void funcB3(); + } + interface IC { + void funcC0(); + void funcC1(); + void funcC2(); + void funcC3(); + } + + static class Alphabet implements Cloneable, IB, IABC, IC, Runnable { + public void funcA0() { + } + public void funcA1() { + } + public void funcA2() { + } + public void funcA3() { + } + public void funcAB0() { + } + public void funcAB1() { + } + public void funcAB2() { + } + public void funcAB3() { + } + public void funcABC0() { + } + public void funcABC1() { + } + public void funcABC2() { + } + public void funcABC3() { + } + public void funcB0() { + } + public void funcB1() { + } + public void funcB2() { + } + public void funcB3() { + } + public void funcC0() { + } + public void funcC1() { + } + public void funcC2() { + } + public void funcC3() { + } + public void run() { + } + }; + + public static class InterfaceTests extends PerformanceTestBase { + private static final int ITERATIONS = 10000; + + public int startPerformance(PerformanceTestCase.Intermediates intermediates) { + intermediates.setInternalIterations(ITERATIONS * 10); + return 0; + } + + /* call method directly */ + public void testInterfaceCalls0() { + Alphabet alpha = new Alphabet(); + + for (int i = ITERATIONS - 1; i >= 0; i--) { + alpha.funcABC1(); + alpha.funcABC1(); + alpha.funcABC1(); + alpha.funcABC1(); + alpha.funcABC1(); + alpha.funcABC1(); + alpha.funcABC1(); + alpha.funcABC1(); + alpha.funcABC1(); + alpha.funcABC1(); + } + } + + /* call method through interface reference */ + public void testInterfaceCalls1() { + Alphabet alpha = new Alphabet(); + IABC iabc = alpha; + + for (int i = ITERATIONS - 1; i >= 0; i--) { + iabc.funcABC1(); + iabc.funcABC1(); + iabc.funcABC1(); + iabc.funcABC1(); + iabc.funcABC1(); + iabc.funcABC1(); + iabc.funcABC1(); + iabc.funcABC1(); + iabc.funcABC1(); + iabc.funcABC1(); + } + } + + public void testInstanceOfTrivial() { + Alphabet alpha = new Alphabet(); + IABC iabc = alpha; + boolean val; + + for (int i = ITERATIONS - 1; i >= 0; i--) { + val = iabc instanceof Alphabet; + val = iabc instanceof Alphabet; + val = iabc instanceof Alphabet; + val = iabc instanceof Alphabet; + val = iabc instanceof Alphabet; + val = iabc instanceof Alphabet; + val = iabc instanceof Alphabet; + val = iabc instanceof Alphabet; + val = iabc instanceof Alphabet; + val = iabc instanceof Alphabet; + } + } + + public void testInstanceOfInterface() { + Alphabet alpha = new Alphabet(); + IABC iabc = alpha; + boolean val; + + for (int i = ITERATIONS - 1; i >= 0; i--) { + val = iabc instanceof IA; + val = iabc instanceof IA; + val = iabc instanceof IA; + val = iabc instanceof IA; + val = iabc instanceof IA; + val = iabc instanceof IA; + val = iabc instanceof IA; + val = iabc instanceof IA; + val = iabc instanceof IA; + val = iabc instanceof IA; + } + } + + public void testInstanceOfNot() { + Alphabet alpha = new Alphabet(); + IABC iabc = alpha; + boolean val; + + for (int i = ITERATIONS - 1; i >= 0; i--) { + val = iabc instanceof EmptyInterface; + val = iabc instanceof EmptyInterface; + val = iabc instanceof EmptyInterface; + val = iabc instanceof EmptyInterface; + val = iabc instanceof EmptyInterface; + val = iabc instanceof EmptyInterface; + val = iabc instanceof EmptyInterface; + val = iabc instanceof EmptyInterface; + val = iabc instanceof EmptyInterface; + val = iabc instanceof EmptyInterface; + } + } + } + + public static class NestedLoop extends PerformanceTestBase { + private static final int ITERATIONS = 10; + private static final int LOOPS = 5; + + public int startPerformance(PerformanceTestCase.Intermediates intermediates) { + intermediates.setInternalIterations(ITERATIONS * LOOPS); + return 0; + } + + public void testRun() { + int x = 0; + for (int a = 0; a < ITERATIONS; a++) { + for (int b = 0; b < ITERATIONS; b++) { + for (int c = 0; c < ITERATIONS; c++) { + for (int d = 0; d < ITERATIONS; d++) { + for (int e = 0; e < ITERATIONS; e++) { + x++; + } + } + } + } + } + } + } + + public static class StringConcatenationTests extends PerformanceTestBase { + private static final int ITERATIONS = 1000; + + public int startPerformance(PerformanceTestCase.Intermediates intermediates) { + intermediates.setInternalIterations(ITERATIONS); + return 0; + } + + public void testStringConcatenation1() { + StringBuffer buffer = new StringBuffer(); + for (int i = ITERATIONS - 1; i >= 0; i--) { + buffer.append("Hello World!\n"); + } + buffer = null; + } + + public void testStringConcatenation2() { + String string = ""; + for (int i = ITERATIONS - 1; i >= 0; i--) { + string += "Hello World!\n"; + } + string = null; + } + } + + public static class StringLength extends PerformanceTestBase { + private static final int ITERATIONS = 10000; + private static final String TEST_STRING = "This is the string we use for testing..."; // 40 chars + + public int startPerformance(PerformanceTestCase.Intermediates intermediates) { + intermediates.setInternalIterations(ITERATIONS * 10); + return 0; + } + + public void testRun() { + String testStr = TEST_STRING; + int length; + + for (int i = ITERATIONS - 1; i >= 0; i--) { + length = testStr.length(); + length = testStr.length(); + length = testStr.length(); + length = testStr.length(); + length = testStr.length(); + length = testStr.length(); + length = testStr.length(); + length = testStr.length(); + length = testStr.length(); + length = testStr.length(); + } + } + } + + public static class EmptyJniStaticMethod0 extends PerformanceTestBase { + private static final int ITERATIONS = 10000; + + public int startPerformance(PerformanceTestCase.Intermediates intermediates) { + intermediates.setInternalIterations(ITERATIONS * 10); + return 0; + } + + public void testRun() { + int a, b, c, d, e, f; + + a = b = c = d = e = f = 0; + + for (int i = ITERATIONS - 1; i >= 0; i--) { + NativeTestTarget.emptyJniStaticMethod0(); + NativeTestTarget.emptyJniStaticMethod0(); + NativeTestTarget.emptyJniStaticMethod0(); + NativeTestTarget.emptyJniStaticMethod0(); + NativeTestTarget.emptyJniStaticMethod0(); + NativeTestTarget.emptyJniStaticMethod0(); + NativeTestTarget.emptyJniStaticMethod0(); + NativeTestTarget.emptyJniStaticMethod0(); + NativeTestTarget.emptyJniStaticMethod0(); + NativeTestTarget.emptyJniStaticMethod0(); + } + } + } + public static class EmptyJniStaticMethod6 extends PerformanceTestBase { + private static final int ITERATIONS = 10000; + + public int startPerformance(PerformanceTestCase.Intermediates intermediates) { + intermediates.setInternalIterations(ITERATIONS * 10); + return 0; + } + + public void testRun() { + int a, b, c, d, e, f; + + a = b = c = d = e = f = 0; + + for (int i = ITERATIONS - 1; i >= 0; i--) { + NativeTestTarget.emptyJniStaticMethod6(a, b, c, d, e, f); + NativeTestTarget.emptyJniStaticMethod6(a, b, c, d, e, f); + NativeTestTarget.emptyJniStaticMethod6(a, b, c, d, e, f); + NativeTestTarget.emptyJniStaticMethod6(a, b, c, d, e, f); + NativeTestTarget.emptyJniStaticMethod6(a, b, c, d, e, f); + NativeTestTarget.emptyJniStaticMethod6(a, b, c, d, e, f); + NativeTestTarget.emptyJniStaticMethod6(a, b, c, d, e, f); + NativeTestTarget.emptyJniStaticMethod6(a, b, c, d, e, f); + NativeTestTarget.emptyJniStaticMethod6(a, b, c, d, e, f); + NativeTestTarget.emptyJniStaticMethod6(a, b, c, d, e, f); + } + } + } + public static class EmptyJniStaticMethod6L extends PerformanceTestBase { + private static final int ITERATIONS = 10000; + + public int startPerformance(PerformanceTestCase.Intermediates intermediates) { + intermediates.setInternalIterations(ITERATIONS * 10); + return 0; + } + + public void testRun() { + String a = null; + String[] b = null; + int[][] c = null; + Object d = null; + Object[] e = null; + Object[][][][] f = null; + + for (int i = ITERATIONS - 1; i >= 0; i--) { + NativeTestTarget.emptyJniStaticMethod6L(a, b, c, d, e, f); + NativeTestTarget.emptyJniStaticMethod6L(a, b, c, d, e, f); + NativeTestTarget.emptyJniStaticMethod6L(a, b, c, d, e, f); + NativeTestTarget.emptyJniStaticMethod6L(a, b, c, d, e, f); + NativeTestTarget.emptyJniStaticMethod6L(a, b, c, d, e, f); + NativeTestTarget.emptyJniStaticMethod6L(a, b, c, d, e, f); + NativeTestTarget.emptyJniStaticMethod6L(a, b, c, d, e, f); + NativeTestTarget.emptyJniStaticMethod6L(a, b, c, d, e, f); + NativeTestTarget.emptyJniStaticMethod6L(a, b, c, d, e, f); + NativeTestTarget.emptyJniStaticMethod6L(a, b, c, d, e, f); + } + } + } + + public static class StringCrawl extends PerformanceTestBase { + private static final int ITERATIONS = 10000; + private static final String TEST_STRING = "This is the string we use for testing..."; // 40 chars + + public int startPerformance(PerformanceTestCase.Intermediates intermediates) { + intermediates.setInternalIterations(ITERATIONS * TEST_STRING.length()); + return 0; + } + + public void testRun() { + String testStr = TEST_STRING; + char ch; + for (int i = ITERATIONS - 1; i >= 0; i--) { + /* this is the wrong way to walk through a string */ + for (int j = 0; j < testStr.length(); j++) { + ch = testStr.charAt(j); + } + } + } + } + + public static class AddTest extends PerformanceTestBase { + private static final int ITERATIONS = 10000; + + public int startPerformance(PerformanceTestCase.Intermediates intermediates) { + intermediates.setInternalIterations(ITERATIONS * 20); + return 0; + } + + public void testRun() { + int j = 0; + for (int i = ITERATIONS - 1; i >= 0; i--) { + j++; + j++; + j++; + j++; + j++; + j++; + j++; + j++; + j++; + j++; + j++; + j++; + j++; + j++; + j++; + j++; + j++; + j++; + j++; + j++; + } + } + } + + public static class AddMemberVariableTest extends PerformanceTestBase { + private static final int ITERATIONS = 10000; + private int j; + + public void setUp() throws Exception { + super.setUp(); + j = 0; + } + + public int startPerformance(PerformanceTestCase.Intermediates intermediates) { + intermediates.setInternalIterations(ITERATIONS * 10); + return 0; + } + + public void testAddMemberVariableTest() { + for (int i = ITERATIONS - 1; i >= 0; i--) { + j++; + j++; + j++; + j++; + j++; + j++; + j++; + j++; + j++; + j++; + } + } + + public void testAddMemberVariableInMethodTest() { + for (int i = ITERATIONS - 1; i >= 0; i--) { + add(); + add(); + add(); + add(); + add(); + add(); + add(); + add(); + add(); + add(); + } + } + + public void add() { + j++; + } + } + + private interface EmptyInterface { + public void emptyVirtual(); + + } + + private static class EmptyClass implements EmptyInterface { + public void emptyVirtual() { + } + + public static void emptyStatic() { + } + } + + public static class EmptyClassBaseTest extends PerformanceTestBase { + protected EmptyInterface mEmptyInterface; + protected EmptyClass mEmptyClass; + + public void setUp() throws Exception { + super.setUp(); + mEmptyClass = new EmptyClass(); + mEmptyInterface = mEmptyClass; + } + private static final int ITERATIONS = 10000; + + public int startPerformance(PerformanceTestCase.Intermediates intermediates) { + intermediates.setInternalIterations(ITERATIONS * 10); + return 0; + } + + public void testEmptyVirtualMethod() { + //EmptyClass emtpyClass = mEmptyClass; + for (int i = ITERATIONS - 1; i >= 0; i--) { + mEmptyClass.emptyVirtual(); + mEmptyClass.emptyVirtual(); + mEmptyClass.emptyVirtual(); + mEmptyClass.emptyVirtual(); + mEmptyClass.emptyVirtual(); + mEmptyClass.emptyVirtual(); + mEmptyClass.emptyVirtual(); + mEmptyClass.emptyVirtual(); + mEmptyClass.emptyVirtual(); + mEmptyClass.emptyVirtual(); + } + } + + public void testEmptyVirtualMethodTestInLocal() { + EmptyClass empty = mEmptyClass; + for (int i = ITERATIONS - 1; i >= 0; i--) { + empty.emptyVirtual(); + empty.emptyVirtual(); + empty.emptyVirtual(); + empty.emptyVirtual(); + empty.emptyVirtual(); + empty.emptyVirtual(); + empty.emptyVirtual(); + empty.emptyVirtual(); + empty.emptyVirtual(); + empty.emptyVirtual(); + } + } + + public void testEmptyStaticMethod () { + for (int i = ITERATIONS - 1; i >= 0; i--) { + EmptyClass.emptyStatic(); + EmptyClass.emptyStatic(); + EmptyClass.emptyStatic(); + EmptyClass.emptyStatic(); + EmptyClass.emptyStatic(); + EmptyClass.emptyStatic(); + EmptyClass.emptyStatic(); + EmptyClass.emptyStatic(); + EmptyClass.emptyStatic(); + EmptyClass.emptyStatic(); + } + } + + public void testEmptyJniStaticMethod0() { + + for (int i = ITERATIONS - 1; i >= 0; i--) { + NativeTestTarget.emptyJniStaticMethod0(); + NativeTestTarget.emptyJniStaticMethod0(); + NativeTestTarget.emptyJniStaticMethod0(); + NativeTestTarget.emptyJniStaticMethod0(); + NativeTestTarget.emptyJniStaticMethod0(); + NativeTestTarget.emptyJniStaticMethod0(); + NativeTestTarget.emptyJniStaticMethod0(); + NativeTestTarget.emptyJniStaticMethod0(); + NativeTestTarget.emptyJniStaticMethod0(); + NativeTestTarget.emptyJniStaticMethod0(); + } + } + + public void testEmptyJniStaticMethod6() { + int a, b, c, d, e, f; + + a = b = c = d = e = f = 0; + + for (int i = ITERATIONS - 1; i >= 0; i--) { + NativeTestTarget.emptyJniStaticMethod6(a, b, c, d, e, f); + NativeTestTarget.emptyJniStaticMethod6(a, b, c, d, e, f); + NativeTestTarget.emptyJniStaticMethod6(a, b, c, d, e, f); + NativeTestTarget.emptyJniStaticMethod6(a, b, c, d, e, f); + NativeTestTarget.emptyJniStaticMethod6(a, b, c, d, e, f); + NativeTestTarget.emptyJniStaticMethod6(a, b, c, d, e, f); + NativeTestTarget.emptyJniStaticMethod6(a, b, c, d, e, f); + NativeTestTarget.emptyJniStaticMethod6(a, b, c, d, e, f); + NativeTestTarget.emptyJniStaticMethod6(a, b, c, d, e, f); + NativeTestTarget.emptyJniStaticMethod6(a, b, c, d, e, f); + } + } + + public void testEmptyInternalStaticMethod() { + /* + * The method called is a VM-internal method with no extra + * wrapping. + */ + for (int i = ITERATIONS - 1; i >= 0; i--) { + NativeTestTarget.emptyInternalStaticMethod(); + NativeTestTarget.emptyInternalStaticMethod(); + NativeTestTarget.emptyInternalStaticMethod(); + NativeTestTarget.emptyInternalStaticMethod(); + NativeTestTarget.emptyInternalStaticMethod(); + NativeTestTarget.emptyInternalStaticMethod(); + NativeTestTarget.emptyInternalStaticMethod(); + NativeTestTarget.emptyInternalStaticMethod(); + NativeTestTarget.emptyInternalStaticMethod(); + NativeTestTarget.emptyInternalStaticMethod(); + } + } + + public void testEmptyInlineStaticMethod() { + /* + * The method called is a VM-internal method that gets + * specially "inlined" in a bytecode transformation. + */ + for (int i = ITERATIONS - 1; i >= 0; i--) { + NativeTestTarget.emptyInlineMethod(); + NativeTestTarget.emptyInlineMethod(); + NativeTestTarget.emptyInlineMethod(); + NativeTestTarget.emptyInlineMethod(); + NativeTestTarget.emptyInlineMethod(); + NativeTestTarget.emptyInlineMethod(); + NativeTestTarget.emptyInlineMethod(); + NativeTestTarget.emptyInlineMethod(); + NativeTestTarget.emptyInlineMethod(); + NativeTestTarget.emptyInlineMethod(); + } + } + + public void testEmptyInterfaceMethodTest() { + EmptyInterface emptyInterface = mEmptyInterface; + for (int i = ITERATIONS - 1; i >= 0; i--) { + emptyInterface.emptyVirtual(); + emptyInterface.emptyVirtual(); + emptyInterface.emptyVirtual(); + emptyInterface.emptyVirtual(); + emptyInterface.emptyVirtual(); + emptyInterface.emptyVirtual(); + emptyInterface.emptyVirtual(); + emptyInterface.emptyVirtual(); + emptyInterface.emptyVirtual(); + emptyInterface.emptyVirtual(); + } + } + } + + public static class LoopTests extends PerformanceTestBase { + private static final int ITERATIONS = 10000; + private SizeTest mSizeTest = new SizeTest(ITERATIONS); + + public int startPerformance(PerformanceTestCase.Intermediates intermediates) { + intermediates.setInternalIterations(ITERATIONS); + return 0; + } + + public void testForLoopTest() { + int i = 0; + for (; i < 10000; i++) { + } + } + + public void testWhileLoopTest() { + int i = 0; + + while (i < 10000) { + i++; + } + } + + public void testForLoopSizeCalledInside() { + for (int i = 0; i < mSizeTest.size(); i++) { + } + } + + public void testForLoopSizeCalledOutside() { + final int size = mSizeTest.size(); + for (int i = 0; i < size; i++) { + } + } + } + + public static class BoundsCheckTest extends PerformanceTestBase { + private static final int ITERATIONS = 10000; + public int startPerformance(PerformanceTestCase.Intermediates intermediates) { + intermediates.setInternalIterations(ITERATIONS * 10); + return 0; + } + + public void testRun() { + int[] data = new int[1]; + + for (int i = ITERATIONS - 1; i >= 0; i--) { + data[0] = i; + data[0] = i; + data[0] = i; + data[0] = i; + data[0] = i; + data[0] = i; + data[0] = i; + data[0] = i; + data[0] = i; + data[0] = i; + } + } + } + + public static class ArrayListBase extends PerformanceTestBase { + public void setUp() throws Exception { + super.setUp(); + mList = new ArrayList(); + mList.add(0); + mList.add(1); + mList.add(2); + mList.add(3); + mList.add(4); + mList.add(5); + mList.add(6); + mList.add(7); + mList.add(8); + mList.add(9); + } + + public int startPerformance(PerformanceTestCase.Intermediates intermediates) { + intermediates.setInternalIterations(100); + return 0; + } + + ArrayList<Integer> mList; + + public void testForArrayList() { + int i = 0; + int res = 0; + for (; i < 100; i++) { + for (int j = 0; j < mList.size(); j++) { + res += mList.get(j); + } + } + } + + public void testForLocalArrayList() { + int i = 0; + int res = 0; + for (; i < 100; i++) { + final List<Integer> list = mList; + final int N = list.size(); + for (int j = 0; j < N; j++) { + res += list.get(j); + } + } + } + + public void testForEachArrayList() { + int i = 0; + int res = 0; + for (; i < 100; i++) { + for (Integer v : mList) { + res += v; + } + } + } + } + + public static class SynchronizedGetAndSetInt extends PerformanceTestBase { + private static final int ITERATIONS = 100000; + + public int mMember = 0; + + public int startPerformance(PerformanceTestCase.Intermediates intermediates) { + intermediates.setInternalIterations(ITERATIONS); + return 0; + } + + public void testRun() { + int result = 0; + for (int i = ITERATIONS - 1; i >= 0; i--) { + synchronized (this) { + result = mMember; + mMember = i; + } + } + } + } + + public static class AtomicGetAndSetInt extends PerformanceTestBase { + private static final int ITERATIONS = 100000; + + public AtomicInteger mMember = new AtomicInteger(0); + + public int startPerformance(PerformanceTestCase.Intermediates intermediates) { + intermediates.setInternalIterations(ITERATIONS); + return 0; + } + + public void testRun() { + int result = 0; + for (int i = ITERATIONS - 1; i >= 0; i--) { + result = mMember.getAndSet(i); + } + } + } + + public static abstract class StringEquals extends PerformanceTestBase { + private static final int ITERATIONS = 10000; + + protected String mString1, mString2; + public void setUp() throws Exception { + super.setUp(); + } + + public int startPerformance(PerformanceTestCase.Intermediates intermediates) { + intermediates.setInternalIterations(ITERATIONS * 10); + return 0; + } + + public void testRun() { + String string1 = mString1; + String string2 = mString2; + + for (int i = ITERATIONS - 1; i >= 0; i--) { + string1.equals(string2); + string1.equals(string2); + string1.equals(string2); + string1.equals(string2); + string1.equals(string2); + string1.equals(string2); + string1.equals(string2); + string1.equals(string2); + string1.equals(string2); + string1.equals(string2); + } + } + } + + public static class StringEquals2 extends StringEquals { + public void setUp() throws Exception { + mString1 = "01"; + mString2 = "0x"; + } + } + public static class StringEquals10 extends StringEquals { + public void setUp() throws Exception { + mString1 = "0123456789"; + mString2 = "012345678x"; + } + } + public static class StringEquals20 extends StringEquals { + public void setUp() throws Exception { + mString1 = "01234567890123456789"; + mString2 = "0123456789012345678x"; + } + } + + public static class StringEquals200 extends StringEquals { + public void setUp() throws Exception { + mString1 = "0123456789012345678901234567890123456789" + + "0123456789012345678901234567890123456789" + + "0123456789012345678901234567890123456789" + + "0123456789012345678901234567890123456789" + + "0123456789012345678901234567890123456789"; + mString2 = "0123456789012345678901234567890123456789" + + "0123456789012345678901234567890123456789" + + "0123456789012345678901234567890123456789" + + "0123456789012345678901234567890123456789" + + "012345678901234567890123456789012345678x"; + } + } + public static class StringEquals200U extends StringEquals { + /* make one of the strings non-word aligned (bad memcmp case) */ + public void setUp() throws Exception { + String tmpStr; + mString1 = "0123456789012345678901234567890123456789" + + "0123456789012345678901234567890123456789" + + "0123456789012345678901234567890123456789" + + "0123456789012345678901234567890123456789" + + "0123456789012345678901234567890123456789"; + tmpStr = "z0123456789012345678901234567890123456789" + + "0123456789012345678901234567890123456789" + + "0123456789012345678901234567890123456789" + + "0123456789012345678901234567890123456789" + + "012345678901234567890123456789012345678x"; + mString2 = tmpStr.substring(1); + } + } + + public static abstract class StringCompareTo extends PerformanceTestBase { + private static final int ITERATIONS = 10000; + + protected String mString1, mString2; + + public int startPerformance(PerformanceTestCase.Intermediates intermediates) { + intermediates.setInternalIterations(ITERATIONS * 10); + return 0; + } + + public void testRun() { + String string1 = mString1; + String string2 = mString2; + + for (int i = ITERATIONS - 1; i >= 0; i--) { + string1.compareTo(string2); + string1.compareTo(string2); + string1.compareTo(string2); + string1.compareTo(string2); + string1.compareTo(string2); + string1.compareTo(string2); + string1.compareTo(string2); + string1.compareTo(string2); + string1.compareTo(string2); + string1.compareTo(string2); + } + } + } + public static class StringCompareTo10 extends StringCompareTo { + public void setUp() throws Exception { + mString1 = "0123456789"; + mString2 = "012345678x"; + } + } + public static class StringCompareTo200 extends StringCompareTo { + public void setUp() throws Exception { + mString1 = "0123456789012345678901234567890123456789" + + "0123456789012345678901234567890123456789" + + "0123456789012345678901234567890123456789" + + "0123456789012345678901234567890123456789" + + "0123456789012345678901234567890123456789"; + mString2 = "0123456789012345678901234567890123456789" + + "0123456789012345678901234567890123456789" + + "0123456789012345678901234567890123456789" + + "0123456789012345678901234567890123456789" + + "012345678901234567890123456789012345678x"; + } + } +} + diff --git a/tests/AndroidTests/src/com/android/unit_tests/RegexTest.java b/tests/AndroidTests/src/com/android/unit_tests/RegexTest.java new file mode 100644 index 0000000..8f55044 --- /dev/null +++ b/tests/AndroidTests/src/com/android/unit_tests/RegexTest.java @@ -0,0 +1,124 @@ +/* + * 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.unit_tests; + +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; + +public class RegexTest extends TestCase { + + @SmallTest + public void testTldPattern() throws Exception { + boolean t; + + t = Regex.TOP_LEVEL_DOMAIN_PATTERN.matcher("com").matches(); + assertTrue("Missed valid TLD", t); + + t = Regex.TOP_LEVEL_DOMAIN_PATTERN.matcher("xer").matches(); + assertFalse("Matched invalid TLD!", t); + } + + @SmallTest + public void testUrlPattern() throws Exception { + boolean t; + + t = Regex.WEB_URL_PATTERN.matcher("http://www.google.com").matches(); + assertTrue("Valid URL", t); + + t = Regex.WEB_URL_PATTERN.matcher("ftp://www.example.com").matches(); + assertFalse("Matched invalid protocol", t); + + t = Regex.WEB_URL_PATTERN.matcher("http://www.example.com:8080").matches(); + assertTrue("Didn't match valid URL with port", t); + + t = Regex.WEB_URL_PATTERN.matcher("http://www.example.com:8080/?foo=bar").matches(); + assertTrue("Didn't match valid URL with port and query args", t); + + t = Regex.WEB_URL_PATTERN.matcher("http://www.example.com:8080/~user/?foo=bar").matches(); + assertTrue("Didn't match valid URL with ~", t); + } + + @SmallTest + public void testIpPattern() throws Exception { + boolean t; + + t = Regex.IP_ADDRESS_PATTERN.matcher("172.29.86.3").matches(); + assertTrue("Valid IP", t); + + t = Regex.IP_ADDRESS_PATTERN.matcher("1234.4321.9.9").matches(); + assertFalse("Invalid IP", t); + } + + @SmallTest + public void testDomainPattern() throws Exception { + boolean t; + + t = Regex.DOMAIN_NAME_PATTERN.matcher("mail.example.com").matches(); + assertTrue("Valid domain", t); + + t = Regex.DOMAIN_NAME_PATTERN.matcher("__+&42.xer").matches(); + assertFalse("Invalid domain", t); + } + + @SmallTest + public void testPhonePattern() throws Exception { + boolean t; + + t = Regex.PHONE_PATTERN.matcher("(919) 555-1212").matches(); + assertTrue("Valid phone", t); + + t = Regex.PHONE_PATTERN.matcher("2334 9323/54321").matches(); + assertFalse("Invalid phone", t); + + String[] tests = { + "Me: 16505551212 this\n", + "Me: 6505551212 this\n", + "Me: 5551212 this\n", + + "Me: 1-650-555-1212 this\n", + "Me: (650) 555-1212 this\n", + "Me: +1 (650) 555-1212 this\n", + "Me: +1-650-555-1212 this\n", + "Me: 650-555-1212 this\n", + "Me: 555-1212 this\n", + + "Me: 1.650.555.1212 this\n", + "Me: (650) 555.1212 this\n", + "Me: +1 (650) 555.1212 this\n", + "Me: +1.650.555.1212 this\n", + "Me: 650.555.1212 this\n", + "Me: 555.1212 this\n", + + "Me: 1 650 555 1212 this\n", + "Me: (650) 555 1212 this\n", + "Me: +1 (650) 555 1212 this\n", + "Me: +1 650 555 1212 this\n", + "Me: 650 555 1212 this\n", + "Me: 555 1212 this\n", + }; + + for (String test : tests) { + Matcher m = Regex.PHONE_PATTERN.matcher(test); + + assertTrue("Valid phone " + test, m.find()); + } + } +} diff --git a/tests/AndroidTests/src/com/android/unit_tests/SMSTest.java b/tests/AndroidTests/src/com/android/unit_tests/SMSTest.java new file mode 100644 index 0000000..ce0b53d --- /dev/null +++ b/tests/AndroidTests/src/com/android/unit_tests/SMSTest.java @@ -0,0 +1,277 @@ +/* + * 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.unit_tests; + +import com.android.internal.telephony.gsm.GsmAlphabet; +import com.android.internal.telephony.gsm.SmsHeader; +import com.android.internal.util.HexDump; +import android.telephony.gsm.SmsMessage; +import android.test.AndroidTestCase; +import android.test.suitebuilder.annotation.SmallTest; + +import java.util.Iterator; + +public class SMSTest extends AndroidTestCase { + + @SmallTest + public void testOne() throws Exception { + String pdu = "07914151551512f2040B916105551511f100006060605130308A04D4F29C0E"; + + SmsMessage sms = SmsMessage.createFromPdu(HexDump.hexStringToByteArray(pdu)); + + assertEquals("+14155551212", sms.getServiceCenterAddress()); + assertEquals("+16505551111", sms.getOriginatingAddress()); + assertEquals("Test", sms.getMessageBody()); + //assertTrue(sms.scTimeMillis == 1152223383000L); + + pdu = "07914151551512f2040B916105551511f100036060924180008A0DA" + + "8695DAC2E8FE9296A794E07"; + + sms = SmsMessage.createFromPdu(HexDump.hexStringToByteArray(pdu)); + + assertEquals("+14155551212", sms.getServiceCenterAddress()); + assertEquals("+16505551111", sms.getOriginatingAddress()); + assertEquals("(Subject)Test", sms.getMessageBody()); + + /* lines[0] = "+CMT: ,45"; + lines[1] = "07914140279510F6440A8111110301003BF56070624111958A8C0B05040B8423F" + + "000033702010106276170706C69636174696F6E2F766E642E7761702E6D6D732D" + + "6D65737361676500AF848D018BB4848C8298524D66616E304A6D7135514141416" + + "57341414141546741414E4E304141414141008D908918802B3136353032343836" + + "3137392F545950453D504C4D4E009646573A20008A808E0222C788058103093A7" + + "F836874"; + + sms = SMSMessage.createFromPdu(mContext, lines); + */ + + pdu = "07914140279510F6440A8111110301003BF56080207130138A8C0B05040B8423F" + + "000032A02010106276170706C69636174696F6E2F766E642E7761702E6D6D732D" + + "6D65737361676500AF848D0185B4848C8298524E453955304A6D7135514141426" + + "66C414141414D7741414236514141414141008D908918802B3135313232393737" + + "3638332F545950453D504C4D4E008A808E022B918805810306977F83687474703" + + "A2F2F36"; + + sms = SmsMessage.createFromPdu(HexDump.hexStringToByteArray(pdu)); + + SmsHeader header = sms.getUserDataHeader(); + assertNotNull(header); + + Iterator<SmsHeader.Element> elements = header.getElements().iterator(); + assertNotNull(elements); + + + pdu = "07914140279510F6440A8111110301003BF56080207130238A3B0B05040B8423F" + + "000032A0202362E3130322E3137312E3135302F524E453955304A6D7135514141" + + "42666C414141414D774141423651414141414100"; + sms = SmsMessage.createFromPdu(HexDump.hexStringToByteArray(pdu)); + + header = sms.getUserDataHeader(); + assertNotNull(header); + + elements = header.getElements().iterator(); + assertNotNull(elements); + + /* + * UCS-2 encoded SMS + */ + + pdu = "07912160130300F4040B914151245584F600087010807121352B10212200A900AE00680065006C006C006F"; + + sms = SmsMessage.createFromPdu(HexDump.hexStringToByteArray(pdu)); + assertEquals("\u2122\u00a9\u00aehello", sms.getMessageBody()); + + // Entire alphabet (minus the escape character) + + /**** + lines[0] = "+CMT: "; + lines[1] = "0001000A8114455245680000808080604028180E888462C168381E90886442A9582E988C06C0E9783EA09068442A994EA8946AC56AB95EB0986C46ABD96EB89C6EC7EBF97EC0A070482C1A8FC8A472C96C3A9FD0A8744AAD5AAFD8AC76CBED7ABFE0B0784C2E9BCFE8B47ACD6EBBDFF0B87C4EAFDBEFF8BC7ECFEFFBFF"; + sms = SMSMessage.createFromPdu(mContext, lines); + + System.out.println("full alphabet message body len: " + + sms.getMessageBody().length()); + + System.out.println("'" + sms.getMessageBody() +"'"); + + assertTrue(sms.getMessageBody().length() == 128); + ****/ + + /* + * Multi-part text SMS with data in septets + */ + pdu = "07916163838408F6440B816105224431F700007060217175830AA0050003" + + "00020162B1582C168BC562B1582C168BC562B1582C168BC562B1582C" + + "168BC562B1582C168BC562B1582C168BC562B1582C168BC562B1582C" + + "168BC562B1582C168BC562B1582C168BC562B1582C168BC562B1582C" + + "168BC562B1582C168BC562B1582C168BC562B1582C168BC562B1582C" + + "168BC562B1582C168BC562B1582C168BC562B1582C168BC562"; + sms = SmsMessage.createFromPdu(HexDump.hexStringToByteArray(pdu)); + assertEquals(sms.getMessageBody(), + "1111111111111111111111111111111111111111" + + "1111111111111111111111111111111111111111" + + "1111111111111111111111111111111111111111" + + "111111111111111111111111111111111"); + + pdu = "07916163838408F6440B816105224431F700007060217185000A23050003" + + "00020262B1582C168BC96432994C2693C96432994C2693C96432990C"; + sms = SmsMessage.createFromPdu(HexDump.hexStringToByteArray(pdu)); + assertEquals("1111111222222222222222222222", sms.getMessageBody()); + } + + @SmallTest + public void testCPHSVoiceMail() throws Exception { + // "set MWI flag" + + String pdu = "07912160130310F20404D0110041006060627171118A0120"; + + SmsMessage sms = SmsMessage.createFromPdu(HexDump.hexStringToByteArray(pdu)); + + assertTrue(sms.isReplace()); + assertEquals("_@", sms.getOriginatingAddress()); + assertEquals(" ", sms.getMessageBody()); + assertTrue(sms.isMWISetMessage()); + + // "clear mwi flag" + + pdu = "07912160130310F20404D0100041006021924193352B0120"; + + sms = SmsMessage.createFromPdu(HexDump.hexStringToByteArray(pdu)); + + assertTrue(sms.isMWIClearMessage()); + + // "clear MWI flag" + + pdu = "07912160130310F20404D0100041006060627161058A0120"; + + sms = SmsMessage.createFromPdu(HexDump.hexStringToByteArray(pdu)); + +// System.out.println("originating address: " +// + (int) (sms.getOriginatingAddress().charAt(0)) + " " +// + (int) (sms.getOriginatingAddress().charAt(1))); + + assertTrue(sms.isReplace()); + assertEquals("\u0394@", sms.getOriginatingAddress()); + assertEquals(" ", sms.getMessageBody()); + assertTrue(sms.isMWIClearMessage()); + } + + @SmallTest + public void testCingularVoiceMail() throws Exception { + // "set MWI flag" + + String pdu = "07912180958750F84401800500C87020026195702B06040102000200"; + SmsMessage sms = SmsMessage.createFromPdu(HexDump.hexStringToByteArray(pdu)); + + assertTrue(sms.isMWISetMessage()); + assertTrue(sms.isMwiDontStore()); + + // "clear mwi flag" + + pdu = "07912180958750F84401800500C07020027160112B06040102000000"; + sms = SmsMessage.createFromPdu(HexDump.hexStringToByteArray(pdu)); + + assertTrue(sms.isMWIClearMessage()); + assertTrue(sms.isMwiDontStore()); + } + +// public void testTwo() throws Exception { +// // FIXME need an SMS-SUBMIT test +// +// System.out.println( +// "SMS SUBMIT: " + SmsMessage.getSubmitPdu(null, "+14155551212", "test", false)); +// } + + @SmallTest + public void testEmailGateway() throws Exception { + // email gateway sms test + String pdu = "07914151551512f204038105f300007011103164638a28e6f71b50c687db" + + "7076d9357eb7412f7a794e07cdeb6275794c07bde8e5391d247e93f3"; + + SmsMessage sms = SmsMessage.createFromPdu(HexDump.hexStringToByteArray(pdu)); + + assertEquals("+14155551212", sms.getServiceCenterAddress()); + assertTrue(sms.isEmail()); + assertEquals("foo@example.com", sms.getEmailFrom()); + assertEquals("foo@example.com", sms.getDisplayOriginatingAddress()); + assertEquals("test subject", sms.getPseudoSubject()); + assertEquals("test body", sms.getDisplayMessageBody()); + assertEquals("test body", sms.getEmailBody()); + + // email gateway sms test, including gsm extended character set. + pdu = "07914151551512f204038105f400007011103105458a29e6f71b50c687db" + + "7076d9357eb741af0d0a442fcfe9c23739bfe16d289bdee6b5f1813629"; + + sms = SmsMessage.createFromPdu(HexDump.hexStringToByteArray(pdu)); + + assertEquals("+14155551212", sms.getServiceCenterAddress()); + assertTrue(sms.isEmail()); + assertEquals("foo@example.com", sms.getDisplayOriginatingAddress()); + assertEquals("foo@example.com", sms.getEmailFrom()); + assertEquals("{ testBody[^~\\] }", sms.getDisplayMessageBody()); + assertEquals("{ testBody[^~\\] }", sms.getEmailBody()); + } + + @SmallTest + public void testExtendedCharacterTable() throws Exception { + String pdu = "07914151551512f2040B916105551511f100006080615131728A44D4F29C0E2" + + "AE3E96537B94C068DD16179784C2FCB41F4B0985D06B958ADD00FB0E94536AF9749" + + "74DA6D281BA00E95E26D509B946FC3DBF87A25D56A04"; + + SmsMessage sms = SmsMessage.createFromPdu(HexDump.hexStringToByteArray(pdu)); + + assertEquals("+14155551212", sms.getServiceCenterAddress()); + assertEquals("+16505551111", sms.getOriginatingAddress()); + assertEquals("Test extended character table .,-!?@~_\\/&\"';^|:()<{}>[]=%*+#", sms.getMessageBody()); + } + + @SmallTest + public void testDecode() throws Exception { + byte[] septets = new byte[(7 * 128 + 7) / 8]; + + int bitOffset = 0; + + for (int i = 0; i < 128; i++) { + int v; + if (i == 0x1b) { + // extended escape char + v = 0; + } else { + v = i; + } + + int byteOffset = bitOffset / 8; + int shift = bitOffset % 8; + + septets[byteOffset] |= v << shift; + + if (shift > 1) { + septets[byteOffset + 1] = (byte) (v >> (8 - shift)); + } + + bitOffset += 7; + } + + String decoded = GsmAlphabet.gsm7BitPackedToString(septets, 0, 128); + byte[] reEncoded = GsmAlphabet.stringToGsm7BitPacked(decoded); + + // reEncoded has the count septets byte at the front + assertEquals(reEncoded.length, septets.length + 1); + + for (int i = 0; i < septets.length; i++) { + assertEquals(reEncoded[i + 1], septets[i]); + } + } +} diff --git a/tests/AndroidTests/src/com/android/unit_tests/SSLClientSessionCacheFactoryTest.java b/tests/AndroidTests/src/com/android/unit_tests/SSLClientSessionCacheFactoryTest.java new file mode 100644 index 0000000..5d7349f --- /dev/null +++ b/tests/AndroidTests/src/com/android/unit_tests/SSLClientSessionCacheFactoryTest.java @@ -0,0 +1,54 @@ +package com.android.unit_tests; + +import com.google.android.net.SSLClientSessionCacheFactory; +import com.android.internal.net.DbSSLSessionCache; +import android.test.AndroidTestCase; +import android.test.suitebuilder.annotation.MediumTest; +import android.content.ContentResolver; +import android.content.Context; +import android.provider.Settings; +import org.apache.harmony.xnet.provider.jsse.SSLClientSessionCache; + +/** + * Unit test for {@link SSLClientSessionCacheFactory}. + */ +@MediumTest +public final class SSLClientSessionCacheFactoryTest extends AndroidTestCase { + + protected void tearDown() throws Exception { + setSslSessionCacheValue(getContext(), ""); + super.tearDown(); + } + + private static void setSslSessionCacheValue(Context context, String value) { + ContentResolver resolver = context.getContentResolver(); + Settings.Gservices.putString(resolver, Settings.Gservices.SSL_SESSION_CACHE, value); + } + + private static SSLClientSessionCache getCache(Context context, String type) { + setSslSessionCacheValue(context, type); + return SSLClientSessionCacheFactory.getCache(context); + } + + public void testGetDbCache() throws Exception { + Context context = getContext(); + SSLClientSessionCache cache = getCache(context, "db"); + assertNotNull(cache); + assertTrue(cache instanceof DbSSLSessionCache); + } + + public void testGetFileCache() throws Exception { + Context context = getContext(); + SSLClientSessionCache cache = getCache(context, "file"); + assertNotNull(cache); + // yuck =) + assertEquals("org.apache.harmony.xnet.provider.jsse.FileClientSessionCache$Impl", + cache.getClass().getName()); + } + + public void testGetNoCache() throws Exception { + Context context = getContext(); + SSLClientSessionCache cache = getCache(context, "none"); + assertNull(cache); + } +} diff --git a/tests/AndroidTests/src/com/android/unit_tests/SSLTest.java b/tests/AndroidTests/src/com/android/unit_tests/SSLTest.java new file mode 100644 index 0000000..9481180 --- /dev/null +++ b/tests/AndroidTests/src/com/android/unit_tests/SSLTest.java @@ -0,0 +1,52 @@ +/* + * 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.unit_tests; + +import android.net.SSLCertificateSocketFactory; +import android.test.suitebuilder.annotation.Suppress; +import junit.framework.TestCase; + +import java.io.InputStream; +import java.io.OutputStream; +import java.net.Socket; + +//This test relies on network resources. +@Suppress +public class SSLTest extends TestCase { + public void testCertificate() throws Exception { + // test www.fortify.net/sslcheck.html + Socket ssl = SSLCertificateSocketFactory.getDefault().createSocket("www.fortify.net",443); + assertNotNull(ssl); + + OutputStream out = ssl.getOutputStream(); + assertNotNull(out); + + InputStream in = ssl.getInputStream(); + assertNotNull(in); + + String get = "GET /sslcheck.html HTTP/1.1\r\nHost: 68.178.217.222\r\n\r\n"; + + // System.out.println("going for write..."); + out.write(get.getBytes()); + + byte[] b = new byte[1024]; + // System.out.println("going for read..."); + int ret = in.read(b); + + // System.out.println(new String(b)); + } +} diff --git a/tests/AndroidTests/src/com/android/unit_tests/SafeSaxTest.java b/tests/AndroidTests/src/com/android/unit_tests/SafeSaxTest.java new file mode 100644 index 0000000..d488a29 --- /dev/null +++ b/tests/AndroidTests/src/com/android/unit_tests/SafeSaxTest.java @@ -0,0 +1,539 @@ +/* + * 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.unit_tests; + +import android.graphics.Bitmap; +import android.sax.Element; +import android.sax.ElementListener; +import android.sax.EndTextElementListener; +import android.sax.RootElement; +import android.sax.StartElementListener; +import android.sax.TextElementListener; +import android.test.AndroidTestCase; +import android.test.suitebuilder.annotation.LargeTest; +import android.test.suitebuilder.annotation.SmallTest; +import android.text.format.Time; +import android.util.Log; +import android.util.Xml; +import com.android.internal.util.XmlUtils; +import org.xml.sax.Attributes; +import org.xml.sax.ContentHandler; +import org.xml.sax.SAXException; +import org.xml.sax.helpers.DefaultHandler; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; + +public class SafeSaxTest extends AndroidTestCase { + + private static final String TAG = SafeSaxTest.class.getName(); + + private static final String ATOM_NAMESPACE = "http://www.w3.org/2005/Atom"; + private static final String MEDIA_NAMESPACE = "http://search.yahoo.com/mrss/"; + private static final String YOUTUBE_NAMESPACE = "http://gdata.youtube.com/schemas/2007"; + private static final String GDATA_NAMESPACE = "http://schemas.google.com/g/2005"; + + private static class ElementCounter implements ElementListener { + int starts = 0; + int ends = 0; + + public void start(Attributes attributes) { + starts++; + } + + public void end() { + ends++; + } + } + + private static class TextElementCounter implements TextElementListener { + int starts = 0; + String bodies = ""; + + public void start(Attributes attributes) { + starts++; + } + + public void end(String body) { + this.bodies += body; + } + } + + @SmallTest + public void testListener() throws Exception { + String xml = "<feed xmlns='http://www.w3.org/2005/Atom'>\n" + + "<entry>\n" + + "<id>a</id>\n" + + "</entry>\n" + + "<entry>\n" + + "<id>b</id>\n" + + "</entry>\n" + + "</feed>\n"; + + RootElement root = new RootElement(ATOM_NAMESPACE, "feed"); + Element entry = root.requireChild(ATOM_NAMESPACE, "entry"); + Element id = entry.requireChild(ATOM_NAMESPACE, "id"); + + ElementCounter rootCounter = new ElementCounter(); + ElementCounter entryCounter = new ElementCounter(); + TextElementCounter idCounter = new TextElementCounter(); + + root.setElementListener(rootCounter); + entry.setElementListener(entryCounter); + id.setTextElementListener(idCounter); + + Xml.parse(xml, root.getContentHandler()); + + assertEquals(1, rootCounter.starts); + assertEquals(1, rootCounter.ends); + assertEquals(2, entryCounter.starts); + assertEquals(2, entryCounter.ends); + assertEquals(2, idCounter.starts); + assertEquals("ab", idCounter.bodies); + } + + @SmallTest + public void testMissingRequiredChild() throws Exception { + String xml = "<feed></feed>"; + RootElement root = new RootElement("feed"); + root.requireChild("entry"); + + try { + Xml.parse(xml, root.getContentHandler()); + fail("expected exception not thrown"); + } catch (SAXException e) { + // Expected. + } + } + + @SmallTest + public void testMixedContent() throws Exception { + String xml = "<feed><entry></entry></feed>"; + + RootElement root = new RootElement("feed"); + root.setEndTextElementListener(new EndTextElementListener() { + public void end(String body) { + } + }); + + try { + Xml.parse(xml, root.getContentHandler()); + fail("expected exception not thrown"); + } catch (SAXException e) { + // Expected. + } + } + + @LargeTest + public void testPerformance() throws Exception { + InputStream in = mContext.getResources().openRawResource(R.raw.youtube); + byte[] xmlBytes; + try { + ByteArrayOutputStream out = new ByteArrayOutputStream(); + byte[] buffer = new byte[1024]; + int length; + while ((length = in.read(buffer)) != -1) { + out.write(buffer, 0, length); + } + xmlBytes = out.toByteArray(); + } finally { + in.close(); + } + + Log.i("***", "File size: " + (xmlBytes.length / 1024) + "k"); + + VideoAdapter videoAdapter = new VideoAdapter(); + ContentHandler handler = newContentHandler(videoAdapter); + for (int i = 0; i < 2; i++) { + pureSaxTest(new ByteArrayInputStream(xmlBytes)); + saxyModelTest(new ByteArrayInputStream(xmlBytes)); + saxyModelTest(new ByteArrayInputStream(xmlBytes), handler); + } + } + + private static void pureSaxTest(InputStream inputStream) throws IOException, SAXException { + long start = System.currentTimeMillis(); + VideoAdapter videoAdapter = new VideoAdapter(); + Xml.parse(inputStream, Xml.Encoding.UTF_8, new YouTubeContentHandler(videoAdapter)); + long elapsed = System.currentTimeMillis() - start; + Log.i(TAG, "pure SAX: " + elapsed + "ms"); + } + + private static void saxyModelTest(InputStream inputStream) throws IOException, SAXException { + long start = System.currentTimeMillis(); + VideoAdapter videoAdapter = new VideoAdapter(); + Xml.parse(inputStream, Xml.Encoding.UTF_8, newContentHandler(videoAdapter)); + long elapsed = System.currentTimeMillis() - start; + Log.i(TAG, "Saxy Model: " + elapsed + "ms"); + } + + private static void saxyModelTest(InputStream inputStream, ContentHandler contentHandler) + throws IOException, SAXException { + long start = System.currentTimeMillis(); + Xml.parse(inputStream, Xml.Encoding.UTF_8, contentHandler); + long elapsed = System.currentTimeMillis() - start; + Log.i(TAG, "Saxy Model (preloaded): " + elapsed + "ms"); + } + + private static class VideoAdapter { + public void addVideo(YouTubeVideo video) { + } + } + + private static ContentHandler newContentHandler(VideoAdapter videoAdapter) { + return new HandlerFactory().newContentHandler(videoAdapter); + } + + private static class HandlerFactory { + YouTubeVideo video; + + public ContentHandler newContentHandler(VideoAdapter videoAdapter) { + RootElement root = new RootElement(ATOM_NAMESPACE, "feed"); + + final VideoListener videoListener = new VideoListener(videoAdapter); + + Element entry = root.getChild(ATOM_NAMESPACE, "entry"); + + entry.setElementListener(videoListener); + + entry.getChild(ATOM_NAMESPACE, "id") + .setEndTextElementListener(new EndTextElementListener() { + public void end(String body) { + video.videoId = body; + } + }); + + entry.getChild(ATOM_NAMESPACE, "published") + .setEndTextElementListener(new EndTextElementListener() { + public void end(String body) { + // TODO(tomtaylor): programmatically get the timezone + video.dateAdded = new Time(Time.TIMEZONE_UTC); + video.dateAdded.parse3339(body); + } + }); + + Element author = entry.getChild(ATOM_NAMESPACE, "author"); + author.getChild(ATOM_NAMESPACE, "name") + .setEndTextElementListener(new EndTextElementListener() { + public void end(String body) { + video.authorName = body; + } + }); + + Element mediaGroup = entry.getChild(MEDIA_NAMESPACE, "group"); + + mediaGroup.getChild(MEDIA_NAMESPACE, "thumbnail") + .setStartElementListener(new StartElementListener() { + public void start(Attributes attributes) { + String url = attributes.getValue("", "url"); + if (video.thumbnailUrl == null && url.length() > 0) { + video.thumbnailUrl = url; + } + } + }); + + mediaGroup.getChild(MEDIA_NAMESPACE, "content") + .setStartElementListener(new StartElementListener() { + public void start(Attributes attributes) { + String url = attributes.getValue("", "url"); + if (url != null) { + video.videoUrl = url; + } + } + }); + + mediaGroup.getChild(MEDIA_NAMESPACE, "player") + .setStartElementListener(new StartElementListener() { + public void start(Attributes attributes) { + String url = attributes.getValue("", "url"); + if (url != null) { + video.playbackUrl = url; + } + } + }); + + mediaGroup.getChild(MEDIA_NAMESPACE, "title") + .setEndTextElementListener(new EndTextElementListener() { + public void end(String body) { + video.title = body; + } + }); + + mediaGroup.getChild(MEDIA_NAMESPACE, "category") + .setEndTextElementListener(new EndTextElementListener() { + public void end(String body) { + video.category = body; + } + }); + + mediaGroup.getChild(MEDIA_NAMESPACE, "description") + .setEndTextElementListener(new EndTextElementListener() { + public void end(String body) { + video.description = body; + } + }); + + mediaGroup.getChild(MEDIA_NAMESPACE, "keywords") + .setEndTextElementListener(new EndTextElementListener() { + public void end(String body) { + video.tags = body; + } + }); + + mediaGroup.getChild(YOUTUBE_NAMESPACE, "duration") + .setStartElementListener(new StartElementListener() { + public void start(Attributes attributes) { + String seconds = attributes.getValue("", "seconds"); + video.lengthInSeconds + = XmlUtils.convertValueToInt(seconds, 0); + } + }); + + mediaGroup.getChild(YOUTUBE_NAMESPACE, "statistics") + .setStartElementListener(new StartElementListener() { + public void start(Attributes attributes) { + String viewCount = attributes.getValue("", "viewCount"); + video.viewCount + = XmlUtils.convertValueToInt(viewCount, 0); + } + }); + + entry.getChild(GDATA_NAMESPACE, "rating") + .setStartElementListener(new StartElementListener() { + public void start(Attributes attributes) { + String average = attributes.getValue("", "average"); + video.rating = average == null + ? 0.0f : Float.parseFloat(average); + } + }); + + return root.getContentHandler(); + } + + class VideoListener implements ElementListener { + + final VideoAdapter videoAdapter; + + public VideoListener(VideoAdapter videoAdapter) { + this.videoAdapter = videoAdapter; + } + + public void start(Attributes attributes) { + video = new YouTubeVideo(); + } + + public void end() { + videoAdapter.addVideo(video); + video = null; + } + } + } + + private static class YouTubeContentHandler extends DefaultHandler { + + final VideoAdapter videoAdapter; + + YouTubeVideo video = null; + StringBuilder builder = null; + + public YouTubeContentHandler(VideoAdapter videoAdapter) { + this.videoAdapter = videoAdapter; + } + + @Override + public void startElement(String uri, String localName, String qName, + Attributes attributes) throws SAXException { + if (uri.equals(ATOM_NAMESPACE)) { + if (localName.equals("entry")) { + video = new YouTubeVideo(); + return; + } + + if (video == null) { + return; + } + + if (!localName.equals("id") + && !localName.equals("published") + && !localName.equals("name")) { + return; + } + this.builder = new StringBuilder(); + return; + + } + + if (video == null) { + return; + } + + if (uri.equals(MEDIA_NAMESPACE)) { + if (localName.equals("thumbnail")) { + String url = attributes.getValue("", "url"); + if (video.thumbnailUrl == null && url.length() > 0) { + video.thumbnailUrl = url; + } + return; + } + + if (localName.equals("content")) { + String url = attributes.getValue("", "url"); + if (url != null) { + video.videoUrl = url; + } + return; + } + + if (localName.equals("player")) { + String url = attributes.getValue("", "url"); + if (url != null) { + video.playbackUrl = url; + } + return; + } + + if (localName.equals("title") + || localName.equals("category") + || localName.equals("description") + || localName.equals("keywords")) { + this.builder = new StringBuilder(); + return; + } + + return; + } + + if (uri.equals(YOUTUBE_NAMESPACE)) { + if (localName.equals("duration")) { + video.lengthInSeconds = XmlUtils.convertValueToInt( + attributes.getValue("", "seconds"), 0); + return; + } + + if (localName.equals("statistics")) { + video.viewCount = XmlUtils.convertValueToInt( + attributes.getValue("", "viewCount"), 0); + return; + } + + return; + } + + if (uri.equals(GDATA_NAMESPACE)) { + if (localName.equals("rating")) { + String average = attributes.getValue("", "average"); + video.rating = average == null + ? 0.0f : Float.parseFloat(average); + } + } + } + + @Override + public void characters(char text[], int start, int length) + throws SAXException { + if (builder != null) { + builder.append(text, start, length); + } + } + + String takeText() { + try { + return builder.toString(); + } finally { + builder = null; + } + } + + @Override + public void endElement(String uri, String localName, String qName) + throws SAXException { + if (video == null) { + return; + } + + if (uri.equals(ATOM_NAMESPACE)) { + if (localName.equals("published")) { + // TODO(tomtaylor): programmatically get the timezone + video.dateAdded = new Time(Time.TIMEZONE_UTC); + video.dateAdded.parse3339(takeText()); + return; + } + + if (localName.equals("name")) { + video.authorName = takeText(); + return; + } + + if (localName.equals("id")) { + video.videoId = takeText(); + return; + } + + if (localName.equals("entry")) { + // Add the video! + videoAdapter.addVideo(video); + video = null; + return; + } + + return; + } + + if (uri.equals(MEDIA_NAMESPACE)) { + if (localName.equals("description")) { + video.description = takeText(); + return; + } + + if (localName.equals("keywords")) { + video.tags = takeText(); + return; + } + + if (localName.equals("category")) { + video.category = takeText(); + return; + } + + if (localName.equals("title")) { + video.title = takeText(); + } + } + } + } + + private static class YouTubeVideo { + public String videoId; // the id used to lookup on YouTube + public String videoUrl; // the url to play the video + public String playbackUrl; // the url to share for users to play video + public String thumbnailUrl; // the url of the thumbnail image + public String title; + public Bitmap bitmap; // cached bitmap of the thumbnail + public int lengthInSeconds; + public int viewCount; // number of times the video has been viewed + public float rating; // ranges from 0.0 to 5.0 + public Boolean triedToLoadThumbnail; + public String authorName; + public Time dateAdded; + public String category; + public String tags; + public String description; + } +} + diff --git a/tests/AndroidTests/src/com/android/unit_tests/SearchManagerTest.java b/tests/AndroidTests/src/com/android/unit_tests/SearchManagerTest.java new file mode 100644 index 0000000..09e3b02 --- /dev/null +++ b/tests/AndroidTests/src/com/android/unit_tests/SearchManagerTest.java @@ -0,0 +1,542 @@ +/* + * 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.unit_tests; + +import com.android.unit_tests.activity.LocalActivity; + +import android.app.Activity; +import android.app.ISearchManager; +import android.app.SearchManager; +import android.content.ComponentName; +import android.content.Context; +import android.content.Intent; +import android.content.pm.ApplicationInfo; +import android.content.pm.PackageManager; +import android.content.pm.ProviderInfo; +import android.content.pm.ResolveInfo; +import android.content.res.Resources; +import android.content.res.XmlResourceParser; +import android.os.ServiceManager; +import android.server.search.SearchableInfo; +import android.server.search.SearchableInfo.ActionKeyInfo; +import android.test.ActivityInstrumentationTestCase; +import android.test.MoreAsserts; +import android.test.mock.MockContext; +import android.test.mock.MockPackageManager; +import android.test.suitebuilder.annotation.LargeTest; +import android.test.suitebuilder.annotation.MediumTest; +import android.util.AndroidRuntimeException; +import android.view.KeyEvent; + +import java.util.ArrayList; +import java.util.List; + +/** + * To launch this test from the command line: + * + * adb shell am instrument -w \ + * -e class com.android.unit_tests.SearchManagerTest \ + * com.android.unit_tests/android.test.InstrumentationTestRunner + */ +public class SearchManagerTest extends ActivityInstrumentationTestCase<LocalActivity> { + + // If non-zero, enable a set of tests that start and stop the search manager. + // This is currently disabled because it's causing an unwanted jump from the unit test + // activity into the contacts activity. We'll put this back after we disable that jump. + private static final int TEST_SEARCH_START = 0; + + /* + * Bug list of test ideas. + * + * testSearchManagerInterfaceAvailable() + * Exercise the interface obtained + * + * testSearchManagerAvailable() + * Exercise the interface obtained + * + * testSearchManagerInvocations() + * FIX - make it work again + * stress test with a very long string + * + * SearchableInfo tests + * Mock the context so I can provide very specific input data + * Confirm OK with "zero" searchables + * Confirm "good" metadata read properly + * Confirm "bad" metadata skipped properly + * Confirm ordering of searchables + * Confirm "good" actionkeys + * confirm "bad" actionkeys are rejected + * confirm XML ordering enforced (will fail today - bug in SearchableInfo) + * findActionKey works + * getIcon works + * + * SearchManager tests + * confirm proper identification of "default" activity based on policy, not hardcoded contacts + * + * SearchBar tests + * Maybe have to do with framework / unittest runner - need instrumented activity? + * How can we unit test the suggestions content providers? + * Should I write unit tests for any of them? + * Test scenarios: + * type-BACK (cancel) + * type-GO (send) + * type-navigate-click (suggestion) + * type-action + * type-navigate-action (suggestion) + */ + + /** + * Local copy of activity context + */ + Context mContext; + + public SearchManagerTest() { + super("com.android.unit_tests", LocalActivity.class); + } + + /** + * Setup any common data for the upcoming tests. + */ + @Override + public void setUp() throws Exception { + super.setUp(); + + Activity testActivity = getActivity(); + mContext = (Context)testActivity; + } + + /** + * The goal of this test is to confirm that we can obtain + * a search manager interface. + */ + @MediumTest + public void testSearchManagerInterfaceAvailable() { + ISearchManager searchManager1 = ISearchManager.Stub.asInterface( + ServiceManager.getService(Context.SEARCH_SERVICE)); + assertNotNull(searchManager1); + } + + /** + * The goal of this test is to confirm that we can *only* obtain a search manager + * interface from an Activity context. + */ + @MediumTest + public void testSearchManagerContextRestrictions() { + SearchManager searchManager1 = (SearchManager) + mContext.getSystemService(Context.SEARCH_SERVICE); + assertNotNull(searchManager1); + + Context applicationContext = mContext.getApplicationContext(); + // this should fail, because you can't get a SearchManager from a non-Activity context + try { + applicationContext.getSystemService(Context.SEARCH_SERVICE); + assertFalse("Shouldn't retrieve SearchManager from a non-Activity context", true); + } catch (AndroidRuntimeException e) { + // happy here - we should catch this. + } + } + + /** + * The goal of this test is to confirm that we can obtain + * a search manager at any time, and that for any given context, + * it is a singleton. + */ + @LargeTest + public void testSearchManagerAvailable() { + SearchManager searchManager1 = (SearchManager) + mContext.getSystemService(Context.SEARCH_SERVICE); + assertNotNull(searchManager1); + SearchManager searchManager2 = (SearchManager) + mContext.getSystemService(Context.SEARCH_SERVICE); + assertNotNull(searchManager2); + assertSame( searchManager1, searchManager2 ); + } + + /** + * The goal of this test is to confirm that we can start and then + * stop a simple search. + */ + + @MediumTest + public void testSearchManagerInvocations() { + SearchManager searchManager = (SearchManager) + mContext.getSystemService(Context.SEARCH_SERVICE); + assertNotNull(searchManager); + + // TODO: make a real component name, or remove this need + final ComponentName cn = new ComponentName("", ""); + + if (TEST_SEARCH_START != 0) { + // These tests should simply run to completion w/o exceptions + searchManager.startSearch(null, false, cn, null, false); + searchManager.stopSearch(); + + searchManager.startSearch("", false, cn, null, false); + searchManager.stopSearch(); + + searchManager.startSearch("test search string", false, cn, null, false); + searchManager.stopSearch(); + + searchManager.startSearch("test search string", true, cn, null, false); + searchManager.stopSearch(); + } + } + + /** + * The goal of this test is to confirm proper operation of the + * SearchableInfo helper class. + * + * TODO: The metadata source needs to be mocked out because adding + * searchability metadata via this test is causing it to leak into the + * real system. So for now I'm just going to test for existence of the + * GoogleSearch app (which is searchable). + */ + @LargeTest + public void testSearchableGoogleSearch() { + // test basic array & hashmap + SearchableInfo.buildSearchableList(mContext); + + // test linkage from another activity + // TODO inject this via mocking into the package manager. + // TODO for now, just check for searchable GoogleSearch app (this isn't really a unit test) + ComponentName thisActivity = new ComponentName( + "com.android.googlesearch", + "com.android.googlesearch.GoogleSearch"); + + SearchableInfo si = SearchableInfo.getSearchableInfo(mContext, thisActivity); + assertNotNull(si); + assertTrue(si.mSearchable); + assertEquals(thisActivity, si.mSearchActivity); + + Context appContext = si.getActivityContext(mContext); + assertNotNull(appContext); + MoreAsserts.assertNotEqual(appContext, mContext); + assertEquals("Google Search", appContext.getString(si.getHintId())); + assertEquals("Google", appContext.getString(si.getLabelId())); + } + + /** + * Test that non-searchable activities return no searchable info (this would typically + * trigger the use of the default searchable e.g. contacts) + */ + @LargeTest + public void testNonSearchable() { + // test basic array & hashmap + SearchableInfo.buildSearchableList(mContext); + + // confirm that we return null for non-searchy activities + ComponentName nonActivity = new ComponentName( + "com.android.unit_tests", + "com.android.unit_tests.NO_SEARCH_ACTIVITY"); + SearchableInfo si = SearchableInfo.getSearchableInfo(mContext, nonActivity); + assertNull(si); + } + + /** + * This is an attempt to run the searchable info list with a mocked context. Here are some + * things I'd like to test. + * + * Confirm OK with "zero" searchables + * Confirm "good" metadata read properly + * Confirm "bad" metadata skipped properly + * Confirm ordering of searchables + * Confirm "good" actionkeys + * confirm "bad" actionkeys are rejected + * confirm XML ordering enforced (will fail today - bug in SearchableInfo) + * findActionKey works + * getIcon works + + */ + @LargeTest + public void testSearchableMocked() { + MyMockPackageManager mockPM = new MyMockPackageManager(mContext.getPackageManager()); + MyMockContext mockContext = new MyMockContext(mContext, mockPM); + ArrayList<SearchableInfo> searchables; + int count; + + // build item list with real-world source data + mockPM.setSearchablesMode(MyMockPackageManager.SEARCHABLES_PASSTHROUGH); + SearchableInfo.buildSearchableList(mockContext); + // tests with "real" searchables (deprecate, this should be a unit test) + searchables = SearchableInfo.getSearchablesList(); + count = searchables.size(); + assertTrue(count >= 1); // this isn't really a unit test + checkSearchables(searchables); + + // build item list with mocked search data + // this round of tests confirms good operations with "zero" searchables found + // This should return either a null pointer or an empty list + mockPM.setSearchablesMode(MyMockPackageManager.SEARCHABLES_MOCK_ZERO); + SearchableInfo.buildSearchableList(mockContext); + searchables = SearchableInfo.getSearchablesList(); + if (searchables != null) { + count = searchables.size(); + assertTrue(count == 0); + } + } + + /** + * Generic health checker for an array of searchables. + * + * This is designed to pass for any semi-legal searchable, without knowing much about + * the format of the underlying data. It's fairly easy for a non-compliant application + * to provide meta-data that will pass here (e.g. a non-existent suggestions authority). + * + * @param searchables The list of searchables to examine. + */ + private void checkSearchables(ArrayList<SearchableInfo> searchablesList) { + assertNotNull(searchablesList); + int count = searchablesList.size(); + for (int ii = 0; ii < count; ii++) { + SearchableInfo si = searchablesList.get(ii); + assertNotNull(si); + assertTrue(si.mSearchable); + assertTrue(si.getLabelId() != 0); // This must be a useable string + assertNotEmpty(si.mSearchActivity.getClassName()); + assertNotEmpty(si.mSearchActivity.getPackageName()); + if (si.getSuggestAuthority() != null) { + // The suggestion fields are largely optional, so we'll just confirm basic health + assertNotEmpty(si.getSuggestAuthority()); + assertNullOrNotEmpty(si.getSuggestPath()); + assertNullOrNotEmpty(si.getSuggestSelection()); + assertNullOrNotEmpty(si.getSuggestIntentAction()); + assertNullOrNotEmpty(si.getSuggestIntentData()); + } + /* Add a way to get the entire action key list, then explicitly test its elements */ + /* For now, test the most common action key (CALL) */ + ActionKeyInfo ai = si.findActionKey(KeyEvent.KEYCODE_CALL); + if (ai != null) { + assertEquals(ai.mKeyCode, KeyEvent.KEYCODE_CALL); + // one of these three fields must be non-null & non-empty + boolean m1 = (ai.mQueryActionMsg != null) && (ai.mQueryActionMsg.length() > 0); + boolean m2 = (ai.mSuggestActionMsg != null) && (ai.mSuggestActionMsg.length() > 0); + boolean m3 = (ai.mSuggestActionMsgColumn != null) && + (ai.mSuggestActionMsgColumn.length() > 0); + assertTrue(m1 || m2 || m3); + } + + /* + * Find ways to test these: + * + * private int mSearchMode + * private Drawable mIcon + */ + + /* + * Explicitly not tested here: + * + * Can be null, so not much to see: + * public String mSearchHint + * private String mZeroQueryBanner + * + * To be deprecated/removed, so don't bother: + * public boolean mFilterMode + * public boolean mQuickStart + * private boolean mIconResized + * private int mIconResizeWidth + * private int mIconResizeHeight + * + * All of these are "internal" working variables, not part of any contract + * private ActivityInfo mActivityInfo + * private Rect mTempRect + * private String mSuggestProviderPackage + * private String mCacheActivityContext + */ + } + } + + /** + * Combo assert for "string not null and not empty" + */ + private void assertNotEmpty(final String s) { + assertNotNull(s); + MoreAsserts.assertNotEqual(s, ""); + } + + /** + * Combo assert for "string null or (not null and not empty)" + */ + private void assertNullOrNotEmpty(final String s) { + if (s != null) { + MoreAsserts.assertNotEqual(s, ""); + } + } + + /** + * This is a mock for context. Used to perform a true unit test on SearchableInfo. + * + */ + private class MyMockContext extends MockContext { + + protected Context mRealContext; + protected PackageManager mPackageManager; + + /** + * Constructor. + * + * @param realContext Please pass in a real context for some pass-throughs to function. + */ + MyMockContext(Context realContext, PackageManager packageManager) { + mRealContext = realContext; + mPackageManager = packageManager; + } + + /** + * Resources. Pass through for now. + */ + @Override + public Resources getResources() { + return mRealContext.getResources(); + } + + /** + * Package manager. Pass through for now. + */ + @Override + public PackageManager getPackageManager() { + return mPackageManager; + } + + /** + * Package manager. Pass through for now. + */ + @Override + public Context createPackageContext(String packageName, int flags) + throws PackageManager.NameNotFoundException { + return mRealContext.createPackageContext(packageName, flags); + } + } + +/** + * This is a mock for package manager. Used to perform a true unit test on SearchableInfo. + * + */ + private class MyMockPackageManager extends MockPackageManager { + + public final static int SEARCHABLES_PASSTHROUGH = 0; + public final static int SEARCHABLES_MOCK_ZERO = 1; + public final static int SEARCHABLES_MOCK_ONEGOOD = 2; + public final static int SEARCHABLES_MOCK_ONEGOOD_ONEBAD = 3; + + protected PackageManager mRealPackageManager; + protected int mSearchablesMode; + + public MyMockPackageManager(PackageManager realPM) { + mRealPackageManager = realPM; + mSearchablesMode = SEARCHABLES_PASSTHROUGH; + } + + /** + * Set the mode for various tests. + */ + public void setSearchablesMode(int newMode) { + switch (newMode) { + case SEARCHABLES_PASSTHROUGH: + case SEARCHABLES_MOCK_ZERO: + mSearchablesMode = newMode; + break; + + default: + throw new UnsupportedOperationException(); + } + } + + /** + * Find activities that support a given intent. + * + * Retrieve all activities that can be performed for the given intent. + * + * @param intent The desired intent as per resolveActivity(). + * @param flags Additional option flags. The most important is + * MATCH_DEFAULT_ONLY, to limit the resolution to only + * those activities that support the CATEGORY_DEFAULT. + * + * @return A List<ResolveInfo> containing one entry for each matching + * Activity. These are ordered from best to worst match -- that + * is, the first item in the list is what is returned by + * resolveActivity(). If there are no matching activities, an empty + * list is returned. + */ + @Override + public List<ResolveInfo> queryIntentActivities(Intent intent, int flags) { + assertNotNull(intent); + assertEquals(intent.getAction(), Intent.ACTION_SEARCH); + switch (mSearchablesMode) { + case SEARCHABLES_PASSTHROUGH: + return mRealPackageManager.queryIntentActivities(intent, flags); + case SEARCHABLES_MOCK_ZERO: + return null; + default: + throw new UnsupportedOperationException(); + } + } + + /** + * Retrieve an XML file from a package. This is a low-level API used to + * retrieve XML meta data. + * + * @param packageName The name of the package that this xml is coming from. + * Can not be null. + * @param resid The resource identifier of the desired xml. Can not be 0. + * @param appInfo Overall information about <var>packageName</var>. This + * may be null, in which case the application information will be retrieved + * for you if needed; if you already have this information around, it can + * be much more efficient to supply it here. + * + * @return Returns an XmlPullParser allowing you to parse out the XML + * data. Returns null if the xml resource could not be found for any + * reason. + */ + @Override + public XmlResourceParser getXml(String packageName, int resid, ApplicationInfo appInfo) { + assertNotNull(packageName); + MoreAsserts.assertNotEqual(packageName, ""); + MoreAsserts.assertNotEqual(resid, 0); + switch (mSearchablesMode) { + case SEARCHABLES_PASSTHROUGH: + return mRealPackageManager.getXml(packageName, resid, appInfo); + case SEARCHABLES_MOCK_ZERO: + default: + throw new UnsupportedOperationException(); + } + } + + /** + * Find a single content provider by its base path name. + * + * @param name The name of the provider to find. + * @param flags Additional option flags. Currently should always be 0. + * + * @return ContentProviderInfo Information about the provider, if found, + * else null. + */ + @Override + public ProviderInfo resolveContentProvider(String name, int flags) { + assertNotNull(name); + MoreAsserts.assertNotEqual(name, ""); + assertEquals(flags, 0); + switch (mSearchablesMode) { + case SEARCHABLES_PASSTHROUGH: + return mRealPackageManager.resolveContentProvider(name, flags); + case SEARCHABLES_MOCK_ZERO: + default: + throw new UnsupportedOperationException(); + } + } + } +} + diff --git a/tests/AndroidTests/src/com/android/unit_tests/SerializationTest.java b/tests/AndroidTests/src/com/android/unit_tests/SerializationTest.java new file mode 100644 index 0000000..4b64144 --- /dev/null +++ b/tests/AndroidTests/src/com/android/unit_tests/SerializationTest.java @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2008 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.unit_tests; + +import junit.framework.TestCase; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.io.Serializable; +import android.test.suitebuilder.annotation.SmallTest; + +/** + * Tests serialization of user-level classes. + */ +public class SerializationTest extends TestCase { + + static class MySerializable implements Serializable {} + + @SmallTest + public void testSerialization() throws IOException, ClassNotFoundException { + ByteArrayOutputStream bout = new ByteArrayOutputStream(); + ObjectOutputStream oout = new ObjectOutputStream(bout); + oout.writeObject(new MySerializable()); + oout.close(); + + ByteArrayInputStream bin = new ByteArrayInputStream(bout.toByteArray()); + Object o = new ObjectInputStream(bin).readObject(); + assertTrue(o instanceof MySerializable); + } +} diff --git a/tests/AndroidTests/src/com/android/unit_tests/SettingsProviderTest.java b/tests/AndroidTests/src/com/android/unit_tests/SettingsProviderTest.java new file mode 100644 index 0000000..8b1db97 --- /dev/null +++ b/tests/AndroidTests/src/com/android/unit_tests/SettingsProviderTest.java @@ -0,0 +1,147 @@ +/* + * Copyright (C) 2008 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.unit_tests; + +import android.content.ContentResolver; +import android.content.ContentUris; +import android.content.ContentValues; +import android.content.Intent; +import android.database.Cursor; +import android.net.Uri; +import android.provider.Settings; +import android.test.AndroidTestCase; +import android.test.suitebuilder.annotation.MediumTest; + +/** Unit test for SettingsProvider. */ +public class SettingsProviderTest extends AndroidTestCase { + @MediumTest + public void testNameValueCache() { + ContentResolver r = getContext().getContentResolver(); + Settings.Gservices.putString(r, "test_service", "Value"); + assertEquals("Value", Settings.Gservices.getString(r, "test_service")); + + // Make sure the value can be overwritten. + Settings.Gservices.putString(r, "test_service", "New"); + assertEquals("New", Settings.Gservices.getString(r, "test_service")); + + // Also that delete works. + assertEquals(1, r.delete(Settings.Gservices.getUriFor("test_service"), null, null)); + assertEquals(null, Settings.Gservices.getString(r, "test_service")); + + // Try all the same things in the System table + Settings.System.putString(r, "test_setting", "Value"); + assertEquals("Value", Settings.System.getString(r, "test_setting")); + + Settings.System.putString(r, "test_setting", "New"); + assertEquals("New", Settings.System.getString(r, "test_setting")); + + assertEquals(1, r.delete(Settings.System.getUriFor("test_setting"), null, null)); + assertEquals(null, Settings.System.getString(r, "test_setting")); + } + + @MediumTest + public void testRowNameContentUri() { + ContentResolver r = getContext().getContentResolver(); + + assertEquals("content://settings/system/test_setting", + Settings.System.getUriFor("test_setting").toString()); + assertEquals("content://settings/gservices/test_service", + Settings.Gservices.getUriFor("test_service").toString()); + + // These tables use the row name (not ID) as their content URI. + Uri tables[] = { Settings.System.CONTENT_URI, Settings.Gservices.CONTENT_URI }; + for (Uri table : tables) { + ContentValues v = new ContentValues(); + v.put(Settings.System.NAME, "test_key"); + v.put(Settings.System.VALUE, "Test"); + Uri uri = r.insert(table, v); + assertEquals(table.toString() + "/test_key", uri.toString()); + + // Query with a specific URI and no WHERE clause succeeds. + Cursor c = r.query(uri, null, null, null, null); + try { + assertTrue(c.moveToNext()); + assertEquals("test_key", c.getString(c.getColumnIndex(Settings.System.NAME))); + assertEquals("Test", c.getString(c.getColumnIndex(Settings.System.VALUE))); + assertFalse(c.moveToNext()); + } finally { + c.close(); + } + + // Query with a specific URI and a WHERE clause fails. + try { + r.query(uri, null, "1", null, null); + fail("UnsupportedOperationException expected"); + } catch (UnsupportedOperationException e) { + if (!e.toString().contains("WHERE clause")) throw e; + } + + // Query with a tablewide URI and a WHERE clause succeeds. + c = r.query(table, null, "name='test_key'", null, null); + try { + assertTrue(c.moveToNext()); + assertEquals("test_key", c.getString(c.getColumnIndex(Settings.System.NAME))); + assertEquals("Test", c.getString(c.getColumnIndex(Settings.System.VALUE))); + assertFalse(c.moveToNext()); + } finally { + c.close(); + } + + v = new ContentValues(); + v.put(Settings.System.VALUE, "Toast"); + assertEquals(1, r.update(uri, v, null, null)); + + c = r.query(uri, null, null, null, null); + try { + assertTrue(c.moveToNext()); + assertEquals("test_key", c.getString(c.getColumnIndex(Settings.System.NAME))); + assertEquals("Toast", c.getString(c.getColumnIndex(Settings.System.VALUE))); + assertFalse(c.moveToNext()); + } finally { + c.close(); + } + + assertEquals(1, r.delete(uri, null, null)); + } + + assertEquals(null, Settings.System.getString(r, "test_key")); + assertEquals(null, Settings.Gservices.getString(r, "test_key")); + } + + @MediumTest + public void testRowNumberContentUri() { + ContentResolver r = getContext().getContentResolver(); + + // The bookmarks table (and everything else) uses standard row number content URIs. + Uri uri = Settings.Bookmarks.add(r, new Intent("TEST"), + "Test Title", "Test Folder", '*', 123); + + assertTrue(ContentUris.parseId(uri) > 0); + + assertEquals("TEST", Settings.Bookmarks.getIntentForShortcut(r, '*').getAction()); + + ContentValues v = new ContentValues(); + v.put(Settings.Bookmarks.INTENT, "#Intent;action=TOAST;end"); + assertEquals(1, r.update(uri, v, null, null)); + + assertEquals("TOAST", Settings.Bookmarks.getIntentForShortcut(r, '*').getAction()); + + assertEquals(1, r.delete(uri, null, null)); + + assertEquals(null, Settings.Bookmarks.getIntentForShortcut(r, '*')); + } +} diff --git a/tests/AndroidTests/src/com/android/unit_tests/SimplePullParserTest.java b/tests/AndroidTests/src/com/android/unit_tests/SimplePullParserTest.java new file mode 100644 index 0000000..9758298 --- /dev/null +++ b/tests/AndroidTests/src/com/android/unit_tests/SimplePullParserTest.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 com.android.unit_tests; + +import com.google.android.util.SimplePullParser; +import junit.framework.TestCase; +import android.test.suitebuilder.annotation.SmallTest; + +public class SimplePullParserTest extends TestCase { + @SmallTest + public void testTwoLevels() throws Exception { + String xml = "" + + "<top a='1' b='hello'>\n" + + " <next c='2' d='there'/>\n" + + " <next c='3' d='bye'/>\n" + + "</top>"; + SimplePullParser parser = new SimplePullParser(xml); + int depth0 = parser.getDepth(); + assertEquals(0, depth0); + assertEquals("top", parser.nextTag(depth0)); + assertEquals(1, parser.getIntAttribute(null, "a")); + assertEquals("hello", parser.getStringAttribute(null, "b")); + + int depth1 = parser.getDepth(); + assertEquals(1, depth1); + assertEquals("next", parser.nextTag(depth1)); + assertEquals(2, parser.getIntAttribute(null, "c")); + assertEquals("there", parser.getStringAttribute(null, "d")); + assertEquals("next", parser.nextTag(depth1)); + assertEquals(3, parser.getIntAttribute(null, "c")); + assertEquals("bye", parser.getStringAttribute(null, "d")); + assertNull(parser.nextTag(depth1)); + + assertNull(parser.nextTag(depth0)); + } + + @SmallTest + public void testAttributes() throws Exception { + String xml = "<top a='1' b='hello'/>"; + SimplePullParser parser = new SimplePullParser(xml); + int depth = parser.getDepth(); + parser.nextTag(depth); + + assertEquals(2, parser.numAttributes()); + assertEquals("a", parser.getAttributeName(0)); + assertEquals("b", parser.getAttributeName(1)); + + assertEquals(1, parser.getIntAttribute(null, "a")); + assertEquals(5, parser.getIntAttribute(null, "c", 5)); + assertEquals("hello", parser.getStringAttribute(null, "b")); + assertEquals("not", parser.getStringAttribute(null, "d", "not")); + } + + @SmallTest + public void testRecovery() throws Exception { + String xml = "" + + "<top a='1' b='hello'>\n" + + " <middle c='2' d='there'>\n" + + " <inner/>\n" + + " <inner2/>\n" + + " <inner3/>\n" + + " </middle>\n" + + " <middle2/>\n" + + "</top>"; + SimplePullParser parser = new SimplePullParser(xml); + assertEquals(0, parser.getDepth()); + assertEquals("top", parser.nextTag(0)); + assertEquals(1, parser.getDepth()); + assertEquals("middle", parser.nextTag(1)); + assertEquals(2, parser.getDepth()); + assertEquals("inner", parser.nextTag(2)); + // Now skip some elements. + assertEquals("middle2", parser.nextTag(1)); + } + + @SmallTest + public void testCdata() throws Exception { + StringBuilder cdataBuilder; + String xml = "" + + "<top>" + + "<![CDATA[data0]]>" + + "<next0/>" + + "<![CDATA[data1]]>" + + "<next1/>" + + "<![CDATA[data2]]>" + + "<next2/>" + + "<![CDATA[data3]]>" + + "<next3/>" + + "<![CDATA[data4]]>" + + "<next4/>" + + "<![CDATA[data5]]>" + + "</top>"; + SimplePullParser parser = new SimplePullParser(xml); + assertEquals("top", parser.nextTag(0)); + + // We can ignore cdata by not passing a cdata builder. + assertEquals("next0", parser.nextTag(1)); + + // We can get the most recent cdata by passing an empty cdata builder. + cdataBuilder = new StringBuilder(); + assertSame(SimplePullParser.TEXT_TAG, parser.nextTagOrText(1, cdataBuilder)); + assertEquals("data1", cdataBuilder.toString()); + assertEquals("next1", parser.nextTag(1)); + + // We can join multiple cdatas by reusing a builder. + cdataBuilder = new StringBuilder(); + assertSame(SimplePullParser.TEXT_TAG, parser.nextTagOrText(1, cdataBuilder)); + assertEquals("next2", parser.nextTag(1)); + assertSame(SimplePullParser.TEXT_TAG, parser.nextTagOrText(1, cdataBuilder)); + assertEquals("data2data3", cdataBuilder.toString()); + assertEquals("next3", parser.nextTag(1)); + + // We can read all of the remaining cdata while ignoring any elements. + cdataBuilder = new StringBuilder(); + parser.readRemainingText(1, cdataBuilder); + assertEquals("data4data5", cdataBuilder.toString()); + } +} diff --git a/tests/AndroidTests/src/com/android/unit_tests/SmsProviderTest.java b/tests/AndroidTests/src/com/android/unit_tests/SmsProviderTest.java new file mode 100644 index 0000000..0e2f0c5 --- /dev/null +++ b/tests/AndroidTests/src/com/android/unit_tests/SmsProviderTest.java @@ -0,0 +1,76 @@ +/* + * 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.unit_tests; + +import android.content.ContentResolver; +import android.content.ContentValues; +import android.database.Cursor; +import android.net.Uri; +import android.provider.Telephony.Sms; +import android.test.AndroidTestCase; +import android.test.suitebuilder.annotation.LargeTest; + +import java.util.GregorianCalendar; + +public class SmsProviderTest extends AndroidTestCase { + + @LargeTest + public void testProvider() throws Exception { + // This test does the following + // 1. Insert 10 messages from the same number at different times. + // + // . Delete the messages and make sure that they were deleted. + + long now = System.currentTimeMillis(); + + Uri[] urls = new Uri[10]; + String[] dates = new String[]{ + Long.toString(new GregorianCalendar(1970, 1, 1, 0, 0, 0).getTimeInMillis()), + Long.toString(new GregorianCalendar(1971, 2, 13, 16, 35, 3).getTimeInMillis()), + Long.toString(new GregorianCalendar(1978, 10, 22, 0, 1, 0).getTimeInMillis()), + Long.toString(new GregorianCalendar(1980, 1, 11, 10, 22, 30).getTimeInMillis()), + Long.toString(now - (5 * 24 * 60 * 60 * 1000)), + Long.toString(now - (2 * 24 * 60 * 60 * 1000)), + Long.toString(now - (5 * 60 * 60 * 1000)), + Long.toString(now - (30 * 60 * 1000)), + Long.toString(now - (5 * 60 * 1000)), + Long.toString(now) + }; + + ContentValues map = new ContentValues(); + map.put("address", "+15045551337"); + map.put("read", 0); + + ContentResolver contentResolver = mContext.getContentResolver(); + + for (int i = 0; i < urls.length; i++) { + map.put("body", "Test " + i + " !"); + map.put("date", dates[i]); + urls[i] = contentResolver.insert(Sms.Inbox.CONTENT_URI, map); + assertNotNull(urls[i]); + } + + Cursor c = contentResolver.query(Sms.Inbox.CONTENT_URI, null, null, null, "date"); + + //DatabaseUtils.dumpCursor(c); + + for (Uri url : urls) { + int count = contentResolver.delete(url, null, null); + assertEquals(1, count); + } + } +} diff --git a/tests/AndroidTests/src/com/android/unit_tests/SpannedTest.java b/tests/AndroidTests/src/com/android/unit_tests/SpannedTest.java new file mode 100644 index 0000000..9e3f483 --- /dev/null +++ b/tests/AndroidTests/src/com/android/unit_tests/SpannedTest.java @@ -0,0 +1,187 @@ +/* + * Copyright (C) 2008 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.unit_tests; + +import android.graphics.Typeface; +import android.os.Parcel; +import android.test.suitebuilder.annotation.SmallTest; +import android.text.*; +import android.text.style.*; +import android.util.Log; + +import junit.framework.TestCase; + +/** + * SpannedTest tests some features of Spanned + */ +public class SpannedTest extends TestCase { + private int mExpect; + + @SmallTest + public void testSpannableString() throws Exception { + checkPriority(new SpannableString("the quick brown fox")); + } + + @SmallTest + public void testSpannableStringBuilder() throws Exception { + checkPriority2(new SpannableStringBuilder("the quick brown fox")); + } + + @SmallTest + public void testAppend() throws Exception { + Object o = new Object(); + SpannableString ss = new SpannableString("Test"); + ss.setSpan(o, 0, ss.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); + + SpannableStringBuilder ssb = new SpannableStringBuilder(); + ssb.append(ss); + assertEquals(0, ssb.getSpanStart(o)); + assertEquals(4, ssb.getSpanEnd(o)); + assertEquals(1, ssb.getSpans(0, 4, Object.class).length); + + ssb.insert(0, ss); + assertEquals(4, ssb.getSpanStart(o)); + assertEquals(8, ssb.getSpanEnd(o)); + assertEquals(0, ssb.getSpans(0, 4, Object.class).length); + assertEquals(1, ssb.getSpans(4, 8, Object.class).length); + } + + @SmallTest + public void testWrapParcel() { + SpannableString s = new SpannableString("Hello there world"); + CharacterStyle mark = new StyleSpan(Typeface.BOLD); + s.setSpan(mark, 1, 2, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); + s.setSpan(CharacterStyle.wrap(mark), 3, 7, + Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); + s.setSpan(new TextAppearanceSpan("mono", 0, -1, null, null), 7, 8, + Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); + s.setSpan(CharacterStyle.wrap(new TypefaceSpan("mono")), 8, 9, + Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); + + Parcel p = Parcel.obtain(); + TextUtils.writeToParcel(s, p, 0); + p.setDataPosition(0); + + Spanned s2 = (Spanned) TextUtils.CHAR_SEQUENCE_CREATOR. + createFromParcel(p); + StyleSpan[] style; + + style = s2.getSpans(1, 2, StyleSpan.class); + assertEquals(1, style.length); + assertEquals(1, s2.getSpanStart(style[0])); + assertEquals(2, s2.getSpanEnd(style[0])); + + style = s2.getSpans(3, 7, StyleSpan.class); + assertEquals(1, style.length); + assertEquals(3, s2.getSpanStart(style[0])); + assertEquals(7, s2.getSpanEnd(style[0])); + + TextAppearanceSpan[] appearance = s2.getSpans(7, 8, + TextAppearanceSpan.class); + assertEquals(1, appearance.length); + assertEquals(7, s2.getSpanStart(appearance[0])); + assertEquals(8, s2.getSpanEnd(appearance[0])); + + TypefaceSpan[] tf = s2.getSpans(8, 9, TypefaceSpan.class); + assertEquals(1, tf.length); + assertEquals(8, s2.getSpanStart(tf[0])); + assertEquals(9, s2.getSpanEnd(tf[0])); + } + + private void checkPriority(Spannable s) { + s.setSpan(new Object(), 0, 1, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE | + (5 << Spannable.SPAN_PRIORITY_SHIFT)); + s.setSpan(new Object(), 0, 1, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE | + (10 << Spannable.SPAN_PRIORITY_SHIFT)); + s.setSpan(new Object(), 0, 1, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE | + (0 << Spannable.SPAN_PRIORITY_SHIFT)); + s.setSpan(new Object(), 0, 1, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE | + (15 << Spannable.SPAN_PRIORITY_SHIFT)); + s.setSpan(new Object(), 0, 1, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE | + (3 << Spannable.SPAN_PRIORITY_SHIFT)); + s.setSpan(new Object(), 0, 1, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE | + (6 << Spannable.SPAN_PRIORITY_SHIFT)); + s.setSpan(new Object(), 0, 1, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE | + (0 << Spannable.SPAN_PRIORITY_SHIFT)); + + Object[] spans = s.getSpans(0, s.length(), Object.class); + + for (int i = 0; i < spans.length - 1; i++) { + assertEquals((s.getSpanFlags(spans[i]) & Spanned.SPAN_PRIORITY) >= + (s.getSpanFlags(spans[i + 1]) & Spanned.SPAN_PRIORITY), + true); + } + + mExpect = 0; + + s.setSpan(new Watcher(2), 0, s.length(), + Spannable.SPAN_INCLUSIVE_INCLUSIVE | + (2 << Spannable.SPAN_PRIORITY_SHIFT)); + s.setSpan(new Watcher(4), 0, s.length(), + Spannable.SPAN_INCLUSIVE_INCLUSIVE | + (4 << Spannable.SPAN_PRIORITY_SHIFT)); + s.setSpan(new Watcher(1), 0, s.length(), + Spannable.SPAN_INCLUSIVE_INCLUSIVE | + (1 << Spannable.SPAN_PRIORITY_SHIFT)); + s.setSpan(new Watcher(3), 0, s.length(), + Spannable.SPAN_INCLUSIVE_INCLUSIVE | + (3 << Spannable.SPAN_PRIORITY_SHIFT)); + + mExpect = 4; + s.setSpan(new Object(), 0, 1, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); + assertEquals(mExpect, 0); + } + + private void checkPriority2(SpannableStringBuilder ssb) { + checkPriority(ssb); + + mExpect = 4; + ssb.insert(3, "something"); + assertEquals(mExpect, 0); + } + + private class Watcher implements SpanWatcher, TextWatcher { + private int mSequence; + + public Watcher(int sequence) { + mSequence = sequence; + } + + public void onSpanChanged(Spannable b, Object o, int s, int e, + int st, int en) { } + public void onSpanRemoved(Spannable b, Object o, int s, int e) { } + + public void onSpanAdded(Spannable b, Object o, int s, int e) { + if (mExpect != 0) { + assertEquals(mSequence, mExpect); + mExpect = mSequence - 1; + } + } + + public void beforeTextChanged(CharSequence s, int start, int count, + int after) { } + public void onTextChanged(CharSequence s, int start, int before, + int count) { + if (mExpect != 0) { + assertEquals(mSequence, mExpect); + mExpect = mSequence - 1; + } + } + + public void afterTextChanged(Editable s) { } + } +} diff --git a/tests/AndroidTests/src/com/android/unit_tests/StringTest.java b/tests/AndroidTests/src/com/android/unit_tests/StringTest.java new file mode 100644 index 0000000..dc40a0a --- /dev/null +++ b/tests/AndroidTests/src/com/android/unit_tests/StringTest.java @@ -0,0 +1,951 @@ +/* + * 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.unit_tests; + +import java.util.Locale; + +import android.test.PerformanceTestBase; +import android.test.PerformanceTestCase; + +public class StringTest extends PerformanceTestBase { + public static final int ITERATIONS = 1000; + public static final String STATIC_STRING_01 = "Hello Android"; + public static final String STATIC_STRING_02 = + "Remember, today is the tomorrow you worried about yesterday"; + public static final char[] STATIC_CHAR_ARRAY = + {'N', 'A', 'N', 'D', 'R', 'O', 'I', 'D'}; + public static StringBuffer STATIC_SBUF = new StringBuffer(STATIC_STRING_02); + + @Override + public int startPerformance(PerformanceTestCase.Intermediates intermediates) { + intermediates.setInternalIterations(ITERATIONS); + return 0; + } + + /** Create an empty String object* */ + + public void testStringCreate() { + String rString; + for (int i = ITERATIONS - 1; i >= 0; i--) { + rString = new String(); + rString = new String(); + rString = new String(); + rString = new String(); + rString = new String(); + rString = new String(); + rString = new String(); + rString = new String(); + rString = new String(); + rString = new String(); + } + } + + /** Create an initialised String object* */ + + public void testStringCreate1() { + String rString, str = STATIC_STRING_01; + for (int i = ITERATIONS - 1; i >= 0; i--) { + rString = new String(str); + rString = new String(str); + rString = new String(str); + rString = new String(str); + rString = new String(str); + rString = new String(str); + rString = new String(str); + rString = new String(str); + rString = new String(str); + rString = new String(str); // 10 + } + } + + /** equals() with for loop* */ + public void testStringEquals() { + String mString = new String(STATIC_STRING_01); + String str = STATIC_STRING_01; + boolean result; + for (int i = ITERATIONS - 1; i >= 0; i--) { + result = mString.equals(str); + result = mString.equals(str); + result = mString.equals(str); + result = mString.equals(str); + result = mString.equals(str); + result = mString.equals(str); + result = mString.equals(str); + result = mString.equals(str); + result = mString.equals(str); + result = mString.equals(str); + } + } + + /** + * ContentEquals- Comparing the content of a String with that of a String + * Buffer* + */ + + public void testStringContentEquals() { + StringBuffer sBuf = new StringBuffer(STATIC_STRING_01); + String str = STATIC_STRING_01; + boolean result; + for (int i = ITERATIONS - 1; i >= 0; i--) { + result = str.contentEquals(sBuf); + result = str.contentEquals(sBuf); + result = str.contentEquals(sBuf); + result = str.contentEquals(sBuf); + result = str.contentEquals(sBuf); + result = str.contentEquals(sBuf); + result = str.contentEquals(sBuf); + result = str.contentEquals(sBuf); + result = str.contentEquals(sBuf); + result = str.contentEquals(sBuf); + } + } + + /** Compare string objects lexicographically using compareTo() with for loop* */ + + public void testStringCompareTo() { + String str1 = new String(STATIC_STRING_01); + String str2 = STATIC_STRING_01; + int result; + for (int i = ITERATIONS - 1; i >= 0; i--) { + result = str1.compareTo(str2); + result = str1.compareTo(str2); + result = str1.compareTo(str2); + result = str1.compareTo(str2); + result = str1.compareTo(str2); + result = str1.compareTo(str2); + result = str1.compareTo(str2); + result = str1.compareTo(str2); + result = str1.compareTo(str2); + result = str1.compareTo(str2); + } + + } + + /** Compare string objects using compareToIgnorecase() with for loop* */ + + public void testStringCompareToIgnoreCase() { + String mString = new String(STATIC_STRING_01); + String str2 = STATIC_STRING_01; + int result; + for (int i = ITERATIONS - 1; i >= 0; i--) { + result = mString.compareToIgnoreCase(str2); + result = mString.compareToIgnoreCase(str2); + result = mString.compareToIgnoreCase(str2); + result = mString.compareToIgnoreCase(str2); + result = mString.compareToIgnoreCase(str2); + result = mString.compareToIgnoreCase(str2); + result = mString.compareToIgnoreCase(str2); + result = mString.compareToIgnoreCase(str2); + result = mString.compareToIgnoreCase(str2); + result = mString.compareToIgnoreCase(str2); + } + } + + /** startsWith * */ + + public void testStringstartsWith() { + boolean result; + String str1 = STATIC_STRING_02, str2 = "Rem"; + for (int i = ITERATIONS - 1; i >= 0; i--) { + result = str1.startsWith(str2); + result = str1.startsWith(str2); + result = str1.startsWith(str2); + result = str1.startsWith(str2); + result = str1.startsWith(str2); + result = str1.startsWith(str2); + result = str1.startsWith(str2); + result = str1.startsWith(str2); + result = str1.startsWith(str2); + result = str1.startsWith(str2); + } + } + + /** startsWith(String seq, int begin) * */ + + public void testStringstartsWith1() { + String str1 = STATIC_STRING_02, str2 = "tom"; + int pos = 10; + boolean result; + for (int i = ITERATIONS - 1; i >= 0; i--) { + result = str1.startsWith(str2, pos); + result = str1.startsWith(str2, pos); + result = str1.startsWith(str2, pos); + result = str1.startsWith(str2, pos); + result = str1.startsWith(str2, pos); + result = str1.startsWith(str2, pos); + result = str1.startsWith(str2, pos); + result = str1.startsWith(str2, pos); + result = str1.startsWith(str2, pos); + result = str1.startsWith(str2, pos); + } + } + + /** endsWith * */ + + public void testStringendsWith() { + String str = STATIC_STRING_02, str1 = "day"; + boolean result; + for (int i = ITERATIONS - 1; i >= 0; i--) { + result = str.endsWith(str1); + result = str.endsWith(str1); + result = str.endsWith(str1); + result = str.endsWith(str1); + result = str.endsWith(str1); + result = str.endsWith(str1); + result = str.endsWith(str1); + result = str.endsWith(str1); + result = str.endsWith(str1); + result = str.endsWith(str1); + } + } + + /** + * indexOf to determine whether a string contains a substring + */ + public void testStringindexOf() { + boolean result; + String str = STATIC_STRING_02, str1 = "tomo"; + for (int i = ITERATIONS - 1; i >= 0; i--) { + result = str.indexOf(str1) > 0; + result = str.indexOf(str1) > 0; + result = str.indexOf(str1) > 0; + result = str.indexOf(str1) > 0; + result = str.indexOf(str1) > 0; + result = str.indexOf(str1) > 0; + result = str.indexOf(str1) > 0; + result = str.indexOf(str1) > 0; + result = str.indexOf(str1) > 0; + result = str.indexOf(str1) > 0; + } + } + + /** indexOf()* */ + + public void testStringindexOf1() { + int index; + String str = STATIC_STRING_02; + char c = 't'; + for (int i = ITERATIONS - 1; i >= 0; i--) { + index = str.indexOf(c); + index = str.indexOf(c); + index = str.indexOf(c); + index = str.indexOf(c); + index = str.indexOf(c); + index = str.indexOf(c); + index = str.indexOf(c); + index = str.indexOf(c); + index = str.indexOf(c); + index = str.indexOf(c); + } + + } + + /** indexOf(char c, int start)* */ + public void testStringindexOf2() { + int index, pos = 12; + String str = STATIC_STRING_02, str1 = "tom"; + for (int i = ITERATIONS - 1; i >= 0; i--) { + index = str.indexOf(str1, pos); + index = str.indexOf(str1, pos); + index = str.indexOf(str1, pos); + index = str.indexOf(str1, pos); + index = str.indexOf(str1, pos); + index = str.indexOf(str1, pos); + index = str.indexOf(str1, pos); + index = str.indexOf(str1, pos); + index = str.indexOf(str1, pos); + index = str.indexOf(str1, pos); + } + } + + /** lastIndexOf()* */ + + public void testStringlastIndexOf() { + int index; + char c = 't'; + String str = STATIC_STRING_02; + for (int i = ITERATIONS - 1; i >= 0; i--) { + index = str.lastIndexOf(c); + index = str.lastIndexOf(c); + index = str.lastIndexOf(c); + index = str.lastIndexOf(c); + index = str.lastIndexOf(c); + index = str.lastIndexOf(c); + index = str.lastIndexOf(c); + index = str.lastIndexOf(c); + index = str.lastIndexOf(c); + index = str.lastIndexOf(c); + } + } + + /** lastIndexOf()* */ + + public void testStringlastIndexOf1() { + int index, pos = 36; + String str = STATIC_STRING_02, str1 = "tom"; + for (int i = ITERATIONS - 1; i >= 0; i--) { + index = str.lastIndexOf(str1, pos); + index = str.lastIndexOf(str1, pos); + index = str.lastIndexOf(str1, pos); + index = str.lastIndexOf(str1, pos); + index = str.lastIndexOf(str1, pos); + index = str.lastIndexOf(str1, pos); + index = str.lastIndexOf(str1, pos); + index = str.lastIndexOf(str1, pos); + index = str.lastIndexOf(str1, pos); + index = str.lastIndexOf(str1, pos); + } + } + + /** + * contains() to determine whether a string contains a substring + */ + + public void testStringcontains() { + boolean result; + String str = STATIC_STRING_02, str1 = "tomo"; + for (int i = ITERATIONS - 1; i >= 0; i--) { + result = str.contains(str1); + result = str.contains(str1); + result = str.contains(str1); + result = str.contains(str1); + result = str.contains(str1); + result = str.contains(str1); + result = str.contains(str1); + result = str.contains(str1); + result = str.contains(str1); + result = str.contains(str1); + } + } + + /** substring(int start) */ + + public void testStringsubstring() { + String rString; + String str = STATIC_STRING_02; + int index = 10; + for (int i = ITERATIONS - 1; i >= 0; i--) { + rString = str.substring(index); + rString = str.substring(index); + rString = str.substring(index); + rString = str.substring(index); + rString = str.substring(index); + rString = str.substring(index); + rString = str.substring(index); + rString = str.substring(index); + rString = str.substring(index); + rString = str.substring(index); + } + } + + /** substring(int start, int end) in a for loop* */ + + public void testStringsubstring1() { + String rString; + String str = STATIC_STRING_02; + int start = 10, end = 48; + for (int i = ITERATIONS - 1; i >= 0; i--) { + rString = str.substring(start, end); + rString = str.substring(start, end); + rString = str.substring(start, end); + rString = str.substring(start, end); + rString = str.substring(start, end); + rString = str.substring(start, end); + rString = str.substring(start, end); + rString = str.substring(start, end); + rString = str.substring(start, end); + rString = str.substring(start, end); + } + } + + /** + * valueOf(char[] cArray) String representation of a character array + */ + public void testStringvalueOf() { + String rString; + char[] cArray = STATIC_CHAR_ARRAY; + for (int i = ITERATIONS - 1; i >= 0; i--) { + rString = String.valueOf(cArray); + rString = String.valueOf(cArray); + rString = String.valueOf(cArray); + rString = String.valueOf(cArray); + rString = String.valueOf(cArray); + rString = String.valueOf(cArray); + rString = String.valueOf(cArray); + rString = String.valueOf(cArray); + rString = String.valueOf(cArray); + rString = String.valueOf(cArray); + } + } + + /** valueOf(char[] cArray, int offset, int count)* */ + + public void testStringvalueOf1() { + String rString; + char[] cArray = STATIC_CHAR_ARRAY; + int start = 1, end = 7; + for (int i = ITERATIONS - 1; i >= 0; i--) { + rString = String.valueOf(cArray, start, end); + rString = String.valueOf(cArray, start, end); + rString = String.valueOf(cArray, start, end); + rString = String.valueOf(cArray, start, end); + rString = String.valueOf(cArray, start, end); + rString = String.valueOf(cArray, start, end); + rString = String.valueOf(cArray, start, end); + rString = String.valueOf(cArray, start, end); + rString = String.valueOf(cArray, start, end); + rString = String.valueOf(cArray, start, end); + } + } + + /** Convert a string to a char Array* */ + + public void testStringtoCharArray() { + char[] cArray; + String str = STATIC_STRING_02; + for (int i = ITERATIONS - 1; i >= 0; i--) { + cArray = str.toCharArray(); + cArray = str.toCharArray(); + cArray = str.toCharArray(); + cArray = str.toCharArray(); + cArray = str.toCharArray(); + cArray = str.toCharArray(); + cArray = str.toCharArray(); + cArray = str.toCharArray(); + cArray = str.toCharArray(); + cArray = str.toCharArray(); + } + } + + /** length()* */ + + public void testStringlength() { + int len; + String str = STATIC_STRING_02; + for (int i = ITERATIONS - 1; i >= 0; i--) { + len = str.length(); + len = str.length(); + len = str.length(); + len = str.length(); + len = str.length(); + len = str.length(); + len = str.length(); + len = str.length(); + len = str.length(); + len = str.length(); + } + } + + /** hashcode()* */ + + public void testStringhashCode() { + int index; + String str = STATIC_STRING_02; + for (int i = ITERATIONS - 1; i >= 0; i--) { + index = str.hashCode(); + index = str.hashCode(); + index = str.hashCode(); + index = str.hashCode(); + index = str.hashCode(); + index = str.hashCode(); + index = str.hashCode(); + index = str.hashCode(); + index = str.hashCode(); + index = str.hashCode(); + } + } + + /** replace()* */ + + public void testStringreplace() { + String rString; + String str = STATIC_STRING_02; + char c1 = ' ', c2 = ' '; + for (int i = ITERATIONS - 1; i >= 0; i--) { + rString = str.replace(c1, c2); + rString = str.replace(c1, c2); + rString = str.replace(c1, c2); + rString = str.replace(c1, c2); + rString = str.replace(c1, c2); + rString = str.replace(c1, c2); + rString = str.replace(c1, c2); + rString = str.replace(c1, c2); + rString = str.replace(c1, c2); + rString = str.replace(c1, c2); + } + } + + public void testStringreplaceAll() { + String rString; + String str = STATIC_STRING_02, str1 = " ", str2 = "/"; + for (int i = ITERATIONS - 1; i >= 0; i--) { + rString = str.replaceAll(str1, str2); + rString = str.replaceAll(str1, str2); + rString = str.replaceAll(str1, str2); + rString = str.replaceAll(str1, str2); + rString = str.replaceAll(str1, str2); + rString = str.replaceAll(str1, str2); + rString = str.replaceAll(str1, str2); + rString = str.replaceAll(str1, str2); + rString = str.replaceAll(str1, str2); + rString = str.replaceAll(str1, str2); + } + } + + /** Convert a StringBuffer to a String* */ + + public void testStringtoString() { + StringBuffer sBuf = new StringBuffer(STATIC_STRING_02); + + String rString; + for (int i = ITERATIONS - 1; i >= 0; i--) { + rString = sBuf.toString(); + rString = sBuf.toString(); + rString = sBuf.toString(); + rString = sBuf.toString(); + rString = sBuf.toString(); + rString = sBuf.toString(); + rString = sBuf.toString(); + rString = sBuf.toString(); + rString = sBuf.toString(); + rString = sBuf.toString(); + } + } + + /** Split a string into an array of strings* */ + + public void testStringsplit() { + String[] strings; + String str1 = STATIC_STRING_02, str = " "; + for (int i = ITERATIONS - 1; i >= 0; i--) { + strings = str1.split(str); + strings = str1.split(str); + strings = str1.split(str); + strings = str1.split(str); + strings = str1.split(str); + strings = str1.split(str); + strings = str1.split(str); + strings = str1.split(str); + strings = str1.split(str); + strings = str1.split(str); + + } + } + + /** Split a string into an array of strings* */ + + public void testStringsplit1() { + String str = STATIC_STRING_02, str1 = " "; + String[] strings; + int pos = 8; + for (int i = ITERATIONS - 1; i >= 0; i--) { + strings = str.split(str1, pos); + strings = str.split(str1, pos); + strings = str.split(str1, pos); + strings = str.split(str1, pos); + strings = str.split(str1, pos); + strings = str.split(str1, pos); + strings = str.split(str1, pos); + strings = str.split(str1, pos); + strings = str.split(str1, pos); + strings = str.split(str1, pos); + } + } + + public void testStringgetBytes() { + byte[] bytes; + String str = STATIC_STRING_02; + for (int i = ITERATIONS - 1; i >= 0; i--) { + bytes = str.getBytes(); + bytes = str.getBytes(); + bytes = str.getBytes(); + bytes = str.getBytes(); + bytes = str.getBytes(); + bytes = str.getBytes(); + bytes = str.getBytes(); + bytes = str.getBytes(); + bytes = str.getBytes(); + bytes = str.getBytes(); + } + } + + /** copyValueOf(char[] data) * */ + + public void testStringcopyValueOf() { + String rString; + char[] cArray = STATIC_CHAR_ARRAY; + for (int i = ITERATIONS - 1; i >= 0; i--) { + rString = String.copyValueOf(cArray); + rString = String.copyValueOf(cArray); + rString = String.copyValueOf(cArray); + rString = String.copyValueOf(cArray); + rString = String.copyValueOf(cArray); + rString = String.copyValueOf(cArray); + rString = String.copyValueOf(cArray); + rString = String.copyValueOf(cArray); + rString = String.copyValueOf(cArray); + rString = String.copyValueOf(cArray); + } + } + + /** copyValueOf(char[] data, int index, int count)* */ + + public void testStringcopyValueOf1() { + String rString; + int start = 1, end = 7; + char[] cArray = STATIC_CHAR_ARRAY; + for (int i = ITERATIONS - 1; i >= 0; i--) { + rString = String.copyValueOf(cArray, start, end); + rString = String.copyValueOf(cArray, start, end); + rString = String.copyValueOf(cArray, start, end); + rString = String.copyValueOf(cArray, start, end); + rString = String.copyValueOf(cArray, start, end); + rString = String.copyValueOf(cArray, start, end); + rString = String.copyValueOf(cArray, start, end); + rString = String.copyValueOf(cArray, start, end); + rString = String.copyValueOf(cArray, start, end); + rString = String.copyValueOf(cArray, start, end); + } + } + + /** trim()* */ + + public void testStringtrim() { + String mString = + new String( + " HELLO ANDROID "); + String rString; + for (int i = ITERATIONS - 1; i >= 0; i--) { + rString = mString.trim(); + rString = mString.trim(); + rString = mString.trim(); + rString = mString.trim(); + rString = mString.trim(); + rString = mString.trim(); + rString = mString.trim(); + rString = mString.trim(); + rString = mString.trim(); + rString = mString.trim(); + } + } + + /** getChars(int srcBegin, int srcEnd, char[] dst, int dstBegin)* */ + + public void testStringgetChars() { + char[] cArray = STATIC_CHAR_ARRAY; + String str = STATIC_STRING_01; + int value1 = 7, value2 = 12, value3 = 1; + for (int i = ITERATIONS - 1; i >= 0; i--) { + str.getChars(value1, value2, cArray, value3); + str.getChars(value1, value2, cArray, value3); + str.getChars(value1, value2, cArray, value3); + str.getChars(value1, value2, cArray, value3); + str.getChars(value1, value2, cArray, value3); + str.getChars(value1, value2, cArray, value3); + str.getChars(value1, value2, cArray, value3); + str.getChars(value1, value2, cArray, value3); + str.getChars(value1, value2, cArray, value3); + str.getChars(value1, value2, cArray, value3); + } + } + + /** toUpperCase()* */ + + public void testStringtoUpperCase() { + String rString, str = STATIC_STRING_02; + for (int i = ITERATIONS - 1; i >= 0; i--) { + rString = str.toUpperCase(); + rString = str.toUpperCase(); + rString = str.toUpperCase(); + rString = str.toUpperCase(); + rString = str.toUpperCase(); + rString = str.toUpperCase(); + rString = str.toUpperCase(); + rString = str.toUpperCase(); + rString = str.toUpperCase(); + rString = str.toUpperCase(); + } + } + + /** toUpperCase() with locale* */ + + public void testStringtoUpperCase1() { + Locale locale = new Locale("tr"); + String str = STATIC_STRING_02; + String rString; + for (int i = ITERATIONS - 1; i >= 0; i--) { + rString = str.toUpperCase(locale); + rString = str.toUpperCase(locale); + rString = str.toUpperCase(locale); + rString = str.toUpperCase(locale); + rString = str.toUpperCase(locale); + rString = str.toUpperCase(locale); + rString = str.toUpperCase(locale); + rString = str.toUpperCase(locale); + rString = str.toUpperCase(locale); + rString = str.toUpperCase(locale); + } + } + + /** toLowerCase* */ + + public void StringtoLowerCase() { + String rString, str = STATIC_STRING_02; + for (int i = ITERATIONS - 1; i >= 0; i--) { + rString = str.toLowerCase(); + rString = str.toLowerCase(); + rString = str.toLowerCase(); + rString = str.toLowerCase(); + rString = str.toLowerCase(); + rString = str.toLowerCase(); + rString = str.toLowerCase(); + rString = str.toLowerCase(); + rString = str.toLowerCase(); + rString = str.toLowerCase(); + } + } + + /** toLowerCase with locale* */ + + public void testStringtoLowerCase1() { + Locale locale = new Locale("tr"); + String rString, str = STATIC_STRING_02; + for (int i = ITERATIONS - 1; i >= 0; i--) { + rString = str.toLowerCase(locale); + rString = str.toLowerCase(locale); + rString = str.toLowerCase(locale); + rString = str.toLowerCase(locale); + rString = str.toLowerCase(locale); + rString = str.toLowerCase(locale); + rString = str.toLowerCase(locale); + rString = str.toLowerCase(locale); + rString = str.toLowerCase(locale); + rString = str.toLowerCase(locale); + } + } + + /** charAt()* */ + + public void testStringcharAt() { + String str = STATIC_STRING_02; + int index, pos = 21; + for (int i = ITERATIONS - 1; i >= 0; i--) { + index = str.charAt(pos); + index = str.charAt(pos); + index = str.charAt(pos); + index = str.charAt(pos); + index = str.charAt(pos); + index = str.charAt(pos); + index = str.charAt(pos); + index = str.charAt(pos); + index = str.charAt(pos); + index = str.charAt(pos); + } + } + + public void testStringConcat() { + String mString, str1 = STATIC_STRING_01, str2 = STATIC_STRING_02; + for (int i = ITERATIONS - 1; i >= 0; i--) { + mString = str1.concat(str2); + mString = str1.concat(str2); + mString = str1.concat(str2); + mString = str1.concat(str2); + mString = str1.concat(str2); + mString = str1.concat(str2); + mString = str1.concat(str2); + mString = str1.concat(str2); + mString = str1.concat(str2); + mString = str1.concat(str2); + } + } + + public void testStringBufferAppend() { + StringBuffer sBuf = new StringBuffer(" "); + for (int i = ITERATIONS - 1; i >= 0; i--) { + sBuf.append(i); + sBuf.append(i); + sBuf.append(i); + sBuf.append(i); + sBuf.append(i); + sBuf.append(i); + sBuf.append(i); + sBuf.append(i); + sBuf.append(i); + sBuf.append(i); + } + } + + public void testStringBufferInsert() { + StringBuffer sBuf = new StringBuffer(" "); + int index = sBuf.length(); + for (int i = ITERATIONS - 1; i >= 0; i--) { + sBuf.insert(index, i); + sBuf.insert(index, i); + sBuf.insert(index, i); + sBuf.insert(index, i); + sBuf.insert(index, i); + sBuf.insert(index, i); + sBuf.insert(index, i); + sBuf.insert(index, i); + sBuf.insert(index, i); + sBuf.insert(index, i); + } + } + + public void testStringBufferReverse() { + StringBuffer sBuf = STATIC_SBUF; + for (int i = ITERATIONS - 1; i >= 0; i--) { + sBuf.reverse(); + sBuf.reverse(); + sBuf.reverse(); + sBuf.reverse(); + sBuf.reverse(); + sBuf.reverse(); + sBuf.reverse(); + sBuf.reverse(); + sBuf.reverse(); + sBuf.reverse(); + } + } + + public void testStringBufferSubstring() { + StringBuffer sBuf = STATIC_SBUF; + String rString; + int index = 0; + for (int i = ITERATIONS - 1; i >= 0; i--) { + rString = sBuf.substring(index); + rString = sBuf.substring(index); + rString = sBuf.substring(index); + rString = sBuf.substring(index); + rString = sBuf.substring(index); + rString = sBuf.substring(index); + rString = sBuf.substring(index); + rString = sBuf.substring(index); + rString = sBuf.substring(index); + rString = sBuf.substring(index); + } + } + + public void testStringBufferSubstring1() { + StringBuffer sBuf = STATIC_SBUF; + String rString; + int start = 5, end = 25; + for (int i = ITERATIONS - 1; i >= 0; i--) { + rString = sBuf.substring(start, end); + rString = sBuf.substring(start, end); + rString = sBuf.substring(start, end); + rString = sBuf.substring(start, end); + rString = sBuf.substring(start, end); + rString = sBuf.substring(start, end); + rString = sBuf.substring(start, end); + rString = sBuf.substring(start, end); + rString = sBuf.substring(start, end); + rString = sBuf.substring(start, end); + } + } + + public void testStringBufferReplace() { + StringBuffer sBuf = STATIC_SBUF; + int start = 3, end = 6; + String str = "ind"; + for (int i = ITERATIONS - 1; i >= 0; i--) { + sBuf.replace(start, end, str); + sBuf.replace(start, end, str); + sBuf.replace(start, end, str); + sBuf.replace(start, end, str); + sBuf.replace(start, end, str); + sBuf.replace(start, end, str); + sBuf.replace(start, end, str); + sBuf.replace(start, end, str); + sBuf.replace(start, end, str); + sBuf.replace(start, end, str); + } + } + + public void testStringBufferIndexOf() { + StringBuffer sBuf = STATIC_SBUF; + String str = "t"; + int index; + for (int i = ITERATIONS - 1; i >= 0; i--) { + index = sBuf.indexOf(str); + index = sBuf.indexOf(str); + index = sBuf.indexOf(str); + index = sBuf.indexOf(str); + index = sBuf.indexOf(str); + index = sBuf.indexOf(str); + index = sBuf.indexOf(str); + index = sBuf.indexOf(str); + index = sBuf.indexOf(str); + index = sBuf.indexOf(str); + } + } + + public void testStringBufferIndexOf1() { + StringBuffer sBuf = STATIC_SBUF; + String str = "tom"; + int index, pos = 12; + for (int i = ITERATIONS - 1; i >= 0; i--) { + index = sBuf.indexOf(str, pos); + index = sBuf.indexOf(str, pos); + index = sBuf.indexOf(str, pos); + index = sBuf.indexOf(str, pos); + index = sBuf.indexOf(str, pos); + index = sBuf.indexOf(str, pos); + index = sBuf.indexOf(str, pos); + index = sBuf.indexOf(str, pos); + index = sBuf.indexOf(str, pos); + index = sBuf.indexOf(str, pos); + } + + } + + public void testStringBufferLastIndexOf() { + StringBuffer sBuf = STATIC_SBUF; + String str = "t"; + int index; + for (int i = ITERATIONS - 1; i >= 0; i--) { + index = sBuf.lastIndexOf(str); + index = sBuf.lastIndexOf(str); + index = sBuf.lastIndexOf(str); + index = sBuf.lastIndexOf(str); + index = sBuf.lastIndexOf(str); + index = sBuf.lastIndexOf(str); + index = sBuf.lastIndexOf(str); + index = sBuf.lastIndexOf(str); + index = sBuf.lastIndexOf(str); + index = sBuf.lastIndexOf(str); + } + } + + public void testStringBufferLastIndexOf1() { + StringBuffer sBuf = STATIC_SBUF; + int index, pos = 36; + String str = "tom"; + for (int i = ITERATIONS - 1; i >= 0; i--) { + index = sBuf.lastIndexOf(str, pos); + index = sBuf.lastIndexOf(str, pos); + index = sBuf.lastIndexOf(str, pos); + index = sBuf.lastIndexOf(str, pos); + index = sBuf.lastIndexOf(str, pos); + index = sBuf.lastIndexOf(str, pos); + index = sBuf.lastIndexOf(str, pos); + index = sBuf.lastIndexOf(str, pos); + index = sBuf.lastIndexOf(str, pos); + index = sBuf.lastIndexOf(str, pos); + } + } +} diff --git a/tests/AndroidTests/src/com/android/unit_tests/TestHttpClient.java b/tests/AndroidTests/src/com/android/unit_tests/TestHttpClient.java new file mode 100644 index 0000000..9b5e655 --- /dev/null +++ b/tests/AndroidTests/src/com/android/unit_tests/TestHttpClient.java @@ -0,0 +1,116 @@ +/* + * $HeadURL: http://svn.apache.org/repos/asf/jakarta/httpcomponents/httpcore/tags/4.0-alpha6/module-main/src/test/java/org/apache/http/mockup/TestHttpClient.java $ + * $Revision: 576077 $ + * $Date: 2007-09-16 04:50:22 -0700 (Sun, 16 Sep 2007) $ + * + * ==================================================================== + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * <http://www.apache.org/>. + * + */ + +package com.android.unit_tests; + +import java.io.IOException; + +import org.apache.http.ConnectionReuseStrategy; +import org.apache.http.HttpClientConnection; +import org.apache.http.HttpException; +import org.apache.http.HttpHost; +import org.apache.http.HttpRequest; +import org.apache.http.HttpResponse; +import org.apache.http.HttpVersion; +import org.apache.http.impl.DefaultConnectionReuseStrategy; +import org.apache.http.params.BasicHttpParams; +import org.apache.http.params.CoreConnectionPNames; +import org.apache.http.params.DefaultedHttpParams; +import org.apache.http.params.HttpParams; +import org.apache.http.params.CoreProtocolPNames; +import org.apache.http.protocol.BasicHttpProcessor; +import org.apache.http.protocol.HttpContext; +import org.apache.http.protocol.BasicHttpContext; +import org.apache.http.protocol.ExecutionContext; +import org.apache.http.protocol.HttpRequestExecutor; +import org.apache.http.protocol.RequestConnControl; +import org.apache.http.protocol.RequestContent; +import org.apache.http.protocol.RequestExpectContinue; +import org.apache.http.protocol.RequestTargetHost; +import org.apache.http.protocol.RequestUserAgent; + +public class TestHttpClient { + + private final HttpParams params; + private final BasicHttpProcessor httpproc; + private final HttpRequestExecutor httpexecutor; + private final ConnectionReuseStrategy connStrategy; + private final HttpContext context; + + public TestHttpClient() { + super(); + this.params = new BasicHttpParams(); + this.params + .setIntParameter(CoreConnectionPNames.SO_TIMEOUT, 5000) + .setBooleanParameter(CoreConnectionPNames.STALE_CONNECTION_CHECK, false) + .setParameter(CoreProtocolPNames.PROTOCOL_VERSION, HttpVersion.HTTP_1_1) + .setParameter(CoreProtocolPNames.USER_AGENT, "TEST-CLIENT/1.1"); + + this.httpproc = new BasicHttpProcessor(); + // Required protocol interceptors + this.httpproc.addInterceptor(new RequestContent()); + this.httpproc.addInterceptor(new RequestTargetHost()); + // Recommended protocol interceptors + this.httpproc.addInterceptor(new RequestConnControl()); + this.httpproc.addInterceptor(new RequestUserAgent()); + this.httpproc.addInterceptor(new RequestExpectContinue()); + + this.httpexecutor = new HttpRequestExecutor(); + this.connStrategy = new DefaultConnectionReuseStrategy(); + this.context = new BasicHttpContext(null); + } + + public HttpParams getParams() { + return this.params; + } + + public HttpResponse execute( + final HttpRequest request, + final HttpHost targetHost, + final HttpClientConnection conn) throws HttpException, IOException { + this.context.setAttribute(ExecutionContext.HTTP_REQUEST, request); + this.context.setAttribute(ExecutionContext.HTTP_TARGET_HOST, targetHost); + this.context.setAttribute(ExecutionContext.HTTP_CONNECTION, conn); + request.setParams( + new DefaultedHttpParams(request.getParams(), this.params)); + this.httpexecutor.preProcess(request, this.httpproc, this.context); + HttpResponse response = this.httpexecutor.execute(request, conn, this.context); + response.setParams( + new DefaultedHttpParams(response.getParams(), this.params)); + this.httpexecutor.postProcess(response, this.httpproc, this.context); + return response; + } + + public boolean keepAlive(final HttpResponse response) { + return this.connStrategy.keepAlive(response, this.context); + } + +} diff --git a/tests/AndroidTests/src/com/android/unit_tests/TestHttpServer.java b/tests/AndroidTests/src/com/android/unit_tests/TestHttpServer.java new file mode 100644 index 0000000..aae21b3 --- /dev/null +++ b/tests/AndroidTests/src/com/android/unit_tests/TestHttpServer.java @@ -0,0 +1,207 @@ +/* + * $HeadURL: http://svn.apache.org/repos/asf/jakarta/httpcomponents/httpcore/tags/4.0-alpha6/module-main/src/test/java/org/apache/http/mockup/TestHttpServer.java $ + * $Revision: 576077 $ + * $Date: 2007-09-16 04:50:22 -0700 (Sun, 16 Sep 2007) $ + * + * ==================================================================== + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * <http://www.apache.org/>. + * + */ + +package com.android.unit_tests; + + +import java.io.IOException; +import java.io.InterruptedIOException; +import java.net.InetAddress; +import java.net.ServerSocket; +import java.net.Socket; + +import org.apache.http.ConnectionClosedException; +import org.apache.http.ConnectionReuseStrategy; +import org.apache.http.HttpException; +import org.apache.http.HttpResponseFactory; +import org.apache.http.HttpServerConnection; +import org.apache.http.impl.DefaultConnectionReuseStrategy; +import org.apache.http.impl.DefaultHttpResponseFactory; +import org.apache.http.impl.DefaultHttpServerConnection; +import org.apache.http.params.BasicHttpParams; +import org.apache.http.params.CoreConnectionPNames; +import org.apache.http.params.HttpParams; +import org.apache.http.params.CoreProtocolPNames; +import org.apache.http.protocol.BasicHttpProcessor; +import org.apache.http.protocol.HttpContext; +import org.apache.http.protocol.BasicHttpContext; +import org.apache.http.protocol.HttpExpectationVerifier; +import org.apache.http.protocol.HttpRequestHandler; +import org.apache.http.protocol.HttpRequestHandlerRegistry; +import org.apache.http.protocol.HttpService; +import org.apache.http.protocol.ResponseConnControl; +import org.apache.http.protocol.ResponseContent; +import org.apache.http.protocol.ResponseDate; +import org.apache.http.protocol.ResponseServer; + +public class TestHttpServer { + + private final HttpParams params; + private final BasicHttpProcessor httpproc; + private final ConnectionReuseStrategy connStrategy; + private final HttpResponseFactory responseFactory; + private final HttpRequestHandlerRegistry reqistry; + private final ServerSocket serversocket; + + private HttpExpectationVerifier expectationVerifier; + + private Thread listener; + private volatile boolean shutdown; + + public TestHttpServer() throws IOException { + super(); + this.params = new BasicHttpParams(); + this.params + .setIntParameter(CoreConnectionPNames.SO_TIMEOUT, 20000) + .setIntParameter(CoreConnectionPNames.SOCKET_BUFFER_SIZE, 8 * 1024) + .setBooleanParameter(CoreConnectionPNames.STALE_CONNECTION_CHECK, false) + .setBooleanParameter(CoreConnectionPNames.TCP_NODELAY, true) + .setParameter(CoreProtocolPNames.ORIGIN_SERVER, "TEST-SERVER/1.1"); + this.httpproc = new BasicHttpProcessor(); + this.httpproc.addInterceptor(new ResponseDate()); + this.httpproc.addInterceptor(new ResponseServer()); + this.httpproc.addInterceptor(new ResponseContent()); + this.httpproc.addInterceptor(new ResponseConnControl()); + this.connStrategy = new DefaultConnectionReuseStrategy(); + this.responseFactory = new DefaultHttpResponseFactory(); + this.reqistry = new HttpRequestHandlerRegistry(); + this.serversocket = new ServerSocket(0); + } + + public void registerHandler( + final String pattern, + final HttpRequestHandler handler) { + this.reqistry.register(pattern, handler); + } + + public void setExpectationVerifier(final HttpExpectationVerifier expectationVerifier) { + this.expectationVerifier = expectationVerifier; + } + + private HttpServerConnection acceptConnection() throws IOException { + Socket socket = this.serversocket.accept(); + DefaultHttpServerConnection conn = new DefaultHttpServerConnection(); + conn.bind(socket, this.params); + return conn; + } + + public int getPort() { + return this.serversocket.getLocalPort(); + } + + public InetAddress getInetAddress() { + return this.serversocket.getInetAddress(); + } + + public void start() { + if (this.listener != null) { + throw new IllegalStateException("Listener already running"); + } + this.listener = new Thread(new Runnable() { + + public void run() { + while (!shutdown && !Thread.interrupted()) { + try { + // Set up HTTP connection + HttpServerConnection conn = acceptConnection(); + // Set up the HTTP service + HttpService httpService = new HttpService( + httpproc, + connStrategy, + responseFactory); + httpService.setParams(params); + httpService.setExpectationVerifier(expectationVerifier); + httpService.setHandlerResolver(reqistry); + + // Start worker thread + Thread t = new WorkerThread(httpService, conn); + t.setDaemon(true); + t.start(); + } catch (InterruptedIOException ex) { + break; + } catch (IOException e) { + break; + } + } + } + + }); + this.listener.start(); + } + + public void shutdown() { + if (this.shutdown) { + return; + } + this.shutdown = true; + try { + this.serversocket.close(); + } catch (IOException ignore) {} + this.listener.interrupt(); + try { + this.listener.join(1000); + } catch (InterruptedException ignore) {} + } + + static class WorkerThread extends Thread { + + private final HttpService httpservice; + private final HttpServerConnection conn; + + public WorkerThread( + final HttpService httpservice, + final HttpServerConnection conn) { + super(); + this.httpservice = httpservice; + this.conn = conn; + } + + public void run() { + HttpContext context = new BasicHttpContext(null); + try { + while (!Thread.interrupted() && this.conn.isOpen()) { + this.httpservice.handleRequest(this.conn, context); + } + } catch (ConnectionClosedException ex) { + } catch (IOException ex) { + System.err.println("I/O error: " + ex.getMessage()); + } catch (HttpException ex) { + System.err.println("Unrecoverable HTTP protocol violation: " + ex.getMessage()); + } finally { + try { + this.conn.shutdown(); + } catch (IOException ignore) {} + } + } + + } + +} diff --git a/tests/AndroidTests/src/com/android/unit_tests/TestHttpService.java b/tests/AndroidTests/src/com/android/unit_tests/TestHttpService.java new file mode 100644 index 0000000..6b57d13 --- /dev/null +++ b/tests/AndroidTests/src/com/android/unit_tests/TestHttpService.java @@ -0,0 +1,608 @@ +/* + * $HeadURL: http://svn.apache.org/repos/asf/jakarta/httpcomponents/httpcore/tags/4.0-alpha6/module-main/src/test/java/org/apache/http/protocol/TestHttpServiceAndExecutor.java $ + * $Revision: 576073 $ + * $Date: 2007-09-16 03:53:13 -0700 (Sun, 16 Sep 2007) $ + * ==================================================================== + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * <http://www.apache.org/>. + * + */ + +package com.android.unit_tests; + +import org.apache.http.protocol.HttpExpectationVerifier; +import org.apache.http.protocol.HttpRequestHandler; +import android.test.PerformanceTestCase; +import android.test.suitebuilder.annotation.LargeTest; +import android.test.suitebuilder.annotation.MediumTest; + +import junit.framework.TestCase; + +import org.apache.http.Header; +import org.apache.http.HttpConnectionMetrics; +import org.apache.http.HttpEntity; +import org.apache.http.HttpEntityEnclosingRequest; +import org.apache.http.HttpException; +import org.apache.http.HttpHost; +import org.apache.http.HttpRequest; +import org.apache.http.HttpResponse; +import org.apache.http.HttpStatus; +import org.apache.http.HttpVersion; +import org.apache.http.entity.ByteArrayEntity; +import org.apache.http.entity.StringEntity; +import org.apache.http.impl.DefaultHttpClientConnection; +import org.apache.http.message.BasicHttpEntityEnclosingRequest; +import org.apache.http.message.BasicHttpRequest; +import org.apache.http.params.CoreProtocolPNames; +import org.apache.http.protocol.HttpContext; +import org.apache.http.util.EncodingUtils; +import org.apache.http.util.EntityUtils; + + +import java.io.IOException; +import java.net.Socket; +import java.net.URI; +import java.util.ArrayList; +import java.util.List; +import java.util.Random; + +public class TestHttpService extends TestCase implements PerformanceTestCase { + + public boolean isPerformanceOnly() { + // TODO Auto-generated method stub + return false; + } + + public int startPerformance(Intermediates intermediates) { + // TODO Auto-generated method stub + return 0; + } + + private TestHttpServer server; + private TestHttpClient client; + + protected void setUp() throws Exception { + this.server = new TestHttpServer(); + this.client = new TestHttpClient(); + } + + protected void tearDown() throws Exception { + if (server != null) { + this.server.shutdown(); + } + } + + /** + * This test case executes a series of simple GET requests + */ + @LargeTest + public void testSimpleBasicHttpRequests() throws Exception { + + int reqNo = 20; + + Random rnd = new Random(); + + // Prepare some random data + final List testData = new ArrayList(reqNo); + for (int i = 0; i < reqNo; i++) { + int size = rnd.nextInt(5000); + byte[] data = new byte[size]; + rnd.nextBytes(data); + testData.add(data); + } + + // Initialize the server-side request handler + this.server.registerHandler("*", new HttpRequestHandler() { + + public void handle( + final HttpRequest request, + final HttpResponse response, + final HttpContext context) throws HttpException, IOException { + + String s = request.getRequestLine().getUri(); + if (s.startsWith("/?")) { + s = s.substring(2); + } + int index = Integer.parseInt(s); + byte[] data = (byte []) testData.get(index); + ByteArrayEntity entity = new ByteArrayEntity(data); + response.setEntity(entity); + } + + }); + + this.server.start(); + + DefaultHttpClientConnection conn = new DefaultHttpClientConnection(); + HttpHost host = new HttpHost("localhost", this.server.getPort()); + + try { + for (int r = 0; r < reqNo; r++) { + if (!conn.isOpen()) { + Socket socket = new Socket(host.getHostName(), host.getPort()); + conn.bind(socket, this.client.getParams()); + } + + BasicHttpRequest get = new BasicHttpRequest("GET", "/?" + r); + HttpResponse response = this.client.execute(get, host, conn); + byte[] received = EntityUtils.toByteArray(response.getEntity()); + byte[] expected = (byte[]) testData.get(r); + + assertEquals(expected.length, received.length); + for (int i = 0; i < expected.length; i++) { + assertEquals(expected[i], received[i]); + } + if (!this.client.keepAlive(response)) { + conn.close(); + } + } + + //Verify the connection metrics + HttpConnectionMetrics cm = conn.getMetrics(); + assertEquals(reqNo, cm.getRequestCount()); + assertEquals(reqNo, cm.getResponseCount()); + + } finally { + conn.close(); + this.server.shutdown(); + } + } + + /** + * This test case executes a series of simple POST requests with content length + * delimited content. + */ + @LargeTest + public void testSimpleHttpPostsWithContentLength() throws Exception { + + int reqNo = 20; + + Random rnd = new Random(); + + // Prepare some random data + List testData = new ArrayList(reqNo); + for (int i = 0; i < reqNo; i++) { + int size = rnd.nextInt(5000); + byte[] data = new byte[size]; + rnd.nextBytes(data); + testData.add(data); + } + + // Initialize the server-side request handler + this.server.registerHandler("*", new HttpRequestHandler() { + + public void handle( + final HttpRequest request, + final HttpResponse response, + final HttpContext context) throws HttpException, IOException { + + if (request instanceof HttpEntityEnclosingRequest) { + HttpEntity incoming = ((HttpEntityEnclosingRequest) request).getEntity(); + byte[] data = EntityUtils.toByteArray(incoming); + + ByteArrayEntity outgoing = new ByteArrayEntity(data); + outgoing.setChunked(false); + response.setEntity(outgoing); + } else { + StringEntity outgoing = new StringEntity("No content"); + response.setEntity(outgoing); + } + } + + }); + + this.server.start(); + + DefaultHttpClientConnection conn = new DefaultHttpClientConnection(); + HttpHost host = new HttpHost("localhost", this.server.getPort()); + + try { + for (int r = 0; r < reqNo; r++) { + if (!conn.isOpen()) { + Socket socket = new Socket(host.getHostName(), host.getPort()); + conn.bind(socket, this.client.getParams()); + } + + BasicHttpEntityEnclosingRequest post = new BasicHttpEntityEnclosingRequest("POST", "/"); + byte[] data = (byte[]) testData.get(r); + ByteArrayEntity outgoing = new ByteArrayEntity(data); + post.setEntity(outgoing); + + HttpResponse response = this.client.execute(post, host, conn); + byte[] received = EntityUtils.toByteArray(response.getEntity()); + byte[] expected = (byte[]) testData.get(r); + + assertEquals(expected.length, received.length); + for (int i = 0; i < expected.length; i++) { + assertEquals(expected[i], received[i]); + } + if (!this.client.keepAlive(response)) { + conn.close(); + } + } + //Verify the connection metrics + HttpConnectionMetrics cm = conn.getMetrics(); + assertEquals(reqNo, cm.getRequestCount()); + assertEquals(reqNo, cm.getResponseCount()); + + } finally { + conn.close(); + this.server.shutdown(); + } + } + + /** + * This test case executes a series of simple POST requests with chunk + * coded content content. + */ + @LargeTest + public void testSimpleHttpPostsChunked() throws Exception { + + int reqNo = 20; + + Random rnd = new Random(); + + // Prepare some random data + List testData = new ArrayList(reqNo); + for (int i = 0; i < reqNo; i++) { + int size = rnd.nextInt(20000); + byte[] data = new byte[size]; + rnd.nextBytes(data); + testData.add(data); + } + + // Initialize the server-side request handler + this.server.registerHandler("*", new HttpRequestHandler() { + + public void handle( + final HttpRequest request, + final HttpResponse response, + final HttpContext context) throws HttpException, IOException { + + if (request instanceof HttpEntityEnclosingRequest) { + HttpEntity incoming = ((HttpEntityEnclosingRequest) request).getEntity(); + byte[] data = EntityUtils.toByteArray(incoming); + + ByteArrayEntity outgoing = new ByteArrayEntity(data); + outgoing.setChunked(true); + response.setEntity(outgoing); + } else { + StringEntity outgoing = new StringEntity("No content"); + response.setEntity(outgoing); + } + } + + }); + + this.server.start(); + + DefaultHttpClientConnection conn = new DefaultHttpClientConnection(); + HttpHost host = new HttpHost("localhost", this.server.getPort()); + + try { + for (int r = 0; r < reqNo; r++) { + if (!conn.isOpen()) { + Socket socket = new Socket(host.getHostName(), host.getPort()); + conn.bind(socket, this.client.getParams()); + } + + BasicHttpEntityEnclosingRequest post = new BasicHttpEntityEnclosingRequest("POST", "/"); + byte[] data = (byte[]) testData.get(r); + ByteArrayEntity outgoing = new ByteArrayEntity(data); + outgoing.setChunked(true); + post.setEntity(outgoing); + + HttpResponse response = this.client.execute(post, host, conn); + byte[] received = EntityUtils.toByteArray(response.getEntity()); + byte[] expected = (byte[]) testData.get(r); + + assertEquals(expected.length, received.length); + for (int i = 0; i < expected.length; i++) { + assertEquals(expected[i], received[i]); + } + if (!this.client.keepAlive(response)) { + conn.close(); + } + } + //Verify the connection metrics + HttpConnectionMetrics cm = conn.getMetrics(); + assertEquals(reqNo, cm.getRequestCount()); + assertEquals(reqNo, cm.getResponseCount()); + } finally { + conn.close(); + this.server.shutdown(); + } + } + + /** + * This test case executes a series of simple HTTP/1.0 POST requests. + */ + @LargeTest + public void testSimpleHttpPostsHTTP10() throws Exception { + + int reqNo = 20; + + Random rnd = new Random(); + + // Prepare some random data + List testData = new ArrayList(reqNo); + for (int i = 0; i < reqNo; i++) { + int size = rnd.nextInt(5000); + byte[] data = new byte[size]; + rnd.nextBytes(data); + testData.add(data); + } + + // Initialize the server-side request handler + this.server.registerHandler("*", new HttpRequestHandler() { + + public void handle( + final HttpRequest request, + final HttpResponse response, + final HttpContext context) throws HttpException, IOException { + + if (request instanceof HttpEntityEnclosingRequest) { + HttpEntity incoming = ((HttpEntityEnclosingRequest) request).getEntity(); + byte[] data = EntityUtils.toByteArray(incoming); + + ByteArrayEntity outgoing = new ByteArrayEntity(data); + outgoing.setChunked(false); + response.setEntity(outgoing); + } else { + StringEntity outgoing = new StringEntity("No content"); + response.setEntity(outgoing); + } + } + + }); + + this.server.start(); + + // Set protocol level to HTTP/1.0 + this.client.getParams().setParameter( + CoreProtocolPNames.PROTOCOL_VERSION, HttpVersion.HTTP_1_0); + + DefaultHttpClientConnection conn = new DefaultHttpClientConnection(); + HttpHost host = new HttpHost("localhost", this.server.getPort()); + + try { + for (int r = 0; r < reqNo; r++) { + if (!conn.isOpen()) { + Socket socket = new Socket(host.getHostName(), host.getPort()); + conn.bind(socket, this.client.getParams()); + } + + BasicHttpEntityEnclosingRequest post = new BasicHttpEntityEnclosingRequest("POST", "/"); + byte[] data = (byte[]) testData.get(r); + ByteArrayEntity outgoing = new ByteArrayEntity(data); + post.setEntity(outgoing); + + HttpResponse response = this.client.execute(post, host, conn); + assertEquals(HttpVersion.HTTP_1_0, response.getStatusLine().getProtocolVersion()); + byte[] received = EntityUtils.toByteArray(response.getEntity()); + byte[] expected = (byte[]) testData.get(r); + + assertEquals(expected.length, received.length); + for (int i = 0; i < expected.length; i++) { + assertEquals(expected[i], received[i]); + } + if (!this.client.keepAlive(response)) { + conn.close(); + } + } + + //Verify the connection metrics + HttpConnectionMetrics cm = conn.getMetrics(); + assertEquals(reqNo, cm.getRequestCount()); + assertEquals(reqNo, cm.getResponseCount()); + } finally { + conn.close(); + this.server.shutdown(); + } + } + + /** + * This test case executes a series of simple POST requests using + * the 'expect: continue' handshake. + */ + @LargeTest + public void testHttpPostsWithExpectContinue() throws Exception { + + int reqNo = 20; + + Random rnd = new Random(); + + // Prepare some random data + List testData = new ArrayList(reqNo); + for (int i = 0; i < reqNo; i++) { + int size = rnd.nextInt(5000); + byte[] data = new byte[size]; + rnd.nextBytes(data); + testData.add(data); + } + + // Initialize the server-side request handler + this.server.registerHandler("*", new HttpRequestHandler() { + + public void handle( + final HttpRequest request, + final HttpResponse response, + final HttpContext context) throws HttpException, IOException { + + if (request instanceof HttpEntityEnclosingRequest) { + HttpEntity incoming = ((HttpEntityEnclosingRequest) request).getEntity(); + byte[] data = EntityUtils.toByteArray(incoming); + + ByteArrayEntity outgoing = new ByteArrayEntity(data); + outgoing.setChunked(true); + response.setEntity(outgoing); + } else { + StringEntity outgoing = new StringEntity("No content"); + response.setEntity(outgoing); + } + } + + }); + + this.server.start(); + + // Activate 'expect: continue' handshake + this.client.getParams().setBooleanParameter(CoreProtocolPNames.USE_EXPECT_CONTINUE, true); + + DefaultHttpClientConnection conn = new DefaultHttpClientConnection(); + HttpHost host = new HttpHost("localhost", this.server.getPort()); + + try { + for (int r = 0; r < reqNo; r++) { + if (!conn.isOpen()) { + Socket socket = new Socket(host.getHostName(), host.getPort()); + conn.bind(socket, this.client.getParams()); + } + + BasicHttpEntityEnclosingRequest post = new BasicHttpEntityEnclosingRequest("POST", "/"); + byte[] data = (byte[]) testData.get(r); + ByteArrayEntity outgoing = new ByteArrayEntity(data); + outgoing.setChunked(true); + post.setEntity(outgoing); + + HttpResponse response = this.client.execute(post, host, conn); + byte[] received = EntityUtils.toByteArray(response.getEntity()); + byte[] expected = (byte[]) testData.get(r); + + assertEquals(expected.length, received.length); + for (int i = 0; i < expected.length; i++) { + assertEquals(expected[i], received[i]); + } + if (!this.client.keepAlive(response)) { + conn.close(); + } + } + + //Verify the connection metrics + HttpConnectionMetrics cm = conn.getMetrics(); + assertEquals(reqNo, cm.getRequestCount()); + assertEquals(reqNo, cm.getResponseCount()); + } finally { + conn.close(); + this.server.shutdown(); + } + } + + + /** + * This test case executes a series of simple POST requests that do not + * meet the target server expectations. + */ + @LargeTest + public void testHttpPostsWithExpectationVerification() throws Exception { + + int reqNo = 3; + + // Initialize the server-side request handler + this.server.registerHandler("*", new HttpRequestHandler() { + + public void handle( + final HttpRequest request, + final HttpResponse response, + final HttpContext context) throws HttpException, IOException { + + StringEntity outgoing = new StringEntity("No content"); + response.setEntity(outgoing); + } + + }); + + this.server.setExpectationVerifier(new HttpExpectationVerifier() { + + public void verify( + final HttpRequest request, + final HttpResponse response, + final HttpContext context) throws HttpException { + Header someheader = request.getFirstHeader("Secret"); + if (someheader != null) { + int secretNumber; + try { + secretNumber = Integer.parseInt(someheader.getValue()); + } catch (NumberFormatException ex) { + response.setStatusCode(HttpStatus.SC_BAD_REQUEST); + return; + } + if (secretNumber < 2) { + response.setStatusCode(HttpStatus.SC_EXPECTATION_FAILED); + ByteArrayEntity outgoing = new ByteArrayEntity( + EncodingUtils.getAsciiBytes("Wrong secret number")); + response.setEntity(outgoing); + } + } + } + + }); + + this.server.start(); + + // Activate 'expect: continue' handshake + this.client.getParams().setBooleanParameter(CoreProtocolPNames.USE_EXPECT_CONTINUE, true); + + DefaultHttpClientConnection conn = new DefaultHttpClientConnection(); + HttpHost host = new HttpHost("localhost", this.server.getPort()); + + try { + for (int r = 0; r < reqNo; r++) { + if (!conn.isOpen()) { + Socket socket = new Socket(host.getHostName(), host.getPort()); + conn.bind(socket, this.client.getParams()); + } + + BasicHttpEntityEnclosingRequest post = new BasicHttpEntityEnclosingRequest("POST", "/"); + post.addHeader("Secret", Integer.toString(r)); + ByteArrayEntity outgoing = new ByteArrayEntity( + EncodingUtils.getAsciiBytes("No content")); + post.setEntity(outgoing); + + HttpResponse response = this.client.execute(post, host, conn); + + HttpEntity entity = response.getEntity(); + assertNotNull(entity); + entity.consumeContent(); + + if (r < 2) { + assertEquals(HttpStatus.SC_EXPECTATION_FAILED, response.getStatusLine().getStatusCode()); + } else { + assertEquals(HttpStatus.SC_OK, response.getStatusLine().getStatusCode()); + } + + if (!this.client.keepAlive(response)) { + conn.close(); + } + } + //Verify the connection metrics + HttpConnectionMetrics cm = conn.getMetrics(); + assertEquals(reqNo, cm.getRequestCount()); + assertEquals(reqNo, cm.getResponseCount()); + } finally { + conn.close(); + this.server.shutdown(); + } + } + +} diff --git a/tests/AndroidTests/src/com/android/unit_tests/TextLayoutTest.java b/tests/AndroidTests/src/com/android/unit_tests/TextLayoutTest.java new file mode 100644 index 0000000..8cfcd5e --- /dev/null +++ b/tests/AndroidTests/src/com/android/unit_tests/TextLayoutTest.java @@ -0,0 +1,51 @@ +/* + * 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.unit_tests; + +import android.test.suitebuilder.annotation.SmallTest; +import android.text.DynamicLayout; +import android.text.Layout; +import android.text.StaticLayout; +import android.text.TextPaint; +import junit.framework.TestCase; + + +public class TextLayoutTest extends TestCase { + + protected String mString; + protected TextPaint mPaint; + + protected void setUp() throws Exception { + super.setUp(); + mString = "The quick brown fox"; + mPaint = new TextPaint(); + } + + @SmallTest + public void testStaticLayout() throws Exception { + Layout l = new StaticLayout(mString, mPaint, 200, + Layout.Alignment.ALIGN_NORMAL, 1, 0, + true); + } + + @SmallTest + public void testDynamicLayoutTest() throws Exception { + Layout l = new DynamicLayout(mString, mPaint, 200, + Layout.Alignment.ALIGN_NORMAL, 1, 0, + true); + } +} diff --git a/tests/AndroidTests/src/com/android/unit_tests/TextUtilsTest.java b/tests/AndroidTests/src/com/android/unit_tests/TextUtilsTest.java new file mode 100644 index 0000000..51e841c --- /dev/null +++ b/tests/AndroidTests/src/com/android/unit_tests/TextUtilsTest.java @@ -0,0 +1,358 @@ +/* + * Copyright (C) 2008 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.unit_tests; + +import com.google.android.collect.Lists; +import com.google.android.collect.Maps; + +import android.graphics.Paint; +import android.test.suitebuilder.annotation.LargeTest; +import android.test.suitebuilder.annotation.SmallTest; +import android.text.Spannable; +import android.text.SpannableString; +import android.text.Spanned; +import android.text.SpannedString; +import android.text.TextPaint; +import android.text.TextUtils; +import android.text.style.StyleSpan; +import android.text.util.Rfc822Validator; +import android.test.MoreAsserts; + +import junit.framework.TestCase; + +import java.util.List; +import java.util.Map; + +/** + * TextUtilsTest tests {@link TextUtils}. + */ +public class TextUtilsTest extends TestCase { + + @SmallTest + public void testBasic() throws Exception { + assertEquals("", TextUtils.concat()); + assertEquals("foo", TextUtils.concat("foo")); + assertEquals("foobar", TextUtils.concat("foo", "bar")); + assertEquals("foobarbaz", TextUtils.concat("foo", "bar", "baz")); + + SpannableString foo = new SpannableString("foo"); + foo.setSpan("foo", 1, 2, Spannable.SPAN_EXCLUSIVE_INCLUSIVE); + + SpannableString bar = new SpannableString("bar"); + bar.setSpan("bar", 1, 2, Spannable.SPAN_EXCLUSIVE_INCLUSIVE); + + SpannableString baz = new SpannableString("baz"); + baz.setSpan("baz", 1, 2, Spannable.SPAN_EXCLUSIVE_INCLUSIVE); + + assertEquals("foo", TextUtils.concat(foo).toString()); + assertEquals("foobar", TextUtils.concat(foo, bar).toString()); + assertEquals("foobarbaz", TextUtils.concat(foo, bar, baz).toString()); + + assertEquals(1, ((Spanned) TextUtils.concat(foo)).getSpanStart("foo")); + + assertEquals(1, ((Spanned) TextUtils.concat(foo, bar)).getSpanStart("foo")); + assertEquals(4, ((Spanned) TextUtils.concat(foo, bar)).getSpanStart("bar")); + + assertEquals(1, ((Spanned) TextUtils.concat(foo, bar, baz)).getSpanStart("foo")); + assertEquals(4, ((Spanned) TextUtils.concat(foo, bar, baz)).getSpanStart("bar")); + assertEquals(7, ((Spanned) TextUtils.concat(foo, bar, baz)).getSpanStart("baz")); + + assertTrue(TextUtils.concat("foo", "bar") instanceof String); + assertTrue(TextUtils.concat(foo, bar) instanceof SpannedString); + } + + @SmallTest + public void testTemplateString() throws Exception { + CharSequence result; + + result = TextUtils.expandTemplate("This is a ^1 of the ^2 broadcast ^3.", + "test", "emergency", "system"); + assertEquals("This is a test of the emergency broadcast system.", + result.toString()); + + result = TextUtils.expandTemplate("^^^1^^^2^3^a^1^^b^^^c", + "one", "two", "three"); + assertEquals("^one^twothree^aone^b^^c", + result.toString()); + + result = TextUtils.expandTemplate("^"); + assertEquals("^", result.toString()); + + result = TextUtils.expandTemplate("^^"); + assertEquals("^", result.toString()); + + result = TextUtils.expandTemplate("^^^"); + assertEquals("^^", result.toString()); + + result = TextUtils.expandTemplate("shorter ^1 values ^2.", "a", ""); + assertEquals("shorter a values .", result.toString()); + + try { + TextUtils.expandTemplate("Only ^1 value given, but ^2 used.", "foo"); + fail(); + } catch (IllegalArgumentException e) { + } + + try { + TextUtils.expandTemplate("^1 value given, and ^0 used.", "foo"); + fail(); + } catch (IllegalArgumentException e) { + } + + result = TextUtils.expandTemplate("^1 value given, and ^9 used.", + "one", "two", "three", "four", "five", + "six", "seven", "eight", "nine"); + assertEquals("one value given, and nine used.", result.toString()); + + try { + TextUtils.expandTemplate("^1 value given, and ^10 used.", + "one", "two", "three", "four", "five", + "six", "seven", "eight", "nine", "ten"); + fail(); + } catch (IllegalArgumentException e) { + } + + // putting carets in the values: expansion is not recursive. + + result = TextUtils.expandTemplate("^2", "foo", "^^"); + assertEquals("^^", result.toString()); + + result = TextUtils.expandTemplate("^^2", "foo", "1"); + assertEquals("^2", result.toString()); + + result = TextUtils.expandTemplate("^1", "value with ^2 in it", "foo"); + assertEquals("value with ^2 in it", result.toString()); + } + + /** Fail unless text+spans contains a span 'spanName' with the given start and end. */ + private void checkContains(Spanned text, String[] spans, String spanName, + int start, int end) throws Exception { + for (String i: spans) { + if (i.equals(spanName)) { + assertEquals(start, text.getSpanStart(i)); + assertEquals(end, text.getSpanEnd(i)); + return; + } + } + fail(); + } + + @SmallTest + public void testTemplateSpan() throws Exception { + SpannableString template; + Spanned result; + String[] spans; + + // ordinary replacement + + template = new SpannableString("a^1b"); + template.setSpan("before", 0, 1, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); + template.setSpan("during", 1, 3, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); + template.setSpan("after", 3, 4, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); + template.setSpan("during+after", 1, 4, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); + + result = (Spanned) TextUtils.expandTemplate(template, "foo"); + assertEquals(5, result.length()); + spans = result.getSpans(0, result.length(), String.class); + + // value is one character longer, so span endpoints should change. + assertEquals(4, spans.length); + checkContains(result, spans, "before", 0, 1); + checkContains(result, spans, "during", 1, 4); + checkContains(result, spans, "after", 4, 5); + checkContains(result, spans, "during+after", 1, 5); + + + // replacement with empty string + + result = (Spanned) TextUtils.expandTemplate(template, ""); + assertEquals(2, result.length()); + spans = result.getSpans(0, result.length(), String.class); + + // the "during" span should disappear. + assertEquals(3, spans.length); + checkContains(result, spans, "before", 0, 1); + checkContains(result, spans, "after", 1, 2); + checkContains(result, spans, "during+after", 1, 2); + } + + @SmallTest + public void testStringSplitterSimple() { + stringSplitterTestHelper("a,b,cde", new String[] {"a", "b", "cde"}); + } + + @SmallTest + public void testStringSplitterEmpty() { + stringSplitterTestHelper("", new String[] {}); + } + + @SmallTest + public void testStringSplitterWithLeadingEmptyString() { + stringSplitterTestHelper(",a,b,cde", new String[] {"", "a", "b", "cde"}); + } + + @SmallTest + public void testStringSplitterWithInternalEmptyString() { + stringSplitterTestHelper("a,b,,cde", new String[] {"a", "b", "", "cde"}); + } + + @SmallTest + public void testStringSplitterWithTrailingEmptyString() { + // A single trailing emtpy string should be ignored. + stringSplitterTestHelper("a,b,cde,", new String[] {"a", "b", "cde"}); + } + + private void stringSplitterTestHelper(String string, String[] expectedStrings) { + TextUtils.StringSplitter splitter = new TextUtils.SimpleStringSplitter(','); + splitter.setString(string); + List<String> strings = Lists.newArrayList(); + for (String s : splitter) { + strings.add(s); + } + MoreAsserts.assertEquals(expectedStrings, strings.toArray(new String[]{})); + } + + @SmallTest + public void testTrim() { + String[] strings = { "abc", " abc", " abc", "abc ", "abc ", + " abc ", " abc ", "\nabc\n", "\nabc", "abc\n" }; + + for (String s : strings) { + assertEquals(s.trim().length(), TextUtils.getTrimmedLength(s)); + } + } + + //============================================================================================== + // Email validator + //============================================================================================== + + @SmallTest + public void testEmailValidator() { + Rfc822Validator validator = new Rfc822Validator("gmail.com"); + String[] validEmails = new String[] { + "a@b.com", "a@b.fr", "a+b@c.com", "a@b.info", + }; + + for (String email : validEmails) { + assertTrue(email + " should be a valid email address", validator.isValid(email)); + } + + String[] invalidEmails = new String[] { + "a", "a@b", "a b", "a@b.12" + }; + + for (String email : invalidEmails) { + assertFalse(email + " should not be a valid email address", validator.isValid(email)); + } + + Map<String, String> fixes = Maps.newHashMap(); + fixes.put("a", "<a@gmail.com>"); + fixes.put("a b", "<ab@gmail.com>"); + fixes.put("a@b", "<a@b>"); + + for (Map.Entry<String, String> e : fixes.entrySet()) { + assertEquals(e.getValue(), validator.fixText(e.getKey()).toString()); + } + } + + @LargeTest + public void testEllipsize() { + CharSequence s1 = "The quick brown fox jumps over \u00FEhe lazy dog."; + CharSequence s2 = new Wrapper(s1); + Spannable s3 = new SpannableString(s1); + s3.setSpan(new StyleSpan(0), 5, 10, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); + TextPaint p = new TextPaint(); + + for (int i = 0; i < 100; i++) { + for (int j = 0; j < 3; j++) { + TextUtils.TruncateAt kind = null; + + switch (j) { + case 0: + kind = TextUtils.TruncateAt.START; + break; + + case 1: + kind = TextUtils.TruncateAt.END; + break; + + case 2: + kind = TextUtils.TruncateAt.MIDDLE; + break; + } + + String out1 = TextUtils.ellipsize(s1, p, i, kind).toString(); + String out2 = TextUtils.ellipsize(s2, p, i, kind).toString(); + String out3 = TextUtils.ellipsize(s3, p, i, kind).toString(); + + String keep1 = TextUtils.ellipsize(s1, p, i, kind, true, null).toString(); + String keep2 = TextUtils.ellipsize(s2, p, i, kind, true, null).toString(); + String keep3 = TextUtils.ellipsize(s3, p, i, kind, true, null).toString(); + + String trim1 = keep1.replace("\uFEFF", ""); + + // Are all normal output strings identical? + assertEquals("wid " + i + " pass " + j, out1, out2); + assertEquals("wid " + i + " pass " + j, out2, out3); + + // Are preserved output strings identical? + assertEquals("wid " + i + " pass " + j, keep1, keep2); + assertEquals("wid " + i + " pass " + j, keep2, keep3); + + // Does trimming padding from preserved yield normal? + assertEquals("wid " + i + " pass " + j, out1, trim1); + + // Did preserved output strings preserve length? + assertEquals("wid " + i + " pass " + j, keep1.length(), s1.length()); + + // Does the output string actually fit in the space? + assertTrue("wid " + i + " pass " + j, p.measureText(out1) <= i); + + // Is the padded output the same width as trimmed output? + assertTrue("wid " + i + " pass " + j, p.measureText(keep1) == p.measureText(out1)); + } + } + } + + /** + * CharSequence wrapper for testing the cases where text is copied into + * a char array instead of working from a String or a Spanned. + */ + private static class Wrapper implements CharSequence { + private CharSequence mString; + + public Wrapper(CharSequence s) { + mString = s; + } + + public int length() { + return mString.length(); + } + + public char charAt(int off) { + return mString.charAt(off); + } + + public String toString() { + return mString.toString(); + } + + public CharSequence subSequence(int start, int end) { + return new Wrapper(mString.subSequence(start, end)); + } + } +} diff --git a/tests/AndroidTests/src/com/android/unit_tests/TextViewPerformanceTest.java b/tests/AndroidTests/src/com/android/unit_tests/TextViewPerformanceTest.java new file mode 100644 index 0000000..6fa8f4f --- /dev/null +++ b/tests/AndroidTests/src/com/android/unit_tests/TextViewPerformanceTest.java @@ -0,0 +1,132 @@ +/* + * 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.unit_tests; + +import android.content.Context; +import android.graphics.Bitmap; +import android.graphics.Canvas; +import android.graphics.Paint; +import android.test.AndroidTestCase; +import android.test.suitebuilder.annotation.MediumTest; +import android.test.suitebuilder.annotation.SmallTest; +import android.text.SpannedString; +import android.view.View; +import android.view.ViewGroup; +import android.widget.TextView; + +public class TextViewPerformanceTest extends AndroidTestCase { + + private String mString = "The quick brown fox"; + private Canvas mCanvas; + private PerformanceTextView mTextView; + private Paint mPaint; + private PerformanceLabelView mLabelView; + + @Override + protected void setUp() throws Exception { + super.setUp(); + + Bitmap mBitmap = Bitmap.createBitmap(320, 240, Bitmap.Config.RGB_565); + mCanvas = new Canvas(mBitmap); + + ViewGroup.LayoutParams p = new ViewGroup.LayoutParams(320, 240); + + mLabelView = new PerformanceLabelView(mContext); + mLabelView.setText(mString); + mLabelView.measure(View.MeasureSpec.AT_MOST | 320, View.MeasureSpec.AT_MOST | 240); + mLabelView.mySetFrame(320, 240); + mLabelView.setLayoutParams(p); + mLabelView.myDraw(mCanvas); + + mPaint = new Paint(); + mCanvas.save(); + mTextView = new PerformanceTextView(mContext); + mTextView.setLayoutParams(p); + mTextView.setText(mString); + mTextView.mySetFrame(320, 240); + mTextView.measure(View.MeasureSpec.AT_MOST | 320, View.MeasureSpec.AT_MOST | 240); + } + + @MediumTest + public void testDrawTextViewLine() throws Exception { + mTextView.myDraw(mCanvas); + mTextView.myDraw(mCanvas); + mTextView.myDraw(mCanvas); + mTextView.myDraw(mCanvas); + mTextView.myDraw(mCanvas); + mTextView.myDraw(mCanvas); + mTextView.myDraw(mCanvas); + mTextView.myDraw(mCanvas); + mTextView.myDraw(mCanvas); + mTextView.myDraw(mCanvas); + } + + @SmallTest + public void testSpan() throws Exception { + CharSequence charSeq = new SpannedString(mString); + mTextView.setText(charSeq); + + mTextView.myDraw(mCanvas); + mTextView.myDraw(mCanvas); + mTextView.myDraw(mCanvas); + mTextView.myDraw(mCanvas); + mTextView.myDraw(mCanvas); + mTextView.myDraw(mCanvas); + mTextView.myDraw(mCanvas); + mTextView.myDraw(mCanvas); + mTextView.myDraw(mCanvas); + mTextView.myDraw(mCanvas); + } + + @SmallTest + public void testCanvasDrawText() throws Exception { + mCanvas.drawText(mString, 30, 30, mPaint); + } + + @SmallTest + public void testLabelViewDraw() throws Exception { + mLabelView.myDraw(mCanvas); + } + + private class PerformanceTextView extends TextView { + public PerformanceTextView(Context context) { + super(context); + } + + final void myDraw(Canvas c) { + super.onDraw(c); + } + + final void mySetFrame(int w, int h) { + super.setFrame(0, 0, w, h); + } + } + + private class PerformanceLabelView extends LabelView { + public PerformanceLabelView(Context context) { + super(context); + } + + final void myDraw(Canvas c) { + super.onDraw(c); + } + + final void mySetFrame(int w, int h) { + super.setFrame(0, 0, w, h); + } + } +} diff --git a/tests/AndroidTests/src/com/android/unit_tests/TextViewTest.java b/tests/AndroidTests/src/com/android/unit_tests/TextViewTest.java new file mode 100644 index 0000000..8e49118 --- /dev/null +++ b/tests/AndroidTests/src/com/android/unit_tests/TextViewTest.java @@ -0,0 +1,61 @@ +/* + * Copyright (C) 2008 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.unit_tests; + +import com.google.android.collect.Lists; +import com.google.android.collect.Maps; + +import android.test.AndroidTestCase; +import android.test.suitebuilder.annotation.SmallTest; +import android.text.GetChars; +import android.widget.TextView; + +/** + * TextViewTest tests {@link TextView}. + */ +public class TextViewTest extends AndroidTestCase { + + @SmallTest + public void testArray() throws Exception { + TextView tv = new TextView(mContext); + + char[] c = new char[] { 'H', 'e', 'l', 'l', 'o', ' ', + 'W', 'o', 'r', 'l', 'd', '!' }; + + tv.setText(c, 1, 4); + CharSequence oldText = tv.getText(); + + tv.setText(c, 4, 5); + CharSequence newText = tv.getText(); + + assertTrue(newText == oldText); + + assertEquals(5, newText.length()); + assertEquals('o', newText.charAt(0)); + assertEquals("o Wor", newText.toString()); + + assertEquals(" Wo", newText.subSequence(1, 4)); + + char[] c2 = new char[7]; + ((GetChars) newText).getChars(1, 4, c2, 2); + assertEquals('\0', c2[1]); + assertEquals(' ', c2[2]); + assertEquals('W', c2[3]); + assertEquals('o', c2[4]); + assertEquals('\0', c2[5]); + } +} diff --git a/tests/AndroidTests/src/com/android/unit_tests/ThreadBitmapTest.java b/tests/AndroidTests/src/com/android/unit_tests/ThreadBitmapTest.java new file mode 100644 index 0000000..220bc99 --- /dev/null +++ b/tests/AndroidTests/src/com/android/unit_tests/ThreadBitmapTest.java @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2008 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.unit_tests; + +import junit.framework.TestCase; +import android.graphics.Bitmap; +import android.test.suitebuilder.annotation.LargeTest; + +public class ThreadBitmapTest extends TestCase { + + @Override + protected void setUp() throws Exception { + } + + @LargeTest + public void testCreation() { + for (int i = 0; i < 200; i++) { + + new MThread().start(); + } + } + + class MThread extends Thread { + public Bitmap b; + + public MThread() { + b = Bitmap.createBitmap(300, 300, Bitmap.Config.RGB_565); + } + + public void run() {} + } +} + diff --git a/tests/AndroidTests/src/com/android/unit_tests/TimeTest.java b/tests/AndroidTests/src/com/android/unit_tests/TimeTest.java new file mode 100644 index 0000000..110caa4 --- /dev/null +++ b/tests/AndroidTests/src/com/android/unit_tests/TimeTest.java @@ -0,0 +1,525 @@ +/* + * 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.unit_tests; + +import android.test.suitebuilder.annotation.SmallTest; +import android.test.suitebuilder.annotation.Suppress; +import android.text.format.Time; +import android.util.Log; + +import junit.framework.TestCase; + +public class TimeTest extends TestCase { + + @SmallTest + public void testNormalize0() throws Exception { + Time t = new Time(Time.TIMEZONE_UTC); + t.parse("20060432T010203"); + t.normalize(false /* use isDst */); +// System.out.println("got: " + t.year + '-' +// + t.month + '-' + t.monthDay +// + ' ' + t.hour + ':' + t.minute +// + ':' + t.second +// + "( " + t.isDst + ',' + t.gmtoff +// + ',' + t.weekDay +// + ',' + t.yearDay + ')'); + } + + private static class DateTest { + public int year1; + public int month1; + public int day1; + public int hour1; + public int minute1; + public int dst1; + + public int offset; + + public int year2; + public int month2; + public int day2; + public int hour2; + public int minute2; + public int dst2; + + public DateTest(int year1, int month1, int day1, int hour1, int minute1, int dst1, + int offset, int year2, int month2, int day2, int hour2, int minute2, + int dst2) { + this.year1 = year1; + this.month1 = month1; + this.day1 = day1; + this.hour1 = hour1; + this.minute1 = minute1; + this.dst1 = dst1; + this.offset = offset; + this.year2 = year2; + this.month2 = month2; + this.day2 = day2; + this.hour2 = hour2; + this.minute2 = minute2; + this.dst2 = dst2; + } + + public DateTest(int year1, int month1, int day1, int hour1, int minute1, + int offset, int year2, int month2, int day2, int hour2, int minute2) { + this.year1 = year1; + this.month1 = month1; + this.day1 = day1; + this.hour1 = hour1; + this.minute1 = minute1; + this.dst1 = -1; + this.offset = offset; + this.year2 = year2; + this.month2 = month2; + this.day2 = day2; + this.hour2 = hour2; + this.minute2 = minute2; + this.dst2 = -1; + } + } + + // These tests assume that DST changes on Nov 4, 2007 at 2am (to 1am). + + // The "offset" field in "dayTests" represents days. + // Use normalize(true) with these tests to change the date by 1 day. + private DateTest[] dayTests = { + // The month numbers are 0-relative, so Jan=0, Feb=1,...Dec=11 + + // Nov 4, 12am + 0 day = Nov 4, 12am + // Nov 5, 12am + 0 day = Nov 5, 12am + new DateTest(2007, 10, 4, 0, 0, 0, 2007, 10, 4, 0, 0), + new DateTest(2007, 10, 5, 0, 0, 0, 2007, 10, 5, 0, 0), + + // Nov 3, 12am + 1 day = Nov 4, 12am + // Nov 4, 12am + 1 day = Nov 5, 12am + // Nov 5, 12am + 1 day = Nov 6, 12am + new DateTest(2007, 10, 3, 0, 0, 1, 2007, 10, 4, 0, 0), + new DateTest(2007, 10, 4, 0, 0, 1, 2007, 10, 5, 0, 0), + new DateTest(2007, 10, 5, 0, 0, 1, 2007, 10, 6, 0, 0), + + // Nov 3, 1am + 1 day = Nov 4, 1am + // Nov 4, 1am + 1 day = Nov 5, 1am + // Nov 5, 1am + 1 day = Nov 6, 1am + new DateTest(2007, 10, 3, 1, 0, 1, 2007, 10, 4, 1, 0), + new DateTest(2007, 10, 4, 1, 0, 1, 2007, 10, 5, 1, 0), + new DateTest(2007, 10, 5, 1, 0, 1, 2007, 10, 6, 1, 0), + + // Nov 3, 2am + 1 day = Nov 4, 2am + // Nov 4, 2am + 1 day = Nov 5, 2am + // Nov 5, 2am + 1 day = Nov 6, 2am + new DateTest(2007, 10, 3, 2, 0, 1, 2007, 10, 4, 2, 0), + new DateTest(2007, 10, 4, 2, 0, 1, 2007, 10, 5, 2, 0), + new DateTest(2007, 10, 5, 2, 0, 1, 2007, 10, 6, 2, 0), + }; + + // The "offset" field in "minuteTests" represents minutes. + // Use normalize(false) with these tests. + private DateTest[] minuteTests = { + // The month numbers are 0-relative, so Jan=0, Feb=1,...Dec=11 + + // Nov 4, 12am + 0 minutes = Nov 4, 12am + // Nov 5, 12am + 0 minutes = Nov 5, 12am + new DateTest(2007, 10, 4, 0, 0, 0, 2007, 10, 4, 0, 0), + new DateTest(2007, 10, 5, 0, 0, 0, 2007, 10, 5, 0, 0), + + // Nov 3, 12am + 60 minutes = Nov 3, 1am + // Nov 4, 12am + 60 minutes = Nov 4, 1am + // Nov 5, 12am + 60 minutes = Nov 5, 1am + new DateTest(2007, 10, 3, 0, 0, 60, 2007, 10, 3, 1, 0), + new DateTest(2007, 10, 4, 0, 0, 60, 2007, 10, 4, 1, 0), + new DateTest(2007, 10, 5, 0, 0, 60, 2007, 10, 5, 1, 0), + + // Nov 3, 1am + 60 minutes = Nov 3, 2am + // Nov 4, 1am (PDT) + 30 minutes = Nov 4, 1:30am (PDT) + // Nov 4, 1am (PDT) + 60 minutes = Nov 4, 1am (PST) + new DateTest(2007, 10, 3, 1, 0, 60, 2007, 10, 3, 2, 0), + new DateTest(2007, 10, 4, 1, 0, 1, 30, 2007, 10, 4, 1, 30, 1), + new DateTest(2007, 10, 4, 1, 0, 1, 60, 2007, 10, 4, 1, 0, 0), + + // Nov 4, 1:30am (PDT) + 15 minutes = Nov 4, 1:45am (PDT) + // Nov 4, 1:30am (PDT) + 30 minutes = Nov 4, 1:00am (PST) + // Nov 4, 1:30am (PDT) + 60 minutes = Nov 4, 1:30am (PST) + new DateTest(2007, 10, 4, 1, 30, 1, 15, 2007, 10, 4, 1, 45, 1), + new DateTest(2007, 10, 4, 1, 30, 1, 30, 2007, 10, 4, 1, 0, 0), + new DateTest(2007, 10, 4, 1, 30, 1, 60, 2007, 10, 4, 1, 30, 0), + + // Nov 4, 1:30am (PST) + 15 minutes = Nov 4, 1:45am (PST) + // Nov 4, 1:30am (PST) + 30 minutes = Nov 4, 2:00am (PST) + // Nov 5, 1am + 60 minutes = Nov 5, 2am + new DateTest(2007, 10, 4, 1, 30, 0, 15, 2007, 10, 4, 1, 45, 0), + new DateTest(2007, 10, 4, 1, 30, 0, 30, 2007, 10, 4, 2, 0, 0), + new DateTest(2007, 10, 5, 1, 0, 60, 2007, 10, 5, 2, 0), + + // Nov 3, 2am + 60 minutes = Nov 3, 3am + // Nov 4, 2am + 30 minutes = Nov 4, 2:30am + // Nov 4, 2am + 60 minutes = Nov 4, 3am + // Nov 5, 2am + 60 minutes = Nov 5, 3am + new DateTest(2007, 10, 3, 2, 0, 60, 2007, 10, 3, 3, 0), + new DateTest(2007, 10, 4, 2, 0, 30, 2007, 10, 4, 2, 30), + new DateTest(2007, 10, 4, 2, 0, 60, 2007, 10, 4, 3, 0), + new DateTest(2007, 10, 5, 2, 0, 60, 2007, 10, 5, 3, 0), + }; + + @SmallTest + public void testNormalize1() throws Exception { + Time local = new Time("America/Los_Angeles"); + + int len = dayTests.length; + for (int index = 0; index < len; index++) { + DateTest test = dayTests[index]; + local.set(0, test.minute1, test.hour1, test.day1, test.month1, test.year1); + // call normalize() to make sure that isDst is set + local.normalize(false /* use isDst */); + local.monthDay += test.offset; + local.normalize(true /* ignore isDst */); + if (local.year != test.year2 || local.month != test.month2 + || local.monthDay != test.day2 || local.hour != test.hour2 + || local.minute != test.minute2) { + String expectedTime = String.format("%d-%02d-%02d %02d:%02d", + test.year2, test.month2, test.day2, test.hour2, test.minute2); + String actualTime = String.format("%d-%02d-%02d %02d:%02d", + local.year, local.month, local.monthDay, local.hour, local.minute); + throw new RuntimeException( + "day test index " + index + ", normalize(): expected local " + expectedTime + + " got: " + actualTime); + } + + local.set(0, test.minute1, test.hour1, test.day1, test.month1, test.year1); + // call normalize() to make sure that isDst is set + local.normalize(false /* use isDst */); + local.monthDay += test.offset; + long millis = local.toMillis(true /* ignore isDst */); + local.set(millis); + if (local.year != test.year2 || local.month != test.month2 + || local.monthDay != test.day2 || local.hour != test.hour2 + || local.minute != test.minute2) { + String expectedTime = String.format("%d-%02d-%02d %02d:%02d", + test.year2, test.month2, test.day2, test.hour2, test.minute2); + String actualTime = String.format("%d-%02d-%02d %02d:%02d", + local.year, local.month, local.monthDay, local.hour, local.minute); + throw new RuntimeException( + "day test index " + index + ", toMillis(): expected local " + expectedTime + + " got: " + actualTime); + } + } + + len = minuteTests.length; + for (int index = 0; index < len; index++) { + DateTest test = minuteTests[index]; + local.set(0, test.minute1, test.hour1, test.day1, test.month1, test.year1); + local.isDst = test.dst1; + // call normalize() to make sure that isDst is set + local.normalize(false /* use isDst */); + if (test.dst2 == -1) test.dst2 = local.isDst; + local.minute += test.offset; + local.normalize(false /* use isDst */); + if (local.year != test.year2 || local.month != test.month2 + || local.monthDay != test.day2 || local.hour != test.hour2 + || local.minute != test.minute2 || local.isDst != test.dst2) { + String expectedTime = String.format("%d-%02d-%02d %02d:%02d isDst: %d", + test.year2, test.month2, test.day2, test.hour2, test.minute2, + test.dst2); + String actualTime = String.format("%d-%02d-%02d %02d:%02d isDst: %d", + local.year, local.month, local.monthDay, local.hour, local.minute, + local.isDst); + throw new RuntimeException( + "minute test index " + index + ", normalize(): expected local " + expectedTime + + " got: " + actualTime); + } + + local.set(0, test.minute1, test.hour1, test.day1, test.month1, test.year1); + local.isDst = test.dst1; + // call normalize() to make sure that isDst is set + local.normalize(false /* use isDst */); + if (test.dst2 == -1) test.dst2 = local.isDst; + local.minute += test.offset; + long millis = local.toMillis(false /* use isDst */); + local.set(millis); + if (local.year != test.year2 || local.month != test.month2 + || local.monthDay != test.day2 || local.hour != test.hour2 + || local.minute != test.minute2 || local.isDst != test.dst2) { + String expectedTime = String.format("%d-%02d-%02d %02d:%02d isDst: %d", + test.year2, test.month2, test.day2, test.hour2, test.minute2, + test.dst2); + String actualTime = String.format("%d-%02d-%02d %02d:%02d isDst: %d", + local.year, local.month, local.monthDay, local.hour, local.minute, + local.isDst); + throw new RuntimeException( + "minute test index " + index + ", toMillis(): expected local " + expectedTime + + " got: " + actualTime); + } + } + } + + @SmallTest + public void testSwitchTimezone0() throws Exception { + Time t = new Time(Time.TIMEZONE_UTC); + t.parse("20061005T120000"); + t.switchTimezone("America/Los_Angeles"); + // System.out.println("got: " + t); + } + + @SmallTest + public void testCtor0() throws Exception { + Time t = new Time(Time.TIMEZONE_UTC); + assertEquals(Time.TIMEZONE_UTC, t.timezone); + } + + @SmallTest + public void testGetActualMaximum0() throws Exception { + Time t = new Time(Time.TIMEZONE_UTC); + int r = t.getActualMaximum(Time.SECOND); + // System.out.println("r=" + r); + } + + @SmallTest + public void testClear0() throws Exception { + Time t = new Time(Time.TIMEZONE_UTC); + t.clear(Time.TIMEZONE_UTC); + } + + @SmallTest + public void testCompare0() throws Exception { + Time a = new Time(Time.TIMEZONE_UTC); + Time b = new Time("America/Los_Angeles"); + int r = Time.compare(a, b); + // System.out.println("r=" + r); + } + + @SmallTest + public void testFormat0() throws Exception { + Time t = new Time(Time.TIMEZONE_UTC); + String r = t.format("%Y%m%dT%H%M%S"); + // System.out.println("r='" + r + "'"); + } + + @SmallTest + public void testToString0() throws Exception { + Time t = new Time(Time.TIMEZONE_UTC); + String r = t.toString(); + // System.out.println("r='" + r + "'"); + } + + @SmallTest + public void testGetCurrentTimezone0() throws Exception { + String r = Time.getCurrentTimezone(); + // System.out.println("r='" + r + "'"); + } + + @SmallTest + public void testSetToNow0() throws Exception { + Time t = new Time(Time.TIMEZONE_UTC); + t.setToNow(); + // System.out.println("t=" + t); + } + + @SmallTest + public void testMillis0() throws Exception { + Time t = new Time(Time.TIMEZONE_UTC); + t.set(0, 0, 0, 1, 1, 2006); + long r = t.toMillis(true /* ignore isDst */); + // System.out.println("r=" + r); + t.set(1, 0, 0, 1, 1, 2006); + r = t.toMillis(true /* ignore isDst */); + // System.out.println("r=" + r); + } + + @SmallTest + public void testMillis1() throws Exception { + Time t = new Time(Time.TIMEZONE_UTC); + t.set(1, 0, 0, 1, 0, 1970); + long r = t.toMillis(true /* ignore isDst */); + // System.out.println("r=" + r); + } + + @SmallTest + public void testParse0() throws Exception { + Time t = new Time(Time.TIMEZONE_UTC); + t.parse("12345678T901234"); + // System.out.println("t=" + t); + } + + @SmallTest + public void testSet0() throws Exception { + Time t = new Time(Time.TIMEZONE_UTC); + t.set(1000L); + // System.out.println("t.year=" + t.year); + // System.out.println("t=" + t); + t.set(2000L); + // System.out.println("t=" + t); + t.set(1000L * 60); + // System.out.println("t=" + t); + t.set((1000L * 60 * 60 * 24) + 1000L); + // System.out.println("t=" + t); + } + + @SmallTest + public void testSet1() throws Exception { + Time t = new Time(Time.TIMEZONE_UTC); + t.set(1, 2, 3, 4, 5, 6); + // System.out.println("t=" + t); + } + + // Timezones that cover the world. Some GMT offsets occur more than + // once in case some cities decide to change their GMT offset. + private static final String[] mTimeZones = { + "Pacific/Kiritimati", + "Pacific/Enderbury", + "Pacific/Fiji", + "Antarctica/South_Pole", + "Pacific/Norfolk", + "Pacific/Ponape", + "Asia/Magadan", + "Australia/Lord_Howe", + "Australia/Sydney", + "Australia/Adelaide", + "Asia/Tokyo", + "Asia/Seoul", + "Asia/Taipei", + "Asia/Singapore", + "Asia/Hong_Kong", + "Asia/Saigon", + "Asia/Bangkok", + "Indian/Cocos", + "Asia/Rangoon", + "Asia/Omsk", + "Antarctica/Mawson", + "Asia/Colombo", + "Asia/Calcutta", + "Asia/Oral", + "Asia/Kabul", + "Asia/Dubai", + "Asia/Tehran", + "Europe/Moscow", + "Asia/Baghdad", + "Africa/Mogadishu", + "Europe/Athens", + "Africa/Cairo", + "Europe/Rome", + "Europe/Berlin", + "Europe/Amsterdam", + "Africa/Tunis", + "Europe/London", + "Europe/Dublin", + "Atlantic/St_Helena", + "Africa/Monrovia", + "Africa/Accra", + "Atlantic/Azores", + "Atlantic/South_Georgia", + "America/Noronha", + "America/Sao_Paulo", + "America/Cayenne", + "America/St_Johns", + "America/Puerto_Rico", + "America/Aruba", + "America/New_York", + "America/Chicago", + "America/Denver", + "America/Los_Angeles", + "America/Anchorage", + "Pacific/Marquesas", + "America/Adak", + "Pacific/Honolulu", + "Pacific/Midway", + }; + + @Suppress + public void disableTestGetJulianDay() throws Exception { + Time time = new Time(); + + // For each day of the year, and for each timezone, get the Julian + // day for 12am and then check that if we change the time we get the + // same Julian day. + for (int monthDay = 1; monthDay <= 366; monthDay++) { + for (int zoneIndex = 0; zoneIndex < mTimeZones.length; zoneIndex++) { + // We leave the "month" as zero because we are changing the + // "monthDay" from 1 to 366. The call to normalize() will + // then change the "month" (but we don't really care). + time.set(0, 0, 0, monthDay, 0, 2008); + time.timezone = mTimeZones[zoneIndex]; + long millis = time.normalize(true); + if (zoneIndex == 0) { + Log.i("TimeTest", time.format("%B %d, %Y")); + } + + // This is the Julian day for 12am for this day of the year + int julianDay = Time.getJulianDay(millis, time.gmtoff); + + // Change the time during the day and check that we get the same + // Julian day. + for (int hour = 0; hour < 24; hour++) { + for (int minute = 0; minute < 60; minute += 15) { + time.set(0, minute, hour, monthDay, 0, 2008); + millis = time.normalize(true); + int day = Time.getJulianDay(millis, time.gmtoff); + if (day != julianDay) { + Log.e("TimeTest", "Julian day: " + day + " at time " + + time.hour + ":" + time.minute + + " != today's Julian day: " + julianDay + + " timezone: " + time.timezone); + } + assertEquals(day, julianDay); + } + } + } + } + } + + @Suppress + public void disableTestSetJulianDay() throws Exception { + Time time = new Time(); + + // For each day of the year in 2008, and for each timezone, + // test that we can set the Julian day correctly. + for (int monthDay = 1; monthDay <= 366; monthDay++) { + for (int zoneIndex = 0; zoneIndex < mTimeZones.length; zoneIndex++) { + // We leave the "month" as zero because we are changing the + // "monthDay" from 1 to 366. The call to normalize() will + // then change the "month" (but we don't really care). + time.set(0, 0, 0, monthDay, 0, 2008); + time.timezone = mTimeZones[zoneIndex]; + long millis = time.normalize(true); + if (zoneIndex == 0) { + Log.i("TimeTest", time.format("%B %d, %Y")); + } + int julianDay = Time.getJulianDay(millis, time.gmtoff); + + time.setJulianDay(julianDay); + + // Some places change daylight saving time at 12am and so there + // is no 12am on some days in some timezones. In those cases, + // the time is set to 1am. + // Examples: Africa/Cairo on April 25, 2008 + // America/Sao_Paulo on October 12, 2008 + // Atlantic/Azores on March 30, 2008 + assertTrue(time.hour == 0 || time.hour == 1); + assertEquals(0, time.minute); + assertEquals(0, time.second); + + millis = time.toMillis(false); + int day = Time.getJulianDay(millis, time.gmtoff); + if (day != julianDay) { + Log.i("TimeTest", "Error: gmtoff " + (time.gmtoff / 3600.0) + + " day " + julianDay + + " millis " + millis + + " " + time.format("%B %d, %Y") + " " + time.timezone); + } + assertEquals(day, julianDay); + } + } + } +} diff --git a/tests/AndroidTests/src/com/android/unit_tests/TimeUtilsTest.java b/tests/AndroidTests/src/com/android/unit_tests/TimeUtilsTest.java new file mode 100644 index 0000000..6ba64fd --- /dev/null +++ b/tests/AndroidTests/src/com/android/unit_tests/TimeUtilsTest.java @@ -0,0 +1,432 @@ +/* + * 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 com.android.unit_tests; + +import junit.framework.TestCase; + +import android.util.TimeUtils; + +import java.util.Calendar; +import java.util.TimeZone; + +/** + * TimeUtilsTest tests the time zone guesser. + */ +public class TimeUtilsTest extends TestCase { + public void testMainstream() throws Exception { + String[] mainstream = new String[] { + "America/New_York", // Eastern + "America/Chicago", // Central + "America/Denver", // Mountain + "America/Los_Angeles", // Pacific + "America/Anchorage", // Alaska + "Pacific/Honolulu", // Hawaii, no DST + }; + + for (String name : mainstream) { + TimeZone tz = TimeZone.getTimeZone(name); + Calendar c = Calendar.getInstance(tz); + TimeZone guess; + + c.set(2008, Calendar.OCTOBER, 20, 12, 00, 00); + guess = guess(c, "us"); + assertEquals(name, guess.getID()); + + c.set(2009, Calendar.JANUARY, 20, 12, 00, 00); + guess = guess(c, "us"); + assertEquals(name, guess.getID()); + } + } + + public void testWeird() throws Exception { + String[] weird = new String[] { + "America/Phoenix", // Mountain, no DST + "America/Adak", // Same as Hawaii, but with DST + }; + + for (String name : weird) { + TimeZone tz = TimeZone.getTimeZone(name); + Calendar c = Calendar.getInstance(tz); + TimeZone guess; + + c.set(2008, Calendar.OCTOBER, 20, 12, 00, 00); + guess = guess(c, "us"); + assertEquals(name, guess.getID()); + } + } + + public void testOld() throws Exception { + String[] old = new String[] { + "America/Indiana/Indianapolis", // Eastern, formerly no DST + }; + + for (String name : old) { + TimeZone tz = TimeZone.getTimeZone(name); + Calendar c = Calendar.getInstance(tz); + TimeZone guess; + + c.set(2005, Calendar.OCTOBER, 20, 12, 00, 00); + guess = guess(c, "us"); + assertEquals(name, guess.getID()); + } + } + + public void testWorld() throws Exception { + String[] world = new String[] { + "ad", "Europe/Andorra", + "ae", "Asia/Dubai", + "af", "Asia/Kabul", + "ag", "America/Antigua", + "ai", "America/Anguilla", + "al", "Europe/Tirane", + "am", "Asia/Yerevan", + "an", "America/Curacao", + "ao", "Africa/Luanda", + "aq", "Antarctica/McMurdo", + "aq", "Antarctica/DumontDUrville", + "aq", "Antarctica/Casey", + "aq", "Antarctica/Davis", + "aq", "Antarctica/Mawson", + "aq", "Antarctica/Syowa", + "aq", "Antarctica/Rothera", + "aq", "Antarctica/Palmer", + "ar", "America/Argentina/Buenos_Aires", + "as", "Pacific/Pago_Pago", + "at", "Europe/Vienna", + "au", "Australia/Sydney", + "au", "Australia/Adelaide", + "au", "Australia/Perth", + "au", "Australia/Eucla", + "aw", "America/Aruba", + "ax", "Europe/Mariehamn", + "az", "Asia/Baku", + "ba", "Europe/Sarajevo", + "bb", "America/Barbados", + "bd", "Asia/Dhaka", + "be", "Europe/Brussels", + "bf", "Africa/Ouagadougou", + "bg", "Europe/Sofia", + "bh", "Asia/Bahrain", + "bi", "Africa/Bujumbura", + "bj", "Africa/Porto-Novo", + "bm", "Atlantic/Bermuda", + "bn", "Asia/Brunei", + "bo", "America/La_Paz", + "br", "America/Noronha", + "br", "America/Sao_Paulo", + "br", "America/Manaus", + "bs", "America/Nassau", + "bt", "Asia/Thimphu", + "bw", "Africa/Gaborone", + "by", "Europe/Minsk", + "bz", "America/Belize", + "ca", "America/St_Johns", + "ca", "America/Halifax", + "ca", "America/Toronto", + "ca", "America/Winnipeg", + "ca", "America/Edmonton", + "ca", "America/Vancouver", + "cc", "Indian/Cocos", + "cd", "Africa/Lubumbashi", + "cd", "Africa/Kinshasa", + "cf", "Africa/Bangui", + "cg", "Africa/Brazzaville", + "ch", "Europe/Zurich", + "ci", "Africa/Abidjan", + "ck", "Pacific/Rarotonga", + "cl", "America/Santiago", + "cl", "Pacific/Easter", + "cm", "Africa/Douala", + "cn", "Asia/Shanghai", + "co", "America/Bogota", + "cr", "America/Costa_Rica", + "cu", "America/Havana", + "cv", "Atlantic/Cape_Verde", + "cx", "Indian/Christmas", + "cy", "Asia/Nicosia", + "cz", "Europe/Prague", + "de", "Europe/Berlin", + "dj", "Africa/Djibouti", + "dk", "Europe/Copenhagen", + "dm", "America/Dominica", + "do", "America/Santo_Domingo", + "dz", "Africa/Algiers", + "ec", "America/Guayaquil", + "ec", "Pacific/Galapagos", + "ee", "Europe/Tallinn", + "eg", "Africa/Cairo", + "eh", "Africa/El_Aaiun", + "er", "Africa/Asmara", + "es", "Europe/Madrid", + "es", "Atlantic/Canary", + "et", "Africa/Addis_Ababa", + "fi", "Europe/Helsinki", + "fj", "Pacific/Fiji", + "fk", "Atlantic/Stanley", + "fm", "Pacific/Ponape", + "fm", "Pacific/Truk", + "fo", "Atlantic/Faroe", + "fr", "Europe/Paris", + "ga", "Africa/Libreville", + "gb", "Europe/London", + "gd", "America/Grenada", + "ge", "Asia/Tbilisi", + "gf", "America/Cayenne", + "gg", "Europe/Guernsey", + "gh", "Africa/Accra", + "gi", "Europe/Gibraltar", + "gl", "America/Danmarkshavn", + "gl", "America/Scoresbysund", + "gl", "America/Godthab", + "gl", "America/Thule", + "gm", "Africa/Banjul", + "gn", "Africa/Conakry", + "gp", "America/Guadeloupe", + "gq", "Africa/Malabo", + "gr", "Europe/Athens", + "gs", "Atlantic/South_Georgia", + "gt", "America/Guatemala", + "gu", "Pacific/Guam", + "gw", "Africa/Bissau", + "gy", "America/Guyana", + "hk", "Asia/Hong_Kong", + "hn", "America/Tegucigalpa", + "hr", "Europe/Zagreb", + "ht", "America/Port-au-Prince", + "hu", "Europe/Budapest", + "id", "Asia/Jayapura", + "id", "Asia/Makassar", + "id", "Asia/Jakarta", + "ie", "Europe/Dublin", + "il", "Asia/Jerusalem", + "im", "Europe/Isle_of_Man", + "in", "Asia/Calcutta", + "io", "Indian/Chagos", + "iq", "Asia/Baghdad", + "ir", "Asia/Tehran", + "is", "Atlantic/Reykjavik", + "it", "Europe/Rome", + "je", "Europe/Jersey", + "jm", "America/Jamaica", + "jo", "Asia/Amman", + "jp", "Asia/Tokyo", + "ke", "Africa/Nairobi", + "kg", "Asia/Bishkek", + "kh", "Asia/Phnom_Penh", + "ki", "Pacific/Kiritimati", + "ki", "Pacific/Enderbury", + "ki", "Pacific/Tarawa", + "km", "Indian/Comoro", + "kn", "America/St_Kitts", + "kp", "Asia/Pyongyang", + "kr", "Asia/Seoul", + "kw", "Asia/Kuwait", + "ky", "America/Cayman", + "kz", "Asia/Almaty", + "kz", "Asia/Aqtau", + "la", "Asia/Vientiane", + "lb", "Asia/Beirut", + "lc", "America/St_Lucia", + "li", "Europe/Vaduz", + "lk", "Asia/Colombo", + "lr", "Africa/Monrovia", + "ls", "Africa/Maseru", + "lt", "Europe/Vilnius", + "lu", "Europe/Luxembourg", + "lv", "Europe/Riga", + "ly", "Africa/Tripoli", + "ma", "Africa/Casablanca", + "mc", "Europe/Monaco", + "md", "Europe/Chisinau", + "me", "Europe/Podgorica", + "mg", "Indian/Antananarivo", + "mh", "Pacific/Majuro", + "mk", "Europe/Skopje", + "ml", "Africa/Bamako", + "mm", "Asia/Rangoon", + "mn", "Asia/Choibalsan", + "mn", "Asia/Hovd", + "mo", "Asia/Macau", + "mp", "Pacific/Saipan", + "mq", "America/Martinique", + "mr", "Africa/Nouakchott", + "ms", "America/Montserrat", + "mt", "Europe/Malta", + "mu", "Indian/Mauritius", + "mv", "Indian/Maldives", + "mw", "Africa/Blantyre", + "mx", "America/Mexico_City", + "mx", "America/Chihuahua", + "mx", "America/Tijuana", + "my", "Asia/Kuala_Lumpur", + "mz", "Africa/Maputo", + "na", "Africa/Windhoek", + "nc", "Pacific/Noumea", + "ne", "Africa/Niamey", + "nf", "Pacific/Norfolk", + "ng", "Africa/Lagos", + "ni", "America/Managua", + "nl", "Europe/Amsterdam", + "no", "Europe/Oslo", + "np", "Asia/Katmandu", + "nr", "Pacific/Nauru", + "nu", "Pacific/Niue", + "nz", "Pacific/Auckland", + "nz", "Pacific/Chatham", + "om", "Asia/Muscat", + "pa", "America/Panama", + "pe", "America/Lima", + "pf", "Pacific/Gambier", + "pf", "Pacific/Marquesas", + "pf", "Pacific/Tahiti", + "pg", "Pacific/Port_Moresby", + "ph", "Asia/Manila", + "pk", "Asia/Karachi", + "pl", "Europe/Warsaw", + "pm", "America/Miquelon", + "pn", "Pacific/Pitcairn", + "pr", "America/Puerto_Rico", + "ps", "Asia/Gaza", + "pt", "Europe/Lisbon", + "pt", "Atlantic/Azores", + "pw", "Pacific/Palau", + "py", "America/Asuncion", + "qa", "Asia/Qatar", + "re", "Indian/Reunion", + "ro", "Europe/Bucharest", + "rs", "Europe/Belgrade", + "ru", "Asia/Kamchatka", + "ru", "Asia/Magadan", + "ru", "Asia/Vladivostok", + "ru", "Asia/Yakutsk", + "ru", "Asia/Irkutsk", + "ru", "Asia/Krasnoyarsk", + "ru", "Asia/Novosibirsk", + "ru", "Asia/Yekaterinburg", + "ru", "Europe/Samara", + "ru", "Europe/Moscow", + "ru", "Europe/Kaliningrad", + "rw", "Africa/Kigali", + "sa", "Asia/Riyadh", + "sb", "Pacific/Guadalcanal", + "sc", "Indian/Mahe", + "sd", "Africa/Khartoum", + "se", "Europe/Stockholm", + "sg", "Asia/Singapore", + "sh", "Atlantic/St_Helena", + "si", "Europe/Ljubljana", + "sj", "Arctic/Longyearbyen", + "sk", "Europe/Bratislava", + "sl", "Africa/Freetown", + "sm", "Europe/San_Marino", + "sn", "Africa/Dakar", + "so", "Africa/Mogadishu", + "sr", "America/Paramaribo", + "st", "Africa/Sao_Tome", + "sv", "America/El_Salvador", + "sy", "Asia/Damascus", + "sz", "Africa/Mbabane", + "tc", "America/Grand_Turk", + "td", "Africa/Ndjamena", + "tf", "Indian/Kerguelen", + "tg", "Africa/Lome", + "th", "Asia/Bangkok", + "tj", "Asia/Dushanbe", + "tk", "Pacific/Fakaofo", + "tl", "Asia/Dili", + "tm", "Asia/Ashgabat", + "tn", "Africa/Tunis", + "to", "Pacific/Tongatapu", + "tr", "Europe/Istanbul", + "tt", "America/Port_of_Spain", + "tv", "Pacific/Funafuti", + "tw", "Asia/Taipei", + "tz", "Africa/Dar_es_Salaam", + "ua", "Europe/Kiev", + "ug", "Africa/Kampala", + "um", "Pacific/Wake", + "um", "Pacific/Johnston", + "um", "Pacific/Midway", + "us", "America/New_York", + "us", "America/Chicago", + "us", "America/Denver", + "us", "America/Los_Angeles", + "us", "America/Anchorage", + "us", "Pacific/Honolulu", + "uy", "America/Montevideo", + "uz", "Asia/Tashkent", + "va", "Europe/Vatican", + "vc", "America/St_Vincent", + "ve", "America/Caracas", + "vg", "America/Tortola", + "vi", "America/St_Thomas", + "vn", "Asia/Saigon", + "vu", "Pacific/Efate", + "wf", "Pacific/Wallis", + "ws", "Pacific/Apia", + "ye", "Asia/Aden", + "yt", "Indian/Mayotte", + "za", "Africa/Johannesburg", + "zm", "Africa/Lusaka", + "zw", "Africa/Harare", + }; + + for (int i = 0; i < world.length; i += 2) { + String country = world[i]; + String name = world[i + 1]; + + TimeZone tz = TimeZone.getTimeZone(name); + Calendar c = Calendar.getInstance(tz); + TimeZone guess; + + c.set(2009, Calendar.JULY, 20, 12, 00, 00); + guess = guess(c, country); + assertEquals(name, guess.getID()); + + c.set(2009, Calendar.JANUARY, 20, 12, 00, 00); + guess = guess(c, country); + assertEquals(name, guess.getID()); + } + } + + public void testWorldWeird() throws Exception { + String[] world = new String[] { + // Distinguisable from Sydney only when DST not in effect + "au", "Australia/Lord_Howe", + }; + + for (int i = 0; i < world.length; i += 2) { + String country = world[i]; + String name = world[i + 1]; + + TimeZone tz = TimeZone.getTimeZone(name); + Calendar c = Calendar.getInstance(tz); + TimeZone guess; + + c.set(2009, Calendar.JULY, 20, 12, 00, 00); + guess = guess(c, country); + assertEquals(name, guess.getID()); + } + } + + private static TimeZone guess(Calendar c, String country) { + return TimeUtils.getTimeZone(c.get(c.ZONE_OFFSET) + c.get(c.DST_OFFSET), + c.get(c.DST_OFFSET) != 0, + c.getTimeInMillis(), + country); + } +} diff --git a/tests/AndroidTests/src/com/android/unit_tests/TraceTest.java b/tests/AndroidTests/src/com/android/unit_tests/TraceTest.java new file mode 100644 index 0000000..6705080 --- /dev/null +++ b/tests/AndroidTests/src/com/android/unit_tests/TraceTest.java @@ -0,0 +1,215 @@ +/* + * 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.unit_tests; + +import android.os.Debug; +import android.test.AndroidTestCase; +import android.test.suitebuilder.annotation.LargeTest; +import android.test.suitebuilder.annotation.SmallTest; +import android.test.suitebuilder.annotation.Suppress; +import android.util.Log; + +/** + * This class is used to test the native tracing support. Run this test + * while tracing on the emulator and then run traceview to view the trace. + */ +public class TraceTest extends AndroidTestCase +{ + private static final String TAG = "TraceTest"; + private int eMethodCalls = 0; + private int fMethodCalls = 0; + private int gMethodCalls = 0; + + @SmallTest + public void testNativeTracingFromJava() + { + long start = System.currentTimeMillis(); + Debug.startNativeTracing(); + //nativeMethod(); + int count = 0; + for (int ii = 0; ii < 20; ii++) { + count = eMethod(); + } + Debug.stopNativeTracing(); + long end = System.currentTimeMillis(); + long elapsed = end - start; + Log.i(TAG, "elapsed millis: " + elapsed); + Log.i(TAG, "eMethod calls: " + eMethodCalls + + " fMethod calls: " + fMethodCalls + + " gMethod calls: " + gMethodCalls); + } + + // This should not run in the automated suite. + @Suppress + public void disableTestNativeTracingFromC() + { + long start = System.currentTimeMillis(); + nativeMethodAndStartTracing(); + long end = System.currentTimeMillis(); + long elapsed = end - start; + Log.i(TAG, "elapsed millis: " + elapsed); + } + + native void nativeMethod(); + native void nativeMethodAndStartTracing(); + + @LargeTest + public void testMethodTracing() + { + long start = System.currentTimeMillis(); + Debug.startMethodTracing("traceTest"); + topMethod(); + Debug.stopMethodTracing(); + long end = System.currentTimeMillis(); + long elapsed = end - start; + Log.i(TAG, "elapsed millis: " + elapsed); + } + + private void topMethod() { + aMethod(); + bMethod(); + cMethod(); + dMethod(5); + + Thread t1 = new aThread(); + t1.start(); + Thread t2 = new aThread(); + t2.start(); + Thread t3 = new aThread(); + t3.start(); + try { + t1.join(); + t2.join(); + t3.join(); + } catch (InterruptedException e) { + } + } + + private class aThread extends Thread { + @Override + public void run() { + aMethod(); + bMethod(); + cMethod(); + } + } + + /** Calls other methods to make some interesting trace data. + * + * @return a meaningless value + */ + private int aMethod() { + int count = 0; + for (int ii = 0; ii < 6; ii++) { + count += bMethod(); + } + for (int ii = 0; ii < 5; ii++) { + count += cMethod(); + } + for (int ii = 0; ii < 4; ii++) { + count += dMethod(ii); + } + return count; + } + + /** Calls another method to make some interesting trace data. + * + * @return a meaningless value + */ + private int bMethod() { + int count = 0; + for (int ii = 0; ii < 4; ii++) { + count += cMethod(); + } + return count; + } + + /** Executes a simple loop to make some interesting trace data. + * + * @return a meaningless value + */ + private int cMethod() { + int count = 0; + for (int ii = 0; ii < 1000; ii++) { + count += ii; + } + return count; + } + + /** Calls itself recursively to make some interesting trace data. + * + * @return a meaningless value + */ + private int dMethod(int level) { + int count = 0; + if (level > 0) { + count = dMethod(level - 1); + } + for (int ii = 0; ii < 100; ii++) { + count += ii; + } + if (level == 0) { + return count; + } + return dMethod(level - 1); + } + + public int eMethod() { + eMethodCalls += 1; + int count = fMethod(); + count += gMethod(3); + return count; + } + + public int fMethod() { + fMethodCalls += 1; + int count = 0; + for (int ii = 0; ii < 10; ii++) { + count += ii; + } + return count; + } + + public int gMethod(int level) { + gMethodCalls += 1; + int count = level; + if (level > 1) + count += gMethod(level - 1); + return count; + } + + /* + * This causes the native shared library to be loaded when the + * class is first used. The library is only loaded once, even if + * multiple classes include this line. + * + * The library must be in java.library.path, which is derived from + * LD_LIBRARY_PATH. The actual library name searched for will be + * "libtrace_test.so" under Linux, but may be different on other + * platforms. + */ + static { + Log.i(TAG, "Loading trace_test native library..."); + try { + System.loadLibrary("trace_test"); + Log.i(TAG, "Successfully loaded trace_test native library"); + } + catch (UnsatisfiedLinkError ule) { + Log.w(TAG, "Could not load trace_test native library"); + } + } +} diff --git a/tests/AndroidTests/src/com/android/unit_tests/TreeMapTest.java b/tests/AndroidTests/src/com/android/unit_tests/TreeMapTest.java new file mode 100644 index 0000000..d77a819 --- /dev/null +++ b/tests/AndroidTests/src/com/android/unit_tests/TreeMapTest.java @@ -0,0 +1,281 @@ +/* + * 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.unit_tests; + +import android.test.PerformanceTestBase; +import android.test.PerformanceTestCase; + +import java.util.Collection; +import java.util.Set; +import java.util.SortedMap; +import java.util.TreeMap; + +/** + * Implements basic performance test functionality for java.util.TreeMap + */ + +public class TreeMapTest extends PerformanceTestBase { + public static final int ITERATIONS = 1000; + public static TreeMap<String, Integer> sMap; + public static String[] sKeys; + + @Override + @SuppressWarnings("unchecked") + protected void setUp() throws Exception { + super.setUp(); + sMap = new TreeMap(); + sKeys = new String[ITERATIONS]; + for (int i = ITERATIONS - 1; i >= 0; i--) { + sKeys[i] = Integer.toString(i, 16); + sMap.put(sKeys[i], i); + } + } + + @Override + public int startPerformance(PerformanceTestCase.Intermediates intermediates) { + intermediates.setInternalIterations(ITERATIONS); + return 0; + } + + @SuppressWarnings("unchecked") + public void testTreeMapPut() { + TreeMap map = new TreeMap(); + for (int i = ITERATIONS - 1; i >= 0; i--) { + map.put(i, i); + map.put(i, i); + map.put(i, i); + map.put(i, i); + map.put(i, i); + map.put(i, i); + map.put(i, i); + map.put(i, i); + map.put(i, i); + map.put(i, i); + } + } + + public void testTreeMapGet() { + int value; + TreeMap<String, Integer> map = sMap; + String[] keys = sKeys; + for (int i = ITERATIONS - 1; i >= 0; i--) { + value = map.get(keys[i]); + value = map.get(keys[i]); + value = map.get(keys[i]); + value = map.get(keys[i]); + value = map.get(keys[i]); + value = map.get(keys[i]); + value = map.get(keys[i]); + value = map.get(keys[i]); + value = map.get(keys[i]); + value = map.get(keys[i]); + } + } + + public void testTreeMapFirstKey() { + String key; + TreeMap<String, Integer> map = sMap; + for (int i = ITERATIONS - 1; i >= 0; i--) { + key = map.firstKey(); + key = map.firstKey(); + key = map.firstKey(); + key = map.firstKey(); + key = map.firstKey(); + key = map.firstKey(); + key = map.firstKey(); + key = map.firstKey(); + key = map.firstKey(); + key = map.firstKey(); + } + } + + public void testTreeMapKeySet() { + Set keyset; + TreeMap<String, Integer> map = sMap; + for (int i = ITERATIONS - 1; i >= 0; i--) { + keyset = map.keySet(); + keyset = map.keySet(); + keyset = map.keySet(); + keyset = map.keySet(); + keyset = map.keySet(); + keyset = map.keySet(); + keyset = map.keySet(); + keyset = map.keySet(); + keyset = map.keySet(); + keyset = map.keySet(); + } + } + + public void testTreeMapEntrySet() { + Set keyset; + TreeMap<String, Integer> map = sMap; + for (int i = ITERATIONS - 1; i >= 0; i--) { + keyset = map.entrySet(); + keyset = map.entrySet(); + keyset = map.entrySet(); + keyset = map.entrySet(); + keyset = map.entrySet(); + keyset = map.entrySet(); + keyset = map.entrySet(); + keyset = map.entrySet(); + keyset = map.entrySet(); + keyset = map.entrySet(); + } + } + + public void testTreeMapValues() { + Collection collection; + TreeMap<String, Integer> map = sMap; + for (int i = ITERATIONS - 1; i >= 0; i--) { + collection = map.values(); + collection = map.values(); + collection = map.values(); + collection = map.values(); + collection = map.values(); + collection = map.values(); + collection = map.values(); + collection = map.values(); + collection = map.values(); + collection = map.values(); + } + } + + public void testTreeMapSize() { + int len; + TreeMap<String, Integer> map = sMap; + for (int i = ITERATIONS - 1; i >= 0; i--) { + len = map.size(); + len = map.size(); + len = map.size(); + len = map.size(); + len = map.size(); + len = map.size(); + len = map.size(); + len = map.size(); + len = map.size(); + len = map.size(); + } + } + + public void testTreeMapContainsKey() { + boolean flag; + String key = sKeys[525]; + TreeMap<String, Integer> map = sMap; + for (int i = ITERATIONS - 1; i >= 0; i--) { + flag = map.containsKey(key); + flag = map.containsKey(key); + flag = map.containsKey(key); + flag = map.containsKey(key); + flag = map.containsKey(key); + flag = map.containsKey(key); + flag = map.containsKey(key); + flag = map.containsKey(key); + flag = map.containsKey(key); + flag = map.containsKey(key); + } + } + + public void testTreeMapContainsValue() { + boolean flag; + TreeMap<String, Integer> map = sMap; + for (int i = ITERATIONS - 1; i >= 0; i--) { + flag = map.containsValue(i); + flag = map.containsValue(i); + flag = map.containsValue(i); + flag = map.containsValue(i); + flag = map.containsValue(i); + flag = map.containsValue(i); + flag = map.containsValue(i); + flag = map.containsValue(i); + flag = map.containsValue(i); + flag = map.containsValue(i); + } + } + + public void testTreeMapHeadMap() { + SortedMap map; + String str = sKeys[100]; + TreeMap<String, Integer> tMap = sMap; + for (int i = ITERATIONS - 1; i >= 0; i--) { + map = tMap.headMap(str); + map = tMap.headMap(str); + map = tMap.headMap(str); + map = tMap.headMap(str); + map = tMap.headMap(str); + map = tMap.headMap(str); + map = tMap.headMap(str); + map = tMap.headMap(str); + map = tMap.headMap(str); + map = tMap.headMap(str); + } + } + + public void testTreeMapSubMap() { + String str1 = sKeys[400]; + String str2 = sKeys[500]; + SortedMap map; + TreeMap<String, Integer> tMap = sMap; + for (int i = ITERATIONS - 1; i >= 0; i--) { + map = tMap.subMap(str1, str2); + map = tMap.subMap(str1, str2); + map = tMap.subMap(str1, str2); + map = tMap.subMap(str1, str2); + map = tMap.subMap(str1, str2); + map = tMap.subMap(str1, str2); + map = tMap.subMap(str1, str2); + map = tMap.subMap(str1, str2); + map = tMap.subMap(str1, str2); + map = tMap.subMap(str1, str2); + } + } + + public void testTreeMapTailMap() { + String str = sKeys[900]; + TreeMap<String, Integer> tMap = sMap; + SortedMap map; + for (int i = ITERATIONS - 1; i >= 0; i--) { + map = tMap.tailMap(str); + map = tMap.tailMap(str); + map = tMap.tailMap(str); + map = tMap.tailMap(str); + map = tMap.tailMap(str); + map = tMap.tailMap(str); + map = tMap.tailMap(str); + map = tMap.tailMap(str); + map = tMap.tailMap(str); + map = tMap.tailMap(str); + } + } + + @SuppressWarnings("unchecked") + public void testTreeMapRemove() { + TreeMap<String, Integer> tMap = new TreeMap(sMap); + String[] keys = sKeys; + for (int i = ITERATIONS - 1; i >= 0; i--) { + tMap.remove(keys[i]); + tMap.remove(keys[i]); + tMap.remove(keys[i]); + tMap.remove(keys[i]); + tMap.remove(keys[i]); + tMap.remove(keys[i]); + tMap.remove(keys[i]); + tMap.remove(keys[i]); + tMap.remove(keys[i]); + tMap.remove(keys[i]); + } + } +} diff --git a/tests/AndroidTests/src/com/android/unit_tests/TreeSetTest.java b/tests/AndroidTests/src/com/android/unit_tests/TreeSetTest.java new file mode 100644 index 0000000..60dfe9a --- /dev/null +++ b/tests/AndroidTests/src/com/android/unit_tests/TreeSetTest.java @@ -0,0 +1,349 @@ +/* + * 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.unit_tests; + +import android.test.PerformanceTestBase; +import android.test.PerformanceTestCase; + +import java.util.TreeSet; +import java.util.SortedSet; +import java.util.Iterator; +import java.util.Comparator; + +/** + * Implements basic performance test functionality for java.util.TreeSet + */ + +public class TreeSetTest extends PerformanceTestBase { + public static final int ITERATIONS = 1000; + public static TreeSet<Integer> sSet; + + @Override + protected void setUp() throws Exception { + super.setUp(); + sSet = new TreeSet<Integer>(); + for (int i = ITERATIONS - 1; i >= 0; i--) { + sSet.add(i); + } + } + + @Override + public int startPerformance(PerformanceTestCase.Intermediates intermediates) { + intermediates.setInternalIterations(ITERATIONS); + return 0; + } + + /** + * + * Tests performance for the java.util.TreeSet method Add(Object arg 0) + * + */ + + @SuppressWarnings("unchecked") + public void testTreeSetAdd() { + TreeSet<Integer> set = new TreeSet(); + for (int i = ITERATIONS - 1; i >= 0; i--) { + set.add(i); + set.add(i); + set.add(i); + set.add(i); + set.add(i); + set.add(i); + set.add(i); + set.add(i); + set.add(i); + set.add(i); + } + } + + /** + * + * Tests performance for the java.util.TreeSet method - first() + * + */ + + public void testTreeSetFirst() { + int value; + TreeSet<Integer> set = sSet; + for (int i = ITERATIONS - 1; i >= 0; i--) { + value = set.first(); + value = set.first(); + value = set.first(); + value = set.first(); + value = set.first(); + value = set.first(); + value = set.first(); + value = set.first(); + value = set.first(); + } + } + + /** + * + * Tests performance for the java.util.TreeSet method - last() + * + */ + + public void testTreeSetLast() { + int value; + TreeSet<Integer> set = sSet; + for (int i = ITERATIONS - 1; i >= 0; i--) { + value = set.last(); + value = set.last(); + value = set.last(); + value = set.last(); + value = set.last(); + value = set.last(); + value = set.last(); + value = set.last(); + value = set.last(); + } + } + + /** + * + * Tests performance of the java.util.TreeSet method- contains(Object arg0) + * + */ + + public void testTreeSetContains() { + Integer index = new Integer(500); + boolean flag; + TreeSet<Integer> set = sSet; + for (int i = ITERATIONS - 1; i >= 0; i--) { + flag = set.contains(index); + flag = set.contains(index); + flag = set.contains(index); + flag = set.contains(index); + flag = set.contains(index); + flag = set.contains(index); + flag = set.contains(index); + flag = set.contains(index); + flag = set.contains(index); + } + } + + /** + * + * Tests performance for the java.util.TreeSet method - size() + * + */ + + public void testTreeSetSize() { + int value; + TreeSet<Integer> set = sSet; + for (int i = ITERATIONS - 1; i >= 0; i--) { + value = set.size(); + value = set.size(); + value = set.size(); + value = set.size(); + value = set.size(); + value = set.size(); + value = set.size(); + value = set.size(); + value = set.size(); + } + } + + /** + * + * Tests performance for the java.util.TreeSet method - iterator() + * + */ + + public void testTreeSetIterator() { + Iterator iterator; + TreeSet<Integer> set = sSet; + for (int i = ITERATIONS - 1; i >= 0; i--) { + iterator = set.iterator(); + iterator = set.iterator(); + iterator = set.iterator(); + iterator = set.iterator(); + iterator = set.iterator(); + iterator = set.iterator(); + iterator = set.iterator(); + iterator = set.iterator(); + iterator = set.iterator(); + } + } + + /** + * + * Tests performance for the java.util.TreeSet method - comparator() + * + */ + + public void testTreeSetComparator() { + Comparator comparator; + TreeSet<Integer> set = sSet; + for (int i = ITERATIONS - 1; i >= 0; i--) { + comparator = set.comparator(); + comparator = set.comparator(); + comparator = set.comparator(); + comparator = set.comparator(); + comparator = set.comparator(); + comparator = set.comparator(); + comparator = set.comparator(); + comparator = set.comparator(); + comparator = set.comparator(); + } + } + + /** + * + * Tests performance for the java.util.TreeSet method - clone() + * + */ + + public void testTreeSetClone() { + Object obj; + TreeSet<Integer> set = sSet; + for (int i = ITERATIONS - 1; i >= 0; i--) { + obj = set.clone(); + obj = set.clone(); + obj = set.clone(); + obj = set.clone(); + obj = set.clone(); + obj = set.clone(); + obj = set.clone(); + obj = set.clone(); + obj = set.clone(); + obj = set.clone(); + } + } + + /** + * + * Tests performance of the java.util.TreeSet method - remove(Object arg0) + * + */ + + @SuppressWarnings("unchecked") + public void testTreeSetRemove() { + TreeSet<Integer> set = new TreeSet(sSet); + for (int i = ITERATIONS - 1; i >= 0; i--) { + set.remove(i); + set.remove(i); + set.remove(i); + set.remove(i); + set.remove(i); + set.remove(i); + set.remove(i); + set.remove(i); + set.remove(i); + set.remove(i); + } + } + + /** + * + * Tests performance of the java.util.TreeSet method- headSet(Integer arg0) + * + */ + + public void testTreeSetHeadSet() { + Integer value = new Integer(100); + SortedSet set; + TreeSet<Integer> tSet = sSet; + for (int i = ITERATIONS - 1; i >= 0; i--) { + set = tSet.headSet(value); + set = tSet.headSet(value); + set = tSet.headSet(value); + set = tSet.headSet(value); + set = tSet.headSet(value); + set = tSet.headSet(value); + set = tSet.headSet(value); + set = tSet.headSet(value); + set = tSet.headSet(value); + set = tSet.headSet(value); + } + } + + /** + * + * Tests performance of subSet(Integer arg0, Integer arg1) - TreeSet + * + */ + + public void testTreeSetSubSet() { + Integer value = new Integer(400); + Integer nInt = new Integer(500); + SortedSet set; + TreeSet<Integer> tSet = sSet; + for (int i = ITERATIONS - 1; i >= 0; i--) { + set = tSet.subSet(value, nInt); + set = tSet.subSet(value, nInt); + set = tSet.subSet(value, nInt); + set = tSet.subSet(value, nInt); + set = tSet.subSet(value, nInt); + set = tSet.subSet(value, nInt); + set = tSet.subSet(value, nInt); + set = tSet.subSet(value, nInt); + set = tSet.subSet(value, nInt); + set = tSet.subSet(value, nInt); + + } + + } + + /** + * + * Tests performance of tailSet(Integer arg0) - TreeSet + * + */ + + public void testTreeSetTailSet() { + Integer value = new Integer(900); + SortedSet set; + TreeSet<Integer> tSet = sSet; + for (int i = ITERATIONS - 1; i >= 0; i--) { + set = tSet.tailSet(value); + set = tSet.tailSet(value); + set = tSet.tailSet(value); + set = tSet.tailSet(value); + set = tSet.tailSet(value); + set = tSet.tailSet(value); + set = tSet.tailSet(value); + set = tSet.tailSet(value); + set = tSet.tailSet(value); + set = tSet.tailSet(value); + } + } + + /** + * + * Tests performance for the java.util.TreeSet method - isEmpty() + * + */ + + public void testTreeSetIsEmpty() { + boolean flag; + TreeSet<Integer> tSet = sSet; + for (int i = ITERATIONS - 1; i >= 0; i--) { + flag = tSet.isEmpty(); + flag = tSet.isEmpty(); + flag = tSet.isEmpty(); + flag = tSet.isEmpty(); + flag = tSet.isEmpty(); + flag = tSet.isEmpty(); + flag = tSet.isEmpty(); + flag = tSet.isEmpty(); + flag = tSet.isEmpty(); + flag = tSet.isEmpty(); + } + } +} diff --git a/tests/AndroidTests/src/com/android/unit_tests/UriMatcherTest.java b/tests/AndroidTests/src/com/android/unit_tests/UriMatcherTest.java new file mode 100644 index 0000000..ce3ea75 --- /dev/null +++ b/tests/AndroidTests/src/com/android/unit_tests/UriMatcherTest.java @@ -0,0 +1,95 @@ +/* + * 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.unit_tests; + +import android.content.UriMatcher; +import android.net.Uri; +import android.test.suitebuilder.annotation.SmallTest; +import junit.framework.TestCase; + +public class UriMatcherTest extends TestCase +{ + static final int ROOT = 0; + static final int PEOPLE = 1; + static final int PEOPLE_ID = 2; + static final int PEOPLE_PHONES = 3; + static final int PEOPLE_PHONES_ID = 4; + static final int PEOPLE_ADDRESSES = 5; + static final int PEOPLE_ADDRESSES_ID = 6; + static final int PEOPLE_CONTACTMETH = 7; + static final int PEOPLE_CONTACTMETH_ID = 8; + static final int CALLS = 9; + static final int CALLS_ID = 10; + static final int CALLERID = 11; + static final int CALLERID_TEXT = 12; + static final int FILTERRECENT = 13; + + @SmallTest + public void testContentUris() { + check("content://asdf", UriMatcher.NO_MATCH); + check("content://people", PEOPLE); + check("content://people/1", PEOPLE_ID); + check("content://people/asdf", UriMatcher.NO_MATCH); + check("content://people/2/phones", PEOPLE_PHONES); + check("content://people/2/phones/3", PEOPLE_PHONES_ID); + check("content://people/2/phones/asdf", UriMatcher.NO_MATCH); + check("content://people/2/addresses", PEOPLE_ADDRESSES); + check("content://people/2/addresses/3", PEOPLE_ADDRESSES_ID); + check("content://people/2/addresses/asdf", UriMatcher.NO_MATCH); + check("content://people/2/contact-methods", PEOPLE_CONTACTMETH); + check("content://people/2/contact-methods/3", PEOPLE_CONTACTMETH_ID); + check("content://people/2/contact-methods/asdf", UriMatcher.NO_MATCH); + check("content://calls", CALLS); + check("content://calls/1", CALLS_ID); + check("content://calls/asdf", UriMatcher.NO_MATCH); + check("content://caller-id", CALLERID); + check("content://caller-id/asdf", CALLERID_TEXT); + check("content://caller-id/1", CALLERID_TEXT); + check("content://filter-recent", FILTERRECENT); + } + + private static final UriMatcher mURLMatcher = new UriMatcher(ROOT); + + static + { + mURLMatcher.addURI("people", null, PEOPLE); + mURLMatcher.addURI("people", "#", PEOPLE_ID); + mURLMatcher.addURI("people", "#/phones", PEOPLE_PHONES); + mURLMatcher.addURI("people", "#/phones/blah", PEOPLE_PHONES_ID); + mURLMatcher.addURI("people", "#/phones/#", PEOPLE_PHONES_ID); + mURLMatcher.addURI("people", "#/addresses", PEOPLE_ADDRESSES); + mURLMatcher.addURI("people", "#/addresses/#", PEOPLE_ADDRESSES_ID); + mURLMatcher.addURI("people", "#/contact-methods", PEOPLE_CONTACTMETH); + mURLMatcher.addURI("people", "#/contact-methods/#", PEOPLE_CONTACTMETH_ID); + mURLMatcher.addURI("calls", null, CALLS); + mURLMatcher.addURI("calls", "#", CALLS_ID); + mURLMatcher.addURI("caller-id", null, CALLERID); + mURLMatcher.addURI("caller-id", "*", CALLERID_TEXT); + mURLMatcher.addURI("filter-recent", null, FILTERRECENT); + } + + void check(String uri, int expected) + { + int result = mURLMatcher.match(Uri.parse(uri)); + if (result != expected) { + String msg = "failed on " + uri; + msg += " expected " + expected + " got " + result; + throw new RuntimeException(msg); + } + } +} + diff --git a/tests/AndroidTests/src/com/android/unit_tests/UriTest.java b/tests/AndroidTests/src/com/android/unit_tests/UriTest.java new file mode 100644 index 0000000..130beeb --- /dev/null +++ b/tests/AndroidTests/src/com/android/unit_tests/UriTest.java @@ -0,0 +1,502 @@ +/* + * 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.unit_tests; + +import android.net.Uri; +import android.content.ContentUris; +import android.os.Parcel; +import android.test.suitebuilder.annotation.SmallTest; +import junit.framework.TestCase; + +import java.io.File; +import java.util.Arrays; + +public class UriTest extends TestCase { + + @SmallTest + public void testToStringWithPathOnly() { + Uri.Builder builder = new Uri.Builder(); + + // Not a valid path, but this came from a user's test case. + builder.path("//foo"); + Uri uri = builder.build(); + assertEquals("//foo", uri.toString()); + } + + @SmallTest + public void testParcelling() { + parcelAndUnparcel(Uri.parse("foo:bob%20lee")); + parcelAndUnparcel(Uri.fromParts("foo", "bob lee", "fragment")); + parcelAndUnparcel(new Uri.Builder() + .scheme("http") + .authority("crazybob.org") + .path("/rss/") + .encodedQuery("a=b") + .fragment("foo") + .build()); + } + + private void parcelAndUnparcel(Uri u) { + Parcel p = Parcel.obtain(); + Uri.writeToParcel(p, u); + p.setDataPosition(0); + assertEquals(u, Uri.CREATOR.createFromParcel(p)); + + p.setDataPosition(0); + u = u.buildUpon().build(); + Uri.writeToParcel(p, u); + p.setDataPosition(0); + assertEquals(u, Uri.CREATOR.createFromParcel(p)); + } + + @SmallTest + public void testBuildUponOpaqueStringUri() { + Uri u = Uri.parse("bob:lee").buildUpon().scheme("robert").build(); + assertEquals("robert", u.getScheme()); + assertEquals("lee", u.getEncodedSchemeSpecificPart()); + assertEquals("lee", u.getSchemeSpecificPart()); + assertNull(u.getQuery()); + assertNull(u.getPath()); + assertNull(u.getAuthority()); + assertNull(u.getHost()); + } + + @SmallTest + public void testStringUri() { + assertEquals("bob lee", + Uri.parse("foo:bob%20lee").getSchemeSpecificPart()); + assertEquals("bob%20lee", + Uri.parse("foo:bob%20lee").getEncodedSchemeSpecificPart()); + assertEquals("/bob%20lee", + Uri.parse("foo:/bob%20lee").getEncodedPath()); + assertNull(Uri.parse("foo:bob%20lee").getPath()); + assertEquals("bob%20lee", + Uri.parse("foo:?bob%20lee").getEncodedQuery()); + assertNull(Uri.parse("foo:bar#?bob%20lee").getQuery()); + assertEquals("bob%20lee", + Uri.parse("foo:#bob%20lee").getEncodedFragment()); + } + + @SmallTest + public void testStringUriIsHierarchical() { + assertTrue(Uri.parse("bob").isHierarchical()); + assertFalse(Uri.parse("bob:").isHierarchical()); + } + + @SmallTest + public void testNullUriString() { + try { + Uri.parse(null); + fail(); + } catch (NullPointerException e) {} + } + + @SmallTest + public void testNullFile() { + try { + Uri.fromFile(null); + fail(); + } catch (NullPointerException e) {} + } + + @SmallTest + public void testCompareTo() { + Uri a = Uri.parse("foo:a"); + Uri b = Uri.parse("foo:b"); + Uri b2 = Uri.parse("foo:b"); + + assertTrue(a.compareTo(b) < 0); + assertTrue(b.compareTo(a) > 0); + assertEquals(0, b.compareTo(b2)); + } + + @SmallTest + public void testEqualsAndHashCode() { + + Uri a = Uri.parse("http://crazybob.org/test/?foo=bar#tee"); + + Uri b = new Uri.Builder() + .scheme("http") + .authority("crazybob.org") + .path("/test/") + .encodedQuery("foo=bar") + .fragment("tee") + .build(); + + // Try alternate builder methods. + Uri c = new Uri.Builder() + .scheme("http") + .encodedAuthority("crazybob.org") + .encodedPath("/test/") + .encodedQuery("foo=bar") + .encodedFragment("tee") + .build(); + + assertFalse(Uri.EMPTY.equals(null)); + + assertEquals(a, b); + assertEquals(b, c); + assertEquals(c, a); + + assertEquals(a.hashCode(), b.hashCode()); + assertEquals(b.hashCode(), c.hashCode()); + } + + @SmallTest + public void testAuthorityParsing() { + Uri uri = Uri.parse("http://localhost:42"); + assertEquals("localhost", uri.getHost()); + assertEquals(42, uri.getPort()); + + uri = Uri.parse("http://bob@localhost:42"); + assertEquals("bob", uri.getUserInfo()); + assertEquals("localhost", uri.getHost()); + assertEquals(42, uri.getPort()); + + uri = Uri.parse("http://bob%20lee@localhost:42"); + assertEquals("bob lee", uri.getUserInfo()); + assertEquals("bob%20lee", uri.getEncodedUserInfo()); + + uri = Uri.parse("http://localhost"); + assertEquals("localhost", uri.getHost()); + assertEquals(-1, uri.getPort()); + } + + @SmallTest + public void testBuildUponOpaqueUri() { + Uri a = Uri.fromParts("foo", "bar", "tee"); + Uri b = a.buildUpon().fragment("new").build(); + assertEquals("new", b.getFragment()); + assertEquals("bar", b.getSchemeSpecificPart()); + assertEquals("foo", b.getScheme()); + } + + @SmallTest + public void testBuildUponEncodedOpaqueUri() { + Uri a = new Uri.Builder() + .scheme("foo") + .encodedOpaquePart("bar") + .fragment("tee") + .build(); + Uri b = a.buildUpon().fragment("new").build(); + assertEquals("new", b.getFragment()); + assertEquals("bar", b.getSchemeSpecificPart()); + assertEquals("foo", b.getScheme()); + } + + @SmallTest + public void testPathSegmentDecoding() { + Uri uri = Uri.parse("foo://bar/a%20a/b%20b"); + assertEquals("a a", uri.getPathSegments().get(0)); + assertEquals("b b", uri.getPathSegments().get(1)); + } + + @SmallTest + public void testSms() { + Uri base = Uri.parse("content://sms"); + Uri appended = base.buildUpon() + .appendEncodedPath("conversations/addr=555-1212") + .build(); + assertEquals("content://sms/conversations/addr=555-1212", + appended.toString()); + assertEquals(2, appended.getPathSegments().size()); + assertEquals("conversations", appended.getPathSegments().get(0)); + assertEquals("addr=555-1212", appended.getPathSegments().get(1)); + } + + @SmallTest + public void testEncodeWithAllowedChars() { + String encoded = Uri.encode("Bob:/", "/"); + assertEquals(-1, encoded.indexOf(':')); + assertTrue(encoded.indexOf('/') > -1); + } + + @SmallTest + public void testEncodeDecode() { + code(null); + code(""); + code("Bob"); + code(":Bob"); + code("::Bob"); + code("Bob::Lee"); + code("Bob:Lee"); + code("Bob::"); + code("Bob:"); + code("::Bob::"); + } + + private void code(String s) { + assertEquals(s, Uri.decode(Uri.encode(s, null))); + } + + @SmallTest + public void testFile() { + File f = new File("/tmp/bob"); + + Uri uri = Uri.fromFile(f); + + assertEquals("file:///tmp/bob", uri.toString()); + } + + @SmallTest + public void testQueryParameters() { + Uri uri = Uri.parse("content://user"); + + assertEquals(null, uri.getQueryParameter("a")); + + uri = uri.buildUpon().appendQueryParameter("a", "b").build(); + + assertEquals("b", uri.getQueryParameter("a")); + + uri = uri.buildUpon().appendQueryParameter("a", "b2").build(); + + assertEquals(Arrays.asList("b", "b2"), uri.getQueryParameters("a")); + + uri = uri.buildUpon().appendQueryParameter("c", "d").build(); + + assertEquals(Arrays.asList("b", "b2"), uri.getQueryParameters("a")); + assertEquals("d", uri.getQueryParameter("c")); + } + + @SmallTest + public void testSchemeOnly() { + Uri uri = Uri.parse("empty:"); + assertEquals("empty", uri.getScheme()); + assertTrue(uri.isAbsolute()); + assertNull(uri.getPath()); + } + + @SmallTest + public void testEmptyPath() { + Uri uri = Uri.parse("content://user"); + assertEquals(0, uri.getPathSegments().size()); + } + + @SmallTest + public void testPathOperations() { + Uri uri = Uri.parse("content://user/a/b"); + + assertEquals(2, uri.getPathSegments().size()); + assertEquals("b", uri.getLastPathSegment()); + + Uri first = uri; + uri = uri.buildUpon().appendPath("c").build(); + + assertEquals(3, uri.getPathSegments().size()); + assertEquals("c", uri.getLastPathSegment()); + assertEquals("content://user/a/b/c", uri.toString()); + + uri = ContentUris.withAppendedId(uri, 100); + + assertEquals(4, uri.getPathSegments().size()); + assertEquals("100", uri.getLastPathSegment()); + assertEquals(100, ContentUris.parseId(uri)); + assertEquals("content://user/a/b/c/100", uri.toString()); + + // Make sure the original URI is still intact. + assertEquals(2, first.getPathSegments().size()); + assertEquals("b", first.getLastPathSegment()); + + try { + first.getPathSegments().get(2); + fail(); + } catch (IndexOutOfBoundsException e) {} + + assertEquals(null, Uri.EMPTY.getLastPathSegment()); + + Uri withC = Uri.parse("foo:/a/b/").buildUpon().appendPath("c").build(); + assertEquals("/a/b/c", withC.getPath()); + } + + @SmallTest + public void testOpaqueUri() { + Uri uri = Uri.parse("mailto:nobody"); + testOpaqueUri(uri); + + uri = uri.buildUpon().build(); + testOpaqueUri(uri); + + uri = Uri.fromParts("mailto", "nobody", null); + testOpaqueUri(uri); + + uri = uri.buildUpon().build(); + testOpaqueUri(uri); + + uri = new Uri.Builder() + .scheme("mailto") + .opaquePart("nobody") + .build(); + testOpaqueUri(uri); + + uri = uri.buildUpon().build(); + testOpaqueUri(uri); + } + + private void testOpaqueUri(Uri uri) { + assertEquals("mailto", uri.getScheme()); + assertEquals("nobody", uri.getSchemeSpecificPart()); + assertEquals("nobody", uri.getEncodedSchemeSpecificPart()); + + assertNull(uri.getFragment()); + assertTrue(uri.isAbsolute()); + assertTrue(uri.isOpaque()); + assertFalse(uri.isRelative()); + assertFalse(uri.isHierarchical()); + + assertNull(uri.getAuthority()); + assertNull(uri.getEncodedAuthority()); + assertNull(uri.getPath()); + assertNull(uri.getEncodedPath()); + assertNull(uri.getUserInfo()); + assertNull(uri.getEncodedUserInfo()); + assertNull(uri.getQuery()); + assertNull(uri.getEncodedQuery()); + assertNull(uri.getHost()); + assertEquals(-1, uri.getPort()); + + assertTrue(uri.getPathSegments().isEmpty()); + assertNull(uri.getLastPathSegment()); + + assertEquals("mailto:nobody", uri.toString()); + + Uri withFragment = uri.buildUpon().fragment("top").build(); + assertEquals("mailto:nobody#top", withFragment.toString()); + } + + @SmallTest + public void testHierarchicalUris() { + testHierarchical("http", "google.com", "/p1/p2", "query", "fragment"); + testHierarchical("file", null, "/p1/p2", null, null); + testHierarchical("content", "contact", "/p1/p2", null, null); + testHierarchical("http", "google.com", "/p1/p2", null, "fragment"); + testHierarchical("http", "google.com", "", null, "fragment"); + testHierarchical("http", "google.com", "", "query", "fragment"); + testHierarchical("http", "google.com", "", "query", null); + testHierarchical("http", null, "/", "query", null); + } + + private static void testHierarchical(String scheme, String authority, + String path, String query, String fragment) { + StringBuilder sb = new StringBuilder(); + + if (authority != null) { + sb.append("//").append(authority); + } + if (path != null) { + sb.append(path); + } + if (query != null) { + sb.append('?').append(query); + } + + String ssp = sb.toString(); + + if (scheme != null) { + sb.insert(0, scheme + ":"); + } + if (fragment != null) { + sb.append('#').append(fragment); + } + + String uriString = sb.toString(); + + Uri uri = Uri.parse(uriString); + + // Run these twice to test caching. + compareHierarchical( + uriString, ssp, uri, scheme, authority, path, query, fragment); + compareHierarchical( + uriString, ssp, uri, scheme, authority, path, query, fragment); + + // Test rebuilt version. + uri = uri.buildUpon().build(); + + // Run these twice to test caching. + compareHierarchical( + uriString, ssp, uri, scheme, authority, path, query, fragment); + compareHierarchical( + uriString, ssp, uri, scheme, authority, path, query, fragment); + + // The decoded and encoded versions of the inputs are all the same. + // We'll test the actual encoding decoding separately. + + // Test building with encoded versions. + Uri built = new Uri.Builder() + .scheme(scheme) + .encodedAuthority(authority) + .encodedPath(path) + .encodedQuery(query) + .encodedFragment(fragment) + .build(); + + compareHierarchical( + uriString, ssp, built, scheme, authority, path, query, fragment); + compareHierarchical( + uriString, ssp, built, scheme, authority, path, query, fragment); + + // Test building with decoded versions. + built = new Uri.Builder() + .scheme(scheme) + .authority(authority) + .path(path) + .query(query) + .fragment(fragment) + .build(); + + compareHierarchical( + uriString, ssp, built, scheme, authority, path, query, fragment); + compareHierarchical( + uriString, ssp, built, scheme, authority, path, query, fragment); + + // Rebuild. + built = built.buildUpon().build(); + + compareHierarchical( + uriString, ssp, built, scheme, authority, path, query, fragment); + compareHierarchical( + uriString, ssp, built, scheme, authority, path, query, fragment); + } + + private static void compareHierarchical(String uriString, String ssp, + Uri uri, + String scheme, String authority, String path, String query, + String fragment) { + assertEquals(scheme, uri.getScheme()); + assertEquals(authority, uri.getAuthority()); + assertEquals(authority, uri.getEncodedAuthority()); + assertEquals(path, uri.getPath()); + assertEquals(path, uri.getEncodedPath()); + assertEquals(query, uri.getQuery()); + assertEquals(query, uri.getEncodedQuery()); + assertEquals(fragment, uri.getFragment()); + assertEquals(fragment, uri.getEncodedFragment()); + assertEquals(ssp, uri.getSchemeSpecificPart()); + + if (scheme != null) { + assertTrue(uri.isAbsolute()); + assertFalse(uri.isRelative()); + } else { + assertFalse(uri.isAbsolute()); + assertTrue(uri.isRelative()); + } + + assertFalse(uri.isOpaque()); + assertTrue(uri.isHierarchical()); + + assertEquals(uriString, uri.toString()); + } +} diff --git a/tests/AndroidTests/src/com/android/unit_tests/UrlRulesTest.java b/tests/AndroidTests/src/com/android/unit_tests/UrlRulesTest.java new file mode 100644 index 0000000..a7c19a7 --- /dev/null +++ b/tests/AndroidTests/src/com/android/unit_tests/UrlRulesTest.java @@ -0,0 +1,120 @@ +/* + * Copyright (C) 2008 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.unit_tests; + +import android.content.ContentResolver; +import android.provider.Settings; +import android.test.AndroidTestCase; +import android.test.suitebuilder.annotation.MediumTest; +import android.test.suitebuilder.annotation.SmallTest; + +import com.google.android.net.UrlRules; +import static com.google.android.net.UrlRules.Rule; + +/** Test loading and matching URL rewrite rules for UrlRules. */ +public class UrlRulesTest extends AndroidTestCase { + @SmallTest + public void testEmptyRules() { + UrlRules rules = new UrlRules(new Rule[] { }); + assertTrue(rules.matchRule("http://foo.bar/") == Rule.DEFAULT); + } + + @SmallTest + public void testInvalidRule() throws Exception { + try { + new Rule("rule", "foo bar"); + } catch (Exception e) { + // Re-throw any exception except the one we're looking for. + if (!e.toString().contains("Illegal rule: foo bar")) throw e; + } + } + + @SmallTest + public void testRewriteRule() throws UrlRules.RuleFormatException { + Rule rule = new Rule("test_rule", + "http://foo.bar/ rewrite http://bar.foo/"); + assertEquals("test_rule", rule.mName); + assertEquals("http://foo.bar/", rule.mPrefix); + assertEquals("http://bar.foo/", rule.mRewrite); + assertFalse(rule.mBlock); + assertEquals("http://bar.foo/bat", rule.apply("http://foo.bar/bat")); + } + + @SmallTest + public void testBlockRule() throws UrlRules.RuleFormatException { + Rule rule = new Rule("test_rule", + "http://foo.bar/ block"); + assertEquals("test_rule", rule.mName); + assertEquals("http://foo.bar/", rule.mPrefix); + assertTrue(rule.mRewrite == null); + assertTrue(rule.mBlock); + assertTrue(rule.apply("http://foo.bar/bat") == null); + } + + @SmallTest + public void testMatchRule() throws UrlRules.RuleFormatException { + UrlRules rules = new UrlRules(new Rule[] { + new Rule("12", "http://one.two/ rewrite http://buckle.my.shoe/"), + new Rule("34", "http://three.four/ rewrite http://close.the.door/"), + new Rule("56", "http://five.six/ rewrite http://pick.up.sticks/"), + }); + + assertTrue(rules.matchRule("https://one.two/") == Rule.DEFAULT); + assertTrue(rules.matchRule("http://one.two") == Rule.DEFAULT); + assertEquals("12", rules.matchRule("http://one.two/foo").mName); + + String u = "http://five.six/bar"; + assertEquals("http://pick.up.sticks/bar", rules.matchRule(u).apply(u)); + } + + @SmallTest + public void testAmbiguousMatch() throws UrlRules.RuleFormatException { + // Rule is the longest match wins. + UrlRules rules = new UrlRules(new Rule[] { + new Rule("1", "http://xyz/one rewrite http://rewrite/"), + new Rule("123", "http://xyz/onetwothree rewrite http://rewrite/"), + new Rule("12", "http://xyz/onetwo rewrite http://rewrite/"), + }); + + assertEquals("1", rules.matchRule("http://xyz/one").mName); + assertEquals("1", rules.matchRule("http://xyz/one...").mName); + assertEquals("12", rules.matchRule("http://xyz/onetwo...").mName); + assertEquals("123", rules.matchRule("http://xyz/onetwothree...").mName); + + } + + @MediumTest + public void testGservicesRules() { + // TODO: use a MockContentProvider/MockContentResolver instead. + ContentResolver r = getContext().getContentResolver(); + + // Update the digest, so the UrlRules cache is reloaded. + Settings.Gservices.putString(r, "digest", "testGservicesRules"); + Settings.Gservices.putString(r, "url:blank_test", ""); + Settings.Gservices.putString(r, "url:test", + "http://foo.bar/ rewrite http://bar.foo/"); + + UrlRules rules = UrlRules.getRules(r); // Don't crash, please. :) + assertTrue(rules.matchRule("http://bar.foo/") == Rule.DEFAULT); + + Rule rule = rules.matchRule("http://foo.bar/bat"); + assertEquals("test", rule.mName); + assertEquals("http://foo.bar/", rule.mPrefix); + assertEquals("http://bar.foo/", rule.mRewrite); + assertFalse(rule.mBlock); + } +} diff --git a/tests/AndroidTests/src/com/android/unit_tests/VectorTest.java b/tests/AndroidTests/src/com/android/unit_tests/VectorTest.java new file mode 100644 index 0000000..22f9771 --- /dev/null +++ b/tests/AndroidTests/src/com/android/unit_tests/VectorTest.java @@ -0,0 +1,555 @@ +/* + * 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.unit_tests; + +import android.test.PerformanceTestBase; +import android.test.PerformanceTestCase; + +import java.util.Vector; +import java.util.Enumeration; + +/** + * Basic Performance Tests for java.util.Vector + */ + +@SuppressWarnings("unchecked") +public class VectorTest extends PerformanceTestBase { + public static final int ITERATIONS = 1000; + private Vector<Integer> mVector; + private Vector<String> mStrVector; + private String mTestString = "Hello Android"; + + @Override + protected void setUp() throws Exception { + super.setUp(); + mVector = new Vector(); + mStrVector = new Vector(); + for (int i = ITERATIONS - 1; i >= 0; i--) { + assertTrue(mVector.add(i)); + assertTrue(mStrVector.add(Integer.toString(i))); + } + } + + @Override + public int startPerformance(PerformanceTestCase.Intermediates intermediates) { + intermediates.setInternalIterations(ITERATIONS); + return 0; + } + + public void testVectorAdd() { + Vector<Integer> vector = new Vector(); + for (int i = ITERATIONS - 1; i >= 0; i--) { + vector.add(i); + vector.add(i); + vector.add(i); + vector.add(i); + vector.add(i); + vector.add(i); + vector.add(i); + vector.add(i); + vector.add(i); + vector.add(i); + } + } + + public void testVectorAdd1() { + Vector<Integer> vector = new Vector(); + for (int i = ITERATIONS - 1; i >= 0; i--) { + vector.add(0, i); + vector.add(0, i); + vector.add(0, i); + vector.add(0, i); + vector.add(0, i); + vector.add(0, i); + vector.add(0, i); + vector.add(0, i); + vector.add(0, i); + vector.add(0, i); + } + } + + public void testVectorToArray() { + Object array; + Vector<Integer> vector = mVector; + for (int i = ITERATIONS - 1; i >= 0; i--) { + array = vector.toArray(); + array = vector.toArray(); + array = vector.toArray(); + array = vector.toArray(); + array = vector.toArray(); + array = vector.toArray(); + array = vector.toArray(); + array = vector.toArray(); + array = vector.toArray(); + array = vector.toArray(); + } + } + + /** + * + */ + public void testVectorSize() { + Vector<Integer> vector = mVector; + for (int i = ITERATIONS - 1; i >= 0; i--) { + int mLen; + mLen = vector.size(); + mLen = vector.size(); + mLen = vector.size(); + mLen = vector.size(); + mLen = vector.size(); + mLen = vector.size(); + mLen = vector.size(); + mLen = vector.size(); + mLen = vector.size(); + mLen = vector.size(); + } + } + + public void testVectorGet() { + int element; + Vector<Integer> vector = mVector; + for (int i = ITERATIONS - 1; i >= 0; i--) { + element = vector.get(i); + element = vector.get(i); + element = vector.get(i); + element = vector.get(i); + element = vector.get(i); + element = vector.get(i); + element = vector.get(i); + element = vector.get(i); + element = vector.get(i); + element = vector.get(i); + } + + } + + public void testVectorContains() { + boolean flag; + Vector<Integer> vector = mVector; + for (int i = ITERATIONS - 1; i >= 0; i--) { + flag = vector.contains(i); + flag = vector.contains(i); + flag = vector.contains(i); + flag = vector.contains(i); + flag = vector.contains(i); + flag = vector.contains(i); + flag = vector.contains(i); + flag = vector.contains(i); + flag = vector.contains(i); + flag = vector.contains(i); + } + } + + public void testVectorToArray1() { + Integer[] rArray = new Integer[100]; + Integer[] array; + Vector<Integer> vector = mVector; + for (int i = ITERATIONS - 1; i >= 0; i--) { + array = vector.toArray(rArray); + array = vector.toArray(rArray); + array = vector.toArray(rArray); + array = vector.toArray(rArray); + array = vector.toArray(rArray); + array = vector.toArray(rArray); + array = vector.toArray(rArray); + array = vector.toArray(rArray); + array = vector.toArray(rArray); + array = vector.toArray(rArray); + } + } + + public void testVectorSet() { + Vector<Integer> vector = mVector; + int pos = 5, value = 0; + for (int i = ITERATIONS - 1; i >= 0; i--) { + vector.set(pos, value); + vector.set(pos, value); + vector.set(pos, value); + vector.set(pos, value); + vector.set(pos, value); + vector.set(pos, value); + vector.set(pos, value); + vector.set(pos, value); + vector.set(pos, value); + vector.set(pos, value); + } + } + + public void testVectorIndexOf() { + int index, value = 0; + Vector<Integer> vector = mVector; + for (int i = ITERATIONS - 1; i >= 0; i--) { + index = vector.indexOf(value); + index = vector.indexOf(value); + index = vector.indexOf(value); + index = vector.indexOf(value); + index = vector.indexOf(value); + index = vector.indexOf(value); + index = vector.indexOf(value); + index = vector.indexOf(value); + index = vector.indexOf(value); + index = vector.indexOf(value); + } + } + + public void testVectorLastIndexOf() { + int index, value = 0; + Vector<Integer> vector = mVector; + for (int i = ITERATIONS - 1; i >= 0; i--) { + index = vector.lastIndexOf(value); + index = vector.lastIndexOf(value); + index = vector.lastIndexOf(value); + index = vector.lastIndexOf(value); + index = vector.lastIndexOf(value); + index = vector.lastIndexOf(value); + index = vector.lastIndexOf(value); + index = vector.lastIndexOf(value); + index = vector.lastIndexOf(value); + index = vector.lastIndexOf(value); + } + } + + public void testVectorRemove() { + int index, value = 0; + Vector<Integer> vector = new Vector(mVector); + for (int i = 10; i > 0; i--) { + index = vector.remove(value); + index = vector.remove(value); + index = vector.remove(value); + index = vector.remove(value); + index = vector.remove(value); + index = vector.remove(value); + index = vector.remove(value); + index = vector.remove(value); + index = vector.remove(value); + index = vector.remove(value); + } + } + + public void testVectorRemoveElement() { + Vector<Integer> vector = new Vector(mVector); + for (int i = 10; i > 0; i--) { + vector.removeElement(i); + vector.removeElement(i); + vector.removeElement(i); + vector.removeElement(i); + vector.removeElement(i); + vector.removeElement(i); + vector.removeElement(i); + vector.removeElement(i); + vector.removeElement(i); + vector.removeElement(i); + } + } + + public void VectorRemoveElementAt() { + Vector<Integer> vector = new Vector(mVector); + for (int i = 10; i > 0; i--) { + vector.removeElementAt(i); + vector.removeElementAt(i); + vector.removeElementAt(i); + vector.removeElementAt(i); + vector.removeElementAt(i); + vector.removeElementAt(i); + vector.removeElementAt(i); + vector.removeElementAt(i); + vector.removeElementAt(i); + vector.removeElementAt(i); + } + } + + public void VectorAddAll() { + Vector<Integer> vector = new Vector(), vector1 = mVector; + + boolean flag; + for (int i = 10; i > 0; i--) { + flag = vector.addAll(vector1); + flag = vector.addAll(vector1); + flag = vector.addAll(vector1); + flag = vector.addAll(vector1); + flag = vector.addAll(vector1); + flag = vector.addAll(vector1); + flag = vector.addAll(vector1); + flag = vector.addAll(vector1); + flag = vector.addAll(vector1); + flag = vector.addAll(vector1); + } + } + + public void VectorRemove1() { + Vector<String> vector = mStrVector; + for (int j = 1000; j > 0; j--) { + vector.add("a"); + vector.add("b"); + } + String s = new String("a"); + boolean flag; + for (int i = 10; i > 0; i--) { + flag = vector.remove(s); + flag = vector.remove(s); + flag = vector.remove(s); + flag = vector.remove(s); + flag = vector.remove(s); + flag = vector.remove(s); + flag = vector.remove(s); + flag = vector.remove(s); + flag = vector.remove(s); + flag = vector.remove(s); + } + } + + public void testVectorAddAll1() { + Vector<Integer> mEmptyVector = new Vector(); + boolean flag; + int pos = 0; + Vector<Integer> vector1 = mVector; + Vector<Integer> vector = mEmptyVector; + for (int i = 10; i > 0; i--) { + flag = vector.addAll(pos, vector1); + flag = vector.addAll(pos, vector1); + flag = vector.addAll(pos, vector1); + flag = vector.addAll(pos, vector1); + flag = vector.addAll(pos, vector1); + flag = vector.addAll(pos, vector1); + flag = vector.addAll(pos, vector1); + flag = vector.addAll(pos, vector1); + flag = vector.addAll(pos, vector1); + flag = vector.addAll(pos, vector1); + } + } + + public void testVectorClone() { + Object obj; + Vector<Integer> vector = mVector; + for (int i = ITERATIONS - 1; i > 0; i--) { + obj = vector.clone(); + obj = vector.clone(); + obj = vector.clone(); + obj = vector.clone(); + obj = vector.clone(); + obj = vector.clone(); + obj = vector.clone(); + obj = vector.clone(); + obj = vector.clone(); + obj = vector.clone(); + } + } + + public void testVectorCapacity() { + int capacity; + Vector<Integer> vector = mVector; + for (int i = ITERATIONS - 1; i > 0; i--) { + capacity = vector.capacity(); + capacity = vector.capacity(); + capacity = vector.capacity(); + capacity = vector.capacity(); + capacity = vector.capacity(); + capacity = vector.capacity(); + capacity = vector.capacity(); + capacity = vector.capacity(); + capacity = vector.capacity(); + capacity = vector.capacity(); + } + } + + public void testVectorHashcode() { + int element; + Vector<Integer> vector = mVector; + for (int i = ITERATIONS - 1; i > 0; i--) { + element = vector.hashCode(); + element = vector.hashCode(); + element = vector.hashCode(); + element = vector.hashCode(); + element = vector.hashCode(); + element = vector.hashCode(); + element = vector.hashCode(); + element = vector.hashCode(); + element = vector.hashCode(); + element = vector.hashCode(); + } + } + + public void testVectorElements() { + Enumeration<Integer> elements; + Vector<Integer> vector = mVector; + for (int i = ITERATIONS - 1; i > 0; i--) { + elements = vector.elements(); + elements = vector.elements(); + elements = vector.elements(); + elements = vector.elements(); + elements = vector.elements(); + elements = vector.elements(); + elements = vector.elements(); + elements = vector.elements(); + elements = vector.elements(); + elements = vector.elements(); + } + } + + public void testVectorToString() { + String str; + Vector<Integer> vector = mVector; + for (int i = ITERATIONS - 1; i > 0; i--) { + str = vector.toString(); + str = vector.toString(); + str = vector.toString(); + str = vector.toString(); + str = vector.toString(); + str = vector.toString(); + str = vector.toString(); + str = vector.toString(); + str = vector.toString(); + str = vector.toString(); + } + } + + public void testVectorElementAt() { + int element; + Vector<Integer> vector = mVector; + for (int i = ITERATIONS - 1; i > 0; i--) { + element = vector.elementAt(50); + element = vector.elementAt(50); + element = vector.elementAt(50); + element = vector.elementAt(50); + element = vector.elementAt(50); + element = vector.elementAt(50); + element = vector.elementAt(50); + element = vector.elementAt(50); + element = vector.elementAt(50); + element = vector.elementAt(50); + } + } + + public void testVectorAddElement() { + int element; + Vector<String> vector = mStrVector; + for (int i = ITERATIONS - 1; i > 0; i--) { + vector.addElement(mTestString); + vector.addElement(mTestString); + vector.addElement(mTestString); + vector.addElement(mTestString); + vector.addElement(mTestString); + vector.addElement(mTestString); + vector.addElement(mTestString); + vector.addElement(mTestString); + vector.addElement(mTestString); + vector.addElement(mTestString); + } + } + + public void testVectorFirstElement() { + int element; + Vector<Integer> vector = mVector; + for (int i = ITERATIONS - 1; i > 0; i--) { + element = vector.firstElement(); + element = vector.firstElement(); + element = vector.firstElement(); + element = vector.firstElement(); + element = vector.firstElement(); + element = vector.firstElement(); + element = vector.firstElement(); + element = vector.firstElement(); + element = vector.firstElement(); + element = vector.firstElement(); + } + } + + public void testVectorLastElement() { + int element; + Vector<Integer> vector = mVector; + for (int i = ITERATIONS - 1; i > 0; i--) { + element = vector.lastElement(); + element = vector.lastElement(); + element = vector.lastElement(); + element = vector.lastElement(); + element = vector.lastElement(); + element = vector.lastElement(); + element = vector.lastElement(); + element = vector.lastElement(); + element = vector.lastElement(); + element = vector.lastElement(); + } + } + + public void testVectorSetElementAt() { + Vector<Integer> vector = mVector; + int value1 = 500, value2 = 50; + for (int i = ITERATIONS - 1; i > 0; i--) { + vector.setElementAt(value1, value2); + vector.setElementAt(value1, value2); + vector.setElementAt(value1, value2); + vector.setElementAt(value1, value2); + vector.setElementAt(value1, value2); + vector.setElementAt(value1, value2); + vector.setElementAt(value1, value2); + vector.setElementAt(value1, value2); + vector.setElementAt(value1, value2); + vector.setElementAt(value1, value2); + } + } + + public void testVectorIsEmpty() { + boolean flag; + Vector<Integer> vector = mVector; + for (int i = ITERATIONS - 1; i > 0; i--) { + flag = vector.isEmpty(); + flag = vector.isEmpty(); + flag = vector.isEmpty(); + flag = vector.isEmpty(); + flag = vector.isEmpty(); + flag = vector.isEmpty(); + flag = vector.isEmpty(); + flag = vector.isEmpty(); + flag = vector.isEmpty(); + flag = vector.isEmpty(); + } + } + + public void testVectorCopyInto() { + Integer[] rArray = new Integer[ITERATIONS]; + Vector<Integer> vector = mVector; + for (int i = ITERATIONS - 1; i > 0; i--) { + vector.copyInto(rArray); + vector.copyInto(rArray); + vector.copyInto(rArray); + vector.copyInto(rArray); + vector.copyInto(rArray); + vector.copyInto(rArray); + vector.copyInto(rArray); + vector.copyInto(rArray); + vector.copyInto(rArray); + vector.copyInto(rArray); + } + } + + public void testVectorInsertElementAt() { + Vector<String> vector = mStrVector; + String string = mTestString; + for (int i = ITERATIONS - 1; i > 0; i--) { + vector.insertElementAt(string, i); + vector.insertElementAt(string, i); + vector.insertElementAt(string, i); + vector.insertElementAt(string, i); + vector.insertElementAt(string, i); + vector.insertElementAt(string, i); + vector.insertElementAt(string, i); + vector.insertElementAt(string, i); + vector.insertElementAt(string, i); + vector.insertElementAt(string, i); + } + } +} diff --git a/tests/AndroidTests/src/com/android/unit_tests/WebkitTest.java b/tests/AndroidTests/src/com/android/unit_tests/WebkitTest.java new file mode 100644 index 0000000..4a0519e --- /dev/null +++ b/tests/AndroidTests/src/com/android/unit_tests/WebkitTest.java @@ -0,0 +1,59 @@ +/* + * 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.unit_tests; + +import android.test.AndroidTestCase; +import android.text.format.DateFormat; +import android.test.suitebuilder.annotation.MediumTest; +import android.util.Log; +import android.webkit.DateSorter; + +import java.util.Calendar; +import java.util.Date; + +public class WebkitTest extends AndroidTestCase { + + private static final String LOGTAG = WebkitTest.class.getName(); + + @MediumTest + public void testDateSorter() throws Exception { + /** + * Note: check the logging output manually to test + * nothing automated yet, besides object creation + */ + DateSorter dateSorter = new DateSorter(mContext); + Date date = new Date(); + + for (int i = 0; i < DateSorter.DAY_COUNT; i++) { + Log.i(LOGTAG, "Boundary " + i + " " + dateSorter.getBoundary(i)); + Log.i(LOGTAG, "Label " + i + " " + dateSorter.getLabel(i)); + } + + Calendar c = Calendar.getInstance(); + long time = c.getTimeInMillis(); + int index; + Log.i(LOGTAG, "now: " + dateSorter.getIndex(time)); + for (int i = 0; i < 20; i++) { + time -= 8 * 60 * 60 * 1000; // 8 hours + date.setTime(time); + c.setTime(date); + index = dateSorter.getIndex(time); + Log.i(LOGTAG, "time: " + DateFormat.format("yyyy/MM/dd kk:mm:ss", c).toString() + + " " + index + " " + dateSorter.getLabel(index)); + } + } +} diff --git a/tests/AndroidTests/src/com/android/unit_tests/activity/AbortReceiver.java b/tests/AndroidTests/src/com/android/unit_tests/activity/AbortReceiver.java new file mode 100644 index 0000000..d9d6101 --- /dev/null +++ b/tests/AndroidTests/src/com/android/unit_tests/activity/AbortReceiver.java @@ -0,0 +1,49 @@ +/* + * 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.unit_tests.activity; + +import android.content.Context; +import android.content.Intent; +import android.content.BroadcastReceiver; +import android.os.RemoteException; +import android.os.IBinder; +import android.os.Parcel; +import android.util.Log; + +public class AbortReceiver extends BroadcastReceiver +{ + public AbortReceiver() + { + } + + public void onReceive(Context context, Intent intent) + { + //Log.i("AbortReceiver", "onReceiveIntent!"); + try { + IBinder caller = intent.getIBinderExtra("caller"); + Parcel data = Parcel.obtain(); + data.writeInterfaceToken(LaunchpadActivity.LAUNCH); + data.writeString(LaunchpadActivity.RECEIVER_ABORT); + caller.transact(LaunchpadActivity.GOT_RECEIVE_TRANSACTION, data, null, 0); + data.recycle(); + } catch (RemoteException ex) { + } + + // abort the broadcast!!! + abortBroadcast(); + } +} diff --git a/tests/AndroidTests/src/com/android/unit_tests/activity/ActivityManagerTest.java b/tests/AndroidTests/src/com/android/unit_tests/activity/ActivityManagerTest.java new file mode 100644 index 0000000..ab91761 --- /dev/null +++ b/tests/AndroidTests/src/com/android/unit_tests/activity/ActivityManagerTest.java @@ -0,0 +1,135 @@ +/* + * Copyright (C) 2008 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.unit_tests.activity; + +import android.app.ActivityManager; +import android.content.Context; +import android.content.pm.ConfigurationInfo; +import android.content.res.Configuration; +import android.test.AndroidTestCase; +import android.test.suitebuilder.annotation.SmallTest; +import android.test.suitebuilder.annotation.Suppress; + +import java.util.Iterator; +import java.util.List; + +public class ActivityManagerTest extends AndroidTestCase { + + protected Context mContext; + protected ActivityManager mActivityManager; + + @Override + protected void setUp() throws Exception { + super.setUp(); + mContext = getContext(); + mActivityManager = (ActivityManager) mContext.getSystemService(Context.ACTIVITY_SERVICE); + } + + // TODO should write a test for getRecentTasks() + // TODO should write a test for getRunningTasks() + // TODO should write a test for getMemoryInfo() + + // TODO: Find a way to re-enable this. It fails if any other app has failed during startup. + // This is probably an OK assumption given the desired system status when we run unit tests, + // but it's not necessarily the right assumption for a unit test. + @Suppress + public void disabledTestErrorTasksEmpty() throws Exception { + + List<ActivityManager.ProcessErrorStateInfo> errList; + + errList = mActivityManager.getProcessesInErrorState(); + + // test: confirm list is empty + assertNull(errList); + } + + // TODO: Force an activity into an error state - then see if we can catch it here? + @SmallTest + public void testErrorTasksWithError() throws Exception { + + List<ActivityManager.ProcessErrorStateInfo> errList; + + // TODO force another process into an error condition. How? + + // test: confirm error list length is at least 1 under varying query lengths +// checkErrorListMax(1,-1); + + errList = mActivityManager.getProcessesInErrorState(); + + // test: the list itself is healthy + checkErrorListSanity(errList); + + // test: confirm our application shows up in the list + } + + // TODO: Force an activity into an ANR state - then see if we can catch it here? + @SmallTest + public void testErrorTasksWithANR() throws Exception { + + List<ActivityManager.ProcessErrorStateInfo> errList; + + // TODO: force an application into an ANR state + + errList = mActivityManager.getProcessesInErrorState(); + + // test: the list itself is healthy + checkErrorListSanity(errList); + + // test: confirm our ANR'ing application shows up in the list + } + + @SmallTest + public void testGetDeviceConfigurationInfo() throws Exception { + ConfigurationInfo config = mActivityManager.getDeviceConfigurationInfo(); + assertNotNull(config); + // Validate values against configuration retrieved from resources + Configuration vconfig = mContext.getResources().getConfiguration(); + assertNotNull(vconfig); + assertEquals(config.reqKeyboardType, vconfig.keyboard); + assertEquals(config.reqTouchScreen, vconfig.touchscreen); + assertEquals(config.reqNavigation, vconfig.navigation); + if (vconfig.navigation == Configuration.NAVIGATION_NONAV) { + assertNotNull(config.reqInputFeatures & ConfigurationInfo.INPUT_FEATURE_FIVE_WAY_NAV); + } + if (vconfig.keyboard != Configuration.KEYBOARD_UNDEFINED) { + assertNotNull(config.reqInputFeatures & ConfigurationInfo.INPUT_FEATURE_HARD_KEYBOARD); + } + } + + // If any entries in appear in the list, sanity check them against all running applications + private void checkErrorListSanity(List<ActivityManager.ProcessErrorStateInfo> errList) { + if (errList == null) return; + + Iterator<ActivityManager.ProcessErrorStateInfo> iter = errList.iterator(); + while (iter.hasNext()) { + ActivityManager.ProcessErrorStateInfo info = iter.next(); + assertNotNull(info); + // sanity checks + assertTrue((info.condition == ActivityManager.ProcessErrorStateInfo.CRASHED) || + (info.condition == ActivityManager.ProcessErrorStateInfo.NOT_RESPONDING)); + // TODO look at each of these and consider a stronger test + // TODO can we cross-check at the process name via some other API? + // TODO is there a better test for strings, e.g. "assertIsLegalString") + assertNotNull(info.processName); + // reasonableness test for info.pid ? + assertNotNull(info.longMsg); + assertNotNull(info.shortMsg); + // is there any reasonable test for the crashData? Probably not. + } + } +} + diff --git a/tests/AndroidTests/src/com/android/unit_tests/activity/ActivityTests.java b/tests/AndroidTests/src/com/android/unit_tests/activity/ActivityTests.java new file mode 100644 index 0000000..cffc60a --- /dev/null +++ b/tests/AndroidTests/src/com/android/unit_tests/activity/ActivityTests.java @@ -0,0 +1,40 @@ +/* + * 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.unit_tests.activity; + +import junit.framework.TestSuite; + +public class ActivityTests { + public static final boolean DEBUG_LIFECYCLE = false; + + public static TestSuite suite() { + TestSuite suite = new TestSuite(ActivityTests.class.getName()); + + suite.addTestSuite(BroadcastTest.class); + suite.addTestSuite(IntentSenderTest.class); + suite.addTestSuite(ActivityManagerTest.class); + suite.addTestSuite(LaunchTest.class); + suite.addTestSuite(LifecycleTest.class); + suite.addTestSuite(ServiceTest.class); + suite.addTestSuite(MetaDataTest.class); + // Remove temporarily until bug 1171309 is fixed. + //suite.addTestSuite(SubActivityTest.class); + suite.addTestSuite(SetTimeZonePermissionsTest.class); + + return suite; + } +} diff --git a/tests/AndroidTests/src/com/android/unit_tests/activity/ActivityTestsBase.java b/tests/AndroidTests/src/com/android/unit_tests/activity/ActivityTestsBase.java new file mode 100644 index 0000000..f960969 --- /dev/null +++ b/tests/AndroidTests/src/com/android/unit_tests/activity/ActivityTestsBase.java @@ -0,0 +1,212 @@ +/* + * 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.unit_tests.activity; + +import android.app.Activity; +import android.content.Context; +import android.content.Intent; +import android.test.AndroidTestCase; +import android.test.PerformanceTestCase; + +public class ActivityTestsBase extends AndroidTestCase + implements PerformanceTestCase, LaunchpadActivity.CallingTest { + public static final String PERMISSION_GRANTED = + "com.android.unit_tests.permission.TEST_GRANTED"; + public static final String PERMISSION_DENIED = + "com.android.unit_tests.permission.TEST_DENIED"; + + protected Intent mIntent; + + private PerformanceTestCase.Intermediates mIntermediates; + private String mExpecting; + + // Synchronization of activity result. + private boolean mFinished; + private int mResultCode = 0; + private Intent mData; + private RuntimeException mResultStack = null; + + @Override + protected void setUp() throws Exception { + super.setUp(); + mIntent = new Intent(mContext, LaunchpadActivity.class); + mIntermediates = null; + } + + @Override + protected void tearDown() throws Exception { + mIntermediates = null; + super.tearDown(); + } + + public boolean isPerformanceOnly() { + return false; + } + + public void setInternalIterations(int count) { + } + + public void startTiming(boolean realTime) { + if (mIntermediates != null) { + mIntermediates.startTiming(realTime); + } + } + + public void addIntermediate(String name) { + if (mIntermediates != null) { + mIntermediates.addIntermediate(name); + } + } + + public void addIntermediate(String name, long timeInNS) { + if (mIntermediates != null) { + mIntermediates.addIntermediate(name, timeInNS); + } + } + + public void finishTiming(boolean realTime) { + if (mIntermediates != null) { + mIntermediates.finishTiming(realTime); + } + } + + public void activityFinished(int resultCode, Intent data, RuntimeException where) { + finishWithResult(resultCode, data, where); + } + + public Intent editIntent() { + return mIntent; + } + + public Context getContext() { + return mContext; + } + + public int startPerformance(Intermediates intermediates) { + mIntermediates = intermediates; + return 1; + } + + public void finishGood() { + finishWithResult(Activity.RESULT_OK, null); + } + + public void finishBad(String error) { + finishWithResult(Activity.RESULT_CANCELED, (new Intent()).setAction(error)); + } + + public void finishWithResult(int resultCode, Intent data) { + RuntimeException where = new RuntimeException("Original error was here"); + where.fillInStackTrace(); + finishWithResult(resultCode, data, where); + } + + public void finishWithResult(int resultCode, Intent data, RuntimeException where) { + synchronized (this) { + //System.out.println("*** Activity finished!!"); + mResultCode = resultCode; + mData = data; + mResultStack = where; + mFinished = true; + notifyAll(); + } + } + + public int runLaunchpad(String action) { + LaunchpadActivity.setCallingTest(this); + + synchronized (this) { + mIntent.setAction(action); + mFinished = false; + //System.out.println("*** Starting: " + mIntent); + mIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + mContext.startActivity(mIntent); + } + + return waitForResultOrThrow(60 * 1000); + } + + public int waitForResultOrThrow(int timeoutMs) { + return waitForResultOrThrow(timeoutMs, null); + } + + public int waitForResultOrThrow(int timeoutMs, String expected) { + int res = waitForResult(timeoutMs, expected); + + if (res == Activity.RESULT_CANCELED) { + if (mResultStack != null) { + throw new RuntimeException( + mData != null ? mData.toString() : "Unable to launch", + mResultStack); + } else { + throw new RuntimeException( + mData != null ? mData.toString() : "Unable to launch"); + } + } + return res; + } + + public int waitForResult(int timeoutMs, String expected) { + mExpecting = expected; + + long endTime = System.currentTimeMillis() + timeoutMs; + + boolean timeout = false; + synchronized (this) { + while (!mFinished) { + long delay = endTime - System.currentTimeMillis(); + if (delay < 0) { + timeout = true; + break; + } + + try { + wait(delay); + } catch (java.lang.InterruptedException e) { + // do nothing + } + } + } + + mFinished = false; + + if (timeout) { + mResultCode = Activity.RESULT_CANCELED; + onTimeout(); + } + return mResultCode; + } + + public int getResultCode() { + return mResultCode; + } + + public Intent getResultData() { + return mData; + } + + public RuntimeException getResultStack() { + return mResultStack; + } + + public void onTimeout() { + String msg = mExpecting == null + ? "Timeout" : ("Timeout while expecting " + mExpecting); + finishWithResult(Activity.RESULT_CANCELED, (new Intent()).setAction(msg)); + } +} + diff --git a/tests/AndroidTests/src/com/android/unit_tests/activity/BroadcastTest.java b/tests/AndroidTests/src/com/android/unit_tests/activity/BroadcastTest.java new file mode 100644 index 0000000..7f6db3c --- /dev/null +++ b/tests/AndroidTests/src/com/android/unit_tests/activity/BroadcastTest.java @@ -0,0 +1,536 @@ +/* + * 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.unit_tests.activity; + +import android.app.Activity; +import android.app.ActivityManagerNative; +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; +import android.content.IntentFilter; +import android.os.Binder; +import android.os.Bundle; +import android.os.IBinder; +import android.os.Parcel; +import android.test.FlakyTest; +import android.test.suitebuilder.annotation.Suppress; +import android.util.Log; + +import java.util.Arrays; + +public class BroadcastTest extends ActivityTestsBase { + public static final int BROADCAST_TIMEOUT = 5 * 1000; + + public static final String BROADCAST_REGISTERED = + "com.android.unit_tests.activity.BROADCAST_REGISTERED"; + public static final String BROADCAST_LOCAL = + "com.android.unit_tests.activity.BROADCAST_LOCAL"; + public static final String BROADCAST_LOCAL_GRANTED = + "com.android.unit_tests.activity.BROADCAST_LOCAL_GRANTED"; + public static final String BROADCAST_LOCAL_DENIED = + "com.android.unit_tests.activity.BROADCAST_LOCAL_DENIED"; + public static final String BROADCAST_REMOTE = + "com.android.unit_tests.activity.BROADCAST_REMOTE"; + public static final String BROADCAST_REMOTE_GRANTED = + "com.android.unit_tests.activity.BROADCAST_REMOTE_GRANTED"; + public static final String BROADCAST_REMOTE_DENIED = + "com.android.unit_tests.activity.BROADCAST_REMOTE_DENIED"; + public static final String BROADCAST_ALL = + "com.android.unit_tests.activity.BROADCAST_ALL"; + public static final String BROADCAST_MULTI = + "com.android.unit_tests.activity.BROADCAST_MULTI"; + public static final String BROADCAST_ABORT = + "com.android.unit_tests.activity.BROADCAST_ABORT"; + + public static final String BROADCAST_STICKY1 = + "com.android.unit_tests.activity.BROADCAST_STICKY1"; + public static final String BROADCAST_STICKY2 = + "com.android.unit_tests.activity.BROADCAST_STICKY2"; + + public static final String BROADCAST_FAIL_REGISTER = + "com.android.unit_tests.activity.BROADCAST_FAIL_REGISTER"; + public static final String BROADCAST_FAIL_BIND = + "com.android.unit_tests.activity.BROADCAST_FAIL_BIND"; + + public static final String RECEIVER_REG = "receiver-reg"; + public static final String RECEIVER_LOCAL = "receiver-local"; + public static final String RECEIVER_REMOTE = "receiver-remote"; + public static final String RECEIVER_ABORT = "receiver-abort"; + public static final String RECEIVER_RESULTS = "receiver-results"; + + public static final String DATA_1 = "one"; + public static final String DATA_2 = "two"; + + public static final int GOT_RECEIVE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION; + public static final int ERROR_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION + 1; + + private String[] mExpectedReceivers = null; + private int mNextReceiver; + + private String[] mExpectedData = null; + private boolean[] mReceivedData = null; + + boolean mReceiverRegistered = false; + + public void setExpectedReceivers(String[] receivers) { + mExpectedReceivers = receivers; + mNextReceiver = 0; + } + + public void setExpectedData(String[] data) { + mExpectedData = data; + mReceivedData = new boolean[data.length]; + } + + public void onTimeout() { + String msg = "Timeout"; + if (mExpectedReceivers != null && mNextReceiver < mExpectedReceivers.length) { + msg = msg + " waiting for " + mExpectedReceivers[mNextReceiver]; + } + finishBad(msg); + } + + public Intent makeBroadcastIntent(String action) { + Intent intent = new Intent(action, null); + intent.putExtra("caller", mCallTarget); + return intent; + } + + public void finishWithResult(int resultCode, Intent data) { + unregisterMyReceiver(); + super.finishWithResult(resultCode, data); + } + + public final void gotReceive(String name, Intent intent) { + synchronized (this) { + + //System.out.println("Got receive: " + name); + //System.out.println(mNextReceiver + " in " + mExpectedReceivers); + //new RuntimeException("stack").printStackTrace(); + + addIntermediate(name); + + if (mExpectedData != null) { + int n = mExpectedData.length; + int i; + boolean prev = false; + for (i = 0; i < n; i++) { + if (mExpectedData[i].equals(intent.getStringExtra("test"))) { + if (mReceivedData[i]) { + prev = true; + continue; + } + mReceivedData[i] = true; + break; + } + } + if (i >= n) { + if (prev) { + finishBad("Receive got data too many times: " + + intent.getStringExtra("test")); + } else { + finishBad("Receive got unexpected data: " + + intent.getStringExtra("test")); + } + new RuntimeException("stack").printStackTrace(); + return; + } + } + + if (mNextReceiver >= mExpectedReceivers.length) { + finishBad("Got too many onReceiveIntent() calls!"); +// System.out.println("Too many intents received: now at " +// + mNextReceiver + ", expect list: " +// + Arrays.toString(mExpectedReceivers)); + fail("Got too many onReceiveIntent() calls!"); + } else if (!mExpectedReceivers[mNextReceiver].equals(name)) { + finishBad("Receive out of order: got " + name + + " but expected " + + mExpectedReceivers[mNextReceiver]); + fail("Receive out of order: got " + name + + " but expected " + + mExpectedReceivers[mNextReceiver]); + } else { + mNextReceiver++; + if (mNextReceiver == mExpectedReceivers.length) { + finishTest(); + } + } + } + } + + public void registerMyReceiver(IntentFilter filter, String permission) { + mReceiverRegistered = true; + //System.out.println("Registering: " + mReceiver); + getContext().registerReceiver(mReceiver, filter, permission, null); + } + + public void unregisterMyReceiver() { + if (mReceiverRegistered) { + unregisterMyReceiverNoCheck(); + } + } + + public void unregisterMyReceiverNoCheck() { + mReceiverRegistered = false; + //System.out.println("Unregistering: " + mReceiver); + getContext().unregisterReceiver(mReceiver); + } + + public void onRegisteredReceiver(Intent intent) { + gotReceive(RECEIVER_REG, intent); + } + + private Binder mCallTarget = new Binder() { + public boolean onTransact(int code, Parcel data, Parcel reply, + int flags) { + data.setDataPosition(0); + data.enforceInterface(LaunchpadActivity.LAUNCH); + if (code == GOT_RECEIVE_TRANSACTION) { + String name = data.readString(); + gotReceive(name, null); + return true; + } else if (code == ERROR_TRANSACTION) { + finishBad(data.readString()); + return true; + } + return false; + } + }; + + private void finishTest() { + if (mReceiverRegistered) { + addIntermediate("before-unregister"); + unregisterMyReceiver(); + } + finishTiming(true); + finishGood(); + } + + private BroadcastReceiver mReceiver = new BroadcastReceiver() { + public void onReceive(Context context, Intent intent) { + //System.out.println("Receive in: " + this + ": " + intent); + onRegisteredReceiver(intent); + } + }; + + // Mark flaky until http://b/issue?id=1191607 is resolved. + @FlakyTest(tolerance=2) + public void testRegistered() throws Exception { + runLaunchpad(LaunchpadActivity.BROADCAST_REGISTERED); + } + + public void testLocal() throws Exception { + runLaunchpad(LaunchpadActivity.BROADCAST_LOCAL); + } + + public void testRemote() throws Exception { + runLaunchpad(LaunchpadActivity.BROADCAST_REMOTE); + } + + public void testAbort() throws Exception { + runLaunchpad(LaunchpadActivity.BROADCAST_ABORT); + } + + @FlakyTest(tolerance=2) + public void testAll() throws Exception { + runLaunchpad(LaunchpadActivity.BROADCAST_ALL); + } + + @FlakyTest(tolerance=2) + public void testMulti() throws Exception { + runLaunchpad(LaunchpadActivity.BROADCAST_MULTI); + } + + private class TestBroadcastReceiver extends BroadcastReceiver { + public boolean mHaveResult = false; + + @Override + public void onReceive(Context context, Intent intent) { + synchronized (BroadcastTest.this) { + mHaveResult = true; + BroadcastTest.this.notifyAll(); + } + } + } + + public void testResult() throws Exception { + TestBroadcastReceiver broadcastReceiver = new TestBroadcastReceiver(); + + synchronized (this) { + Bundle map = new Bundle(); + map.putString("foo", "you"); + map.putString("remove", "me"); + getContext().sendOrderedBroadcast( + new Intent("com.android.unit_tests.activity.BROADCAST_RESULT"), + null, broadcastReceiver, null, 1, "foo", map); + while (!broadcastReceiver.mHaveResult) { + try { + wait(); + } catch (InterruptedException e) { + } + } + + //System.out.println("Code: " + mResultCode + ", data: " + mResultData); + //System.out.println("Extras: " + mResultExtras); + + assertEquals("Incorrect code: " + broadcastReceiver.getResultCode(), + 3, broadcastReceiver.getResultCode()); + + assertEquals("bar", broadcastReceiver.getResultData()); + + Bundle resultExtras = broadcastReceiver.getResultExtras(false); + assertEquals("them", resultExtras.getString("bar")); + assertEquals("you", resultExtras.getString("foo")); + assertNull(resultExtras.getString("remove")); + } + } + + public void testSetSticky() throws Exception { + Intent intent = new Intent(LaunchpadActivity.BROADCAST_STICKY1, null); + intent.putExtra("test", LaunchpadActivity.DATA_1); + ActivityManagerNative.getDefault().unbroadcastIntent(null, intent); + + ActivityManagerNative.broadcastStickyIntent(intent, null); + addIntermediate("finished-broadcast"); + + IntentFilter filter = new IntentFilter(LaunchpadActivity.BROADCAST_STICKY1); + Intent sticky = getContext().registerReceiver(null, filter); + assertNotNull("Sticky not found", sticky); + assertEquals(LaunchpadActivity.DATA_1, sticky.getStringExtra("test")); + } + + public void testClearSticky() throws Exception { + Intent intent = new Intent(LaunchpadActivity.BROADCAST_STICKY1, null); + intent.putExtra("test", LaunchpadActivity.DATA_1); + ActivityManagerNative.broadcastStickyIntent(intent, null); + + ActivityManagerNative.getDefault().unbroadcastIntent( + null, new Intent(LaunchpadActivity.BROADCAST_STICKY1, null)); + addIntermediate("finished-unbroadcast"); + + IntentFilter filter = new IntentFilter(LaunchpadActivity.BROADCAST_STICKY1); + Intent sticky = getContext().registerReceiver(null, filter); + assertNull("Sticky not found", sticky); + } + + public void testReplaceSticky() throws Exception { + Intent intent = new Intent(LaunchpadActivity.BROADCAST_STICKY1, null); + intent.putExtra("test", LaunchpadActivity.DATA_1); + ActivityManagerNative.broadcastStickyIntent(intent, null); + intent.putExtra("test", LaunchpadActivity.DATA_2); + + ActivityManagerNative.broadcastStickyIntent(intent, null); + addIntermediate("finished-broadcast"); + + IntentFilter filter = new IntentFilter(LaunchpadActivity.BROADCAST_STICKY1); + Intent sticky = getContext().registerReceiver(null, filter); + assertNotNull("Sticky not found", sticky); + assertEquals(LaunchpadActivity.DATA_2, sticky.getStringExtra("test")); + } + + // Marking flaky until http://b/issue?id=1191337 is resolved + @FlakyTest(tolerance=2) + public void testReceiveSticky() throws Exception { + Intent intent = new Intent(LaunchpadActivity.BROADCAST_STICKY1, null); + intent.putExtra("test", LaunchpadActivity.DATA_1); + ActivityManagerNative.broadcastStickyIntent(intent, null); + + runLaunchpad(LaunchpadActivity.BROADCAST_STICKY1); + } + + // Marking flaky until http://b/issue?id=1191337 is resolved + @FlakyTest(tolerance=2) + public void testReceive2Sticky() throws Exception { + Intent intent = new Intent(LaunchpadActivity.BROADCAST_STICKY1, null); + intent.putExtra("test", LaunchpadActivity.DATA_1); + ActivityManagerNative.broadcastStickyIntent(intent, null); + intent = new Intent(LaunchpadActivity.BROADCAST_STICKY2, null); + intent.putExtra("test", LaunchpadActivity.DATA_2); + ActivityManagerNative.broadcastStickyIntent(intent, null); + + runLaunchpad(LaunchpadActivity.BROADCAST_STICKY2); + } + + public void testRegisteredReceivePermissionGranted() throws Exception { + setExpectedReceivers(new String[]{RECEIVER_REG}); + registerMyReceiver(new IntentFilter(BROADCAST_REGISTERED), PERMISSION_GRANTED); + addIntermediate("after-register"); + getContext().sendBroadcast(makeBroadcastIntent(BROADCAST_REGISTERED)); + waitForResultOrThrow(BROADCAST_TIMEOUT); + } + + public void testRegisteredReceivePermissionDenied() throws Exception { + setExpectedReceivers(new String[]{RECEIVER_RESULTS}); + registerMyReceiver(new IntentFilter(BROADCAST_REGISTERED), PERMISSION_DENIED); + addIntermediate("after-register"); + + BroadcastReceiver finish = new BroadcastReceiver() { + public void onReceive(Context context, Intent intent) { + gotReceive(RECEIVER_RESULTS, intent); + } + }; + + getContext().sendOrderedBroadcast( + makeBroadcastIntent(BROADCAST_REGISTERED), + null, finish, null, Activity.RESULT_CANCELED, null, null); + waitForResultOrThrow(BROADCAST_TIMEOUT); + } + + public void testRegisteredBroadcastPermissionGranted() throws Exception { + setExpectedReceivers(new String[]{RECEIVER_REG}); + registerMyReceiver(new IntentFilter(BROADCAST_REGISTERED), null); + addIntermediate("after-register"); + getContext().sendBroadcast( + makeBroadcastIntent(BROADCAST_REGISTERED), + PERMISSION_GRANTED); + waitForResultOrThrow(BROADCAST_TIMEOUT); + } + + public void testRegisteredBroadcastPermissionDenied() throws Exception { + setExpectedReceivers(new String[]{RECEIVER_RESULTS}); + registerMyReceiver(new IntentFilter(BROADCAST_REGISTERED), null); + addIntermediate("after-register"); + + BroadcastReceiver finish = new BroadcastReceiver() { + public void onReceive(Context context, Intent intent) { + gotReceive(RECEIVER_RESULTS, intent); + } + }; + + getContext().sendOrderedBroadcast( + makeBroadcastIntent(BROADCAST_REGISTERED), + PERMISSION_DENIED, finish, null, Activity.RESULT_CANCELED, + null, null); + waitForResultOrThrow(BROADCAST_TIMEOUT); + } + + public void testLocalReceivePermissionGranted() throws Exception { + setExpectedReceivers(new String[]{RECEIVER_LOCAL}); + getContext().sendBroadcast(makeBroadcastIntent(BROADCAST_LOCAL_GRANTED)); + waitForResultOrThrow(BROADCAST_TIMEOUT); + } + + public void testLocalReceivePermissionDenied() throws Exception { + setExpectedReceivers(new String[]{RECEIVER_RESULTS}); + + BroadcastReceiver finish = new BroadcastReceiver() { + public void onReceive(Context context, Intent intent) { + gotReceive(RECEIVER_RESULTS, intent); + } + }; + + getContext().sendOrderedBroadcast( + makeBroadcastIntent(BROADCAST_LOCAL_DENIED), + null, finish, null, Activity.RESULT_CANCELED, + null, null); + waitForResultOrThrow(BROADCAST_TIMEOUT); + } + + public void testLocalBroadcastPermissionGranted() throws Exception { + setExpectedReceivers(new String[]{RECEIVER_LOCAL}); + getContext().sendBroadcast( + makeBroadcastIntent(BROADCAST_LOCAL), + PERMISSION_GRANTED); + waitForResultOrThrow(BROADCAST_TIMEOUT); + } + + public void testLocalBroadcastPermissionDenied() throws Exception { + setExpectedReceivers(new String[]{RECEIVER_RESULTS}); + + BroadcastReceiver finish = new BroadcastReceiver() { + public void onReceive(Context context, Intent intent) { + gotReceive(RECEIVER_RESULTS, intent); + } + }; + + getContext().sendOrderedBroadcast( + makeBroadcastIntent(BROADCAST_LOCAL), + PERMISSION_DENIED, finish, null, Activity.RESULT_CANCELED, + null, null); + waitForResultOrThrow(BROADCAST_TIMEOUT); + } + + public void testRemoteReceivePermissionGranted() throws Exception { + setExpectedReceivers(new String[]{RECEIVER_REMOTE}); + getContext().sendBroadcast(makeBroadcastIntent(BROADCAST_REMOTE_GRANTED)); + waitForResultOrThrow(BROADCAST_TIMEOUT); + } + + public void testRemoteReceivePermissionDenied() throws Exception { + setExpectedReceivers(new String[]{RECEIVER_RESULTS}); + + BroadcastReceiver finish = new BroadcastReceiver() { + public void onReceive(Context context, Intent intent) { + gotReceive(RECEIVER_RESULTS, intent); + } + }; + + getContext().sendOrderedBroadcast( + makeBroadcastIntent(BROADCAST_REMOTE_DENIED), + null, finish, null, Activity.RESULT_CANCELED, + null, null); + waitForResultOrThrow(BROADCAST_TIMEOUT); + } + + public void testRemoteBroadcastPermissionGranted() throws Exception { + setExpectedReceivers(new String[]{RECEIVER_REMOTE}); + getContext().sendBroadcast( + makeBroadcastIntent(BROADCAST_REMOTE), + PERMISSION_GRANTED); + waitForResultOrThrow(BROADCAST_TIMEOUT); + } + + public void testRemoteBroadcastPermissionDenied() throws Exception { + setExpectedReceivers(new String[]{RECEIVER_RESULTS}); + + BroadcastReceiver finish = new BroadcastReceiver() { + public void onReceive(Context context, Intent intent) { + gotReceive(RECEIVER_RESULTS, intent); + } + }; + + getContext().sendOrderedBroadcast( + makeBroadcastIntent(BROADCAST_REMOTE), + PERMISSION_DENIED, finish, null, Activity.RESULT_CANCELED, + null, null); + waitForResultOrThrow(BROADCAST_TIMEOUT); + } + + public void testReceiverCanNotRegister() throws Exception { + setExpectedReceivers(new String[]{RECEIVER_LOCAL}); + getContext().sendBroadcast(makeBroadcastIntent(BROADCAST_FAIL_REGISTER)); + waitForResultOrThrow(BROADCAST_TIMEOUT); + } + + public void testReceiverCanNotBind() throws Exception { + setExpectedReceivers(new String[]{RECEIVER_LOCAL}); + getContext().sendBroadcast(makeBroadcastIntent(BROADCAST_FAIL_BIND)); + waitForResultOrThrow(BROADCAST_TIMEOUT); + } + + public void testLocalUnregisterTwice() throws Exception { + registerMyReceiver(new IntentFilter(BROADCAST_REGISTERED), null); + unregisterMyReceiverNoCheck(); + try { + unregisterMyReceiverNoCheck(); + fail("No exception thrown on second unregister"); + } catch (IllegalArgumentException e) { + Log.i("foo", "Unregister exception", e); + } + } +} diff --git a/tests/AndroidTests/src/com/android/unit_tests/activity/ClearTop.java b/tests/AndroidTests/src/com/android/unit_tests/activity/ClearTop.java new file mode 100644 index 0000000..dd5274a --- /dev/null +++ b/tests/AndroidTests/src/com/android/unit_tests/activity/ClearTop.java @@ -0,0 +1,51 @@ +/* + * 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.unit_tests.activity; + +import android.app.Activity; +import android.content.Intent; +import android.os.Bundle; +import android.util.Log; + +public class ClearTop extends Activity { + public static final String WAIT_CLEAR_TASK = "waitClearTask"; + + public ClearTop() { + } + + @Override + public void onCreate(Bundle icicle) { + super.onCreate(icicle); + //Log.i("foo", "Creating: " + this); + Intent intent = new Intent(getIntent()).setAction(LocalScreen.CLEAR_TASK) + .setClass(this, LocalScreen.class); + startActivity(intent); + } + + @Override + public void onNewIntent(Intent intent) { + //Log.i("foo", "New intent in " + this + ": " + intent); + if (LocalScreen.CLEAR_TASK.equals(intent.getAction())) { + setResult(RESULT_OK); + } else { + setResult(RESULT_CANCELED, new Intent().setAction( + "New intent received " + intent + ", expecting action " + + TestedScreen.CLEAR_TASK)); + } + finish(); + } +} diff --git a/tests/AndroidTests/src/com/android/unit_tests/activity/IntentSenderTest.java b/tests/AndroidTests/src/com/android/unit_tests/activity/IntentSenderTest.java new file mode 100644 index 0000000..a30c1cb --- /dev/null +++ b/tests/AndroidTests/src/com/android/unit_tests/activity/IntentSenderTest.java @@ -0,0 +1,86 @@ +/* + * 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.unit_tests.activity; + +import android.app.Activity; +import android.app.PendingIntent; +import android.content.Intent; +import android.content.IntentFilter; +import android.test.suitebuilder.annotation.Suppress; +import android.os.Bundle; +import android.test.suitebuilder.annotation.Suppress; + +public class IntentSenderTest extends BroadcastTest { + + public void testRegisteredReceivePermissionGranted() throws Exception { + setExpectedReceivers(new String[]{RECEIVER_REG}); + registerMyReceiver(new IntentFilter(BROADCAST_REGISTERED), PERMISSION_GRANTED); + addIntermediate("after-register"); + PendingIntent is = PendingIntent.getBroadcast(getContext(), 0, + makeBroadcastIntent(BROADCAST_REGISTERED), 0); + is.send(); + waitForResultOrThrow(BROADCAST_TIMEOUT); + is.cancel(); + } + + public void testRegisteredReceivePermissionDenied() throws Exception { + final Intent intent = makeBroadcastIntent(BROADCAST_REGISTERED); + + setExpectedReceivers(new String[]{RECEIVER_RESULTS}); + registerMyReceiver(new IntentFilter(BROADCAST_REGISTERED), PERMISSION_DENIED); + addIntermediate("after-register"); + + PendingIntent.OnFinished finish = new PendingIntent.OnFinished() { + public void onSendFinished(PendingIntent pi, Intent intent, + int resultCode, String resultData, Bundle resultExtras) { + gotReceive(RECEIVER_RESULTS, intent); + } + }; + + PendingIntent is = PendingIntent.getBroadcast(getContext(), 0, intent, 0); + is.send(Activity.RESULT_CANCELED, finish, null); + waitForResultOrThrow(BROADCAST_TIMEOUT); + is.cancel(); + } + + public void testLocalReceivePermissionGranted() throws Exception { + setExpectedReceivers(new String[]{RECEIVER_LOCAL}); + PendingIntent is = PendingIntent.getBroadcast(getContext(), 0, + makeBroadcastIntent(BROADCAST_LOCAL_GRANTED), 0); + is.send(); + waitForResultOrThrow(BROADCAST_TIMEOUT); + is.cancel(); + } + + public void testLocalReceivePermissionDenied() throws Exception { + final Intent intent = makeBroadcastIntent(BROADCAST_LOCAL_DENIED); + + setExpectedReceivers(new String[]{RECEIVER_RESULTS}); + + PendingIntent.OnFinished finish = new PendingIntent.OnFinished() { + public void onSendFinished(PendingIntent pi, Intent intent, + int resultCode, String resultData, Bundle resultExtras) { + gotReceive(RECEIVER_RESULTS, intent); + } + }; + + PendingIntent is = PendingIntent.getBroadcast(getContext(), 0, intent, 0); + is.send(Activity.RESULT_CANCELED, finish, null); + waitForResultOrThrow(BROADCAST_TIMEOUT); + is.cancel(); + } +} diff --git a/tests/AndroidTests/src/com/android/unit_tests/activity/LaunchTest.java b/tests/AndroidTests/src/com/android/unit_tests/activity/LaunchTest.java new file mode 100644 index 0000000..12b1b5d --- /dev/null +++ b/tests/AndroidTests/src/com/android/unit_tests/activity/LaunchTest.java @@ -0,0 +1,75 @@ +/* + * 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.unit_tests.activity; + +import android.content.ComponentName; +import android.test.suitebuilder.annotation.LargeTest; + +public class LaunchTest extends ActivityTestsBase { + + @LargeTest + public void testColdActivity() throws Exception { + mIntent.putExtra("component", new ComponentName(getContext(), TestedActivity.class)); + runLaunchpad(LaunchpadActivity.LAUNCH); + } + + @LargeTest + public void testLocalActivity() throws Exception { + mIntent.putExtra("component", new ComponentName(getContext(), LocalActivity.class)); + runLaunchpad(LaunchpadActivity.LAUNCH); + } + + @LargeTest + public void testColdScreen() throws Exception { + mIntent.putExtra("component", new ComponentName(getContext(), TestedScreen.class)); + runLaunchpad(LaunchpadActivity.LAUNCH); + } + + @LargeTest + public void testLocalScreen() throws Exception { + mIntent.putExtra("component", new ComponentName(getContext(), LocalScreen.class)); + runLaunchpad(LaunchpadActivity.LAUNCH); + } + + @LargeTest + public void testForwardResult() throws Exception { + runLaunchpad(LaunchpadActivity.FORWARD_RESULT); + } + + // The following is disabled until we can catch and recover from + // application errors. + public void xxtestBadParcelable() throws Exception { + // All we really care about for this test is that the system + // doesn't crash. + runLaunchpad(LaunchpadActivity.BAD_PARCELABLE); + } + + @LargeTest + public void testClearTopInCreate() throws Exception { + mIntent.putExtra("component", new ComponentName(getContext(), ClearTop.class)); + runLaunchpad(LaunchpadActivity.LAUNCH); + } + + @LargeTest + public void testClearTopWhileResumed() throws Exception { + mIntent.putExtra("component", new ComponentName(getContext(), ClearTop.class)); + mIntent.putExtra(ClearTop.WAIT_CLEAR_TASK, true); + runLaunchpad(LaunchpadActivity.LAUNCH); + } +} + + diff --git a/tests/AndroidTests/src/com/android/unit_tests/activity/LaunchpadActivity.java b/tests/AndroidTests/src/com/android/unit_tests/activity/LaunchpadActivity.java new file mode 100644 index 0000000..06e7a84 --- /dev/null +++ b/tests/AndroidTests/src/com/android/unit_tests/activity/LaunchpadActivity.java @@ -0,0 +1,588 @@ +/* + * 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.unit_tests.activity; + +import android.app.Activity; +import android.content.BroadcastReceiver; +import android.content.ComponentName; +import android.content.Context; +import android.content.Intent; +import android.content.IntentFilter; +import android.os.Binder; +import android.os.Bundle; +import android.os.Handler; +import android.os.IBinder; +import android.os.Message; +import android.os.Parcel; +import android.os.Parcelable; +import android.test.PerformanceTestCase; +import android.util.Log; + +class MyBadParcelable implements Parcelable { + public MyBadParcelable() { + } + + public void writeToParcel(Parcel out, int flags) { + out.writeString("I am bad"); + } + + public int describeContents() { + return 0; + } + + public static final Parcelable.Creator<MyBadParcelable> CREATOR + = new Parcelable.Creator<MyBadParcelable>() { + public MyBadParcelable createFromParcel(Parcel in) { + return new MyBadParcelable(in); + } + + public MyBadParcelable[] newArray(int size) { + return new MyBadParcelable[size]; + } + }; + + public MyBadParcelable(Parcel in) { + String nm = in.readString(); + } +} + +public class LaunchpadActivity extends Activity { + public interface CallingTest extends PerformanceTestCase.Intermediates { + public void startTiming(boolean realTime); + public void addIntermediate(String name); + public void addIntermediate(String name, long timeInNS); + public void finishTiming(boolean realTime); + public void activityFinished(int resultCode, Intent data, + RuntimeException where); + } + + // Also used as the Binder interface descriptor string in these tests + public static final String LAUNCH = "com.android.unit_tests.activity.LAUNCH"; + + public static final String FORWARD_RESULT = + "com.android.unit_tests.activity.FORWARD_RESULT"; + public static final String RETURNED_RESULT = + "com.android.unit_tests.activity.RETURNED_RESULT"; + + public static final String BAD_PARCELABLE = + "com.android.unit_tests.activity.BAD_PARCELABLE"; + + public static final int LAUNCHED_RESULT = 1; + public static final int FORWARDED_RESULT = 2; + + public static final String LIFECYCLE_BASIC = + "com.android.unit_tests.activity.LIFECYCLE_BASIC"; + public static final String LIFECYCLE_SCREEN = + "com.android.unit_tests.activity.LIFECYCLE_SCREEN"; + public static final String LIFECYCLE_DIALOG = + "com.android.unit_tests.activity.LIFECYCLE_DIALOG"; + public static final String LIFECYCLE_FINISH_CREATE = + "com.android.unit_tests.activity.LIFECYCLE_FINISH_CREATE"; + public static final String LIFECYCLE_FINISH_START = + "com.android.unit_tests.activity.LIFECYCLE_FINISH_START"; + + public static final String BROADCAST_REGISTERED = + "com.android.unit_tests.activity.BROADCAST_REGISTERED"; + public static final String BROADCAST_LOCAL = + "com.android.unit_tests.activity.BROADCAST_LOCAL"; + public static final String BROADCAST_REMOTE = + "com.android.unit_tests.activity.BROADCAST_REMOTE"; + public static final String BROADCAST_ALL = + "com.android.unit_tests.activity.BROADCAST_ALL"; + public static final String BROADCAST_REPEAT = + "com.android.unit_tests.activity.BROADCAST_REPEAT"; + public static final String BROADCAST_MULTI = + "com.android.unit_tests.activity.BROADCAST_MULTI"; + public static final String BROADCAST_ABORT = + "com.android.unit_tests.activity.BROADCAST_ABORT"; + + public static final String BROADCAST_STICKY1 = + "com.android.unit_tests.activity.BROADCAST_STICKY1"; + public static final String BROADCAST_STICKY2 = + "com.android.unit_tests.activity.BROADCAST_STICKY2"; + + public static final String RECEIVER_REG = "receiver-reg"; + public static final String RECEIVER_LOCAL = "receiver-local"; + public static final String RECEIVER_REMOTE = "receiver-remote"; + public static final String RECEIVER_ABORT = "receiver-abort"; + + public static final String DATA_1 = "one"; + public static final String DATA_2 = "two"; + + public static final String ON_START = "onStart"; + public static final String ON_RESTART = "onRestart"; + public static final String ON_RESUME = "onResume"; + public static final String ON_FREEZE = "onSaveInstanceState"; + public static final String ON_PAUSE = "onPause"; + public static final String ON_STOP = "onStop"; + public static final String ON_DESTROY = "onDestroy"; + + public static final String DO_FINISH = "finish"; + public static final String DO_LOCAL_SCREEN = "local-screen"; + public static final String DO_LOCAL_DIALOG = "local-dialog"; + + private boolean mBadParcelable = false; + + private boolean mStarted = false; + private long mStartTime; + + private int mResultCode = RESULT_CANCELED; + private Intent mData = (new Intent()).setAction("No result received"); + private RuntimeException mResultStack = null; + + private String[] mExpectedLifecycle = null; + private int mNextLifecycle; + + private String[] mExpectedReceivers = null; + private int mNextReceiver; + + private String[] mExpectedData = null; + private boolean[] mReceivedData = null; + + boolean mReceiverRegistered = false; + + private static CallingTest sCallingTest = null; + + public static void setCallingTest(CallingTest ct) { + sCallingTest = ct; + } + + public LaunchpadActivity() { + mStartTime = System.currentTimeMillis(); + } + + @Override + protected void onCreate(Bundle icicle) { + super.onCreate(icicle); + String action = getIntent().getAction(); + if (ActivityTests.DEBUG_LIFECYCLE) Log.v("test", "CREATE lauchpad " + + Integer.toHexString(System.identityHashCode(this)) + ": " + getIntent()); + if (LIFECYCLE_BASIC.equals(action)) { + setExpectedLifecycle(new String[]{ON_START, ON_RESUME, + DO_FINISH, ON_PAUSE, ON_STOP, ON_DESTROY}); + } else if (LIFECYCLE_SCREEN.equals(action)) { + setExpectedLifecycle(new String[]{ON_START, ON_RESUME, + DO_LOCAL_SCREEN, ON_FREEZE, ON_PAUSE, ON_STOP, + ON_RESTART, ON_START, ON_RESUME, + DO_FINISH, ON_PAUSE, ON_STOP, ON_DESTROY}); + } else if (LIFECYCLE_DIALOG.equals(action)) { + setExpectedLifecycle(new String[]{ON_START, ON_RESUME, + DO_LOCAL_DIALOG, ON_FREEZE, ON_PAUSE, ON_RESUME, + DO_FINISH, ON_PAUSE, ON_STOP, ON_DESTROY}); + } else if (LIFECYCLE_FINISH_CREATE.equals(action)) { + // This one behaves a little differently when running in a group. + if (getParent() == null) { + setExpectedLifecycle(new String[]{ON_DESTROY}); + } else { + setExpectedLifecycle(new String[]{ON_START, ON_STOP, ON_DESTROY}); + } + finish(); + } else if (LIFECYCLE_FINISH_START.equals(action)) { + setExpectedLifecycle(new String[]{ON_START, DO_FINISH, + ON_STOP, ON_DESTROY}); + } + } + + @Override + protected void onStart() { + super.onStart(); + if (ActivityTests.DEBUG_LIFECYCLE) Log.v("test", "START lauchpad " + + Integer.toHexString(System.identityHashCode(this)) + ": " + getIntent()); + checkLifecycle(ON_START); + } + + @Override + protected void onRestart() { + super.onStart(); + checkLifecycle(ON_RESTART); + } + + @Override + protected void onResume() { + super.onResume(); + + if (ActivityTests.DEBUG_LIFECYCLE) Log.v("test", "RESUME lauchpad " + + Integer.toHexString(System.identityHashCode(this)) + ": " + getIntent()); + checkLifecycle(ON_RESUME); + + if (!mStarted) { + mStarted = true; + + mHandler.postDelayed(mTimeout, 5 * 1000); + + String action = getIntent().getAction(); + + sCallingTest.startTiming(true); + + if (LAUNCH.equals(action)) { + Intent intent = getIntent(); + intent.setFlags(0); + intent.setComponent((ComponentName) + intent.getParcelableExtra("component")); + //System.out.println("*** Launchpad is starting: comp=" + intent.component); + startActivityForResult(intent, LAUNCHED_RESULT); + } else if (FORWARD_RESULT.equals(action)) { + Intent intent = getIntent(); + intent.setFlags(0); + intent.setClass(this, LocalScreen.class); + startActivityForResult(intent, FORWARDED_RESULT); + } else if (BAD_PARCELABLE.equals(action)) { + mBadParcelable = true; + Intent intent = getIntent(); + intent.setFlags(0); + intent.setClass(this, LocalScreen.class); + startActivityForResult(intent, LAUNCHED_RESULT); + } else if (BROADCAST_REGISTERED.equals(action)) { + setExpectedReceivers(new String[]{RECEIVER_REG}); + registerMyReceiver(new IntentFilter(BROADCAST_REGISTERED)); + sCallingTest.addIntermediate("after-register"); + sendBroadcast(makeBroadcastIntent(BROADCAST_REGISTERED)); + } else if (BROADCAST_LOCAL.equals(action)) { + setExpectedReceivers(new String[]{RECEIVER_LOCAL}); + sendBroadcast(makeBroadcastIntent(BROADCAST_LOCAL)); + } else if (BROADCAST_REMOTE.equals(action)) { + setExpectedReceivers(new String[]{RECEIVER_REMOTE}); + sendBroadcast(makeBroadcastIntent(BROADCAST_REMOTE)); + } else if (BROADCAST_ALL.equals(action)) { + setExpectedReceivers(new String[]{ + RECEIVER_REMOTE, RECEIVER_REG, RECEIVER_LOCAL}); + registerMyReceiver(new IntentFilter(BROADCAST_ALL)); + sCallingTest.addIntermediate("after-register"); + sendOrderedBroadcast(makeBroadcastIntent(BROADCAST_ALL), null); + } else if (BROADCAST_MULTI.equals(action)) { + setExpectedReceivers(new String[]{ + RECEIVER_REMOTE, RECEIVER_REG, RECEIVER_LOCAL, + RECEIVER_REMOTE, RECEIVER_REG, RECEIVER_LOCAL, + RECEIVER_REMOTE, RECEIVER_REG, RECEIVER_LOCAL, + RECEIVER_LOCAL, RECEIVER_REMOTE, + RECEIVER_LOCAL, RECEIVER_REMOTE, + RECEIVER_REMOTE, RECEIVER_REG, RECEIVER_LOCAL, + RECEIVER_REMOTE, RECEIVER_REG, RECEIVER_LOCAL, + RECEIVER_REMOTE, RECEIVER_REG, RECEIVER_LOCAL, + RECEIVER_REMOTE, RECEIVER_LOCAL, + RECEIVER_REMOTE, RECEIVER_LOCAL}); + registerMyReceiver(new IntentFilter(BROADCAST_ALL)); + sCallingTest.addIntermediate("after-register"); + sendOrderedBroadcast(makeBroadcastIntent(BROADCAST_ALL), null); + sendOrderedBroadcast(makeBroadcastIntent(BROADCAST_ALL), null); + sendOrderedBroadcast(makeBroadcastIntent(BROADCAST_ALL), null); + sendOrderedBroadcast(makeBroadcastIntent(BROADCAST_LOCAL), null); + sendOrderedBroadcast(makeBroadcastIntent(BROADCAST_REMOTE), null); + sendOrderedBroadcast(makeBroadcastIntent(BROADCAST_LOCAL), null); + sendOrderedBroadcast(makeBroadcastIntent(BROADCAST_REMOTE), null); + sendOrderedBroadcast(makeBroadcastIntent(BROADCAST_ALL), null); + sendOrderedBroadcast(makeBroadcastIntent(BROADCAST_ALL), null); + sendOrderedBroadcast(makeBroadcastIntent(BROADCAST_ALL), null); + sendOrderedBroadcast(makeBroadcastIntent(BROADCAST_REPEAT), null); + } else if (BROADCAST_ABORT.equals(action)) { + setExpectedReceivers(new String[]{ + RECEIVER_REMOTE, RECEIVER_ABORT}); + registerMyReceiver(new IntentFilter(BROADCAST_ABORT)); + sCallingTest.addIntermediate("after-register"); + sendOrderedBroadcast(makeBroadcastIntent(BROADCAST_ABORT), null); + } else if (BROADCAST_STICKY1.equals(action)) { + setExpectedReceivers(new String[]{RECEIVER_REG}); + setExpectedData(new String[]{DATA_1}); + registerMyReceiver(new IntentFilter(BROADCAST_STICKY1)); + sCallingTest.addIntermediate("after-register"); + } else if (BROADCAST_STICKY2.equals(action)) { + setExpectedReceivers(new String[]{RECEIVER_REG, RECEIVER_REG}); + setExpectedData(new String[]{DATA_1, DATA_2}); + IntentFilter filter = new IntentFilter(BROADCAST_STICKY1); + filter.addAction(BROADCAST_STICKY2); + registerMyReceiver(filter); + sCallingTest.addIntermediate("after-register"); + } + } + } + + @Override + protected void onSaveInstanceState(Bundle icicle) { + super.onSaveInstanceState(icicle); + checkLifecycle(ON_FREEZE); + if (mBadParcelable) { + icicle.putParcelable("baddy", new MyBadParcelable()); + } + } + + @Override + protected void onPause() { + super.onPause(); + if (ActivityTests.DEBUG_LIFECYCLE) Log.v("test", "PAUSE lauchpad " + + Integer.toHexString(System.identityHashCode(this)) + ": " + getIntent()); + checkLifecycle(ON_PAUSE); + } + + @Override + protected void onStop() { + super.onStop(); + if (ActivityTests.DEBUG_LIFECYCLE) Log.v("test", "STOP lauchpad " + + Integer.toHexString(System.identityHashCode(this)) + ": " + getIntent()); + checkLifecycle(ON_STOP); + } + + @Override + protected void onActivityResult(int requestCode, int resultCode, + Intent data) { + switch (requestCode) { + case LAUNCHED_RESULT: + sCallingTest.finishTiming(true); + finishWithResult(resultCode, data); + break; + case FORWARDED_RESULT: + sCallingTest.finishTiming(true); + if (RETURNED_RESULT.equals(data.getAction())) { + finishWithResult(resultCode, data); + } else { + finishWithResult(RESULT_CANCELED, (new Intent()).setAction( + "Bad data returned: " + data)); + } + break; + default: + sCallingTest.finishTiming(true); + finishWithResult(RESULT_CANCELED, (new Intent()).setAction( + "Unexpected request code: " + requestCode)); + break; + } + } + + @Override + protected void onDestroy() { + super.onDestroy(); + if (ActivityTests.DEBUG_LIFECYCLE) Log.v("test", "DESTROY lauchpad " + + Integer.toHexString(System.identityHashCode(this)) + ": " + getIntent()); + checkLifecycle(ON_DESTROY); + sCallingTest.activityFinished(mResultCode, mData, mResultStack); + } + + private void setExpectedLifecycle(String[] lifecycle) { + mExpectedLifecycle = lifecycle; + mNextLifecycle = 0; + } + + private void checkLifecycle(String where) { + if (mExpectedLifecycle == null) return; + + if (mNextLifecycle >= mExpectedLifecycle.length) { + finishBad("Activity lifecycle incorrect: received " + where + + " but don't expect any more calls"); + mExpectedLifecycle = null; + return; + } + if (!mExpectedLifecycle[mNextLifecycle].equals(where)) { + finishBad("Activity lifecycle incorrect: received " + where + + " but expected " + mExpectedLifecycle[mNextLifecycle] + + " at " + mNextLifecycle); + mExpectedLifecycle = null; + return; + } + + mNextLifecycle++; + + if (mNextLifecycle >= mExpectedLifecycle.length) { + setTestResult(RESULT_OK, null); + return; + } + + String next = mExpectedLifecycle[mNextLifecycle]; + if (where.equals(ON_DESTROY)) { + finishBad("Activity lifecycle incorrect: received " + where + + " but expected more actions (next is " + next + ")"); + mExpectedLifecycle = null; + return; + } else if (next.equals(DO_FINISH)) { + mNextLifecycle++; + if (mNextLifecycle >= mExpectedLifecycle.length) { + setTestResult(RESULT_OK, null); + } + if (!isFinishing()) { + finish(); + } + } else if (next.equals(DO_LOCAL_SCREEN)) { + mNextLifecycle++; + Intent intent = new Intent(TestedScreen.WAIT_BEFORE_FINISH); + intent.setClass(this, LocalScreen.class); + startActivity(intent); + } else if (next.equals(DO_LOCAL_DIALOG)) { + mNextLifecycle++; + Intent intent = new Intent(TestedScreen.WAIT_BEFORE_FINISH); + intent.setClass(this, LocalDialog.class); + startActivity(intent); + } + } + + private void setExpectedReceivers(String[] receivers) { + mExpectedReceivers = receivers; + mNextReceiver = 0; + } + + private void setExpectedData(String[] data) { + mExpectedData = data; + mReceivedData = new boolean[data.length]; + } + + private Intent makeBroadcastIntent(String action) { + Intent intent = new Intent(action, null); + intent.putExtra("caller", mCallTarget); + return intent; + } + + private void finishGood() { + finishWithResult(RESULT_OK, null); + } + + private void finishBad(String error) { + finishWithResult(RESULT_CANCELED, (new Intent()).setAction(error)); + } + + private void finishWithResult(int resultCode, Intent data) { + setTestResult(resultCode, data); + finish(); + } + + private void setTestResult(int resultCode, Intent data) { + mHandler.removeCallbacks(mTimeout); + unregisterMyReceiver(); + mResultCode = resultCode; + mData = data; + mResultStack = new RuntimeException("Original error was here"); + mResultStack.fillInStackTrace(); + } + + private void registerMyReceiver(IntentFilter filter) { + mReceiverRegistered = true; + //System.out.println("Registering: " + mReceiver); + registerReceiver(mReceiver, filter); + } + + private void unregisterMyReceiver() { + if (mReceiverRegistered) { + mReceiverRegistered = false; + //System.out.println("Unregistering: " + mReceiver); + unregisterReceiver(mReceiver); + } + } + + private Handler mHandler = new Handler() { + public void handleMessage(Message msg) { + } + }; + + static final int GOT_RECEIVE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION; + static final int ERROR_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION + 1; + + private Binder mCallTarget = new Binder() { + public boolean onTransact(int code, Parcel data, Parcel reply, int flags) { + data.setDataPosition(0); + data.enforceInterface(LaunchpadActivity.LAUNCH); + if (code == GOT_RECEIVE_TRANSACTION) { + String name = data.readString(); + gotReceive(name, null); + return true; + } else if (code == ERROR_TRANSACTION) { + finishBad(data.readString()); + return true; + } + return false; + } + }; + + private final void gotReceive(String name, Intent intent) { + synchronized (this) { + + //System.out.println("Got receive: " + name); + //System.out.println(mNextReceiver + " in " + mExpectedReceivers); + //new RuntimeException("stack").printStackTrace(); + + sCallingTest.addIntermediate(mNextReceiver + "-" + name); + + if (mExpectedData != null) { + int n = mExpectedData.length; + int i; + boolean prev = false; + for (i = 0; i < n; i++) { + if (mExpectedData[i].equals(intent.getStringExtra("test"))) { + if (mReceivedData[i]) { + prev = true; + continue; + } + mReceivedData[i] = true; + break; + } + } + if (i >= n) { + if (prev) { + finishBad("Receive got data too many times: " + + intent.getStringExtra("test")); + } else { + finishBad("Receive got unexpected data: " + + intent.getStringExtra("test")); + } + return; + } + } + + if (mNextReceiver >= mExpectedReceivers.length) { + finishBad("Got too many onReceiveIntent() calls!"); +// System.out.println("Too many intents received: now at " +// + mNextReceiver + ", expect list: " +// + Arrays.toString(mExpectedReceivers)); + } else if (!mExpectedReceivers[mNextReceiver].equals(name)) { + finishBad("Receive out of order: got " + name + " but expected " + + mExpectedReceivers[mNextReceiver] + " at " + + mNextReceiver); + } else { + mNextReceiver++; + if (mNextReceiver == mExpectedReceivers.length) { + mHandler.post(mUnregister); + } + } + + } + } + + private Runnable mUnregister = new Runnable() { + public void run() { + if (mReceiverRegistered) { + sCallingTest.addIntermediate("before-unregister"); + unregisterMyReceiver(); + } + sCallingTest.finishTiming(true); + finishGood(); + } + }; + + private Runnable mTimeout = new Runnable() { + public void run() { + Log.i("foo", "**** TIMEOUT"); + String msg = "Timeout"; + if (mExpectedReceivers != null + && mNextReceiver < mExpectedReceivers.length) { + msg = msg + " waiting for " + mExpectedReceivers[mNextReceiver]; + } + finishBad(msg); + } + }; + + private BroadcastReceiver mReceiver = new BroadcastReceiver() { + public void onReceive(Context context, Intent intent) { + //System.out.println("Receive in: " + this + ": " + intent); + gotReceive(RECEIVER_REG, intent); + } + }; +} + diff --git a/tests/AndroidTests/src/com/android/unit_tests/activity/LaunchpadTabActivity.java b/tests/AndroidTests/src/com/android/unit_tests/activity/LaunchpadTabActivity.java new file mode 100644 index 0000000..1e0e4a6 --- /dev/null +++ b/tests/AndroidTests/src/com/android/unit_tests/activity/LaunchpadTabActivity.java @@ -0,0 +1,43 @@ +/* + * 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.unit_tests.activity; + +import android.app.TabActivity; +import android.content.ComponentName; +import android.content.Intent; +import android.os.Bundle; +import android.widget.TabHost; + +public class LaunchpadTabActivity extends TabActivity { + public LaunchpadTabActivity() { + } + + @Override + public void onCreate(Bundle icicle) { + super.onCreate(icicle); + + Intent tabIntent = new Intent(getIntent()); + tabIntent.setComponent((ComponentName)tabIntent.getParcelableExtra("tab")); + + TabHost th = getTabHost(); + TabHost.TabSpec ts = th.newTabSpec("1"); + ts.setIndicator("One"); + ts.setContent(tabIntent); + th.addTab(ts); + } +} + diff --git a/tests/AndroidTests/src/com/android/unit_tests/activity/LifecycleTest.java b/tests/AndroidTests/src/com/android/unit_tests/activity/LifecycleTest.java new file mode 100644 index 0000000..fdc12ce --- /dev/null +++ b/tests/AndroidTests/src/com/android/unit_tests/activity/LifecycleTest.java @@ -0,0 +1,108 @@ +/* + * 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.unit_tests.activity; + +import android.content.ComponentName; +import android.content.Intent; +import android.test.FlakyTest; +import android.test.suitebuilder.annotation.LargeTest; +import android.test.suitebuilder.annotation.MediumTest; +import android.test.suitebuilder.annotation.SmallTest; +import android.test.suitebuilder.annotation.Suppress; + +public class LifecycleTest extends ActivityTestsBase { + private Intent mTopIntent; + private Intent mTabIntent; + + @Override + protected void setUp() throws Exception { + super.setUp(); + mTopIntent = mIntent; + mTabIntent = new Intent(mContext, LaunchpadTabActivity.class); + mTabIntent.putExtra("tab", new ComponentName(mContext, + LaunchpadActivity.class)); + } + + @LargeTest + public void testBasic() throws Exception { + mIntent = mTopIntent; + runLaunchpad(LaunchpadActivity.LIFECYCLE_BASIC); + } + + //Suppressing until 1285425 is fixed. + @Suppress + public void testTabBasic() throws Exception { + mIntent = mTabIntent; + runLaunchpad(LaunchpadActivity.LIFECYCLE_BASIC); + } + + //Marking flaky until bug 1164344 is fixed. + @FlakyTest(tolerance=2) + @LargeTest + public void testScreen() throws Exception { + mIntent = mTopIntent; + runLaunchpad(LaunchpadActivity.LIFECYCLE_SCREEN); + } + + //Marking flaky until bug 1164344 is fixed. + //@FlakyTest(tolerance=2) + //Suppressing until 1285425 is fixed. + @Suppress + public void testTabScreen() throws Exception { + mIntent = mTabIntent; + runLaunchpad(LaunchpadActivity.LIFECYCLE_SCREEN); + } + + @LargeTest + public void testDialog() throws Exception { + mIntent = mTopIntent; + runLaunchpad(LaunchpadActivity.LIFECYCLE_DIALOG); + } + + //Suppressing until 1285425 is fixed. + @Suppress + public void testTabDialog() throws Exception { + mIntent = mTabIntent; + runLaunchpad(LaunchpadActivity.LIFECYCLE_DIALOG); + } + + @MediumTest + public void testFinishCreate() throws Exception { + mIntent = mTopIntent; + runLaunchpad(LaunchpadActivity.LIFECYCLE_FINISH_CREATE); + } + + //Suppressing until 1285425 is fixed. + @Suppress + public void testTabFinishCreate() throws Exception { + mIntent = mTabIntent; + runLaunchpad(LaunchpadActivity.LIFECYCLE_FINISH_CREATE); + } + + @MediumTest + public void testFinishStart() throws Exception { + mIntent = mTopIntent; + runLaunchpad(LaunchpadActivity.LIFECYCLE_FINISH_START); + } + + //Suppressing until 1285425 is fixed. + @Suppress + public void testTabFinishStart() throws Exception { + mIntent = mTabIntent; + runLaunchpad(LaunchpadActivity.LIFECYCLE_FINISH_START); + } +} diff --git a/tests/AndroidTests/src/com/android/unit_tests/activity/LocalActivity.java b/tests/AndroidTests/src/com/android/unit_tests/activity/LocalActivity.java new file mode 100644 index 0000000..3c107be --- /dev/null +++ b/tests/AndroidTests/src/com/android/unit_tests/activity/LocalActivity.java @@ -0,0 +1,33 @@ +/* + * 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.unit_tests.activity; + +import java.util.Map; + +import android.app.Activity; +import android.os.Handler; +import android.os.Looper; +import android.os.Message; +import android.os.MessageQueue; + +public class LocalActivity extends TestedActivity +{ + public LocalActivity() + { + } +} + diff --git a/tests/AndroidTests/src/com/android/unit_tests/activity/LocalDeniedReceiver.java b/tests/AndroidTests/src/com/android/unit_tests/activity/LocalDeniedReceiver.java new file mode 100644 index 0000000..ac235c0 --- /dev/null +++ b/tests/AndroidTests/src/com/android/unit_tests/activity/LocalDeniedReceiver.java @@ -0,0 +1,42 @@ +/* + * 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.unit_tests.activity; + +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; +import android.os.RemoteException; +import android.os.IBinder; +import android.os.Parcel; + +class LocalDeniedReceiver extends BroadcastReceiver { + public LocalDeniedReceiver() { + } + + public void onReceive(Context context, Intent intent) { + try { + IBinder caller = intent.getIBinderExtra("caller"); + Parcel data = Parcel.obtain(); + data.writeInterfaceToken(LaunchpadActivity.LAUNCH); + data.writeString(BroadcastTest.RECEIVER_LOCAL); + caller.transact(BroadcastTest.GOT_RECEIVE_TRANSACTION, data, null, 0); + data.recycle(); + } catch (RemoteException ex) { + } + } +} + diff --git a/tests/AndroidTests/src/com/android/unit_tests/activity/LocalDeniedService.java b/tests/AndroidTests/src/com/android/unit_tests/activity/LocalDeniedService.java new file mode 100644 index 0000000..0473ea9 --- /dev/null +++ b/tests/AndroidTests/src/com/android/unit_tests/activity/LocalDeniedService.java @@ -0,0 +1,22 @@ +/* + * 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.unit_tests.activity; + +public class LocalDeniedService extends LocalService +{ +} + diff --git a/tests/AndroidTests/src/com/android/unit_tests/activity/LocalDialog.java b/tests/AndroidTests/src/com/android/unit_tests/activity/LocalDialog.java new file mode 100644 index 0000000..3694375 --- /dev/null +++ b/tests/AndroidTests/src/com/android/unit_tests/activity/LocalDialog.java @@ -0,0 +1,33 @@ +/* + * 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.unit_tests.activity; + +import java.util.Map; + +import android.app.Activity; +import android.os.Handler; +import android.os.Looper; +import android.os.Message; +import android.os.MessageQueue; + +public class LocalDialog extends TestedScreen +{ + public LocalDialog() + { + } +} + diff --git a/tests/AndroidTests/src/com/android/unit_tests/activity/LocalGrantedReceiver.java b/tests/AndroidTests/src/com/android/unit_tests/activity/LocalGrantedReceiver.java new file mode 100644 index 0000000..48f5658 --- /dev/null +++ b/tests/AndroidTests/src/com/android/unit_tests/activity/LocalGrantedReceiver.java @@ -0,0 +1,42 @@ +/* + * 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.unit_tests.activity; + +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; +import android.os.RemoteException; +import android.os.IBinder; +import android.os.Parcel; + +public class LocalGrantedReceiver extends BroadcastReceiver { + public LocalGrantedReceiver() { + } + + public void onReceive(Context context, Intent intent) { + try { + IBinder caller = intent.getIBinderExtra("caller"); + Parcel data = Parcel.obtain(); + data.writeInterfaceToken(LaunchpadActivity.LAUNCH); + data.writeString(BroadcastTest.RECEIVER_LOCAL); + caller.transact(BroadcastTest.GOT_RECEIVE_TRANSACTION, data, null, 0); + data.recycle(); + } catch (RemoteException ex) { + } + } +} + diff --git a/tests/AndroidTests/src/com/android/unit_tests/activity/LocalGrantedService.java b/tests/AndroidTests/src/com/android/unit_tests/activity/LocalGrantedService.java new file mode 100644 index 0000000..0dbcd00 --- /dev/null +++ b/tests/AndroidTests/src/com/android/unit_tests/activity/LocalGrantedService.java @@ -0,0 +1,22 @@ +/* + * 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.unit_tests.activity; + +public class LocalGrantedService extends LocalService +{ +} + diff --git a/tests/AndroidTests/src/com/android/unit_tests/activity/LocalProvider.java b/tests/AndroidTests/src/com/android/unit_tests/activity/LocalProvider.java new file mode 100644 index 0000000..a3375bd --- /dev/null +++ b/tests/AndroidTests/src/com/android/unit_tests/activity/LocalProvider.java @@ -0,0 +1,163 @@ +/* + * 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.unit_tests.activity; + +import android.content.UriMatcher; +import android.content.*; +import android.database.Cursor; +import android.database.sqlite.SQLiteDatabase; +import android.database.sqlite.SQLiteOpenHelper; +import android.database.sqlite.SQLiteQueryBuilder; +import android.net.Uri; +import android.util.Config; +import android.util.Log; + +/** Simple test provider that runs in the local process. */ +public class LocalProvider extends ContentProvider { + private static final String TAG = "LocalProvider"; + + private SQLiteOpenHelper mOpenHelper; + + private static final int DATA = 1; + private static final int DATA_ID = 2; + private static final UriMatcher sURLMatcher = new UriMatcher( + UriMatcher.NO_MATCH); + + static { + sURLMatcher.addURI("*", "data", DATA); + sURLMatcher.addURI("*", "data/#", DATA_ID); + } + + private static class DatabaseHelper extends SQLiteOpenHelper { + private static final String DATABASE_NAME = "local.db"; + private static final int DATABASE_VERSION = 1; + + public DatabaseHelper(Context context) { + super(context, DATABASE_NAME, null, DATABASE_VERSION); + } + + @Override + public void onCreate(SQLiteDatabase db) { + db.execSQL("CREATE TABLE data (" + + "_id INTEGER PRIMARY KEY," + + "text TEXT, " + + "integer INTEGER);"); + + // insert alarms + db.execSQL("INSERT INTO data (text, integer) VALUES ('first data', 100);"); + } + + @Override + public void onUpgrade(SQLiteDatabase db, int oldVersion, int currentVersion) { + Log.w(TAG, "Upgrading test database from version " + + oldVersion + " to " + currentVersion + + ", which will destroy all old data"); + db.execSQL("DROP TABLE IF EXISTS data"); + onCreate(db); + } + } + + + public LocalProvider() { + } + + @Override + public boolean onCreate() { + mOpenHelper = new DatabaseHelper(getContext()); + return true; + } + + @Override + public Cursor query(Uri url, String[] projectionIn, String selection, + String[] selectionArgs, String sort) { + SQLiteQueryBuilder qb = new SQLiteQueryBuilder(); + + // Generate the body of the query + int match = sURLMatcher.match(url); + switch (match) { + case DATA: + qb.setTables("data"); + break; + case DATA_ID: + qb.setTables("data"); + qb.appendWhere("_id="); + qb.appendWhere(url.getPathSegments().get(1)); + break; + default: + throw new IllegalArgumentException("Unknown URL " + url); + } + + SQLiteDatabase db = mOpenHelper.getReadableDatabase(); + Cursor ret = qb.query(db, projectionIn, selection, selectionArgs, + null, null, sort); + + if (ret == null) { + if (Config.LOGD) Log.d(TAG, "Alarms.query: failed"); + } else { + ret.setNotificationUri(getContext().getContentResolver(), url); + } + + return ret; + } + + @Override + public String getType(Uri url) { + int match = sURLMatcher.match(url); + switch (match) { + case DATA: + return "vnd.android.cursor.dir/vnd.google.unit_tests.local"; + case DATA_ID: + return "vnd.android.cursor.item/vnd.google.unit_tests.local"; + default: + throw new IllegalArgumentException("Unknown URL"); + } + } + + @Override + public int update(Uri url, ContentValues values, String where, String[] whereArgs) { + int count; + long rowId = 0; + int match = sURLMatcher.match(url); + SQLiteDatabase db = mOpenHelper.getWritableDatabase(); + switch (match) { + case DATA_ID: { + String segment = url.getPathSegments().get(1); + rowId = Long.parseLong(segment); + count = db.update("data", values, "_id=" + rowId, null); + break; + } + default: { + throw new UnsupportedOperationException( + "Cannot update URL: " + url); + } + } + if (Config.LOGD) Log.d(TAG, "*** notifyChange() rowId: " + rowId); + getContext().getContentResolver().notifyChange(url, null); + return count; + } + + + @Override + public Uri insert(Uri url, ContentValues initialValues) { + return null; + } + + @Override + public int delete(Uri url, String where, String[] whereArgs) { + throw new UnsupportedOperationException("delete not supported"); + } +} diff --git a/tests/AndroidTests/src/com/android/unit_tests/activity/LocalReceiver.java b/tests/AndroidTests/src/com/android/unit_tests/activity/LocalReceiver.java new file mode 100644 index 0000000..019c5c0 --- /dev/null +++ b/tests/AndroidTests/src/com/android/unit_tests/activity/LocalReceiver.java @@ -0,0 +1,77 @@ +/* + * 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.unit_tests.activity; + +import android.content.BroadcastReceiver; +import android.content.ComponentName; +import android.content.Context; +import android.content.Intent; +import android.content.IntentFilter; +import android.content.ReceiverCallNotAllowedException; +import android.content.ServiceConnection; +import android.os.RemoteException; +import android.os.IBinder; +import android.os.Parcel; + +public class LocalReceiver extends BroadcastReceiver { + public LocalReceiver() { + } + + public void onReceive(Context context, Intent intent) { + String resultString = LaunchpadActivity.RECEIVER_LOCAL; + if (BroadcastTest.BROADCAST_FAIL_REGISTER.equals(intent.getAction())) { + resultString = "Successfully registered, but expected it to fail"; + try { + context.registerReceiver(this, new IntentFilter("foo.bar")); + context.unregisterReceiver(this); + } catch (ReceiverCallNotAllowedException e) { + //resultString = "This is the correct behavior but not yet implemented"; + resultString = LaunchpadActivity.RECEIVER_LOCAL; + } + } else if (BroadcastTest.BROADCAST_FAIL_BIND.equals(intent.getAction())) { + resultString = "Successfully bound to service, but expected it to fail"; + try { + ServiceConnection sc = new ServiceConnection() { + public void onServiceConnected(ComponentName name, IBinder service) { + } + + public void onServiceDisconnected(ComponentName name) { + } + }; + context.bindService(new Intent(context, LocalService.class), sc, 0); + context.unbindService(sc); + } catch (ReceiverCallNotAllowedException e) { + //resultString = "This is the correct behavior but not yet implemented"; + resultString = LaunchpadActivity.RECEIVER_LOCAL; + } + } else if (LaunchpadActivity.BROADCAST_REPEAT.equals(intent.getAction())) { + Intent newIntent = new Intent(intent); + newIntent.setAction(LaunchpadActivity.BROADCAST_LOCAL); + context.sendOrderedBroadcast(newIntent, null); + } + try { + IBinder caller = intent.getIBinderExtra("caller"); + Parcel data = Parcel.obtain(); + data.writeInterfaceToken(LaunchpadActivity.LAUNCH); + data.writeString(resultString); + caller.transact(LaunchpadActivity.GOT_RECEIVE_TRANSACTION, data, null, 0); + data.recycle(); + } catch (RemoteException ex) { + } + } +} + diff --git a/tests/AndroidTests/src/com/android/unit_tests/activity/LocalScreen.java b/tests/AndroidTests/src/com/android/unit_tests/activity/LocalScreen.java new file mode 100644 index 0000000..ad65fcc --- /dev/null +++ b/tests/AndroidTests/src/com/android/unit_tests/activity/LocalScreen.java @@ -0,0 +1,33 @@ +/* + * 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.unit_tests.activity; + +import java.util.Map; + +import android.app.Activity; +import android.os.Handler; +import android.os.Looper; +import android.os.Message; +import android.os.MessageQueue; + +public class LocalScreen extends TestedScreen +{ + public LocalScreen() + { + } +} + diff --git a/tests/AndroidTests/src/com/android/unit_tests/activity/LocalService.java b/tests/AndroidTests/src/com/android/unit_tests/activity/LocalService.java new file mode 100644 index 0000000..d79205d --- /dev/null +++ b/tests/AndroidTests/src/com/android/unit_tests/activity/LocalService.java @@ -0,0 +1,122 @@ +/* + * 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.unit_tests.activity; + +import android.app.Service; +import android.content.Intent; +import android.os.Binder; +import android.os.Bundle; +import android.os.RemoteException; +import android.os.IBinder; +import android.os.Parcel; +import android.util.Log; + +public class LocalService extends Service { + private final IBinder mBinder = new Binder() { + + @Override + protected boolean onTransact(int code, Parcel data, Parcel reply, + int flags) throws RemoteException { + if (code == ServiceTest.SET_REPORTER_CODE) { + data.enforceInterface(ServiceTest.SERVICE_LOCAL); + mReportObject = data.readStrongBinder(); + return true; + } else { + return super.onTransact(code, data, reply, flags); + } + } + + }; + + private IBinder mReportObject; + private int mStartCount = 1; + + public LocalService() { + } + + @Override + public void onStart(Intent intent, int startId) { + //Log.i("LocalService", "onStart: " + intent); + if (intent.getExtras() != null) { + mReportObject = intent.getExtras().getIBinder(ServiceTest.REPORT_OBJ_NAME); + if (mReportObject != null) { + try { + Parcel data = Parcel.obtain(); + data.writeInterfaceToken(ServiceTest.SERVICE_LOCAL); + data.writeInt(mStartCount); + mStartCount++; + mReportObject.transact( + ServiceTest.STARTED_CODE, data, null, 0); + data.recycle(); + } catch (RemoteException e) { + } + } + } + } + + @Override + public void onDestroy() { + Log.i("LocalService", "onDestroy: mReportObject=" + mReportObject); + if (mReportObject != null) { + try { + Parcel data = Parcel.obtain(); + data.writeInterfaceToken(ServiceTest.SERVICE_LOCAL); + mReportObject.transact( + ServiceTest.DESTROYED_CODE, data, null, 0); + data.recycle(); + } catch (RemoteException e) { + } + } + } + + @Override + public IBinder onBind(Intent intent) { + Log.i("LocalService", "onBind: " + intent); + return mBinder; + } + + @Override + public boolean onUnbind(Intent intent) { + Log.i("LocalService", "onUnbind: " + intent); + if (mReportObject != null) { + try { + Parcel data = Parcel.obtain(); + data.writeInterfaceToken(ServiceTest.SERVICE_LOCAL); + mReportObject.transact( + ServiceTest.UNBIND_CODE, data, null, 0); + data.recycle(); + } catch (RemoteException e) { + } + } + return true; + } + + @Override + public void onRebind(Intent intent) { + Log.i("LocalService", "onUnbind: " + intent); + if (mReportObject != null) { + try { + Parcel data = Parcel.obtain(); + data.writeInterfaceToken(ServiceTest.SERVICE_LOCAL); + mReportObject.transact( + ServiceTest.REBIND_CODE, data, null, 0); + data.recycle(); + } catch (RemoteException e) { + } + } + } +} diff --git a/tests/AndroidTests/src/com/android/unit_tests/activity/MetaDataTest.java b/tests/AndroidTests/src/com/android/unit_tests/activity/MetaDataTest.java new file mode 100644 index 0000000..4660e29 --- /dev/null +++ b/tests/AndroidTests/src/com/android/unit_tests/activity/MetaDataTest.java @@ -0,0 +1,166 @@ +/* + * 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.unit_tests.activity; + +import android.content.ComponentName; +import android.content.pm.ActivityInfo; +import android.content.pm.PackageItemInfo; +import android.content.pm.PackageManager; +import android.content.pm.PermissionInfo; +import android.content.pm.ProviderInfo; +import android.content.pm.ServiceInfo; +import android.content.res.TypedArray; +import android.content.res.XmlResourceParser; +import android.os.Bundle; +import android.test.AndroidTestCase; +import android.test.suitebuilder.annotation.MediumTest; +import android.test.suitebuilder.annotation.SmallTest; +import com.android.unit_tests.R; +import org.xmlpull.v1.XmlPullParser; +import org.xmlpull.v1.XmlPullParserException; + +import java.io.IOException; + +/** + * Tests for meta-data associated with application components. + */ +public class MetaDataTest extends AndroidTestCase { + + private void checkMetaData(ComponentName cn, PackageItemInfo ci) + throws IOException, XmlPullParserException { + assertNotNull("Unable to find component " + cn, ci); + + Bundle md = ci.metaData; + assertNotNull("No meta data found", md); + + assertEquals("foo", md.getString("com.android.unit_tests.string")); + assertTrue(md.getBoolean("com.android.unit_tests.boolean")); + assertEquals(100, md.getInt("com.android.unit_tests.integer")); + assertEquals(0xff000000, md.getInt("com.android.unit_tests.color")); + + assertEquals((double) 1001, + Math.floor(md.getFloat("com.android.unit_tests.float") * 10 + .5)); + + assertEquals(R.xml.metadata, md.getInt("com.android.unit_tests.reference")); + + XmlResourceParser xml = ci.loadXmlMetaData(mContext.getPackageManager(), + "com.android.unit_tests.reference"); + assertNotNull(xml); + + int type; + while ((type = xml.next()) != XmlPullParser.START_TAG + && type != XmlPullParser.END_DOCUMENT) { + } + assertEquals(XmlPullParser.START_TAG, type); + assertEquals("thedata", xml.getName()); + + // method 1: direct access + final String rawAttr = xml.getAttributeValue(null, "rawText"); + assertEquals("some raw text", rawAttr); + + // method 2: direct access of typed value + final int rawColorIntAttr = xml.getAttributeIntValue(null, "rawColor", 0); + assertEquals(0xffffff00, rawColorIntAttr); + final String rawColorStrAttr = xml.getAttributeValue(null, "rawColor"); + assertEquals("#ffffff00", rawColorStrAttr); + + // method 2: direct access of resource attribute + final String nameSpace = "http://schemas.android.com/apk/res/android"; + final int colorIntAttr = xml.getAttributeIntValue(nameSpace, "color", 0); + assertEquals(0xffff0000, colorIntAttr); + final String colorStrAttr = xml.getAttributeValue(nameSpace, "color"); + assertEquals("#ffff0000", colorStrAttr); + + // method 3: styled access (borrowing an attr from view system here) + TypedArray a = mContext.obtainStyledAttributes(xml, + android.R.styleable.TextView); + String styledAttr = a.getString(android.R.styleable.TextView_text); + assertEquals("text", styledAttr); + a.recycle(); + + xml.close(); + } + + @SmallTest + public void testActivityWithData() throws Exception { + ComponentName cn = new ComponentName(mContext, LocalActivity.class); + ActivityInfo ai = mContext.getPackageManager().getActivityInfo( + cn, PackageManager.GET_META_DATA); + + checkMetaData(cn, ai); + + ai = mContext.getPackageManager().getActivityInfo(cn, 0); + + assertNull("Meta data returned when not requested", ai.metaData); + } + + @SmallTest + public void testReceiverWithData() throws Exception { + ComponentName cn = new ComponentName(mContext, LocalReceiver.class); + ActivityInfo ai = mContext.getPackageManager().getReceiverInfo( + cn, PackageManager.GET_META_DATA); + + checkMetaData(cn, ai); + + ai = mContext.getPackageManager().getReceiverInfo(cn, 0); + + assertNull("Meta data returned when not requested", ai.metaData); + } + + @SmallTest + public void testServiceWithData() throws Exception { + ComponentName cn = new ComponentName(mContext, LocalService.class); + ServiceInfo si = mContext.getPackageManager().getServiceInfo( + cn, PackageManager.GET_META_DATA); + + checkMetaData(cn, si); + + si = mContext.getPackageManager().getServiceInfo(cn, 0); + + assertNull("Meta data returned when not requested", si.metaData); + } + + @MediumTest + public void testProviderWithData() throws Exception { + ComponentName cn = new ComponentName(mContext, LocalProvider.class); + ProviderInfo pi = mContext.getPackageManager().resolveContentProvider( + "com.android.unit_tests.LocalProvider", + PackageManager.GET_META_DATA); + checkMetaData(cn, pi); + + pi = mContext.getPackageManager().resolveContentProvider( + "com.android.unit_tests.LocalProvider", 0); + + assertNull("Meta data returned when not requested", pi.metaData); + } + + @SmallTest + public void testPermissionWithData() throws Exception { + ComponentName cn = new ComponentName("foo", + "com.android.unit_tests.permission.TEST_GRANTED"); + PermissionInfo pi = mContext.getPackageManager().getPermissionInfo( + cn.getClassName(), PackageManager.GET_META_DATA); + checkMetaData(cn, pi); + + pi = mContext.getPackageManager().getPermissionInfo( + cn.getClassName(), 0); + + assertNull("Meta data returned when not requested", pi.metaData); + } +} + + diff --git a/tests/AndroidTests/src/com/android/unit_tests/activity/RemoteDeniedReceiver.java b/tests/AndroidTests/src/com/android/unit_tests/activity/RemoteDeniedReceiver.java new file mode 100644 index 0000000..7656580 --- /dev/null +++ b/tests/AndroidTests/src/com/android/unit_tests/activity/RemoteDeniedReceiver.java @@ -0,0 +1,42 @@ +/* + * 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.unit_tests.activity; + +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; +import android.os.RemoteException; +import android.os.IBinder; +import android.os.Parcel; + +class RemoteDeniedReceiver extends BroadcastReceiver { + public RemoteDeniedReceiver() { + } + + public void onReceive(Context context, Intent intent) { + try { + IBinder caller = intent.getIBinderExtra("caller"); + Parcel data = Parcel.obtain(); + data.writeInterfaceToken(LaunchpadActivity.LAUNCH); + data.writeString(BroadcastTest.RECEIVER_REMOTE); + caller.transact(BroadcastTest.GOT_RECEIVE_TRANSACTION, data, null, 0); + data.recycle(); + } catch (RemoteException ex) { + } + } +} + diff --git a/tests/AndroidTests/src/com/android/unit_tests/activity/RemoteGrantedReceiver.java b/tests/AndroidTests/src/com/android/unit_tests/activity/RemoteGrantedReceiver.java new file mode 100644 index 0000000..034aa1d --- /dev/null +++ b/tests/AndroidTests/src/com/android/unit_tests/activity/RemoteGrantedReceiver.java @@ -0,0 +1,42 @@ +/* + * 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.unit_tests.activity; + +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; +import android.os.RemoteException; +import android.os.IBinder; +import android.os.Parcel; + +public class RemoteGrantedReceiver extends BroadcastReceiver { + public RemoteGrantedReceiver() { + } + + public void onReceive(Context context, Intent intent) { + try { + IBinder caller = intent.getIBinderExtra("caller"); + Parcel data = Parcel.obtain(); + data.writeInterfaceToken(LaunchpadActivity.LAUNCH); + data.writeString(BroadcastTest.RECEIVER_REMOTE); + caller.transact(BroadcastTest.GOT_RECEIVE_TRANSACTION, data, null, 0); + data.recycle(); + } catch (RemoteException ex) { + } + } +} + diff --git a/tests/AndroidTests/src/com/android/unit_tests/activity/RemoteReceiver.java b/tests/AndroidTests/src/com/android/unit_tests/activity/RemoteReceiver.java new file mode 100644 index 0000000..818bffe --- /dev/null +++ b/tests/AndroidTests/src/com/android/unit_tests/activity/RemoteReceiver.java @@ -0,0 +1,50 @@ +/* + * 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.unit_tests.activity; + +import android.content.Context; +import android.content.Intent; +import android.content.BroadcastReceiver; +import android.os.RemoteException; +import android.os.IBinder; +import android.os.Parcel; + +public class RemoteReceiver extends BroadcastReceiver +{ + public RemoteReceiver() + { + } + + public void onReceive(Context context, Intent intent) + { + if (LaunchpadActivity.BROADCAST_REPEAT.equals(intent.getAction())) { + Intent newIntent = new Intent(intent); + newIntent.setAction(LaunchpadActivity.BROADCAST_REMOTE); + context.sendOrderedBroadcast(newIntent, null); + } + try { + IBinder caller = intent.getIBinderExtra("caller"); + Parcel data = Parcel.obtain(); + data.writeInterfaceToken(LaunchpadActivity.LAUNCH); + data.writeString(LaunchpadActivity.RECEIVER_REMOTE); + caller.transact(LaunchpadActivity.GOT_RECEIVE_TRANSACTION, data, null, 0); + data.recycle(); + } catch (RemoteException ex) { + } + } +} + diff --git a/tests/AndroidTests/src/com/android/unit_tests/activity/RemoteSubActivityScreen.java b/tests/AndroidTests/src/com/android/unit_tests/activity/RemoteSubActivityScreen.java new file mode 100644 index 0000000..e750ed6 --- /dev/null +++ b/tests/AndroidTests/src/com/android/unit_tests/activity/RemoteSubActivityScreen.java @@ -0,0 +1,59 @@ +/* //device/apps/AndroidTests/src/com.android.unit_tests/activity/TestedScreen.java +** +** 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. +*/ + +package com.android.unit_tests.activity; + +import android.content.Intent; +import android.os.Bundle; +import android.os.Handler; +import android.os.Process; +import android.util.Log; + +public class RemoteSubActivityScreen extends SubActivityScreen { + Handler mHandler = new Handler(); + boolean mFirst = false; + + public RemoteSubActivityScreen() { + } + + @Override + public void onCreate(Bundle icicle) { + // We are running in a remote process, so want to have the sub-activity + // sending the result back in the original process. + Intent intent = getIntent(); + intent.setClass(this, SubActivityScreen.class); + + super.onCreate(icicle); + + boolean kill = intent.getBooleanExtra("kill", false); + //Log.i("foo", "RemoteSubActivityScreen pid=" + Process.myPid() + // + " kill=" + kill); + + if (kill) { + // After finishing initialization, kill the process! But only if + // this is the first time... + if (icicle == null) { + mHandler.post(new Runnable() { + public void run() { + handleBeforeStopping(); + Process.killProcess(Process.myPid()); + } + }); + } + } + } +} diff --git a/tests/AndroidTests/src/com/android/unit_tests/activity/ResultReceiver.java b/tests/AndroidTests/src/com/android/unit_tests/activity/ResultReceiver.java new file mode 100644 index 0000000..4b5d468 --- /dev/null +++ b/tests/AndroidTests/src/com/android/unit_tests/activity/ResultReceiver.java @@ -0,0 +1,43 @@ +/* + * 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.unit_tests.activity; + +import android.content.Context; +import android.content.Intent; +import android.content.BroadcastReceiver; +import android.os.IBinder; +import android.os.Parcel; +import android.os.Bundle; + +import java.util.Map; + +public class ResultReceiver extends BroadcastReceiver +{ + public ResultReceiver() + { + } + + public void onReceive(Context context, Intent intent) + { + setResultCode(3); + setResultData("bar"); + Bundle map = getResultExtras(false); + map.remove("remove"); + map.putString("bar", "them"); + } +} + diff --git a/tests/AndroidTests/src/com/android/unit_tests/activity/ServiceTest.java b/tests/AndroidTests/src/com/android/unit_tests/activity/ServiceTest.java new file mode 100644 index 0000000..db523dc --- /dev/null +++ b/tests/AndroidTests/src/com/android/unit_tests/activity/ServiceTest.java @@ -0,0 +1,465 @@ +/* + * 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.unit_tests.activity; + +import android.content.ComponentName; +import android.content.Context; +import android.content.Intent; +import android.content.ServiceConnection; +import android.os.Binder; +import android.os.Bundle; +import android.os.RemoteException; +import android.os.IBinder; +import android.os.Parcel; +import android.test.suitebuilder.annotation.MediumTest; +import android.test.suitebuilder.annotation.SmallTest; +import android.util.Log; + +// These test binders purport to support an interface whose canonical +// interface name is ServiceTest.SERVICE_LOCAL +public class ServiceTest extends ActivityTestsBase { + + public static final String SERVICE_LOCAL = + "com.android.unit_tests.activity.SERVICE_LOCAL"; + public static final String SERVICE_LOCAL_GRANTED = + "com.android.unit_tests.activity.SERVICE_LOCAL_GRANTED"; + public static final String SERVICE_LOCAL_DENIED = + "com.android.unit_tests.activity.SERVICE_LOCAL_DENIED"; + + public static final String REPORT_OBJ_NAME = "report"; + + public static final int STARTED_CODE = 1; + public static final int DESTROYED_CODE = 2; + public static final int SET_REPORTER_CODE = 3; + public static final int UNBIND_CODE = 4; + public static final int REBIND_CODE = 5; + + public static final int STATE_START_1 = 0; + public static final int STATE_START_2 = 1; + public static final int STATE_UNBIND = 2; + public static final int STATE_DESTROY = 3; + public static final int STATE_REBIND = 4; + public static final int STATE_UNBIND_ONLY = 5; + public int mStartState; + + public IBinder mStartReceiver = new Binder() { + @Override + protected boolean onTransact(int code, Parcel data, Parcel reply, + int flags) throws RemoteException { + //Log.i("ServiceTest", "Received code " + code + " in state " + mStartState); + if (code == STARTED_CODE) { + data.enforceInterface(SERVICE_LOCAL); + int count = data.readInt(); + if (mStartState == STATE_START_1) { + if (count == 1) { + finishGood(); + } else { + finishBad("onStart() again on an object when it should have been the first time"); + } + } else if (mStartState == STATE_START_2) { + if (count == 2) { + finishGood(); + } else { + finishBad("onStart() the first time on an object when it should have been the second time"); + } + } else { + finishBad("onStart() was called when not expected (state="+mStartState+")"); + } + return true; + } else if (code == DESTROYED_CODE) { + data.enforceInterface(SERVICE_LOCAL); + if (mStartState == STATE_DESTROY) { + finishGood(); + } else { + finishBad("onDestroy() was called when not expected (state="+mStartState+")"); + } + return true; + } else if (code == UNBIND_CODE) { + data.enforceInterface(SERVICE_LOCAL); + if (mStartState == STATE_UNBIND) { + mStartState = STATE_DESTROY; + } else if (mStartState == STATE_UNBIND_ONLY) { + finishGood(); + } else { + finishBad("onUnbind() was called when not expected (state="+mStartState+")"); + } + return true; + } else if (code == REBIND_CODE) { + data.enforceInterface(SERVICE_LOCAL); + if (mStartState == STATE_REBIND) { + finishGood(); + } else { + finishBad("onRebind() was called when not expected (state="+mStartState+")"); + } + return true; + } else { + return super.onTransact(code, data, reply, flags); + } + } + }; + + public class EmptyConnection implements ServiceConnection { + public void onServiceConnected(ComponentName name, IBinder service) { + } + + public void onServiceDisconnected(ComponentName name) { + } + } + + public class TestConnection implements ServiceConnection { + private final boolean mExpectDisconnect; + private final boolean mSetReporter; + private boolean mMonitor; + private int mCount; + + public TestConnection(boolean expectDisconnect, boolean setReporter) { + mExpectDisconnect = expectDisconnect; + mSetReporter = setReporter; + mMonitor = !setReporter; + } + + void setMonitor(boolean v) { + mMonitor = v; + } + + public void onServiceConnected(ComponentName name, IBinder service) { + if (mSetReporter) { + Parcel data = Parcel.obtain(); + data.writeInterfaceToken(SERVICE_LOCAL); + data.writeStrongBinder(mStartReceiver); + try { + service.transact(SET_REPORTER_CODE, data, null, 0); + } catch (RemoteException e) { + finishBad("DeadObjectException when sending reporting object"); + } + data.recycle(); + } + + if (mMonitor) { + mCount++; + if (mStartState == STATE_START_1) { + if (mCount == 1) { + finishGood(); + } else { + finishBad("onServiceConnected() again on an object when it should have been the first time"); + } + } else if (mStartState == STATE_START_2) { + if (mCount == 2) { + finishGood(); + } else { + finishBad("onServiceConnected() the first time on an object when it should have been the second time"); + } + } else { + finishBad("onServiceConnected() called unexpectedly"); + } + } + } + + public void onServiceDisconnected(ComponentName name) { + if (mMonitor) { + if (mStartState == STATE_DESTROY) { + if (mExpectDisconnect) { + finishGood(); + } else { + finishBad("onServiceDisconnected() when it shouldn't have been"); + } + } else { + finishBad("onServiceDisconnected() called unexpectedly"); + } + } + } + } + + void startExpectResult(Intent service) { + startExpectResult(service, new Bundle()); + } + + void startExpectResult(Intent service, Bundle bundle) { + bundle.putIBinder(REPORT_OBJ_NAME, mStartReceiver); + boolean success = false; + try { + //Log.i("foo", "STATE_START_1"); + mStartState = STATE_START_1; + getContext().startService(new Intent(service).putExtras(bundle)); + waitForResultOrThrow(5 * 1000, "service to start first time"); + //Log.i("foo", "STATE_START_2"); + mStartState = STATE_START_2; + getContext().startService(new Intent(service).putExtras(bundle)); + waitForResultOrThrow(5 * 1000, "service to start second time"); + success = true; + } finally { + if (!success) { + try { + getContext().stopService(service); + } catch (Exception e) { + // eat + } + } + } + //Log.i("foo", "STATE_DESTROY"); + mStartState = STATE_DESTROY; + getContext().stopService(service); + waitForResultOrThrow(5 * 1000, "service to be destroyed"); + } + + void startExpectNoPermission(Intent service) { + try { + getContext().startService(service); + fail("Expected security exception when starting " + service); + } catch (SecurityException e) { + // expected + } + } + + void bindExpectResult(Intent service) { + TestConnection conn = new TestConnection(true, false); + TestConnection conn2 = new TestConnection(false, false); + boolean success = false; + try { + // Expect to see the TestConnection connected. + mStartState = STATE_START_1; + getContext().bindService(service, conn, 0); + getContext().startService(service); + waitForResultOrThrow(5 * 1000, "existing connection to receive service"); + + // Expect to see the second TestConnection connected. + getContext().bindService(service, conn2, 0); + waitForResultOrThrow(5 * 1000, "new connection to receive service"); + + getContext().unbindService(conn2); + success = true; + } finally { + if (!success) { + try { + getContext().stopService(service); + getContext().unbindService(conn); + getContext().unbindService(conn2); + } catch (Exception e) { + // eat + } + } + } + + // Expect to see the TestConnection disconnected. + mStartState = STATE_DESTROY; + getContext().stopService(service); + waitForResultOrThrow(5 * 1000, "existing connection to lose service"); + + getContext().unbindService(conn); + + conn = new TestConnection(true, true); + success = false; + try { + // Expect to see the TestConnection connected. + conn.setMonitor(true); + mStartState = STATE_START_1; + getContext().bindService(service, conn, 0); + getContext().startService(service); + waitForResultOrThrow(5 * 1000, "existing connection to receive service"); + + success = true; + } finally { + if (!success) { + try { + getContext().stopService(service); + getContext().unbindService(conn); + } catch (Exception e) { + // eat + } + } + } + + // Expect to see the service unbind and then destroyed. + conn.setMonitor(false); + mStartState = STATE_UNBIND; + getContext().stopService(service); + waitForResultOrThrow(5 * 1000, "existing connection to lose service"); + + getContext().unbindService(conn); + + conn = new TestConnection(true, true); + success = false; + try { + // Expect to see the TestConnection connected. + conn.setMonitor(true); + mStartState = STATE_START_1; + getContext().bindService(service, conn, 0); + getContext().startService(service); + waitForResultOrThrow(5 * 1000, "existing connection to receive service"); + + success = true; + } finally { + if (!success) { + try { + getContext().stopService(service); + getContext().unbindService(conn); + } catch (Exception e) { + // eat + } + } + } + + // Expect to see the service unbind but not destroyed. + conn.setMonitor(false); + mStartState = STATE_UNBIND_ONLY; + getContext().unbindService(conn); + waitForResultOrThrow(5 * 1000, "existing connection to unbind service"); + + // Expect to see the service rebound. + mStartState = STATE_REBIND; + getContext().bindService(service, conn, 0); + waitForResultOrThrow(5 * 1000, "existing connection to rebind service"); + + // Expect to see the service unbind and then destroyed. + mStartState = STATE_UNBIND; + getContext().stopService(service); + waitForResultOrThrow(5 * 1000, "existing connection to lose service"); + + getContext().unbindService(conn); + } + + void bindAutoExpectResult(Intent service) { + TestConnection conn = new TestConnection(false, true); + boolean success = false; + try { + conn.setMonitor(true); + mStartState = STATE_START_1; + getContext().bindService( + service, conn, Context.BIND_AUTO_CREATE); + waitForResultOrThrow(5 * 1000, "connection to start and receive service"); + success = true; + } finally { + if (!success) { + try { + getContext().unbindService(conn); + } catch (Exception e) { + // eat + } + } + } + mStartState = STATE_UNBIND; + getContext().unbindService(conn); + waitForResultOrThrow(5 * 1000, "disconnecting from service"); + } + + void bindExpectNoPermission(Intent service) { + TestConnection conn = new TestConnection(false, false); + try { + getContext().bindService(service, conn, Context.BIND_AUTO_CREATE); + fail("Expected security exception when binding " + service); + } catch (SecurityException e) { + // expected + } finally { + getContext().unbindService(conn); + } + } + + + @MediumTest + public void testLocalStartClass() throws Exception { + startExpectResult(new Intent(getContext(), LocalService.class)); + } + + @MediumTest + public void testLocalStartAction() throws Exception { + startExpectResult(new Intent(SERVICE_LOCAL)); + } + + @MediumTest + public void testLocalBindClass() throws Exception { + bindExpectResult(new Intent(getContext(), LocalService.class)); + } + + @MediumTest + public void testLocalBindAction() throws Exception { + bindExpectResult(new Intent(SERVICE_LOCAL)); + } + + @MediumTest + public void testLocalBindAutoClass() throws Exception { + bindAutoExpectResult(new Intent(getContext(), LocalService.class)); + } + + @MediumTest + public void testLocalBindAutoAction() throws Exception { + bindAutoExpectResult(new Intent(SERVICE_LOCAL)); + } + + @MediumTest + public void testLocalStartClassPermissionGranted() throws Exception { + startExpectResult(new Intent(getContext(), LocalGrantedService.class)); + } + + @MediumTest + public void testLocalStartActionPermissionGranted() throws Exception { + startExpectResult(new Intent(SERVICE_LOCAL_GRANTED)); + } + + @MediumTest + public void testLocalBindClassPermissionGranted() throws Exception { + bindExpectResult(new Intent(getContext(), LocalGrantedService.class)); + } + + @MediumTest + public void testLocalBindActionPermissionGranted() throws Exception { + bindExpectResult(new Intent(SERVICE_LOCAL_GRANTED)); + } + + @MediumTest + public void testLocalBindAutoClassPermissionGranted() throws Exception { + bindAutoExpectResult(new Intent(getContext(), LocalGrantedService.class)); + } + + @MediumTest + public void testLocalBindAutoActionPermissionGranted() throws Exception { + bindAutoExpectResult(new Intent(SERVICE_LOCAL_GRANTED)); + } + + @MediumTest + public void testLocalStartClassPermissionDenied() throws Exception { + startExpectNoPermission(new Intent(getContext(), LocalDeniedService.class)); + } + + @MediumTest + public void testLocalStartActionPermissionDenied() throws Exception { + startExpectNoPermission(new Intent(SERVICE_LOCAL_DENIED)); + } + + @MediumTest + public void testLocalBindClassPermissionDenied() throws Exception { + bindExpectNoPermission(new Intent(getContext(), LocalDeniedService.class)); + } + + @MediumTest + public void testLocalBindActionPermissionDenied() throws Exception { + bindExpectNoPermission(new Intent(SERVICE_LOCAL_DENIED)); + } + + @MediumTest + public void testLocalUnbindTwice() throws Exception { + EmptyConnection conn = new EmptyConnection(); + getContext().bindService( + new Intent(SERVICE_LOCAL_GRANTED), conn, 0); + getContext().unbindService(conn); + try { + getContext().unbindService(conn); + fail("No exception thrown on second unbind"); + } catch (IllegalArgumentException e) { + //Log.i("foo", "Unbind exception", e); + } + } +} diff --git a/tests/AndroidTests/src/com/android/unit_tests/activity/SetTimeZonePermissionsTest.java b/tests/AndroidTests/src/com/android/unit_tests/activity/SetTimeZonePermissionsTest.java new file mode 100644 index 0000000..1fa7579 --- /dev/null +++ b/tests/AndroidTests/src/com/android/unit_tests/activity/SetTimeZonePermissionsTest.java @@ -0,0 +1,70 @@ +/* + * Copyright (C) 2008 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.unit_tests.activity; + +import android.app.AlarmManager; +import android.content.Context; +import android.test.AndroidTestCase; +import android.test.suitebuilder.annotation.LargeTest; + +import java.util.TimeZone; + +public class SetTimeZonePermissionsTest extends AndroidTestCase { + + private String[] mZones; + private String mCurrentZone; + private AlarmManager mAlarm; + + @Override + protected void setUp() throws Exception { + super.setUp(); + + mZones = TimeZone.getAvailableIDs(); + mCurrentZone = TimeZone.getDefault().getID(); + mAlarm = (AlarmManager) mContext.getSystemService(Context.ALARM_SERVICE); + } + + /** + * Verify that non-system processes cannot set the time zone. + */ + @LargeTest + public void testSetTimeZonePermissions() { + /** + * Attempt to set several predefined time zones, verifying that the system + * system default time zone has not actually changed from its prior state + * after each attempt. + */ + int max = (mZones.length > 10) ? mZones.length : 10; + assertTrue("No system-defined time zones - test invalid", max > 0); + + for (int i = 0; i < max; i++) { + String tz = mZones[i]; + try { + mAlarm.setTimeZone(tz); + } catch (SecurityException se) { + // Expected failure; no need to handle specially since we're + // about to assert that the test invariant holds: no change + // to the system time zone. + } + + String newZone = TimeZone.getDefault().getID(); + assertEquals("AlarmManager.setTimeZone() succeeded despite lack of permission", + mCurrentZone, + newZone); + } + } +} diff --git a/tests/AndroidTests/src/com/android/unit_tests/activity/SubActivityScreen.java b/tests/AndroidTests/src/com/android/unit_tests/activity/SubActivityScreen.java new file mode 100644 index 0000000..914b909 --- /dev/null +++ b/tests/AndroidTests/src/com/android/unit_tests/activity/SubActivityScreen.java @@ -0,0 +1,168 @@ +/* + * 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.unit_tests.activity; + +import android.app.Activity; +import android.app.PendingIntent; +import android.content.Intent; +import android.os.Bundle; + +public class SubActivityScreen extends Activity { + static final int NO_RESULT_MODE = 0; + static final int RESULT_MODE = 1; + static final int PENDING_RESULT_MODE = 2; + static final int FINISH_SUB_MODE = 3; + + static final int CHILD_OFFSET = 1000; + + int mMode; + + public SubActivityScreen() { + } + + @Override + public void onCreate(Bundle icicle) { + super.onCreate(icicle); + mMode = getIntent().getIntExtra("mode", mMode); + //Log.i("foo", "SubActivityScreen pid=" + Process.myPid() + // + " mode=" + mMode); + + // Move on to the next thing that will generate a result... but only + // if we are being launched for the first time. + if (icicle == null) { + if (mMode == PENDING_RESULT_MODE) { + PendingIntent apr = createPendingResult(1, null, + Intent.FILL_IN_ACTION); + Intent res = new Intent(); + res.putExtra("tkey", "tval"); + res.setAction("test"); + try { + apr.send(this, RESULT_OK, res); + } catch (PendingIntent.CanceledException e) { + } + } else if (mMode < CHILD_OFFSET) { + Intent intent = new Intent(); + intent.setClass(this, SubActivityScreen.class); + intent.putExtra("mode", CHILD_OFFSET+mMode); + //System.out.println("*** Starting from onStart: " + intent); + startActivityForResult(intent, 1); + return; + } + } + } + + @Override + protected void onRestoreInstanceState(Bundle state) { + super.onRestoreInstanceState(state); + } + + @Override + protected void onResume() { + super.onResume(); + + //Log.i("foo", "SubActivityScreen pid=" + Process.myPid() + " onResume"); + + if (mMode >= CHILD_OFFSET) { + // Wait a little bit, to give our parent time to kill itself + // if that is something it is into. + try { + Thread.sleep(500); + } catch (InterruptedException e) { + setResult(RESULT_CANCELED, (new Intent()).setAction("Interrupted!")); + finish(); + return; + } + //System.out.println("Resuming sub-activity: mode=" + mMode); + switch (mMode-CHILD_OFFSET) { + case NO_RESULT_MODE: + finish(); + break; + case RESULT_MODE: + Intent res = new Intent(); + res.putExtra("tkey", "tval"); + res.setAction("test"); + setResult(RESULT_OK, res); + finish(); + break; + case FINISH_SUB_MODE: + break; + } + } + } + + @Override + protected void onActivityResult(int requestCode, int resultCode, + Intent data) { + //Log.i("foo", "SubActivityScreen pid=" + Process.myPid() + // + " onActivityResult: req=" + requestCode + // + " res=" + resultCode); + + // Assume success. + setResult(RESULT_OK); + + if (requestCode == 1) { + switch (mMode) { + case NO_RESULT_MODE: + case FINISH_SUB_MODE: + if (resultCode != RESULT_CANCELED) { + setResult(RESULT_CANCELED, (new Intent()).setAction( + "Incorrect result code returned: " + resultCode)); + } + break; + case RESULT_MODE: + case PENDING_RESULT_MODE: + if (resultCode != RESULT_OK) { + setResult(RESULT_CANCELED, (new Intent()).setAction( + "Incorrect result code returned: " + resultCode)); + } else if (data == null) { + setResult(RESULT_CANCELED, (new Intent()).setAction( + "null data returned")); + } else if (!("test".equals(data.getAction()))) { + setResult(RESULT_CANCELED, (new Intent()).setAction( + "Incorrect action returned: " + data)); + } else if (!("tval".equals(data.getStringExtra("tkey")))) { + setResult(RESULT_CANCELED, (new Intent()).setAction( + "Incorrect extras returned: " + data.getExtras())); + } + break; + } + } else { + setResult(RESULT_CANCELED, (new Intent()).setAction( + "Incorrect request code returned: " + requestCode)); + } + + finish(); + } + + @Override + protected void onSaveInstanceState(Bundle outState) { + super.onSaveInstanceState(outState); + } + + @Override + protected void onStop() { + super.onStop(); + handleBeforeStopping(); + } + + public void handleBeforeStopping() { + if (mMode == FINISH_SUB_MODE) { + finishActivity(1); + } + } +} + diff --git a/tests/AndroidTests/src/com/android/unit_tests/activity/SubActivityTest.java b/tests/AndroidTests/src/com/android/unit_tests/activity/SubActivityTest.java new file mode 100644 index 0000000..ee02c98 --- /dev/null +++ b/tests/AndroidTests/src/com/android/unit_tests/activity/SubActivityTest.java @@ -0,0 +1,92 @@ +/* + * 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.unit_tests.activity; + +import android.test.suitebuilder.annotation.Suppress; +import android.content.ComponentName; + +@Suppress +public class SubActivityTest extends ActivityTestsBase { + + public void testPendingResult() throws Exception { + mIntent.putExtra("component", new ComponentName(getContext(), SubActivityScreen.class)); + mIntent.putExtra("mode", SubActivityScreen.PENDING_RESULT_MODE); + runLaunchpad(LaunchpadActivity.LAUNCH); + } + + public void testNoResult() throws Exception { + mIntent.putExtra("component", new ComponentName(getContext(), SubActivityScreen.class)); + mIntent.putExtra("mode", SubActivityScreen.NO_RESULT_MODE); + runLaunchpad(LaunchpadActivity.LAUNCH); + } + + public void testResult() throws Exception { + mIntent.putExtra("component", new ComponentName(getContext(), SubActivityScreen.class)); + mIntent.putExtra("mode", SubActivityScreen.RESULT_MODE); + runLaunchpad(LaunchpadActivity.LAUNCH); + } + + public void testFinishSub() throws Exception { + mIntent.putExtra("component", + new ComponentName(getContext(), RemoteSubActivityScreen.class)); + mIntent.putExtra("mode", SubActivityScreen.FINISH_SUB_MODE); + runLaunchpad(LaunchpadActivity.LAUNCH); + } + + public void testRemoteNoResult() throws Exception { + mIntent.putExtra("component", + new ComponentName(getContext(), RemoteSubActivityScreen.class)); + mIntent.putExtra("mode", SubActivityScreen.NO_RESULT_MODE); + runLaunchpad(LaunchpadActivity.LAUNCH); + } + + public void testRemoteResult() throws Exception { + mIntent.putExtra("component", + new ComponentName(getContext(), RemoteSubActivityScreen.class)); + mIntent.putExtra("mode", SubActivityScreen.RESULT_MODE); + runLaunchpad(LaunchpadActivity.LAUNCH); + } + + public void testRemoteFinishSub() throws Exception { + mIntent.putExtra("component", new ComponentName(getContext(), SubActivityScreen.class)); + mIntent.putExtra("mode", SubActivityScreen.FINISH_SUB_MODE); + runLaunchpad(LaunchpadActivity.LAUNCH); + } + + public void testRemoteRestartNoResult() throws Exception { + mIntent.putExtra("component", + new ComponentName(getContext(), RemoteSubActivityScreen.class)); + mIntent.putExtra("mode", SubActivityScreen.NO_RESULT_MODE); + mIntent.putExtra("kill", true); + runLaunchpad(LaunchpadActivity.LAUNCH); + } + + public void testRemoteRestartResult() throws Exception { + mIntent.putExtra("component", + new ComponentName(getContext(), RemoteSubActivityScreen.class)); + mIntent.putExtra("mode", SubActivityScreen.RESULT_MODE); + mIntent.putExtra("kill", true); + runLaunchpad(LaunchpadActivity.LAUNCH); + } + + public void testRemoteRestartFinishSub() throws Exception { + mIntent.putExtra("component", new ComponentName(getContext(), SubActivityScreen.class)); + mIntent.putExtra("mode", SubActivityScreen.FINISH_SUB_MODE); + mIntent.putExtra("kill", true); + runLaunchpad(LaunchpadActivity.LAUNCH); + } +} diff --git a/tests/AndroidTests/src/com/android/unit_tests/activity/TestedActivity.java b/tests/AndroidTests/src/com/android/unit_tests/activity/TestedActivity.java new file mode 100644 index 0000000..ec407a9 --- /dev/null +++ b/tests/AndroidTests/src/com/android/unit_tests/activity/TestedActivity.java @@ -0,0 +1,77 @@ +/* + * 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.unit_tests.activity; + +import android.app.Activity; +import android.os.Handler; +import android.os.Looper; +import android.os.Message; +import android.os.MessageQueue; +import android.os.Bundle; + +public class TestedActivity extends Activity +{ + public TestedActivity() + { + } + + public void onCreate(Bundle icicle) + { + super.onCreate(icicle); + } + + protected void onRestoreInstanceState(Bundle state) + { + super.onRestoreInstanceState(state); + } + + protected void onResume() + { + super.onResume(); + Looper.myLooper().myQueue().addIdleHandler(new Idler()); + } + + protected void onSaveInstanceState(Bundle outState) + { + super.onSaveInstanceState(outState); + } + + protected void onStop() + { + super.onStop(); + } + + private Handler mHandler = new Handler() { + public void handleMessage(Message msg) { + setResult(RESULT_OK); + finish(); + } + }; + + private class Idler implements MessageQueue.IdleHandler + { + public final boolean queueIdle() + { + //Message m = Message.obtain(); + //mHandler.sendMessageAtTime(m, SystemClock.uptimeMillis()+1000); + setResult(RESULT_OK); + finish(); + return false; + } + } +} + diff --git a/tests/AndroidTests/src/com/android/unit_tests/activity/TestedScreen.java b/tests/AndroidTests/src/com/android/unit_tests/activity/TestedScreen.java new file mode 100644 index 0000000..4085aa9 --- /dev/null +++ b/tests/AndroidTests/src/com/android/unit_tests/activity/TestedScreen.java @@ -0,0 +1,128 @@ +/* + * 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.unit_tests.activity; + +import android.app.Activity; +import android.content.Intent; +import android.os.Handler; +import android.os.Looper; +import android.os.Message; +import android.os.MessageQueue; +import android.os.SystemClock; +import android.os.Bundle; +import android.util.Log; + +public class TestedScreen extends Activity +{ + public static final String WAIT_BEFORE_FINISH = "TestedScreen.WAIT_BEFORE_FINISH"; + public static final String DELIVER_RESULT = "TestedScreen.DELIVER_RESULT"; + public static final String CLEAR_TASK = "TestedScreen.CLEAR_TASK"; + + public TestedScreen() { + } + + public void onCreate(Bundle icicle) { + super.onCreate(icicle); + if (ActivityTests.DEBUG_LIFECYCLE) Log.v("test", "CREATE tested " + + Integer.toHexString(System.identityHashCode(this)) + ": " + getIntent()); + if (LaunchpadActivity.FORWARD_RESULT.equals(getIntent().getAction())) { + Intent intent = new Intent(getIntent()); + intent.setAction(DELIVER_RESULT); + intent.setFlags(Intent.FLAG_ACTIVITY_FORWARD_RESULT); + startActivity(intent); + if (ActivityTests.DEBUG_LIFECYCLE) Log.v("test", "Finishing tested " + + Integer.toHexString(System.identityHashCode(this)) + ": " + getIntent()); + finish(); + } else if (DELIVER_RESULT.equals(getIntent().getAction())) { + setResult(RESULT_OK, (new Intent()).setAction( + LaunchpadActivity.RETURNED_RESULT)); + if (ActivityTests.DEBUG_LIFECYCLE) Log.v("test", "Finishing tested " + + Integer.toHexString(System.identityHashCode(this)) + ": " + getIntent()); + finish(); + } else if (CLEAR_TASK.equals(getIntent().getAction())) { + if (!getIntent().getBooleanExtra(ClearTop.WAIT_CLEAR_TASK, false)) { + launchClearTask(); + } + } + } + + protected void onRestoreInstanceState(Bundle state) { + super.onRestoreInstanceState(state); + } + + protected void onResume() { + super.onResume(); + if (ActivityTests.DEBUG_LIFECYCLE) Log.v("test", "RESUME tested " + + Integer.toHexString(System.identityHashCode(this)) + ": " + getIntent()); + if (CLEAR_TASK.equals(getIntent().getAction())) { + if (getIntent().getBooleanExtra(ClearTop.WAIT_CLEAR_TASK, false)) { + Looper.myLooper().myQueue().addIdleHandler(new Idler()); + } + } else { + Looper.myLooper().myQueue().addIdleHandler(new Idler()); + } + } + + protected void onSaveInstanceState(Bundle outState) { + super.onSaveInstanceState(outState); + } + + protected void onStop() { + super.onStop(); + if (ActivityTests.DEBUG_LIFECYCLE) Log.v("test", "STOP tested " + + Integer.toHexString(System.identityHashCode(this)) + ": " + getIntent()); + } + + private void launchClearTask() { + Intent intent = new Intent(getIntent()). + addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP). + setClass(this, ClearTop.class); + startActivity(intent); + } + + private Handler mHandler = new Handler() { + public void handleMessage(Message msg) { + if (CLEAR_TASK.equals(getIntent().getAction())) { + launchClearTask(); + } else { + if (ActivityTests.DEBUG_LIFECYCLE) Log.v("test", "Finishing tested " + + Integer.toHexString(System.identityHashCode(this)) + ": " + getIntent()); + setResult(RESULT_OK); + finish(); + } + } + }; + + private class Idler implements MessageQueue.IdleHandler { + public final boolean queueIdle() { + if (WAIT_BEFORE_FINISH.equals(getIntent().getAction())) { + Message m = Message.obtain(); + mHandler.sendMessageAtTime(m, SystemClock.uptimeMillis()+1000); + } else if (CLEAR_TASK.equals(getIntent().getAction())) { + Message m = Message.obtain(); + mHandler.sendMessageAtTime(m, SystemClock.uptimeMillis()+1000); + } else { + if (ActivityTests.DEBUG_LIFECYCLE) Log.v("test", "Finishing tested " + + Integer.toHexString(System.identityHashCode(this)) + ": " + getIntent()); + setResult(RESULT_OK); + finish(); + } + return false; + } + } +} + diff --git a/tests/AndroidTests/src/com/android/unit_tests/content/ArrayTest.java b/tests/AndroidTests/src/com/android/unit_tests/content/ArrayTest.java new file mode 100644 index 0000000..4d5b5e7 --- /dev/null +++ b/tests/AndroidTests/src/com/android/unit_tests/content/ArrayTest.java @@ -0,0 +1,77 @@ +/* + * 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.unit_tests.content; + +import android.content.res.Resources; +import android.test.AndroidTestCase; +import android.test.suitebuilder.annotation.SmallTest; +import android.util.TypedValue; +import com.android.unit_tests.R; + +public class ArrayTest extends AndroidTestCase { + private Resources mResources; + + @Override + protected void setUp() throws Exception { + super.setUp(); + mResources = mContext.getResources(); + } + + private void checkEntry(int resid, int index, Object res, Object expected) { + assertEquals("in resource 0x" + Integer.toHexString(resid) + + " at index " + index, expected, res); + } + + private void checkStringArray(int resid, String[] expected) { + String[] res = mResources.getStringArray(resid); + assertEquals(res.length, expected.length); + for (int i=0; i<expected.length; i++) { + checkEntry(resid, i, res[i], expected[i]); + } + } + + private void checkTextArray(int resid, String[] expected) { + CharSequence[] res = mResources.getTextArray(resid); + assertEquals(res.length, expected.length); + for (int i=0; i<expected.length; i++) { + checkEntry(resid, i, res[i], expected[i]); + } + } + + private void checkIntArray(int resid, int[] expected) { + int[] res = mResources.getIntArray(resid); + assertEquals(res.length, expected.length); + for (int i=0; i<expected.length; i++) { + assertEquals("in resource 0x" + Integer.toHexString(resid) + + " at index " + i, expected[i], res[i]); + } + } + + @SmallTest + public void testStrings() throws Exception { + checkStringArray(R.array.strings, new String[] {"zero", "1", "here"}); + checkTextArray(R.array.strings, new String[] {"zero", "1", "here"}); + checkStringArray(R.array.integers, new String[] {null, null, null}); + checkTextArray(R.array.integers, new String[] {null, null, null}); + } + + @SmallTest + public void testIntegers() throws Exception { + checkIntArray(R.array.strings, new int[] {0, 0, 0}); + checkIntArray(R.array.integers, new int[] {0, 1, 101}); + } +} diff --git a/tests/AndroidTests/src/com/android/unit_tests/content/AssetTest.java b/tests/AndroidTests/src/com/android/unit_tests/content/AssetTest.java new file mode 100644 index 0000000..f38d062 --- /dev/null +++ b/tests/AndroidTests/src/com/android/unit_tests/content/AssetTest.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.unit_tests.content; + +import android.content.res.AssetManager; +import android.test.AndroidTestCase; +import android.test.suitebuilder.annotation.SmallTest; + +import java.io.IOException; +import java.io.InputStream; + +public class AssetTest extends AndroidTestCase { + private AssetManager mAssets; + + @Override + protected void setUp() throws Exception { + super.setUp(); + mAssets = mContext.getAssets(); + } + + public static void verifyTextAsset(InputStream is) throws IOException { + String expectedString = "OneTwoThreeFourFiveSixSevenEightNineTen"; + byte[] buffer = new byte[10]; + + int readCount; + int curIndex = 0; + while ((readCount = is.read(buffer, 0, buffer.length)) > 0) { + for (int i = 0; i < readCount; i++) { + assertEquals("At index " + curIndex + + " expected " + expectedString.charAt(curIndex) + + " but found " + ((char) buffer[i]), + buffer[i], expectedString.charAt(curIndex)); + curIndex++; + } + } + + readCount = is.read(buffer, 0, buffer.length); + assertEquals("Reading end of buffer: expected readCount=-1 but got " + readCount, + -1, readCount); + + readCount = is.read(buffer, buffer.length, 0); + assertEquals("Reading end of buffer length 0: expected readCount=0 but got " + readCount, + 0, readCount); + + is.close(); + } + + @SmallTest + public void testReadToEnd() throws Exception { + InputStream is = mAssets.open("text.txt"); + verifyTextAsset(is); + } + + // XXX failing + public void xxtestListDir() throws Exception { + String[] files = mAssets.list(""); + assertEquals(1, files.length); + assertEquals("test.txt", files[0]); + } +} diff --git a/tests/AndroidTests/src/com/android/unit_tests/content/ConfigTest.java b/tests/AndroidTests/src/com/android/unit_tests/content/ConfigTest.java new file mode 100644 index 0000000..a63885d --- /dev/null +++ b/tests/AndroidTests/src/com/android/unit_tests/content/ConfigTest.java @@ -0,0 +1,326 @@ +/* + * 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.unit_tests.content; + +import android.content.Context; +import android.content.res.AssetManager; +import android.content.res.Configuration; +import android.content.res.Resources; +import android.content.res.TypedArray; +import android.test.AndroidTestCase; +import android.test.suitebuilder.annotation.MediumTest; +import android.test.suitebuilder.annotation.SmallTest; +import android.util.DisplayMetrics; +import android.view.Display; +import android.view.WindowManager; +import com.android.unit_tests.R; + +import java.util.Locale; + +public class ConfigTest extends AndroidTestCase { + + private static void checkValue(Resources res, int resId, String expectedValue) { + try { + String actual = res.getString(resId); + assertNotNull("Returned wrong configuration-based simple value: expected <nothing>, got '" + + actual + "' from resource 0x" + + Integer.toHexString(resId), + expectedValue); + assertEquals("Returned wrong configuration-based simple value: expected " + + expectedValue + ", got '" + actual + "' from resource 0x" + + Integer.toHexString(resId), + expectedValue, actual); + } catch (Resources.NotFoundException e) { + assertNull("Resource not found for configuration-based simple value: expecting \"" + + expectedValue + "\"", + expectedValue); + } + } + + private static void checkValue(Resources res, int resId, + int[] styleable, String[] expectedValues) { + Resources.Theme theme = res.newTheme(); + TypedArray sa = theme.obtainStyledAttributes(resId, styleable); + for (int i = 0; i < styleable.length; i++) { + String actual = sa.getString(i); + assertEquals("Returned wrong configuration-based style value: expected " + + expectedValues[i] + ", got '" + actual + "' from attr " + + i + " of resource 0x" + Integer.toHexString(resId), + actual, expectedValues[i]); + } + sa.recycle(); + } + + public Resources getResources(Configuration config, + int mcc, int mnc, int touchscreen, int keyboard, int keysHidden, + int navigation, int width, int height) { + AssetManager assmgr = new AssetManager(); + assmgr.addAssetPath(mContext.getPackageResourcePath()); + DisplayMetrics metrics = new DisplayMetrics(); + WindowManager wm = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE); + Display d = wm.getDefaultDisplay(); + d.getMetrics(metrics); + config.mcc = mcc; + config.mnc = mnc; + config.touchscreen = touchscreen; + config.keyboard = keyboard; + config.keyboardHidden = keysHidden; + config.navigation = navigation; + metrics.widthPixels = width; + metrics.heightPixels = height; + return new Resources(assmgr, metrics, config); + } + + private static void checkPair(Resources res, int[] notResIds, + int simpleRes, String simpleString, + int bagRes, String bagString) { + boolean willHave = true; + if (notResIds != null) { + for (int i : notResIds) { + if (i == simpleRes) { + willHave = false; + break; + } + } + } + checkValue(res, simpleRes, willHave ? simpleString : null); + checkValue(res, bagRes, R.styleable.TestConfig, + new String[]{willHave ? bagString : null}); + } + + private static void checkAllExcept(Resources res, int[] notResIds) { + checkPair(res, notResIds, + R.configVarying.simple_default, "only simple default", + R.configVarying.bag_default, "only bag default"); + checkPair(res, notResIds, + R.configVarying.simple_mcc111, "only simple mcc111", + R.configVarying.bag_mcc111, "only bag mcc111"); + checkPair(res, notResIds, + R.configVarying.simple_mnc222, "only simple mnc222", + R.configVarying.bag_mnc222, "only bag mnc222"); + checkPair(res, notResIds, + R.configVarying.simple_xx, "only simple xx", + R.configVarying.bag_xx, "only bag xx"); + checkPair(res, notResIds, + R.configVarying.simple_xx_rYY, "only simple xx_rYY", + R.configVarying.bag_xx_rYY, "only bag xx_rYY"); + checkPair(res, notResIds, + R.configVarying.simple_notouch, "only simple notouch", + R.configVarying.bag_notouch, "only bag notouch"); + checkPair(res, notResIds, + R.configVarying.simple_finger, "only simple finger", + R.configVarying.bag_finger, "only bag finger"); + checkPair(res, notResIds, + R.configVarying.simple_stylus, "only simple stylus", + R.configVarying.bag_stylus, "only bag stylus"); + checkPair(res, notResIds, + R.configVarying.simple_12key, "only simple 12key", + R.configVarying.bag_12key, "only bag 12key"); + checkPair(res, notResIds, + R.configVarying.simple_320x200, "only simple 320x200", + R.configVarying.bag_320x200, "only bag 320x200"); + checkPair(res, notResIds, + R.configVarying.simple_480x320, "only simple 480x320", + R.configVarying.bag_480x320, "only bag 480x320"); + } + + @SmallTest + public void testDefaultNavigationMethod() throws Exception { + assertEquals(mContext.getResources().getConfiguration().navigation, + Configuration.NAVIGATION_TRACKBALL); + } + + @SmallTest + public void testAllConfigs() throws Exception { + /** + * Test a resource that contains a value for each possible single + * configuration value. + */ + Configuration config = new Configuration(); + Resources res = getResources(config, 0, 0, 0, 0, 0, 0, 0, 0); + checkValue(res, R.configVarying.simple, "simple default"); + checkValue(res, R.configVarying.bag, + R.styleable.TestConfig, new String[]{"bag default"}); + + config.locale = new Locale("xx"); + res = getResources(config, 0, 0, 0, 0, 0, 0, 0, 0); + checkValue(res, R.configVarying.simple, "simple xx"); + checkValue(res, R.configVarying.bag, + R.styleable.TestConfig, new String[]{"bag xx"}); + + config.locale = new Locale("xx", "YY"); + res = getResources(config, 0, 0, 0, 0, 0, 0, 0, 0); + checkValue(res, R.configVarying.simple, "simple xx-rYY"); + checkValue(res, R.configVarying.bag, + R.styleable.TestConfig, new String[]{"bag xx-rYY"}); + + config = new Configuration(); + res = getResources(config, 111, 0, 0, 0, 0, 0, 0, 0); + checkValue(res, R.configVarying.simple, "simple mcc111"); + checkValue(res, R.configVarying.bag, + R.styleable.TestConfig, new String[]{"bag mcc111"}); + + res = getResources(config, 0, 222, 0, 0, 0, 0, 0, 0); + checkValue(res, R.configVarying.simple, "simple mnc222"); + checkValue(res, R.configVarying.bag, + R.styleable.TestConfig, new String[]{"bag mnc222"}); + + res = getResources(config, 0, 0, Configuration.TOUCHSCREEN_NOTOUCH, 0, 0, 0, 0, 0); + checkValue(res, R.configVarying.simple, "simple notouch"); + checkValue(res, R.configVarying.bag, + R.styleable.TestConfig, new String[]{"bag notouch"}); + + res = getResources(config, 0, 0, Configuration.TOUCHSCREEN_FINGER, 0, 0, 0, 0, 0); + checkValue(res, R.configVarying.simple, "simple finger"); + checkValue(res, R.configVarying.bag, + R.styleable.TestConfig, new String[]{"bag finger"}); + + res = getResources(config, 0, 0, Configuration.TOUCHSCREEN_STYLUS, 0, 0, 0, 0, 0); + checkValue(res, R.configVarying.simple, "simple stylus"); + checkValue(res, R.configVarying.bag, + R.styleable.TestConfig, new String[]{"bag stylus"}); + + res = getResources(config, 0, 0, 0, Configuration.KEYBOARD_NOKEYS, 0, 0, 0, 0); + checkValue(res, R.configVarying.simple, "simple nokeys"); + checkValue(res, R.configVarying.bag, + R.styleable.TestConfig, new String[]{"bag nokeys"}); + + res = getResources(config, 0, 0, 0, Configuration.KEYBOARD_QWERTY, 0, 0, 0, 0); + checkValue(res, R.configVarying.simple, "simple qwerty"); + checkValue(res, R.configVarying.bag, + R.styleable.TestConfig, new String[]{"bag qwerty"}); + + res = getResources(config, 0, 0, 0, Configuration.KEYBOARD_12KEY, 0, 0, 0, 0); + checkValue(res, R.configVarying.simple, "simple 12key"); + checkValue(res, R.configVarying.bag, + R.styleable.TestConfig, new String[]{"bag 12key"}); + + res = getResources(config, 0, 0, 0, 0, Configuration.KEYBOARDHIDDEN_YES, 0, 0, 0); + checkValue(res, R.configVarying.simple, "simple keyshidden"); + checkValue(res, R.configVarying.bag, + R.styleable.TestConfig, new String[]{"bag keyshidden"}); + + res = getResources(config, 0, 0, 0, 0, Configuration.KEYBOARDHIDDEN_NO, 0, 0, 0); + checkValue(res, R.configVarying.simple, "simple keysexposed"); + checkValue(res, R.configVarying.bag, + R.styleable.TestConfig, new String[]{"bag keysexposed"}); + + res = getResources(config, 0, 0, 0, 0, 0, Configuration.NAVIGATION_NONAV, 0, 0); + checkValue(res, R.configVarying.simple, "simple nonav"); + checkValue(res, R.configVarying.bag, + R.styleable.TestConfig, new String[]{"bag nonav"}); + + res = getResources(config, 0, 0, 0, 0, 0, Configuration.NAVIGATION_DPAD, 0, 0); + checkValue(res, R.configVarying.simple, "simple dpad"); + checkValue(res, R.configVarying.bag, + R.styleable.TestConfig, new String[]{"bag dpad"}); + + res = getResources(config, 0, 0, 0, 0, 0, Configuration.NAVIGATION_TRACKBALL, 0, 0); + checkValue(res, R.configVarying.simple, "simple trackball"); + checkValue(res, R.configVarying.bag, + R.styleable.TestConfig, new String[]{"bag trackball"}); + + res = getResources(config, 0, 0, 0, 0, 0, Configuration.NAVIGATION_WHEEL, 0, 0); + checkValue(res, R.configVarying.simple, "simple wheel"); + checkValue(res, R.configVarying.bag, + R.styleable.TestConfig, new String[]{"bag wheel"}); + + res = getResources(config, 0, 0, 0, 0, 0, 0, 320, 200); + checkValue(res, R.configVarying.simple, "simple 320x200"); + checkValue(res, R.configVarying.bag, + R.styleable.TestConfig, new String[]{"bag 320x200"}); + + res = getResources(config, 0, 0, 0, 0, 0, 0, 480, 320); + checkValue(res, R.configVarying.simple, "simple 480x320"); + checkValue(res, R.configVarying.bag, + R.styleable.TestConfig, new String[]{"bag 480x320"}); + } + + @MediumTest + public void testSingleConfig() throws Exception { + /** + * Test resources that contain a value for only one possible configuration + * value. XXX This is not yet complete. + */ + Configuration config = new Configuration(); + Resources res = getResources(config, 0, 0, 0, 0, 0, 0, 0, 0); + checkAllExcept(res, new int[]{ + R.configVarying.simple_xx, + R.configVarying.simple_xx_rYY}); + + config.locale = new Locale("xx"); + res = getResources(config, 0, 0, 0, 0, 0, 0, 0, 0); + checkAllExcept(res, null); + + config.locale = new Locale("xx", "YY"); + res = getResources(config, 0, 0, 0, 0, 0, 0, 0, 0); + checkAllExcept(res, null); + + config.locale = new Locale("xx", "ZZ"); + res = getResources(config, 0, 0, 0, 0, 0, 0, 0, 0); + checkAllExcept(res, new int[]{R.configVarying.simple_xx_rYY}); + + config = new Configuration(); + res = getResources(config, 111, 0, 0, 0, 0, 0, 0, 0); + checkAllExcept(res, new int[]{ + R.configVarying.simple_xx, + R.configVarying.simple_xx_rYY}); + + res = getResources(config, 0, 222, 0, 0, 0, 0, 0, 0); + checkAllExcept(res, new int[]{ + R.configVarying.simple_xx, + R.configVarying.simple_xx_rYY}); + + res = getResources(config, 0, 0, Configuration.TOUCHSCREEN_NOTOUCH, 0, 0, 0, 0, 0); + checkAllExcept(res, new int[]{ + R.configVarying.simple_xx, + R.configVarying.simple_xx_rYY, + R.configVarying.simple_finger, + R.configVarying.simple_stylus}); + + res = getResources(config, 0, 0, Configuration.TOUCHSCREEN_FINGER, 0, 0, 0, 0, 0); + checkAllExcept(res, new int[]{ + R.configVarying.simple_xx, + R.configVarying.simple_xx_rYY, + R.configVarying.simple_notouch, + R.configVarying.simple_stylus}); + + res = getResources(config, 0, 0, Configuration.TOUCHSCREEN_STYLUS, 0, 0, 0, 0, 0); + checkAllExcept(res, new int[]{ + R.configVarying.simple_xx, + R.configVarying.simple_xx_rYY, + R.configVarying.simple_notouch, + R.configVarying.simple_finger}); + + res = getResources(config, 0, 0, 0, Configuration.KEYBOARD_12KEY, 0, 0, 0, 0); + checkAllExcept(res, new int[]{ + R.configVarying.simple_xx, + R.configVarying.simple_xx_rYY}); + + res = getResources(config, 0, 0, 0, 0, 0, 0, 320, 200); + checkAllExcept(res, new int[]{ + R.configVarying.simple_xx, + R.configVarying.simple_xx_rYY, + R.configVarying.simple_480x320}); + + res = getResources(config, 0, 0, 0, 0, 0, 0, 480, 320); + checkAllExcept(res, new int[]{ + R.configVarying.simple_xx, + R.configVarying.simple_xx_rYY, + R.configVarying.simple_320x200}); + } +} diff --git a/tests/AndroidTests/src/com/android/unit_tests/content/ContentTests.java b/tests/AndroidTests/src/com/android/unit_tests/content/ContentTests.java new file mode 100644 index 0000000..80318dc --- /dev/null +++ b/tests/AndroidTests/src/com/android/unit_tests/content/ContentTests.java @@ -0,0 +1,32 @@ +/* + * 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.unit_tests.content; + +import junit.framework.TestSuite; + +public class ContentTests { + public static TestSuite suite() { + TestSuite suite = new TestSuite(ContentTests.class.getName()); + + suite.addTestSuite(AssetTest.class); + suite.addTestSuite(IntentFilterTest.class); + suite.addTest(ResourceTests.suite()); + suite.addTestSuite(PluralResourcesTest.class); + suite.addTestSuite(ConfigTest.class); + return suite; + } +} diff --git a/tests/AndroidTests/src/com/android/unit_tests/content/FractionTest.java b/tests/AndroidTests/src/com/android/unit_tests/content/FractionTest.java new file mode 100644 index 0000000..74a6b8d --- /dev/null +++ b/tests/AndroidTests/src/com/android/unit_tests/content/FractionTest.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 com.android.unit_tests.content; + +import android.content.res.Resources; +import android.test.AndroidTestCase; +import android.test.suitebuilder.annotation.SmallTest; +import android.util.TypedValue; +import com.android.unit_tests.R; + +public class FractionTest extends AndroidTestCase { + + private Resources mResources; + private final TypedValue mValue = new TypedValue(); + + @Override + protected void setUp() throws Exception { + super.setUp(); + mResources = mContext.getResources(); + } + + @SmallTest + public void testFractions() throws Exception { + tryFraction(R.dimen.frac100perc, 1, 1, 1); + tryFraction(R.dimen.frac1perc, 1, 1, .01f); + tryFraction(R.dimen.fracp1perc, 1, 1, .001f); + tryFraction(R.dimen.fracp01perc, 1, 1, .0001f); + tryFraction(R.dimen.frac0perc, 1, 1, 0); + tryFraction(R.dimen.frac1p1perc, 1, 1, .011f); + tryFraction(R.dimen.frac100p1perc, 1, 1, 1.001f); + tryFraction(R.dimen.frac25510perc, 1, 1, 255.1f); + tryFraction(R.dimen.frac25610perc, 1, 1, 256.1f); + tryFraction(R.dimen.frac6553510perc, 1, 1, 65535.1f); + tryFraction(R.dimen.frac6553610perc, 1, 1, 65536.1f); + + tryFraction(R.dimen.frac100perc, 100, 1, 100); + tryFraction(R.dimen.frac1perc, 100, 1, .01f * 100); + tryFraction(R.dimen.fracp1perc, 100, 1, .001f * 100); + tryFraction(R.dimen.fracp01perc, 100, 1, .0001f * 100); + tryFraction(R.dimen.frac0perc, 100, 1, 0); + tryFraction(R.dimen.frac1p1perc, 100, 1, .011f * 100); + tryFraction(R.dimen.frac100p1perc, 100, 1, 1.001f * 100); + tryFraction(R.dimen.frac25510perc, 100, 1, 255.1f * 100); + tryFraction(R.dimen.frac25610perc, 100, 1, 256.1f * 100); + tryFraction(R.dimen.frac6553510perc, 100, 1, 65535.1f * 100); + tryFraction(R.dimen.frac6553610perc, 100, 1, 65536.1f * 100); + + tryFraction(R.dimen.frac100pperc, 100, 2, 2); + tryFraction(R.dimen.frac1pperc, 100, 2, .01f * 2); + tryFraction(R.dimen.fracp1pperc, 100, 2, .001f * 2); + tryFraction(R.dimen.fracp01pperc, 100, 2, .0001f * 2); + tryFraction(R.dimen.frac0pperc, 100, 2, 0); + tryFraction(R.dimen.frac1p1pperc, 100, 2, .011f * 2); + tryFraction(R.dimen.frac100p1pperc, 100, 2, 1.001f * 2); + tryFraction(R.dimen.frac25510pperc, 100, 2, 255.1f * 2); + tryFraction(R.dimen.frac25610pperc, 100, 2, 256.1f * 2); + tryFraction(R.dimen.frac6553510pperc, 100, 2, 65535.1f * 2); + tryFraction(R.dimen.frac6553610pperc, 100, 2, 65536.1f * 2); + } + + private void tryFraction(int resid, float base, float pbase, float expected) { + mResources.getValue(resid, mValue, true); + float res = mValue.getFraction(base, pbase); + float diff = Math.abs(expected - res); + float prec = expected * 1e-4f; + if (prec < 1e-5f) { + prec = 1e-5f; + } + //System.out.println( + // "Res 0x" + Integer.toHexString(resid) + ": got=" + res + // + ", expected=" + expected + ", diff=" + diff); + assertFalse("Expecting value " + expected + " got " + res + + ": in resource 0x" + Integer.toHexString(resid) + + " " + mValue, + diff > prec); + } +} + diff --git a/tests/AndroidTests/src/com/android/unit_tests/content/IntentFilterTest.java b/tests/AndroidTests/src/com/android/unit_tests/content/IntentFilterTest.java new file mode 100644 index 0000000..0335b9d --- /dev/null +++ b/tests/AndroidTests/src/com/android/unit_tests/content/IntentFilterTest.java @@ -0,0 +1,570 @@ +/* + * 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.unit_tests.content; + +import android.content.IntentFilter; +import android.test.suitebuilder.annotation.SmallTest; +import static android.os.PatternMatcher.PATTERN_LITERAL; +import static android.os.PatternMatcher.PATTERN_PREFIX; +import static android.os.PatternMatcher.PATTERN_SIMPLE_GLOB; +import android.net.Uri; +import android.util.StringBuilderPrinter; +import junit.framework.TestCase; + +import java.util.HashSet; + +public class IntentFilterTest extends TestCase { + + public static class Match extends IntentFilter { + Match(String[] actions, String[] categories, String[] mimeTypes, + String[] schemes, String[] authorities, String[] ports) { + if (actions != null) { + for (int i = 0; i < actions.length; i++) { + addAction(actions[i]); + } + } + if (categories != null) { + for (int i = 0; i < categories.length; i++) { + addCategory(categories[i]); + } + } + if (mimeTypes != null) { + for (int i = 0; i < mimeTypes.length; i++) { + try { + addDataType(mimeTypes[i]); + } catch (IntentFilter.MalformedMimeTypeException e) { + throw new RuntimeException("Bad mime type", e); + } + } + } + if (schemes != null) { + for (int i = 0; i < schemes.length; i++) { + addDataScheme(schemes[i]); + } + } + if (authorities != null) { + for (int i = 0; i < authorities.length; i++) { + addDataAuthority(authorities[i], + ports != null ? ports[i] : null); + } + } + } + + Match(String[] actions, String[] categories, String[] mimeTypes, + String[] schemes, String[] authorities, String[] ports, + String[] paths, int[] pathTypes) { + this(actions, categories, mimeTypes, schemes, authorities, ports); + if (paths != null) { + for (int i = 0; i < paths.length; i++) { + addDataPath(paths[i], pathTypes[i]); + } + } + } + } + + public static class MatchCondition { + public final int result; + public final String action; + public final String mimeType; + public final Uri data; + public final String[] categories; + + public MatchCondition(int _result, String _action, String[] _categories, + String _mimeType, String _data) { + result = _result; + action = _action; + mimeType = _mimeType; + data = _data != null ? Uri.parse(_data) : null; + categories = _categories; + } + } + + public static void checkMatches(IntentFilter filter, + MatchCondition[] results) { + for (int i = 0; i < results.length; i++) { + MatchCondition mc = results[i]; + HashSet<String> categories = null; + if (mc.categories != null) { + for (int j = 0; j < mc.categories.length; j++) { + if (categories == null) { + categories = new HashSet<String>(); + } + categories.add(mc.categories[j]); + } + } + int result = filter.match(mc.action, mc.mimeType, + mc.data != null ? mc.data.getScheme() : null, mc.data, + categories, "test"); + if ( (result & IntentFilter.MATCH_CATEGORY_MASK) + != (mc.result & IntentFilter.MATCH_CATEGORY_MASK) ) { + StringBuilder msg = new StringBuilder(); + msg.append("Error matching against IntentFilter:\n"); + filter.dump(new StringBuilderPrinter(msg), " "); + msg.append("Match action: "); + msg.append(mc.action); + msg.append("\nMatch mimeType: "); + msg.append(mc.mimeType); + msg.append("\nMatch data: "); + msg.append(mc.data); + msg.append("\nMatch categories: "); + if (mc.categories != null) { + for (int j = 0; j < mc.categories.length; j++) { + if (j > 0) msg.append(", "); + msg.append(mc.categories[j]); + } + } + msg.append("\nExpected result: 0x"); + msg.append(Integer.toHexString(mc.result)); + msg.append(", got result: 0x"); + msg.append(Integer.toHexString(result)); + throw new RuntimeException(msg.toString()); + } + } + } + + @SmallTest + public void testActions() throws Exception { + IntentFilter filter = new Match( + new String[]{"action1"}, null, null, null, null, null); + checkMatches(filter, new MatchCondition[]{ + new MatchCondition(IntentFilter.MATCH_CATEGORY_EMPTY, null, + null, null, null), + new MatchCondition(IntentFilter.MATCH_CATEGORY_EMPTY, "action1", + null, null, null), + new MatchCondition(IntentFilter.NO_MATCH_ACTION, "action2", + null, null, null), + }); + + filter = new Match( + new String[]{"action1", "action2"}, + null, null, null, null, null); + checkMatches(filter, new MatchCondition[]{ + new MatchCondition(IntentFilter.MATCH_CATEGORY_EMPTY, null, + null, null, null), + new MatchCondition(IntentFilter.MATCH_CATEGORY_EMPTY, "action1", + null, null, null), + new MatchCondition(IntentFilter.MATCH_CATEGORY_EMPTY, "action2", + null, null, null), + new MatchCondition(IntentFilter.NO_MATCH_ACTION, "action3", + null, null, null), + }); + } + + @SmallTest + public void testCategories() throws Exception { + IntentFilter filter = new Match( + null, new String[]{"category1"}, null, null, null, null); + checkMatches(filter, new MatchCondition[]{ + new MatchCondition(IntentFilter.MATCH_CATEGORY_EMPTY, null, + null, null, null), + new MatchCondition(IntentFilter.MATCH_CATEGORY_EMPTY, null, + new String[]{"category1"}, null, null), + new MatchCondition(IntentFilter.NO_MATCH_CATEGORY, null, + new String[]{"category2"}, null, null), + new MatchCondition(IntentFilter.NO_MATCH_CATEGORY, null, + new String[]{"category1", "category2"}, null, null), + }); + + filter = new Match( + null, new String[]{"category1", "category2"}, null, null, + null, null); + checkMatches(filter, new MatchCondition[]{ + new MatchCondition(IntentFilter.MATCH_CATEGORY_EMPTY, null, + null, null, null), + new MatchCondition(IntentFilter.MATCH_CATEGORY_EMPTY, null, + new String[]{"category1"}, null, null), + new MatchCondition(IntentFilter.MATCH_CATEGORY_EMPTY, null, + new String[]{"category2"}, null, null), + new MatchCondition(IntentFilter.MATCH_CATEGORY_EMPTY, null, + new String[]{"category1", "category2"}, null, null), + new MatchCondition(IntentFilter.NO_MATCH_CATEGORY, null, + new String[]{"category3"}, null, null), + new MatchCondition(IntentFilter.NO_MATCH_CATEGORY, null, + new String[]{"category1", "category2", "category3"}, + null, null), + }); + } + + @SmallTest + public void testMimeTypes() throws Exception { + IntentFilter filter = new Match( + null, null, new String[]{"which1/what1"}, null, null, null); + checkMatches(filter, new MatchCondition[]{ + new MatchCondition(IntentFilter.NO_MATCH_TYPE, null, + null, null, null), + new MatchCondition(IntentFilter.MATCH_CATEGORY_TYPE, null, null, + "which1/what1", null), + new MatchCondition(IntentFilter.MATCH_CATEGORY_TYPE, null, null, + "which1/*", null), + new MatchCondition(IntentFilter.MATCH_CATEGORY_TYPE, null, null, + "*/*", null), + new MatchCondition(IntentFilter.NO_MATCH_TYPE, null, null, + "which2/what2", null), + new MatchCondition(IntentFilter.NO_MATCH_TYPE, null, null, + "which2/*", null), + new MatchCondition(IntentFilter.NO_MATCH_TYPE, null, null, + "which1/what2", null), + }); + + filter = new Match(null, null, + new String[]{"which1/what1", "which2/what2"}, null, null, + null); + checkMatches(filter, new MatchCondition[]{ + new MatchCondition(IntentFilter.NO_MATCH_TYPE, null, + null, null, null), + new MatchCondition(IntentFilter.MATCH_CATEGORY_TYPE, null, null, + "which1/what1", null), + new MatchCondition(IntentFilter.MATCH_CATEGORY_TYPE, null, null, + "which1/*", null), + new MatchCondition(IntentFilter.MATCH_CATEGORY_TYPE, null, null, + "*/*", null), + new MatchCondition(IntentFilter.MATCH_CATEGORY_TYPE, null, null, + "which2/what2", null), + new MatchCondition(IntentFilter.MATCH_CATEGORY_TYPE, null, null, + "which2/*", null), + new MatchCondition(IntentFilter.NO_MATCH_TYPE, null, null, + "which1/what2", null), + new MatchCondition(IntentFilter.NO_MATCH_TYPE, null, null, + "which3/what3", null), + }); + + filter = new Match(null, null, + new String[]{"which1/*"}, null, null, null); + checkMatches(filter, new MatchCondition[]{ + new MatchCondition(IntentFilter.NO_MATCH_TYPE, null, + null, null, null), + new MatchCondition(IntentFilter.MATCH_CATEGORY_TYPE, null, null, + "which1/what1", null), + new MatchCondition(IntentFilter.MATCH_CATEGORY_TYPE, null, null, + "which1/*", null), + new MatchCondition(IntentFilter.MATCH_CATEGORY_TYPE, null, null, + "*/*", null), + new MatchCondition(IntentFilter.NO_MATCH_TYPE, null, null, + "which2/what2", null), + new MatchCondition(IntentFilter.NO_MATCH_TYPE, null, null, + "which2/*", null), + new MatchCondition(IntentFilter.MATCH_CATEGORY_TYPE, null, null, + "which1/what2", null), + new MatchCondition(IntentFilter.NO_MATCH_TYPE, null, null, + "which3/what3", null), + }); + + filter = new Match(null, null, + new String[]{"*/*"}, null, null, null); + checkMatches(filter, new MatchCondition[]{ + new MatchCondition(IntentFilter.NO_MATCH_TYPE, null, + null, null, null), + new MatchCondition(IntentFilter.MATCH_CATEGORY_TYPE, null, null, + "which1/what1", null), + new MatchCondition(IntentFilter.MATCH_CATEGORY_TYPE, null, null, + "which1/*", null), + new MatchCondition(IntentFilter.MATCH_CATEGORY_TYPE, null, null, + "*/*", null), + new MatchCondition(IntentFilter.MATCH_CATEGORY_TYPE, null, null, + "which2/what2", null), + new MatchCondition(IntentFilter.MATCH_CATEGORY_TYPE, null, null, + "which2/*", null), + new MatchCondition(IntentFilter.MATCH_CATEGORY_TYPE, null, null, + "which1/what2", null), + new MatchCondition(IntentFilter.MATCH_CATEGORY_TYPE, null, null, + "which3/what3", null), + }); + } + + @SmallTest + public void testSchemes() throws Exception { + IntentFilter filter = new Match(null, null, null, + new String[]{"scheme1"}, null, null); + checkMatches(filter, new MatchCondition[]{ + new MatchCondition(IntentFilter.NO_MATCH_DATA, null, + null, null, null), + new MatchCondition(IntentFilter.MATCH_CATEGORY_SCHEME, null, + null, null, "scheme1:foo"), + new MatchCondition(IntentFilter.NO_MATCH_DATA, null, + null, null, "scheme2:foo"), + }); + + filter = new Match(null, null, null, + new String[]{"scheme1", "scheme2"}, null, null); + checkMatches(filter, new MatchCondition[]{ + new MatchCondition(IntentFilter.NO_MATCH_DATA, null, + null, null, null), + new MatchCondition(IntentFilter.MATCH_CATEGORY_SCHEME, null, + null, null, "scheme1:foo"), + new MatchCondition(IntentFilter.MATCH_CATEGORY_SCHEME, null, + null, null, "scheme2:foo"), + new MatchCondition(IntentFilter.NO_MATCH_DATA, null, + null, null, "scheme3:foo"), + }); + } + + @SmallTest + public void testAuthorities() throws Exception { + IntentFilter filter = new Match(null, null, null, + new String[]{"scheme1"}, + new String[]{"authority1"}, new String[]{null}); + checkMatches(filter, new MatchCondition[]{ + new MatchCondition(IntentFilter.NO_MATCH_DATA, null, + null, null, null), + new MatchCondition(IntentFilter.NO_MATCH_DATA, null, + null, null, "scheme1:foo"), + new MatchCondition(IntentFilter.MATCH_CATEGORY_HOST, null, + null, null, "scheme1://authority1/"), + new MatchCondition(IntentFilter.NO_MATCH_DATA, null, + null, null, "scheme1://authority2/"), + new MatchCondition(IntentFilter.MATCH_CATEGORY_HOST, null, + null, null, "scheme1://authority1:100/"), + }); + + filter = new Match(null, null, null, new String[]{"scheme1"}, + new String[]{"authority1"}, new String[]{"100"}); + checkMatches(filter, new MatchCondition[]{ + new MatchCondition(IntentFilter.NO_MATCH_DATA, null, + null, null, null), + new MatchCondition(IntentFilter.NO_MATCH_DATA, null, + null, null, "scheme1:foo"), + new MatchCondition(IntentFilter.NO_MATCH_DATA, null, + null, null, "scheme1://authority1/"), + new MatchCondition(IntentFilter.NO_MATCH_DATA, null, + null, null, "scheme1://authority2/"), + new MatchCondition(IntentFilter.MATCH_CATEGORY_PORT, null, + null, null, "scheme1://authority1:100/"), + new MatchCondition(IntentFilter.NO_MATCH_DATA, null, + null, null, "scheme1://authority1:200/"), + }); + + filter = new Match(null, null, null, new String[]{"scheme1"}, + new String[]{"authority1", "authority2"}, + new String[]{"100", null}); + checkMatches(filter, new MatchCondition[]{ + new MatchCondition(IntentFilter.NO_MATCH_DATA, null, + null, null, null), + new MatchCondition(IntentFilter.NO_MATCH_DATA, null, + null, null, "scheme1:foo"), + new MatchCondition(IntentFilter.NO_MATCH_DATA, null, + null, null, "scheme1://authority1/"), + new MatchCondition(IntentFilter.MATCH_CATEGORY_HOST, null, + null, null, "scheme1://authority2/"), + new MatchCondition(IntentFilter.MATCH_CATEGORY_PORT, null, + null, null, "scheme1://authority1:100/"), + new MatchCondition(IntentFilter.NO_MATCH_DATA, null, + null, null, "scheme1://authority1:200/"), + }); + } + + @SmallTest + public void testPaths() throws Exception { + IntentFilter filter = new Match(null, null, null, + new String[]{"scheme"}, new String[]{"authority"}, null, + new String[]{"/literal1", "/2literal"}, + new int[]{PATTERN_LITERAL, PATTERN_LITERAL}); + checkMatches(filter, new MatchCondition[]{ + new MatchCondition(IntentFilter.NO_MATCH_DATA, null, + null, null, null), + new MatchCondition(IntentFilter.MATCH_CATEGORY_PATH, null, + null, null, "scheme://authority/literal1"), + new MatchCondition(IntentFilter.MATCH_CATEGORY_PATH, null, + null, null, "scheme://authority/2literal"), + new MatchCondition(IntentFilter.NO_MATCH_DATA, null, + null, null, "scheme://authority/literal"), + new MatchCondition(IntentFilter.NO_MATCH_DATA, null, + null, null, "scheme://authority/literal12"), + }); + filter = new Match(null, null, null, + new String[]{"scheme"}, new String[]{"authority"}, null, + new String[]{"/literal1", "/2literal"}, + new int[]{PATTERN_PREFIX, PATTERN_PREFIX}); + checkMatches(filter, new MatchCondition[]{ + new MatchCondition(IntentFilter.NO_MATCH_DATA, null, + null, null, null), + new MatchCondition(IntentFilter.MATCH_CATEGORY_PATH, null, + null, null, "scheme://authority/literal1"), + new MatchCondition(IntentFilter.MATCH_CATEGORY_PATH, null, + null, null, "scheme://authority/2literal"), + new MatchCondition(IntentFilter.NO_MATCH_DATA, null, + null, null, "scheme://authority/literal"), + new MatchCondition(IntentFilter.MATCH_CATEGORY_PATH, null, + null, null, "scheme://authority/literal12"), + }); + filter = new Match(null, null, null, + new String[]{"scheme"}, new String[]{"authority"}, null, + new String[]{"/.*"}, + new int[]{PATTERN_SIMPLE_GLOB}); + checkMatches(filter, new MatchCondition[]{ + new MatchCondition(IntentFilter.NO_MATCH_DATA, null, + null, null, null), + new MatchCondition(IntentFilter.MATCH_CATEGORY_PATH, null, + null, null, "scheme://authority/literal1"), + new MatchCondition(IntentFilter.MATCH_CATEGORY_PATH, null, + null, null, "scheme://authority/"), + new MatchCondition(IntentFilter.NO_MATCH_DATA, null, + null, null, "scheme://authority"), + }); + filter = new Match(null, null, null, + new String[]{"scheme"}, new String[]{"authority"}, null, + new String[]{".*"}, + new int[]{PATTERN_SIMPLE_GLOB}); + checkMatches(filter, new MatchCondition[]{ + new MatchCondition(IntentFilter.NO_MATCH_DATA, null, + null, null, null), + new MatchCondition(IntentFilter.MATCH_CATEGORY_PATH, null, + null, null, "scheme://authority/literal1"), + new MatchCondition(IntentFilter.MATCH_CATEGORY_PATH, null, + null, null, "scheme://authority/"), + new MatchCondition(IntentFilter.MATCH_CATEGORY_PATH, null, + null, null, "scheme://authority"), + }); + filter = new Match(null, null, null, + new String[]{"scheme"}, new String[]{"authority"}, null, + new String[]{"/a1*b"}, + new int[]{PATTERN_SIMPLE_GLOB}); + checkMatches(filter, new MatchCondition[]{ + new MatchCondition(IntentFilter.NO_MATCH_DATA, null, + null, null, null), + new MatchCondition(IntentFilter.MATCH_CATEGORY_PATH, null, + null, null, "scheme://authority/ab"), + new MatchCondition(IntentFilter.MATCH_CATEGORY_PATH, null, + null, null, "scheme://authority/a1b"), + new MatchCondition(IntentFilter.MATCH_CATEGORY_PATH, null, + null, null, "scheme://authority/a11b"), + new MatchCondition(IntentFilter.NO_MATCH_DATA, null, + null, null, "scheme://authority/a2b"), + new MatchCondition(IntentFilter.NO_MATCH_DATA, null, + null, null, "scheme://authority/a1bc"), + new MatchCondition(IntentFilter.NO_MATCH_DATA, null, + null, null, "scheme://authority/"), + }); + filter = new Match(null, null, null, + new String[]{"scheme"}, new String[]{"authority"}, null, + new String[]{"/a1*"}, + new int[]{PATTERN_SIMPLE_GLOB}); + checkMatches(filter, new MatchCondition[]{ + new MatchCondition(IntentFilter.NO_MATCH_DATA, null, + null, null, null), + new MatchCondition(IntentFilter.MATCH_CATEGORY_PATH, null, + null, null, "scheme://authority/a1"), + new MatchCondition(IntentFilter.NO_MATCH_DATA, null, + null, null, "scheme://authority/ab"), + new MatchCondition(IntentFilter.MATCH_CATEGORY_PATH, null, + null, null, "scheme://authority/a11"), + new MatchCondition(IntentFilter.NO_MATCH_DATA, null, + null, null, "scheme://authority/a1b"), + new MatchCondition(IntentFilter.MATCH_CATEGORY_PATH, null, + null, null, "scheme://authority/a11"), + new MatchCondition(IntentFilter.NO_MATCH_DATA, null, + null, null, "scheme://authority/a2"), + }); + filter = new Match(null, null, null, + new String[]{"scheme"}, new String[]{"authority"}, null, + new String[]{"/a\\.*b"}, + new int[]{PATTERN_SIMPLE_GLOB}); + checkMatches(filter, new MatchCondition[]{ + new MatchCondition(IntentFilter.NO_MATCH_DATA, null, + null, null, null), + new MatchCondition(IntentFilter.MATCH_CATEGORY_PATH, null, + null, null, "scheme://authority/ab"), + new MatchCondition(IntentFilter.MATCH_CATEGORY_PATH, null, + null, null, "scheme://authority/a.b"), + new MatchCondition(IntentFilter.MATCH_CATEGORY_PATH, null, + null, null, "scheme://authority/a..b"), + new MatchCondition(IntentFilter.NO_MATCH_DATA, null, + null, null, "scheme://authority/a2b"), + new MatchCondition(IntentFilter.NO_MATCH_DATA, null, + null, null, "scheme://authority/a.bc"), + new MatchCondition(IntentFilter.NO_MATCH_DATA, null, + null, null, "scheme://authority/"), + }); + filter = new Match(null, null, null, + new String[]{"scheme"}, new String[]{"authority"}, null, + new String[]{"/a.*b"}, + new int[]{PATTERN_SIMPLE_GLOB}); + checkMatches(filter, new MatchCondition[]{ + new MatchCondition(IntentFilter.NO_MATCH_DATA, null, + null, null, null), + new MatchCondition(IntentFilter.MATCH_CATEGORY_PATH, null, + null, null, "scheme://authority/ab"), + new MatchCondition(IntentFilter.MATCH_CATEGORY_PATH, null, + null, null, "scheme://authority/a.b"), + new MatchCondition(IntentFilter.MATCH_CATEGORY_PATH, null, + null, null, "scheme://authority/a.1b"), + new MatchCondition(IntentFilter.MATCH_CATEGORY_PATH, null, + null, null, "scheme://authority/a2b"), + new MatchCondition(IntentFilter.NO_MATCH_DATA, null, + null, null, "scheme://authority/a.bc"), + new MatchCondition(IntentFilter.NO_MATCH_DATA, null, + null, null, "scheme://authority/"), + }); + filter = new Match(null, null, null, + new String[]{"scheme"}, new String[]{"authority"}, null, + new String[]{"/a.*"}, + new int[]{PATTERN_SIMPLE_GLOB}); + checkMatches(filter, new MatchCondition[]{ + new MatchCondition(IntentFilter.NO_MATCH_DATA, null, + null, null, null), + new MatchCondition(IntentFilter.MATCH_CATEGORY_PATH, null, + null, null, "scheme://authority/ab"), + new MatchCondition(IntentFilter.MATCH_CATEGORY_PATH, null, + null, null, "scheme://authority/a.b"), + new MatchCondition(IntentFilter.MATCH_CATEGORY_PATH, null, + null, null, "scheme://authority/a.1b"), + new MatchCondition(IntentFilter.MATCH_CATEGORY_PATH, null, + null, null, "scheme://authority/a2b"), + new MatchCondition(IntentFilter.MATCH_CATEGORY_PATH, null, + null, null, "scheme://authority/a.bc"), + new MatchCondition(IntentFilter.NO_MATCH_DATA, null, + null, null, "scheme://authority/"), + }); + filter = new Match(null, null, null, + new String[]{"scheme"}, new String[]{"authority"}, null, + new String[]{"/a.\\*b"}, + new int[]{PATTERN_SIMPLE_GLOB}); + checkMatches(filter, new MatchCondition[]{ + new MatchCondition(IntentFilter.NO_MATCH_DATA, null, + null, null, null), + new MatchCondition(IntentFilter.NO_MATCH_DATA, null, + null, null, "scheme://authority/ab"), + new MatchCondition(IntentFilter.MATCH_CATEGORY_PATH, null, + null, null, "scheme://authority/a.*b"), + new MatchCondition(IntentFilter.MATCH_CATEGORY_PATH, null, + null, null, "scheme://authority/a1*b"), + new MatchCondition(IntentFilter.NO_MATCH_DATA, null, + null, null, "scheme://authority/a2b"), + new MatchCondition(IntentFilter.NO_MATCH_DATA, null, + null, null, "scheme://authority/a.bc"), + new MatchCondition(IntentFilter.NO_MATCH_DATA, null, + null, null, "scheme://authority/"), + }); + filter = new Match(null, null, null, + new String[]{"scheme"}, new String[]{"authority"}, null, + new String[]{"/a.\\*"}, + new int[]{PATTERN_SIMPLE_GLOB}); + checkMatches(filter, new MatchCondition[]{ + new MatchCondition(IntentFilter.NO_MATCH_DATA, null, + null, null, null), + new MatchCondition(IntentFilter.NO_MATCH_DATA, null, + null, null, "scheme://authority/ab"), + new MatchCondition(IntentFilter.MATCH_CATEGORY_PATH, null, + null, null, "scheme://authority/a.*"), + new MatchCondition(IntentFilter.MATCH_CATEGORY_PATH, null, + null, null, "scheme://authority/a1*"), + new MatchCondition(IntentFilter.NO_MATCH_DATA, null, + null, null, "scheme://authority/a1b"), + }); + } + +} + diff --git a/tests/AndroidTests/src/com/android/unit_tests/content/PluralResourcesTest.java b/tests/AndroidTests/src/com/android/unit_tests/content/PluralResourcesTest.java new file mode 100644 index 0000000..c3d1478 --- /dev/null +++ b/tests/AndroidTests/src/com/android/unit_tests/content/PluralResourcesTest.java @@ -0,0 +1,97 @@ +/* + * Copyright (C) 2007 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.unit_tests.content; + +import android.content.res.AssetManager; +import android.content.res.Configuration; +import android.content.res.Resources; +import android.content.res.TypedArray; +import android.test.AndroidTestCase; +import android.test.suitebuilder.annotation.SmallTest; +import android.util.TypedValue; +import android.util.Log; +import com.android.unit_tests.R; + +import junit.framework.Assert; + +import java.util.Locale; + +public class PluralResourcesTest extends AndroidTestCase { + private static final String TAG = "PluralResourcesTest"; + + private Resources mResources; + + @Override + protected void setUp() throws Exception { + super.setUp(); + mResources = mContext.getResources(); + } + + Resources resourcesForLanguage(String lang) { + Configuration config = new Configuration(); + config.updateFrom(mResources.getConfiguration()); + config.locale = new Locale(lang); + return new Resources(mResources.getAssets(), mResources.getDisplayMetrics(), config); + } + + @SmallTest + public void testPlurals() throws Exception { + CharSequence cs; + Resources res = resourcesForLanguage("en"); + + cs = res.getQuantityText(R.plurals.plurals_test, 0); + Log.d(TAG, "english 0 cs=" + cs); + Assert.assertEquals(cs.toString(), "Some dogs"); + + cs = res.getQuantityText(R.plurals.plurals_test, 1); + Log.d(TAG, "english 1 cs=" + cs); + Assert.assertEquals(cs.toString(), "A dog"); + + cs = res.getQuantityText(R.plurals.plurals_test, 2); + Assert.assertEquals(cs.toString(), "Some dogs"); + + cs = res.getQuantityText(R.plurals.plurals_test, 5); + Assert.assertEquals(cs.toString(), "Some dogs"); + + cs = res.getQuantityText(R.plurals.plurals_test, 500); + Assert.assertEquals(cs.toString(), "Some dogs"); + } + + @SmallTest + public void testCzech() throws Exception { + CharSequence cs; + Resources res = resourcesForLanguage("cs"); + + cs = res.getQuantityText(R.plurals.plurals_test, 0); + Log.d(TAG, "czech 0 cs=" + cs); + Assert.assertEquals(cs.toString(), "Some Czech dogs"); + + cs = res.getQuantityText(R.plurals.plurals_test, 1); + Log.d(TAG, "czech 1 cs=" + cs); + Assert.assertEquals(cs.toString(), "A Czech dog"); + + cs = res.getQuantityText(R.plurals.plurals_test, 2); + Log.d(TAG, "czech 2 cs=" + cs); + Assert.assertEquals(cs.toString(), "Few Czech dogs"); + + cs = res.getQuantityText(R.plurals.plurals_test, 5); + Assert.assertEquals(cs.toString(), "Some Czech dogs"); + + cs = res.getQuantityText(R.plurals.plurals_test, 500); + Assert.assertEquals(cs.toString(), "Some Czech dogs"); + } +} diff --git a/tests/AndroidTests/src/com/android/unit_tests/content/PrimitiveTest.java b/tests/AndroidTests/src/com/android/unit_tests/content/PrimitiveTest.java new file mode 100644 index 0000000..44098cc --- /dev/null +++ b/tests/AndroidTests/src/com/android/unit_tests/content/PrimitiveTest.java @@ -0,0 +1,141 @@ +/* + * 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.unit_tests.content; + +import android.content.res.Resources; +import android.content.res.TypedArray; +import android.test.AndroidTestCase; +import android.test.suitebuilder.annotation.SmallTest; +import android.util.TypedValue; +import com.android.unit_tests.R; + +public class PrimitiveTest extends AndroidTestCase { + private Resources mResources; + + @Override + protected void setUp() throws Exception { + super.setUp(); + mResources = mContext.getResources(); + } + + private void tryEnum(int resid, int expected) { + TypedArray sa = + mContext.obtainStyledAttributes(resid, R.styleable.EnumStyle); + int value = sa.getInt(R.styleable.EnumStyle_testEnum, -1); + sa.recycle(); + + assertEquals("Expecting value " + expected + " got " + value + + ": in resource 0x" + Integer.toHexString(resid), + expected, value); + } + + @SmallTest + public void testEnum() throws Exception { + tryEnum(R.style.TestEnum1, 1); + tryEnum(R.style.TestEnum2, 2); + tryEnum(R.style.TestEnum10, 10); + tryEnum(R.style.TestEnum1_EmptyInherit, 1); + } + + private void tryFlag(int resid, int expected) { + TypedArray sa = + mContext.obtainStyledAttributes(resid, R.styleable.FlagStyle); + int value = sa.getInt(R.styleable.FlagStyle_testFlags, -1); + sa.recycle(); + + assertEquals("Expecting value " + expected + " got " + value + + ": in resource 0x" + Integer.toHexString(resid), + expected, value); + } + + @SmallTest + public void testFlags() throws Exception { + tryFlag(R.style.TestFlag1, 0x1); + tryFlag(R.style.TestFlag2, 0x2); + tryFlag(R.style.TestFlag31, 0x40000000); + tryFlag(R.style.TestFlag1And2, 0x3); + tryFlag(R.style.TestFlag1And2And31, 0x40000003); + } + + private void tryBoolean(int resid, boolean expected) { + TypedValue v = new TypedValue(); + mContext.getResources().getValue(resid, v, true); + assertEquals(TypedValue.TYPE_INT_BOOLEAN, v.type); + assertEquals("Expecting boolean value " + expected + " got " + v + + " from TypedValue: in resource 0x" + Integer.toHexString(resid), + expected, v.data != 0); + assertEquals("Expecting boolean value " + expected + " got " + v + + " from getBoolean(): in resource 0x" + Integer.toHexString(resid), + expected, mContext.getResources().getBoolean(resid)); + } + + @SmallTest + public void testBoolean() throws Exception { + tryBoolean(R.bool.trueRes, true); + tryBoolean(R.bool.falseRes, false); + } + + private void tryString(int resid, String expected) { + TypedValue v = new TypedValue(); + mContext.getResources().getValue(resid, v, true); + assertEquals(TypedValue.TYPE_STRING, v.type); + assertEquals("Expecting string value " + expected + " got " + v + + ": in resource 0x" + Integer.toHexString(resid), + expected, v.string); + } + + @SmallTest + public void testStringCoerce() throws Exception { + tryString(R.string.coerceIntegerToString, "100"); + tryString(R.string.coerceBooleanToString, "true"); + tryString(R.string.coerceColorToString, "#fff"); + tryString(R.string.coerceFloatToString, "100.0"); + tryString(R.string.coerceDimensionToString, "100px"); + tryString(R.string.coerceFractionToString, "100%"); + } + + private static void checkString(int resid, String actual, String expected) { + assertEquals("Expecting string value \"" + expected + "\" got \"" + + actual + "\" in resources 0x" + Integer.toHexString(resid), + expected, actual); + } + + @SmallTest + public void testFormattedString() throws Exception { + // Make sure the regular one doesn't format anything + checkString(R.string.formattedStringNone, + mResources.getString(R.string.formattedStringNone), + "Format[]"); + checkString(R.string.formattedStringOne, + mResources.getString(R.string.formattedStringOne), + "Format[%d]"); + checkString(R.string.formattedStringTwo, + mResources.getString(R.string.formattedStringTwo), + "Format[%3$d,%2$s]"); + // Make sure the formatted one works + checkString(R.string.formattedStringNone, + mResources.getString(R.string.formattedStringNone), + "Format[]"); + checkString(R.string.formattedStringOne, + mResources.getString(R.string.formattedStringOne, 42), + "Format[42]"); + checkString(R.string.formattedStringTwo, + mResources.getString(R.string.formattedStringTwo, "unused", "hi", 43), + "Format[43,hi]"); + } +} + diff --git a/tests/AndroidTests/src/com/android/unit_tests/content/RawResourceTest.java b/tests/AndroidTests/src/com/android/unit_tests/content/RawResourceTest.java new file mode 100644 index 0000000..1786dc4 --- /dev/null +++ b/tests/AndroidTests/src/com/android/unit_tests/content/RawResourceTest.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 com.android.unit_tests.content; + +import android.content.res.Resources; +import android.test.AndroidTestCase; +import android.test.suitebuilder.annotation.SmallTest; +import com.android.unit_tests.R; + +import java.io.InputStream; + +public class RawResourceTest extends AndroidTestCase { + private Resources mResources; + + @Override + protected void setUp() throws Exception { + super.setUp(); + mResources = mContext.getResources(); + } + + @SmallTest + public void testReadToEnd() throws Exception { + InputStream is = mResources.openRawResource(R.raw.text); + AssetTest.verifyTextAsset(is); + } +} diff --git a/tests/AndroidTests/src/com/android/unit_tests/content/ResourceNameTest.java b/tests/AndroidTests/src/com/android/unit_tests/content/ResourceNameTest.java new file mode 100644 index 0000000..2a56243 --- /dev/null +++ b/tests/AndroidTests/src/com/android/unit_tests/content/ResourceNameTest.java @@ -0,0 +1,61 @@ +/* + * 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.unit_tests.content; + +import android.content.res.Resources; +import android.test.AndroidTestCase; +import android.test.suitebuilder.annotation.SmallTest; + +import com.android.unit_tests.R; + +public class ResourceNameTest extends AndroidTestCase { + + @SmallTest + public void testGetResourceName() { + Resources res = mContext.getResources(); + + String fullName = res.getResourceName(R.configVarying.simple); + assertEquals("com.android.unit_tests:configVarying/simple", fullName); + + String packageName = res.getResourcePackageName(R.configVarying.simple); + assertEquals("com.android.unit_tests", packageName); + + String typeName = res.getResourceTypeName(R.configVarying.simple); + assertEquals("configVarying", typeName); + + String entryName = res.getResourceEntryName(R.configVarying.simple); + assertEquals("simple", entryName); + } + + @SmallTest + public void testGetResourceIdentifier() { + Resources res = mContext.getResources(); + int resid = res.getIdentifier( + "com.android.unit_tests:configVarying/simple", + null, null); + assertEquals(R.configVarying.simple, resid); + + resid = res.getIdentifier("configVarying/simple", null, + "com.android.unit_tests"); + assertEquals(R.configVarying.simple, resid); + + resid = res.getIdentifier("simple", "configVarying", + "com.android.unit_tests"); + assertEquals(R.configVarying.simple, resid); + } +} + diff --git a/tests/AndroidTests/src/com/android/unit_tests/content/ResourceTests.java b/tests/AndroidTests/src/com/android/unit_tests/content/ResourceTests.java new file mode 100644 index 0000000..943941e --- /dev/null +++ b/tests/AndroidTests/src/com/android/unit_tests/content/ResourceTests.java @@ -0,0 +1,33 @@ +/* + * 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.unit_tests.content; + +import junit.framework.TestSuite; + +public class ResourceTests { + public static TestSuite suite() { + TestSuite suite = new TestSuite(ResourceTests.class.getName()); + + suite.addTestSuite(FractionTest.class); + suite.addTestSuite(PrimitiveTest.class); + suite.addTestSuite(ArrayTest.class); + suite.addTestSuite(ConfigTest.class); + suite.addTestSuite(RawResourceTest.class); + suite.addTestSuite(ResourceNameTest.class); + return suite; + } +} diff --git a/tests/AndroidTests/src/com/android/unit_tests/graphics/BitmapTest.java b/tests/AndroidTests/src/com/android/unit_tests/graphics/BitmapTest.java new file mode 100644 index 0000000..e8001e3 --- /dev/null +++ b/tests/AndroidTests/src/com/android/unit_tests/graphics/BitmapTest.java @@ -0,0 +1,232 @@ +/* + * 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.unit_tests.graphics; + +import android.graphics.Bitmap; +import android.graphics.Color; +import android.test.suitebuilder.annotation.SmallTest; +import junit.framework.TestCase; + + +public class BitmapTest extends TestCase { + + @SmallTest + public void testBasic() throws Exception { + Bitmap bm1 = Bitmap.createBitmap(100, 200, Bitmap.Config.ARGB_8888); + Bitmap bm2 = Bitmap.createBitmap(100, 200, Bitmap.Config.RGB_565); + Bitmap bm3 = Bitmap.createBitmap(100, 200, Bitmap.Config.ARGB_4444); + + assertTrue("mutability", bm1.isMutable()); + assertTrue("mutability", bm2.isMutable()); + assertTrue("mutability", bm3.isMutable()); + + assertEquals("width", 100, bm1.getWidth()); + assertEquals("width", 100, bm2.getWidth()); + assertEquals("width", 100, bm3.getWidth()); + + assertEquals("rowbytes", 400, bm1.getRowBytes()); + assertEquals("rowbytes", 200, bm2.getRowBytes()); + assertEquals("rowbytes", 200, bm3.getRowBytes()); + + assertEquals("height", 200, bm1.getHeight()); + assertEquals("height", 200, bm2.getHeight()); + assertEquals("height", 200, bm3.getHeight()); + + assertTrue("hasAlpha", bm1.hasAlpha()); + assertFalse("hasAlpha", bm2.hasAlpha()); + assertTrue("hasAlpha", bm3.hasAlpha()); + + assertTrue("getConfig", bm1.getConfig() == Bitmap.Config.ARGB_8888); + assertTrue("getConfig", bm2.getConfig() == Bitmap.Config.RGB_565); + assertTrue("getConfig", bm3.getConfig() == Bitmap.Config.ARGB_4444); + } + + @SmallTest + public void testMutability() throws Exception { + Bitmap bm1 = Bitmap.createBitmap(100, 200, Bitmap.Config.ARGB_8888); + Bitmap bm2 = Bitmap.createBitmap(new int[100 * 200], 100, 200, + Bitmap.Config.ARGB_8888); + + assertTrue("mutability", bm1.isMutable()); + assertFalse("mutability", bm2.isMutable()); + + bm1.eraseColor(0); + + try { + bm2.eraseColor(0); + fail("eraseColor should throw exception"); + } catch (IllegalStateException ex) { + // safe to catch and ignore this + } + } + + @SmallTest + public void testGetPixelsWithAlpha() throws Exception { + int[] colors = new int[100]; + for (int i = 0; i < 100; i++) { + colors[i] = (0xFF << 24) | (i << 16) | (i << 8) | i; + } + + Bitmap bm = Bitmap.createBitmap(colors, 10, 10, + Bitmap.Config.ARGB_8888); + + int[] pixels = new int[100]; + bm.getPixels(pixels, 0, 10, 0, 0, 10, 10); + for (int i = 0; i < 100; i++) { + int p = bm.getPixel(i % 10, i / 10); + assertEquals("getPixels", p, pixels[i]); + } + + for (int i = 0; i < 100; i++) { + int p = bm.getPixel(i % 10, i / 10); + assertEquals("getPixel", p, colors[i]); + assertEquals("pixel value", p, + ((0xFF << 24) | (i << 16) | (i << 8) | i)); + } + + } + + @SmallTest + public void testGetPixelsWithoutAlpha() throws Exception { + int[] colors = new int[100]; + for (int i = 0; i < 100; i++) { + colors[i] = (0xFF << 24) | (i << 16) | (i << 8) | i; + } + + Bitmap bm = Bitmap.createBitmap(colors, 10, 10, Bitmap.Config.RGB_565); + + int[] pixels = new int[100]; + bm.getPixels(pixels, 0, 10, 0, 0, 10, 10); + for (int i = 0; i < 100; i++) { + int p = bm.getPixel(i % 10, i / 10); + assertEquals("getPixels", p, pixels[i]); + } + } + + @SmallTest + public void testSetPixelsWithAlpha() throws Exception { + int[] colors = new int[100]; + for (int i = 0; i < 100; i++) { + colors[i] = (0xFF << 24) | (i << 16) | (i << 8) | i; + } + + Bitmap.Config config = Bitmap.Config.ARGB_8888; + Bitmap bm1 = Bitmap.createBitmap(colors, 10, 10, config); + Bitmap bm2 = Bitmap.createBitmap(10, 10, config); + + for (int i = 0; i < 100; i++) { + bm2.setPixel(i % 10, i / 10, colors[i]); + } + + for (int i = 0; i < 100; i++) { + assertEquals("setPixel", + bm1.getPixel(i % 10, i / 10), bm2.getPixel(i % 10, i / 10)); + } + + for (int i = 0; i < 100; i++) { + assertEquals("setPixel value", + bm1.getPixel(i % 10, i / 10), colors[i]); + } + } + + @SmallTest + public void testSetPixelsWithoutAlpha() throws Exception { + int[] colors = new int[100]; + for (int i = 0; i < 100; i++) { + colors[i] = (0xFF << 24) | (i << 16) | (i << 8) | i; + } + + Bitmap.Config config = Bitmap.Config.RGB_565; + Bitmap bm1 = Bitmap.createBitmap(colors, 10, 10, config); + Bitmap bm2 = Bitmap.createBitmap(10, 10, config); + + for (int i = 0; i < 100; i++) { + bm2.setPixel(i % 10, i / 10, colors[i]); + } + + for (int i = 0; i < 100; i++) { + assertEquals("setPixel", bm1.getPixel(i % 10, i / 10), + bm2.getPixel(i % 10, i / 10)); + } + } + + private static int computePrePostMul(int alpha, int comp) { + if (alpha == 0) { + return 0; + } + int premul = Math.round(alpha * comp / 255.f); + int unpre = Math.round(255.0f * premul / alpha); + return unpre; + } + + @SmallTest + public void testSetPixelsWithNonOpaqueAlpha() throws Exception { + int[] colors = new int[256]; + for (int i = 0; i < 256; i++) { + colors[i] = (i << 24) | (0xFF << 16) | (0x80 << 8) | 0; + } + + Bitmap.Config config = Bitmap.Config.ARGB_8888; + + // create a bitmap with the color array specified + Bitmap bm1 = Bitmap.createBitmap(colors, 16, 16, config); + + // create a bitmap with no colors, but then call setPixels + Bitmap bm2 = Bitmap.createBitmap(16, 16, config); + bm2.setPixels(colors, 0, 16, 0, 0, 16, 16); + + // now check that we did a good job returning the unpremultiplied alpha + final int tolerance = 1; + for (int i = 0; i < 256; i++) { + int c0 = colors[i]; + int c1 = bm1.getPixel(i % 16, i / 16); + int c2 = bm2.getPixel(i % 16, i / 16); + + // these two should always be identical + assertEquals("getPixel", c1, c2); + + // comparing the original (c0) with the returned color is tricky, + // since it gets premultiplied during the set(), and unpremultiplied + // by the get(). + int a0 = Color.alpha(c0); + int a1 = Color.alpha(c1); + assertEquals("alpha", a0, a1); + + int r0 = Color.red(c0); + int r1 = Color.red(c1); + int rr = computePrePostMul(a0, r0); + assertTrue("red", Math.abs(rr - r1) <= tolerance); + + int g0 = Color.green(c0); + int g1 = Color.green(c1); + int gg = computePrePostMul(a0, g0); + assertTrue("green", Math.abs(gg - g1) <= tolerance); + + int b0 = Color.blue(c0); + int b1 = Color.blue(c1); + int bb = computePrePostMul(a0, b0); + assertTrue("blue", Math.abs(bb - b1) <= tolerance); + + if (false) { + int cc = Color.argb(a0, rr, gg, bb); + android.util.Log.d("skia", "original " + Integer.toHexString(c0) + + " set+get " + Integer.toHexString(c1) + + " local " + Integer.toHexString(cc)); + } + } + } +} diff --git a/tests/AndroidTests/src/com/android/unit_tests/graphics/GraphicsTests.java b/tests/AndroidTests/src/com/android/unit_tests/graphics/GraphicsTests.java new file mode 100644 index 0000000..a8b6b9a --- /dev/null +++ b/tests/AndroidTests/src/com/android/unit_tests/graphics/GraphicsTests.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 com.android.unit_tests.graphics; + +import junit.framework.TestSuite; + +public class GraphicsTests { + public static TestSuite suite() { + TestSuite suite = new TestSuite(GraphicsTests.class.getName()); + + suite.addTestSuite(BitmapTest.class); + suite.addTestSuite(TypefaceTest.class); + return suite; + } +} diff --git a/tests/AndroidTests/src/com/android/unit_tests/graphics/TypefaceTest.java b/tests/AndroidTests/src/com/android/unit_tests/graphics/TypefaceTest.java new file mode 100644 index 0000000..5c40e6f --- /dev/null +++ b/tests/AndroidTests/src/com/android/unit_tests/graphics/TypefaceTest.java @@ -0,0 +1,91 @@ +/* + * Copyright (C) 2008 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.unit_tests.graphics; + +import android.graphics.Paint; +import android.graphics.Typeface; +import android.test.suitebuilder.annotation.MediumTest; +import android.test.suitebuilder.annotation.SmallTest; +import junit.framework.TestCase; + + +public class TypefaceTest extends TestCase { + + // create array of all std faces + private final Typeface[] mFaces = new Typeface[] { + Typeface.create(Typeface.SANS_SERIF, 0), + Typeface.create(Typeface.SANS_SERIF, 1), + Typeface.create(Typeface.SERIF, 0), + Typeface.create(Typeface.SERIF, 1), + Typeface.create(Typeface.SERIF, 2), + Typeface.create(Typeface.SERIF, 3), + Typeface.create(Typeface.MONOSPACE, 0) + }; + + @SmallTest + public void testBasic() throws Exception { + assertTrue("basic", Typeface.DEFAULT != null); + assertTrue("basic", Typeface.DEFAULT_BOLD != null); + assertTrue("basic", Typeface.SANS_SERIF != null); + assertTrue("basic", Typeface.SERIF != null); + assertTrue("basic", Typeface.MONOSPACE != null); + } + + @SmallTest + public void testUnique() throws Exception { + final int n = mFaces.length; + for (int i = 0; i < n; i++) { + for (int j = i + 1; j < n; j++) { + assertTrue("unique", mFaces[i] != mFaces[j]); + } + } + } + + @SmallTest + public void testStyles() throws Exception { + assertTrue("style", mFaces[0].getStyle() == Typeface.NORMAL); + assertTrue("style", mFaces[1].getStyle() == Typeface.BOLD); + assertTrue("style", mFaces[2].getStyle() == Typeface.NORMAL); + assertTrue("style", mFaces[3].getStyle() == Typeface.BOLD); + assertTrue("style", mFaces[4].getStyle() == Typeface.ITALIC); + assertTrue("style", mFaces[5].getStyle() == Typeface.BOLD_ITALIC); + assertTrue("style", mFaces[6].getStyle() == Typeface.NORMAL); + } + + @MediumTest + public void testUniformY() throws Exception { + Paint p = new Paint(); + final int n = mFaces.length; + for (int i = 1; i <= 36; i++) { + p.setTextSize(i); + float ascent = 0; + float descent = 0; + for (int j = 0; j < n; j++) { + p.setTypeface(mFaces[j]); + Paint.FontMetrics fm = p.getFontMetrics(); + if (j == 0) { + ascent = fm.ascent; + descent = fm.descent; + } else { + assertTrue("fontMetrics", fm.ascent == ascent); + assertTrue("fontMetrics", fm.descent == descent); + } + } + } + } + +} diff --git a/tests/AndroidTests/src/com/android/unit_tests/os/AidlTest.aidl b/tests/AndroidTests/src/com/android/unit_tests/os/AidlTest.aidl new file mode 100644 index 0000000..62c75a5 --- /dev/null +++ b/tests/AndroidTests/src/com/android/unit_tests/os/AidlTest.aidl @@ -0,0 +1,20 @@ +/* //device/apps/AndroidTests/src/com.android.unit_tests/AidlTest.aidl +** +** 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 com.android.unit_tests.os; + +parcelable AidlTest.TestParcelable; diff --git a/tests/AndroidTests/src/com/android/unit_tests/os/AidlTest.java b/tests/AndroidTests/src/com/android/unit_tests/os/AidlTest.java new file mode 100644 index 0000000..52e666d --- /dev/null +++ b/tests/AndroidTests/src/com/android/unit_tests/os/AidlTest.java @@ -0,0 +1,422 @@ +/* + * 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.unit_tests.os; + +import android.os.IInterface; +import android.os.Parcel; +import android.os.Parcelable; +import android.test.suitebuilder.annotation.SmallTest; +import com.google.android.collect.Lists; +import junit.framework.TestCase; + +import java.util.List; + +public class AidlTest extends TestCase { + + private IAidlTest mRemote; + + @Override + protected void setUp() throws Exception { + super.setUp(); + AidlObject mLocal = new AidlObject(); + mRemote = IAidlTest.Stub.asInterface(mLocal); + } + + private static boolean check(TestParcelable p, int n, String s) { + return p.mAnInt == n && + ((s == null && p.mAString == null) || s.equals(p.mAString)); + } + + public static class TestParcelable implements Parcelable { + public int mAnInt; + public String mAString; + + public TestParcelable() { + } + + public TestParcelable(int i, String s) { + mAnInt = i; + mAString = s; + } + + public int describeContents() { + return 0; + } + + public void writeToParcel(Parcel parcel, int flags) { + parcel.writeInt(mAnInt); + parcel.writeString(mAString); + } + + public void readFromParcel(Parcel parcel) { + mAnInt = parcel.readInt(); + mAString = parcel.readString(); + } + + public static final Parcelable.Creator<TestParcelable> CREATOR + = new Parcelable.Creator<TestParcelable>() { + public TestParcelable createFromParcel(Parcel parcel) { + return new TestParcelable(parcel.readInt(), + parcel.readString()); + } + + public TestParcelable[] newArray(int size) { + return new TestParcelable[size]; + } + }; + + public String toString() { + return super.toString() + " {" + mAnInt + "/" + mAString + "}"; + } + } + + private static class AidlObject extends IAidlTest.Stub { + public IInterface queryLocalInterface(String descriptor) { + // overriding this to return null makes asInterface always + // generate a proxy + return null; + } + + public int intMethod(int a) { + return a; + } + + public TestParcelable parcelableIn(TestParcelable p) { + p.mAnInt++; + return p; + } + + public TestParcelable parcelableOut(TestParcelable p) { + p.mAnInt = 44; + return p; + } + + public TestParcelable parcelableInOut(TestParcelable p) { + p.mAnInt++; + return p; + } + + public TestParcelable listParcelableLonger(List<TestParcelable> list, int index) { + list.add(list.get(index)); + return list.get(index); + } + + public int listParcelableShorter(List<TestParcelable> list, int index) { + list.remove(index); + return list.size(); + } + + public boolean[] booleanArray(boolean[] a0, boolean[] a1, boolean[] a2) { + for (int i = 0; i < a0.length && i < a2.length; i++) { + a2[i] = a0[i]; + } + for (int i = 0; i < a0.length && i < a1.length; i++) { + a1[i] = a0[i]; + } + return a0; + } + + public char[] charArray(char[] a0, char[] a1, char[] a2) { + for (int i = 0; i < a0.length && i < a2.length; i++) { + a2[i] = a0[i]; + } + for (int i = 0; i < a0.length && i < a1.length; i++) { + a1[i] = a0[i]; + } + return a0; + } + + public int[] intArray(int[] a0, int[] a1, int[] a2) { + for (int i = 0; i < a0.length && i < a2.length; i++) { + a2[i] = a0[i]; + } + for (int i = 0; i < a0.length && i < a1.length; i++) { + a1[i] = a0[i]; + } + return a0; + } + + public long[] longArray(long[] a0, long[] a1, long[] a2) { + for (int i = 0; i < a0.length && i < a2.length; i++) { + a2[i] = a0[i]; + } + for (int i = 0; i < a0.length && i < a1.length; i++) { + a1[i] = a0[i]; + } + return a0; + } + + public float[] floatArray(float[] a0, float[] a1, float[] a2) { + for (int i = 0; i < a0.length && i < a2.length; i++) { + a2[i] = a0[i]; + } + for (int i = 0; i < a0.length && i < a1.length; i++) { + a1[i] = a0[i]; + } + return a0; + } + + public double[] doubleArray(double[] a0, double[] a1, double[] a2) { + for (int i = 0; i < a0.length && i < a2.length; i++) { + a2[i] = a0[i]; + } + for (int i = 0; i < a0.length && i < a1.length; i++) { + a1[i] = a0[i]; + } + return a0; + } + + public String[] stringArray(String[] a0, String[] a1, String[] a2) { + for (int i = 0; i < a0.length && i < a2.length; i++) { + a2[i] = a0[i]; + } + for (int i = 0; i < a0.length && i < a1.length; i++) { + a1[i] = a0[i]; + } + return a0; + } + + public TestParcelable[] parcelableArray(TestParcelable[] a0, + TestParcelable[] a1, TestParcelable[] a2) { + return null; + } + + public void voidSecurityException() { + throw new SecurityException("gotcha!"); + } + + public int intSecurityException() { + throw new SecurityException("gotcha!"); + } + } + + @SmallTest + public void testInt() throws Exception { + int result = mRemote.intMethod(42); + assertEquals(42, result); + } + + @SmallTest + public void testParcelableIn() throws Exception { + TestParcelable arg = new TestParcelable(43, "hi"); + TestParcelable result = mRemote.parcelableIn(arg); + assertNotSame(arg, result); + + assertEquals(43, arg.mAnInt); + assertEquals(44, result.mAnInt); + } + + @SmallTest + public void testParcelableOut() throws Exception { + TestParcelable arg = new TestParcelable(43, "hi"); + TestParcelable result = mRemote.parcelableOut(arg); + assertNotSame(arg, result); + assertEquals(44, arg.mAnInt); + } + + @SmallTest + public void testParcelableInOut() throws Exception { + TestParcelable arg = new TestParcelable(43, "hi"); + TestParcelable result = mRemote.parcelableInOut(arg); + assertNotSame(arg, result); + assertEquals(44, arg.mAnInt); + } + + @SmallTest + public void testListParcelableLonger() throws Exception { + List<TestParcelable> list = Lists.newArrayList(); + list.add(new TestParcelable(33, "asdf")); + list.add(new TestParcelable(34, "jkl;")); + + TestParcelable result = mRemote.listParcelableLonger(list, 1); + +// System.out.println("result=" + result); +// for (TestParcelable p : list) { +// System.out.println("longer: " + p); +// } + + assertEquals("jkl;", result.mAString); + assertEquals(34, result.mAnInt); + + assertEquals(3, list.size()); + assertTrue("out parameter 0: " + list.get(0), check(list.get(0), 33, "asdf")); + assertTrue("out parameter 1: " + list.get(1), check(list.get(1), 34, "jkl;")); + assertTrue("out parameter 2: " + list.get(2), check(list.get(2), 34, "jkl;")); + + assertNotSame(list.get(1), list.get(2)); + } + + @SmallTest + public void testListParcelableShorter() throws Exception { + List<TestParcelable> list = Lists.newArrayList(); + list.add(new TestParcelable(33, "asdf")); + list.add(new TestParcelable(34, "jkl;")); + list.add(new TestParcelable(35, "qwerty")); + + int result = mRemote.listParcelableShorter(list, 2); + +// System.out.println("result=" + result); +// for (TestParcelable p : list) { +// System.out.println("shorter: " + p); +// } + + assertEquals(2, result); + assertEquals(2, list.size()); + assertTrue("out parameter 0: " + list.get(0), check(list.get(0), 33, "asdf")); + assertTrue("out parameter 1: " + list.get(1), check(list.get(1), 34, "jkl;")); + + assertNotSame(list.get(0), list.get(1)); + } + + @SmallTest + public void testArrays() throws Exception { + // boolean + boolean[] b0 = new boolean[]{true}; + boolean[] b1 = new boolean[]{false, true}; + boolean[] b2 = new boolean[]{true, false, true}; + boolean[] br = mRemote.booleanArray(b0, b1, b2); + + assertEquals(1, br.length); + assertTrue(br[0]); + + assertTrue(b1[0]); + assertFalse(b1[1]); + + assertTrue(b2[0]); + assertFalse(b2[1]); + assertTrue(b2[2]); + + // char + char[] c0 = new char[]{'a'}; + char[] c1 = new char[]{'b', 'c'}; + char[] c2 = new char[]{'d', 'e', 'f'}; + char[] cr = mRemote.charArray(c0, c1, c2); + + assertEquals(1, cr.length); + assertEquals('a', cr[0]); + + assertEquals('a', c1[0]); + assertEquals('\0', c1[1]); + + assertEquals('a', c2[0]); + assertEquals('e', c2[1]); + assertEquals('f', c2[2]); + + // int + int[] i0 = new int[]{34}; + int[] i1 = new int[]{38, 39}; + int[] i2 = new int[]{42, 43, 44}; + int[] ir = mRemote.intArray(i0, i1, i2); + + assertEquals(1, ir.length); + assertEquals(34, ir[0]); + + assertEquals(34, i1[0]); + assertEquals(0, i1[1]); + + assertEquals(34, i2[0]); + assertEquals(43, i2[1]); + assertEquals(44, i2[2]); + + // long + long[] l0 = new long[]{50}; + long[] l1 = new long[]{51, 52}; + long[] l2 = new long[]{53, 54, 55}; + long[] lr = mRemote.longArray(l0, l1, l2); + + assertEquals(1, lr.length); + assertEquals(50, lr[0]); + + assertEquals(50, l1[0]); + assertEquals(0, l1[1]); + + assertEquals(50, l2[0]); + assertEquals(54, l2[1]); + assertEquals(55, l2[2]); + + // float + float[] f0 = new float[]{90.1f}; + float[] f1 = new float[]{90.2f, 90.3f}; + float[] f2 = new float[]{90.4f, 90.5f, 90.6f}; + float[] fr = mRemote.floatArray(f0, f1, f2); + + assertEquals(1, fr.length); + assertEquals(90.1f, fr[0]); + + assertEquals(90.1f, f1[0]); + assertEquals(0f, f1[1], 0.0f); + + assertEquals(90.1f, f2[0]); + assertEquals(90.5f, f2[1]); + assertEquals(90.6f, f2[2]); + + // double + double[] d0 = new double[]{100.1}; + double[] d1 = new double[]{100.2, 100.3}; + double[] d2 = new double[]{100.4, 100.5, 100.6}; + double[] dr = mRemote.doubleArray(d0, d1, d2); + + assertEquals(1, dr.length); + assertEquals(100.1, dr[0]); + + assertEquals(100.1, d1[0]); + assertEquals(0, d1[1], 0.0); + + assertEquals(100.1, d2[0]); + assertEquals(100.5, d2[1]); + assertEquals(100.6, d2[2]); + + // String + String[] s0 = new String[]{"s0[0]"}; + String[] s1 = new String[]{"s1[0]", "s1[1]"}; + String[] s2 = new String[]{"s2[0]", "s2[1]", "s2[2]"}; + String[] sr = mRemote.stringArray(s0, s1, s2); + + assertEquals(1, sr.length); + assertEquals("s0[0]", sr[0]); + + assertEquals("s0[0]", s1[0]); + assertNull(s1[1]); + + assertEquals("s0[0]", s2[0]); + assertEquals("s2[1]", s2[1]); + assertEquals("s2[2]", s2[2]); + } + + @SmallTest + public void testVoidSecurityException() throws Exception { + boolean good = false; + try { + mRemote.voidSecurityException(); + } catch (SecurityException e) { + good = true; + } + assertEquals(good, true); + } + + @SmallTest + public void testIntSecurityException() throws Exception { + boolean good = false; + try { + mRemote.intSecurityException(); + } catch (SecurityException e) { + good = true; + } + assertEquals(good, true); + } +} + diff --git a/tests/AndroidTests/src/com/android/unit_tests/os/BroadcasterTest.java b/tests/AndroidTests/src/com/android/unit_tests/os/BroadcasterTest.java new file mode 100644 index 0000000..0df1653 --- /dev/null +++ b/tests/AndroidTests/src/com/android/unit_tests/os/BroadcasterTest.java @@ -0,0 +1,232 @@ +/* + * 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.unit_tests.os; + +import android.os.Broadcaster; +import android.os.Handler; +import android.os.Message; +import android.test.suitebuilder.annotation.MediumTest; +import android.test.suitebuilder.annotation.SmallTest; +import junit.framework.TestCase; + +public class BroadcasterTest extends TestCase { + private static final int MESSAGE_A = 23234; + private static final int MESSAGE_B = 3; + private static final int MESSAGE_C = 14; + private static final int MESSAGE_D = 95; + + @MediumTest + public void test1() throws Exception { + /* + * One handler requestes one message, with a translation + */ + HandlerTester tester = new HandlerTester() { + Handler h; + + public void go() { + Broadcaster b = new Broadcaster(); + h = new H(); + + b.request(MESSAGE_A, h, MESSAGE_B); + + Message msg = new Message(); + msg.what = MESSAGE_A; + + b.broadcast(msg); + } + + public void handleMessage(Message msg) { + if (msg.what == MESSAGE_B) { + success(); + } else { + failure(); + } + } + }; + tester.doTest(1000); + } + + private static class Tests2and3 extends HandlerTester { + Tests2and3(int n) { + N = n; + } + + int N; + Handler mHandlers[]; + boolean mSuccess[]; + + public void go() { + Broadcaster b = new Broadcaster(); + mHandlers = new Handler[N]; + mSuccess = new boolean[N]; + for (int i = 0; i < N; i++) { + mHandlers[i] = new H(); + mSuccess[i] = false; + b.request(MESSAGE_A, mHandlers[i], MESSAGE_B + i); + } + + Message msg = new Message(); + msg.what = MESSAGE_A; + + b.broadcast(msg); + } + + public void handleMessage(Message msg) { + int index = msg.what - MESSAGE_B; + if (index < 0 || index >= N) { + failure(); + } else { + if (msg.getTarget() == mHandlers[index]) { + mSuccess[index] = true; + } + } + boolean winner = true; + for (int i = 0; i < N; i++) { + if (!mSuccess[i]) { + winner = false; + } + } + if (winner) { + success(); + } + } + } + + @MediumTest + public void test2() throws Exception { + /* + * 2 handlers request the same message, with different translations + */ + HandlerTester tester = new Tests2and3(2); + tester.doTest(1000); + } + + @MediumTest + public void test3() throws Exception { + /* + * 1000 handlers request the same message, with different translations + */ + HandlerTester tester = new Tests2and3(10); + tester.doTest(1000); + } + + @MediumTest + public void test4() throws Exception { + /* + * Two handlers request different messages, with translations, sending + * only one. The other one should never get sent. + */ + HandlerTester tester = new HandlerTester() { + Handler h1; + Handler h2; + + public void go() { + Broadcaster b = new Broadcaster(); + h1 = new H(); + h2 = new H(); + + b.request(MESSAGE_A, h1, MESSAGE_C); + b.request(MESSAGE_B, h2, MESSAGE_D); + + Message msg = new Message(); + msg.what = MESSAGE_A; + + b.broadcast(msg); + } + + public void handleMessage(Message msg) { + if (msg.what == MESSAGE_C && msg.getTarget() == h1) { + success(); + } else { + failure(); + } + } + }; + tester.doTest(1000); + } + + @MediumTest + public void test5() throws Exception { + /* + * Two handlers request different messages, with translations, sending + * only one. The other one should never get sent. + */ + HandlerTester tester = new HandlerTester() { + Handler h1; + Handler h2; + + public void go() { + Broadcaster b = new Broadcaster(); + h1 = new H(); + h2 = new H(); + + b.request(MESSAGE_A, h1, MESSAGE_C); + b.request(MESSAGE_B, h2, MESSAGE_D); + + Message msg = new Message(); + msg.what = MESSAGE_B; + + b.broadcast(msg); + } + + public void handleMessage(Message msg) { + if (msg.what == MESSAGE_D && msg.getTarget() == h2) { + success(); + } else { + failure(); + } + } + }; + tester.doTest(1000); + } + + @MediumTest + public void test6() throws Exception { + /* + * Two handlers request same message. Cancel the request for the + * 2nd handler, make sure the first still works. + */ + HandlerTester tester = new HandlerTester() { + Handler h1; + Handler h2; + + public void go() { + Broadcaster b = new Broadcaster(); + h1 = new H(); + h2 = new H(); + + b.request(MESSAGE_A, h1, MESSAGE_C); + b.request(MESSAGE_A, h2, MESSAGE_D); + b.cancelRequest(MESSAGE_A, h2, MESSAGE_D); + + Message msg = new Message(); + msg.what = MESSAGE_A; + + b.broadcast(msg); + } + + public void handleMessage(Message msg) { + if (msg.what == MESSAGE_C && msg.getTarget() == h1) { + success(); + } else { + failure(); + } + } + }; + tester.doTest(1000); + } +} diff --git a/tests/AndroidTests/src/com/android/unit_tests/os/FileObserverTest.java b/tests/AndroidTests/src/com/android/unit_tests/os/FileObserverTest.java new file mode 100644 index 0000000..a504cd3 --- /dev/null +++ b/tests/AndroidTests/src/com/android/unit_tests/os/FileObserverTest.java @@ -0,0 +1,120 @@ +/* + * 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.unit_tests.os; + +import com.google.android.collect.Lists; +import com.google.android.collect.Maps; + +import android.os.FileObserver; +import android.test.AndroidTestCase; +import android.test.suitebuilder.annotation.LargeTest; +import android.util.Log; + +import java.io.File; +import java.io.FileOutputStream; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +public class FileObserverTest extends AndroidTestCase { + private Observer mObserver; + private File mTestFile; + + private static class Observer extends FileObserver { + public List<Map> events = Lists.newArrayList(); + public int totalEvents = 0; + + public Observer(String path) { + super(path); + } + + public void onEvent(int event, String path) { + synchronized (this) { + totalEvents++; + Map<String, Object> map = Maps.newHashMap(); + + map.put("event", event); + map.put("path", path); + + events.add(map); + + this.notifyAll(); + } + } + } + + @Override + protected void setUp() throws Exception { + mTestFile = File.createTempFile(".file_observer_test", ".txt"); + } + + @Override + protected void tearDown() throws Exception { + if (mTestFile != null && mTestFile.exists()) { + mTestFile.delete(); + } + } + + @LargeTest + public void testRun() throws Exception { + // make file changes and wait for them + assertTrue(mTestFile.exists()); + assertNotNull(mTestFile.getParent()); + + mObserver = new Observer(mTestFile.getParent()); + mObserver.startWatching(); + + FileOutputStream out = new FileOutputStream(mTestFile); + try { + out.write(0x20); + waitForEvent(); // open + waitForEvent(); // modify + + mTestFile.delete(); + waitForEvent(); // delete + + mObserver.stopWatching(); + + // Ensure that we have seen at least 3 events. + assertTrue(mObserver.totalEvents > 3); + } finally { + out.close(); + } + } + + private void waitForEvent() { + synchronized (mObserver) { + boolean done = false; + while (!done) { + try { + mObserver.wait(2000); + done = true; + } catch (InterruptedException e) { + } + } + + Iterator<Map> it = mObserver.events.iterator(); + + while (it.hasNext()) { + Map map = it.next(); + Log.i("FileObserverTest", "event: " + map.get("event").toString() + " path: " + map.get("path")); + } + + mObserver.events.clear(); + } + } +} diff --git a/tests/AndroidTests/src/com/android/unit_tests/os/FileUtilsTest.java b/tests/AndroidTests/src/com/android/unit_tests/os/FileUtilsTest.java new file mode 100644 index 0000000..f2c9293 --- /dev/null +++ b/tests/AndroidTests/src/com/android/unit_tests/os/FileUtilsTest.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 com.android.unit_tests.os; + +import android.content.Context; +import android.os.FileUtils; +import android.os.FileUtils.FileStatus; +import android.test.AndroidTestCase; +import android.test.suitebuilder.annotation.LargeTest; +import android.test.suitebuilder.annotation.MediumTest; +import android.test.suitebuilder.annotation.SmallTest; + +import java.io.ByteArrayInputStream; +import java.io.File; +import java.io.FileWriter; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; + +import junit.framework.Assert; + +public class FileUtilsTest extends AndroidTestCase { + private static final String TEST_DATA = + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; + + private File mTestFile; + private File mCopyFile; + + @Override + protected void setUp() throws Exception { + super.setUp(); + File testDir = getContext().getDir("testing", Context.MODE_PRIVATE); + mTestFile = new File(testDir, "test.file"); + mCopyFile = new File(testDir, "copy.file"); + FileWriter writer = new FileWriter(mTestFile); + try { + writer.write(TEST_DATA, 0, TEST_DATA.length()); + } finally { + writer.close(); + } + } + + @Override + protected void tearDown() throws Exception { + if (mTestFile.exists()) mTestFile.delete(); + if (mCopyFile.exists()) mCopyFile.delete(); + } + + @LargeTest + public void testGetFileStatus() { + final byte[] MAGIC = { 0xB, 0xE, 0x0, 0x5 }; + + try { + // truncate test file and write MAGIC (4 bytes) to it. + FileOutputStream os = new FileOutputStream(mTestFile, false); + os.write(MAGIC, 0, 4); + os.flush(); + os.close(); + } catch (FileNotFoundException e) { + Assert.fail("File was removed durning test" + e); + } catch (IOException e) { + Assert.fail("Unexpected IOException: " + e); + } + + Assert.assertTrue(mTestFile.exists()); + Assert.assertTrue(FileUtils.getFileStatus(mTestFile.getPath(), null)); + + FileStatus status1 = new FileStatus(); + FileUtils.getFileStatus(mTestFile.getPath(), status1); + + Assert.assertEquals(4, status1.size); + + // Sleep for at least one second so that the modification time will be different. + try { + Thread.sleep(1000); + } catch (InterruptedException e) { + } + + try { + // append so we don't change the creation time. + FileOutputStream os = new FileOutputStream(mTestFile, true); + os.write(MAGIC, 0, 4); + os.flush(); + os.close(); + } catch (FileNotFoundException e) { + Assert.fail("File was removed durning test" + e); + } catch (IOException e) { + Assert.fail("Unexpected IOException: " + e); + } + + FileStatus status2 = new FileStatus(); + FileUtils.getFileStatus(mTestFile.getPath(), status2); + + Assert.assertEquals(8, status2.size); + Assert.assertTrue(status2.mtime > status1.mtime); + + mTestFile.delete(); + + Assert.assertFalse(mTestFile.exists()); + Assert.assertFalse(FileUtils.getFileStatus(mTestFile.getPath(), null)); + } + + // TODO: test setPermissions(), getPermissions() + + @MediumTest + public void testCopyFile() throws Exception { + assertFalse(mCopyFile.exists()); + FileUtils.copyFile(mTestFile, mCopyFile); + assertTrue(mCopyFile.exists()); + assertEquals(TEST_DATA, FileUtils.readTextFile(mCopyFile, 0, null)); + } + + @MediumTest + public void testCopyToFile() throws Exception { + final String s = "Foo Bar"; + assertFalse(mCopyFile.exists()); + FileUtils.copyToFile(new ByteArrayInputStream(s.getBytes()), mCopyFile); assertTrue(mCopyFile.exists()); + assertEquals(s, FileUtils.readTextFile(mCopyFile, 0, null)); + } + + @MediumTest + public void testIsFilenameSafe() throws Exception { + assertTrue(FileUtils.isFilenameSafe(new File("foobar"))); + assertTrue(FileUtils.isFilenameSafe(new File("a_b-c=d.e/0,1+23"))); + assertFalse(FileUtils.isFilenameSafe(new File("foo*bar"))); + assertFalse(FileUtils.isFilenameSafe(new File("foo\nbar"))); + } + + @MediumTest + public void testReadTextFile() throws Exception { + assertEquals(TEST_DATA, FileUtils.readTextFile(mTestFile, 0, null)); + + assertEquals("ABCDE", FileUtils.readTextFile(mTestFile, 5, null)); + assertEquals("ABCDE<>", FileUtils.readTextFile(mTestFile, 5, "<>")); + assertEquals(TEST_DATA.substring(0, 51) + "<>", + FileUtils.readTextFile(mTestFile, 51, "<>")); + assertEquals(TEST_DATA, FileUtils.readTextFile(mTestFile, 52, "<>")); + assertEquals(TEST_DATA, FileUtils.readTextFile(mTestFile, 100, "<>")); + + assertEquals("vwxyz", FileUtils.readTextFile(mTestFile, -5, null)); + assertEquals("<>vwxyz", FileUtils.readTextFile(mTestFile, -5, "<>")); + assertEquals("<>" + TEST_DATA.substring(1, 52), + FileUtils.readTextFile(mTestFile, -51, "<>")); + assertEquals(TEST_DATA, FileUtils.readTextFile(mTestFile, -52, "<>")); + assertEquals(TEST_DATA, FileUtils.readTextFile(mTestFile, -100, "<>")); + } + + @MediumTest + public void testReadTextFileWithZeroLengthFile() throws Exception { + new FileOutputStream(mTestFile).close(); // Zero out the file + assertEquals("", FileUtils.readTextFile(mTestFile, 0, null)); + assertEquals("", FileUtils.readTextFile(mTestFile, 1, "<>")); + assertEquals("", FileUtils.readTextFile(mTestFile, 10, "<>")); + assertEquals("", FileUtils.readTextFile(mTestFile, -1, "<>")); + assertEquals("", FileUtils.readTextFile(mTestFile, -10, "<>")); + } +} diff --git a/tests/AndroidTests/src/com/android/unit_tests/os/HandlerStateMachineTest.java b/tests/AndroidTests/src/com/android/unit_tests/os/HandlerStateMachineTest.java new file mode 100644 index 0000000..29045a3 --- /dev/null +++ b/tests/AndroidTests/src/com/android/unit_tests/os/HandlerStateMachineTest.java @@ -0,0 +1,119 @@ +/* + * 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.unit_tests.os; + +import junit.framework.TestCase; +import java.util.Vector; + +import android.os.Handler; +import android.os.HandlerState; +import android.os.HandlerStateMachine; +import android.os.HandlerThread; +import android.os.Looper; +import android.os.Process; +import android.os.Message; +import android.test.suitebuilder.annotation.MediumTest; +import android.test.suitebuilder.annotation.SmallTest; + +import android.util.Log; + +public class HandlerStateMachineTest extends TestCase { + private static final int TEST_WHAT_1 = 1; + private static final int TEST_WHAT_2 = 2; + + private static final boolean DBG = false; + private static final String TAG = "HandlerStateMachineTest"; + + private boolean mDidEnter = false; + private boolean mDidExit = false; + private Vector<Integer> mGotMessagesWhat = new Vector<Integer>(); + + /** + * This test statemachine has two states, it receives + * two messages in state mS1 deferring them until what == TEST_WHAT_2 + * and then transitions to state mS2. State mS2 should then receive + * both of the deferred messages first TEST_WHAT_1 and then TEST_WHAT_2. + * When TEST_WHAT_2 is received it invokes notifyAll so the test can + * conclude. + */ + class StateMachine1 extends HandlerStateMachine { + StateMachine1(String name) { + super(name); + mThisSm = this; + setDbg(DBG); + setInitialState(mS1); + } + + class S1 extends HandlerState { + @Override public void enter(Message message) { + mDidEnter = true; + } + + @Override public void processMessage(Message message) { + deferMessage(message); + if (message.what == TEST_WHAT_2) { + transitionTo(mS2); + } + } + + @Override public void exit(Message message) { + mDidExit = true; + } + } + + class S2 extends HandlerState { + @Override public void processMessage(Message message) { + mGotMessagesWhat.add(message.what); + if (message.what == TEST_WHAT_2) { + synchronized (mThisSm) { + mThisSm.notifyAll(); + } + } + } + } + + private StateMachine1 mThisSm; + private S1 mS1 = new S1(); + private S2 mS2 = new S2(); + } + + @SmallTest + public void testStateMachine1() throws Exception { + StateMachine1 sm1 = new StateMachine1("sm1"); + if (sm1.isDbg()) Log.d(TAG, "testStateMachine1 E"); + + synchronized (sm1) { + // Send two messages + sm1.sendMessage(sm1.obtainMessage(TEST_WHAT_1)); + sm1.sendMessage(sm1.obtainMessage(TEST_WHAT_2)); + + try { + // wait for the messages to be handled + sm1.wait(); + } catch (InterruptedException e) { + Log.e(TAG, "testStateMachine1: exception while waiting " + e.getMessage()); + } + } + + assertTrue(mDidEnter); + assertTrue(mDidExit); + assertTrue(mGotMessagesWhat.size() == 2); + assertTrue(mGotMessagesWhat.get(0) == TEST_WHAT_1); + assertTrue(mGotMessagesWhat.get(1) == TEST_WHAT_2); + if (sm1.isDbg()) Log.d(TAG, "testStateMachine1 X"); + } +} diff --git a/tests/AndroidTests/src/com/android/unit_tests/os/HandlerTester.java b/tests/AndroidTests/src/com/android/unit_tests/os/HandlerTester.java new file mode 100644 index 0000000..303245f --- /dev/null +++ b/tests/AndroidTests/src/com/android/unit_tests/os/HandlerTester.java @@ -0,0 +1,89 @@ +/* + * 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.unit_tests.os; + +import android.os.Handler; +import android.os.Looper; +import android.os.Message; + +public abstract class HandlerTester extends Thread { + public abstract void go(); + public abstract void handleMessage(Message msg); + + public HandlerTester() { + } + + public void doTest(long timeout) { + start(); + + synchronized (this) { + try { + wait(timeout); + quit(); + } + catch (InterruptedException e) { + } + } + + if (!mDone) { + throw new RuntimeException("test timed out"); + } + if (!mSuccess) { + throw new RuntimeException("test failed"); + } + } + + public void success() { + mDone = true; + mSuccess = true; + } + + public void failure() { + mDone = true; + mSuccess = false; + } + + public void run() { + Looper.prepare(); + mLooper = Looper.myLooper(); + go(); + Looper.loop(); + } + + protected class H extends Handler { + public void handleMessage(Message msg) { + synchronized (HandlerTester.this) { + // Call into them with our monitor locked, so they don't have + // to deal with other races. + HandlerTester.this.handleMessage(msg); + if (mDone) { + HandlerTester.this.notify(); + quit(); + } + } + } + } + + private void quit() { + mLooper.quit(); + } + + private boolean mDone = false; + private boolean mSuccess = false; + private Looper mLooper; +} + diff --git a/tests/AndroidTests/src/com/android/unit_tests/os/HandlerThreadTest.java b/tests/AndroidTests/src/com/android/unit_tests/os/HandlerThreadTest.java new file mode 100644 index 0000000..c62f94f --- /dev/null +++ b/tests/AndroidTests/src/com/android/unit_tests/os/HandlerThreadTest.java @@ -0,0 +1,90 @@ +/* + * 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.unit_tests.os; + +import junit.framework.TestCase; +import android.os.Handler; +import android.os.HandlerThread; +import android.os.Message; +import android.os.Process; +import android.test.suitebuilder.annotation.MediumTest; +import android.test.suitebuilder.annotation.SmallTest; + +public class HandlerThreadTest extends TestCase { + private static final int TEST_WHAT = 1; + + private boolean mGotMessage = false; + private int mGotMessageWhat = -1; + private volatile boolean mDidSetup = false; + private volatile int mLooperTid = -1; + + @MediumTest + public void testHandlerThread() throws Exception { + HandlerThread th1 = new HandlerThread("HandlerThreadTest") { + protected void onLooperPrepared() { + mDidSetup = true; + mLooperTid = Process.myTid(); + } + }; + + assertFalse(th1.isAlive()); + assertNull(th1.getLooper()); + + th1.start(); + + assertTrue(th1.isAlive()); + assertNotNull(th1.getLooper()); + + /* + * Since getLooper() will block until the HandlerThread is setup, we are guaranteed + * that mDidSetup and mLooperTid will have been initalized. If they have not, then + * this test should fail + */ + // Make sure that the onLooperPrepared() was called on a different thread. + assertNotSame(Process.myTid(), mLooperTid); + assertTrue(mDidSetup); + + final Handler h1 = new Handler(th1.getLooper()) { + public void handleMessage(Message msg) { + assertEquals(TEST_WHAT, msg.what); + // Ensure that we are running on the same thread in which the looper was setup on. + assertEquals(mLooperTid, Process.myTid()); + + mGotMessageWhat = msg.what; + mGotMessage = true; + synchronized(this) { + notifyAll(); + } + } + }; + + Message msg = h1.obtainMessage(TEST_WHAT); + + synchronized (h1) { + // wait until we have the lock before sending the message. + h1.sendMessage(msg); + try { + // wait for the message to be handled + h1.wait(); + } catch (InterruptedException e) { + } + } + + assertTrue(mGotMessage); + assertEquals(TEST_WHAT, mGotMessageWhat); + } +} diff --git a/tests/AndroidTests/src/com/android/unit_tests/os/IAidlTest.aidl b/tests/AndroidTests/src/com/android/unit_tests/os/IAidlTest.aidl new file mode 100644 index 0000000..94c39ff --- /dev/null +++ b/tests/AndroidTests/src/com/android/unit_tests/os/IAidlTest.aidl @@ -0,0 +1,47 @@ +/* //device/apps/AndroidTests/src/com.android.unit_tests/IAidlTest.aidl +** +** 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 com.android.unit_tests.os; + +import com.android.unit_tests.os.AidlTest; + +interface IAidlTest { + int intMethod(int a); + + AidlTest.TestParcelable parcelableIn(in AidlTest.TestParcelable p); + AidlTest.TestParcelable parcelableOut(out AidlTest.TestParcelable p); + AidlTest.TestParcelable parcelableInOut(inout AidlTest.TestParcelable p); + + AidlTest.TestParcelable listParcelableLonger( + inout List<AidlTest.TestParcelable> list, int index); + int listParcelableShorter( + inout List<AidlTest.TestParcelable> list, int index); + + boolean[] booleanArray(in boolean[] a0, out boolean[] a1, inout boolean[] a2); + char[] charArray(in char[] a0, out char[] a1, inout char[] a2); + int[] intArray(in int[] a0, out int[] a1, inout int[] a2); + long[] longArray(in long[] a0, out long[] a1, inout long[] a2); + float[] floatArray(in float[] a0, out float[] a1, inout float[] a2); + double[] doubleArray(in double[] a0, out double[] a1, inout double[] a2); + String[] stringArray(in String[] a0, out String[] a1, inout String[] a2); + AidlTest.TestParcelable[] parcelableArray(in AidlTest.TestParcelable[] a0, + out AidlTest.TestParcelable[] a1, + inout AidlTest.TestParcelable[] a2); + + void voidSecurityException(); + int intSecurityException(); +} diff --git a/tests/AndroidTests/src/com/android/unit_tests/os/IdleHandlerTest.java b/tests/AndroidTests/src/com/android/unit_tests/os/IdleHandlerTest.java new file mode 100644 index 0000000..fc3b007 --- /dev/null +++ b/tests/AndroidTests/src/com/android/unit_tests/os/IdleHandlerTest.java @@ -0,0 +1,199 @@ +/* + * 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.unit_tests.os; + +import android.os.Handler; +import android.os.Looper; +import android.os.Message; +import android.os.MessageQueue.IdleHandler; +import android.test.suitebuilder.annotation.MediumTest; +import junit.framework.TestCase; + +public class IdleHandlerTest extends TestCase { + + private static class BaseTestHandler extends TestHandlerThread { + Handler mHandler; + + public BaseTestHandler() { + } + + public void go() { + mHandler = new Handler() { + public void handleMessage(Message msg) { + BaseTestHandler.this.handleMessage(msg); + } + }; + } + + public void addIdleHandler() { + Looper.myQueue().addIdleHandler(new IdleHandler() { + public boolean queueIdle() { + return BaseTestHandler.this.queueIdle(); + } + }); + } + + public void handleMessage(Message msg) { + } + + public boolean queueIdle() { + return false; + } + } + + @MediumTest + public void testOneShotFirst() throws Exception { + TestHandlerThread tester = new BaseTestHandler() { + int mCount; + + public void go() { + super.go(); + mCount = 0; + mHandler.sendMessageDelayed(mHandler.obtainMessage(0), 100); + addIdleHandler(); + } + + public void handleMessage(Message msg) { + if (msg.what == 0) { + mHandler.sendMessageDelayed(mHandler.obtainMessage(1), 100); + } else if (msg.what == 1) { + if (mCount == 1) { + success(); + } else { + failure(new RuntimeException( + "Idle handler called " + mCount + " times")); + } + } + } + + public boolean queueIdle() { + mCount++; + return false; + } + }; + + tester.doTest(1000); + } + + @MediumTest + public void testOneShotLater() throws Exception { + TestHandlerThread tester = new BaseTestHandler() { + int mCount; + + public void go() { + super.go(); + mCount = 0; + mHandler.sendMessage(mHandler.obtainMessage(0)); + } + + public void handleMessage(Message msg) { + if (msg.what == 0) { + addIdleHandler(); + mHandler.sendMessageDelayed(mHandler.obtainMessage(1), 100); + } else if (msg.what == 1) { + mHandler.sendMessageDelayed(mHandler.obtainMessage(2), 100); + } else if (msg.what == 2) { + if (mCount == 1) { + success(); + } else { + failure(new RuntimeException( + "Idle handler called " + mCount + " times")); + } + } + } + + public boolean queueIdle() { + mCount++; + return false; + } + }; + + tester.doTest(1000); + } + + + @MediumTest + public void testRepeatedFirst() throws Exception { + TestHandlerThread tester = new BaseTestHandler() { + int mCount; + + public void go() { + super.go(); + mCount = 0; + mHandler.sendMessageDelayed(mHandler.obtainMessage(0), 100); + addIdleHandler(); + } + + public void handleMessage(Message msg) { + if (msg.what == 0) { + mHandler.sendMessageDelayed(mHandler.obtainMessage(1), 100); + } else if (msg.what == 1) { + if (mCount == 2) { + success(); + } else { + failure(new RuntimeException( + "Idle handler called " + mCount + " times")); + } + } + } + + public boolean queueIdle() { + mCount++; + return true; + } + }; + + tester.doTest(1000); + } + + @MediumTest + public void testRepeatedLater() throws Exception { + TestHandlerThread tester = new BaseTestHandler() { + int mCount; + + public void go() { + super.go(); + mCount = 0; + mHandler.sendMessage(mHandler.obtainMessage(0)); + } + + public void handleMessage(Message msg) { + if (msg.what == 0) { + addIdleHandler(); + mHandler.sendMessageDelayed(mHandler.obtainMessage(1), 100); + } else if (msg.what == 1) { + mHandler.sendMessageDelayed(mHandler.obtainMessage(2), 100); + } else if (msg.what == 2) { + if (mCount == 2) { + success(); + } else { + failure(new RuntimeException( + "Idle handler called " + mCount + " times")); + } + } + } + + public boolean queueIdle() { + mCount++; + return true; + } + }; + + tester.doTest(1000); + } +} + diff --git a/tests/AndroidTests/src/com/android/unit_tests/os/MemoryFileTest.java b/tests/AndroidTests/src/com/android/unit_tests/os/MemoryFileTest.java new file mode 100644 index 0000000..508afcf --- /dev/null +++ b/tests/AndroidTests/src/com/android/unit_tests/os/MemoryFileTest.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 com.android.unit_tests.os; + +import android.os.MemoryFile; +import android.test.suitebuilder.annotation.MediumTest; +import android.test.suitebuilder.annotation.SmallTest; +import junit.framework.TestCase; + +import java.io.InputStream; +import java.io.OutputStream; +import java.io.IOException; + +import java.util.List; +import java.util.ArrayList; + +public class MemoryFileTest extends TestCase { + + private void compareBuffers(byte[] buffer1, byte[] buffer2, int length) throws Exception { + for (int i = 0; i < length; i++) { + if (buffer1[i] != buffer2[i]) { + throw new Exception("readBytes did not read back what writeBytes wrote"); + } + } + } + + /** + * Keep allocating new files till the system purges them. + */ + @MediumTest + public void testPurge() throws Exception { + List<MemoryFile> files = new ArrayList<MemoryFile>(); + while (true) { + MemoryFile newFile = new MemoryFile("MemoryFileTest", 1000000); + newFile.allowPurging(true); + newFile.writeBytes(testString, 0, 0, testString.length); + files.add(newFile); + for (MemoryFile file : files) { + try { + file.readBytes(testString, 0, 0, testString.length); + } catch (IOException e) { + // Expected + for (MemoryFile fileToClose : files) { + fileToClose.close(); + } + return; + } + } + } + } + + @SmallTest + public void testRun() throws Exception { + MemoryFile file = new MemoryFile("MemoryFileTest", 1000000); + + byte[] buffer = new byte[testString.length]; + + // check low level accessors + file.writeBytes(testString, 0, 2000, testString.length); + file.readBytes(buffer, 2000, 0, testString.length); + compareBuffers(testString, buffer, testString.length); + + // check streams + buffer = new byte[testString.length]; + + OutputStream os = file.getOutputStream(); + os.write(testString); + + InputStream is = file.getInputStream(); + is.mark(testString.length); + is.read(buffer); + compareBuffers(testString, buffer, testString.length); + + // test mark/reset + buffer = new byte[testString.length]; + is.reset(); + is.read(buffer); + compareBuffers(testString, buffer, testString.length); + + file.close(); + } + + private static final byte[] testString = new byte[] { + 3, 1, 4, 1, 5, 9, 2, 6, 5, 3, 5, 8, 9, 7, 9, 3, 2, 3, 8, 4, 6, 2, 6, 4, 3, 3, 8, 3, 2, 7, 9, 5, 0, 2, 8, 8, 4, 1, 9, 7, 1, 6, 9, 3, 9, 9, 3, 7, 5, 1, 0, 5, 8, 2, 0, 9, 7, 4, 9, 4, 4, 5, 9, 2, 3, 0, 7, 8, 1, 6, 4, + 0, 6, 2, 8, 6, 2, 0, 8, 9, 9, 8, 6, 2, 8, 0, 3, 4, 8, 2, 5, 3, 4, 2, 1, 1, 7, 0, 6, 7, 9, 8, 2, 1, 4, 8, 0, 8, 6, 5, 1, 3, 2, 8, 2, 3, 0, 6, 6, 4, 7, 0, 9, 3, 8, 4, 4, 6, 0, 9, 5, 5, 0, 5, 8, 2, 2, 3, 1, 7, 2, + 5, 3, 5, 9, 4, 0, 8, 1, 2, 8, 4, 8, 1, 1, 1, 7, 4, 5, 0, 2, 8, 4, 1, 0, 2, 7, 0, 1, 9, 3, 8, 5, 2, 1, 1, 0, 5, 5, 5, 9, 6, 4, 4, 6, 2, 2, 9, 4, 8, 9, 5, 4, 9, 3, 0, 3, 8, 1, 9, 6, 4, 4, 2, 8, 8, 1, 0, 9, 7, 5, + 6, 6, 5, 9, 3, 3, 4, 4, 6, 1, 2, 8, 4, 7, 5, 6, 4, 8, 2, 3, 3, 7, 8, 6, 7, 8, 3, 1, 6, 5, 2, 7, 1, 2, 0, 1, 9, 0, 9, 1, 4, 5, 6, 4, 8, 5, 6, 6, 9, 2, 3, 4, 6, 0, 3, 4, 8, 6, 1, 0, 4, 5, 4, 3, 2, 6, 6, 4, 8, 2, + 1, 3, 3, 9, 3, 6, 0, 7, 2, 6, 0, 2, 4, 9, 1, 4, 1, 2, 7, 3, 7, 2, 4, 5, 8, 7, 0, 0, 6, 6, 0, 6, 3, 1, 5, 5, 8, 8, 1, 7, 4, 8, 8, 1, 5, 2, 0, 9, 2, 0, 9, 6, 2, 8, 2, 9, 2, 5, 4, 0, 9, 1, 7, 1, 5, 3, 6, 4, 3, 6, + 7, 8, 9, 2, 5, 9, 0, 3, 6, 0, 0, 1, 1, 3, 3, 0, 5, 3, 0, 5, 4, 8, 8, 2, 0, 4, 6, 6, 5, 2, 1, 3, 8, 4, 1, 4, 6, 9, 5, 1, 9, 4, 1, 5, 1, 1, 6, 0, 9, 4, 3, 3, 0, 5, 7, 2, 7, 0, 3, 6, 5, 7, 5, 9, 5, 9, 1, 9, 5, 3, + 0, 9, 2, 1, 8, 6, 1, 1, 7, 3, 8, 1, 9, 3, 2, 6, 1, 1, 7, 9, 3, 1, 0, 5, 1, 1, 8, 5, 4, 8, 0, 7, 4, 4, 6, 2, 3, 7, 9, 9, 6, 2, 7, 4, 9, 5, 6, 7, 3, 5, 1, 8, 8, 5, 7, 5, 2, 7, 2, 4, 8, 9, 1, 2, 2, 7, 9, 3, 8, 1, + 8, 3, 0, 1, 1, 9, 4, 9, 1, 2, 9, 8, 3, 3, 6, 7, 3, 3, 6, 2, 4, 4, 0, 6, 5, 6, 6, 4, 3, 0, 8, 6, 0, 2, 1, 3, 9, 4, 9, 4, 6, 3, 9, 5, 2, 2, 4, 7, 3, 7, 1, 9, 0, 7, 0, 2, 1, 7, 9, 8, 6, 0, 9, 4, 3, 7, 0, 2, 7, 7, + 0, 5, 3, 9, 2, 1, 7, 1, 7, 6, 2, 9, 3, 1, 7, 6, 7, 5, 2, 3, 8, 4, 6, 7, 4, 8, 1, 8, 4, 6, 7, 6, 6, 9, 4, 0, 5, 1, 3, 2, 0, 0, 0, 5, 6, 8, 1, 2, 7, 1, 4, 5, 2, 6, 3, 5, 6, 0, 8, 2, 7, 7, 8, 5, 7, 7, 1, 3, 4, 2, + 7, 5, 7, 7, 8, 9, 6, 0, 9, 1, 7, 3, 6, 3, 7, 1, 7, 8, 7, 2, 1, 4, 6, 8, 4, 4, 0, 9, 0, 1, 2, 2, 4, 9, 5, 3, 4, 3, 0, 1, 4, 6, 5, 4, 9, 5, 8, 5, 3, 7, 1, 0, 5, 0, 7, 9, 2, 2, 7, 9, 6, 8, 9, 2, 5, 8, 9, 2, 3, 5, + 4, 2, 0, 1, 9, 9, 5, 6, 1, 1, 2, 1, 2, 9, 0, 2, 1, 9, 6, 0, 8, 6, 4, 0, 3, 4, 4, 1, 8, 1, 5, 9, 8, 1, 3, 6, 2, 9, 7, 7, 4, 7, 7, 1, 3, 0, 9, 9, 6, 0, 5, 1, 8, 7, 0, 7, 2, 1, 1, 3, 4, 9, 9, 9, 9, 9, 9, 8, 3, 7, + 2, 9, 7, 8, 0, 4, 9, 9, 5, 1, 0, 5, 9, 7, 3, 1, 7, 3, 2, 8, 1, 6, 0, 9, 6, 3, 1, 8, 5, 9, 5, 0, 2, 4, 4, 5, 9, 4, 5, 5, 3, 4, 6, 9, 0, 8, 3, 0, 2, 6, 4, 2, 5, 2, 2, 3, 0, 8, 2, 5, 3, 3, 4, 4, 6, 8, 5, 0, 3, 5, + 2, 6, 1, 9, 3, 1, 1, 8, 8, 1, 7, 1, 0, 1, 0, 0, 0, 3, 1, 3, 7, 8, 3, 8, 7, 5, 2, 8, 8, 6, 5, 8, 7, 5, 3, 3, 2, 0, 8, 3, 8, 1, 4, 2, 0, 6, 1, 7, 1, 7, 7, 6, 6, 9, 1, 4, 7, 3, 0, 3, 5, 9, 8, 2, 5, 3, 4, 9, 0, 4, + 2, 8, 7, 5, 5, 4, 6, 8, 7, 3, 1, 1, 5, 9, 5, 6, 2, 8, 6, 3, 8, 8, 2, 3, 5, 3, 7, 8, 7, 5, 9, 3, 7, 5, 1, 9, 5, 7, 7, 8, 1, 8, 5, 7, 7, 8, 0, 5, 3, 2, 1, 7, 1, 2, 2, 6, 8, 0, 6, 6, 1, 3, 0, 0, 1, 9, 2, 7, 8, 7, + 6, 6, 1, 1, 1, 9, 5, 9, 0, 9, 2, 1, 6, 4, 2, 0, 1, 9, 8, 9, 3, 8, 0, 9, 5, 2, 5, 7, 2, 0, 1, 0, 6, 5, 4, 8, 5, 8, 6, 3, 2, 7, 8, 8, 6, 5, 9, 3, 6, 1, 5, 3, 3, 8, 1, 8, 2, 7, 9, 6, 8, 2, 3, 0, 3, 0, 1, 9, 5, 2, + 0, 3, 5, 3, 0, 1, 8, 5, 2, 9, 6, 8, 9, 9, 5, 7, 7, 3, 6, 2, 2, 5, 9, 9, 4, 1, 3, 8, 9, 1, 2, 4, 9, 7, 2, 1, 7, 7, 5, 2, 8, 3, 4, 7, 9, 1, 3, 1, 5, 1, 5, 5, 7, 4, 8, 5, 7, 2, 4, 2, 4, 5, 4, 1, 5, 0, 6, 9, 5, 9, + 5, 0, 8, 2, 9, 5, 3, 3, 1, 1, 6, 8, 6, 1, 7, 2, 7, 8, 5, 5, 8, 8, 9, 0, 7, 5, 0, 9, 8, 3, 8, 1, 7, 5, 4, 6, 3, 7, 4, 6, 4, 9, 3, 9, 3, 1, 9, 2, 5, 5, 0, 6, 0, 4, 0, 0, 9, 2, 7, 7, 0, 1, 6, 7, 1, 1, 3, 9, 0, 0, + 9, 8, 4, 8, 8, 2, 4, 0, 1, 2, 8, 5, 8, 3, 6, 1, 6, 0, 3, 5, 6, 3, 7, 0, 7, 6, 6, 0, 1, 0, 4, 7, 1, 0, 1, 8, 1, 9, 4, 2, 9, 5, 5, 5, 9, 6, 1, 9, 8, 9, 4, 6, 7, 6, 7, 8, 3, 7, 4, 4, 9, 4, 4, 8, 2, 5, 5, 3, 7, 9, + 7, 7, 4, 7, 2, 6, 8, 4, 7, 1, 0, 4, 0, 4, 7, 5, 3, 4, 6, 4, 6, 2, 0, 8, 0, 4, 6, 6, 8, 4, 2, 5, 9, 0, 6, 9, 4, 9, 1, 2, 9, 3, 3, 1, 3, 6, 7, 7, 0, 2, 8, 9, 8, 9, 1, 5, 2, 1, 0, 4, 7, 5, 2, 1, 6, 2, 0, 5, 6, 9, + 6, 6, 0, 2, 4, 0, 5, 8, 0, 3, 8, 1, 5, 0, 1, 9, 3, 5, 1, 1, 2, 5, 3, 3, 8, 2, 4, 3, 0, 0, 3, 5, 5, 8, 7, 6, 4, 0, 2, 4, 7, 4, 9, 6, 4, 7, 3, 2, 6, 3, 9, 1, 4, 1, 9, 9, 2, 7, 2, 6, 0, 4, 2, 6, 9, 9, 2, 2, 7, 9, + 6, 7, 8, 2, 3, 5, 4, 7, 8, 1, 6, 3, 6, 0, 0, 9, 3, 4, 1, 7, 2, 1, 6, 4, 1, 2, 1, 9, 9, 2, 4, 5, 8, 6, 3, 1, 5, 0, 3, 0, 2, 8, 6, 1, 8, 2, 9, 7, 4, 5, 5, 5, 7, 0, 6, 7, 4, 9, 8, 3, 8, 5, 0, 5, 4, 9, 4, 5, 8, 8, + 5, 8, 6, 9, 2, 6, 9, 9, 5, 6, 9, 0, 9, 2, 7, 2, 1, 0, 7, 9, 7, 5, 0, 9, 3, 0, 2, 9, 5, 5, 3, 2, 1, 1, 6, 5, 3, 4, 4, 9, 8, 7, 2, 0, 2, 7, 5, 5, 9, 6, 0, 2, 3, 6, 4, 8, 0, 6, 6, 5, 4, 9, 9, 1, 1, 9, 8, 8, 1, 8, + 3, 4, 7, 9, 7, 7, 5, 3, 5, 6, 6, 3, 6, 9, 8, 0, 7, 4, 2, 6, 5, 4, 2, 5, 2, 7, 8, 6, 2, 5, 5, 1, 8, 1, 8, 4, 1, 7, 5, 7, 4, 6, 7, 2, 8, 9, 0, 9, 7, 7, 7, 7, 2, 7, 9, 3, 8, 0, 0, 0, 8, 1, 6, 4, 7, 0, 6, 0, 0, 1, + 6, 1, 4, 5, 2, 4, 9, 1, 9, 2, 1, 7, 3, 2, 1, 7, 2, 1, 4, 7, 7, 2, 3, 5, 0, 1, 4, 1, 4, 4, 1, 9, 7, 3, 5, 6, 8, 5, 4, 8, 1, 6, 1, 3, 6, 1, 1, 5, 7, 3, 5, 2, 5, 5, 2, 1, 3, 3, 4, 7, 5, 7, 4, 1, 8, 4, 9, 4, 6, 8, + 4, 3, 8, 5, 2, 3, 3, 2, 3, 9, 0, 7, 3, 9, 4, 1, 4, 3, 3, 3, 4, 5, 4, 7, 7, 6, 2, 4, 1, 6, 8, 6, 2, 5, 1, 8, 9, 8, 3, 5, 6, 9, 4, 8, 5, 5, 6, 2, 0, 9, 9, 2, 1, 9, 2, 2, 2, 1, 8, 4, 2, 7, 2, 5, 5, 0, 2, 5, 4, 2, + 5, 6, 8, 8, 7, 6, 7, 1, 7, 9, 0, 4, 9, 4, 6, 0, 1, 6, 5, 3, 4, 6, 6, 8, 0, 4, 9, 8, 8, 6, 2, 7, 2, 3, 2, 7, 9, 1, 7, 8, 6, 0, 8, 5, 7, 8, 4, 3, 8, 3, 8, 2, 7, 9, 6, 7, 9, 7, 6, 6, 8, 1, 4, 5, 4, 1, 0, 0, 9, 5, + 3, 8, 8, 3, 7, 8, 6, 3, 6, 0, 9, 5, 0, 6, 8, 0, 0, 6, 4, 2, 2, 5, 1, 2, 5, 2, 0, 5, 1, 1, 7, 3, 9, 2, 9, 8, 4, 8, 9, 6, 0, 8, 4, 1, 2, 8, 4, 8, 8, 6, 2, 6, 9, 4, 5, 6, 0, 4, 2, 4, 1, 9, 6, 5, 2, 8, 5, 0, 2, 2, + 2, 1, 0, 6, 6, 1, 1, 8, 6, 3, 0, 6, 7, 4, 4, 2, 7, 8, 6, 2, 2, 0, 3, 9, 1, 9, 4, 9, 4, 5, 0, 4, 7, 1, 2, 3, 7, 1, 3, 7, 8, 6, 9, 6, 0, 9, 5, 6, 3, 6, 4, 3, 7, 1, 9, 1, 7, 2, 8, 7, 4, 6, 7, 7, 6, 4, 6, 5, 7, 5, + 7, 3, 9, 6, 2, 4, 1, 3, 8, 9, 0, 8, 6, 5, 8, 3, 2, 6, 4, 5, 9, 9, 5, 8, 1, 3, 3, 9, 0, 4, 7, 8, 0, 2, 7, 5, 9, 0, 0, 9, 9, 4, 6, 5, 7, 6, 4, 0, 7, 8, 9, 5, 1, 2, 6, 9, 4, 6, 8, 3, 9, 8, 3, 5, 2, 5, 9, 5, 7, 0, + 9, 8, 2, 5, 8, 2, 2, 6, 2, 0, 5, 2, 2, 4, 8, 9, 4, 0, 7, 7, 2, 6, 7, 1, 9, 4, 7, 8, 2, 6, 8, 4, 8, 2, 6, 0, 1, 4, 7, 6, 9, 9, 0, 9, 0, 2, 6, 4, 0, 1, 3, 6, 3, 9, 4, 4, 3, 7, 4, 5, 5, 3, 0, 5, 0, 6, 8, 2, 0, 3, + 4, 9, 6, 2, 5, 2, 4, 5, 1, 7, 4, 9, 3, 9, 9, 6, 5, 1, 4, 3, 1, 4, 2, 9, 8, 0, 9, 1, 9, 0, 6, 5, 9, 2, 5, 0, 9, 3, 7, 2, 2, 1, 6, 9, 6, 4, 6, 1, 5, 1, 5, 7, 0, 9, 8, 5, 8, 3, 8, 7, 4, 1, 0, 5, 9, 7, 8, 8, 5, 9, + 5, 9, 7, 7, 2, 9, 7, 5, 4, 9, 8, 9, 3, 0, 1, 6, 1, 7, 5, 3, 9, 2, 8, 4, 6, 8, 1, 3, 8, 2, 6, 8, 6, 8, 3, 8, 6, 8, 9, 4, 2, 7, 7, 4, 1, 5, 5, 9, 9, 1, 8, 5, 5, 9, 2, 5, 2, 4, 5, 9, 5, 3, 9, 5, 9, 4, 3, 1, 0, 4, + 9, 9, 7, 2, 5, 2, 4, 6, 8, 0, 8, 4, 5, 9, 8, 7, 2, 7, 3, 6, 4, 4, 6, 9, 5, 8, 4, 8, 6, 5, 3, 8, 3, 6, 7, 3, 6, 2, 2, 2, 6, 2, 6, 0, 9, 9, 1, 2, 4, 6, 0, 8, 0, 5, 1, 2, 4, 3, 8, 8, 4, 3, 9, 0, 4, 5, 1, 2, 4, 4, + 1, 3, 6, 5, 4, 9, 7, 6, 2, 7, 8, 0, 7, 9, 7, 7, 1, 5, 6, 9, 1, 4, 3, 5, 9, 9, 7, 7, 0, 0, 1, 2, 9, 6, 1, 6, 0, 8, 9, 4, 4, 1, 6, 9, 4, 8, 6, 8, 5, 5, 5, 8, 4, 8, 4, 0, 6, 3, 5, 3, 4, 2, 2, 0, 7, 2, 2, 2, 5, 8, + 2, 8, 4, 8, 8, 6, 4, 8, 1, 5, 8, 4, 5, 6, 0, 2, 8, 5, 0, 6, 0, 1, 6, 8, 4, 2, 7, 3, 9, 4, 5, 2, 2, 6, 7, 4, 6, 7, 6, 7, 8, 8, 9, 5, 2, 5, 2, 1, 3, 8, 5, 2, 2, 5, 4, 9, 9, 5, 4, 6, 6, 6, 7, 2, 7, 8, 2, 3, 9, 8, + 6, 4, 5, 6, 5, 9, 6, 1, 1, 6, 3, 5, 4, 8, 8, 6, 2, 3, 0, 5, 7, 7, 4, 5, 6, 4, 9, 8, 0, 3, 5, 5, 9, 3, 6, 3, 4, 5, 6, 8, 1, 7, 4, 3, 2, 4, 1, 1, 2, 5, 1, 5, 0, 7, 6, 0, 6, 9, 4, 7, 9, 4, 5, 1, 0, 9, 6, 5, 9, 6, + 0, 9, 4, 0, 2, 5, 2, 2, 8, 8, 7, 9, 7, 1, 0, 8, 9, 3, 1, 4, 5, 6, 6, 9, 1, 3, 6, 8, 6, 7, 2, 2, 8, 7, 4, 8, 9, 4, 0, 5, 6, 0, 1, 0, 1, 5, 0, 3, 3, 0, 8, 6, 1, 7, 9, 2, 8, 6, 8, 0, 9, 2, 0, 8, 7, 4, 7, 6, 0, 9, + 1, 7, 8, 2, 4, 9, 3, 8, 5, 8, 9, 0, 0, 9, 7, 1, 4, 9, 0, 9, 6, 7, 5, 9, 8, 5, 2, 6, 1, 3, 6, 5, 5, 4, 9, 7, 8, 1, 8, 9, 3, 1, 2, 9, 7, 8, 4, 8, 2, 1, 6, 8, 2, 9, 9, 8, 9, 4, 8, 7, 2, 2, 6, 5, 8, 8, 0, 4, 8, 5, + 7, 5, 6, 4, 0, 1, 4, 2, 7, 0, 4, 7, 7, 5, 5, 5, 1, 3, 2, 3, 7, 9, 6, 4, 1, 4, 5, 1, 5, 2, 3, 7, 4, 6, 2, 3, 4, 3, 6, 4, 5, 4, 2, 8, 5, 8, 4, 4, 4, 7, 9, 5, 2, 6, 5, 8, 6, 7, 8, 2, 1, 0, 5, 1, 1, 4, 1, 3, 5, 4, + 7, 3, 5, 7, 3, 9, 5, 2, 3, 1, 1, 3, 4, 2, 7, 1, 6, 6, 1, 0, 2, 1, 3, 5, 9, 6, 9, 5, 3, 6, 2, 3, 1, 4, 4, 2, 9, 5, 2, 4, 8, 4, 9, 3, 7, 1, 8, 7, 1, 1, 0, 1, 4, 5, 7, 6, 5, 4, 0, 3, 5, 9, 0, 2, 7, 9, 9, 3, 4, 4, + 0, 3, 7, 4, 2, 0, 0, 7, 3, 1, 0, 5, 7, 8, 5, 3, 9, 0, 6, 2, 1, 9, 8, 3, 8, 7, 4, 4, 7, 8, 0, 8, 4, 7, 8, 4, 8, 9, 6, 8, 3, 3, 2, 1, 4, 4, 5, 7, 1, 3, 8, 6, 8, 7, 5, 1, 9, 4, 3, 5, 0, 6, 4, 3, 0, 2, 1, 8, 4, 5, + 3, 1, 9, 1, 0, 4, 8, 4, 8, 1, 0, 0, 5, 3, 7, 0, 6, 1, 4, 6, 8, 0, 6, 7, 4, 9, 1, 9, 2, 7, 8, 1, 9, 1, 1, 9, 7, 9, 3, 9, 9, 5, 2, 0, 6, 1, 4, 1, 9, 6, 6, 3, 4, 2, 8, 7, 5, 4, 4, 4, 0, 6, 4, 3, 7, 4, 5, 1, 2, 3, + 7, 1, 8, 1, 9, 2, 1, 7, 9, 9, 9, 8, 3, 9, 1, 0, 1, 5, 9, 1, 9, 5, 6, 1, 8, 1, 4, 6, 7, 5, 1, 4, 2, 6, 9, 1, 2, 3, 9, 7, 4, 8, 9, 4, 0, 9, 0, 7, 1, 8, 6, 4, 9, 4, 2, 3, 1, 9, 6, 1, 5, 6, 7, 9, 4, 5, 2, 0, 8, 0, + 9, 5, 1, 4, 6, 5, 5, 0, 2, 2, 5, 2, 3, 1, 6, 0, 3, 8, 8, 1, 9, 3, 0, 1, 4, 2, 0, 9, 3, 7, 6, 2, 1, 3, 7, 8, 5, 5, 9, 5, 6, 6, 3, 8, 9, 3, 7, 7, 8, 7, 0, 8, 3, 0, 3, 9, 0, 6, 9, 7, 9, 2, 0, 7, 7, 3, 4, 6, 7, 2, + 2, 1, 8, 2, 5, 6, 2, 5, 9, 9, 6, 6, 1, 5, 0, 1, 4, 2, 1, 5, 0, 3, 0, 6, 8, 0, 3, 8, 4, 4, 7, 7, 3, 4, 5, 4, 9, 2, 0, 2, 6, 0, 5, 4, 1, 4, 6, 6, 5, 9, 2, 5, 2, 0, 1, 4, 9, 7, 4, 4, 2, 8, 5, 0, 7, 3, 2, 5, 1, 8, + 6, 6, 6, 0, 0, 2, 1, 3, 2, 4, 3, 4, 0, 8, 8, 1, 9, 0, 7, 1, 0, 4, 8, 6, 3, 3, 1, 7, 3, 4, 6, 4, 9, 6, 5, 1, 4, 5, 3, 9, 0, 5, 7, 9, 6, 2, 6, 8, 5, 6, 1, 0, 0, 5, 5, 0, 8, 1, 0, 6, 6, 5, 8, 7, 9, 6, 9, 9, 8, 1, + 6, 3, 5, 7, 4, 7, 3, 6, 3, 8, 4, 0, 5, 2, 5, 7, 1, 4, 5, 9, 1, 0, 2, 8, 9, 7, 0, 6, 4, 1, 4, 0, 1, 1, 0, 9, 7, 1, 2, 0, 6, 2, 8, 0, 4, 3, 9, 0, 3, 9, 7, 5, 9, 5, 1, 5, 6, 7, 7, 1, 5, 7, 7, 0, 0, 4, 2, 0, 3, 3, + 7, 8, 6, 9, 9, 3, 6, 0, 0, 7, 2, 3, 0, 5, 5, 8, 7, 6, 3, 1, 7, 6, 3, 5, 9, 4, 2, 1, 8, 7, 3, 1, 2, 5, 1, 4, 7, 1, 2, 0, 5, 3, 2, 9, 2, 8, 1, 9, 1, 8, 2, 6, 1, 8, 6, 1, 2, 5, 8, 6, 7, 3, 2, 1, 5, 7, 9, 1, 9, 8, + 4, 1, 4, 8, 4, 8, 8, 2, 9, 1, 6, 4, 4, 7, 0, 6, 0, 9, 5, 7, 5, 2, 7, 0, 6, 9, 5, 7, 2, 2, 0, 9, 1, 7, 5, 6, 7, 1, 1, 6, 7, 2, 2, 9, 1, 0, 9, 8, 1, 6, 9, 0, 9, 1, 5, 2, 8, 0, 1, 7, 3, 5, 0, 6, 7, 1, 2, 7, 4, 8, + 5, 8, 3, 2, 2, 2, 8, 7, 1, 8, 3, 5, 2, 0, 9, 3, 5, 3, 9, 6, 5, 7, 2, 5, 1, 2, 1, 0, 8, 3, 5, 7, 9, 1, 5, 1, 3, 6, 9, 8, 8, 2, 0, 9, 1, 4, 4, 4, 2, 1, 0, 0, 6, 7, 5, 1, 0, 3, 3, 4, 6, 7, 1, 1, 0, 3, 1, 4, 1, 2, + 6, 7, 1, 1, 1, 3, 6, 9, 9, 0, 8, 6, 5, 8, 5, 1, 6, 3, 9, 8, 3, 1, 5, 0, 1, 9, 7, 0, 1, 6, 5, 1, 5, 1, 1, 6, 8, 5, 1, 7, 1, 4, 3, 7, 6, 5, 7, 6, 1, 8, 3, 5, 1, 5, 5, 6, 5, 0, 8, 8, 4, 9, 0, 9, 9, 8, 9, 8, 5, 9, + 9, 8, 2, 3, 8, 7, 3, 4, 5, 5, 2, 8, 3, 3, 1, 6, 3, 5, 5, 0, 7, 6, 4, 7, 9, 1, 8, 5, 3, 5, 8, 9, 3, 2, 2, 6, 1, 8, 5, 4, 8, 9, 6, 3, 2, 1, 3, 2, 9, 3, 3, 0, 8, 9, 8, 5, 7, 0, 6, 4, 2, 0, 4, 6, 7, 5, 2, 5, 9, 0, + 7, 0, 9, 1, 5, 4, 8, 1, 4, 1, 6, 5, 4, 9, 8, 5, 9, 4, 6, 1, 6, 3, 7, 1, 8, 0, 2, 7, 0, 9, 8, 1, 9, 9, 4, 3, 0, 9, 9, 2, 4, 4, 8, 8, 9, 5, 7, 5, 7, 1, 2, 8, 2, 8, 9, 0, 5, 9, 2, 3, 2, 3, 3, 2, 6, 0, 9, 7, 2, 9, + 9, 7, 1, 2, 0, 8, 4, 4, 3, 3, 5, 7, 3, 2, 6, 5, 4, 8, 9, 3, 8, 2, 3, 9, 1, 1, 9, 3, 2, 5, 9, 7, 4, 6, 3, 6, 6, 7, 3, 0, 5, 8, 3, 6, 0, 4, 1, 4, 2, 8, 1, 3, 8, 8, 3, 0, 3, 2, 0, 3, 8, 2, 4, 9, 0, 3, 7, 5, 8, 9, + 8, 5, 2, 4, 3, 7, 4, 4, 1, 7, 0, 2, 9, 1, 3, 2, 7, 6, 5, 6, 1, 8, 0, 9, 3, 7, 7, 3, 4, 4, 4, 0, 3, 0, 7, 0, 7, 4, 6, 9, 2, 1, 1, 2, 0, 1, 9, 1, 3, 0, 2, 0, 3, 3, 0, 3, 8, 0, 1, 9, 7, 6, 2, 1, 1, 0, 1, 1, 0, 0, + 4, 4, 9, 2, 9, 3, 2, 1, 5, 1, 6, 0, 8, 4, 2, 4, 4, 4, 8, 5, 9, 6, 3, 7, 6, 6, 9, 8, 3, 8, 9, 5, 2, 2, 8, 6, 8, 4, 7, 8, 3, 1, 2, 3, 5, 5, 2, 6, 5, 8, 2, 1, 3, 1, 4, 4, 9, 5, 7, 6, 8, 5, 7, 2, 6, 2, 4, 3, 3, 4, + 4, 1, 8, 9, 3, 0, 3, 9, 6, 8, 6, 4, 2, 6, 2, 4, 3, 4, 1, 0, 7, 7, 3, 2, 2, 6, 9, 7, 8, 0, 2, 8, 0, 7, 3, 1, 8, 9, 1, 5, 4, 4, 1, 1, 0, 1, 0, 4, 4, 6, 8, 2, 3, 2, 5, 2, 7, 1, 6, 2, 0, 1, 0, 5, 2, 6, 5, 2, 2, 7, + 2, 1, 1, 1, 6, 6, 0, 3, 9, 6, 6, 6, 5, 5, 7, 3, 0, 9, 2, 5, 4, 7, 1, 1, 0, 5, 5, 7, 8, 5, 3, 7, 6, 3, 4, 6, 6, 8, 2, 0, 6, 5, 3, 1, 0, 9, 8, 9, 6, 5, 2, 6, 9, 1, 8, 6, 2, 0, 5, 6, 4, 7, 6, 9, 3, 1, 2, 5, 7, 0, + 5, 8, 6, 3, 5, 6, 6, 2, 0, 1, 8, 5, 5, 8, 1, 0, 0, 7, 2, 9, 3, 6, 0, 6, 5, 9, 8, 7, 6, 4, 8, 6, 1, 1, 7, 9, 1, 0, 4, 5, 3, 3, 4, 8, 8, 5, 0, 3, 4, 6, 1, 1, 3, 6, 5, 7, 6, 8, 6, 7, 5, 3, 2, 4, 9, 4, 4, 1, 6, 6, + 8, 0, 3, 9, 6, 2, 6, 5, 7, 9, 7, 8, 7, 7, 1, 8, 5, 5, 6, 0, 8, 4, 5, 5, 2, 9, 6, 5, 4, 1, 2, 6, 6, 5, 4, 0, 8, 5, 3, 0, 6, 1, 4, 3, 4, 4, 4, 3, 1, 8, 5, 8, 6, 7, 6, 9, 7, 5, 1, 4, 5, 6, 6, 1, 4, 0, 6, 8, 0, 0, + 7, 0, 0, 2, 3, 7, 8, 7, 7, 6, 5, 9, 1, 3, 4, 4, 0, 1, 7, 1, 2, 7, 4, 9, 4, 7, 0, 4, 2, 0, 5, 6, 2, 2, 3, 0, 5, 3, 8, 9, 9, 4, 5, 6, 1, 3, 1, 4, 0, 7, 1, 1, 2, 7, 0, 0, 0, 4, 0, 7, 8, 5, 4, 7, 3, 3, 2, 6, 9, 9, + 3, 9, 0, 8, 1, 4, 5, 4, 6, 6, 4, 6, 4, 5, 8, 8, 0, 7, 9, 7, 2, 7, 0, 8, 2, 6, 6, 8, 3, 0, 6, 3, 4, 3, 2, 8, 5, 8, 7, 8, 5, 6, 9, 8, 3, 0, 5, 2, 3, 5, 8, 0, 8, 9, 3, 3, 0, 6, 5, 7, 5, 7, 4, 0, 6, 7, 9, 5, 4, 5, + 7, 1, 6, 3, 7, 7, 5, 2, 5, 4, 2, 0, 2, 1, 1, 4, 9, 5, 5, 7, 6, 1, 5, 8, 1, 4, 0, 0, 2, 5, 0, 1, 2, 6, 2, 2, 8, 5, 9, 4, 1, 3, 0, 2, 1, 6, 4, 7, 1, 5, 5, 0, 9, 7, 9, 2, 5, 9, 2, 3, 0, 9, 9, 0, 7, 9, 6, 5, 4, 7, + 3, 7, 6, 1, 2, 5, 5, 1, 7, 6, 5, 6, 7, 5, 1, 3, 5, 7, 5, 1, 7, 8, 2, 9, 6, 6, 6, 4, 5, 4, 7, 7, 9, 1, 7, 4, 5, 0, 1, 1, 2, 9, 9, 6, 1, 4, 8, 9, 0, 3, 0, 4, 6, 3, 9, 9, 4, 7, 1, 3, 2, 9, 6, 2, 1, 0, 7, 3, 4, 0, + 4, 3, 7, 5, 1, 8, 9, 5, 7, 3, 5, 9, 6, 1, 4, 5, 8, 9, 0, 1, 9, 3, 8, 9, 7, 1, 3, 1, 1, 1, 7, 9, 0, 4, 2, 9, 7, 8, 2, 8, 5, 6, 4, 7, 5, 0, 3, 2, 0, 3, 1, 9, 8, 6, 9, 1, 5, 1, 4, 0, 2, 8, 7, 0, 8, 0, 8, 5, 9, 9, + 0, 4, 8, 0, 1, 0, 9, 4, 1, 2, 1, 4, 7, 2, 2, 1, 3, 1, 7, 9, 4, 7, 6, 4, 7, 7, 7, 2, 6, 2, 2, 4, 1, 4, 2, 5, 4, 8, 5, 4, 5, 4, 0, 3, 3, 2, 1, 5, 7, 1, 8, 5, 3, 0, 6, 1, 4, 2, 2, 8, 8, 1, 3, 7, 5, 8, 5, 0, 4, 3, + 0, 6, 3, 3, 2, 1, 7, 5, 1, 8, 2, 9, 7, 9, 8, 6, 6, 2, 2, 3, 7, 1, 7, 2, 1, 5, 9, 1, 6, 0, 7, 7, 1, 6, 6, 9, 2, 5, 4, 7, 4, 8, 7, 3, 8, 9, 8, 6, 6, 5, 4, 9, 4, 9, 4, 5, 0, 1, 1, 4, 6, 5, 4, 0, 6, 2, 8, 4, 3, 3, + 6, 6, 3, 9, 3, 7, 9, 0, 0, 3, 9, 7, 6, 9, 2, 6, 5, 6, 7, 2, 1, 4, 6, 3, 8, 5, 3, 0, 6, 7, 3, 6, 0, 9, 6, 5, 7, 1, 2, 0, 9, 1, 8, 0, 7, 6, 3, 8, 3, 2, 7, 1, 6, 6, 4, 1, 6, 2, 7, 4, 8, 8, 8, 8, 0, 0, 7, 8, 6, 9, + 2, 5, 6, 0, 2, 9, 0, 2, 2, 8, 4, 7, 2, 1, 0, 4, 0, 3, 1, 7, 2, 1, 1, 8, 6, 0, 8, 2, 0, 4, 1, 9, 0, 0, 0, 4, 2, 2, 9, 6, 6, 1, 7, 1, 1, 9, 6, 3, 7, 7, 9, 2, 1, 3, 3, 7, 5, 7, 5, 1, 1, 4, 9, 5, 9, 5, 0, 1, 5, 6, + 6, 0, 4, 9, 6, 3, 1, 8, 6, 2, 9, 4, 7, 2, 6, 5, 4, 7, 3, 6, 4, 2, 5, 2, 3, 0, 8, 1, 7, 7, 0, 3, 6, 7, 5, 1, 5, 9, 0, 6, 7, 3, 5, 0, 2, 3, 5, 0, 7, 2, 8, 3, 5, 4, 0, 5, 6, 7, 0, 4, 0, 3, 8, 6, 7, 4, 3, 5, 1, 3, + 6, 2, 2, 2, 2, 4, 7, 7, 1, 5, 8, 9, 1, 5, 0, 4, 9, 5, 3, 0, 9, 8, 4, 4, 4, 8, 9, 3, 3, 3, 0, 9, 6, 3, 4, 0, 8, 7, 8, 0, 7, 6, 9, 3, 2, 5, 9, 9, 3, 9, 7, 8, 0, 5, 4, 1, 9, 3, 4, 1, 4, 4, 7, 3, 7, 7, 4, 4, 1, 8, + 4, 2, 6, 3, 1, 2, 9, 8, 6, 0, 8, 0, 9, 9, 8, 8, 8, 6, 8, 7, 4, 1, 3, 2, 6, 0, 4, 7, 2, 1, 5, 6, 9, 5, 1, 6, 2, 3, 9, 6, 5, 8, 6, 4, 5, 7, 3, 0, 2, 1, 6, 3, 1, 5, 9, 8, 1, 9, 3, 1, 9, 5, 1, 6, 7, 3, 5, 3, 8, 1, + 2, 9, 7, 4, 1, 6, 7, 7, 2, 9, 4, 7, 8, 6, 7, 2, 4, 2, 2, 9, 2, 4, 6, 5, 4, 3, 6, 6, 8, 0, 0, 9, 8, 0, 6, 7, 6, 9, 2, 8, 2, 3, 8, 2, 8, 0, 6, 8, 9, 9, 6, 4, 0, 0, 4, 8, 2, 4, 3, 5, 4, 0, 3, 7, 0, 1, 4, 1, 6, 3, + 1, 4, 9, 6, 5, 8, 9, 7, 9, 4, 0, 9, 2, 4, 3, 2, 3, 7, 8, 9, 6, 9, 0, 7, 0, 6, 9, 7, 7, 9, 4, 2, 2, 3, 6, 2, 5, 0, 8, 2, 2, 1, 6, 8, 8, 9, 5, 7, 3, 8, 3, 7, 9, 8, 6, 2, 3, 0, 0, 1, 5, 9, 3, 7, 7, 6, 4, 7, 1, 6, + 5, 1, 2, 2, 8, 9, 3, 5, 7, 8, 6, 0, 1, 5, 8, 8, 1, 6, 1, 7, 5, 5, 7, 8, 2, 9, 7, 3, 5, 2, 3, 3, 4, 4, 6, 0, 4, 2, 8, 1, 5, 1, 2, 6, 2, 7, 2, 0, 3, 7, 3, 4, 3, 1, 4, 6, 5, 3, 1, 9, 7, 7, 7, 7, 4, 1, 6, 0, 3, 1, + 9, 9, 0, 6, 6, 5, 5, 4, 1, 8, 7, 6, 3, 9, 7, 9, 2, 9, 3, 3, 4, 4, 1, 9, 5, 2, 1, 5, 4, 1, 3, 4, 1, 8, 9, 9, 4, 8, 5, 4, 4, 4, 7, 3, 4, 5, 6, 7, 3, 8, 3, 1, 6, 2, 4, 9, 9, 3, 4, 1, 9, 1, 3, 1, 8, 1, 4, 8, 0, 9, + 2, 7, 7, 7, 7, 1, 0, 3, 8, 6, 3, 8, 7, 7, 3, 4, 3, 1, 7, 7, 2, 0, 7, 5, 4, 5, 6, 5, 4, 5, 3, 2, 2, 0, 7, 7, 7, 0, 9, 2, 1, 2, 0, 1, 9, 0, 5, 1, 6, 6, 0, 9, 6, 2, 8, 0, 4, 9, 0, 9, 2, 6, 3, 6, 0, 1, 9, 7, 5, 9, + 8, 8, 2, 8, 1, 6, 1, 3, 3, 2, 3, 1, 6, 6, 6, 3, 6, 5, 2, 8, 6, 1, 9, 3, 2, 6, 6, 8, 6, 3, 3, 6, 0, 6, 2, 7, 3, 5, 6, 7, 6, 3, 0, 3, 5, 4, 4, 7, 7, 6, 2, 8, 0, 3, 5, 0, 4, 5, 0, 7, 7, 7, 2, 3, 5, 5, 4, 7, 1, 0, + 5, 8, 5, 9, 5, 4, 8, 7, 0, 2, 7, 9, 0, 8, 1, 4, 3, 5, 6, 2, 4, 0, 1, 4, 5, 1, 7, 1, 8, 0, 6, 2, 4, 6, 4, 3, 6, 2, 6, 7, 9, 4, 5, 6, 1, 2, 7, 5, 3, 1, 8, 1, 3, 4, 0, 7, 8, 3, 3, 0, 3, 3, 6, 2, 5, 4, 2, 3, 2, 7, + 8, 3, 9, 4, 4, 9, 7, 5, 3, 8, 2, 4, 3, 7, 2, 0, 5, 8, 3, 5, 3, 1, 1, 4, 7, 7, 1, 1, 9, 9, 2, 6, 0, 6, 3, 8, 1, 3, 3, 4, 6, 7, 7, 6, 8, 7, 9, 6, 9, 5, 9, 7, 0, 3, 0, 9, 8, 3, 3, 9, 1, 3, 0, 7, 7, 1, 0, 9, 8, 7, + 0, 4, 0, 8, 5, 9, 1, 3, 3, 7, 4, 6, 4, 1, 4, 4, 2, 8, 2, 2, 7, 7, 2, 6, 3, 4, 6, 5, 9, 4, 7, 0, 4, 7, 4, 5, 8, 7, 8, 4, 7, 7, 8, 7, 2, 0, 1, 9, 2, 7, 7, 1, 5, 2, 8, 0, 7, 3, 1, 7, 6, 7, 9, 0, 7, 7, 0, 7, 1, 5, + 7, 2, 1, 3, 4, 4, 4, 7, 3, 0, 6, 0, 5, 7, 0, 0, 7, 3, 3, 4, 9, 2, 4, 3, 6, 9, 3, 1, 1, 3, 8, 3, 5, 0, 4, 9, 3, 1, 6, 3, 1, 2, 8, 4, 0, 4, 2, 5, 1, 2, 1, 9, 2, 5, 6, 5, 1, 7, 9, 8, 0, 6, 9, 4, 1, 1, 3, 5, 2, 8, + 0, 1, 3, 1, 4, 7, 0, 1, 3, 0, 4, 7, 8, 1, 6, 4, 3, 7, 8, 8, 5, 1, 8, 5, 2, 9, 0, 9, 2, 8, 5, 4, 5, 2, 0, 1, 1, 6, 5, 8, 3, 9, 3, 4, 1, 9, 6, 5, 6, 2, 1, 3, 4, 9, 1, 4, 3, 4, 1, 5, 9, 5, 6, 2, 5, 8, 6, 5, 8, 6, + 5, 5, 7, 0, 5, 5, 2, 6, 9, 0, 4, 9, 6, 5, 2, 0, 9, 8, 5, 8, 0, 3, 3, 8, 5, 0, 7, 2, 2, 4, 2, 6, 4, 8, 2, 9, 3, 9, 7, 2, 8, 5, 8, 4, 7, 8, 3, 1, 6, 3, 0, 5, 7, 7, 7, 7, 5, 6, 0, 6, 8, 8, 8, 7, 6, 4, 4, 6, 2, 4, + 8, 2, 4, 6, 8, 5, 7, 9, 2, 6, 0, 3, 9, 5, 3, 5, 2, 7, 7, 3, 4, 8, 0, 3, 0, 4, 8, 0, 2, 9, 0, 0, 5, 8, 7, 6, 0, 7, 5, 8, 2, 5, 1, 0, 4, 7, 4, 7, 0, 9, 1, 6, 4, 3, 9, 6, 1, 3, 6, 2, 6, 7, 6, 0, 4, 4, 9, 2, 5, 6, + 2, 7, 4, 2, 0, 4, 2, 0, 8, 3, 2, 0, 8, 5, 6, 6, 1, 1, 9, 0, 6, 2, 5, 4, 5, 4, 3, 3, 7, 2, 1, 3, 1, 5, 3, 5, 9, 5, 8, 4, 5, 0, 6, 8, 7, 7, 2, 4, 6, 0, 2, 9, 0, 1, 6, 1, 8, 7, 6, 6, 7, 9, 5, 2, 4, 0, 6, 1, 6, 3, + 4, 2, 5, 2, 2, 5, 7, 7, 1, 9, 5, 4, 2, 9, 1, 6, 2, 9, 9, 1, 9, 3, 0, 6, 4, 5, 5, 3, 7, 7, 9, 9, 1, 4, 0, 3, 7, 3, 4, 0, 4, 3, 2, 8, 7, 5, 2, 6, 2, 8, 8, 8, 9, 6, 3, 9, 9, 5, 8, 7, 9, 4, 7, 5, 7, 2, 9, 1, 7, 4, + 6, 4, 2, 6, 3, 5, 7, 4, 5, 5, 2, 5, 4, 0, 7, 9, 0, 9, 1, 4, 5, 1, 3, 5, 7, 1, 1, 1, 3, 6, 9, 4, 1, 0, 9, 1, 1, 9, 3, 9, 3, 2, 5, 1, 9, 1, 0, 7, 6, 0, 2, 0, 8, 2, 5, 2, 0, 2, 6, 1, 8, 7, 9, 8, 5, 3, 1, 8, 8, 7, + 7, 0, 5, 8, 4, 2, 9, 7, 2, 5, 9, 1, 6, 7, 7, 8, 1, 3, 1, 4, 9, 6, 9, 9, 0, 0, 9, 0, 1, 9, 2, 1, 1, 6, 9, 7, 1, 7, 3, 7, 2, 7, 8, 4, 7, 6, 8, 4, 7, 2, 6, 8, 6, 0, 8, 4, 9, 0, 0, 3, 3, 7, 7, 0, 2, 4, 2, 4, 2, 9, + 1, 6, 5, 1, 3, 0, 0, 5, 0, 0, 5, 1, 6, 8, 3, 2, 3, 3, 6, 4, 3, 5, 0, 3, 8, 9, 5, 1, 7, 0, 2, 9, 8, 9, 3, 9, 2, 2, 3, 3, 4, 5, 1, 7, 2, 2, 0, 1, 3, 8, 1, 2, 8, 0, 6, 9, 6, 5, 0, 1, 1, 7, 8, 4, 4, 0, 8, 7, 4, 5, + 1, 9, 6, 0, 1, 2, 1, 2, 2, 8, 5, 9, 9, 3, 7, 1, 6, 2, 3, 1, 3, 0, 1, 7, 1, 1, 4, 4, 4, 8, 4, 6, 4, 0, 9, 0, 3, 8, 9, 0, 6, 4, 4, 9, 5, 4, 4, 4, 0, 0, 6, 1, 9, 8, 6, 9, 0, 7, 5, 4, 8, 5, 1, 6, 0, 2, 6, 3, 2, 7, + 5, 0, 5, 2, 9, 8, 3, 4, 9, 1, 8, 7, 4, 0, 7, 8, 6, 6, 8, 0, 8, 8, 1, 8, 3, 3, 8, 5, 1, 0, 2, 2, 8, 3, 3, 4, 5, 0, 8, 5, 0, 4, 8, 6, 0, 8, 2, 5, 0, 3, 9, 3, 0, 2, 1, 3, 3, 2, 1, 9, 7, 1, 5, 5, 1, 8, 4, 3, 0, 6, + 3, 5, 4, 5, 5, 0, 0, 7, 6, 6, 8, 2, 8, 2, 9, 4, 9, 3, 0, 4, 1, 3, 7, 7, 6, 5, 5, 2, 7, 9, 3, 9, 7, 5, 1, 7, 5, 4, 6, 1, 3, 9, 5, 3, 9, 8, 4, 6, 8, 3, 3, 9, 3, 6, 3, 8, 3, 0, 4, 7, 4, 6, 1, 1, 9, 9, 6, 6, 5, 3, + 8, 5, 8, 1, 5, 3, 8, 4, 2, 0, 5, 6, 8, 5, 3, 3, 8, 6, 2, 1, 8, 6, 7, 2, 5, 2, 3, 3, 4, 0, 2, 8, 3, 0, 8, 7, 1, 1, 2, 3, 2, 8, 2, 7, 8, 9, 2, 1, 2, 5, 0, 7, 7, 1, 2, 6, 2, 9, 4, 6, 3, 2, 2, 9, 5, 6, 3, 9, 8, 9, + 8, 9, 8, 9, 3, 5, 8, 2, 1, 1, 6, 7, 4, 5, 6, 2, 7, 0, 1, 0, 2, 1, 8, 3, 5, 6, 4, 6, 2, 2, 0, 1, 3, 4, 9, 6, 7, 1, 5, 1, 8, 8, 1, 9, 0, 9, 7, 3, 0, 3, 8, 1, 1, 9, 8, 0, 0, 4, 9, 7, 3, 4, 0, 7, 2, 3, 9, 6, 1, 0, + 3, 6, 8, 5, 4, 0, 6, 6, 4, 3, 1, 9, 3, 9, 5, 0, 9, 7, 9, 0, 1, 9, 0, 6, 9, 9, 6, 3, 9, 5, 5, 2, 4, 5, 3, 0, 0, 5, 4, 5, 0, 5, 8, 0, 6, 8, 5, 5, 0, 1, 9, 5, 6, 7, 3, 0, 2, 2, 9, 2, 1, 9, 1, 3, 9, 3, 3, 9, 1, 8, + 5, 6, 8, 0, 3, 4, 4, 9, 0, 3, 9, 8, 2, 0, 5, 9, 5, 5, 1, 0, 0, 2, 2, 6, 3, 5, 3, 5, 3, 6, 1, 9, 2, 0, 4, 1, 9, 9, 4, 7, 4, 5, 5, 3, 8, 5, 9, 3, 8, 1, 0, 2, 3, 4, 3, 9, 5, 5, 4, 4, 9, 5, 9, 7, 7, 8, 3, 7, 7, 9, + 0, 2, 3, 7, 4, 2, 1, 6, 1, 7, 2, 7, 1, 1, 1, 7, 2, 3, 6, 4, 3, 4, 3, 5, 4, 3, 9, 4, 7, 8, 2, 2, 1, 8, 1, 8, 5, 2, 8, 6, 2, 4, 0, 8, 5, 1, 4, 0, 0, 6, 6, 6, 0, 4, 4, 3, 3, 2, 5, 8, 8, 8, 5, 6, 9, 8, 6, 7, 0, 5, + 4, 3, 1, 5, 4, 7, 0, 6, 9, 6, 5, 7, 4, 7, 4, 5, 8, 5, 5, 0, 3, 3, 2, 3, 2, 3, 3, 4, 2, 1, 0, 7, 3, 0, 1, 5, 4, 5, 9, 4, 0, 5, 1, 6, 5, 5, 3, 7, 9, 0, 6, 8, 6, 6, 2, 7, 3, 3, 3, 7, 9, 9, 5, 8, 5, 1, 1, 5, 6, 2, + 5, 7, 8, 4, 3, 2, 2, 9, 8, 8, 2, 7, 3, 7, 2, 3, 1, 9, 8, 9, 8, 7, 5, 7, 1, 4, 1, 5, 9, 5, 7, 8, 1, 1, 1, 9, 6, 3, 5, 8, 3, 3, 0, 0, 5, 9, 4, 0, 8, 7, 3, 0, 6, 8, 1, 2, 1, 6, 0, 2, 8, 7, 6, 4, 9, 6, 2, 8, 6, 7, + 4, 4, 6, 0, 4, 7, 7, 4, 6, 4, 9, 1, 5, 9, 9, 5, 0, 5, 4, 9, 7, 3, 7, 4, 2, 5, 6, 2, 6, 9, 0, 1, 0, 4, 9, 0, 3, 7, 7, 8, 1, 9, 8, 6, 8, 3, 5, 9, 3, 8, 1, 4, 6, 5, 7, 4, 1, 2, 6, 8, 0, 4, 9, 2, 5, 6, 4, 8, 7, 9, + 8, 5, 5, 6, 1, 4, 5, 3, 7, 2, 3, 4, 7, 8, 6, 7, 3, 3, 0, 3, 9, 0, 4, 6, 8, 8, 3, 8, 3, 4, 3, 6, 3, 4, 6, 5, 5, 3, 7, 9, 4, 9, 8, 6, 4, 1, 9, 2, 7, 0, 5, 6, 3, 8, 7, 2, 9, 3, 1, 7, 4, 8, 7, 2, 3, 3, 2, 0, 8, 3, + 7, 6, 0, 1, 1, 2, 3, 0, 2, 9, 9, 1, 1, 3, 6, 7, 9, 3, 8, 6, 2, 7, 0, 8, 9, 4, 3, 8, 7, 9, 9, 3, 6, 2, 0, 1, 6, 2, 9, 5, 1, 5, 4, 1, 3, 3, 7, 1, 4, 2, 4, 8, 9, 2, 8, 3, 0, 7, 2, 2, 0, 1, 2, 6, 9, 0, 1, 4, 7, 5, + 4, 6, 6, 8, 4, 7, 6, 5, 3, 5, 7, 6, 1, 6, 4, 7, 7, 3, 7, 9, 4, 6, 7, 5, 2, 0, 0, 4, 9, 0, 7, 5, 7, 1, 5, 5, 5, 2, 7, 8, 1, 9, 6, 5, 3, 6, 2, 1, 3, 2, 3, 9, 2, 6, 4, 0, 6, 1, 6, 0, 1, 3, 6, 3, 5, 8, 1, 5, 5, 9, + 0, 7, 4, 2, 2, 0, 2, 0, 2, 0, 3, 1, 8, 7, 2, 7, 7, 6, 0, 5, 2, 7, 7, 2, 1, 9, 0, 0, 5, 5, 6, 1, 4, 8, 4, 2, 5, 5, 5, 1, 8, 7, 9, 2, 5, 3, 0, 3, 4, 3, 5, 1, 3, 9, 8, 4, 4, 2, 5, 3, 2, 2, 3, 4, 1, 5, 7, 6, 2, 3, + 3, 6, 1, 0, 6, 4, 2, 5, 0, 6, 3, 9, 0, 4, 9, 7, 5, 0, 0, 8, 6, 5, 6, 2, 7, 1, 0, 9, 5, 3, 5, 9, 1, 9, 4, 6, 5, 8, 9, 7, 5, 1, 4, 1, 3, 1, 0, 3, 4, 8, 2, 2, 7, 6, 9, 3, 0, 6, 2, 4, 7, 4, 3, 5, 3, 6, 3, 2, 5, 6, + 9, 1, 6, 0, 7, 8, 1, 5, 4, 7, 8, 1, 8, 1, 1, 5, 2, 8, 4, 3, 6, 6, 7, 9, 5, 7, 0, 6, 1, 1, 0, 8, 6, 1, 5, 3, 3, 1, 5, 0, 4, 4, 5, 2, 1, 2, 7, 4, 7, 3, 9, 2, 4, 5, 4, 4, 9, 4, 5, 4, 2, 3, 6, 8, 2, 8, 8, 6, 0, 6, + 1, 3, 4, 0, 8, 4, 1, 4, 8, 6, 3, 7, 7, 6, 7, 0, 0, 9, 6, 1, 2, 0, 7, 1, 5, 1, 2, 4, 9, 1, 4, 0, 4, 3, 0, 2, 7, 2, 5, 3, 8, 6, 0, 7, 6, 4, 8, 2, 3, 6, 3, 4, 1, 4, 3, 3, 4, 6, 2, 3, 5, 1, 8, 9, 7, 5, 7, 6, 6, 4, + 5, 2, 1, 6, 4, 1, 3, 7, 6, 7, 9, 6, 9, 0, 3, 1, 4, 9, 5, 0, 1, 9, 1, 0, 8, 5, 7, 5, 9, 8, 4, 4, 2, 3, 9, 1, 9, 8, 6, 2, 9, 1, 6, 4, 2, 1, 9, 3, 9, 9, 4, 9, 0, 7, 2, 3, 6, 2, 3, 4, 6, 4, 6, 8, 4, 4, 1, 1, 7, 3, + 9, 4, 0, 3, 2, 6, 5, 9, 1, 8, 4, 0, 4, 4, 3, 7, 8, 0, 5, 1, 3, 3, 3, 8, 9, 4, 5, 2, 5, 7, 4, 2, 3, 9, 9, 5, 0, 8, 2, 9, 6, 5, 9, 1, 2, 2, 8, 5, 0, 8, 5, 5, 5, 8, 2, 1, 5, 7, 2, 5, 0, 3, 1, 0, 7, 1, 2, 5, 7, 0, + 1, 2, 6, 6, 8, 3, 0, 2, 4, 0, 2, 9, 2, 9, 5, 2, 5, 2, 2, 0, 1, 1, 8, 7, 2, 6, 7, 6, 7, 5, 6, 2, 2, 0, 4, 1, 5, 4, 2, 0, 5, 1, 6, 1, 8, 4, 1, 6, 3, 4, 8, 4, 7, 5, 6, 5, 1, 6, 9, 9, 9, 8, 1, 1, 6, 1, 4, 1, 0, 1, + 0, 0, 2, 9, 9, 6, 0, 7, 8, 3, 8, 6, 9, 0, 9, 2, 9, 1, 6, 0, 3, 0, 2, 8, 8, 4, 0, 0, 2, 6, 9, 1, 0, 4, 1, 4, 0, 7, 9, 2, 8, 8, 6, 2, 1, 5, 0, 7, 8, 4, 2, 4, 5, 1, 6, 7, 0, 9, 0, 8, 7, 0, 0, 0, 6, 9, 9, 2, 8, 2, + 1, 2, 0, 6, 6, 0, 4, 1, 8, 3, 7, 1, 8, 0, 6, 5, 3, 5, 5, 6, 7, 2, 5, 2, 5, 3, 2, 5, 6, 7, 5, 3, 2, 8, 6, 1, 2, 9, 1, 0, 4, 2, 4, 8, 7, 7, 6, 1, 8, 2, 5, 8, 2, 9, 7, 6, 5, 1, 5, 7, 9, 5, 9, 8, 4, 7, 0, 3, 5, 6, + 2, 2, 2, 6, 2, 9, 3, 4, 8, 6, 0, 0, 3, 4, 1, 5, 8, 7, 2, 2, 9, 8, 0, 5, 3, 4, 9, 8, 9, 6, 5, 0, 2, 2, 6, 2, 9, 1, 7, 4, 8, 7, 8, 8, 2, 0, 2, 7, 3, 4, 2, 0, 9, 2, 2, 2, 2, 4, 5, 3, 3, 9, 8, 5, 6, 2, 6, 4, 7, 6, + 6, 9, 1, 4, 9, 0, 5, 5, 6, 2, 8, 4, 2, 5, 0, 3, 9, 1, 2, 7, 5, 7, 7, 1, 0, 2, 8, 4, 0, 2, 7, 9, 9, 8, 0, 6, 6, 3, 6, 5, 8, 2, 5, 4, 8, 8, 9, 2, 6, 4, 8, 8, 0, 2, 5, 4, 5, 6, 6, 1, 0, 1, 7, 2, 9, 6, 7, 0, 2, 6, + 6, 4, 0, 7, 6, 5, 5, 9, 0, 4, 2, 9, 0, 9, 9, 4, 5, 6, 8, 1, 5, 0, 6, 5, 2, 6, 5, 3, 0, 5, 3, 7, 1, 8, 2, 9, 4, 1, 2, 7, 0, 3, 3, 6, 9, 3, 1, 3, 7, 8, 5, 1, 7, 8, 6, 0, 9, 0, 4, 0, 7, 0, 8, 6, 6, 7, 1, 1, 4, 9, + 6, 5, 5, 8, 3, 4, 3, 4, 3, 4, 7, 6, 9, 3, 3, 8, 5, 7, 8, 1, 7, 1, 1, 3, 8, 6, 4, 5, 5, 8, 7, 3, 6, 7, 8, 1, 2, 3, 0, 1, 4, 5, 8, 7, 6, 8, 7, 1, 2, 6, 6, 0, 3, 4, 8, 9, 1, 3, 9, 0, 9, 5, 6, 2, 0, 0, 9, 9, 3, 9, + 3, 6, 1, 0, 3, 1, 0, 2, 9, 1, 6, 1, 6, 1, 5, 2, 8, 8, 1, 3, 8, 4, 3, 7, 9, 0, 9, 9, 0, 4, 2, 3, 1, 7, 4, 7, 3, 3, 6, 3, 9, 4, 8, 0, 4, 5, 7, 5, 9, 3, 1, 4, 9, 3, 1, 4, 0, 5, 2, 9, 7, 6, 3, 4, 7, 5, 7, 4, 8, 1, + 1, 9, 3, 5, 6, 7, 0, 9, 1, 1, 0, 1, 3, 7, 7, 5, 1, 7, 2, 1, 0, 0, 8, 0, 3, 1, 5, 5, 9, 0, 2, 4, 8, 5, 3, 0, 9, 0, 6, 6, 9, 2, 0, 3, 7, 6, 7, 1, 9, 2, 2, 0, 3, 3, 2, 2, 9, 0, 9, 4, 3, 3, 4, 6, 7, 6, 8, 5, 1, 4, + 2, 2, 1, 4, 4, 7, 7, 3, 7, 9, 3, 9, 3, 7, 5, 1, 7, 0, 3, 4, 4, 3, 6, 6, 1, 9, 9, 1, 0, 4, 0, 3, 3, 7, 5, 1, 1, 1, 7, 3, 5, 4, 7, 1, 9, 1, 8, 5, 5, 0, 4, 6, 4, 4, 9, 0, 2, 6, 3, 6, 5, 5, 1, 2, 8, 1, 6, 2, 2, 8, + 8, 2, 4, 4, 6, 2, 5, 7, 5, 9, 1, 6, 3, 3, 3, 0, 3, 9, 1, 0, 7, 2, 2, 5, 3, 8, 3, 7, 4, 2, 1, 8, 2, 1, 4, 0, 8, 8, 3, 5, 0, 8, 6, 5, 7, 3, 9, 1, 7, 7, 1, 5, 0, 9, 6, 8, 2, 8, 8, 7, 4, 7, 8, 2, 6, 5, 6, 9, 9, 5, + 9, 9, 5, 7, 4, 4, 9, 0, 6, 6, 1, 7, 5, 8, 3, 4, 4, 1, 3, 7, 5, 2, 2, 3, 9, 7, 0, 9, 6, 8, 3, 4, 0, 8, 0, 0, 5, 3, 5, 5, 9, 8, 4, 9, 1, 7, 5, 4, 1, 7, 3, 8, 1, 8, 8, 3, 9, 9, 9, 4, 4, 6, 9, 7, 4, 8, 6, 7, 6, 2, + 6, 5, 5, 1, 6, 5, 8, 2, 7, 6, 5, 8, 4, 8, 3, 5, 8, 8, 4, 5, 3, 1, 4, 2, 7, 7, 5, 6, 8, 7, 9, 0, 0, 2, 9, 0, 9, 5, 1, 7, 0, 2, 8, 3, 5, 2, 9, 7, 1, 6, 3, 4, 4, 5, 6, 2, 1, 2, 9, 6, 4, 0, 4, 3, 5, 2, 3, 1, 1, 7, + 6, 0, 0, 6, 6, 5, 1, 0, 1, 2, 4, 1, 2, 0, 0, 6, 5, 9, 7, 5, 5, 8, 5, 1, 2, 7, 6, 1, 7, 8, 5, 8, 3, 8, 2, 9, 2, 0, 4, 1, 9, 7, 4, 8, 4, 4, 2, 3, 6, 0, 8, 0, 0, 7, 1, 9, 3, 0, 4, 5, 7, 6, 1, 8, 9, 3, 2, 3, 4, 9, + 2, 2, 9, 2, 7, 9, 6, 5, 0, 1, 9, 8, 7, 5, 1, 8, 7, 2, 1, 2, 7, 2, 6, 7, 5, 0, 7, 9, 8, 1, 2, 5, 5, 4, 7, 0, 9, 5, 8, 9, 0, 4, 5, 5, 6, 3, 5, 7, 9, 2, 1, 2, 2, 1, 0, 3, 3, 3, 4, 6, 6, 9, 7, 4, 9, 9, 2, 3, 5, 6, + 3, 0, 2, 5, 4, 9, 4, 7, 8, 0, 2, 4, 9, 0, 1, 1, 4, 1, 9, 5, 2, 1, 2, 3, 8, 2, 8, 1, 5, 3, 0, 9, 1, 1, 4, 0, 7, 9, 0, 7, 3, 8, 6, 0, 2, 5, 1, 5, 2, 2, 7, 4, 2, 9, 9, 5, 8, 1, 8, 0, 7, 2, 4, 7, 1, 6, 2, 5, 9, 1, + 6, 6, 8, 5, 4, 5, 1, 3, 3, 3, 1, 2, 3, 9, 4, 8, 0, 4, 9, 4, 7, 0, 7, 9, 1, 1, 9, 1, 5, 3, 2, 6, 7, 3, 4, 3, 0, 2, 8, 2, 4, 4, 1, 8, 6, 0, 4, 1, 4, 2, 6, 3, 6, 3, 9, 5, 4, 8, 0, 0, 0, 4, 4, 8, 0, 0, 2, 6, 7, 0, + 4, 9, 6, 2, 4, 8, 2, 0, 1, 7, 9, 2, 8, 9, 6, 4, 7, 6, 6, 9, 7, 5, 8, 3, 1, 8, 3, 2, 7, 1, 3, 1, 4, 2, 5, 1, 7, 0, 2, 9, 6, 9, 2, 3, 4, 8, 8, 9, 6, 2, 7, 6, 6, 8, 4, 4, 0, 3, 2, 3, 2, 6, 0, 9, 2, 7, 5, 2, 4, 9, + 6, 0, 3, 5, 7, 9, 9, 6, 4, 6, 9, 2, 5, 6, 5, 0, 4, 9, 3, 6, 8, 1, 8, 3, 6, 0, 9, 0, 0, 3, 2, 3, 8, 0, 9, 2, 9, 3, 4, 5, + 9, 5, 8, 8, 9, 7, 0, 6, 9, 5, 3, 6, 5, 3, 4, 9, 4, 0, 6, 0, 3, 4, 0, 2, 1, 6, 6, 5, 4, 4, 3, 7, 5, 5, 8, 9, 0, 0, 4, 5, 6, 3, 2, 8, 8, 2, 2, 5, 0, 5, 4, 5, 2, 5, 5, 6, 4, 0, 5, 6, 4, 4, 8, 2, 4, 6, 5, 1, 5, 1, + 8, 7, 5, 4, 7, 1, 1, 9, 6, 2, 1, 8, 4, 4, 3, 9, 6, 5, 8, 2, 5, 3, 3, 7, 5, 4, 3, 8, 8, 5, 6, 9, 0, 9, 4, 1, 1, 3, 0, 3, 1, 5, 0, 9, 5, 2, 6, 1, 7, 9, 3, 7, 8, 0, 0, 2, 9, 7, 4, 1, 2, 0, 7, 6, 6, 5, 1, 4, 7, 9, + 3, 9, 4, 2, 5, 9, 0, 2, 9, 8, 9, 6, 9, 5, 9, 4, 6, 9, 9, 5, 5, 6, 5, 7, 6, 1, 2, 1, 8, 6, 5, 6, 1, 9, 6, 7, 3, 3, 7, 8, 6, 2, 3, 6, 2, 5, 6, 1, 2, 5, 2, 1, 6, 3, 2, 0, 8, 6, 2, 8, 6, 9, 2, 2, 2, 1, 0, 3, 2, 7, + 4, 8, 8, 9, 2, 1, 8, 6, 5, 4, 3, 6, 4, 8, 0, 2, 2, 9, 6, 7, 8, 0, 7, 0, 5, 7, 6, 5, 6, 1, 5, 1, 4, 4, 6, 3, 2, 0, 4, 6, 9, 2, 7, 9, 0, 6, 8, 2, 1, 2, 0, 7, 3, 8, 8, 3, 7, 7, 8, 1, 4, 2, 3, 3, 5, 6, 2, 8, 2, 3, + 6, 0, 8, 9, 6, 3, 2, 0, 8, 0, 6, 8, 2, 2, 2, 4, 6, 8, 0, 1, 2, 2, 4, 8, 2, 6, 1, 1, 7, 7, 1, 8, 5, 8, 9, 6, 3, 8, 1, 4, 0, 9, 1, 8, 3, 9, 0, 3, 6, 7, 3, 6, 7, 2, 2, 2, 0, 8, 8, 8, 3, 2, 1, 5, 1, 3, 7, 5, 5, 6, + 0, 0, 3, 7, 2, 7, 9, 8, 3, 9, 4, 0, 0, 4, 1, 5, 2, 9, 7, 0, 0, 2, 8, 7, 8, 3, 0, 7, 6, 6, 7, 0, 9, 4, 4, 4, 7, 4, 5, 6, 0, 1, 3, 4, 5, 5, 6, 4, 1, 7, 2, 5, 4, 3, 7, 0, 9, 0, 6, 9, 7, 9, 3, 9, 6, 1, 2, 2, 5, 7, + 1, 4, 2, 9, 8, 9, 4, 6, 7, 1, 5, 4, 3, 5, 7, 8, 4, 6, 8, 7, 8, 8, 6, 1, 4, 4, 4, 5, 8, 1, 2, 3, 1, 4, 5, 9, 3, 5, 7, 1, 9, 8, 4, 9, 2, 2, 5, 2, 8, 4, 7, 1, 6, 0, 5, 0, 4, 9, 2, 2, 1, 2, 4, 2, 4, 7, 0, 1, 4, 1, + 2, 1, 4, 7, 8, 0, 5, 7, 3, 4, 5, 5, 1, 0, 5, 0, 0, 8, 0, 1, 9, 0, 8, 6, 9, 9, 6, 0, 3, 3, 0, 2, 7, 6, 3, 4, 7, 8, 7, 0, 8, 1, 0, 8, 1, 7, 5, 4, 5, 0, 1, 1, 9, 3, 0, 7, 1, 4, 1, 2, 2, 3, 3, 9, 0, 8, 6, 6, 3, 9, + 3, 8, 3, 3, 9, 5, 2, 9, 4, 2, 5, 7, 8, 6, 9, 0, 5, 0, 7, 6, 4, 3, 1, 0, 0, 6, 3, 8, 3, 5, 1, 9, 8, 3, 4, 3, 8, 9, 3, 4, 1, 5, 9, 6, 1, 3, 1, 8, 5, 4, 3, 4, 7, 5, 4, 6, 4, 9, 5, 5, 6, 9, 7, 8, 1, 0, 3, 8, 2, 9, + 3, 0, 9, 7, 1, 6, 4, 6, 5, 1, 4, 3, 8, 4, 0, 7, 0, 0, 7, 0, 7, 3, 6, 0, 4, 1, 1, 2, 3, 7, 3, 5, 9, 9, 8, 4, 3, 4, 5, 2, 2, 5, 1, 6, 1, 0, 5, 0, 7, 0, 2, 7, 0, 5, 6, 2, 3, 5, 2, 6, 6, 0, 1, 2, 7, 6, 4, 8, 4, 8, + 3, 0, 8, 4, 0, 7, 6, 1, 1, 8, 3, 0, 1, 3, 0, 5, 2, 7, 9, 3, 2, 0, 5, 4, 2, 7, 4, 6, 2, 8, 6, 5, 4, 0, 3, 6, 0, 3, 6, 7, 4, 5, 3, 2, 8, 6, 5, 1, 0, 5, 7, 0, 6, 5, 8, 7, 4, 8, 8, 2, 2, 5, 6, 9, 8, 1, 5, 7, 9, 3, + 6, 7, 8, 9, 7, 6, 6, 9, 7, 4, 2, 2, 0, 5, 7, 5, 0, 5, 9, 6, 8, 3, 4, 4, 0, 8, 6, 9, 7, 3, 5, 0, 2, 0, 1, 4, 1, 0, 2, 0, 6, 7, 2, 3, 5, 8, 5, 0, 2, 0, 0, 7, 2, 4, 5, 2, 2, 5, 6, 3, 2, 6, 5, 1, 3, 4, 1, 0, 5, 5, + 9, 2, 4, 0, 1, 9, 0, 2, 7, 4, 2, 1, 6, 2, 4, 8, 4, 3, 9, 1, 4, 0, 3, 5, 9, 9, 8, 9, 5, 3, 5, 3, 9, 4, 5, 9, 0, 9, 4, 4, 0, 7, 0, 4, 6, 9, 1, 2, 0, 9, 1, 4, 0, 9, 3, 8, 7, 0, 0, 1, 2, 6, 4, 5, 6, 0, 0, 1, 6, 2, + 3, 7, 4, 2, 8, 8, 0, 2, 1, 0, 9, 2, 7, 6, 4, 5, 7, 9, 3, 1, 0, 6, 5, 7, 9, 2, 2, 9, 5, 5, 2, 4, 9, 8, 8, 7, 2, 7, 5, 8, 4, 6, 1, 0, 1, 2, 6, 4, 8, 3, 6, 9, 9, 9, 8, 9, 2, 2, 5, 6, 9, 5, 9, 6, 8, 8, 1, 5, 9, 2, + 0, 5, 6, 0, 0, 1, 0, 1, 6, 5, 5, 2, 5, 6, 3, 7, 5, 6, 7, 8 + }; +} diff --git a/tests/AndroidTests/src/com/android/unit_tests/os/MessageQueueTest.java b/tests/AndroidTests/src/com/android/unit_tests/os/MessageQueueTest.java new file mode 100644 index 0000000..155a247 --- /dev/null +++ b/tests/AndroidTests/src/com/android/unit_tests/os/MessageQueueTest.java @@ -0,0 +1,103 @@ +/* + * 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.unit_tests.os; + +import android.os.Handler; +import android.os.Message; +import android.os.SystemClock; +import android.test.suitebuilder.annotation.MediumTest; +import junit.framework.TestCase; + +public class MessageQueueTest extends TestCase { + + private static class BaseTestHandler extends TestHandlerThread { + Handler mHandler; + int mLastMessage; + int mCount; + + public BaseTestHandler() { + } + + public void go() { + mHandler = new Handler() { + public void handleMessage(Message msg) { + BaseTestHandler.this.handleMessage(msg); + } + }; + } + + public void handleMessage(Message msg) { + if (mCount <= mLastMessage) { + if (msg.what != mCount) { + failure(new RuntimeException( + "Expected message #" + mCount + + ", received #" + msg.what)); + } else if (mCount == mLastMessage) { + success(); + } + mCount++; + } else { + failure(new RuntimeException( + "Message received after done, #" + msg.what)); + } + } + } + + @MediumTest + public void testMessageOrder() throws Exception { + TestHandlerThread tester = new BaseTestHandler() { + public void go() { + super.go(); + long now = SystemClock.uptimeMillis() + 200; + mLastMessage = 4; + mCount = 0; + mHandler.sendMessageAtTime(mHandler.obtainMessage(2), now + 1); + mHandler.sendMessageAtTime(mHandler.obtainMessage(3), now + 2); + mHandler.sendMessageAtTime(mHandler.obtainMessage(4), now + 2); + mHandler.sendMessageAtTime(mHandler.obtainMessage(0), now + 0); + mHandler.sendMessageAtTime(mHandler.obtainMessage(1), now + 0); + } + }; + + tester.doTest(1000); + } + + @MediumTest + public void testAtFrontOfQueue() throws Exception { + TestHandlerThread tester = new BaseTestHandler() { + public void go() { + super.go(); + long now = SystemClock.uptimeMillis() + 200; + mLastMessage = 3; + mCount = 0; + mHandler.sendMessageAtTime(mHandler.obtainMessage(3), now); + mHandler.sendMessageAtFrontOfQueue(mHandler.obtainMessage(2)); + mHandler.sendMessageAtFrontOfQueue(mHandler.obtainMessage(0)); + } + + public void handleMessage(Message msg) { + super.handleMessage(msg); + if (msg.what == 0) { + mHandler.sendMessageAtFrontOfQueue(mHandler.obtainMessage(1)); + } + } + }; + + tester.doTest(1000); + } +} + diff --git a/tests/AndroidTests/src/com/android/unit_tests/os/MessengerService.java b/tests/AndroidTests/src/com/android/unit_tests/os/MessengerService.java new file mode 100644 index 0000000..9228a43 --- /dev/null +++ b/tests/AndroidTests/src/com/android/unit_tests/os/MessengerService.java @@ -0,0 +1,50 @@ +/* + * 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.unit_tests.os; + +import android.app.Service; +import android.content.Intent; +import android.os.RemoteException; +import android.os.IBinder; +import android.os.Handler; +import android.os.Message; +import android.os.Messenger; + +public class MessengerService extends Service { + private final Handler mHandler = new Handler() { + @Override + public void handleMessage(Message msg) { + Message reply = Message.obtain(); + reply.copyFrom(msg); + try { + msg.replyTo.send(reply); + } catch (RemoteException e) { + } + } + }; + + private final Messenger mMessenger = new Messenger(mHandler); + + public MessengerService() { + } + + @Override + public IBinder onBind(Intent intent) { + return mMessenger.getBinder(); + } +} + diff --git a/tests/AndroidTests/src/com/android/unit_tests/os/MessengerTest.java b/tests/AndroidTests/src/com/android/unit_tests/os/MessengerTest.java new file mode 100644 index 0000000..2a3e204 --- /dev/null +++ b/tests/AndroidTests/src/com/android/unit_tests/os/MessengerTest.java @@ -0,0 +1,119 @@ +/* + * 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.unit_tests.os; + +import android.content.ComponentName; +import android.content.Context; +import android.content.Intent; +import android.content.ServiceConnection; +import android.os.RemoteException; +import android.os.Handler; +import android.os.IBinder; +import android.os.Message; +import android.os.Messenger; +import android.test.AndroidTestCase; +import android.test.suitebuilder.annotation.MediumTest; + +public class MessengerTest extends AndroidTestCase { + private Messenger mServiceMessenger; + + private ServiceConnection mConnection = new ServiceConnection() { + public void onServiceConnected(ComponentName name, IBinder service) { + synchronized (MessengerTest.this) { + mServiceMessenger = new Messenger(service); + MessengerTest.this.notifyAll(); + } + } + public void onServiceDisconnected(ComponentName name) { + mServiceMessenger = null; + } + }; + + private class TestThread extends TestHandlerThread { + private Handler mTestHandler; + private Messenger mTestMessenger; + + public void go() { + synchronized (MessengerTest.this) { + mTestHandler = new Handler() { + public void handleMessage(Message msg) { + TestThread.this.handleMessage(msg); + } + }; + mTestMessenger = new Messenger(mTestHandler); + TestThread.this.executeTest(); + } + } + + public void executeTest() { + Message msg = Message.obtain(); + msg.arg1 = 100; + msg.arg2 = 1000; + msg.replyTo = mTestMessenger; + try { + mServiceMessenger.send(msg); + } catch (RemoteException e) { + } + } + + public void handleMessage(Message msg) { + if (msg.arg1 != 100) { + failure(new RuntimeException( + "Message.arg1 is not 100: " + msg.arg1)); + return; + } + if (msg.arg2 != 1000) { + failure(new RuntimeException( + "Message.arg2 is not 1000: " + msg.arg2)); + return; + } + if (!mTestMessenger.equals(msg.replyTo)) { + failure(new RuntimeException( + "Message.replyTo is not me: " + msg.replyTo)); + return; + } + success(); + } + }; + + @Override + protected void setUp() throws Exception { + super.setUp(); + getContext().bindService(new Intent(mContext, MessengerService.class), + mConnection, Context.BIND_AUTO_CREATE); + synchronized (this) { + while (mServiceMessenger == null) { + try { + wait(); + } catch (InterruptedException e) { + } + } + } + } + + @Override + protected void tearDown() throws Exception { + super.tearDown(); + getContext().unbindService(mConnection); + } + + @MediumTest + public void testSend() { + (new TestThread()).doTest(1000); + + } +} diff --git a/tests/AndroidTests/src/com/android/unit_tests/os/OsTests.java b/tests/AndroidTests/src/com/android/unit_tests/os/OsTests.java new file mode 100644 index 0000000..bf02509 --- /dev/null +++ b/tests/AndroidTests/src/com/android/unit_tests/os/OsTests.java @@ -0,0 +1,41 @@ +/* + * 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.unit_tests.os; + +import com.google.android.collect.Lists; +import junit.framework.TestSuite; + +import java.util.Enumeration; +import java.util.List; + +public class OsTests { + public static TestSuite suite() { + TestSuite suite = new TestSuite(OsTests.class.getName()); + + suite.addTestSuite(AidlTest.class); + suite.addTestSuite(BroadcasterTest.class); + suite.addTestSuite(FileObserverTest.class); + suite.addTestSuite(IdleHandlerTest.class); + suite.addTestSuite(MemoryFileTest.class); + suite.addTestSuite(MessageQueueTest.class); + suite.addTestSuite(MessengerTest.class); + suite.addTestSuite(PowerManagerTest.class); + suite.addTestSuite(SystemPropertiesTest.class); + + return suite; + } +} diff --git a/tests/AndroidTests/src/com/android/unit_tests/os/PowerManagerTest.java b/tests/AndroidTests/src/com/android/unit_tests/os/PowerManagerTest.java new file mode 100644 index 0000000..bd5c955 --- /dev/null +++ b/tests/AndroidTests/src/com/android/unit_tests/os/PowerManagerTest.java @@ -0,0 +1,125 @@ +/* + * Copyright (C) 2008 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.unit_tests.os; + +import android.content.Context; +import android.os.PowerManager; +import android.test.AndroidTestCase; +import android.test.suitebuilder.annotation.MediumTest; + +public class PowerManagerTest extends AndroidTestCase { + + private PowerManager mPm; + + /** + * Setup any common data for the upcoming tests. + */ + @Override + public void setUp() throws Exception { + super.setUp(); + mPm = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE); + } + + /** + * Confirm that the setup is good. + * + * @throws Exception + */ + @MediumTest + public void testPreconditions() throws Exception { + assertNotNull(mPm); + } + + /** + * Confirm that we can create functional wakelocks. + * + * @throws Exception + */ + @MediumTest + public void testNewWakeLock() throws Exception { + PowerManager.WakeLock wl = mPm.newWakeLock(PowerManager.FULL_WAKE_LOCK, "FULL_WAKE_LOCK"); + doTestWakeLock(wl); + + wl = mPm.newWakeLock(PowerManager.SCREEN_BRIGHT_WAKE_LOCK, "SCREEN_BRIGHT_WAKE_LOCK"); + doTestWakeLock(wl); + + wl = mPm.newWakeLock(PowerManager.SCREEN_DIM_WAKE_LOCK, "SCREEN_DIM_WAKE_LOCK"); + doTestWakeLock(wl); + + wl = mPm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "PARTIAL_WAKE_LOCK"); + doTestWakeLock(wl); + + // TODO: Some sort of functional test (maybe not in the unit test here?) + // that confirms that things are really happening e.g. screen power, keyboard power. +} + + /** + * Confirm that we can't create dysfunctional wakelocks. + * + * @throws Exception + */ + @MediumTest + public void testBadNewWakeLock() throws Exception { + + final int badFlags = PowerManager.SCREEN_BRIGHT_WAKE_LOCK + | PowerManager.SCREEN_DIM_WAKE_LOCK; + // wrap in try because we want the error here + try { + PowerManager.WakeLock wl = mPm.newWakeLock(badFlags, "foo"); + } catch (IllegalArgumentException e) { + return; + } + fail("Bad WakeLock flag was not caught."); + } + + /** + * Apply a few tests to a wakelock to make sure it's healthy. + * + * @param wl The wakelock to be tested. + */ + private void doTestWakeLock(PowerManager.WakeLock wl) { + // First try simple acquire/release + wl.acquire(); + assertTrue(wl.isHeld()); + wl.release(); + assertFalse(wl.isHeld()); + + // Try ref-counted acquire/release + wl.setReferenceCounted(true); + wl.acquire(); + assertTrue(wl.isHeld()); + wl.acquire(); + assertTrue(wl.isHeld()); + wl.release(); + assertTrue(wl.isHeld()); + wl.release(); + assertFalse(wl.isHeld()); + + // Try non-ref-counted + wl.setReferenceCounted(false); + wl.acquire(); + assertTrue(wl.isHeld()); + wl.acquire(); + assertTrue(wl.isHeld()); + wl.release(); + assertFalse(wl.isHeld()); + + // TODO: Threaded test (needs handler) to make sure timed wakelocks work too + } + + +} diff --git a/tests/AndroidTests/src/com/android/unit_tests/os/SystemPropertiesTest.java b/tests/AndroidTests/src/com/android/unit_tests/os/SystemPropertiesTest.java new file mode 100644 index 0000000..df08bb9 --- /dev/null +++ b/tests/AndroidTests/src/com/android/unit_tests/os/SystemPropertiesTest.java @@ -0,0 +1,51 @@ +/* + * 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.unit_tests.os; + +import static junit.framework.Assert.assertEquals; +import junit.framework.TestCase; + +import android.os.SystemProperties; +import android.test.suitebuilder.annotation.SmallTest; + +public class SystemPropertiesTest extends TestCase { + private static final String KEY = "com.android.unit_tests"; + @SmallTest + public void testProperties() throws Exception { + if (false) { + String value; + + SystemProperties.set(KEY, ""); + value = SystemProperties.get(KEY, "default"); + assertEquals("default", value); + + SystemProperties.set(KEY, "AAA"); + value = SystemProperties.get(KEY, "default"); + assertEquals("AAA", value); + + value = SystemProperties.get(KEY); + assertEquals("AAA", value); + + SystemProperties.set(KEY, ""); + value = SystemProperties.get(KEY, "default"); + assertEquals("default", value); + + value = SystemProperties.get(KEY); + assertEquals("", value); + } + } +} diff --git a/tests/AndroidTests/src/com/android/unit_tests/os/TestHandlerThread.java b/tests/AndroidTests/src/com/android/unit_tests/os/TestHandlerThread.java new file mode 100644 index 0000000..dba8dde --- /dev/null +++ b/tests/AndroidTests/src/com/android/unit_tests/os/TestHandlerThread.java @@ -0,0 +1,104 @@ +/* + * 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.unit_tests.os; + +import android.os.Handler; +import android.os.Looper; +import android.os.Message; +import android.os.MessageQueue.IdleHandler; + +abstract class TestHandlerThread { + private boolean mDone = false; + private boolean mSuccess = false; + private RuntimeException mFailure = null; + private Looper mLooper; + + public abstract void go(); + + public TestHandlerThread() { + } + + public void doTest(long timeout) { + (new LooperThread()).start(); + + synchronized (this) { + long now = System.currentTimeMillis(); + long endTime = now + timeout; + while (!mDone && now < endTime) { + try { + wait(endTime-now); + } + catch (InterruptedException e) { + } + now = System.currentTimeMillis(); + } + } + + mLooper.quit(); + + if (!mDone) { + throw new RuntimeException("test timed out"); + } + if (!mSuccess) { + throw mFailure; + } + } + + public Looper getLooper() { + return mLooper; + } + + public void success() { + synchronized (this) { + mSuccess = true; + quit(); + } + } + + public void failure(RuntimeException failure) { + synchronized (this) { + mSuccess = false; + mFailure = failure; + quit(); + } + } + + class LooperThread extends Thread { + public void run() { + Looper.prepare(); + mLooper = Looper.myLooper(); + go(); + Looper.loop(); + + synchronized (TestHandlerThread.this) { + mDone = true; + if (!mSuccess && mFailure == null) { + mFailure = new RuntimeException("no failure exception set"); + } + TestHandlerThread.this.notifyAll(); + } + } + + } + + private void quit() { + synchronized (this) { + mDone = true; + notifyAll(); + } + } +} |