auto import from //depot/cupcake/@135843
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
new file mode 100644
index 0000000..28dc925
--- /dev/null
+++ b/tests/AndroidTests/res/drawable/test128x96.png
Binary files differ
diff --git a/tests/AndroidTests/res/drawable/test16x12.png b/tests/AndroidTests/res/drawable/test16x12.png
new file mode 100644
index 0000000..1a3c7e5
--- /dev/null
+++ b/tests/AndroidTests/res/drawable/test16x12.png
Binary files differ
diff --git a/tests/AndroidTests/res/drawable/test256x192.png b/tests/AndroidTests/res/drawable/test256x192.png
new file mode 100644
index 0000000..ce8ee04
--- /dev/null
+++ b/tests/AndroidTests/res/drawable/test256x192.png
Binary files differ
diff --git a/tests/AndroidTests/res/drawable/test320x240.png b/tests/AndroidTests/res/drawable/test320x240.png
new file mode 100644
index 0000000..9b5800d
--- /dev/null
+++ b/tests/AndroidTests/res/drawable/test320x240.png
Binary files differ
diff --git a/tests/AndroidTests/res/drawable/test32x24.png b/tests/AndroidTests/res/drawable/test32x24.png
new file mode 100644
index 0000000..76bab75
--- /dev/null
+++ b/tests/AndroidTests/res/drawable/test32x24.png
Binary files differ
diff --git a/tests/AndroidTests/res/drawable/test64x48.png b/tests/AndroidTests/res/drawable/test64x48.png
new file mode 100644
index 0000000..9119613
--- /dev/null
+++ b/tests/AndroidTests/res/drawable/test64x48.png
Binary files differ
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
new file mode 100644
index 0000000..6f1bf54
--- /dev/null
+++ b/tests/AndroidTests/res/raw/calendarjsgz.jsgz
Binary files differ
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
new file mode 100644
index 0000000..6c86462
--- /dev/null
+++ b/tests/AndroidTests/res/raw/calendarxmlgz.xmlgz
Binary files differ
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..220bc99e
--- /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..e8001e34
--- /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..9228a43f
--- /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..2a3e204d
--- /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();
+ }
+ }
+}